def decode(self, byts, version):
        bits = BitSource(byts)
        result = ''
        ###CharacterSetECI currentCharacterSetECI = None
        fc1InEffect = False
        ###Vector byteSegments = new Vector(1)
        ###Mode mode
        while True:
            # 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
                except IllegalArgumentException as iae:
                    raise ReaderException.getInstance()
            if (not mode.equals(Mode.TERMINATOR)):
                if (mode.equals(Mode.FNC1_FIRST_POSITION) or mode.equals(Mode.FNC1_SECOND_POSITION)):
                    # We do little with FNC1 except alter the parsed result a bit according to the spec
                    fc1InEffect = True
                elif (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)
                elif (mode.equals(Mode.ECI)):
                    # Count doesn't apply to ECI
                    value = parseECIValue(bits)
                    currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value)
                    if (currentCharacterSetECI == None):
                        raise ReaderException.getInstance()
                else:
                    # How many characters will follow, encoded in this mode?
                    count = bits.readBits(mode.getCharacterCountBits(version))
                    if (mode.equals(Mode.NUMERIC)):
                        decodeNumericSegment(bits, result, count)
                    elif (mode.equals(Mode.ALPHANUMERIC)):
                        decodeAlphanumericSegment(bits, result, count, fc1InEffect)
                    elif (mode.equals(Mode.BYTE)):
                        decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments)
                    elif (mode.equals(Mode.KANJI)):
                        decodeKanjiSegment(bits, result, count)
                    else:
                        raise ReaderException.getInstance()
            if (mode.equals(Mode.TERMINATOR)):
                break

        return DecoderResult(byts, str(result), None if byteSegments.isEmpty() else byteSegments)
 def decodeByteSegment(bits, result, count, currentCharacterSetECI,
         byteSegments):
     readBytes = bytearray[count]
     if (count << 3 > bits.available()):
         raise ReaderException.getInstance()
     for i in range(count):
         readBytes[i] = bits.readBits(8)
     if (currentCharacterSetECI == None):
         # 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.getEncodingName()
     try:
         result.append(readBytes.decode(encoding))
     except UnsupportedEncodingException as uce:
         raise ReaderException.getInstance()
     byteSegments.addElement(readBytes)
 def decodeNumericSegment(bits, result, count):
     # Read three digits at a time
     while (count >= 3):
         # Each 10 bits encodes three digits
         threeDigitsBits = bits.readBits(10)
         if (threeDigitsBits >= 1000):
             raise ReaderException.getInstance()
         result.append(ALPHANUMERIC_CHARS[int(threeDigitsBits / 100)])
         result.append(ALPHANUMERIC_CHARS[int(threeDigitsBits / 10) % 10])
         result.append(ALPHANUMERIC_CHARS[threeDigitsBits % 10])
         count -= 3
     if (count == 2):
         # Two digits left over to read, encoded in 7 bits
         twoDigitsBits = bits.readBits(7)
         if (twoDigitsBits >= 100):
             raise ReaderException.getInstance()
         result.append(ALPHANUMERIC_CHARS[int(twoDigitsBits / 10)])
         result.append(ALPHANUMERIC_CHARS[twoDigitsBits % 10])
     elif (count == 1):
         # One digit left over to read
         digitBits = bits.readBits(4)
         if (digitBits >= 10):
             raise ReaderException.getInstance()
         result.append(ALPHANUMERIC_CHARS[digitBits])
 def decodeKanjiSegment(bits, result, count):
     # Each character will require 2 bytes. Read the characters as 2-byte pairs
     # and decode as Shift_JIS afterwards
     buffer = bytearray(2 * count)
     offset = 0
     while (count > 0):
         # Each 13 bits encodes a 2-byte character
         twoBytes = bits.readBits(13)
         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] = (assembledTwoBytes >> 8)
         buffer[offset + 1] = assembledTwoBytes
         offset += 2
         count-=1
     # Shift_JIS may not be supported in some environments:
     try:
         result.append(buffer.decode(SHIFT_JIS))
     except UnsupportedEncodingException as uee:
         raise ReaderException.getInstance()