/* * Copyright 2016 Huy Cuong Nguyen * Copyright 2016 ZXing authors */ // SPDX-License-Identifier: Apache-2.0 #pragma once #include "GTIN.h" #include #include #include #include namespace ZXing::OneD::UPCEANCommon { using Digit = std::array; /** * Start/end guard pattern. */ extern const std::array START_END_PATTERN; /** * "Odd", or "L" patterns used to encode UPC/EAN digits. */ extern const std::array L_PATTERNS; /** * Pattern marking the middle of a UPC/EAN pattern, separating the two halves. */ extern const std::array MIDDLE_PATTERN; /** * As above but also including the "even", or "G" patterns used to encode UPC/EAN digits. */ extern const std::array L_AND_G_PATTERNS; /** * UPCE end guard pattern (== MIDDLE_PATTERN + single module black bar) */ extern const std::array UPCE_END_PATTERN; /** * See {@link #L_AND_G_PATTERNS}; these values similarly represent patterns of * even-odd parity encodings of digits that imply both the number system (0 or 1) * used (index / 10), and the check digit (index % 10). */ extern const std::array NUMSYS_AND_CHECK_DIGIT_PATTERNS; template std::array DigitString2IntArray(const std::basic_string& in, int checkDigit = -1) { static_assert(N == 8 || N == 13, "invalid UPC/EAN length"); if (in.size() != N && in.size() != N - 1) throw std::invalid_argument("Invalid input string length"); std::array out = {}; for (size_t i = 0; i < in.size(); ++i) { out[i] = in[i] - '0'; if (out[i] < 0 || out[i] > 9) throw std::invalid_argument("Contents must contain only digits: 0-9"); } if (checkDigit == -1) checkDigit = GTIN::ComputeCheckDigit(in, N == in.size()); if (in.size() == N - 1) out.back() = checkDigit - '0'; else if (in.back() != checkDigit) throw std::invalid_argument("Checksum error"); return out; } /** * Expands a UPC-E value back into its full, equivalent UPC-A code value. * * @param upce UPC-E code as string of digits * @return equivalent UPC-A code as string of digits */ template StringT ConvertUPCEtoUPCA(const StringT& upce) { if (upce.length() < 7) return upce; auto upceChars = upce.substr(1, 6); StringT result; result.reserve(12); result += upce[0]; auto lastChar = upceChars[5]; switch (lastChar) { case '0': case '1': case '2': result += upceChars.substr(0, 2); result += lastChar; result += StringT(4, '0'); result += upceChars.substr(2, 3); break; case '3': result += upceChars.substr(0, 3); result += StringT(5, '0'); result += upceChars.substr(3, 2); break; case '4': result += upceChars.substr(0, 4); result += StringT(5, '0'); ; result += upceChars[4]; break; default: result += upceChars.substr(0, 5); result += StringT(4, '0'); result += lastChar; break; } // Only append check digit in conversion if supplied if (upce.length() >= 8) { result += upce[7]; } return result; } } // namespace ZXing::OneD::UPCEANCommon