ITF-14/EAN-14/NVE-18: allow check digit to be given and then

verified;
  allow and ignore prefixes "01", "[01]" and "(01)" (or "00" etc
  if NVE-18) if check digit given, following commit [789e04]
  (ticket #333)
This commit is contained in:
gitlost 2025-04-07 17:25:44 +01:00
parent d886ecf5c7
commit 86363ff0f7
7 changed files with 211 additions and 84 deletions

View file

@ -43,9 +43,20 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[]
INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, error_number, zeroes;
unsigned char local_source[14];
unsigned char have_check_digit = '\0';
unsigned char check_digit;
if (length > 13) {
return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 311, "Input length %d too long (maximum 13)", length);
/* Allow and ignore any AI prefix, but only if have check digit */
if (length == 18 && (memcmp(source, "[01]", 4) == 0 || memcmp(source, "(01)", 4) == 0)) {
source += 4;
length -= 4;
/* Likewise initial '01', if have check digit */
} else if (length == 16 && source[0] == '0' && source[1] == '1') {
source += 2;
length -= 2;
}
if (length > 14) {
return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 311, "Input length %d too long (maximum 14)", length);
}
if ((i = not_sane(NEON_F, source, length))) {
@ -53,6 +64,11 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt
"Invalid character at position %d in input (digits only)", i);
}
if (length == 14) {
have_check_digit = source[13];
length--;
}
/* Add leading zeros as required */
zeroes = 13 - length;
for (i = 0; i < zeroes; i++) {
@ -61,7 +77,12 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt
memcpy(local_source + zeroes, source, length);
/* Calculate the check digit - the same method used for EAN-13 */
local_source[13] = gs1_check_digit(local_source, 13);
check_digit = (unsigned char) gs1_check_digit(local_source, 13);
if (have_check_digit && have_check_digit != check_digit) {
return ZEXT errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 850, "Invalid check digit '%1$c', expecting '%2$c'",
have_check_digit, check_digit);
}
local_source[13] = check_digit;
error_number = c25_inter_common(symbol, local_source, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/);
if (error_number < ZINT_ERROR) {

View file

@ -42,32 +42,53 @@
INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int length);
/* Helper to do NVE18 or EAN14 */
static int nve18_or_ean14(struct zint_symbol *symbol, unsigned char source[], const int length, const int data_len) {
static int nve18_or_ean14(struct zint_symbol *symbol, const unsigned char source[], int length, const int data_len) {
static const char prefix[2][2][5] = {
{ "(01)", "[01]" }, /* EAN14 */
{ "(00)", "[00]" }, /* NVE18 */
};
const int idx = data_len == 17;
unsigned char ean128_equiv[23];
int i, zeroes;
unsigned char have_check_digit = '\0';
unsigned char check_digit;
int error_number;
if (length > data_len) {
return ZEXT errtxtf(ZINT_ERROR_TOO_LONG, symbol, 345, "Input length %1$d too long (maximum %2$d)", length,
data_len);
/* Allow and ignore any AI prefix, but only if have check digit */
if (length == data_len + 1 + 4
&& (memcmp(source, prefix[idx][0], 4) == 0 || memcmp(source, prefix[idx][1], 4) == 0)) {
source += 4;
length -= 4;
/* Likewise initial '01' (EAN-14) or '00' (NVE-18), if have check digit */
} else if (length == data_len + 1 + 2 && source[0] == prefix[idx][0][1] && source[1] == prefix[idx][0][2]) {
source += 2;
length -= 2;
}
if (length > data_len + 1) {
return ZEXT errtxtf(ZINT_ERROR_TOO_LONG, symbol, 345, "Input length %1$d too long (maximum %2$d)",
length, data_len + 1);
}
if ((i = not_sane(NEON_F, source, length))) {
/* Note: for all "at position" error messages, escape sequences not accounted for */
return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 346,
"Invalid character at position %d in input (digits only)", i);
}
if (length == data_len + 1) {
have_check_digit = source[data_len];
length--;
}
zeroes = data_len - length;
memcpy(ean128_equiv, prefix[data_len == 17][!(symbol->input_mode & GS1PARENS_MODE)], 4);
memcpy(ean128_equiv, prefix[idx][!(symbol->input_mode & GS1PARENS_MODE)], 4);
memset(ean128_equiv + 4, '0', zeroes);
memcpy(ean128_equiv + 4 + zeroes, source, length);
ean128_equiv[data_len + 4] = gs1_check_digit(ean128_equiv + 4, data_len);
check_digit = (unsigned char) gs1_check_digit(ean128_equiv + 4, data_len);
if (have_check_digit && have_check_digit != check_digit) {
return ZEXT errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 347, "Invalid check digit '%1$c', expecting '%2$c'",
have_check_digit, check_digit);
}
ean128_equiv[data_len + 4] = check_digit;
ean128_equiv[data_len + 5] = '\0'; /* Terminating NUL required by `c128_cost()` */
error_number = gs1_128(symbol, ean128_equiv, data_len + 5);

View file

@ -70,8 +70,8 @@ static void test_large(const testCtx *const p_ctx) {
/* 21*/ { BARCODE_DPLEIT, -1, "1", 14, ZINT_ERROR_TOO_LONG, -1, -1, "Error 313: Input length 14 too long (maximum 13)" },
/* 22*/ { BARCODE_DPIDENT, -1, "1", 11, 0, 1, 117, "" },
/* 23*/ { BARCODE_DPIDENT, -1, "1", 12, ZINT_ERROR_TOO_LONG, -1, -1, "Error 315: Input length 12 too long (maximum 11)" },
/* 24*/ { BARCODE_ITF14, -1, "1", 13, 0, 1, 135, "" },
/* 25*/ { BARCODE_ITF14, -1, "1", 14, ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 14 too long (maximum 13)" },
/* 24*/ { BARCODE_ITF14, -1, "0", 14, 0, 1, 135, "" },
/* 25*/ { BARCODE_ITF14, -1, "0", 15, ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 15 too long (maximum 14)" },
};
const int data_size = ARRAY_SIZE(data);
int i, length, ret;
@ -89,18 +89,26 @@ static void test_large(const testCtx *const p_ctx) {
assert_nonnull(symbol, "Symbol not created\n");
testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length);
assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf));
assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n",
i, data[i].length, (int) strlen(data_buf));
length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug);
length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/,
-1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/,
data_buf, data[i].length, debug);
ret = ZBarcode_Encode(symbol, TCU(data_buf), length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n", i, ret ? "set" : "empty", symbol->errtxt);
assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n",
i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n",
i, ret ? "set" : "empty", symbol->errtxt);
assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n",
i, symbol->errtxt, data[i].expected_errtxt);
if (ret < ZINT_ERROR) {
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n",
i, symbol->rows, data[i].expected_rows);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n",
i, symbol->width, data[i].expected_width);
}
ZBarcode_Delete(symbol);
@ -242,6 +250,19 @@ static void test_input(const testCtx *const p_ctx) {
/* 8*/ { BARCODE_DPIDENT, -1, "A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 316: Invalid character at position 1 in input (digits only)" },
/* 9*/ { BARCODE_DPIDENT, -1, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 316: Invalid character at position 11 in input (digits only)" },
/* 10*/ { BARCODE_ITF14, -1, "A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 312: Invalid character at position 1 in input (digits only)" },
/* 11*/ { BARCODE_ITF14, -1, "1234567890123", 0, 1, 135, "" },
/* 12*/ { BARCODE_ITF14, -1, "12345678901231", 0, 1, 135, "" },
/* 13*/ { BARCODE_ITF14, -1, "12345678901234", ZINT_ERROR_INVALID_CHECK, -1, -1, "Error 850: Invalid check digit '4', expecting '1'" },
/* 14*/ { BARCODE_ITF14, -1, "1234567890123A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 312: Invalid character at position 14 in input (digits only)" },
/* 15*/ { BARCODE_ITF14, -1, "0112345678901231", 0, 1, 135, "" }, /* Allow '01' prefix if have check digit */
/* 16*/ { BARCODE_ITF14, -1, "011234567890123", ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 15 too long (maximum 14)" }, /* But not without */
/* 17*/ { BARCODE_ITF14, -1, "[01]12345678901231", 0, 1, 135, "" }, /* Allow '[01]' prefix if have check digit */
/* 18*/ { BARCODE_ITF14, -1, "[01]1234567890123", ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 17 too long (maximum 14)" }, /* But not without */
/* 19*/ { BARCODE_ITF14, -1, "(01)12345678901231", 0, 1, 135, "" }, /* Allow '(01)' prefix if have check digit */
/* 20*/ { BARCODE_ITF14, -1, "(01)1234567890123", ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 17 too long (maximum 14)" }, /* But not without */
/* 21*/ { BARCODE_ITF14, -1, "0012345678901231", ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 16 too long (maximum 14)" },
/* 22*/ { BARCODE_ITF14, -1, "[00]12345678901231", ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 18 too long (maximum 14)" },
/* 23*/ { BARCODE_ITF14, -1, "[01)12345678901231", ZINT_ERROR_TOO_LONG, -1, -1, "Error 311: Input length 18 too long (maximum 14)" },
};
const int data_size = ARRAY_SIZE(data);
int i, length, ret;
@ -256,16 +277,23 @@ static void test_input(const testCtx *const p_ctx) {
symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1 /*option_2*/, -1, -1 /*output_options*/, data[i].data, -1, debug);
length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/,
-1 /*option_1*/, -1 /*option_2*/, -1, -1 /*output_options*/,
data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, TCU(data[i].data), length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n", i, ret ? "set" : "empty", symbol->errtxt);
assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n",
i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n",
i, ret ? "set" : "empty", symbol->errtxt);
assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n",
i, symbol->errtxt, data[i].expected_errtxt);
if (ret < ZINT_ERROR) {
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n", i, symbol->rows, data[i].expected_rows);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n", i, symbol->width, data[i].expected_width);
assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d\n",
i, symbol->rows, data[i].expected_rows);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d\n",
i, symbol->width, data[i].expected_width);
}
ZBarcode_Delete(symbol);

View file

@ -87,10 +87,10 @@ static void test_large(const testCtx *const p_ctx) {
/* 32*/ { BARCODE_GS1_128, -1, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]123456789012345678901234567890123456789012345678901234567890123456789012345678901234[93]123", -1, ZINT_ERROR_TOO_LONG, -1, "Error 344: Input too long, requires 104 symbol characters (maximum 102)", 1 }, /* StartC + 194 nos + CodeA + single no. + 3 FNC1s */
/* 33*/ { BARCODE_GS1_128, -1, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345[93]1", -1, ZINT_ERROR_TOO_LONG, -1, "Error 344: Input too long, requires 132 symbol characters (maximum 102)", 1 },
/* 34*/ { BARCODE_GS1_128, -1, -1, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234567890123456789012345678901234567890123456789012345678901234567890[92]12345678901234567890123456789012345678901234567890123456789012345[93]12", -1, ZINT_ERROR_TOO_LONG, -1, "Error 342: Input length 257 too long (maximum 256)", 1 },
/* 35*/ { BARCODE_EAN14, -1, -1, "1234567890123", -1, 0, 134, "", 1 },
/* 36*/ { BARCODE_EAN14, -1, -1, "12345678901234", -1, ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 14 too long (maximum 13)", 1 },
/* 37*/ { BARCODE_NVE18, -1, -1, "12345678901234567", -1, 0, 156, "", 1 },
/* 38*/ { BARCODE_NVE18, -1, -1, "123456789012345678", -1, ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 17)", 1 },
/* 35*/ { BARCODE_EAN14, -1, -1, "12345678901231", -1, 0, 134, "", 1 },
/* 36*/ { BARCODE_EAN14, -1, -1, "123456789012315", -1, ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 15 too long (maximum 14)", 1 },
/* 37*/ { BARCODE_NVE18, -1, -1, "123456789012345675", -1, 0, 156, "", 1 },
/* 38*/ { BARCODE_NVE18, -1, -1, "1234567890123456759", -1, ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 19 too long (maximum 18)", 1 },
/* 39*/ { BARCODE_HIBC_128, -1, -1, "1", 110, 0, 684, "", 1 },
/* 40*/ { BARCODE_HIBC_128, -1, -1, "1", 111, ZINT_ERROR_TOO_LONG, -1, "Error 202: Input length 111 too long for HIBC LIC (maximum 110)", 1 },
};
@ -1018,9 +1018,23 @@ static void test_nve18_input(const testCtx *const p_ctx) {
const char *comment;
};
static const struct item data[] = {
/* 0*/ { -1, "123456789012345678", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 17)", "" },
/* 1*/ { -1, "1234A568901234567", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 5 in input (digits only)", "" },
/* 2*/ { ESCAPE_MODE, "\\d049\\d050\\d051\\d052A568901234567", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 5 in input (digits only)", "Position does not account for escape sequences" },
/* 0*/ { -1, "1234567890123456789", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 19 too long (maximum 18)", "" },
/* 1*/ { -1, "12345678901234567A", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 18 in input (digits only)", "" },
/* 2*/ { -1, "123456789012345678", ZINT_ERROR_INVALID_CHECK, -1, "Error 347: Invalid check digit '8', expecting '5'", "" },
/* 3*/ { -1, "1234A568901234567", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 5 in input (digits only)", "" },
/* 4*/ { ESCAPE_MODE, "\\d049\\d050\\d051\\d052A568901234567", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 5 in input (digits only)", "Position does not account for escape sequences" },
/* 5*/ { -1, "123456789012345675", 0, 156, "(14) 105 102 0 12 34 56 78 90 12 34 56 75 42 106", "" },
/* 6*/ { -1, "12345678901234567", 0, 156, "(14) 105 102 0 12 34 56 78 90 12 34 56 75 42 106", "" },
/* 7*/ { -1, "00123456789012345675", 0, 156, "(14) 105 102 0 12 34 56 78 90 12 34 56 75 42 106", "'00' prefix allowed if check digit" },
/* 8*/ { -1, "0012345678901234567", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 19 too long (maximum 18)", "But not without" },
/* 9*/ { -1, "[00]123456789012345675", 0, 156, "(14) 105 102 0 12 34 56 78 90 12 34 56 75 42 106", "'[00]' prefix allowed if check digit" },
/* 10*/ { -1, "[00]12345678901234567", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 21 too long (maximum 18)", "But not without" },
/* 11*/ { -1, "(00)123456789012345675", 0, 156, "(14) 105 102 0 12 34 56 78 90 12 34 56 75 42 106", "'(00)' prefix allowed if check digit" },
/* 12*/ { -1, "(00)12345678901234567", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 21 too long (maximum 18)", "But not without" },
/* 13*/ { -1, "01123456789012345675", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 20 too long (maximum 18)", "" },
/* 14*/ { -1, "[01]123456789012345675", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 22 too long (maximum 18)", "" },
/* 15*/ { -1, "(01)123456789012345675", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 22 too long (maximum 18)", "" },
/* 16*/ { -1, "(00]123456789012345675", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 22 too long (maximum 18)", "" },
};
const int data_size = ARRAY_SIZE(data);
int i, length, ret;
@ -1044,18 +1058,21 @@ static void test_nve18_input(const testCtx *const p_ctx) {
data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, TCU(data[i].data), length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->errtxt[0] == '\0', ret == 0, "i:%d symbol->errtxt not %s (%s)\n", i, ret ? "set" : "empty", symbol->errtxt);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n",
i, ret, data[i].ret, symbol->errtxt);
if (p_ctx->generate) {
printf(" /*%3d*/ { \"%s\", %s, %d, \"%s\", \"%s\" },\n",
i, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
printf(" /*%3d*/ { %s, \"%s\", %s, %d, \"%s\", \"%s\" },\n",
i, testUtilInputModeName(data[i].input_mode),
testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment);
} else {
assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected);
if (ret < ZINT_ERROR) {
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n",
i, symbol->width, data[i].expected_width, data[i].data);
}
assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n",
i, symbol->errtxt, data[i].expected);
}
ZBarcode_Delete(symbol);
@ -1075,8 +1092,22 @@ static void test_ean14_input(const testCtx *const p_ctx) {
const char *comment;
};
static const struct item data[] = {
/* 0*/ { "12345678901234", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 14 too long (maximum 13)", "" },
/* 1*/ { "123456789012A", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 13 in input (digits only)", "" },
/* 0*/ { "123456789012345", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 15 too long (maximum 14)", "" },
/* 1*/ { "1234567890123A", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 14 in input (digits only)", "" },
/* 2*/ { "12345678901234", ZINT_ERROR_INVALID_CHECK, -1, "Error 347: Invalid check digit '4', expecting '1'", "" },
/* 3*/ { "123456789012A", ZINT_ERROR_INVALID_DATA, -1, "Error 346: Invalid character at position 13 in input (digits only)", "" },
/* 4*/ { "1234567890123", 0, 134, "(12) 105 102 1 12 34 56 78 90 12 31 74 106", "" },
/* 5*/ { "12345678901231", 0, 134, "(12) 105 102 1 12 34 56 78 90 12 31 74 106", "" },
/* 6*/ { "0112345678901231", 0, 134, "(12) 105 102 1 12 34 56 78 90 12 31 74 106", "'01' prefix allowed if check digit" },
/* 7*/ { "011234567890123", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 15 too long (maximum 14)", "But not without" },
/* 8*/ { "[01]12345678901231", 0, 134, "(12) 105 102 1 12 34 56 78 90 12 31 74 106", "'[01]' prefix allowed if check digit" },
/* 9*/ { "[01]1234567890123", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 17 too long (maximum 14)", "But not without" },
/* 10*/ { "(01)12345678901231", 0, 134, "(12) 105 102 1 12 34 56 78 90 12 31 74 106", "'(01)' prefix allowed if check digit" },
/* 11*/ { "(01)1234567890123", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 17 too long (maximum 14)", "But not without" },
/* 12*/ { "0012345678901231", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 16 too long (maximum 14)", "" },
/* 13*/ { "[00]12345678901231", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 14)", "" },
/* 14*/ { "(00)12345678901231", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 14)", "" },
/* 15*/ { "(01]12345678901231", ZINT_ERROR_TOO_LONG, -1, "Error 345: Input length 18 too long (maximum 14)", "" },
};
const int data_size = ARRAY_SIZE(data);
int i, length, ret;
@ -1100,7 +1131,8 @@ static void test_ean14_input(const testCtx *const p_ctx) {
data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, TCU(data[i].data), length);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n",
i, ret, data[i].ret, symbol->errtxt);
if (p_ctx->generate) {
printf(" /*%3d*/ { \"%s\", %s, %d, \"%s\", \"%s\" },\n",
@ -1108,9 +1140,11 @@ static void test_ean14_input(const testCtx *const p_ctx) {
testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment);
} else {
if (ret < ZINT_ERROR) {
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n",
i, symbol->width, data[i].expected_width, data[i].data);
}
assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected);
assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n",
i, symbol->errtxt, data[i].expected);
}
ZBarcode_Delete(symbol);

View file

@ -4472,9 +4472,10 @@ aria-hidden="true"><code>zint -b ITF14 --compliantheight -d "9212320967145"</cod
</figure>
<p>ITF-14, also known as UPC Shipping Container Symbol or Case Code, is
based on Interleaved Code 2 of 5 and is designed to encode a GTIN-14. It
takes a 13-digit numeric input (digits 0-9), which will be prefixed with
leading zeroes if less than 13 digits entered. One modulo-10 check digit
is added by Zint.</p>
takes a 13-digit input, which will be prefixed with leading zeroes if
less than 13 digits entered, or a 14-digit input if the standard GS1
check digit is given, in which case the check digit will be verified. A
standard GS1 check digit is added by Zint unless already given.</p>
<p>If no border option is specified Zint defaults to adding a bounding
box with a border width of 5. This behaviour can be overridden by using
the <code>--bind</code> option (API
@ -5011,9 +5012,12 @@ alt="zint -b EAN14 --compliantheight -d &quot;9889876543210&quot;" />
<figcaption
aria-hidden="true"><code>zint -b EAN14 --compliantheight -d "9889876543210"</code></figcaption>
</figure>
<p>A shorter version of GS1-128 which encodes GTIN data only. A 13-digit
number is required. The GTIN check digit and HRT-only AI
<code>"(01)"</code> are added by Zint.</p>
<p>A shorter version of GS1-128 which encodes GTIN-14 data only, EAN-14
takes a 13-digit input, which will be prefixed with leading zeroes if
less than 13 digits entered, or a 14-digit number if the standard GS1
check digit is given, in which case the check digit will be verified.
The GS1 check digit (if not given) and HRT-only AI <code>"(01)"</code>
are added by Zint.</p>
<h4 id="nve-18-sscc-18">6.1.10.5 NVE-18 (SSCC-18)</h4>
<figure>
<img src="images/nve18.svg" title="fig:" class="lin"
@ -5023,9 +5027,11 @@ aria-hidden="true"><code>zint -b NVE18 --compliantheight -d "37612345000001003"<
</figure>
<p>A variation of Code 128 the Nummer der Versandeinheit standard,
also known as SSCC-18 (Serial Shipping Container Code), includes both a
visible modulo-10 and a hidden modulo-103 check digit. NVE-18 requires a
17-digit numerical input. Check digits and HRT-only AI
<code>"(00)"</code> are added by Zint.</p>
visible standard GS1 check digit and a hidden modulo-103 check digit.
NVE-18 takes a 17-digit input, which will be prefixed with leading zeros
if less than 17 digits given, or an 18-digit input if the GS1 check
digit is included, in which case the check digit will be verified. Check
digit(s) and HRT-only AI <code>"(00)"</code> are added by Zint.</p>
<h4 id="hibc-code-128">6.1.10.6 HIBC Code 128</h4>
<figure>
<img src="images/hibc_128.svg" title="fig:" class="lin"
@ -5129,8 +5135,8 @@ aria-hidden="true"><code>zint -b DBAR_OMN --compliantheight -d "0950110153001"</
<p>Previously known as RSS-14 this standard encodes a 13-digit item
code. A check digit and HRT-only Application Identifier of
<code>"(01)"</code> are added by Zint. (A 14-digit code that appends the
check digit may be given, in which case the check digit will be
verified.)</p>
standard GS1 check digit may be given, in which case the check digit
will be verified.)</p>
<p>GS1 DataBar Omnidirectional symbols should have a height of 33 or
greater. To produce a GS1 DataBar Truncated symbol set the symbol height
to a value between 13 and 32. Truncated symbols may not be scannable by
@ -5171,10 +5177,11 @@ inclusion of parentheses in the data to be encoded. If the data does not
include parentheses, the AIs may alternatively be encased in parentheses
using the <code>--gs1parens</code> switch. See <a
href="#gs1-128">6.1.10.3 GS1-128</a>.</p>
<p>GTIN data AI (01) should also include the check digit data as this is
not calculated by Zint when this symbology is encoded. Fixed length data
should be entered at the appropriate length for correct encoding. The
following is an example of a valid GS1 DataBar Expanded input:</p>
<p>GTIN data AI (01) should also include the standard GS1 check digit
data as this is not calculated by Zint when this symbology is encoded.
Fixed length data should be entered at the appropriate length for
correct encoding. The following is an example of a valid GS1 DataBar
Expanded input:</p>
<div class="sourceCode" id="cb105"><pre
class="sourceCode bash"><code class="sourceCode bash"><span id="cb105-1"><a href="#cb105-1" aria-hidden="true" tabindex="-1"></a><span class="ex">zint</span> <span class="at">-b</span> 31 <span class="at">-d</span> <span class="st">&quot;[01]98898765432106[3202]012345[15]991231&quot;</span></span></code></pre></div>
<h3 id="korea-post-barcode">6.1.12 Korea Post Barcode</h3>

View file

@ -2828,8 +2828,10 @@ same as for [6.1.2.1 Standard Code 2 of 5].
ITF-14, also known as UPC Shipping Container Symbol or Case Code, is based on
Interleaved Code 2 of 5 and is designed to encode a GTIN-14. It takes a 13-digit
numeric input (digits 0-9), which will be prefixed with leading zeroes if less
than 13 digits entered. One modulo-10 check digit is added by Zint.
input, which will be prefixed with leading zeroes if less than 13 digits
entered, or a 14-digit input if the standard GS1 check digit is given, in which
case the check digit will be verified. A standard GS1 check digit is added by
Zint unless already given.
If no border option is specified Zint defaults to adding a bounding box with a
border width of 5. This behaviour can be overridden by using the `--bind` option
@ -3296,8 +3298,13 @@ zint -b 16 --gs1parens -d "(01)98898765432106(3202)012345(15)991231"
![`zint -b EAN14 --compliantheight -d "9889876543210"`](images/ean14.svg){.lin}
A shorter version of GS1-128 which encodes GTIN data only. A 13-digit number is
required. The GTIN check digit and HRT-only AI `"(01)"` are added by Zint.
A shorter version of GS1-128 which encodes GTIN-14 data only, EAN-14 takes a
13-digit input, which will be prefixed with leading zeroes if less than 13
digits entered, or a 14-digit number if the standard GS1 check digit is given,
in which case the check digit will be verified. The GS1 check digit (if not
given) and HRT-only AI `"(01)"` are added by Zint.
\clearpage
#### 6.1.10.5 NVE-18 (SSCC-18)
@ -3305,9 +3312,11 @@ required. The GTIN check digit and HRT-only AI `"(01)"` are added by Zint.
"37612345000001003"`](images/nve18.svg){.lin}
A variation of Code 128 the 'Nummer der Versandeinheit' standard, also known as
SSCC-18 (Serial Shipping Container Code), includes both a visible modulo-10 and
a hidden modulo-103 check digit. NVE-18 requires a 17-digit numerical input.
Check digits and HRT-only AI `"(00)"` are added by Zint.
SSCC-18 (Serial Shipping Container Code), includes both a visible standard GS1
check digit and a hidden modulo-103 check digit. NVE-18 takes a 17-digit input,
which will be prefixed with leading zeros if less than 17 digits given, or an
18-digit input if the GS1 check digit is included, in which case the check digit
will be verified. Check digit(s) and HRT-only AI `"(00)"` are added by Zint.
#### 6.1.10.6 HIBC Code 128
@ -3388,8 +3397,8 @@ GS1 DataBar symbol is to be printed with a 2D component as specified in ISO/IEC
Previously known as RSS-14 this standard encodes a 13-digit item code. A check
digit and HRT-only Application Identifier of `"(01)"` are added by Zint. (A
14-digit code that appends the check digit may be given, in which case the check
digit will be verified.)
14-digit code that appends the standard GS1 check digit may be given, in which
case the check digit will be verified.)
GS1 DataBar Omnidirectional symbols should have a height of 33 or greater. To
produce a GS1 DataBar Truncated symbol set the symbol height to a value between
@ -3423,10 +3432,10 @@ the symbol. This method allows the inclusion of parentheses in the data to be
encoded. If the data does not include parentheses, the AIs may alternatively be
encased in parentheses using the `--gs1parens` switch. See [6.1.10.3 GS1-128].
GTIN data AI (01) should also include the check digit data as this is not
calculated by Zint when this symbology is encoded. Fixed length data should be
entered at the appropriate length for correct encoding. The following is an
example of a valid GS1 DataBar Expanded input:
GTIN data AI (01) should also include the standard GS1 check digit data as this
is not calculated by Zint when this symbology is encoded. Fixed length data
should be entered at the appropriate length for correct encoding. The following
is an example of a valid GS1 DataBar Expanded input:
```bash
zint -b 31 -d "[01]98898765432106[3202]012345[15]991231"

View file

@ -2748,8 +2748,10 @@ same as for 6.1.2.1 Standard Code 2 of 5.
ITF-14, also known as UPC Shipping Container Symbol or Case Code, is based on
Interleaved Code 2 of 5 and is designed to encode a GTIN-14. It takes a 13-digit
numeric input (digits 0-9), which will be prefixed with leading zeroes if less
than 13 digits entered. One modulo-10 check digit is added by Zint.
input, which will be prefixed with leading zeroes if less than 13 digits
entered, or a 14-digit input if the standard GS1 check digit is given, in which
case the check digit will be verified. A standard GS1 check digit is added by
Zint unless already given.
If no border option is specified Zint defaults to adding a bounding box with a
border width of 5. This behaviour can be overridden by using the --bind option
@ -3162,17 +3164,22 @@ or using the --gs1parens option:
[zint -b EAN14 --compliantheight -d "9889876543210"]
A shorter version of GS1-128 which encodes GTIN data only. A 13-digit number is
required. The GTIN check digit and HRT-only AI "(01)" are added by Zint.
A shorter version of GS1-128 which encodes GTIN-14 data only, EAN-14 takes a
13-digit input, which will be prefixed with leading zeroes if less than 13
digits entered, or a 14-digit number if the standard GS1 check digit is given,
in which case the check digit will be verified. The GS1 check digit (if not
given) and HRT-only AI "(01)" are added by Zint.
6.1.10.5 NVE-18 (SSCC-18)
[zint -b NVE18 --compliantheight -d "37612345000001003"]
A variation of Code 128 the Nummer der Versandeinheit standard, also known as
SSCC-18 (Serial Shipping Container Code), includes both a visible modulo-10 and
a hidden modulo-103 check digit. NVE-18 requires a 17-digit numerical input.
Check digits and HRT-only AI "(00)" are added by Zint.
SSCC-18 (Serial Shipping Container Code), includes both a visible standard GS1
check digit and a hidden modulo-103 check digit. NVE-18 takes a 17-digit input,
which will be prefixed with leading zeros if less than 17 digits given, or an
18-digit input if the GS1 check digit is included, in which case the check digit
will be verified. Check digit(s) and HRT-only AI "(00)" are added by Zint.
6.1.10.6 HIBC Code 128
@ -3248,8 +3255,8 @@ to find out how to generate DataBar symbols with 2D components.
Previously known as RSS-14 this standard encodes a 13-digit item code. A check
digit and HRT-only Application Identifier of "(01)" are added by Zint. (A
14-digit code that appends the check digit may be given, in which case the check
digit will be verified.)
14-digit code that appends the standard GS1 check digit may be given, in which
case the check digit will be verified.)
GS1 DataBar Omnidirectional symbols should have a height of 33 or greater. To
produce a GS1 DataBar Truncated symbol set the symbol height to a value between
@ -3281,10 +3288,10 @@ the symbol. This method allows the inclusion of parentheses in the data to be
encoded. If the data does not include parentheses, the AIs may alternatively be
encased in parentheses using the --gs1parens switch. See 6.1.10.3 GS1-128.
GTIN data AI (01) should also include the check digit data as this is not
calculated by Zint when this symbology is encoded. Fixed length data should be
entered at the appropriate length for correct encoding. The following is an
example of a valid GS1 DataBar Expanded input:
GTIN data AI (01) should also include the standard GS1 check digit data as this
is not calculated by Zint when this symbology is encoded. Fixed length data
should be entered at the appropriate length for correct encoding. The following
is an example of a valid GS1 DataBar Expanded input:
zint -b 31 -d "[01]98898765432106[3202]012345[15]991231"