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()