CFX_ByteString CBC_DetectionResult::toString() {
  CBC_DetectionResultColumn* rowIndicatorColumn =
      (CBC_DetectionResultColumn*)m_detectionResultColumns[0];
  if (rowIndicatorColumn == NULL) {
    rowIndicatorColumn = (CBC_DetectionResultColumn*)
        m_detectionResultColumns[m_barcodeColumnCount + 1];
  }
  CFX_ByteString result;
  for (int32_t codewordsRow = 0;
       codewordsRow < rowIndicatorColumn->getCodewords()->GetSize();
       codewordsRow++) {
    result += (FX_CHAR)codewordsRow;
    for (int32_t barcodeColumn = 0; barcodeColumn < m_barcodeColumnCount + 2;
         barcodeColumn++) {
      if (m_detectionResultColumns[barcodeColumn] == NULL) {
        result += "    |   ";
        continue;
      }
      CBC_Codeword* codeword =
          (CBC_Codeword*)((CBC_DetectionResultColumn*)
                              m_detectionResultColumns[barcodeColumn])
              ->getCodewords()
              ->GetAt(codewordsRow);
      if (codeword == NULL) {
        result += "    |   ";
        continue;
      }
      result += codeword->getRowNumber();
      result += codeword->getValue();
    }
  }
  return result;
}
CBC_BarcodeMetadata*
CBC_DetectionResultRowIndicatorColumn::getBarcodeMetadata() {
  CFX_PtrArray* codewords = getCodewords();
  CBC_BarcodeValue barcodeColumnCount;
  CBC_BarcodeValue barcodeRowCountUpperPart;
  CBC_BarcodeValue barcodeRowCountLowerPart;
  CBC_BarcodeValue barcodeECLevel;
  for (int32_t i = 0; i < codewords->GetSize(); i++) {
    CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(i);
    if (codeword == NULL) {
      continue;
    }
    codeword->setRowNumberAsRowIndicatorColumn();
    int32_t rowIndicatorValue = codeword->getValue() % 30;
    int32_t codewordRowNumber = codeword->getRowNumber();
    if (!m_isLeft) {
      codewordRowNumber += 2;
    }
    switch (codewordRowNumber % 3) {
      case 0:
        barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1);
        break;
      case 1:
        barcodeECLevel.setValue(rowIndicatorValue / 3);
        barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3);
        break;
      case 2:
        barcodeColumnCount.setValue(rowIndicatorValue + 1);
        break;
    }
  }
  if ((barcodeColumnCount.getValue()->GetSize() == 0) ||
      (barcodeRowCountUpperPart.getValue()->GetSize() == 0) ||
      (barcodeRowCountLowerPart.getValue()->GetSize() == 0) ||
      (barcodeECLevel.getValue()->GetSize() == 0) ||
      barcodeColumnCount.getValue()->GetAt(0) < 1 ||
      barcodeRowCountUpperPart.getValue()->GetAt(0) +
              barcodeRowCountLowerPart.getValue()->GetAt(0) <
          CBC_PDF417Common::MIN_ROWS_IN_BARCODE ||
      barcodeRowCountUpperPart.getValue()->GetAt(0) +
              barcodeRowCountLowerPart.getValue()->GetAt(0) >
          CBC_PDF417Common::MAX_ROWS_IN_BARCODE) {
    return NULL;
  }
  CBC_BarcodeMetadata* barcodeMetadata =
      new CBC_BarcodeMetadata(barcodeColumnCount.getValue()->GetAt(0),
                              barcodeRowCountUpperPart.getValue()->GetAt(0),
                              barcodeRowCountLowerPart.getValue()->GetAt(0),
                              barcodeECLevel.getValue()->GetAt(0));
  removeIncorrectCodewords(codewords, *barcodeMetadata);
  return barcodeMetadata;
}
void CBC_DetectionResultRowIndicatorColumn::removeIncorrectCodewords(
    CFX_PtrArray* codewords,
    CBC_BarcodeMetadata barcodeMetadata) {
  for (int32_t codewordRow = 0; codewordRow < codewords->GetSize();
       codewordRow++) {
    CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordRow);
    if (codeword == NULL) {
      continue;
    }
    int32_t rowIndicatorValue = codeword->getValue() % 30;
    int32_t codewordRowNumber = codeword->getRowNumber();
    if (codewordRowNumber > barcodeMetadata.getRowCount()) {
      codewords->SetAt(codewordRow, NULL);
      continue;
    }
    if (!m_isLeft) {
      codewordRowNumber += 2;
    }
    switch (codewordRowNumber % 3) {
      case 0:
        if (rowIndicatorValue * 3 + 1 !=
            barcodeMetadata.getRowCountUpperPart()) {
          codewords->SetAt(codewordRow, NULL);
        }
        break;
      case 1:
        if (rowIndicatorValue / 3 !=
                barcodeMetadata.getErrorCorrectionLevel() ||
            rowIndicatorValue % 3 != barcodeMetadata.getRowCountLowerPart()) {
          codewords->SetAt(codewordRow, NULL);
        }
        break;
      case 2:
        if (rowIndicatorValue + 1 != barcodeMetadata.getColumnCount()) {
          codewords->SetAt(codewordRow, NULL);
        }
        break;
    }
  }
}