internal static System.String decode(sbyte[] bytes, Version version)
        {
            BitSource bits = new BitSource(bytes);
            System.Text.StringBuilder result = new System.Text.StringBuilder();
            Mode mode;
            do
            {
                // While still another segment to read...
                mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
                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);
                    }
                    else if (mode.Equals(Mode.BYTE))
                    {
                        decodeByteSegment(bits, result, count);
                    }
                    else if (mode.Equals(Mode.KANJI))
                    {
                        decodeKanjiSegment(bits, result, count);
                    }
                    else
                    {
                        throw new ReaderException("Unsupported mode indicator");
                    }
                }
            }
            while (!mode.Equals(Mode.TERMINATOR));

            // I thought it wasn't allowed to leave extra bytes after the terminator but it happens
            /*
            int bitsLeft = bits.available();
            if (bitsLeft > 0) {
            if (bitsLeft > 6 || bits.readBits(bitsLeft) != 0) {
            throw new ReaderException("Excess bits or non-zero bits after terminator mode indicator");
            }
            }
            */
            return result.ToString();
        }
 /**
    * See ISO 16022:2006, 5.2.9 and Annex B, B.2
    */
 private static void decodeBase256Segment(BitSource bits, 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);
     }
     byte[] bytes = new byte[count];
     for (int i = 0; i < count; i++) {
       bytes[i] = unrandomize255State(bits.readBits(8), i);
     }
     byteSegments.Add(bytes);
     try {
         result.Append(System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytes));
     } catch (Exception uee) {
       throw new Exception("Platform does not support required encoding: " + uee);
     }
 }
 /**
    * See ISO 16022:2006, 5.2.3 and Annex C, Table C.2
    */
 private static int decodeAsciiSegment(BitSource bits, StringBuilder result, StringBuilder resultTrailer)
 {
     bool upperShift = false;
     do {
       int oneByte = bits.readBits(8);
       if (oneByte == 0) {
             throw new ReaderException();
         } 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 = oneByte - 130;
           if (value < 10) { // padd with '0' for single digit values
             result.Append('0');
           }
             result.Append(value);
         } 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 new ReaderException();
         } else if (oneByte == 233) {  // Structured Append
             throw new ReaderException();
         } else if (oneByte == 234) {  // Reader Programming
             throw new ReaderException();
         } 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 new ReaderException();
         } else if (oneByte >= 242) {  // Not to be used in ASCII encodation
             throw new ReaderException();
         }
     } while (bits.available() > 0);
     return ASCII_ENCODE;
 }
        /**
           * See ISO 16022:2006, 5.2.7
           */
        private static void decodeAnsiX12Segment(BitSource bits, 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 new ReaderException();
                }
              }
            } while (bits.available() > 0);
        }
 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
     {
         byte[] bytes = SupportClass.ToByteArray(buffer);
         //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(bytes, 0, bytes.Length));
     }
     catch (System.IO.IOException uee)
     {
         throw new ReaderException("SHIFT_JIS encoding is not supported on this device");
     }
 }
 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 new ReaderException("Illegal value for 3-digit unit: " + threeDigitsBits);
         }
         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 new ReaderException("Illegal value for 2-digit unit: " + twoDigitsBits);
         }
         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 new ReaderException("Illegal value for digit unit: " + digitBits);
         }
         result.Append(ALPHANUMERIC_CHARS[digitBits]);
     }
 }
 private static void decodeAlphanumericSegment(BitSource bits, System.Text.StringBuilder result, int count)
 {
     // Read two characters at a time
     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)]);
     }
 }
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private static void decodeByteSegment(com.google.zxing.common.BitSource bits, StringBuilder result, int count, com.google.zxing.common.CharacterSetECI currentCharacterSetECI, java.util.Collection<byte[]> byteSegments, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.FormatException
        private static void decodeByteSegment(BitSource bits, StringBuilder result, int count, CharacterSetECI currentCharacterSetECI, ICollection<sbyte[]> byteSegments, IDictionary<DecodeHintType, object> hints)
        {
            // Don't crash trying to read more bits than we have available.
            if (count << 3 > bits.available())
            {
              throw FormatException.FormatInstance;
            }

            sbyte[] readBytes = new sbyte[count];
            for (int i = 0; i < count; i++)
            {
              readBytes[i] = (sbyte) bits.readBits(8);
            }
            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 = StringUtils.guessEncoding(readBytes, hints);
            }
            else
            {
              encoding = currentCharacterSetECI.name();
            }
            try
            {
              //result.Append(new string(readBytes, encoding));
            result.Append(GetEncodedStringFromBuffer(readBytes, encoding));
            }
            catch (System.IO.IOException)
            {
              throw FormatException.FormatInstance;
            }
            byteSegments.Add(readBytes);
        }
 //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
 //ORIGINAL LINE: private static int parseECIValue(com.google.zxing.common.BitSource bits) throws com.google.zxing.FormatException
 private static int parseECIValue(BitSource bits)
 {
     int firstByte = bits.readBits(8);
     if ((firstByte & 0x80) == 0)
     {
       // just one byte
       return firstByte & 0x7F;
     }
     if ((firstByte & 0xC0) == 0x80)
     {
       // two bytes
       int secondByte = bits.readBits(8);
       return ((firstByte & 0x3F) << 8) | secondByte;
     }
     if ((firstByte & 0xE0) == 0xC0)
     {
       // three bytes
       int secondThirdBytes = bits.readBits(16);
       return ((firstByte & 0x1F) << 16) | secondThirdBytes;
     }
     throw FormatException.FormatInstance;
 }
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: static com.google.zxing.common.DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.FormatException
        internal static DecoderResult decode(sbyte[] bytes, Version version, ErrorCorrectionLevel ecLevel, IDictionary<DecodeHintType, object> hints)
        {
            BitSource bits = new BitSource(bytes);
            StringBuilder result = new StringBuilder(50);
            IList<sbyte[]> byteSegments = new List<sbyte[]>(1);
            try
            {
              CharacterSetECI currentCharacterSetECI = null;
              bool fc1InEffect = false;
              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
            {
              mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
            }
            if (mode != Mode.TERMINATOR)
            {
              if (mode == Mode.FNC1_FIRST_POSITION || mode == 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 == Mode.STRUCTURED_APPEND)
              {
                if (bits.available() < 16)
                {
                  throw FormatException.FormatInstance;
                }
                // 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 == Mode.ECI)
              {
                // Count doesn't apply to ECI
                int value = parseECIValue(bits);
                currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
                if (currentCharacterSetECI == null)
                {
                  throw FormatException.FormatInstance;
                }
              }
              else
              {
                // First handle Hanzi mode which does not start with character count
                if (mode == Mode.HANZI)
                {
                  //chinese mode contains a sub set indicator right after mode indicator
                  int subset = bits.readBits(4);
                  int countHanzi = bits.readBits(mode.getCharacterCountBits(version));
                  if (subset == GB2312_SUBSET)
                  {
                    decodeHanziSegment(bits, result, countHanzi);
                  }
                }
                else
                {
                  // "Normal" QR code modes:
                  // How many characters will follow, encoded in this mode?
                  int count = bits.readBits(mode.getCharacterCountBits(version));
                  if (mode == Mode.NUMERIC)
                  {
                    decodeNumericSegment(bits, result, count);
                  }
                  else if (mode == Mode.ALPHANUMERIC)
                  {
                    decodeAlphanumericSegment(bits, result, count, fc1InEffect);
                  }
                  else if (mode == Mode.BYTE)
                  {
                    decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
                  }
                  else if (mode == Mode.KANJI)
                  {
                    decodeKanjiSegment(bits, result, count);
                  }
                  else
                  {
                    throw FormatException.FormatInstance;
                  }
                }
              }
            }
              } while (mode != Mode.TERMINATOR);
            }
            catch (System.ArgumentException iae)
            {
              // from readBits() calls
              throw FormatException.FormatInstance;
            }

            return new DecoderResult(bytes, result.ToString(), byteSegments.Count == 0 ? null : byteSegments, ecLevel == null ? null : ecLevel.ToString());
        }
 //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
 //ORIGINAL LINE: private static void decodeNumericSegment(com.google.zxing.common.BitSource bits, StringBuilder result, int count) throws com.google.zxing.FormatException
 private static void decodeNumericSegment(BitSource bits, StringBuilder result, int count)
 {
     // Read three digits at a time
     while (count >= 3)
     {
       // Each 10 bits encodes three digits
       if (bits.available() < 10)
       {
     throw FormatException.FormatInstance;
       }
       int threeDigitsBits = bits.readBits(10);
       if (threeDigitsBits >= 1000)
       {
     throw FormatException.FormatInstance;
       }
       result.Append(toAlphaNumericChar(threeDigitsBits / 100));
       result.Append(toAlphaNumericChar((threeDigitsBits / 10) % 10));
       result.Append(toAlphaNumericChar(threeDigitsBits % 10));
       count -= 3;
     }
     if (count == 2)
     {
       // Two digits left over to read, encoded in 7 bits
       if (bits.available() < 7)
       {
     throw FormatException.FormatInstance;
       }
       int twoDigitsBits = bits.readBits(7);
       if (twoDigitsBits >= 100)
       {
     throw FormatException.FormatInstance;
       }
       result.Append(toAlphaNumericChar(twoDigitsBits / 10));
       result.Append(toAlphaNumericChar(twoDigitsBits % 10));
     }
     else if (count == 1)
     {
       // One digit left over to read
       if (bits.available() < 4)
       {
     throw FormatException.FormatInstance;
       }
       int digitBits = bits.readBits(4);
       if (digitBits >= 10)
       {
     throw FormatException.FormatInstance;
       }
       result.Append(toAlphaNumericChar(digitBits));
     }
 }
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private static void decodeKanjiSegment(com.google.zxing.common.BitSource bits, StringBuilder result, int count) throws com.google.zxing.FormatException
        private static void decodeKanjiSegment(BitSource bits, StringBuilder result, int count)
        {
            // Don't crash trying to read more bits than we have available.
            if (count * 13 > bits.available())
            {
              throw FormatException.FormatInstance;
            }

            // 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
            {
              //result.Append(new string(buffer, StringUtils.SHIFT_JIS));
            result.Append(GetEncodedStringFromBuffer(buffer, StringUtils.SHIFT_JIS));
            }
            catch (System.IO.IOException)
            {
              throw FormatException.FormatInstance;
            }
        }
        /// <summary>
        /// See specification GBT 18284-2000
        /// </summary>
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private static void decodeHanziSegment(com.google.zxing.common.BitSource bits, StringBuilder result, int count) throws com.google.zxing.FormatException
        private static void decodeHanziSegment(BitSource bits, StringBuilder result, int count)
        {
            // Don't crash trying to read more bits than we have available.
            if (count * 13 > bits.available())
            {
              throw FormatException.FormatInstance;
            }

            // Each character will require 2 bytes. Read the characters as 2-byte pairs
            // and decode as GB2312 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 / 0x060) << 8) | (twoBytes % 0x060);
              if (assembledTwoBytes < 0x003BF)
              {
            // In the 0xA1A1 to 0xAAFE range
            assembledTwoBytes += 0x0A1A1;
              }
              else
              {
            // In the 0xB0A1 to 0xFAFE range
            assembledTwoBytes += 0x0A6A1;
              }
              buffer[offset] = (sbyte)((assembledTwoBytes >> 8) & 0xFF);
              buffer[offset + 1] = (sbyte)(assembledTwoBytes & 0xFF);
              offset += 2;
              count--;
            }

            try
            {

              //result.Append(new string(buffer,  StringUtils.GB2312));
              result.Append(GetEncodedStringFromBuffer(buffer, StringUtils.GB2312));
            }
            catch (System.IO.IOException)
            {
              throw FormatException.FormatInstance;
            }
        }
        /**
           * See ISO 16022:2006, 5.2.8 and Annex C Table C.3
           */
        private static void decodeEdifactSegment(BitSource bits, 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 decodeByteSegment(BitSource bits, System.Text.StringBuilder result, int count)
 {
     sbyte[] readBytes = new sbyte[count];
     if (count << 3 > bits.available())
     {
         throw new ReaderException("Count too large: " + count);
     }
     for (int i = 0; i < count; i++)
     {
         readBytes[i] = (sbyte)bits.readBits(8);
     }
     // 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.
     System.String encoding = guessEncoding(readBytes);
     try
     {
         byte[] bytes = SupportClass.ToByteArray(readBytes);
         //System.Windows.Forms.MessageBox.Show("encodings: "+ System.Text.Encoding.());
         //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(bytes, 0, bytes.Length));
     }
     catch (System.IO.IOException uce)
     {
         //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 ReaderException(uce.ToString());
     }
 }
        /**
           * See ISO 16022:2006, 5.2.6 and Annex C, Table C.2
           */
        private static void decodeTextSegment(BitSource bits, 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 new ReaderException();
                    } else if (cValue == 30) {  // Upper Shift
                      upperShift = true;
                    } else {
                      throw new ReaderException();
                    }
                    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 new ReaderException();
                }
              }
            } while (bits.available() > 0);
        }
 //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
 //ORIGINAL LINE: private static void decodeAlphanumericSegment(com.google.zxing.common.BitSource bits, StringBuilder result, int count, boolean fc1InEffect) throws com.google.zxing.FormatException
 private static void decodeAlphanumericSegment(BitSource bits, StringBuilder result, int count, bool fc1InEffect)
 {
     // Read two characters at a time
     int start = result.Length;
     while (count > 1)
     {
       if (bits.available() < 11)
       {
     throw FormatException.FormatInstance;
       }
       int nextTwoCharsBits = bits.readBits(11);
       result.Append(toAlphaNumericChar(nextTwoCharsBits / 45));
       result.Append(toAlphaNumericChar(nextTwoCharsBits % 45));
       count -= 2;
     }
     if (count == 1)
     {
       // special case: one character left
       if (bits.available() < 6)
       {
     throw FormatException.FormatInstance;
       }
       result.Append(toAlphaNumericChar(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;
       }
     }
       }
     }
 }