fix log to reflect reality
[zxing.git] / csharp / client / result / ResultParser.cs
1 /*\r
2 * Copyright 2007 ZXing authors\r
3 *\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
7 *\r
8 *      http://www.apache.org/licenses/LICENSE-2.0\r
9 *\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
15 */\r
16 using System;\r
17 using Result = com.google.zxing.Result;\r
18 namespace com.google.zxing.client.result\r
19 {\r
20         \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
25         /// \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
28         /// \r
29         /// </summary>\r
30         /// <author>  Sean Owen\r
31         /// </author>\r
32         /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
33         /// </author>\r
34         public abstract class ResultParser\r
35         {\r
36                 \r
37                 public static ParsedResult parseResult(Result theResult)\r
38                 {\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
44                         {\r
45                                 return result;\r
46                         }\r
47                         else if ((result = AddressBookDoCoMoResultParser.parse(theResult)) != null)\r
48                         {\r
49                                 return result;\r
50                         }\r
51                         else if ((result = EmailDoCoMoResultParser.parse(theResult)) != null)\r
52                         {\r
53                                 return result;\r
54                         }\r
55                         else if ((result = AddressBookAUResultParser.parse(theResult)) != null)\r
56                         {\r
57                                 return result;\r
58                         }\r
59                         else if ((result = VCardResultParser.parse(theResult)) != null)\r
60                         {\r
61                                 return result;\r
62                         }\r
63                         else if ((result = BizcardResultParser.parse(theResult)) != null)\r
64                         {\r
65                                 return result;\r
66                         }\r
67                         else if ((result = VEventResultParser.parse(theResult)) != null)\r
68                         {\r
69                                 return result;\r
70                         }\r
71                         else if ((result = EmailAddressResultParser.parse(theResult)) != null)\r
72                         {\r
73                                 return result;\r
74                         }\r
75                         else if ((result = TelResultParser.parse(theResult)) != null)\r
76                         {\r
77                                 return result;\r
78                         }\r
79                         else if ((result = SMSMMSResultParser.parse(theResult)) != null)\r
80                         {\r
81                                 return result;\r
82                         }\r
83                         else if ((result = GeoResultParser.parse(theResult)) != null)\r
84                         {\r
85                                 return result;\r
86                         }\r
87                         else if ((result = URLTOResultParser.parse(theResult)) != null)\r
88                         {\r
89                                 return result;\r
90                         }\r
91                         else if ((result = URIResultParser.parse(theResult)) != null)\r
92                         {\r
93                                 return result;\r
94                         }\r
95                         else if ((result = ISBNResultParser.parse(theResult)) != null)\r
96                         {\r
97                                 // We depend on ISBN parsing coming before UPC, as it is a subset.\r
98                                 return result;\r
99                         }\r
100                         else if ((result = ProductResultParser.parse(theResult)) != null)\r
101                         {\r
102                                 return result;\r
103                         }\r
104                         return new TextParsedResult(theResult.Text, null);\r
105                 }\r
106                 \r
107                 protected internal static void  maybeAppend(System.String value_Renamed, System.Text.StringBuilder result)\r
108                 {\r
109                         if (value_Renamed != null)\r
110                         {\r
111                                 result.Append('\n');\r
112                                 result.Append(value_Renamed);\r
113                         }\r
114                 }\r
115                 \r
116                 protected internal static void  maybeAppend(System.String[] value_Renamed, System.Text.StringBuilder result)\r
117                 {\r
118                         if (value_Renamed != null)\r
119                         {\r
120                                 for (int i = 0; i < value_Renamed.Length; i++)\r
121                                 {\r
122                                         result.Append('\n');\r
123                                         result.Append(value_Renamed[i]);\r
124                                 }\r
125                         }\r
126                 }\r
127                 \r
128                 protected internal static System.String[] maybeWrap(System.String value_Renamed)\r
129                 {\r
130                         return value_Renamed == null?null:new System.String[]{value_Renamed};\r
131                 }\r
132                 \r
133                 protected internal static System.String unescapeBackslash(System.String escaped)\r
134                 {\r
135                         if (escaped != null)\r
136                         {\r
137                                 int backslash = escaped.IndexOf('\\');\r
138                                 if (backslash >= 0)\r
139                                 {\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
145                                         {\r
146                                                 char c = escaped[i];\r
147                                                 if (nextIsEscaped || c != '\\')\r
148                                                 {\r
149                                                         unescaped.Append(c);\r
150                                                         nextIsEscaped = false;\r
151                                                 }\r
152                                                 else\r
153                                                 {\r
154                                                         nextIsEscaped = true;\r
155                                                 }\r
156                                         }\r
157                                         return unescaped.ToString();\r
158                                 }\r
159                         }\r
160                         return escaped;\r
161                 }\r
162                 \r
163                 private static System.String urlDecode(System.String escaped)\r
164                 {\r
165                         \r
166                         // No we can't use java.net.URLDecoder here. JavaME doesn't have it.\r
167                         if (escaped == null)\r
168                         {\r
169                                 return null;\r
170                         }\r
171                         char[] escapedArray = escaped.ToCharArray();\r
172                         \r
173                         int first = findFirstEscape(escapedArray);\r
174                         if (first < 0)\r
175                         {\r
176                                 return escaped;\r
177                         }\r
178                         \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
184                         \r
185                         for (int i = first; i < max; i++)\r
186                         {\r
187                                 char c = escapedArray[i];\r
188                                 if (c == '+')\r
189                                 {\r
190                                         // + is translated directly into a space\r
191                                         unescaped.Append(' ');\r
192                                 }\r
193                                 else if (c == '%')\r
194                                 {\r
195                                         // Are there even two more chars? if not we will just copy the escaped sequence and be done\r
196                                         if (i >= max - 2)\r
197                                         {\r
198                                                 unescaped.Append('%'); // append that % and move on\r
199                                         }\r
200                                         else\r
201                                         {\r
202                                                 int firstDigitValue = parseHexDigit(escapedArray[++i]);\r
203                                                 int secondDigitValue = parseHexDigit(escapedArray[++i]);\r
204                                                 if (firstDigitValue < 0 || secondDigitValue < 0)\r
205                                                 {\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
210                                                 }\r
211                                                 unescaped.Append((char) ((firstDigitValue << 4) + secondDigitValue));\r
212                                         }\r
213                                 }\r
214                                 else\r
215                                 {\r
216                                         unescaped.Append(c);\r
217                                 }\r
218                         }\r
219                         return unescaped.ToString();\r
220                 }\r
221                 \r
222                 private static int findFirstEscape(char[] escapedArray)\r
223                 {\r
224                         int max = escapedArray.Length;\r
225                         for (int i = 0; i < max; i++)\r
226                         {\r
227                                 char c = escapedArray[i];\r
228                                 if (c == '+' || c == '%')\r
229                                 {\r
230                                         return i;\r
231                                 }\r
232                         }\r
233                         return - 1;\r
234                 }\r
235                 \r
236                 private static int parseHexDigit(char c)\r
237                 {\r
238                         if (c >= 'a')\r
239                         {\r
240                                 if (c <= 'f')\r
241                                 {\r
242                                         return 10 + (c - 'a');\r
243                                 }\r
244                         }\r
245                         else if (c >= 'A')\r
246                         {\r
247                                 if (c <= 'F')\r
248                                 {\r
249                                         return 10 + (c - 'A');\r
250                                 }\r
251                         }\r
252                         else if (c >= '0')\r
253                         {\r
254                                 if (c <= '9')\r
255                                 {\r
256                                         return c - '0';\r
257                                 }\r
258                         }\r
259                         return - 1;\r
260                 }\r
261                 \r
262                 protected internal static bool isStringOfDigits(System.String value_Renamed, int length)\r
263                 {\r
264                         if (value_Renamed == null)\r
265                         {\r
266                                 return false;\r
267                         }\r
268                         int stringLength = value_Renamed.Length;\r
269                         if (length != stringLength)\r
270                         {\r
271                                 return false;\r
272                         }\r
273                         for (int i = 0; i < length; i++)\r
274                         {\r
275                                 char c = value_Renamed[i];\r
276                                 if (c < '0' || c > '9')\r
277                                 {\r
278                                         return false;\r
279                                 }\r
280                         }\r
281                         return true;\r
282                 }\r
283                 \r
284                 protected internal static bool isSubstringOfDigits(System.String value_Renamed, int offset, int length)\r
285                 {\r
286                         if (value_Renamed == null)\r
287                         {\r
288                                 return false;\r
289                         }\r
290                         int stringLength = value_Renamed.Length;\r
291                         int max = offset + length;\r
292                         if (stringLength < max)\r
293                         {\r
294                                 return false;\r
295                         }\r
296                         for (int i = offset; i < max; i++)\r
297                         {\r
298                                 char c = value_Renamed[i];\r
299                                 if (c < '0' || c > '9')\r
300                                 {\r
301                                         return false;\r
302                                 }\r
303                         }\r
304                         return true;\r
305                 }\r
306                 \r
307                 internal static System.Collections.Hashtable parseNameValuePairs(System.String uri)\r
308                 {\r
309                         int paramStart = uri.IndexOf('?');\r
310                         if (paramStart < 0)\r
311                         {\r
312                                 return null;\r
313                         }\r
314                         System.Collections.Hashtable result = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(3));\r
315                         paramStart++;\r
316                         int paramEnd;\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
319                         {\r
320                                 appendKeyValue(uri, paramStart, paramEnd, result);\r
321                                 paramStart = paramEnd + 1;\r
322                         }\r
323                         appendKeyValue(uri, paramStart, uri.Length, result);\r
324                         return result;\r
325                 }\r
326                 \r
327                 private static void  appendKeyValue(System.String uri, int paramStart, int paramEnd, System.Collections.Hashtable result)\r
328                 {\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
332                         {\r
333                                 // key = value\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
338                         }\r
339                         // Can't put key, null into a hashtable\r
340                 }\r
341                 \r
342                 internal static System.String[] matchPrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)\r
343                 {\r
344                         System.Collections.ArrayList matches = null;\r
345                         int i = 0;\r
346                         int max = rawText.Length;\r
347                         while (i < max)\r
348                         {\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
351                                 if (i < 0)\r
352                                 {\r
353                                         break;\r
354                                 }\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
357                                 bool done = false;\r
358                                 while (!done)\r
359                                 {\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
362                                         if (i < 0)\r
363                                         {\r
364                                                 // No terminating end character? uh, done. Set i such that loop terminates and break\r
365                                                 i = rawText.Length;\r
366                                                 done = true;\r
367                                         }\r
368                                         else if (rawText[i - 1] == '\\')\r
369                                         {\r
370                                                 // semicolon was escaped so continue\r
371                                                 i++;\r
372                                         }\r
373                                         else\r
374                                         {\r
375                                                 // found a match\r
376                                                 if (matches == null)\r
377                                                 {\r
378                                                         matches = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(3)); // lazy init\r
379                                                 }\r
380                                                 System.String element = unescapeBackslash(rawText.Substring(start, (i) - (start)));\r
381                                                 if (trim)\r
382                                                 {\r
383                                                         element = element.Trim();\r
384                                                 }\r
385                                                 matches.Add(element);\r
386                                                 i++;\r
387                                                 done = true;\r
388                                         }\r
389                                 }\r
390                         }\r
391                         if (matches == null || (matches.Count == 0))\r
392                         {\r
393                                 return null;\r
394                         }\r
395                         return toStringArray(matches);\r
396                 }\r
397                 \r
398                 internal static System.String matchSinglePrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)\r
399                 {\r
400                         System.String[] matches = matchPrefixedField(prefix, rawText, endChar, trim);\r
401                         return matches == null?null:matches[0];\r
402                 }\r
403                 \r
404                 internal static System.String[] toStringArray(System.Collections.ArrayList strings)\r
405                 {\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
409                         {\r
410                                 result[j] = ((System.String) strings[j]);\r
411                         }\r
412                         return result;\r
413                 }\r
414         }\r
415 }