/// <summary>
        ///
        /// ISO/IEC 18004:2006(E)
        /// Table 2 ¡ª Mode indicators for QR Code 2005
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="version"></param>
        /// <param name="ecLevel"></param>
        /// <returns></returns>
        internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel)
        {
            BitSource bits = new BitSource(bytes);

            System.Text.StringBuilder result = new System.Text.StringBuilder(50);
            CharacterSetECI           currentCharacterSetECI = null;
            bool fc1InEffect = false;

            System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1));
            Mode mode   = Mode.TERMINATOR;
            int  bitLen = Mode.NUMERIC.getBitsLength(version.VersionNumber);

            if (version.VersionNumber > 1)
            {
                try
                {
                    mode = Mode.forBits(bits.readBits(bitLen));
                }
                catch (System.ArgumentException iae)
                {
                    throw ReaderException.Instance;
                }
            }
            else
            {
                mode = Mode.NUMERIC;
            }

            if (!mode.Equals(Mode.TERMINATOR))
            {
                // How many characters will follow, encoded in this mode?
                int count = bits.readBits(mode.getCharacterCountBits(version));
                if (mode.Equals(Mode.NUMERIC))
                {
                    decodeNumericSegment(bits, result, count);
                }
                else if (mode.Equals(Mode.ALPHANUMERIC))
                {
                    decodeAlphanumericSegment(bits, result, count, fc1InEffect);
                }
                else if (mode.Equals(Mode.BYTE))
                {
                    decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments);
                }
                else if (mode.Equals(Mode.KANJI))
                {
                    decodeKanjiSegment(bits, result, count);
                }
                else
                {
                    throw ReaderException.Instance;
                }
            }

            return(new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0) ? null : byteSegments, ecLevel));
        }
        internal static DecoderResult decode(sbyte[] bytes)
        {
            BitSource bits = new BitSource(bytes);
            System.Text.StringBuilder result = new System.Text.StringBuilder(100);
            System.Text.StringBuilder resultTrailer = new System.Text.StringBuilder(0);
            // System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); // commented by .net follower (http://dotnetfollower.com)
            System.Collections.Generic.List<Object> byteSegments = new System.Collections.Generic.List<Object>(1); // added by .net follower (http://dotnetfollower.com)
            int mode = ASCII_ENCODE;
            do
            {
                if (mode == ASCII_ENCODE)
                {
                    mode = decodeAsciiSegment(bits, result, resultTrailer);
                }
                else
                {
                    switch (mode)
                    {

                        case C40_ENCODE:
                            decodeC40Segment(bits, result);
                            break;

                        case TEXT_ENCODE:
                            decodeTextSegment(bits, result);
                            break;

                        case ANSIX12_ENCODE:
                            decodeAnsiX12Segment(bits, result);
                            break;

                        case EDIFACT_ENCODE:
                            decodeEdifactSegment(bits, result);
                            break;

                        case BASE256_ENCODE:
                            decodeBase256Segment(bits, result, byteSegments);
                            break;

                        default:
                            throw ReaderException.Instance;

                    }
                    mode = ASCII_ENCODE;
                }
            }
            while (mode != PAD_ENCODE && bits.available() > 0);
            if (resultTrailer.Length > 0)
            {
                result.Append(resultTrailer.ToString());
            }
            return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, null);
        }
Exemplo n.º 3
0
        internal static DecoderResult decode(sbyte[] bytes)
        {
            BitSource bits = new BitSource(bytes);

            System.Text.StringBuilder result        = new System.Text.StringBuilder(100);
            System.Text.StringBuilder resultTrailer = new System.Text.StringBuilder(0);
            // System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1)); // commented by .net follower (http://dotnetfollower.com)
            System.Collections.Generic.List <Object> byteSegments = new System.Collections.Generic.List <Object>(1); // added by .net follower (http://dotnetfollower.com)
            int mode = ASCII_ENCODE;

            do
            {
                if (mode == ASCII_ENCODE)
                {
                    mode = decodeAsciiSegment(bits, result, resultTrailer);
                }
                else
                {
                    switch (mode)
                    {
                    case C40_ENCODE:
                        decodeC40Segment(bits, result);
                        break;

                    case TEXT_ENCODE:
                        decodeTextSegment(bits, result);
                        break;

                    case ANSIX12_ENCODE:
                        decodeAnsiX12Segment(bits, result);
                        break;

                    case EDIFACT_ENCODE:
                        decodeEdifactSegment(bits, result);
                        break;

                    case BASE256_ENCODE:
                        decodeBase256Segment(bits, result, byteSegments);
                        break;

                    default:
                        throw ReaderException.Instance;
                    }
                    mode = ASCII_ENCODE;
                }
            }while (mode != PAD_ENCODE && bits.available() > 0);
            if (resultTrailer.Length > 0)
            {
                result.Append(resultTrailer.ToString());
            }
            return(new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, null));
        }
Exemplo n.º 4
0
        internal static DecoderResult decode(sbyte[] bytes)
        {
            BitSource bits = new BitSource(bytes);

            System.Text.StringBuilder result        = new System.Text.StringBuilder(100);
            System.Text.StringBuilder resultTrailer = new System.Text.StringBuilder(0);
            List <object>             byteSegments  = new List <object>();
            int mode = ASCII_ENCODE;

            do
            {
                if (mode == ASCII_ENCODE)
                {
                    mode = decodeAsciiSegment(bits, result, resultTrailer);
                }
                else
                {
                    switch (mode)
                    {
                    case C40_ENCODE:
                        decodeC40Segment(bits, result);
                        break;

                    case TEXT_ENCODE:
                        decodeTextSegment(bits, result);
                        break;

                    case ANSIX12_ENCODE:
                        decodeAnsiX12Segment(bits, result);
                        break;

                    case EDIFACT_ENCODE:
                        decodeEdifactSegment(bits, result);
                        break;

                    case BASE256_ENCODE:
                        decodeBase256Segment(bits, result, byteSegments);
                        break;

                    default:
                        throw ReaderException.Instance;
                    }
                    mode = ASCII_ENCODE;
                }
            }while (mode != PAD_ENCODE && bits.available() > 0);
            if (resultTrailer.Length > 0)
            {
                result.Append(resultTrailer.ToString());
            }
            return(new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, null));
        }
        private static void  decodeKanjiSegment(BitSource bits, System.Text.StringBuilder result, int count)
        {
            // Each character will require 2 bytes. Read the characters as 2-byte pairs
            // and decode as Shift_JIS afterwards
            sbyte[] buffer = new sbyte[2 * count];
            int     offset = 0;

            while (count > 0)
            {
                // Each 13 bits encodes a 2-byte character
                int twoBytes          = bits.readBits(13);
                int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
                if (assembledTwoBytes < 0x01F00)
                {
                    // In the 0x8140 to 0x9FFC range
                    assembledTwoBytes += 0x08140;
                }
                else
                {
                    // In the 0xE040 to 0xEBBF range
                    assembledTwoBytes += 0x0C140;
                }
                buffer[offset]     = (sbyte)(assembledTwoBytes >> 8);
                buffer[offset + 1] = (sbyte)assembledTwoBytes;
                offset            += 2;
                count--;
            }
            // Shift_JIS may not be supported in some environments:
            try
            {
                //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'"
#if WINDOWS_PHONE
                byte[] byteArray = SupportClass.ToByteArray(buffer);
                result.Append(System.Text.Encoding.GetEncoding(SHIFT_JIS).GetString(byteArray, 0, byteArray.Length));
#else
                result.Append(System.Text.Encoding.GetEncoding(SHIFT_JIS).GetString(SupportClass.ToByteArray(buffer)));
#endif
            }
            catch (System.IO.IOException uee)
            {
                throw ReaderException.Instance;
            }
        }
        private static void  decodeByteSegment(BitSource bits, System.Text.StringBuilder result, int count, CharacterSetECI currentCharacterSetECI, System.Collections.ArrayList byteSegments)
        {
            sbyte[] readBytes = new sbyte[count];
            if (count << 3 > bits.available())
            {
                throw ReaderException.Instance;
            }
            for (int i = 0; i < count; i++)
            {
                readBytes[i] = (sbyte)bits.readBits(8);
            }
            System.String encoding;
            if (currentCharacterSetECI == null)
            {
                // The spec isn't clear on this mode; see
                // section 6.4.5: t does not say which encoding to assuming
                // upon decoding. I have seen ISO-8859-1 used as well as
                // Shift_JIS -- without anything like an ECI designator to
                // give a hint.
                encoding = guessEncoding(readBytes);
            }
            else
            {
                encoding = currentCharacterSetECI.EncodingName;
            }
            try
            {
                //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'"
#if WINDOWS_PHONE
                byte[] byteArray = SupportClass.ToByteArray(readBytes);
                result.Append(System.Text.Encoding.GetEncoding(encoding).GetString(byteArray, 0, byteArray.Length));
#else
                result.Append(System.Text.Encoding.GetEncoding(encoding).GetString(SupportClass.ToByteArray(readBytes)));
#endif
            }
            catch (System.IO.IOException uce)
            {
                throw ReaderException.Instance;
            }
            byteSegments.Add(SupportClass.ToByteArray(readBytes));
        }
        /// <summary> See ISO 16022:2006, 5.2.9 and Annex B, B.2</summary>
        private static void  decodeBase256Segment(BitSource bits, System.Text.StringBuilder result, System.Collections.ArrayList byteSegments)
        {
            // Figure out how long the Base 256 Segment is.
            int d1 = bits.readBits(8);
            int count;

            if (d1 == 0)
            {
                // Read the remainder of the symbol
                count = bits.available() / 8;
            }
            else if (d1 < 250)
            {
                count = d1;
            }
            else
            {
                count = 250 * (d1 - 249) + bits.readBits(8);
            }
            sbyte[] bytes = new sbyte[count];
            for (int i = 0; i < count; i++)
            {
                bytes[i] = unrandomize255State(bits.readBits(8), i);
            }
            byteSegments.Add(SupportClass.ToByteArray(bytes));
            try
            {
                //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'"
#if WINDOWS_PHONE
                byte[] byteArray = SupportClass.ToByteArray(bytes);
                result.Append(System.Text.Encoding.GetEncoding("ISO8859_1").GetString(byteArray, 0, byteArray.Length));
#else
                result.Append(System.Text.Encoding.GetEncoding("ISO8859_1").GetString(SupportClass.ToByteArray(bytes)));
#endif
            }
            catch (System.IO.IOException uee)
            {
                //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'"
                throw new System.SystemException("Platform does not support required encoding: " + uee);
            }
        }
        private static void  decodeAlphanumericSegment(BitSource bits, System.Text.StringBuilder result, int count, bool fc1InEffect)
        {
            // Read two characters at a time
            int start = result.Length;

            while (count > 1)
            {
                int nextTwoCharsBits = bits.readBits(11);
                result.Append(ALPHANUMERIC_CHARS[nextTwoCharsBits / 45]);
                result.Append(ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]);
                count -= 2;
            }
            if (count == 1)
            {
                // special case: one character left
                result.Append(ALPHANUMERIC_CHARS[bits.readBits(6)]);
            }
            // See section 6.4.8.1, 6.4.8.2
            if (fc1InEffect)
            {
                // We need to massage the result a bit if in an FNC1 mode:
                for (int i = start; i < result.Length; i++)
                {
                    if (result[i] == '%')
                    {
                        if (i < result.Length - 1 && result[i + 1] == '%')
                        {
                            // %% is rendered as %
                            result.Remove(i + 1, 1);
                        }
                        else
                        {
                            // In alpha mode, % should be converted to FNC1 separator 0x1D
                            result[i] = (char)0x1D;
                        }
                    }
                }
            }
        }
 private static void  decodeNumericSegment(BitSource bits, System.Text.StringBuilder result, int count)
 {
     // Read three digits at a time
     while (count >= 3)
     {
         // Each 10 bits encodes three digits
         int threeDigitsBits = bits.readBits(10);
         if (threeDigitsBits >= 1000)
         {
             throw ReaderException.Instance;
         }
         result.Append(ALPHANUMERIC_CHARS[threeDigitsBits / 100]);
         result.Append(ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]);
         result.Append(ALPHANUMERIC_CHARS[threeDigitsBits % 10]);
         count -= 3;
     }
     if (count == 2)
     {
         // Two digits left over to read, encoded in 7 bits
         int twoDigitsBits = bits.readBits(7);
         if (twoDigitsBits >= 100)
         {
             throw ReaderException.Instance;
         }
         result.Append(ALPHANUMERIC_CHARS[twoDigitsBits / 10]);
         result.Append(ALPHANUMERIC_CHARS[twoDigitsBits % 10]);
     }
     else if (count == 1)
     {
         // One digit left over to read
         int digitBits = bits.readBits(4);
         if (digitBits >= 10)
         {
             throw ReaderException.Instance;
         }
         result.Append(ALPHANUMERIC_CHARS[digitBits]);
     }
 }
        private static int parseECIValue(BitSource bits)
        {
            int firstByte = bits.readBits(8);

            if ((firstByte & 0x80) == 0)
            {
                // just one byte
                return(firstByte & 0x7F);
            }
            else if ((firstByte & 0xC0) == 0x80)
            {
                // two bytes
                int secondByte = bits.readBits(8);
                return(((firstByte & 0x3F) << 8) | secondByte);
            }
            else if ((firstByte & 0xE0) == 0xC0)
            {
                // three bytes
                int secondThirdBytes = bits.readBits(16);
                return(((firstByte & 0x1F) << 16) | secondThirdBytes);
            }
            throw new System.ArgumentException("Bad ECI bits starting with byte " + firstByte);
        }
Exemplo n.º 11
0
        /// <summary> See ISO 16022:2006, 5.2.8 and Annex C Table C.3</summary>
        private static void  decodeEdifactSegment(BitSource bits, System.Text.StringBuilder result)
        {
            bool unlatch = false;

            do
            {
                // If there is only two or less bytes left then it will be encoded as ASCII
                if (bits.available() <= 16)
                {
                    return;
                }

                for (int i = 0; i < 4; i++)
                {
                    int edifactValue = bits.readBits(6);

                    // Check for the unlatch character
                    if (edifactValue == 0x2B67)
                    {
                        // 011111
                        unlatch = true;
                        // If we encounter the unlatch code then continue reading because the Codeword triple
                        // is padded with 0's
                    }

                    if (!unlatch)
                    {
                        if ((edifactValue & 32) == 0)
                        {
                            // no 1 in the leading (6th) bit
                            edifactValue |= 64;                             // Add a leading 01 to the 6 bit binary value
                        }
                        result.Append(edifactValue);
                    }
                }
            }while (!unlatch && bits.available() > 0);
        }
 private static void decodeAlphanumericSegment(BitSource bits, System.Text.StringBuilder result, int count, bool fc1InEffect)
 {
     // Read two characters at a time
     int start = result.Length;
     while (count > 1)
     {
         int nextTwoCharsBits = bits.readBits(11);
         result.Append(ALPHANUMERIC_CHARS[nextTwoCharsBits / 45]);
         result.Append(ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]);
         count -= 2;
     }
     if (count == 1)
     {
         // special case: one character left
         result.Append(ALPHANUMERIC_CHARS[bits.readBits(6)]);
     }
     // See section 6.4.8.1, 6.4.8.2
     if (fc1InEffect)
     {
         // We need to massage the result a bit if in an FNC1 mode:
         for (int i = start; i < result.Length; i++)
         {
             if (result[i] == '%')
             {
                 if (i < result.Length - 1 && result[i + 1] == '%')
                 {
                     // %% is rendered as %
                     result.Remove(i + 1, 1);
                 }
                 else
                 {
                     // In alpha mode, % should be converted to FNC1 separator 0x1D
                     result[i] = (char) 0x1D;
                 }
             }
         }
     }
 }
        private static void decodeAlphanumericSegment(BitSource bits, StringBuilder result, int count, bool fc1InEffect)
        {
            // Read two characters at a time
            int start = result.ToString().Length;
            while (count > 1)
            {
                int nextTwoCharsBits = bits.readBits(11);
                result.Append(ALPHANUMERIC_CHARS[Math.Floor(nextTwoCharsBits / 45)]);
                result.Append(ALPHANUMERIC_CHARS[nextTwoCharsBits % 45]);
                count -= 2;
            }
            if (count == 1)
            {
                // special case: one character left
                result.Append(ALPHANUMERIC_CHARS[bits.readBits(6)]);
            }

            char[] c = new char[result.ToString().Length];
            SupportClass.GetCharsFromString(result.ToString(), 0, result.ToString().Length, c, 0);
            List<char> list = new List<char>(c);
            // See section 6.4.8.1, 6.4.8.2
            if (fc1InEffect)
            {
                // We need to massage the result a bit if in an FNC1 mode:
                for (int i = start; i < list.Count; i++)
                {
                    if (list[i] == '%')
                    {
                        if (i < list.Count - 1 && list[i + 1] == '%')
                        {
                            // %% is rendered as %
                            list = list.RemoveRange(i + 1, 1);
                        }
                        else
                        {
                            // In alpha mode, % should be converted to FNC1 separator 0x1D
                            list[i] = Int32Extend.ToChar(0x1D);
                        }
                    }
                }
                result.Clear();
                result.Append(list.Join());
            }
        }
Exemplo n.º 14
0
        /// <summary> See ISO 16022:2006, 5.2.3 and Annex C, Table C.2</summary>
        private static int decodeAsciiSegment(BitSource bits, System.Text.StringBuilder result, System.Text.StringBuilder resultTrailer)
        {
            bool upperShift = false;

            do
            {
                int oneByte = bits.readBits(8);
                if (oneByte == 0)
                {
                    throw ReaderException.Instance;
                }
                else if (oneByte <= 128)
                {
                    // ASCII data (ASCII value + 1)
                    oneByte    = upperShift?(oneByte + 128):oneByte;
                    upperShift = false;
                    result.Append((char)(oneByte - 1));
                    return(ASCII_ENCODE);
                }
                else if (oneByte == 129)
                {
                    // Pad
                    return(PAD_ENCODE);
                }
                else if (oneByte <= 229)
                {
                    // 2-digit data 00-99 (Numeric Value + 130)
                    int value_Renamed = oneByte - 130;
                    if (value_Renamed < 10)
                    {
                        // padd with '0' for single digit values
                        result.Append('0');
                    }
                    result.Append(value_Renamed);
                }
                else if (oneByte == 230)
                {
                    // Latch to C40 encodation
                    return(C40_ENCODE);
                }
                else if (oneByte == 231)
                {
                    // Latch to Base 256 encodation
                    return(BASE256_ENCODE);
                }
                else if (oneByte == 232)
                {
                    // FNC1
                    //throw ReaderException.getInstance();
                    // Ignore this symbol for now
                }
                else if (oneByte == 233)
                {
                    // Structured Append
                    //throw ReaderException.getInstance();
                    // Ignore this symbol for now
                }
                else if (oneByte == 234)
                {
                    // Reader Programming
                    //throw ReaderException.getInstance();
                    // Ignore this symbol for now
                }
                else if (oneByte == 235)
                {
                    // Upper Shift (shift to Extended ASCII)
                    upperShift = true;
                }
                else if (oneByte == 236)
                {
                    // 05 Macro
                    result.Append("[)>\u001E05\u001D");
                    resultTrailer.Insert(0, "\u001E\u0004");
                }
                else if (oneByte == 237)
                {
                    // 06 Macro
                    result.Append("[)>\u001E06\u001D");
                    resultTrailer.Insert(0, "\u001E\u0004");
                }
                else if (oneByte == 238)
                {
                    // Latch to ANSI X12 encodation
                    return(ANSIX12_ENCODE);
                }
                else if (oneByte == 239)
                {
                    // Latch to Text encodation
                    return(TEXT_ENCODE);
                }
                else if (oneByte == 240)
                {
                    // Latch to EDIFACT encodation
                    return(EDIFACT_ENCODE);
                }
                else if (oneByte == 241)
                {
                    // ECI Character
                    // TODO(bbrown): I think we need to support ECI
                    //throw ReaderException.getInstance();
                    // Ignore this symbol for now
                }
                else if (oneByte >= 242)
                {
                    // Not to be used in ASCII encodation
                    throw ReaderException.Instance;
                }
            }while (bits.available() > 0);
            return(ASCII_ENCODE);
        }
Exemplo n.º 15
0
        /// <summary> See ISO 16022:2006, 5.2.6 and Annex C, Table C.2</summary>
        private static void  decodeTextSegment(BitSource bits, System.Text.StringBuilder result)
        {
            // Three Text values are encoded in a 16-bit value as
            // (1600 * C1) + (40 * C2) + C3 + 1
            // TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
            bool upperShift = false;

            int[] cValues = new int[3];
            do
            {
                // If there is only one byte left then it will be encoded as ASCII
                if (bits.available() == 8)
                {
                    return;
                }
                int firstByte = bits.readBits(8);
                if (firstByte == 254)
                {
                    // Unlatch codeword
                    return;
                }

                parseTwoBytes(firstByte, bits.readBits(8), cValues);

                int shift = 0;
                for (int i = 0; i < 3; i++)
                {
                    int cValue = cValues[i];
                    switch (shift)
                    {
                    case 0:
                        if (cValue < 3)
                        {
                            shift = cValue + 1;
                        }
                        else
                        {
                            if (upperShift)
                            {
                                result.Append((char)(TEXT_BASIC_SET_CHARS[cValue] + 128));
                                upperShift = false;
                            }
                            else
                            {
                                result.Append(TEXT_BASIC_SET_CHARS[cValue]);
                            }
                        }
                        break;

                    case 1:
                        if (upperShift)
                        {
                            result.Append((char)(cValue + 128));
                            upperShift = false;
                        }
                        else
                        {
                            result.Append(cValue);
                        }
                        shift = 0;
                        break;

                    case 2:
                        // Shift 2 for Text is the same encoding as C40
                        if (cValue < 27)
                        {
                            if (upperShift)
                            {
                                result.Append((char)(C40_SHIFT2_SET_CHARS[cValue] + 128));
                                upperShift = false;
                            }
                            else
                            {
                                result.Append(C40_SHIFT2_SET_CHARS[cValue]);
                            }
                        }
                        else if (cValue == 27)
                        {
                            // FNC1
                            throw ReaderException.Instance;
                        }
                        else if (cValue == 30)
                        {
                            // Upper Shift
                            upperShift = true;
                        }
                        else
                        {
                            throw ReaderException.Instance;
                        }
                        shift = 0;
                        break;

                    case 3:
                        if (upperShift)
                        {
                            result.Append((char)(TEXT_SHIFT3_SET_CHARS[cValue] + 128));
                            upperShift = false;
                        }
                        else
                        {
                            result.Append(TEXT_SHIFT3_SET_CHARS[cValue]);
                        }
                        shift = 0;
                        break;

                    default:
                        throw ReaderException.Instance;
                    }
                }
            }while (bits.available() > 0);
        }
		/// <summary> See ISO 16022:2006, 5.2.9 and Annex B, B.2</summary>
		private static void  decodeBase256Segment(BitSource bits, System.Text.StringBuilder result, System.Collections.ArrayList byteSegments)
		{
			// Figure out how long the Base 256 Segment is.
			int d1 = bits.readBits(8);
			int count;
			if (d1 == 0)
			{
				// Read the remainder of the symbol
				count = bits.available() / 8;
			}
			else if (d1 < 250)
			{
				count = d1;
			}
			else
			{
				count = 250 * (d1 - 249) + bits.readBits(8);
			}
			sbyte[] bytes = new sbyte[count];
			for (int i = 0; i < count; i++)
			{
				bytes[i] = unrandomize255State(bits.readBits(8), i);
			}
			byteSegments.Add(SupportClass.ToByteArray(bytes));
			try
			{
				//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'"
#if WINDOWS_PHONE
                byte[] byteArray = SupportClass.ToByteArray(bytes);
                result.Append(System.Text.Encoding.GetEncoding("ISO8859_1").GetString(byteArray, 0, byteArray.Length));
#else
                result.Append(System.Text.Encoding.GetEncoding("ISO8859_1").GetString(SupportClass.ToByteArray(bytes)));
#endif
			}
			catch (System.IO.IOException uee)
			{
				//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'"
				throw new System.SystemException("Platform does not support required encoding: " + uee);
			}
		}
		/// <summary> See ISO 16022:2006, 5.2.8 and Annex C Table C.3</summary>
		private static void  decodeEdifactSegment(BitSource bits, System.Text.StringBuilder result)
		{
			bool unlatch = false;
			do 
			{
				// If there is only two or less bytes left then it will be encoded as ASCII
				if (bits.available() <= 16)
				{
					return ;
				}
				
				for (int i = 0; i < 4; i++)
				{
					int edifactValue = bits.readBits(6);
					
					// Check for the unlatch character
					if (edifactValue == 0x2B67)
					{
						// 011111
						unlatch = true;
						// If we encounter the unlatch code then continue reading because the Codeword triple
						// is padded with 0's
					}
					
					if (!unlatch)
					{
						if ((edifactValue & 32) == 0)
						{
							// no 1 in the leading (6th) bit
							edifactValue |= 64; // Add a leading 01 to the 6 bit binary value
						}
						result.Append(edifactValue);
					}
				}
			}
			while (!unlatch && bits.available() > 0);
		}
        internal static DecoderResult decode(sbyte[] bytes)
        {
            BitSource bits = new BitSource(bytes);
            StringBuilder result = new StringBuilder();
            StringBuilder resultTrailer = new StringBuilder();
            ArrayList byteSegments = new ArrayList();
            int mode = ASCII_ENCODE;
            do
            {
                if (mode == ASCII_ENCODE)
                {
                    mode = decodeAsciiSegment(bits, result, resultTrailer);
                }
                else
                {
                    switch (mode)
                    {

                        case C40_ENCODE:
                            decodeC40Segment(bits, result);
                            break;

                        case TEXT_ENCODE:
                            decodeTextSegment(bits, result);
                            break;

                        case ANSIX12_ENCODE:
                            decodeAnsiX12Segment(bits, result);
                            break;

                        case EDIFACT_ENCODE:
                            decodeEdifactSegment(bits, result);
                            break;

                        case BASE256_ENCODE:
                            decodeBase256Segment(bits, result, byteSegments);
                            break;

                        default:
                            throw new Exception("ReaderException");

                    }
                    mode = ASCII_ENCODE;
                }
            }
            while (mode != PAD_ENCODE && bits.available() > 0);
            if (resultTrailer.ToString().Length > 0)
            {
                result.Append(resultTrailer.ToString());
            }
            return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, null);
        }
 private static int parseECIValue(BitSource bits)
 {
     int firstByte = bits.readBits(8);
     if ((firstByte & 0x80) == 0)
     {
         // just one byte
         return firstByte & 0x7F;
     }
     else if ((firstByte & 0xC0) == 0x80)
     {
         // two bytes
         int secondByte = bits.readBits(8);
         return ((firstByte & 0x3F) << 8) | secondByte;
     }
     else if ((firstByte & 0xE0) == 0xC0)
     {
         // three bytes
         int secondThirdBytes = bits.readBits(16);
         return ((firstByte & 0x1F) << 16) | secondThirdBytes;
     }
     throw new System.ArgumentException("Bad ECI bits starting with byte " + firstByte);
 }
 private static void decodeKanjiSegment(BitSource bits, System.Text.StringBuilder result, int count)
 {
     // Each character will require 2 bytes. Read the characters as 2-byte pairs
     // and decode as Shift_JIS afterwards
     sbyte[] buffer = new sbyte[2 * count];
     int offset = 0;
     while (count > 0)
     {
         // Each 13 bits encodes a 2-byte character
         int twoBytes = bits.readBits(13);
         int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
         if (assembledTwoBytes < 0x01F00)
         {
             // In the 0x8140 to 0x9FFC range
             assembledTwoBytes += 0x08140;
         }
         else
         {
             // In the 0xE040 to 0xEBBF range
             assembledTwoBytes += 0x0C140;
         }
         buffer[offset] = (sbyte) (assembledTwoBytes >> 8);
         buffer[offset + 1] = (sbyte) assembledTwoBytes;
         offset += 2;
         count--;
     }
     // Shift_JIS may not be supported in some environments:
     try
     {
         //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'"
         result.Append(System.Text.Encoding.GetEncoding(SHIFT_JIS).GetString(SupportClass.ToByteArray(buffer)));
     }
     catch (System.IO.IOException)
     {
         throw ReaderException.Instance;
     }
 }
Exemplo n.º 21
0
        /// <summary> See ISO 16022:2006, 5.2.7</summary>
        private static void  decodeAnsiX12Segment(BitSource bits, System.Text.StringBuilder result)
        {
            // Three ANSI X12 values are encoded in a 16-bit value as
            // (1600 * C1) + (40 * C2) + C3 + 1

            int[] cValues = new int[3];
            do
            {
                // If there is only one byte left then it will be encoded as ASCII
                if (bits.available() == 8)
                {
                    return;
                }
                int firstByte = bits.readBits(8);
                if (firstByte == 254)
                {
                    // Unlatch codeword
                    return;
                }

                parseTwoBytes(firstByte, bits.readBits(8), cValues);

                for (int i = 0; i < 3; i++)
                {
                    int cValue = cValues[i];
                    if (cValue == 0)
                    {
                        // X12 segment terminator <CR>
                        result.Append('\r');
                    }
                    else if (cValue == 1)
                    {
                        // X12 segment separator *
                        result.Append('*');
                    }
                    else if (cValue == 2)
                    {
                        // X12 sub-element separator >
                        result.Append('>');
                    }
                    else if (cValue == 3)
                    {
                        // space
                        result.Append(' ');
                    }
                    else if (cValue < 14)
                    {
                        // 0 - 9
                        result.Append((char)(cValue + 44));
                    }
                    else if (cValue < 40)
                    {
                        // A - Z
                        result.Append((char)(cValue + 51));
                    }
                    else
                    {
                        throw ReaderException.Instance;
                    }
                }
            }while (bits.available() > 0);
        }
        internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel)
        {
            BitSource bits = new BitSource(bytes);

            System.Text.StringBuilder result = new System.Text.StringBuilder(50);
            CharacterSetECI           currentCharacterSetECI = null;
            bool fc1InEffect = false;

            System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1));
            Mode mode;

            do
            {
                // While still another segment to read...
                if (bits.available() < 4)
                {
                    // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
                    mode = Mode.TERMINATOR;
                }
                else
                {
                    try
                    {
                        mode = Mode.forBits(bits.readBits(4));                         // mode is encoded by 4 bits
                    }
                    catch (System.ArgumentException iae)
                    {
                        throw ReaderException.Instance;
                    }
                }
                if (!mode.Equals(Mode.TERMINATOR))
                {
                    if (mode.Equals(Mode.FNC1_FIRST_POSITION) || mode.Equals(Mode.FNC1_SECOND_POSITION))
                    {
                        // We do little with FNC1 except alter the parsed result a bit according to the spec
                        fc1InEffect = true;
                    }
                    else if (mode.Equals(Mode.STRUCTURED_APPEND))
                    {
                        // not really supported; all we do is ignore it
                        // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
                        bits.readBits(16);
                    }
                    else if (mode.Equals(Mode.ECI))
                    {
                        // Count doesn't apply to ECI
                        int value_Renamed = parseECIValue(bits);
                        currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value_Renamed);
                        if (currentCharacterSetECI == null)
                        {
                            throw ReaderException.Instance;
                        }
                    }
                    else
                    {
                        // How many characters will follow, encoded in this mode?
                        int count = bits.readBits(mode.getCharacterCountBits(version));
                        if (mode.Equals(Mode.NUMERIC))
                        {
                            decodeNumericSegment(bits, result, count);
                        }
                        else if (mode.Equals(Mode.ALPHANUMERIC))
                        {
                            decodeAlphanumericSegment(bits, result, count, fc1InEffect);
                        }
                        else if (mode.Equals(Mode.BYTE))
                        {
                            decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments);
                        }
                        else if (mode.Equals(Mode.KANJI))
                        {
                            decodeKanjiSegment(bits, result, count);
                        }
                        else
                        {
                            throw ReaderException.Instance;
                        }
                    }
                }
            }while (!mode.Equals(Mode.TERMINATOR));

            return(new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, ecLevel));
        }
		/// <summary> See ISO 16022:2006, 5.2.3 and Annex C, Table C.2</summary>
		private static int decodeAsciiSegment(BitSource bits, System.Text.StringBuilder result, System.Text.StringBuilder resultTrailer)
		{
			bool upperShift = false;
			do 
			{
				int oneByte = bits.readBits(8);
				if (oneByte == 0)
				{
					throw ReaderException.Instance;
				}
				else if (oneByte <= 128)
				{
					// ASCII data (ASCII value + 1)
					oneByte = upperShift?(oneByte + 128):oneByte;
					upperShift = false;
					result.Append((char) (oneByte - 1));
					return ASCII_ENCODE;
				}
				else if (oneByte == 129)
				{
					// Pad
					return PAD_ENCODE;
				}
				else if (oneByte <= 229)
				{
					// 2-digit data 00-99 (Numeric Value + 130)
					int value_Renamed = oneByte - 130;
					if (value_Renamed < 10)
					{
						// padd with '0' for single digit values
						result.Append('0');
					}
					result.Append(value_Renamed);
				}
				else if (oneByte == 230)
				{
					// Latch to C40 encodation
					return C40_ENCODE;
				}
				else if (oneByte == 231)
				{
					// Latch to Base 256 encodation
					return BASE256_ENCODE;
				}
				else if (oneByte == 232)
				{
					// FNC1
					//throw ReaderException.getInstance();
					// Ignore this symbol for now
				}
				else if (oneByte == 233)
				{
					// Structured Append
					//throw ReaderException.getInstance();
					// Ignore this symbol for now
				}
				else if (oneByte == 234)
				{
					// Reader Programming
					//throw ReaderException.getInstance();
					// Ignore this symbol for now
				}
				else if (oneByte == 235)
				{
					// Upper Shift (shift to Extended ASCII)
					upperShift = true;
				}
				else if (oneByte == 236)
				{
					// 05 Macro
					result.Append("[)>\u001E05\u001D");
					resultTrailer.Insert(0, "\u001E\u0004");
				}
				else if (oneByte == 237)
				{
					// 06 Macro
					result.Append("[)>\u001E06\u001D");
					resultTrailer.Insert(0, "\u001E\u0004");
				}
				else if (oneByte == 238)
				{
					// Latch to ANSI X12 encodation
					return ANSIX12_ENCODE;
				}
				else if (oneByte == 239)
				{
					// Latch to Text encodation
					return TEXT_ENCODE;
				}
				else if (oneByte == 240)
				{
					// Latch to EDIFACT encodation
					return EDIFACT_ENCODE;
				}
				else if (oneByte == 241)
				{
					// ECI Character
					// TODO(bbrown): I think we need to support ECI
					//throw ReaderException.getInstance();
					// Ignore this symbol for now
				}
				else if (oneByte >= 242)
				{
					// Not to be used in ASCII encodation
					throw ReaderException.Instance;
				}
			}
			while (bits.available() > 0);
			return ASCII_ENCODE;
		}
 private static void decodeByteSegment(BitSource bits, System.Text.StringBuilder result, int count, CharacterSetECI currentCharacterSetECI, System.Collections.ArrayList byteSegments)
 {
     sbyte[] readBytes = new sbyte[count];
     if (count << 3 > bits.available())
     {
         throw ReaderException.Instance;
     }
     for (int i = 0; i < count; i++)
     {
         readBytes[i] = (sbyte) bits.readBits(8);
     }
     System.String encoding;
     if (currentCharacterSetECI == null)
     {
         // The spec isn't clear on this mode; see
         // section 6.4.5: t does not say which encoding to assuming
         // upon decoding. I have seen ISO-8859-1 used as well as
         // Shift_JIS -- without anything like an ECI designator to
         // give a hint.
         encoding = guessEncoding(readBytes);
     }
     else
     {
         encoding = currentCharacterSetECI.EncodingName;
     }
     try
     {
         //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'"
         result.Append(System.Text.Encoding.GetEncoding(encoding).GetString(SupportClass.ToByteArray(readBytes)));
     }
     catch (System.IO.IOException)
     {
         throw ReaderException.Instance;
     }
     byteSegments.Add(SupportClass.ToByteArray(readBytes));
 }
		/// <summary> See ISO 16022:2006, 5.2.6 and Annex C, Table C.2</summary>
		private static void  decodeTextSegment(BitSource bits, System.Text.StringBuilder result)
		{
			// Three Text values are encoded in a 16-bit value as
			// (1600 * C1) + (40 * C2) + C3 + 1
			// TODO(bbrown): The Upper Shift with Text doesn't work in the 4 value scenario all the time
			bool upperShift = false;
			
			int[] cValues = new int[3];
			do 
			{
				// If there is only one byte left then it will be encoded as ASCII
				if (bits.available() == 8)
				{
					return ;
				}
				int firstByte = bits.readBits(8);
				if (firstByte == 254)
				{
					// Unlatch codeword
					return ;
				}
				
				parseTwoBytes(firstByte, bits.readBits(8), cValues);
				
				int shift = 0;
				for (int i = 0; i < 3; i++)
				{
					int cValue = cValues[i];
					switch (shift)
					{
						
						case 0: 
							if (cValue < 3)
							{
								shift = cValue + 1;
							}
							else
							{
								if (upperShift)
								{
									result.Append((char) (TEXT_BASIC_SET_CHARS[cValue] + 128));
									upperShift = false;
								}
								else
								{
									result.Append(TEXT_BASIC_SET_CHARS[cValue]);
								}
							}
							break;
						
						case 1: 
							if (upperShift)
							{
								result.Append((char) (cValue + 128));
								upperShift = false;
							}
							else
							{
								result.Append(cValue);
							}
							shift = 0;
							break;
						
						case 2: 
							// Shift 2 for Text is the same encoding as C40
							if (cValue < 27)
							{
								if (upperShift)
								{
									result.Append((char) (C40_SHIFT2_SET_CHARS[cValue] + 128));
									upperShift = false;
								}
								else
								{
									result.Append(C40_SHIFT2_SET_CHARS[cValue]);
								}
							}
							else if (cValue == 27)
							{
								// FNC1
								throw ReaderException.Instance;
							}
							else if (cValue == 30)
							{
								// Upper Shift
								upperShift = true;
							}
							else
							{
								throw ReaderException.Instance;
							}
							shift = 0;
							break;
						
						case 3: 
							if (upperShift)
							{
								result.Append((char) (TEXT_SHIFT3_SET_CHARS[cValue] + 128));
								upperShift = false;
							}
							else
							{
								result.Append(TEXT_SHIFT3_SET_CHARS[cValue]);
							}
							shift = 0;
							break;
						
						default: 
							throw ReaderException.Instance;
						
					}
				}
			}
			while (bits.available() > 0);
		}
 private static void decodeNumericSegment(BitSource bits, System.Text.StringBuilder result, int count)
 {
     // Read three digits at a time
     while (count >= 3)
     {
         // Each 10 bits encodes three digits
         int threeDigitsBits = bits.readBits(10);
         if (threeDigitsBits >= 1000)
         {
             throw ReaderException.Instance;
         }
         result.Append(ALPHANUMERIC_CHARS[threeDigitsBits / 100]);
         result.Append(ALPHANUMERIC_CHARS[(threeDigitsBits / 10) % 10]);
         result.Append(ALPHANUMERIC_CHARS[threeDigitsBits % 10]);
         count -= 3;
     }
     if (count == 2)
     {
         // Two digits left over to read, encoded in 7 bits
         int twoDigitsBits = bits.readBits(7);
         if (twoDigitsBits >= 100)
         {
             throw ReaderException.Instance;
         }
         result.Append(ALPHANUMERIC_CHARS[twoDigitsBits / 10]);
         result.Append(ALPHANUMERIC_CHARS[twoDigitsBits % 10]);
     }
     else if (count == 1)
     {
         // One digit left over to read
         int digitBits = bits.readBits(4);
         if (digitBits >= 10)
         {
             throw ReaderException.Instance;
         }
         result.Append(ALPHANUMERIC_CHARS[digitBits]);
     }
 }
		/// <summary> See ISO 16022:2006, 5.2.7</summary>
		private static void  decodeAnsiX12Segment(BitSource bits, System.Text.StringBuilder result)
		{
			// Three ANSI X12 values are encoded in a 16-bit value as
			// (1600 * C1) + (40 * C2) + C3 + 1
			
			int[] cValues = new int[3];
			do 
			{
				// If there is only one byte left then it will be encoded as ASCII
				if (bits.available() == 8)
				{
					return ;
				}
				int firstByte = bits.readBits(8);
				if (firstByte == 254)
				{
					// Unlatch codeword
					return ;
				}
				
				parseTwoBytes(firstByte, bits.readBits(8), cValues);
				
				for (int i = 0; i < 3; i++)
				{
					int cValue = cValues[i];
					if (cValue == 0)
					{
						// X12 segment terminator <CR>
						result.Append('\r');
					}
					else if (cValue == 1)
					{
						// X12 segment separator *
						result.Append('*');
					}
					else if (cValue == 2)
					{
						// X12 sub-element separator >
						result.Append('>');
					}
					else if (cValue == 3)
					{
						// space
						result.Append(' ');
					}
					else if (cValue < 14)
					{
						// 0 - 9
						result.Append((char) (cValue + 44));
					}
					else if (cValue < 40)
					{
						// A - Z
						result.Append((char) (cValue + 51));
					}
					else
					{
						throw ReaderException.Instance;
					}
				}
			}
			while (bits.available() > 0);
		}
        internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel)
        {
            BitSource bits = new BitSource(bytes);
            System.Text.StringBuilder result = new System.Text.StringBuilder(50);
            CharacterSetECI currentCharacterSetECI = null;
            bool fc1InEffect = false;
            System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1));
            Mode mode;
            do
            {
                // While still another segment to read...
                if (bits.available() < 4)
                {
                    // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
                    mode = Mode.TERMINATOR;
                }
                else
                {
                    try
                    {
                        mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
                    }
                    catch (System.ArgumentException)
                    {
                        throw ReaderException.Instance;
                    }
                }
                if (!mode.Equals(Mode.TERMINATOR))
                {
                    if (mode.Equals(Mode.FNC1_FIRST_POSITION) || mode.Equals(Mode.FNC1_SECOND_POSITION))
                    {
                        // We do little with FNC1 except alter the parsed result a bit according to the spec
                        fc1InEffect = true;
                    }
                    else if (mode.Equals(Mode.STRUCTURED_APPEND))
                    {
                        // not really supported; all we do is ignore it
                        // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
                        bits.readBits(16);
                    }
                    else if (mode.Equals(Mode.ECI))
                    {
                        // Count doesn't apply to ECI
                        int value_Renamed = parseECIValue(bits);
                        currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value_Renamed);
                        if (currentCharacterSetECI == null)
                        {
                            throw ReaderException.Instance;
                        }
                    }
                    else
                    {
                        // How many characters will follow, encoded in this mode?
                        int count = bits.readBits(mode.getCharacterCountBits(version));
                        if (mode.Equals(Mode.NUMERIC))
                        {
                            decodeNumericSegment(bits, result, count);
                        }
                        else if (mode.Equals(Mode.ALPHANUMERIC))
                        {
                            decodeAlphanumericSegment(bits, result, count, fc1InEffect);
                        }
                        else if (mode.Equals(Mode.BYTE))
                        {
                            decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments);
                        }
                        else if (mode.Equals(Mode.KANJI))
                        {
                            decodeKanjiSegment(bits, result, count);
                        }
                        else
                        {
                            throw ReaderException.Instance;
                        }
                    }
                }
            }
            while (!mode.Equals(Mode.TERMINATOR));

            return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0)?null:byteSegments, ecLevel);
        }
Exemplo n.º 29
0
        /// <summary>
        /// 
        /// ISO/IEC 18004:2006(E) 
        /// Table 2 ¡ª Mode indicators for QR Code 2005 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="version"></param>
        /// <param name="ecLevel"></param>
        /// <returns></returns>
        internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel)
        {
            BitSource bits = new BitSource(bytes);
            System.Text.StringBuilder result = new System.Text.StringBuilder(50);
            CharacterSetECI currentCharacterSetECI = null;
            bool fc1InEffect = false;
            System.Collections.ArrayList byteSegments = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(1));
            Mode mode = Mode.TERMINATOR;
            int bitLen = Mode.NUMERIC.getBitsLength(version.VersionNumber);

            if (version.VersionNumber > 1)
            {
                try
                {
                    mode = Mode.forBits(bits.readBits(bitLen));
                }
                catch (System.ArgumentException iae)
                {
                    throw ReaderException.Instance;
                }
            }
            else
                mode = Mode.NUMERIC;

            if (!mode.Equals(Mode.TERMINATOR))
            {
                // How many characters will follow, encoded in this mode?
                int count = bits.readBits(mode.getCharacterCountBits(version));
                if (mode.Equals(Mode.NUMERIC))
                {
                    decodeNumericSegment(bits, result, count);
                }
                else if (mode.Equals(Mode.ALPHANUMERIC))
                {
                    decodeAlphanumericSegment(bits, result, count, fc1InEffect);
                }
                else if (mode.Equals(Mode.BYTE))
                {
                    decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments);
                }
                else if (mode.Equals(Mode.KANJI))
                {
                    decodeKanjiSegment(bits, result, count);
                }
                else
                {
                    throw ReaderException.Instance;
                }
            }

            return new DecoderResult(bytes, result.ToString(), (byteSegments.Count == 0) ? null : byteSegments, ecLevel);
        }