zxing/csharp/client/result/ResultParser.cs
srowen d4efd44fb0 New C# port from Suraj Supekar
git-svn-id: https://zxing.googlecode.com/svn/trunk@1202 59b500cc-1b3d-0410-9834-0bbf25fbcc57
2010-02-05 19:52:53 +00:00

415 lines
12 KiB
C#
Executable file

/*
* Copyright 2007 ZXing authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using Result = com.google.zxing.Result;
namespace com.google.zxing.client.result
{
/// <summary> <p>Abstract class representing the result of decoding a barcode, as more than
/// a String -- as some type of structured data. This might be a subclass which represents
/// a URL, or an e-mail address. {@link #parseResult(com.google.zxing.Result)} will turn a raw
/// decoded string into the most appropriate type of structured representation.</p>
///
/// <p>Thanks to Jeff Griffin for proposing rewrite of these classes that relies less
/// on exception-based mechanisms during parsing.</p>
///
/// </summary>
/// <author> Sean Owen
/// </author>
/// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source
/// </author>
public abstract class ResultParser
{
public static ParsedResult parseResult(Result theResult)
{
// This is a bit messy, but given limited options in MIDP / CLDC, this may well be the simplest
// way to go about this. For example, we have no reflection available, really.
// Order is important here.
ParsedResult result;
if ((result = BookmarkDoCoMoResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = AddressBookDoCoMoResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = EmailDoCoMoResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = AddressBookAUResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = VCardResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = BizcardResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = VEventResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = EmailAddressResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = TelResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = SMSMMSResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = GeoResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = URLTOResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = URIResultParser.parse(theResult)) != null)
{
return result;
}
else if ((result = ISBNResultParser.parse(theResult)) != null)
{
// We depend on ISBN parsing coming before UPC, as it is a subset.
return result;
}
else if ((result = ProductResultParser.parse(theResult)) != null)
{
return result;
}
return new TextParsedResult(theResult.Text, null);
}
protected internal static void maybeAppend(System.String value_Renamed, System.Text.StringBuilder result)
{
if (value_Renamed != null)
{
result.Append('\n');
result.Append(value_Renamed);
}
}
protected internal static void maybeAppend(System.String[] value_Renamed, System.Text.StringBuilder result)
{
if (value_Renamed != null)
{
for (int i = 0; i < value_Renamed.Length; i++)
{
result.Append('\n');
result.Append(value_Renamed[i]);
}
}
}
protected internal static System.String[] maybeWrap(System.String value_Renamed)
{
return value_Renamed == null?null:new System.String[]{value_Renamed};
}
protected internal static System.String unescapeBackslash(System.String escaped)
{
if (escaped != null)
{
int backslash = escaped.IndexOf('\\');
if (backslash >= 0)
{
int max = escaped.Length;
System.Text.StringBuilder unescaped = new System.Text.StringBuilder(max - 1);
unescaped.Append(escaped.ToCharArray(), 0, backslash);
bool nextIsEscaped = false;
for (int i = backslash; i < max; i++)
{
char c = escaped[i];
if (nextIsEscaped || c != '\\')
{
unescaped.Append(c);
nextIsEscaped = false;
}
else
{
nextIsEscaped = true;
}
}
return unescaped.ToString();
}
}
return escaped;
}
private static System.String urlDecode(System.String escaped)
{
// No we can't use java.net.URLDecoder here. JavaME doesn't have it.
if (escaped == null)
{
return null;
}
char[] escapedArray = escaped.ToCharArray();
int first = findFirstEscape(escapedArray);
if (first < 0)
{
return escaped;
}
int max = escapedArray.Length;
// final length is at most 2 less than original due to at least 1 unescaping
System.Text.StringBuilder unescaped = new System.Text.StringBuilder(max - 2);
// Can append everything up to first escape character
unescaped.Append(escapedArray, 0, first);
for (int i = first; i < max; i++)
{
char c = escapedArray[i];
if (c == '+')
{
// + is translated directly into a space
unescaped.Append(' ');
}
else if (c == '%')
{
// Are there even two more chars? if not we will just copy the escaped sequence and be done
if (i >= max - 2)
{
unescaped.Append('%'); // append that % and move on
}
else
{
int firstDigitValue = parseHexDigit(escapedArray[++i]);
int secondDigitValue = parseHexDigit(escapedArray[++i]);
if (firstDigitValue < 0 || secondDigitValue < 0)
{
// bad digit, just move on
unescaped.Append('%');
unescaped.Append(escapedArray[i - 1]);
unescaped.Append(escapedArray[i]);
}
unescaped.Append((char) ((firstDigitValue << 4) + secondDigitValue));
}
}
else
{
unescaped.Append(c);
}
}
return unescaped.ToString();
}
private static int findFirstEscape(char[] escapedArray)
{
int max = escapedArray.Length;
for (int i = 0; i < max; i++)
{
char c = escapedArray[i];
if (c == '+' || c == '%')
{
return i;
}
}
return - 1;
}
private static int parseHexDigit(char c)
{
if (c >= 'a')
{
if (c <= 'f')
{
return 10 + (c - 'a');
}
}
else if (c >= 'A')
{
if (c <= 'F')
{
return 10 + (c - 'A');
}
}
else if (c >= '0')
{
if (c <= '9')
{
return c - '0';
}
}
return - 1;
}
protected internal static bool isStringOfDigits(System.String value_Renamed, int length)
{
if (value_Renamed == null)
{
return false;
}
int stringLength = value_Renamed.Length;
if (length != stringLength)
{
return false;
}
for (int i = 0; i < length; i++)
{
char c = value_Renamed[i];
if (c < '0' || c > '9')
{
return false;
}
}
return true;
}
protected internal static bool isSubstringOfDigits(System.String value_Renamed, int offset, int length)
{
if (value_Renamed == null)
{
return false;
}
int stringLength = value_Renamed.Length;
int max = offset + length;
if (stringLength < max)
{
return false;
}
for (int i = offset; i < max; i++)
{
char c = value_Renamed[i];
if (c < '0' || c > '9')
{
return false;
}
}
return true;
}
internal static System.Collections.Hashtable parseNameValuePairs(System.String uri)
{
int paramStart = uri.IndexOf('?');
if (paramStart < 0)
{
return null;
}
System.Collections.Hashtable result = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable(3));
paramStart++;
int paramEnd;
//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'"
while ((paramEnd = uri.IndexOf('&', paramStart)) >= 0)
{
appendKeyValue(uri, paramStart, paramEnd, result);
paramStart = paramEnd + 1;
}
appendKeyValue(uri, paramStart, uri.Length, result);
return result;
}
private static void appendKeyValue(System.String uri, int paramStart, int paramEnd, System.Collections.Hashtable result)
{
//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'"
int separator = uri.IndexOf('=', paramStart);
if (separator >= 0)
{
// key = value
System.String key = uri.Substring(paramStart, (separator) - (paramStart));
System.String value_Renamed = uri.Substring(separator + 1, (paramEnd) - (separator + 1));
value_Renamed = urlDecode(value_Renamed);
result[key] = value_Renamed;
}
// Can't put key, null into a hashtable
}
internal static System.String[] matchPrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)
{
System.Collections.ArrayList matches = null;
int i = 0;
int max = rawText.Length;
while (i < max)
{
//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'"
i = rawText.IndexOf(prefix, i);
if (i < 0)
{
break;
}
i += prefix.Length; // Skip past this prefix we found to start
int start = i; // Found the start of a match here
bool done = false;
while (!done)
{
//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'"
i = rawText.IndexOf((System.Char) endChar, i);
if (i < 0)
{
// No terminating end character? uh, done. Set i such that loop terminates and break
i = rawText.Length;
done = true;
}
else if (rawText[i - 1] == '\\')
{
// semicolon was escaped so continue
i++;
}
else
{
// found a match
if (matches == null)
{
matches = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(3)); // lazy init
}
System.String element = unescapeBackslash(rawText.Substring(start, (i) - (start)));
if (trim)
{
element = element.Trim();
}
matches.Add(element);
i++;
done = true;
}
}
}
if (matches == null || (matches.Count == 0))
{
return null;
}
return toStringArray(matches);
}
internal static System.String matchSinglePrefixedField(System.String prefix, System.String rawText, char endChar, bool trim)
{
System.String[] matches = matchPrefixedField(prefix, rawText, endChar, trim);
return matches == null?null:matches[0];
}
internal static System.String[] toStringArray(System.Collections.ArrayList strings)
{
int size = strings.Count;
System.String[] result = new System.String[size];
for (int j = 0; j < size; j++)
{
result[j] = ((System.String) strings[j]);
}
return result;
}
}
}