New C# port from Suraj Supekar
[zxing.git] / csharp / datamatrix / decoder / DecodedBitStreamParser.cs
diff --git a/csharp/datamatrix/decoder/DecodedBitStreamParser.cs b/csharp/datamatrix/decoder/DecodedBitStreamParser.cs
new file mode 100755 (executable)
index 0000000..12e3faa
--- /dev/null
@@ -0,0 +1,625 @@
+/*\r
+* Copyright 2008 ZXing authors\r
+*\r
+* Licensed under the Apache License, Version 2.0 (the "License");\r
+* you may not use this file except in compliance with the License.\r
+* You may obtain a copy of the License at\r
+*\r
+*      http://www.apache.org/licenses/LICENSE-2.0\r
+*\r
+* Unless required by applicable law or agreed to in writing, software\r
+* distributed under the License is distributed on an "AS IS" BASIS,\r
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+* See the License for the specific language governing permissions and\r
+* limitations under the License.\r
+*/\r
+using System;\r
+using ReaderException = com.google.zxing.ReaderException;\r
+using BitSource = com.google.zxing.common.BitSource;\r
+using DecoderResult = com.google.zxing.common.DecoderResult;\r
+namespace com.google.zxing.datamatrix.decoder\r
+{\r
+       \r
+       /// <summary> <p>Data Matrix Codes can encode text as bits in one of several modes, and can use multiple modes\r
+       /// in one Data Matrix Code. This class decodes the bits back into text.</p>\r
+       /// \r
+       /// <p>See ISO 16022:2006, 5.2.1 - 5.2.9.2</p>\r
+       /// \r
+       /// </summary>\r
+       /// <author>  bbrown@google.com (Brian Brown)\r
+       /// </author>\r
+       /// <author>  Sean Owen\r
+       /// </author>\r
+       /// <author>www.Redivivus.in (suraj.supekar@redivivus.in) - Ported from ZXING Java Source \r
+       /// </author>\r
+       sealed class DecodedBitStreamParser\r
+       {\r
+               \r
+               /// <summary> See ISO 16022:2006, Annex C Table C.1\r
+               /// The C40 Basic Character Set (*'s used for placeholders for the shift values)\r
+               /// </summary>\r
+               //UPGRADE_NOTE: Final was removed from the declaration of 'C40_BASIC_SET_CHARS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
+               private static readonly char[] C40_BASIC_SET_CHARS = new char[]{'*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};\r
+               \r
+               //UPGRADE_NOTE: Final was removed from the declaration of 'C40_SHIFT2_SET_CHARS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
+               private static readonly char[] C40_SHIFT2_SET_CHARS = new char[]{'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_'};\r
+               \r
+               /// <summary> See ISO 16022:2006, Annex C Table C.2\r
+               /// The Text Basic Character Set (*'s used for placeholders for the shift values)\r
+               /// </summary>\r
+               //UPGRADE_NOTE: Final was removed from the declaration of 'TEXT_BASIC_SET_CHARS'. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1003'"\r
+               private static readonly char[] TEXT_BASIC_SET_CHARS = new char[]{'*', '*', '*', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};\r
+               \r
+               private static char[] TEXT_SHIFT3_SET_CHARS = new char[]{'\'', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', (char) 127};\r
+               \r
+               private const int PAD_ENCODE = 0; // Not really an encoding\r
+               private const int ASCII_ENCODE = 1;\r
+               private const int C40_ENCODE = 2;\r
+               private const int TEXT_ENCODE = 3;\r
+               private const int ANSIX12_ENCODE = 4;\r
+               private const int EDIFACT_ENCODE = 5;\r
+               private const int BASE256_ENCODE = 6;\r
+               \r
+               private DecodedBitStreamParser()\r
+               {\r
+               }\r
+               \r
+               internal static DecoderResult decode(sbyte[] bytes)\r
+               {\r
+                       BitSource bits = new BitSource(bytes);\r
+                       System.Text.StringBuilder result = new System.Text.StringBuilder(100);\r
+                       System.Text.StringBuilder resultTrailer = new System.Text.StringBuilder(0);\r
+                       System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1));\r
+                       int mode = ASCII_ENCODE;\r
+                       do \r
+                       {\r
+                               if (mode == ASCII_ENCODE)\r
+                               {\r
+                                       mode = decodeAsciiSegment(bits, result, resultTrailer);\r
+                               }\r
+                               else\r
+                               {\r
+                                       switch (mode)\r
+                                       {\r
+                                               \r
+                                               case C40_ENCODE: \r
+                                                       decodeC40Segment(bits, result);\r
+                                                       break;\r
+                                               \r
+                                               case TEXT_ENCODE: \r
+                                                       decodeTextSegment(bits, result);\r
+                                                       break;\r
+                                               \r
+                                               case ANSIX12_ENCODE: \r
+                                                       decodeAnsiX12Segment(bits, result);\r
+                                                       break;\r
+                                               \r
+                                               case EDIFACT_ENCODE: \r
+                                                       decodeEdifactSegment(bits, result);\r
+                                                       break;\r
+                                               \r
+                                               case BASE256_ENCODE: \r
+                                                       decodeBase256Segment(bits, result, byteSegments);\r
+                                                       break;\r
+                                               \r
+                                               default: \r
+                                                       throw ReaderException.Instance;\r
+                                               \r
+                                       }\r
+                                       mode = ASCII_ENCODE;\r
+                               }\r
+                       }\r
+                       while (mode != PAD_ENCODE && bits.available() > 0);\r
+                       if (resultTrailer.Length > 0)\r
+                       {\r
+                               result.Append(resultTrailer.ToString());\r
+                       }\r
+                       return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, null);\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, 5.2.3 and Annex C, Table C.2</summary>\r
+               private static int decodeAsciiSegment(BitSource bits, System.Text.StringBuilder result, System.Text.StringBuilder resultTrailer)\r
+               {\r
+                       bool upperShift = false;\r
+                       do \r
+                       {\r
+                               int oneByte = bits.readBits(8);\r
+                               if (oneByte == 0)\r
+                               {\r
+                                       throw ReaderException.Instance;\r
+                               }\r
+                               else if (oneByte <= 128)\r
+                               {\r
+                                       // ASCII data (ASCII value + 1)\r
+                                       oneByte = upperShift?(oneByte + 128):oneByte;\r
+                                       upperShift = false;\r
+                                       result.Append((char) (oneByte - 1));\r
+                                       return ASCII_ENCODE;\r
+                               }\r
+                               else if (oneByte == 129)\r
+                               {\r
+                                       // Pad\r
+                                       return PAD_ENCODE;\r
+                               }\r
+                               else if (oneByte <= 229)\r
+                               {\r
+                                       // 2-digit data 00-99 (Numeric Value + 130)\r
+                                       int value_Renamed = oneByte - 130;\r
+                                       if (value_Renamed < 10)\r
+                                       {\r
+                                               // padd with '0' for single digit values\r
+                                               result.Append('0');\r
+                                       }\r
+                                       result.Append(value_Renamed);\r
+                               }\r
+                               else if (oneByte == 230)\r
+                               {\r
+                                       // Latch to C40 encodation\r
+                                       return C40_ENCODE;\r
+                               }\r
+                               else if (oneByte == 231)\r
+                               {\r
+                                       // Latch to Base 256 encodation\r
+                                       return BASE256_ENCODE;\r
+                               }\r
+                               else if (oneByte == 232)\r
+                               {\r
+                                       // FNC1\r
+                                       //throw ReaderException.getInstance();\r
+                                       // Ignore this symbol for now\r
+                               }\r
+                               else if (oneByte == 233)\r
+                               {\r
+                                       // Structured Append\r
+                                       //throw ReaderException.getInstance();\r
+                                       // Ignore this symbol for now\r
+                               }\r
+                               else if (oneByte == 234)\r
+                               {\r
+                                       // Reader Programming\r
+                                       //throw ReaderException.getInstance();\r
+                                       // Ignore this symbol for now\r
+                               }\r
+                               else if (oneByte == 235)\r
+                               {\r
+                                       // Upper Shift (shift to Extended ASCII)\r
+                                       upperShift = true;\r
+                               }\r
+                               else if (oneByte == 236)\r
+                               {\r
+                                       // 05 Macro\r
+                                       result.Append("[)>\u001E05\u001D");\r
+                                       resultTrailer.Insert(0, "\u001E\u0004");\r
+                               }\r
+                               else if (oneByte == 237)\r
+                               {\r
+                                       // 06 Macro\r
+                                       result.Append("[)>\u001E06\u001D");\r
+                                       resultTrailer.Insert(0, "\u001E\u0004");\r
+                               }\r
+                               else if (oneByte == 238)\r
+                               {\r
+                                       // Latch to ANSI X12 encodation\r
+                                       return ANSIX12_ENCODE;\r
+                               }\r
+                               else if (oneByte == 239)\r
+                               {\r
+                                       // Latch to Text encodation\r
+                                       return TEXT_ENCODE;\r
+                               }\r
+                               else if (oneByte == 240)\r
+                               {\r
+                                       // Latch to EDIFACT encodation\r
+                                       return EDIFACT_ENCODE;\r
+                               }\r
+                               else if (oneByte == 241)\r
+                               {\r
+                                       // ECI Character\r
+                                       // TODO(bbrown): I think we need to support ECI\r
+                                       //throw ReaderException.getInstance();\r
+                                       // Ignore this symbol for now\r
+                               }\r
+                               else if (oneByte >= 242)\r
+                               {\r
+                                       // Not to be used in ASCII encodation\r
+                                       throw ReaderException.Instance;\r
+                               }\r
+                       }\r
+                       while (bits.available() > 0);\r
+                       return ASCII_ENCODE;\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, 5.2.5 and Annex C, Table C.1</summary>\r
+               private static void  decodeC40Segment(BitSource bits, System.Text.StringBuilder result)\r
+               {\r
+                       // Three C40 values are encoded in a 16-bit value as\r
+                       // (1600 * C1) + (40 * C2) + C3 + 1\r
+                       // TODO(bbrown): The Upper Shift with C40 doesn't work in the 4 value scenario all the time\r
+                       bool upperShift = false;\r
+                       \r
+                       int[] cValues = new int[3];\r
+                       do \r
+                       {\r
+                               // If there is only one byte left then it will be encoded as ASCII\r
+                               if (bits.available() == 8)\r
+                               {\r
+                                       return ;\r
+                               }\r
+                               int firstByte = bits.readBits(8);\r
+                               if (firstByte == 254)\r
+                               {\r
+                                       // Unlatch codeword\r
+                                       return ;\r
+                               }\r
+                               \r
+                               parseTwoBytes(firstByte, bits.readBits(8), cValues);\r
+                               \r
+                               int shift = 0;\r
+                               for (int i = 0; i < 3; i++)\r
+                               {\r
+                                       int cValue = cValues[i];\r
+                                       switch (shift)\r
+                                       {\r
+                                               \r
+                                               case 0: \r
+                                                       if (cValue < 3)\r
+                                                       {\r
+                                                               shift = cValue + 1;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               if (upperShift)\r
+                                                               {\r
+                                                                       result.Append((char) (C40_BASIC_SET_CHARS[cValue] + 128));\r
+                                                                       upperShift = false;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       result.Append(C40_BASIC_SET_CHARS[cValue]);\r
+                                                               }\r
+                                                       }\r
+                                                       break;\r
+                                               \r
+                                               case 1: \r
+                                                       if (upperShift)\r
+                                                       {\r
+                                                               result.Append((char) (cValue + 128));\r
+                                                               upperShift = false;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               result.Append(cValue);\r
+                                                       }\r
+                                                       shift = 0;\r
+                                                       break;\r
+                                               \r
+                                               case 2: \r
+                                                       if (cValue < 27)\r
+                                                       {\r
+                                                               if (upperShift)\r
+                                                               {\r
+                                                                       result.Append((char) (C40_SHIFT2_SET_CHARS[cValue] + 128));\r
+                                                                       upperShift = false;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       result.Append(C40_SHIFT2_SET_CHARS[cValue]);\r
+                                                               }\r
+                                                       }\r
+                                                       else if (cValue == 27)\r
+                                                       {\r
+                                                               // FNC1\r
+                                                               throw ReaderException.Instance;\r
+                                                       }\r
+                                                       else if (cValue == 30)\r
+                                                       {\r
+                                                               // Upper Shift\r
+                                                               upperShift = true;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               throw ReaderException.Instance;\r
+                                                       }\r
+                                                       shift = 0;\r
+                                                       break;\r
+                                               \r
+                                               case 3: \r
+                                                       if (upperShift)\r
+                                                       {\r
+                                                               result.Append((char) (cValue + 224));\r
+                                                               upperShift = false;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               result.Append((char) (cValue + 96));\r
+                                                       }\r
+                                                       shift = 0;\r
+                                                       break;\r
+                                               \r
+                                               default: \r
+                                                       throw ReaderException.Instance;\r
+                                               \r
+                                       }\r
+                               }\r
+                       }\r
+                       while (bits.available() > 0);\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, 5.2.6 and Annex C, Table C.2</summary>\r
+               private static void  decodeTextSegment(BitSource bits, System.Text.StringBuilder result)\r
+               {\r
+                       // Three Text values are encoded in a 16-bit value as\r
+                       // (1600 * C1) + (40 * C2) + C3 + 1\r
+                       // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time\r
+                       bool upperShift = false;\r
+                       \r
+                       int[] cValues = new int[3];\r
+                       do \r
+                       {\r
+                               // If there is only one byte left then it will be encoded as ASCII\r
+                               if (bits.available() == 8)\r
+                               {\r
+                                       return ;\r
+                               }\r
+                               int firstByte = bits.readBits(8);\r
+                               if (firstByte == 254)\r
+                               {\r
+                                       // Unlatch codeword\r
+                                       return ;\r
+                               }\r
+                               \r
+                               parseTwoBytes(firstByte, bits.readBits(8), cValues);\r
+                               \r
+                               int shift = 0;\r
+                               for (int i = 0; i < 3; i++)\r
+                               {\r
+                                       int cValue = cValues[i];\r
+                                       switch (shift)\r
+                                       {\r
+                                               \r
+                                               case 0: \r
+                                                       if (cValue < 3)\r
+                                                       {\r
+                                                               shift = cValue + 1;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               if (upperShift)\r
+                                                               {\r
+                                                                       result.Append((char) (TEXT_BASIC_SET_CHARS[cValue] + 128));\r
+                                                                       upperShift = false;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       result.Append(TEXT_BASIC_SET_CHARS[cValue]);\r
+                                                               }\r
+                                                       }\r
+                                                       break;\r
+                                               \r
+                                               case 1: \r
+                                                       if (upperShift)\r
+                                                       {\r
+                                                               result.Append((char) (cValue + 128));\r
+                                                               upperShift = false;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               result.Append(cValue);\r
+                                                       }\r
+                                                       shift = 0;\r
+                                                       break;\r
+                                               \r
+                                               case 2: \r
+                                                       // Shift 2 for Text is the same encoding as C40\r
+                                                       if (cValue < 27)\r
+                                                       {\r
+                                                               if (upperShift)\r
+                                                               {\r
+                                                                       result.Append((char) (C40_SHIFT2_SET_CHARS[cValue] + 128));\r
+                                                                       upperShift = false;\r
+                                                               }\r
+                                                               else\r
+                                                               {\r
+                                                                       result.Append(C40_SHIFT2_SET_CHARS[cValue]);\r
+                                                               }\r
+                                                       }\r
+                                                       else if (cValue == 27)\r
+                                                       {\r
+                                                               // FNC1\r
+                                                               throw ReaderException.Instance;\r
+                                                       }\r
+                                                       else if (cValue == 30)\r
+                                                       {\r
+                                                               // Upper Shift\r
+                                                               upperShift = true;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               throw ReaderException.Instance;\r
+                                                       }\r
+                                                       shift = 0;\r
+                                                       break;\r
+                                               \r
+                                               case 3: \r
+                                                       if (upperShift)\r
+                                                       {\r
+                                                               result.Append((char) (TEXT_SHIFT3_SET_CHARS[cValue] + 128));\r
+                                                               upperShift = false;\r
+                                                       }\r
+                                                       else\r
+                                                       {\r
+                                                               result.Append(TEXT_SHIFT3_SET_CHARS[cValue]);\r
+                                                       }\r
+                                                       shift = 0;\r
+                                                       break;\r
+                                               \r
+                                               default: \r
+                                                       throw ReaderException.Instance;\r
+                                               \r
+                                       }\r
+                               }\r
+                       }\r
+                       while (bits.available() > 0);\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, 5.2.7</summary>\r
+               private static void  decodeAnsiX12Segment(BitSource bits, System.Text.StringBuilder result)\r
+               {\r
+                       // Three ANSI X12 values are encoded in a 16-bit value as\r
+                       // (1600 * C1) + (40 * C2) + C3 + 1\r
+                       \r
+                       int[] cValues = new int[3];\r
+                       do \r
+                       {\r
+                               // If there is only one byte left then it will be encoded as ASCII\r
+                               if (bits.available() == 8)\r
+                               {\r
+                                       return ;\r
+                               }\r
+                               int firstByte = bits.readBits(8);\r
+                               if (firstByte == 254)\r
+                               {\r
+                                       // Unlatch codeword\r
+                                       return ;\r
+                               }\r
+                               \r
+                               parseTwoBytes(firstByte, bits.readBits(8), cValues);\r
+                               \r
+                               for (int i = 0; i < 3; i++)\r
+                               {\r
+                                       int cValue = cValues[i];\r
+                                       if (cValue == 0)\r
+                                       {\r
+                                               // X12 segment terminator <CR>\r
+                                               result.Append('\r');\r
+                                       }\r
+                                       else if (cValue == 1)\r
+                                       {\r
+                                               // X12 segment separator *\r
+                                               result.Append('*');\r
+                                       }\r
+                                       else if (cValue == 2)\r
+                                       {\r
+                                               // X12 sub-element separator >\r
+                                               result.Append('>');\r
+                                       }\r
+                                       else if (cValue == 3)\r
+                                       {\r
+                                               // space\r
+                                               result.Append(' ');\r
+                                       }\r
+                                       else if (cValue < 14)\r
+                                       {\r
+                                               // 0 - 9\r
+                                               result.Append((char) (cValue + 44));\r
+                                       }\r
+                                       else if (cValue < 40)\r
+                                       {\r
+                                               // A - Z\r
+                                               result.Append((char) (cValue + 51));\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               throw ReaderException.Instance;\r
+                                       }\r
+                               }\r
+                       }\r
+                       while (bits.available() > 0);\r
+               }\r
+               \r
+               private static void  parseTwoBytes(int firstByte, int secondByte, int[] result)\r
+               {\r
+                       int fullBitValue = (firstByte << 8) + secondByte - 1;\r
+                       int temp = fullBitValue / 1600;\r
+                       result[0] = temp;\r
+                       fullBitValue -= temp * 1600;\r
+                       temp = fullBitValue / 40;\r
+                       result[1] = temp;\r
+                       result[2] = fullBitValue - temp * 40;\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, 5.2.8 and Annex C Table C.3</summary>\r
+               private static void  decodeEdifactSegment(BitSource bits, System.Text.StringBuilder result)\r
+               {\r
+                       bool unlatch = false;\r
+                       do \r
+                       {\r
+                               // If there is only two or less bytes left then it will be encoded as ASCII\r
+                               if (bits.available() <= 16)\r
+                               {\r
+                                       return ;\r
+                               }\r
+                               \r
+                               for (int i = 0; i < 4; i++)\r
+                               {\r
+                                       int edifactValue = bits.readBits(6);\r
+                                       \r
+                                       // Check for the unlatch character\r
+                                       if (edifactValue == 0x2B67)\r
+                                       {\r
+                                               // 011111\r
+                                               unlatch = true;\r
+                                               // If we encounter the unlatch code then continue reading because the Codeword triple\r
+                                               // is padded with 0's\r
+                                       }\r
+                                       \r
+                                       if (!unlatch)\r
+                                       {\r
+                                               if ((edifactValue & 32) == 0)\r
+                                               {\r
+                                                       // no 1 in the leading (6th) bit\r
+                                                       edifactValue |= 64; // Add a leading 01 to the 6 bit binary value\r
+                                               }\r
+                                               result.Append(edifactValue);\r
+                                       }\r
+                               }\r
+                       }\r
+                       while (!unlatch && bits.available() > 0);\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, 5.2.9 and Annex B, B.2</summary>\r
+               private static void  decodeBase256Segment(BitSource bits, System.Text.StringBuilder result, System.Collections.ArrayList byteSegments)\r
+               {\r
+                       // Figure out how long the Base 256 Segment is.\r
+                       int d1 = bits.readBits(8);\r
+                       int count;\r
+                       if (d1 == 0)\r
+                       {\r
+                               // Read the remainder of the symbol\r
+                               count = bits.available() / 8;\r
+                       }\r
+                       else if (d1 < 250)\r
+                       {\r
+                               count = d1;\r
+                       }\r
+                       else\r
+                       {\r
+                               count = 250 * (d1 - 249) + bits.readBits(8);\r
+                       }\r
+                       sbyte[] bytes = new sbyte[count];\r
+                       for (int i = 0; i < count; i++)\r
+                       {\r
+                               bytes[i] = unrandomize255State(bits.readBits(8), i);\r
+                       }\r
+                       byteSegments.Add(SupportClass.ToByteArray(bytes));\r
+                       try\r
+                       {\r
+                               //UPGRADE_TODO: The differences in the Format  of parameters for constructor 'java.lang.String.String'  may cause compilation errors.  "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1092'"\r
+                               result.Append(System.Text.Encoding.GetEncoding("ISO8859_1").GetString(SupportClass.ToByteArray(bytes)));\r
+                       }\r
+                       catch (System.IO.IOException uee)\r
+                       {\r
+                               //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Throwable.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"\r
+                               throw new System.SystemException("Platform does not support required encoding: " + uee);\r
+                       }\r
+               }\r
+               \r
+               /// <summary> See ISO 16022:2006, Annex B, B.2</summary>\r
+               private static sbyte unrandomize255State(int randomizedBase256Codeword, int base256CodewordPosition)\r
+               {\r
+                       int pseudoRandomNumber = ((149 * base256CodewordPosition) % 255) + 1;\r
+                       int tempVariable = randomizedBase256Codeword - pseudoRandomNumber;\r
+                       return (sbyte) (tempVariable >= 0?tempVariable:(tempVariable + 256));\r
+               }\r
+       }\r
+}
\ No newline at end of file