CBC_CommonDecoderResult* CBC_DecodedBitStreamPaser::decode(
    CFX_Int32Array& codewords,
    CFX_ByteString ecLevel,
    int32_t& e) {
  CFX_ByteString result;
  int32_t codeIndex = 1;
  int32_t code = codewords.GetAt(codeIndex);
  codeIndex++;
  CBC_PDF417ResultMetadata* resultMetadata = new CBC_PDF417ResultMetadata;
  while (codeIndex < codewords[0]) {
    switch (code) {
      case TEXT_COMPACTION_MODE_LATCH:
        codeIndex = textCompaction(codewords, codeIndex, result);
        break;
      case BYTE_COMPACTION_MODE_LATCH:
        codeIndex = byteCompaction(code, codewords, codeIndex, result);
        break;
      case NUMERIC_COMPACTION_MODE_LATCH:
        codeIndex = numericCompaction(codewords, codeIndex, result, e);
        BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
        break;
      case MODE_SHIFT_TO_BYTE_COMPACTION_MODE:
        codeIndex = byteCompaction(code, codewords, codeIndex, result);
        break;
      case BYTE_COMPACTION_MODE_LATCH_6:
        codeIndex = byteCompaction(code, codewords, codeIndex, result);
        break;
      case BEGIN_MACRO_PDF417_CONTROL_BLOCK:
        codeIndex = decodeMacroBlock(codewords, codeIndex, resultMetadata, e);
        if (e != BCExceptionNO) {
          delete resultMetadata;
          return NULL;
        }
        break;
      default:
        codeIndex--;
        codeIndex = textCompaction(codewords, codeIndex, result);
        break;
    }
    if (codeIndex < codewords.GetSize()) {
      code = codewords[codeIndex++];
    } else {
      e = BCExceptionFormatInstance;
      delete resultMetadata;
      return NULL;
    }
  }
  if (result.GetLength() == 0) {
    e = BCExceptionFormatInstance;
    delete resultMetadata;
    return NULL;
  }
  CFX_ByteArray rawBytes;
  CFX_PtrArray byteSegments;
  CBC_CommonDecoderResult* tempCd = new CBC_CommonDecoderResult();
  tempCd->Init(rawBytes, result, byteSegments, ecLevel, e);
  if (e != BCExceptionNO) {
    delete resultMetadata;
    return NULL;
  }
  tempCd->setOther(resultMetadata);
  return tempCd;
}