2 * Copyright 2007 ZXing authors
\r
4 * Licensed under the Apache License, Version 2.0 (the "License");
\r
5 * you may not use this file except in compliance with the License.
\r
6 * You may obtain a copy of the License at
\r
8 * http://www.apache.org/licenses/LICENSE-2.0
\r
10 * Unless required by applicable law or agreed to in writing, software
\r
11 * distributed under the License is distributed on an "AS IS" BASIS,
\r
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 * See the License for the specific language governing permissions and
\r
14 * limitations under the License.
\r
17 using Result = com.google.zxing.Result;
\r
18 namespace com.google.zxing.client.result
\r
21 /// <summary> <p>Abstract class representing the result of decoding a barcode, as more than
\r
22 /// a String -- as some type of structured data. This might be a subclass which represents
\r
23 /// a URL, or an e-mail address. {@link #parseResult(com.google.zxing.Result)} will turn a raw
\r
24 /// decoded string into the most appropriate type of structured representation.</p>
\r
26 /// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
\r
27 /// on exception-based mechanisms during parsing.</p>
\r
30 /// <author> Sean Owen
\r
32 /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
\r
34 public abstract class ResultParser
\r
37 public static ParsedResult parseResult(Result theResult)
\r
39 // This is a bit messy, but given limited options in MIDP / CLDC, this may well be the simplest
\r
40 // way to go about this. For example, we have no reflection available, really.
\r
41 // Order is important here.
\r
42 ParsedResult result;
\r
43 if ((result = BookmarkDoCoMoResultParser.parse(theResult)) != null)
\r
47 else if ((result = AddressBookDoCoMoResultParser.parse(theResult)) != null)
\r
51 else if ((result = EmailDoCoMoResultParser.parse(theResult)) != null)
\r
55 else if ((result = AddressBookAUResultParser.parse(theResult)) != null)
\r
59 else if ((result = VCardResultParser.parse(theResult)) != null)
\r
63 else if ((result = BizcardResultParser.parse(theResult)) != null)
\r
67 else if ((result = VEventResultParser.parse(theResult)) != null)
\r
71 else if ((result = EmailAddressResultParser.parse(theResult)) != null)
\r
75 else if ((result = TelResultParser.parse(theResult)) != null)
\r
79 else if ((result = SMSMMSResultParser.parse(theResult)) != null)
\r
83 else if ((result = GeoResultParser.parse(theResult)) != null)
\r
87 else if ((result = URLTOResultParser.parse(theResult)) != null)
\r
91 else if ((result = URIResultParser.parse(theResult)) != null)
\r
95 else if ((result = ISBNResultParser.parse(theResult)) != null)
\r
97 // We depend on ISBN parsing coming before UPC, as it is a subset.
\r
100 else if ((result = ProductResultParser.parse(theResult)) != null)
\r
104 return new TextParsedResult(theResult.Text, null);
\r
107 protected internal static void maybeAppend(System.String value_Renamed, System.Text.StringBuilder result)
\r
109 if (value_Renamed != null)
\r
111 result.Append('\n');
\r
112 result.Append(value_Renamed);
\r
116 protected internal static void maybeAppend(System.String[] value_Renamed, System.Text.StringBuilder result)
\r
118 if (value_Renamed != null)
\r
120 for (int i = 0; i < value_Renamed.Length; i++)
\r
122 result.Append('\n');
\r
123 result.Append(value_Renamed[i]);
\r
128 protected internal static System.String[] maybeWrap(System.String value_Renamed)
\r
130 return value_Renamed == null?null:new System.String[]{value_Renamed};
\r
133 protected internal static System.String unescapeBackslash(System.String escaped)
\r
135 if (escaped != null)
\r
137 int backslash = escaped.IndexOf('\\');
\r
138 if (backslash >= 0)
\r
140 int max = escaped.Length;
\r
141 System.Text.StringBuilder unescaped = new System.Text.StringBuilder(max - 1);
\r
142 unescaped.Append(escaped.ToCharArray(), 0, backslash);
\r
143 bool nextIsEscaped = false;
\r
144 for (int i = backslash; i < max; i++)
\r
146 char c = escaped[i];
\r
147 if (nextIsEscaped || c != '\\')
\r
149 unescaped.Append(c);
\r
150 nextIsEscaped = false;
\r
154 nextIsEscaped = true;
\r
157 return unescaped.ToString();
\r
163 private static System.String urlDecode(System.String escaped)
\r
166 // No we can't use java.net.URLDecoder here. JavaME doesn't have it.
\r
167 if (escaped == null)
\r
171 char[] escapedArray = escaped.ToCharArray();
\r
173 int first = findFirstEscape(escapedArray);
\r
179 int max = escapedArray.Length;
\r
180 // final length is at most 2 less than original due to at least 1 unescaping
\r
181 System.Text.StringBuilder unescaped = new System.Text.StringBuilder(max - 2);
\r
182 // Can append everything up to first escape character
\r
183 unescaped.Append(escapedArray, 0, first);
\r
185 for (int i = first; i < max; i++)
\r
187 char c = escapedArray[i];
\r
190 // + is translated directly into a space
\r
191 unescaped.Append(' ');
\r
195 // Are there even two more chars? if not we will just copy the escaped sequence and be done
\r
198 unescaped.Append('%'); // append that % and move on
\r
202 int firstDigitValue = parseHexDigit(escapedArray[++i]);
\r
203 int secondDigitValue = parseHexDigit(escapedArray[++i]);
\r
204 if (firstDigitValue < 0 || secondDigitValue < 0)
\r
206 // bad digit, just move on
\r
207 unescaped.Append('%');
\r
208 unescaped.Append(escapedArray[i - 1]);
\r
209 unescaped.Append(escapedArray[i]);
\r
211 unescaped.Append((char) ((firstDigitValue << 4) + secondDigitValue));
\r
216 unescaped.Append(c);
\r
219 return unescaped.ToString();
\r
222 private static int findFirstEscape(char[] escapedArray)
\r
224 int max = escapedArray.Length;
\r
225 for (int i = 0; i < max; i++)
\r
227 char c = escapedArray[i];
\r
228 if (c == '+' || c == '%')
\r
236 private static int parseHexDigit(char c)
\r
242 return 10 + (c - 'a');
\r
249 return 10 + (c - 'A');
\r
262 protected internal static bool isStringOfDigits(System.String value_Renamed, int length)
\r
264 if (value_Renamed == null)
\r
268 int stringLength = value_Renamed.Length;
\r
269 if (length != stringLength)
\r
273 for (int i = 0; i < length; i++)
\r
275 char c = value_Renamed[i];
\r
276 if (c < '0' || c > '9')
\r
284 protected internal static bool isSubstringOfDigits(System.String value_Renamed, int offset, int length)
\r
286 if (value_Renamed == null)
\r
290 int stringLength = value_Renamed.Length;
\r
291 int max = offset + length;
\r
292 if (stringLength < max)
\r
296 for (int i = offset; i < max; i++)
\r
298 char c = value_Renamed[i];
\r
299 if (c < '0' || c > '9')
\r
307 internal static System.Collections.Hashtable parseNameValuePairs(System.String uri)
\r
309 int paramStart = uri.IndexOf('?');
\r
310 if (paramStart < 0)
\r
314 System.Collections.Hashtable result = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(3));
\r
317 //UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
\r
318 while ((paramEnd = uri.IndexOf('&', paramStart)) >= 0)
\r
320 appendKeyValue(uri, paramStart, paramEnd, result);
\r
321 paramStart = paramEnd + 1;
\r
323 appendKeyValue(uri, paramStart, uri.Length, result);
\r
327 private static void appendKeyValue(System.String uri, int paramStart, int paramEnd, System.Collections.Hashtable result)
\r
329 //UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
\r
330 int separator = uri.IndexOf('=', paramStart);
\r
331 if (separator >= 0)
\r
334 System.String key = uri.Substring(paramStart, (separator) - (paramStart));
\r
335 System.String value_Renamed = uri.Substring(separator + 1, (paramEnd) - (separator + 1));
\r
336 value_Renamed = urlDecode(value_Renamed);
\r
337 result[key] = value_Renamed;
\r
339 // Can't put key, null into a hashtable
\r
342 internal static System.String[] matchPrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)
\r
344 System.Collections.ArrayList matches = null;
\r
346 int max = rawText.Length;
\r
349 //UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
\r
350 i = rawText.IndexOf(prefix, i);
\r
355 i += prefix.Length; // Skip past this prefix we found to start
\r
356 int start = i; // Found the start of a match here
\r
360 //UPGRADE_WARNING: Method 'java.lang.String.indexOf' was converted to 'System.String.IndexOf' which may throw an exception. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1101'"
\r
361 i = rawText.IndexOf((System.Char) endChar, i);
\r
364 // No terminating end character? uh, done. Set i such that loop terminates and break
\r
365 i = rawText.Length;
\r
368 else if (rawText[i - 1] == '\\')
\r
370 // semicolon was escaped so continue
\r
376 if (matches == null)
\r
378 matches = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(3)); // lazy init
\r
380 System.String element = unescapeBackslash(rawText.Substring(start, (i) - (start)));
\r
383 element = element.Trim();
\r
385 matches.Add(element);
\r
391 if (matches == null || (matches.Count == 0))
\r
395 return toStringArray(matches);
\r
398 internal static System.String matchSinglePrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)
\r
400 System.String[] matches = matchPrefixedField(prefix, rawText, endChar, trim);
\r
401 return matches == null?null:matches[0];
\r
404 internal static System.String[] toStringArray(System.Collections.ArrayList strings)
\r
406 int size = strings.Count;
\r
407 System.String[] result = new System.String[size];
\r
408 for (int j = 0; j < size; j++)
\r
410 result[j] = ((System.String) strings[j]);
\r