diff --git a/.clang-tidy b/.clang-tidy index d41bac60..b00e6c77 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,3 +1,3 @@ --- -Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy' +Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling' HeaderFilterRegex: '.*' diff --git a/ChangeLog b/ChangeLog index 4d8dd40b..0967e211 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,24 @@ -Version 2.14.0.9 (dev) not released yet (2025-02-07) +Version 2.14.0.9 (dev) not released yet (2025-02-15) ==================================================== +**Incompatible changes** +------------------------ +- New `text_length` field in `symbol` (useful for new output option + `BARCODE_PLAIN_HRT`) + Changes ------- - iso4217: remove 191 (HRK), 694 (SLL), 931 (CUC); add 926 (VED) +- Add `text_length` (length of `text`) to `zint_symbol`, and new + `BARCODE_PLAIN_HRT` option for `output_options` +- PLESSEY: add show default check characters option Bugs ---- +- CODE32: ignore `option_2` (check digit options) +- PZN: ignore `option_2` (check digit options) except for indicates PZN7 only +- DPD: exclude DEL from ident tag also +- out_maybe_mkdir: fix `utf8_to_wide()` return (Windows only) - man page: fix Code 93 `--vers=1` hide -> show default check digits diff --git a/README.clang-tidy b/README.clang-tidy index 55be6fc9..96c6779a 100644 --- a/README.clang-tidy +++ b/README.clang-tidy @@ -1,5 +1,5 @@ -% README.clang-tidy 2024-09-03 -% Current as of latest clang-tidy-20 from Ubuntu 22.04 apt package +% README.clang-tidy 2025-02-15 +% Current as of latest clang-tidy-20 from Ubuntu 24.04 apt package Requires cmake in "build" sub-directory with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON (for "build/compile_commands.json") and -DCMAKE_BUILD_TYPE=Debug (so `assert()`s defined), and then make (for Qt generated includes). @@ -8,15 +8,15 @@ In project root directory (warning, slow): clang-tidy-20 backend/*.c frontend/*.c backend_qt/*.cpp frontend_qt/*.cpp -p build/compile_commands.json -For "backend_tcl", which has no "compile_commands.json", specify the tcl include directory, e.g. +For "backend_tcl", which has no "compile_commands.json", specify the tcl include directory and package define, e.g. -clang-tidy-20 backend_tcl/*.c -- -I/usr/include/tcl8.6 +clang-tidy-20 backend_tcl/*.c -- -I/usr/include/tcl8.6 -DPACKAGE_VERSION='"2.14.0"' -Options are in ".clang-tidy" (in the project root directory). The excluded checks are -`clang-analyzer-security.insecureAPI.strcpy` (for `strcpy()`, `strcat()` etc), and +Options are in ".clang-tidy" (in the project root directory). The excluded check is `clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling` (for `sprintf()`). -The test suite (cmake given -DZINT_TEST=ON) can also be analysed with an additional check disabled: +The test suite (cmake given -DZINT_TEST=ON) can also be analysed with additional checks disabled: clang-tidy-20 backend/tests/*.c frontend/tests/*.c backend_qt/tests/*.cpp \ - -checks='-clang-analyzer-optin.performance.Padding' -p build/compile_commands.json + -checks='-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding' \ + -p build/compile_commands.json diff --git a/backend/2of5.c b/backend/2of5.c index e529ddd4..11a002b8 100644 --- a/backend/2of5.c +++ b/backend/2of5.c @@ -60,8 +60,9 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], int i; char dest[818]; /* Largest destination 4 + (80 + 1) * 10 + 3 + 1 = 818 */ char *d = dest; - unsigned char temp[113 + 1 + 1]; /* Largest maximum 113 + optional check digit */ + unsigned char local_source[113 + 1]; /* Largest maximum 113 + optional check digit */ const int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > max) { /* errtxt 301: 303: 305: 307: */ @@ -75,13 +76,13 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], "Invalid character at position %d in input (digits only)", i); } - ustrcpy(temp, source); + memcpy(local_source, source, length); if (have_checkdigit) { /* Add standard GS1 check digit */ - temp[length] = gs1_check_digit(source, length); - temp[++length] = '\0'; - if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %c\n", temp[length - 1]); + local_source[length] = gs1_check_digit(source, length); + length++; + if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %c\n", local_source[length - 1]); } /* Start character */ @@ -90,11 +91,11 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], if (is_matrix) { for (i = 0; i < length; i++, d += 6) { - memcpy(d, C25MatrixTable[temp[i] - '0'], 6); + memcpy(d, C25MatrixTable[local_source[i] - '0'], 6); } } else { for (i = 0; i < length; i++, d += 10) { - memcpy(d, C25IndustTable[temp[i] - '0'], 10); + memcpy(d, C25IndustTable[local_source[i] - '0'], 10); } } @@ -104,10 +105,11 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], expand(symbol, dest, d - dest); - ustrcpy(symbol->text, temp); - if (symbol->option_2 == 2) { - /* Remove check digit from HRT */ - symbol->text[length - 1] = '\0'; + if (symbol->option_2 == 2 && !plain_hrt) { + /* Exclude check digit from HRT */ + hrt_cpy_nochk(symbol, local_source, length - 1); + } else { + hrt_cpy_nochk(symbol, local_source, length); } return 0; diff --git a/backend/2of5inter.c b/backend/2of5inter.c index 94cf7a19..ee863c9a 100644 --- a/backend/2of5inter.c +++ b/backend/2of5inter.c @@ -48,8 +48,9 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[] int i, j, error_number = 0; char dest[638]; /* 4 + (125 + 1) * 5 + 3 + 1 = 638 */ char *d = dest; - unsigned char temp[125 + 1 + 1]; + unsigned char local_source[125 + 1]; const int have_checkdigit = checkdigit_option == 1 || checkdigit_option == 2; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 125) { /* 4 + (125 + 1) * 9 + 5 = 1143 */ return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 309, "Input length %d too long (maximum 125)", length); @@ -63,17 +64,16 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[] if an odd number of characters has been entered and no check digit or an even number and have check digit then add a leading zero */ if (have_checkdigit == !(length & 1)) { - temp[0] = '0'; - memcpy(temp + 1, source, length++); + local_source[0] = '0'; + memcpy(local_source + 1, source, length++); } else { - memcpy(temp, source, length); + memcpy(local_source, source, length); } - temp[length] = '\0'; if (have_checkdigit) { /* Add standard GS1 check digit */ - temp[length] = gs1_check_digit(temp, length); - temp[++length] = '\0'; + local_source[length] = gs1_check_digit(local_source, length); + length++; } /* Start character */ @@ -82,8 +82,8 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[] for (i = 0; i < length; i += 2) { /* Look up the bars and the spaces */ - const char *const bars = C25InterTable[temp[i] - '0']; - const char *const spaces = C25InterTable[temp[i + 1] - '0']; + const char *const bars = C25InterTable[local_source[i] - '0']; + const char *const spaces = C25InterTable[local_source[i + 1] - '0']; /* Then merge (interlace) the strings together */ for (j = 0; j < 5; j++) { @@ -98,12 +98,6 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[] expand(symbol, dest, d - dest); - ustrcpy(symbol->text, temp); - if (checkdigit_option == 2) { - /* Remove check digit from HRT */ - symbol->text[length - 1] = '\0'; - } - if (!dont_set_height) { if (symbol->output_options & COMPLIANT_HEIGHT) { /* ISO/IEC 16390:2007 Section 4.4 min height 5mm or 15% of symbol width whichever greater where @@ -123,6 +117,13 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[] } } + if (checkdigit_option == 2 && !plain_hrt) { + /* Exclude check digit from HRT */ + hrt_cpy_nochk(symbol, local_source, length - 1); + } else { + hrt_cpy_nochk(symbol, local_source, length); + } + return error_number; } diff --git a/backend/2of5inter_based.c b/backend/2of5inter_based.c index 18b0e767..b89d3398 100644 --- a/backend/2of5inter_based.c +++ b/backend/2of5inter_based.c @@ -42,7 +42,7 @@ INTERNAL int c25_inter_common(struct zint_symbol *symbol, unsigned char source[] /* Interleaved 2-of-5 (ITF-14) */ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int length) { int i, error_number, zeroes; - unsigned char localstr[16] = {0}; + unsigned char local_source[14]; if (length > 13) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 311, "Input length %d too long (maximum 13)", length); @@ -56,15 +56,13 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt /* Add leading zeros as required */ zeroes = 13 - length; for (i = 0; i < zeroes; i++) { - localstr[i] = '0'; + local_source[i] = '0'; } - ustrcpy(localstr + zeroes, source); + memcpy(local_source + zeroes, source, length); /* Calculate the check digit - the same method used for EAN-13 */ - localstr[13] = gs1_check_digit(localstr, 13); - localstr[14] = '\0'; - error_number = c25_inter_common(symbol, localstr, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); - ustrcpy(symbol->text, localstr); + local_source[13] = gs1_check_digit(local_source, 13); + error_number = c25_inter_common(symbol, local_source, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); if (error_number < ZINT_ERROR) { if (!(symbol->output_options & (BARCODE_BOX | BARCODE_BIND | BARCODE_BIND_TOP))) { @@ -88,6 +86,8 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt } } + hrt_cpy_nochk(symbol, local_source, 14); + return error_number; } @@ -101,11 +101,12 @@ static char c25_dp_check_digit(const unsigned int count) { https://www.deutschepost.de/content/dam/dpag/images/D_d/dialogpost-schwer/dp-dialogpost-schwer-broschuere-072021.pdf */ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, j, error_number; + int i, error_number; unsigned int count; int factor; - unsigned char localstr[16] = {0}; + unsigned char local_source[14]; int zeroes; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; count = 0; if (length > 13) { @@ -118,41 +119,41 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng zeroes = 13 - length; for (i = 0; i < zeroes; i++) - localstr[i] = '0'; - ustrcpy(localstr + zeroes, source); + local_source[i] = '0'; + memcpy(local_source + zeroes, source, length); factor = 4; for (i = 12; i >= 0; i--) { - count += factor * ctoi(localstr[i]); + count += factor * ctoi(local_source[i]); factor ^= 0x0D; /* Toggles 4 and 9 */ } - localstr[13] = c25_dp_check_digit(count); - localstr[14] = '\0'; - error_number = c25_inter_common(symbol, localstr, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); - - /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do examples at - https://www.philaseiten.de/cgi-bin/index.pl?ST=8615&CP=0&F=1#M147 */ - for (i = 0, j = 0; i <= 14; i++) { - symbol->text[j++] = localstr[i]; - if (i == 4 || i == 7 || i == 10) { - symbol->text[j++] = '.'; - } - } + local_source[13] = c25_dp_check_digit(count); + error_number = c25_inter_common(symbol, local_source, 14, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); /* TODO: Find documentation on BARCODE_DPLEIT dimensions/height */ /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); + if (plain_hrt) { + hrt_cpy_nochk(symbol, local_source, 14); + } else { + /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do examples at + https://www.philaseiten.de/cgi-bin/index.pl?ST=8615&CP=0&F=1#M147 */ + hrt_printf_nochk(symbol, "%.5s.%.3s.%.3s.%.3s", local_source, local_source + 5, local_source + 8, + local_source + 11); + } + return error_number; } /* Deutsche Post Identcode */ /* See dpleit() for (sort of) documentation reference */ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, j, error_number, zeroes; + int i, error_number, zeroes; unsigned int count; int factor; - unsigned char localstr[16] = {0}; + unsigned char local_source[12]; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; count = 0; if (length > 11) { @@ -165,32 +166,29 @@ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int len zeroes = 11 - length; for (i = 0; i < zeroes; i++) - localstr[i] = '0'; - ustrcpy(localstr + zeroes, source); + local_source[i] = '0'; + memcpy(local_source + zeroes, source, length); factor = 4; for (i = 10; i >= 0; i--) { - count += factor * ctoi(localstr[i]); + count += factor * ctoi(local_source[i]); factor ^= 0x0D; /* Toggles 4 and 9 */ } - localstr[11] = c25_dp_check_digit(count); - localstr[12] = '\0'; - error_number = c25_inter_common(symbol, localstr, 12, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); - - /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do other examples (see above) */ - for (i = 0, j = 0; i <= 12; i++) { - symbol->text[j++] = localstr[i]; - if (i == 1 || i == 4 || i == 7) { - symbol->text[j++] = '.'; - } else if (i == 3 || i == 10) { - symbol->text[j++] = ' '; - } - } + local_source[11] = c25_dp_check_digit(count); + error_number = c25_inter_common(symbol, local_source, 12, 0 /*checkdigit_option*/, 1 /*dont_set_height*/); /* TODO: Find documentation on BARCODE_DPIDENT dimensions/height */ /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); + if (plain_hrt) { + hrt_cpy_nochk(symbol, local_source, 12); + } else { + /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do other examples (see above) */ + hrt_printf_nochk(symbol, "%.2s.%.2s %c.%.3s.%.3s %c", local_source, local_source + 2, local_source[4], + local_source + 5, local_source + 8, local_source[11]); + } + return error_number; } diff --git a/backend/auspost.c b/backend/auspost.c index a5cfdd57..f4db94a3 100644 --- a/backend/auspost.c +++ b/backend/auspost.c @@ -118,8 +118,11 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len char data_pattern[200]; char *d = data_pattern; - char fcc[3] = {0}, dpid[10]; - char localstr[30]; + unsigned char fcc[2] = {0}; /* Suppress clang-tidy warning clang-analyzer-core.UndefinedBinaryOperatorResult */ + unsigned char dpid[9]; + unsigned char local_source[30]; + int zeroes = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; /* Do all of the length checking first to avoid stack smashing */ if (symbol->symbology == BARCODE_AUSPOST) { @@ -137,19 +140,17 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len "Invalid character at position %d in input (alphanumerics, space and \"#\" only)", i); } - localstr[0] = '\0'; - if (symbol->symbology == BARCODE_AUSPOST) { /* Format control code (FCC) */ switch (length) { case 8: - strcpy(fcc, "11"); + memcpy(fcc, "11", 2); break; case 13: - strcpy(fcc, "59"); + memcpy(fcc, "59", 2); break; case 16: - strcpy(fcc, "59"); + memcpy(fcc, "59", 2); if ((i = not_sane(NEON_F, source, length))) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 402, "Invalid character at position %d in input (digits only for FCC 59 length 16)", @@ -157,10 +158,10 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len } break; case 18: - strcpy(fcc, "62"); + memcpy(fcc, "62", 2); break; case 23: - strcpy(fcc, "62"); + memcpy(fcc, "62", 2); if ((i = not_sane(NEON_F, source, length))) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 406, "Invalid character at position %d in input (digits only for FCC 62 length 23)", @@ -169,32 +170,29 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len break; } } else { - int zeroes; switch (symbol->symbology) { - case BARCODE_AUSREPLY: strcpy(fcc, "45"); + case BARCODE_AUSREPLY: memcpy(fcc, "45", 2); break; - case BARCODE_AUSROUTE: strcpy(fcc, "87"); + case BARCODE_AUSROUTE: memcpy(fcc, "87", 2); break; - case BARCODE_AUSREDIRECT: strcpy(fcc, "92"); + case BARCODE_AUSREDIRECT: memcpy(fcc, "92", 2); break; } /* Add leading zeros as required */ zeroes = 8 - length; - memset(localstr, '0', zeroes); - localstr[zeroes] = '\0'; + memset(local_source, '0', zeroes); } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("AUSPOST FCC: %s\n", fcc); + printf("AUSPOST FCC: %.2s\n", fcc); } - ustrncat(localstr, source, length); - h = (int) strlen(localstr); + memcpy(local_source + zeroes, source, length); + length += zeroes; /* Verify that the first 8 characters are numbers */ - memcpy(dpid, localstr, 8); - dpid[8] = '\0'; - if ((i = not_sane(NEON_F, (const unsigned char *) dpid, 8))) { + memcpy(dpid, local_source, 8); + if ((i = not_sane(NEON_F, dpid, 8))) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 405, "Invalid character at position %d in DPID (first 8 characters) (digits only)", i); } @@ -214,14 +212,14 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len } /* Customer Information */ - if (h > 8) { - if ((h == 13) || (h == 18)) { - for (reader = 8; reader < h; reader++, d += 3) { - memcpy(d, AusCTable[posn(GDSET, localstr[reader])], 3); + if (length > 8) { + if ((length == 13) || (length == 18)) { + for (reader = 8; reader < length; reader++, d += 3) { + memcpy(d, AusCTable[posn(GDSET, local_source[reader])], 3); } - } else if ((h == 16) || (h == 23)) { - for (reader = 8; reader < h; reader++, d += 2) { - memcpy(d, AusNTable[localstr[reader] - '0'], 2); + } else if ((length == 16) || (length == 23)) { + for (reader = 8; reader < length; reader++, d += 2) { + memcpy(d, AusNTable[local_source[reader] - '0'], 2); } } } @@ -279,6 +277,11 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len symbol->rows = 3; symbol->width = writer - 1; + if (plain_hrt) { + hrt_cpy_nochk(symbol, fcc, 2); + hrt_cat_nochk(symbol, local_source, length); + } + return error_number; } diff --git a/backend/bc412.c b/backend/bc412.c index 17e219f1..b195017e 100644 --- a/backend/bc412.c +++ b/backend/bc412.c @@ -1,7 +1,7 @@ /* bc412.c - Handles IBM BC412 (SEMI T1-95) symbology */ /* libzint - the open source barcode library - Copyright (C) 2022-2024 Robin Stuart + Copyright (C) 2022-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -87,7 +87,6 @@ INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int lengt for (i = 2; i <= length; i++) { padded_source[i] = source[i - 1]; } - padded_source[length + 1] = 0; if ((i = not_sane_lookup(BROMINE, 35, padded_source, length + 1, posns))) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 791, @@ -131,7 +130,6 @@ INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int lengt d += 3; expand(symbol, dest, d - dest); - ustrcpy(symbol->text, padded_source); if (symbol->output_options & COMPLIANT_HEIGHT) { /* SEMI T1-95 Table 1 "Module" (Character) Height 2mm ± 0.025mm, using Module Spacing 0.12mm ± 0.025mm as @@ -146,6 +144,8 @@ INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int lengt (void) set_height(symbol, 0.0f, default_height, 0.0f, 1 /*no_errtxt*/); } + hrt_cpy_nochk(symbol, padded_source, length + 1); + return error_number; } diff --git a/backend/channel.c b/backend/channel.c index bc1fb60b..966aafa6 100644 --- a/backend/channel.c +++ b/backend/channel.c @@ -174,6 +174,7 @@ nb0: if (++B[0] <= bmax[0]) goto lb0; /* Channel Code - According to ANSI/AIM BC12-1998 */ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int length) { static const int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 }; + static const unsigned char zeroes_str[] = "0000000"; /* 7 zeroes */ int S[8] = {0}, B[8] = {0}; int target_value; char dest[30]; @@ -233,14 +234,6 @@ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int len *d++ = itoc(B[i]); } - zeroes = channels - 1 - length; - if (zeroes < 0) { - zeroes = 0; - } else if (zeroes) { - memset(symbol->text, '0', zeroes); - } - ustrcpy(symbol->text + zeroes, source); - expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { @@ -253,6 +246,14 @@ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int len (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); } + zeroes = channels - 1 - length; + if (zeroes > 0) { + hrt_cpy_nochk(symbol, zeroes_str, zeroes); + hrt_cat_nochk(symbol, source, length); + } else { + hrt_cpy_nochk(symbol, source, length); + } + return error_number; } diff --git a/backend/codabar.c b/backend/codabar.c index c17c6809..167d3b8a 100644 --- a/backend/codabar.c +++ b/backend/codabar.c @@ -58,6 +58,7 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len char *d = dest; int add_checksum, count = 0, checksum = 0; int d_chars = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 103) { /* No stack smashing please (103 + 1) * 11 = 1144 */ return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 356, "Input length %d too long (maximum 103)", length); @@ -133,11 +134,11 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); } - ustrcpy(symbol->text, source); - if (symbol->option_2 == 2) { - symbol->text[length - 1] = CALCIUM[checksum]; /* Place before final A/B/C/D character (BS EN 798:1995 A.3) */ - symbol->text[length] = source[length - 1]; - symbol->text[length + 1] = '\0'; + if (symbol->option_2 == 2 || (plain_hrt && add_checksum)) { + /* Place before final A/B/C/D character (BS EN 798:1995 A.3) */ + hrt_printf_nochk(symbol, "%.*s%c%c", length - 1, source, CALCIUM[checksum], source[length - 1]); + } else { + hrt_cpy_nochk(symbol, source, length); } return error_number; diff --git a/backend/codablock.c b/backend/codablock.c index 7a275525..623ca1c6 100644 --- a/backend/codablock.c +++ b/backend/codablock.c @@ -1,7 +1,7 @@ /* codablock.c - Handles Codablock-F */ /* libzint - the open source barcode library - Copyright (C) 2016-2024 Harald Oehlmann + Copyright (C) 2016-2025 Harald Oehlmann Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -47,8 +47,8 @@ #define CFill 32 #define CodeFNC1 64 #define CodeFNC4 128 -#define ZTNum (CodeA + CodeB + CodeC) -#define ZTFNC1 (CodeA + CodeB + CodeC + CodeFNC1) +#define ZTNum (CodeA | CodeB | CodeC) +#define ZTFNC1 (CodeA | CodeB | CodeC | CodeFNC1) /* ASCII-Extension for Codablock-F */ #define aFNC1 ((uchar) 128) @@ -76,14 +76,14 @@ static int GetPossibleCharacterSet(unsigned char C) { if (C <= '\x1f') /* Control chars */ return CodeA; if (z_isdigit(C)) - return ZTNum; /* ZTNum=CodeA+CodeB+CodeC */ + return ZTNum; /* ZTNum = CodeA | CodeB | CodeC */ if (C == aFNC1) /* FNC1s (GS1) not used */ - return ZTFNC1; /* ZTFNC1=CodeA+CodeB+CodeC+CodeFNC1 */ /* Not reached */ + return ZTFNC1; /* ZTFNC1 = CodeA | CodeB | CodeC | CodeFNC1 */ /* Not reached */ if (C == aFNC4) return (CodeA | CodeB | CodeFNC4); if (C >= '\x60' && C <= '\x7f') /* 60 to 127 */ return CodeB; - return CodeA + CodeB; + return CodeA | CodeB; } /* Create a Table with the following information for each Data character: @@ -561,7 +561,7 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int if (symbol->border_width == 0) { /* Allow override if non-zero */ symbol->border_width = 1; /* AIM ISS-X-24 Section 4.6.1 b) (note change from previous default 2) */ } - symbol->text[0] = '\0'; /* Disable HRT for compatibility with CODABLOCKF */ + hrt_cpy_nochk(symbol, (const unsigned char *) "", 0); /* Zap HRT for compatibility with CODABLOCKF */ if (symbol->output_options & COMPLIANT_HEIGHT) { /* AIM ISS-X-24 Section 4.6.1 minimum row height 8X (for compatibility with CODABLOCKF, not specced for CODE128) */ @@ -613,9 +613,10 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int CreateCharacterSetTable(T, data, dataLength); /* Find final row and column count */ - /* nor row nor column count given */ + + /* Neither row nor column count given */ if (rows <= 0 && columns <= 0) { - /* use 1/1 aspect/ratio Codablock */ + /* Use 1/1 aspect/ratio */ columns = (int) floor(sqrt(dataLength)) + 5; if (columns > 67) { columns = 67; @@ -629,10 +630,10 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int /* There are 5 Codewords for Organisation Start(2),row(1),CheckSum,Stop */ useColumns = columns - 5; if (rows > 0) { - /* row count given */ + /* Row count given */ error_number = Rows2Columns(symbol, T, dataLength, &rows, &useColumns, pSet, &fillings); } else { - /* column count given */ + /* Column count given */ error_number = Columns2Rows(symbol, T, dataLength, &rows, &useColumns, pSet, &fillings); } if (error_number != 0) { @@ -649,14 +650,14 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int Sum2 = (Sum2 + charCur * source[charCur]) % 86; } - if (symbol->debug & ZINT_DEBUG_PRINT) { /* start a new level of local variables */ + if (symbol->debug & ZINT_DEBUG_PRINT) { int DPos; fputs("\nData:", stdout); for (DPos = 0; DPos < dataLength; DPos++) fputc(data[DPos], stdout); fputs("\n Set:", stdout); for (DPos = 0; DPos < dataLength; DPos++) { - switch (pSet[DPos] & (CodeA + CodeB + CodeC)) { + switch (pSet[DPos] & (CodeA | CodeB | CodeC)) { case CodeA: fputc('A', stdout); break; case CodeB: fputc('B', stdout); break; case CodeC: fputc('C', stdout); break; @@ -690,10 +691,8 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int for (rowCur = 0; rowCur < rows; rowCur++) { if (charCur >= dataLength) { /* >> Empty line with StartA, aCodeB, row #, and then filler aCodeC aCodeB etc */ - *pOutPos = '\x67'; - pOutPos++; - *pOutPos = 100; /* aCodeB */ - pOutPos++; + *pOutPos++ = '\x67'; + *pOutPos++ = 100; /* aCodeB */ characterSetCur = CodeB; SumASCII(&pOutPos, rowCur + 42, characterSetCur); /* Row # */ emptyColumns = useColumns; @@ -711,29 +710,23 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int --emptyColumns; } } else { - /* >> Normal Line */ + /* >> Normal line */ /* > Startcode */ - switch (pSet[charCur] & (CodeA + CodeB + CodeC)) { + switch (pSet[charCur] & (CodeA | CodeB | CodeC)) { case CodeA: - *pOutPos = '\x67'; - pOutPos++; - *pOutPos = '\x62'; - pOutPos++; + *pOutPos++ = '\x67'; + *pOutPos++ = '\x62'; characterSetCur = CodeA; break; case CodeB: - *pOutPos = '\x67'; - pOutPos++; - *pOutPos = '\x64'; - pOutPos++; + *pOutPos++ = '\x67'; + *pOutPos++ = '\x64'; characterSetCur = CodeB; break; case CodeC: default: - *pOutPos = '\x67'; - pOutPos++; - *pOutPos = '\x63'; - pOutPos++; + *pOutPos++ = '\x67'; + *pOutPos++ = '\x63'; characterSetCur = CodeC; break; } @@ -788,7 +781,7 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int } /* >> End Criteria */ if ((pSet[charCur] & CFill) || (pSet[charCur] & CEnd)) { - /* Fill Line but leave space for checks in last line */ + /* Fill line but leave space for checks in last line */ if (rowCur == rows - 1) { emptyColumns -= 2; } @@ -812,7 +805,7 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int } ++charCur; } /* Loop over characters */ - } /* if filling-Line / normal */ + } /* if filling line / normal line */ /* Add checksum in last line */ if (rowCur == rows - 1) { @@ -826,26 +819,20 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int for (; Pos < useColumns + 3; Pos++) { Sum = (Sum + pOutput[columns * rowCur + Pos] * Pos) % 103; } - *pOutPos = (uchar) Sum; - pOutPos++; + *pOutPos++ = (uchar) Sum; } /* Add end character */ - *pOutPos = 106; - pOutPos++; + *pOutPos++ = 106; } /* End Lineloop */ if (symbol->debug & ZINT_DEBUG_PRINT) { - /* Dump the output to the screen - */ + int DPos, DPos2; fputs("\nCode 128 Code Numbers:\n", stdout); - { /* start a new level of local variables */ - int DPos, DPos2; - for (DPos = 0; DPos < rows; DPos++) { - for (DPos2 = 0; DPos2 < columns; DPos2++) { - printf("%3d ", (int) (pOutput[DPos * columns + DPos2])); - } - fputc('\n', stdout); + for (DPos = 0; DPos < rows; DPos++) { + for (DPos2 = 0; DPos2 < columns; DPos2++) { + printf("%3d ", (int) pOutput[DPos * columns + DPos2]); } + fputc('\n', stdout); } printf("rows=%d columns=%d (%d data) fillings=%d\n", rows, columns, columns - 5, fillings); } diff --git a/backend/code.c b/backend/code.c index 99c7e040..0dfdb515 100644 --- a/backend/code.c +++ b/backend/code.c @@ -126,9 +126,8 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng int posns[86]; char dest[890]; /* 10 (Start) + 86 * 10 + 10 (Check) + 9 (Stop) + 1 = 890 */ char *d = dest; - char localstr[2] = {0}; - - counter = 0; + char check_digit = '\0'; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if ((symbol->option_2 < 0) || (symbol->option_2 > 2)) { symbol->option_2 = 0; @@ -155,28 +154,17 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng memcpy(d, C39Table[43], 10); d += 10; - for (i = 0; i < length; i++, d += 10) { + for (i = 0, counter = 0; i < length; i++, d += 10) { memcpy(d, C39Table[posns[i]], 10); counter += posns[i]; } if (symbol->option_2 == 1 || symbol->option_2 == 2) { /* Visible or hidden check digit */ - - char check_digit; counter %= 43; check_digit = SILVER[counter]; memcpy(d, C39Table[counter], 10); d += 10; - /* Display a space check digit as _, otherwise it looks like an error */ - if (check_digit == ' ') { - check_digit = '_'; - } - - if (symbol->option_2 == 1) { /* Visible check digit */ - localstr[0] = check_digit; - localstr[1] = '\0'; - } if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %c\n", check_digit); } @@ -223,14 +211,19 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng (void) set_height(symbol, 0.0f, 50.f, 0.0f, 1 /*no_errtxt*/); } - if (symbol->symbology == BARCODE_CODE39) { - ustrcpy(symbol->text, "*"); - ustrncat(symbol->text, source, length); - ustrcat(symbol->text, localstr); - ustrcat(symbol->text, "*"); + if (symbol->symbology == BARCODE_CODE39 && !plain_hrt) { + hrt_cpy_chr(symbol, '*'); + hrt_cat_nochk(symbol, source, length); + if (symbol->option_2 == 1) { /* Visible check digit */ + /* Display a space check digit as _, otherwise it looks like an error */ + hrt_cat_chr_nochk(symbol, check_digit == ' ' ? '_' : check_digit); + } + hrt_cat_chr_nochk(symbol, '*'); } else { - ustrcpy(symbol->text, source); - ustrcat(symbol->text, localstr); + hrt_cpy_nochk(symbol, source, length); + if (symbol->option_2 == 1 || (plain_hrt && check_digit)) { + hrt_cat_chr_nochk(symbol, !plain_hrt && check_digit == ' ' ? '_' : check_digit); + } } return error_number; } @@ -243,6 +236,7 @@ INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int le unsigned char check_digit = '\0'; int i; int error_number; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 86) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 328, "Input length %d too long (maximum 86)", length); @@ -250,7 +244,7 @@ INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int le /* Creates a buffer string and places control characters into it */ for (i = 0; i < length; i++) { - if (source[i] > 127) { + if (!z_isascii(source[i])) { /* Cannot encode extended ASCII */ return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 329, "Invalid character at position %d in input, extended ASCII not allowed", i + 1); @@ -267,22 +261,16 @@ INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int le /* Then sends the buffer to the C39 function */ error_number = code39(symbol, buffer, b - buffer); - /* Save visible check digit */ - if (symbol->option_2 == 1) { - const int len = (int) ustrlen(symbol->text); - if (len > 0) { - check_digit = symbol->text[len - 1]; - } + /* Save visible (or BARCODE_PLAIN_HRT) check digit */ + if (symbol->option_2 == 1 || (plain_hrt && symbol->option_2 == 2)) { + check_digit = symbol->text[symbol->text_length - 1]; } - /* Copy over source to HRT, subbing space for unprintables */ - for (i = 0; i < length; i++) - symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; - + /* Copy over source to HRT, subbing space for unprintables (unless BARCODE_PLAIN_HRT) */ + (void) hrt_cpy_iso8859_1(symbol, source, length); /* Will fit (ASCII, length <= 86) */ if (check_digit) { - symbol->text[i++] = check_digit; + hrt_cat_chr_nochk(symbol, check_digit); } - symbol->text[i] = '\0'; return error_number; } @@ -301,6 +289,7 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng char *b = buffer; char dest[764]; /* 6 (Start) + 123*6 + 2*6 (Checks) + 7 (Stop) + 1 (NUL) = 764 */ char *d = dest; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; /* Suppresses clang-tidy clang-analyzer-core.CallAndMessage warning */ assert(length > 0); @@ -311,14 +300,13 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng /* Message Content */ for (i = 0; i < length; i++) { - if (source[i] > 127) { + if (!z_isascii(source[i])) { /* Cannot encode extended ASCII */ return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 331, "Invalid character at position %d in input, extended ASCII not allowed", i + 1); } memcpy(b, C93Ctrl[source[i]], 2); b += C93Ctrl[source[i]][1] ? 2 : 1; - symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; } /* Now we can check the true length of the barcode */ @@ -360,7 +348,7 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng h += 2; if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Check digit c: %d, k: %d\n", c, k); + printf("Check digit c: %c (%d), k: %c (%d)\n", SILVER[c], c, SILVER[k], k); } /* Start character */ @@ -387,10 +375,10 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); } - if (symbol->option_2 == 1) { - symbol->text[length] = SILVER[c]; - symbol->text[length + 1] = SILVER[k]; - symbol->text[length + 2] = '\0'; + (void) hrt_cpy_iso8859_1(symbol, source, length); /* Will fit (ASCII, length <= 123) */ + if (symbol->option_2 == 1 || plain_hrt) { + hrt_cat_chr_nochk(symbol, SILVER[c]); + hrt_cat_chr_nochk(symbol, SILVER[k]); } return error_number; @@ -407,6 +395,7 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) char output_check; int sum; int i; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; static const char weight[17] = { 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 }; /* Check length */ @@ -465,7 +454,7 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) d += 10; /* Import character 'I' prefix? */ - if (symbol->option_2 & 1) { + if (symbol->option_2 == 1) { memcpy(d, C39Table[18], 10); d += 10; } @@ -481,7 +470,12 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) expand(symbol, dest, d - dest); - ustrcpy(symbol->text, source); + if (plain_hrt && symbol->option_2 == 1) { + hrt_cpy_chr(symbol, 'I'); + hrt_cat_nochk(symbol, source, length); + } else { + hrt_cpy_nochk(symbol, source, length); + } /* Specification of dimensions/height for BARCODE_VIN unlikely */ diff --git a/backend/code11.c b/backend/code11.c index e103ba12..cb4a3ddf 100644 --- a/backend/code11.c +++ b/backend/code11.c @@ -55,8 +55,8 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng int error_number = 0; char *d = dest; int num_check_digits; - char checkstr[3] = {0}; - static const char checkchrs[11] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' }; + unsigned char checkstr[2]; + static const unsigned char checkchrs[11] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' }; /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */ assert(length > 0); @@ -134,7 +134,8 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Check digit (%d): %s\n", num_check_digits, num_check_digits ? checkstr : ""); + printf("Check digits (%d): %.*s%s\n", num_check_digits, num_check_digits, checkstr, + num_check_digits ? "" : ""); } /* Stop character */ @@ -145,9 +146,9 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng /* TODO: Find documentation on BARCODE_CODE11 dimensions/height */ - ustrcpy(symbol->text, source); + hrt_cpy_nochk(symbol, source, length); if (num_check_digits) { - ustrcat(symbol->text, checkstr); + hrt_cat_nochk(symbol, checkstr, num_check_digits); } return error_number; } diff --git a/backend/code128.c b/backend/code128.c index f9d5590c..1f1ff029 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -142,7 +142,7 @@ static int c128_cost_ab(const int cset, const unsigned char ch, int *p_mode) { } /* FNC4 */ - if (C128_A0B0(cset) == (ch >= 128)) { /* If A0/B0 and extended ASCII, or A1/B1 and ASCII */ + if (C128_A0B0(cset) == !z_isascii(ch)) { /* If A0/B0 and extended ASCII, or A1/B1 and ASCII */ cost++; *p_mode |= 0x20; } @@ -508,6 +508,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int int separator_row = 0; int reduced_length; unsigned char *reduced = (unsigned char *) z_alloca(length + 1); + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > C128_MAX) { /* This only blocks ridiculously long input - the actual length of the @@ -522,12 +523,11 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int symbol->rows += 1; } - error_number = gs1_verify(symbol, source, length, reduced); + error_number = gs1_verify(symbol, source, length, reduced, &reduced_length); if (error_number >= ZINT_ERROR) { return error_number; } - reduced_length = (int) ustrlen(reduced); memset(fncs, 1, reduced_length); /* Control and extended chars not allowed so only have B/C (+FNC1) */ @@ -631,29 +631,16 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int "Cannot use Reader Initialisation in GS1 mode, ignoring"); } - if (symbol->input_mode & GS1PARENS_MODE) { - i = length < (int) sizeof(symbol->text) ? length : (int) sizeof(symbol->text); - memcpy(symbol->text, source, i); + /* Note won't overflow `text` buffer due to symbol character maximum restricted to C128_SYMBOL_MAX */ + if (plain_hrt) { + hrt_cpy_nochk(symbol, reduced, reduced_length); } else { - int bracket_level = 0; /* Non-compliant closing square brackets may be in text */ - for (i = 0; i < length && i < (int) sizeof(symbol->text); i++) { - if (source[i] == '[') { - symbol->text[i] = '('; - bracket_level++; - } else if (source[i] == ']' && bracket_level) { - symbol->text[i] = ')'; - bracket_level--; - } else { - symbol->text[i] = source[i]; - } + if (symbol->input_mode & GS1PARENS_MODE) { + hrt_cpy_nochk(symbol, source, length); + } else { + hrt_conv_gs1_brackets_nochk(symbol, source, length); } } - if (i == sizeof(symbol->text)) { - /* Trumps all other warnings */ - error_number = errtxt(ZINT_WARN_HRT_TRUNCATED, symbol, 844, "Human Readable Text truncated"); - i--; - } - symbol->text[i] = '\0'; return error_number; } diff --git a/backend/code128_based.c b/backend/code128_based.c index 2aecdd20..bfc34c59 100644 --- a/backend/code128_based.c +++ b/backend/code128_based.c @@ -62,9 +62,9 @@ static int nve18_or_ean14(struct zint_symbol *symbol, unsigned char source[], co } zeroes = data_len - length; - ustrcpy(ean128_equiv, prefix[data_len == 17][!(symbol->input_mode & GS1PARENS_MODE)]); + memcpy(ean128_equiv, prefix[data_len == 17][!(symbol->input_mode & GS1PARENS_MODE)], 4); memset(ean128_equiv + 4, '0', zeroes); - ustrcpy(ean128_equiv + 4 + zeroes, source); + memcpy(ean128_equiv + 4 + zeroes, source, length); ean128_equiv[data_len + 4] = gs1_check_digit(ean128_equiv + 4, data_len); ean128_equiv[data_len + 5] = '\0'; @@ -97,8 +97,10 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) unsigned char ident_tag; unsigned char local_source_buf[29]; unsigned char *local_source; + unsigned char hrt[37]; const int mod = 36; const int relabel = symbol->option_2 == 1; /* A "relabel" has no identification tag */ + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; int cd; /* Check digit */ if ((length != 27 && length != 28) || (length == 28 && relabel)) { @@ -110,7 +112,7 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) if (length == 27 && !relabel) { local_source_buf[0] = '%'; - ustrcpy(local_source_buf + 1, source); + memcpy(local_source_buf + 1, source, length); local_source = local_source_buf; length++; } else { @@ -129,9 +131,9 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) "Invalid character at position %d in input (alphanumerics only after first)", i); } - if ((ident_tag < 32) || (ident_tag > 127)) { + if (z_iscntrl(ident_tag) || !z_isascii(ident_tag)) { return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 343, - "Invalid DPD identification tag (first character), ASCII values 32 to 127 only"); + "Invalid DPD identification tag (first character), ASCII values 32 to 126 only"); } (void) code128(symbol, local_source, length); /* Only error returned is for large text which can't happen */ @@ -160,27 +162,27 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) cd = mod; - p = 0; - for (i = !relabel; i < length; i++) { - symbol->text[p] = local_source[i]; - p++; + for (i = !relabel, p = 0; i < length; i++) { + hrt[p++] = local_source[i]; cd += posn(KRSET, local_source[i]); if (cd > mod) cd -= mod; cd *= 2; if (cd >= (mod + 1)) cd -= mod + 1; - switch (i + relabel) { - case 4: - case 7: - case 11: - case 15: - case 19: - case 21: - case 24: - case 27: - symbol->text[p++] = ' '; - break; + if (!plain_hrt) { + switch (i + relabel) { + case 4: + case 7: + case 11: + case 15: + case 19: + case 21: + case 24: + case 27: + hrt[p++] = ' '; + break; + } } } @@ -188,13 +190,12 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) if (cd == mod) cd = 0; if (cd < 10) { - symbol->text[p] = cd + '0'; + hrt[p] = cd + '0'; } else { - symbol->text[p] = (cd - 10) + 'A'; + hrt[p] = (cd - 10) + 'A'; } - p++; - symbol->text[p] = '\0'; + hrt_cpy_nochk(symbol, hrt, p + 1); /* Some compliance checks */ if (not_sane(NEON_F, local_source + length - 16, 16)) { @@ -215,12 +216,14 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) /* Universal Postal Union S10 */ /* https://www.upu.int/UPU/media/upu/files/postalSolutions/programmesAndServices/standards/S10-12.pdf */ INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int length) { + static const char weights[8] = { 8, 6, 4, 2, 3, 5, 9, 7 }; int i, j; unsigned char local_source[13 + 1]; unsigned char have_check_digit = '\0'; int check_digit; - static const char weights[8] = { 8, 6, 4, 2, 3, 5, 9, 7 }; int error_number = 0; + unsigned char hrt[18]; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length != 12 && length != 13) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 834, "Input length %d wrong (12 or 13 only)", length); @@ -228,9 +231,10 @@ INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int len if (length == 13) { /* Includes check digit - remove for now */ have_check_digit = source[10]; memcpy(local_source, source, 10); - ustrcpy(local_source + 10, source + 11); + memcpy(local_source + 10, source + 11, length - 11); + length--; } else { - ustrcpy(local_source, source); + memcpy(local_source, source, length); } to_upper(local_source, length); @@ -283,14 +287,15 @@ INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int len (void) code128(symbol, local_source, 13); /* Only error returned is for large text which can't happen */ - j = 0; - for (i = 0; i < 13; i++) { - if (i == 2 || i == 5 || i == 8 || i == 11) { - symbol->text[j++] = ' '; + for (i = 0, j = 0; i < 13; i++) { + if (!plain_hrt) { + if (i == 2 || i == 5 || i == 8 || i == 11) { + hrt[j++] = ' '; + } } - symbol->text[j++] = local_source[i]; + hrt[j++] = local_source[i]; } - symbol->text[j] = '\0'; + hrt_cpy_nochk(symbol, hrt, j); if (symbol->output_options & COMPLIANT_HEIGHT) { /* Universal Postal Union S10 Section 8, using max X 0.51mm & minimum height 12.5mm or 15% of width */ diff --git a/backend/code49.c b/backend/code49.c index 5e7c3464..fdf03bd3 100644 --- a/backend/code49.c +++ b/backend/code49.c @@ -1,7 +1,7 @@ /* code49.c - Handles Code 49 */ /* libzint - the open source barcode library - Copyright (C) 2009-2024 Robin Stuart + Copyright (C) 2009-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -254,8 +254,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng } } } else if (symbol->option_1 >= 1) { - strcpy(symbol->errtxt, "433: Minimum number of rows out of range (2 to 8)"); - return ZINT_ERROR_INVALID_OPTION; + return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 433, "Minimum number of rows out of range (2 to 8)"); } /* Add row count and mode character */ diff --git a/backend/common.c b/backend/common.c index 7b2f6d0d..c06aaccb 100644 --- a/backend/common.c +++ b/backend/common.c @@ -116,7 +116,7 @@ static const unsigned short flgs[256] = { /* Whether a character matches `flg` */ INTERNAL int is_chr(const unsigned int flg, const unsigned int c) { - return c < 0x80 && (flgs[c] & flg) != 0; + return z_isascii(c) && (flgs[c] & flg); } /* Verifies if a string only uses valid characters, returning 1-based position in `source` if not, 0 for success */ @@ -263,7 +263,7 @@ static int errtxt_id_str(char *errtxt, int num) { /* Set `symbol->errtxt` to "err_id: msg", returning `error_number`. If `err_id` is -1, the "err_id: " prefix is omitted */ INTERNAL int errtxt(const int error_number, struct zint_symbol *symbol, const int err_id, const char *msg) { - const int max_len = (int) sizeof(symbol->errtxt) - 1; + const int max_len = ARRAY_SIZE(symbol->errtxt) - 1; const int id_len = errtxt_id_str(symbol->errtxt, err_id); int msg_len = (int) strlen(msg); @@ -348,7 +348,7 @@ static int errtxtf_dpad(const char *fmt) { be numbered, "%s" with length precisions: "%.*s", "%$.*$s", "%.

s" and "%$.

s", and "%d" with zero-padded minimum field lengths: "%0d" or %$0d" ("" 1-99) */ INTERNAL int errtxtf(const int error_number, struct zint_symbol *symbol, const int err_id, const char *fmt, ...) { - const int max_len = (int) sizeof(symbol->errtxt) - 1; + const int max_len = ARRAY_SIZE(symbol->errtxt) - 1; int p = errtxt_id_str(symbol->errtxt, err_id); const char *f; int i; @@ -499,21 +499,9 @@ INTERNAL int errtxtf(const int error_number, struct zint_symbol *symbol, const i /* Helper to prepend/append to existing `symbol->errtxt` by calling `errtxtf(fmt)` with 2 arguments (copy of `errtxt` & `msg`) if `msg` not NULL, or 1 argument (just copy of `errtxt`) if `msg` NULL, returning `error_number` */ INTERNAL int errtxt_adj(const int error_number, struct zint_symbol *symbol, const char *fmt, const char *msg) { - char err_buf[sizeof(symbol->errtxt)]; + char err_buf[ARRAY_SIZE(symbol->errtxt)]; - err_buf[0] = '\0'; - -/* Suppress gcc 8+ warning output may be truncated */ -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" -#endif - - strncat(err_buf, symbol->errtxt, sizeof(symbol->errtxt) - 1); - -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 -#pragma GCC diagnostic pop -#endif + memcpy(err_buf, symbol->errtxt, strlen(symbol->errtxt) + 1); /* Include terminating NUL */ if (msg) { errtxtf(0, symbol, -1, fmt, err_buf, msg); @@ -716,12 +704,11 @@ INTERNAL int utf8_to_unicode(struct zint_symbol *symbol, const unsigned char sou } while (bpos < *length && state != 0 && state != 12); if (state != 0) { - strcpy(symbol->errtxt, "240: Corrupt Unicode data"); - return ZINT_ERROR_INVALID_DATA; + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 240, "Corrupt Unicode data"); } if (disallow_4byte && codepoint > 0xffff) { - strcpy(symbol->errtxt, "242: Unicode sequences of more than 3 bytes not supported"); - return ZINT_ERROR_INVALID_DATA; + return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 242, + "Unicode sequences of more than 3 bytes not supported"); } vals[jpos] = codepoint; @@ -734,27 +721,29 @@ INTERNAL int utf8_to_unicode(struct zint_symbol *symbol, const unsigned char sou } /* Treats source as ISO/IEC 8859-1 and copies into `symbol->text`, converting to UTF-8. Control chars (incl. DEL) and - non-ISO/IEC 8859-1 (0x80-9F) are replaced with spaces. Returns warning if truncated, else 0 */ + non-ISO/IEC 8859-1 (0x80-9F) are replaced with spaces, unless BARCODE_PLAIN_HRT set in `output_options`. + Returns warning if truncated, else 0 */ INTERNAL int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char source[], const int length) { int i, j; int warn_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; - for (i = 0, j = 0; i < length && j < (int) sizeof(symbol->text); i++) { - if (source[i] < 0x80) { - symbol->text[j++] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; + for (i = 0, j = 0; i < length && j < ARRAY_SIZE(symbol->text); i++) { + if (z_isascii(source[i])) { + symbol->text[j++] = !plain_hrt && z_iscntrl(source[i]) ? ' ' : source[i]; } else if (source[i] < 0xC0) { - if (source[i] >= 0xA0) { /* 0x80-0x9F not valid ISO/IEC 8859-1 */ - if (j + 2 >= (int) sizeof(symbol->text)) { + if (!plain_hrt && source[i] < 0xA0) { /* 0x80-0x9F not valid ISO/IEC 8859-1 */ + symbol->text[j++] = ' '; + } else { + if (j + 2 >= ARRAY_SIZE(symbol->text)) { warn_number = ZINT_WARN_HRT_TRUNCATED; break; } symbol->text[j++] = 0xC2; symbol->text[j++] = source[i]; - } else { - symbol->text[j++] = ' '; } } else { - if (j + 2 >= (int) sizeof(symbol->text)) { + if (j + 2 >= ARRAY_SIZE(symbol->text)) { warn_number = ZINT_WARN_HRT_TRUNCATED; break; } @@ -762,10 +751,11 @@ INTERNAL int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char s symbol->text[j++] = source[i] - 0x40; } } - if (j == sizeof(symbol->text)) { + if (j == ARRAY_SIZE(symbol->text)) { warn_number = ZINT_WARN_HRT_TRUNCATED; j--; } + symbol->text_length = j; symbol->text[j] = '\0'; if (warn_number) { @@ -774,6 +764,79 @@ INTERNAL int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char s return warn_number; } +/* No-check as-is copy of ASCII into `symbol->text`, assuming `length` fits */ +INTERNAL void hrt_cpy_nochk(struct zint_symbol *symbol, const unsigned char source[], const int length) { + assert(length < ARRAY_SIZE(symbol->text)); + + memcpy(symbol->text, source, length); + symbol->text_length = length; + symbol->text[length] = '\0'; +} + +/* Copy a single ASCII character into `symbol->text` (i.e. replaces content) */ +INTERNAL void hrt_cpy_chr(struct zint_symbol *symbol, const char ch) { + symbol->text[0] = ch; + symbol->text_length = 1; + symbol->text[1] = '\0'; +} + +/* No-check as-is append of ASCII to `symbol->text`, assuming current `symbol->text_length` + `length` fits */ +INTERNAL void hrt_cat_nochk(struct zint_symbol *symbol, const unsigned char source[], const int length) { + assert(symbol->text_length + length < ARRAY_SIZE(symbol->text)); + + memcpy(symbol->text + symbol->text_length, source, length); + symbol->text_length += length; + symbol->text[symbol->text_length] = '\0'; +} + +/* No-check append of `ch` to `symbol->text`, assuming current `symbol->text_length` + 1 fits */ +INTERNAL void hrt_cat_chr_nochk(struct zint_symbol *symbol, const char ch) { + assert(symbol->text_length + 1 < ARRAY_SIZE(symbol->text)); + + symbol->text[symbol->text_length++] = (const unsigned char) ch; + symbol->text[symbol->text_length] = '\0'; +} + +/* No-check `sprintf()` into `symbol->text`, assuming it fits */ +INTERNAL void hrt_printf_nochk(struct zint_symbol *symbol, const char *fmt, ...) { + va_list ap; + int size; + + va_start(ap, fmt); + + size = vsprintf((char *) symbol->text, fmt, ap); + + assert(size >= 0); + assert(size < ARRAY_SIZE(symbol->text)); + + symbol->text_length = size; + + va_end(ap); +} + +/* No-check copy of `source` into `symbol->text`, converting GS1 square brackets into round ones. Assumes it fits */ +INTERNAL void hrt_conv_gs1_brackets_nochk(struct zint_symbol *symbol, const unsigned char source[], + const int length) { + int i; + int bracket_level = 0; /* Non-compliant closing square brackets may be in text */ + + assert(length < ARRAY_SIZE(symbol->text)); + + for (i = 0; i < length; i++) { + if (source[i] == '[') { + symbol->text[i] = '('; + bracket_level++; + } else if (source[i] == ']' && bracket_level) { + symbol->text[i] = ')'; + bracket_level--; + } else { + symbol->text[i] = source[i]; + } + } + symbol->text_length = length; + symbol->text[length] = '\0'; +} + /* Sets symbol height, returning a warning if not within minimum and/or maximum if given. `default_height` does not include height of fixed-height rows (i.e. separators/composite data) */ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height, const float default_height, @@ -882,7 +945,7 @@ INTERNAL char *debug_print_escape(const unsigned char *source, const int first_l int j = 0; for (i = 0; i < first_len; i++) { const unsigned char ch = source[i]; - if (ch < 32 || ch >= 127) { + if (z_iscntrl(ch) || !z_isascii(ch)) { j += sprintf(buf + j, "\\x%02X", ch & 0xFF); } else { buf[j++] = ch; @@ -892,7 +955,7 @@ INTERNAL char *debug_print_escape(const unsigned char *source, const int first_l } else { for (i = 0; i < first_len; i++) { const unsigned char ch = source[i]; - if (ch < 32 || ch >= 127) { + if (z_iscntrl(ch) || !z_isascii(ch)) { printf("\\x%02X", ch & 0xFF); } else { fputc(ch, stdout); @@ -911,7 +974,7 @@ INTERNAL char *debug_print_escape(const unsigned char *source, const int first_l /* Dumps hex-formatted codewords in symbol->errtxt (for use in testing) */ INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigned char *codewords, const int length) { int i, max = length, cnt_len = 0; - assert(sizeof(symbol->errtxt) >= 100); + assert(ARRAY_SIZE(symbol->errtxt) >= 100); if (length > 30) { /* 30*3 < errtxt 92 (100 - "Warning ") chars */ sprintf(symbol->errtxt, "(%d) ", length); /* Place the number of codewords at the front */ cnt_len = (int) strlen(symbol->errtxt); @@ -927,7 +990,7 @@ INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigne INTERNAL void debug_test_codeword_dump_short(struct zint_symbol *symbol, const short *codewords, const int length) { int i, max = 0, cnt_len, errtxt_len; char temp[20]; - assert(sizeof(symbol->errtxt) >= 100); + assert(ARRAY_SIZE(symbol->errtxt) >= 100); errtxt_len = sprintf(symbol->errtxt, "(%d) ", length); /* Place the number of codewords at the front */ for (i = 0, cnt_len = errtxt_len; i < length; i++) { cnt_len += sprintf(temp, "%d ", codewords[i]); @@ -946,7 +1009,7 @@ INTERNAL void debug_test_codeword_dump_short(struct zint_symbol *symbol, const s INTERNAL void debug_test_codeword_dump_int(struct zint_symbol *symbol, const int *codewords, const int length) { int i, max = 0, cnt_len, errtxt_len; char temp[20]; - assert(sizeof(symbol->errtxt) >= 100); + assert(ARRAY_SIZE(symbol->errtxt) >= 100); errtxt_len = sprintf(symbol->errtxt, "(%d) ", length); /* Place the number of codewords at the front */ for (i = 0, cnt_len = errtxt_len; i < length; i++) { cnt_len += sprintf(temp, "%d ", codewords[i]); diff --git a/backend/common.h b/backend/common.h index 8b5e908b..dcbf735f 100644 --- a/backend/common.h +++ b/backend/common.h @@ -140,15 +140,16 @@ typedef unsigned __int64 uint64_t; #define z_isdigit(c) ((c) <= '9' && (c) >= '0') #define z_isupper(c) ((c) >= 'A' && (c) <= 'Z') #define z_islower(c) ((c) >= 'a' && (c) <= 'z') +#define z_isascii(c) (((c) & 0x7F) == (c)) +#define z_iscntrl(c) (z_isascii(c) && ((c) < 32 || (c) == 127)) -/* Helpers to cast away char pointer signedness */ +/* Helper to cast away char pointer signedness */ #define ustrlen(source) strlen((const char *) (source)) -#define ustrcpy(target, source) strcpy((char *) (target), (const char *) (source)) -#define ustrcat(target, source) strcat((char *) (target), (const char *) (source)) -#define ustrncat(target, source, count) strncat((char *) (target), (const char *) (source), (count)) /* Converts an integer value to its value + '0' (so >= 10 becomes ':', ';' etc) */ #define itoc(i) ((i) + '0') +/* Converts an integer value to its hexadecimal digit */ +#define xtoc(i) ((i) < 10 ? itoc(i) : ((i) - 10) + 'A') /* Converts a character 0-9, A-F to its equivalent integer value */ INTERNAL int ctoi(const char source); @@ -299,9 +300,28 @@ INTERNAL int utf8_to_unicode(struct zint_symbol *symbol, const unsigned char sou int *length, const int disallow_4byte); /* Treats source as ISO/IEC 8859-1 and copies into `symbol->text`, converting to UTF-8. Control chars (incl. DEL) and - non-ISO/IEC 8859-1 (0x80-9F) are replaced with spaces. Returns warning if truncated, else 0 */ + non-ISO/IEC 8859-1 (0x80-9F) are replaced with spaces, unless BARCODE_PLAIN_HRT set in `output_options`. + Returns warning if truncated, else 0 */ INTERNAL int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char source[], const int length); +/* No-check as-is copy of ASCII into `symbol->text`, assuming `length` fits */ +INTERNAL void hrt_cpy_nochk(struct zint_symbol *symbol, const unsigned char source[], const int length); + +/* Copy a single ASCII character into `symbol->text` (i.e. replaces content) */ +INTERNAL void hrt_cpy_chr(struct zint_symbol *symbol, const char ch); + +/* No-check as-is append of ASCII to `symbol->text`, assuming current `symbol->text_length` + `length` fits */ +INTERNAL void hrt_cat_nochk(struct zint_symbol *symbol, const unsigned char source[], const int length); + +/* No-check append of `ch` to `symbol->text`, assuming current `symbol->text_length` + 1 fits */ +INTERNAL void hrt_cat_chr_nochk(struct zint_symbol *symbol, const char ch); + +/* No-check `sprintf()` into `symbol->text`, assuming it fits */ +INTERNAL void hrt_printf_nochk(struct zint_symbol *symbol, const char *fmt, ...) ZINT_FORMAT_PRINTF(2, 3); + +/* No-check copy of `source` into `symbol->text`, converting GS1 square brackets into round ones. Assumes it fits */ +INTERNAL void hrt_conv_gs1_brackets_nochk(struct zint_symbol *symbol, const unsigned char source[], const int length); + /* Sets symbol height, returning a warning if not within minimum and/or maximum if given. `default_height` does not include height of fixed-height rows (i.e. separators/composite data) */ diff --git a/backend/composite.c b/backend/composite.c index 686fc8f6..302979ae 100644 --- a/backend/composite.c +++ b/backend/composite.c @@ -62,7 +62,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int const int cc_rows); INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); -INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], +INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], const int length, unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part, unsigned char *zsecond_part); @@ -1210,20 +1210,19 @@ static int cc_binary_string(struct zint_symbol *symbol, const unsigned char sour } /* Calculate the width of the linear part (primary) */ -static int cc_linear_dummy_run(int input_mode, unsigned char *source, const int length, const int debug, - char *errtxt) { +static int cc_linear_dummy_run(struct zint_symbol *symbol, unsigned char *source, const int length) { struct zint_symbol dummy = {0}; int error_number; int linear_width; dummy.symbology = BARCODE_GS1_128_CC; dummy.option_1 = -1; - dummy.input_mode = input_mode; - dummy.debug = debug; + dummy.input_mode = symbol->input_mode; + dummy.debug = symbol->debug; error_number = gs1_128_cc(&dummy, source, length, 3 /*cc_mode*/, 0 /*cc_rows*/); linear_width = dummy.width; - if (error_number >= ZINT_ERROR || (debug & ZINT_DEBUG_TEST)) { - strcpy(errtxt, dummy.errtxt); + if (error_number >= ZINT_ERROR || (symbol->debug & ZINT_DEBUG_TEST)) { + (void) errtxt(0, symbol, -1, dummy.errtxt); } if (error_number >= ZINT_ERROR) { @@ -1268,8 +1267,7 @@ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int l if (symbol->symbology == BARCODE_GS1_128_CC) { /* Do a test run of encoding the linear component to establish its width */ - linear_width = cc_linear_dummy_run(symbol->input_mode, (unsigned char *) symbol->primary, pri_len, - symbol->debug, symbol->errtxt); + linear_width = cc_linear_dummy_run(symbol, (unsigned char *) symbol->primary, pri_len); if (linear_width == 0) { return errtxt_adj(ZINT_ERROR_INVALID_DATA, symbol, "%1$s%2$s", " (linear component)"); } @@ -1285,8 +1283,8 @@ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int l int padded_pri_len; int with_addon; unsigned char padded_pri[21]; - if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon, NULL, - NULL)) { + if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, pri_len, padded_pri, &with_addon, + NULL, NULL)) { return errtxt_adj(ZINT_ERROR_TOO_LONG, symbol, "%1$s%2$s", " (linear component)"); } padded_pri_len = (int) ustrlen(padded_pri); @@ -1448,7 +1446,7 @@ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int l switch (symbol->symbology) { /* Determine horizontal alignment (according to section 12.3) */ case BARCODE_EANX_CC: - switch (ustrlen(linear->text)) { /* Use zero-padded length */ + switch (linear->text_length) { /* Use zero-padded length */ case 8: /* EAN-8 */ case 11: /* EAN-8 + 2 */ case 14: /* EAN-8 + 5 */ @@ -1580,7 +1578,7 @@ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int l } } - ustrcpy(symbol->text, linear->text); + hrt_cpy_nochk(symbol, linear->text, linear->text_length); ZBarcode_Delete(linear); diff --git a/backend/dmatrix.c b/backend/dmatrix.c index 53fd3342..60558a5f 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -761,9 +761,12 @@ static int dm_getEndMode(struct zint_symbol *symbol, const unsigned char *source } #if 0 -#define DM_TRACE -#endif #include "dmatrix_trace.h" +#else +#define DM_TRACE_Edges(px, s, l, p, v) +#define DM_TRACE_AddEdge(s, l, es, p, v, e) +#define DM_TRACE_NotAddEdge(s, l, es, p, v, ij, e) +#endif /* Return number of C40/TEXT codewords needed to encode characters in full batches of 3 (or less if EOD). The number of characters encoded is returned in `len` */ diff --git a/backend/dmatrix_trace.h b/backend/dmatrix_trace.h index f115f07d..170eaac3 100644 --- a/backend/dmatrix_trace.h +++ b/backend/dmatrix_trace.h @@ -1,7 +1,7 @@ /* dmatrix_trace.h - Trace routines for DM_COMPRESSION algorithm */ /* libzint - the open source barcode library - Copyright (C) 2021-2022 Robin Stuart + Copyright (C) 2021-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -33,12 +33,6 @@ #ifndef Z_DMATRIX_TRACE_H #define Z_DMATRIX_TRACE_H -#ifndef DM_TRACE -#define DM_TRACE_Edges(px, s, l, p, v) -#define DM_TRACE_AddEdge(s, l, es, p, v, e) -#define DM_TRACE_NotAddEdge(s, l, es, p, v, ij, e) -#else - static int DM_TRACE_getPreviousMode(struct dm_edge *edges, struct dm_edge *edge) { struct dm_edge *previous = DM_PREVIOUS(edges, edge); return previous == NULL ? DM_ASCII : previous->endMode; @@ -70,8 +64,9 @@ static void DM_TRACE_EdgeToString(char *buf, const unsigned char *source, const static void DM_TRACE_Path(const unsigned char *source, const int length, struct dm_edge *edges, struct dm_edge *edge, char *result, const int result_size) { + struct dm_edge *current; DM_TRACE_EdgeToString(result, source, length, edges, edge); - struct dm_edge *current = DM_PREVIOUS(edges, edge); + current = DM_PREVIOUS(edges, edge); while (current) { char s[256]; char *pos; @@ -81,8 +76,7 @@ static void DM_TRACE_Path(const unsigned char *source, const int length, struct assert(pos); len = strlen(result); if ((pos - s) + 1 + len + 1 >= result_size) { - result[result_size - 4] = '\0'; - strcat(result, "..."); + memcpy(result + result_size - 4, "...", 4); /* Include terminating NUL */ break; } memmove(result + (pos - s) + 1, result, len + 1); @@ -150,6 +144,5 @@ static void DM_TRACE_NotAddEdge(const unsigned char *source, const int length, s } } -#endif /* DM_TRACE */ /* vim: set ts=4 sw=4 et : */ #endif /* Z_DMATRIX_TRACE_H */ diff --git a/backend/dxfilmedge.c b/backend/dxfilmedge.c index 868d6f89..16e680e8 100644 --- a/backend/dxfilmedge.c +++ b/backend/dxfilmedge.c @@ -52,25 +52,17 @@ #define DX_MAX_FRAME_INFO_LENGTH 3 #define DX_MAX_FRAME_INFO_MAX_STR "3" /* String version of above */ -static void dx_int_to_binary(const int value, const int width, char *output) { - int i; - for (i = 0; i < width; i++) { - output[width - 1 - i] = (value & (1 << i)) ? '1' : '0'; - } - output[width] = '\0'; -} - static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source, const int length, char *binary_output, int *output_length, int *has_frame_info) { int i; int parity_bit = 0; - int dx_extract = -1, dx_code_1 = -1, dx_code_2 = -1, frame_number = -1; - char binary_dx_code_1[8], binary_dx_code_2[5], binary_frame_number[7]; + int dx_code_1 = -1, dx_code_2 = -1, frame_number = -1; + int bp; char half_frame_flag = '\0'; - char dx_info[DX_MAX_DX_INFO_LENGTH + 1] = "\0"; - char frame_info[DX_MAX_FRAME_INFO_LENGTH + 1] = "\0"; + char dx_info[DX_MAX_DX_INFO_LENGTH + 1] = {0}; + char frame_info[DX_MAX_FRAME_INFO_LENGTH + 1] = {0}; int dx_length; - const char *frame_start; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; *has_frame_info = 0; @@ -85,20 +77,20 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source dx_length = posn((const char *) source, '/'); if (dx_length != -1) { /* Split the DX information from the frame number */ + const char *frame_start; int frame_info_len; if (dx_length > DX_MAX_DX_INFO_LENGTH) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 971, "DX information length %d too long (maximum " DX_MAX_DX_INFO_MAX_STR ")", dx_length); } - ustrncat(dx_info, source, dx_length); - dx_info[dx_length] = '\0'; + memcpy(dx_info, source, dx_length); frame_start = (const char *) source + dx_length + 1; frame_info_len = (int) strlen(frame_start); if (frame_info_len > DX_MAX_FRAME_INFO_LENGTH) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 972, "Frame number part length %d too long (maximum " DX_MAX_FRAME_INFO_MAX_STR ")", frame_info_len); } - ustrcpy(frame_info, frame_start); + memcpy(frame_info, frame_start, frame_info_len); *has_frame_info = 1; to_upper((unsigned char *) frame_info, frame_info_len); if (not_sane(IS_UPR_F | IS_NUM_F | IS_MNS_F, (const unsigned char *) frame_info, frame_info_len)) { @@ -113,7 +105,7 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 974, "DX information length %d too long (maximum " DX_MAX_DX_INFO_MAX_STR ")", dx_length); } - ustrcpy(dx_info, source); + memcpy(dx_info, source, dx_length); } if ((i = not_sane(IS_NUM_F | IS_MNS_F, (const unsigned char *) dx_info, dx_length))) { @@ -143,6 +135,7 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source dx_code_2); } } else { + int dx_extract; /* DX format is either 4 digits (DX Extract, eg: 1271) or 6 digits (DX Full, eg: 012710) */ if (debug_print) printf("No \"-\" separator, computing from DX Extract (4 digits) or DX Full (6 digits)\n"); if (dx_length == 5 || dx_length > 6) { @@ -157,7 +150,6 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source for (i = 0; i <= 3; ++i) { dx_info[i] = dx_info[i + 1]; } - dx_info[4] = '\0'; dx_length = 4; } /* Compute the DX parts 1 and 2 from the DX extract */ @@ -172,13 +164,9 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source dx_code_2 = dx_extract % 16; } - /* Convert components to binary strings */ - dx_int_to_binary(dx_code_1, 7, binary_dx_code_1); - dx_int_to_binary(dx_code_2, 4, binary_dx_code_2); - if (debug_print) { - printf("%-*s%d\t-> %s\n", DX_DEBUG_STR_LEN, "DX code 1:", dx_code_1, binary_dx_code_1); - printf("%-*s%d\t-> %s\n", DX_DEBUG_STR_LEN, "DX code 2:", dx_code_2, binary_dx_code_2); + printf("%-*s%d\n", DX_DEBUG_STR_LEN, "DX code 1:", dx_code_1); + printf("%-*s%d\n", DX_DEBUG_STR_LEN, "DX code 2:", dx_code_2); } if (*has_frame_info) { @@ -190,17 +178,17 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source } /* Some frame numbers are special values, convert them their equivalent number */ if (strcmp(frame_info, "S") == 0 || strcmp(frame_info, "X") == 0) { - strcpy(frame_info, "62"); + memcpy(frame_info, "62", 3); /* Include terminating NUL */ } else if (strcmp(frame_info, "SA") == 0 || strcmp(frame_info, "XA") == 0) { - strcpy(frame_info, "62A"); + memcpy(frame_info, "62A", 4); } else if (strcmp(frame_info, "K") == 0 || strcmp(frame_info, "00") == 0) { - strcpy(frame_info, "63"); + memcpy(frame_info, "63", 3); } else if (strcmp(frame_info, "KA") == 0 || strcmp(frame_info, "00A") == 0) { - strcpy(frame_info, "63A"); + memcpy(frame_info, "63A", 4); } else if (strcmp(frame_info, "F") == 0) { - strcpy(frame_info, "0"); + memcpy(frame_info, "0", 2); } else if (strcmp(frame_info, "FA") == 0) { - strcpy(frame_info, "0A"); + memcpy(frame_info, "0A", 3); } ret_sscanf = sscanf(frame_info, "%d%c%n", &frame_number, &half_frame_flag, &n); @@ -213,23 +201,22 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 984, "Frame number \"%d\" out of range (0 to 63)", frame_number); } - dx_int_to_binary(frame_number, 6, binary_frame_number); if (debug_print) { - printf("%-*s%d\t-> %s\n", DX_DEBUG_STR_LEN, "Frame number:", frame_number, binary_frame_number); + printf("%-*s%d\n", DX_DEBUG_STR_LEN, "Frame number:", frame_number); } } /* Build the binary output */ - strcpy(binary_output, "101010"); /* Start pattern */ - strcat(binary_output, binary_dx_code_1); - strcat(binary_output, "0"); /* Separator between DX part 1 and DX part 2 */ - strcat(binary_output, binary_dx_code_2); + memcpy(binary_output, "101010", 6); /* Start pattern */ + bp = bin_append_posn(dx_code_1, 7, binary_output, 6); + binary_output[bp++] = '0'; /* Separator between DX part 1 and DX part 2 */ + bp = bin_append_posn(dx_code_2, 4, binary_output, bp); if (*has_frame_info) { - strcat(binary_output, binary_frame_number); + bp = bin_append_posn(frame_number, 6, binary_output, bp); to_upper((unsigned char *) &half_frame_flag, 1); if (half_frame_flag == 'A') { if (debug_print) printf("%-*s'%c'\t-> 1\n", DX_DEBUG_STR_LEN, "Half frame flag:", half_frame_flag); - strcat(binary_output, "1"); /* Half-frame is set */ + binary_output[bp++] = '1'; /* Half-frame is set */ } else { if (half_frame_flag) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 985, @@ -237,70 +224,69 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source frame_info); } if (debug_print) printf("%-*s'%c'\t-> 0\n", DX_DEBUG_STR_LEN, "Half frame flag:", half_frame_flag); - strcat(binary_output, "0"); /* Half-frame is NOT set */ + binary_output[bp++] = '0'; /* Half-frame is NOT set */ } - strcat(binary_output, "0"); /* Separator between half frame flag and parity bit*/ + binary_output[bp++] = '0'; /* Separator between half frame flag and parity bit*/ } /* Parity bit */ - for (i = 6; binary_output[i] != '\0'; i++) { + for (i = 6; i < bp; i++) { if (binary_output[i] == '1') { - parity_bit++; + parity_bit ^= 1; } } - parity_bit %= 2; if (debug_print) { printf("%-*s%s\t-> %d\n", DX_DEBUG_STR_LEN, "Parity bit:", parity_bit ? "yes" : "no", parity_bit); } - if (parity_bit) { - strcat(binary_output, "1"); - } else { - strcat(binary_output, "0"); + binary_output[bp++] = parity_bit ? '1' : '0'; + + memcpy(binary_output + bp, "0101", 4); /* Stop pattern */ + bp += 4; + + *output_length = bp; + + if (plain_hrt) { + hrt_printf_nochk(symbol, "%04d%s", (dx_code_1 << 4) | dx_code_2, frame_info); } - strcat(binary_output, "0101"); /* Stop pattern */ - - *output_length = (int) strlen(binary_output); return 0; } INTERNAL int dxfilmedge(struct zint_symbol *symbol, unsigned char source[], int length) { int i; int writer = 0; - int error_number = 0; + int error_number; - char char_data[32]; - int data_length; + char binary_output[32]; + int output_length; int has_frame_info; const char long_clock_pattern[] = "1111101010101010101010101010111"; const char short_clock_pattern[] = "11111010101010101010111"; const char *clock_pattern; - int clock_length; - int parse_result = -1; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; if (length > 10) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 986, "Input length %d too long (maximum 10)", length); } - parse_result = dx_parse_code(symbol, source, length, char_data, &data_length, &has_frame_info); - if (parse_result != 0) { + error_number = dx_parse_code(symbol, source, length, binary_output, &output_length, &has_frame_info); + if (error_number != 0) { if (debug_print) printf("Error %s\n\n", symbol->errtxt); - return parse_result; + return error_number; } /* Clock signal is longer if the frame number is provided */ if (has_frame_info) { clock_pattern = long_clock_pattern; - clock_length = sizeof(long_clock_pattern) -1; + assert(output_length == (int) sizeof(long_clock_pattern) - 1); } else { clock_pattern = short_clock_pattern; - clock_length = sizeof(short_clock_pattern) -1; + assert(output_length == (int) sizeof(short_clock_pattern) - 1); } /* First row: clock pattern */ - for (i = 0; i < clock_length; i++) { + for (i = 0; i < output_length; i++) { if (clock_pattern[i] == '1') { set_module(symbol, 0, writer); } else if (clock_pattern[i] == '0') { @@ -313,16 +299,16 @@ INTERNAL int dxfilmedge(struct zint_symbol *symbol, unsigned char source[], int writer = 0; /* Second row: data signal */ - for (i = 0; i < clock_length; i++) { - if (char_data[i] == '1') { + for (i = 0; i < output_length; i++) { + if (binary_output[i] == '1') { set_module(symbol, 1, writer); - } else if (char_data[i] == '0') { + } else if (binary_output[i] == '0') { unset_module(symbol, 1, writer); } writer++; } symbol->rows = 2; - symbol->width = clock_length; + symbol->width = output_length; if (symbol->output_options & COMPLIANT_HEIGHT) { /* Measured ratio on 35mm films. Depending on the brands, one symbol height is about 3 * the X-dim.*/ diff --git a/backend/gs1.c b/backend/gs1.c index 85cbdadb..7acc21d1 100644 --- a/backend/gs1.c +++ b/backend/gs1.c @@ -31,12 +31,41 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include #include "common.h" #include "gs1.h" /* gs1_lint() validators and checkers */ +/* Set `err_msg`, returning 0 for convenience */ +static int gs1_err_msg_cpy_nochk(char err_msg[50], const char *msg) { + const int length = (int) strlen(msg); + + assert(length < 50); + memcpy(err_msg, msg, length + 1); /* Include terminating NUL */ + + return 0; +} + +/* sprintf into `err_msg`, returning 0 for convenience */ +ZINT_FORMAT_PRINTF(2, 3) static int gs1_err_msg_printf_nochk(char err_msg[50], const char *fmt, ...) { + va_list ap; + int size; + + va_start(ap, fmt); + + size = vsprintf(err_msg, fmt, ap); + + (void)size; + assert(size >= 0); + assert(size < 50); + + va_end(ap); + + return 0; +} + /* Validate numeric */ static int numeric(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, int *p_err_posn, char err_msg[50]) { @@ -55,8 +84,7 @@ static int numeric(const unsigned char *data, int data_len, int offset, int min, if (!z_isdigit(*d)) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Non-numeric character '%c'", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Non-numeric character '%c'", *d); } } } @@ -93,8 +121,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min, if (*d < '!' || *d > 'z' || c82[*d - '!'] == 82) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Invalid CSET 82 character '%c'", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid CSET 82 character '%c'", *d); } } } @@ -121,8 +148,7 @@ static int cset39(const unsigned char *data, int data_len, int offset, int min, if ((*d < '0' && *d != '#' && *d != '-' && *d != '/') || (*d > '9' && *d < 'A') || *d > 'Z') { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Invalid CSET 39 character '%c'", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid CSET 39 character '%c'", *d); } } } @@ -154,8 +180,7 @@ static int cset64(const unsigned char *data, int data_len, int offset, int min, } *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Invalid CSET 64 character '%c'", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid CSET 64 character '%c'", *d); } } } @@ -190,8 +215,7 @@ static int csum(const unsigned char *data, int data_len, int offset, int min, in if (checksum != *d - '0') { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Bad checksum '%c', expected '%c'", *d, checksum + '0'); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Bad checksum '%c', expected '%c'", *d, checksum + '0'); } } @@ -233,10 +257,10 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi *p_err_no = 3; if (de[0] != c1) { *p_err_posn = (de - data) + 1; - sprintf(err_msg, "Bad checksum '%c', expected '%c'", de[0], c1); + (void) gs1_err_msg_printf_nochk(err_msg, "Bad checksum '%c', expected '%c'", de[0], c1); } else { *p_err_posn = (de + 1 - data) + 1; - sprintf(err_msg, "Bad checksum '%c', expected '%c'", de[1], c2); + (void) gs1_err_msg_printf_nochk(err_msg, "Bad checksum '%c', expected '%c'", de[1], c2); } return 0; } @@ -269,8 +293,7 @@ static int key(const unsigned char *data, int data_len, int offset, int min, int if (data_len < GS1_GCP_MIN_LENGTH) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "GS1 Company Prefix length %d too short (minimum 4)", data_len); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "GS1 Company Prefix length %d too short (minimum 4)", data_len); } data += offset; @@ -279,8 +302,7 @@ static int key(const unsigned char *data, int data_len, int offset, int min, int if (!z_isdigit(data[i])) { *p_err_no = 3; *p_err_posn = offset + i + 1; - sprintf(err_msg, "Non-numeric company prefix '%c'", data[i]); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Non-numeric company prefix '%c'", data[i]); } } } @@ -318,16 +340,14 @@ static int yyyymmd0(const unsigned char *data, int data_len, int offset, int min if (month == 0 || month > 12) { *p_err_no = 3; *p_err_posn = offset + 4 + 1; - sprintf(err_msg, "Invalid month '%.2s'", data + offset + 4); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid month '%.2s'", data + offset + 4); } day = to_int(data + offset + 6, 2); if (day && day > days_in_month[month]) { *p_err_no = 3; *p_err_posn = offset + 6 + 1; - sprintf(err_msg, "Invalid day '%.2s'", data + offset + 6); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid day '%.2s'", data + offset + 6); } /* Leap year check */ if (month == 2 && day == 29) { @@ -335,8 +355,7 @@ static int yyyymmd0(const unsigned char *data, int data_len, int offset, int min if ((year & 3) || (year % 100 == 0 && year % 400 != 0)) { *p_err_no = 3; *p_err_posn = offset + 6 + 1; - sprintf(err_msg, "Invalid day '%.2s'", data + offset + 6); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid day '%.2s'", data + offset + 6); } } } @@ -359,8 +378,7 @@ static int yyyymmdd(const unsigned char *data, int data_len, int offset, int min if (day == 0) { *p_err_no = 3; *p_err_posn = offset + 6 + 1; - sprintf(err_msg, "Invalid day '%.2s'", data + offset + 6); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid day '%.2s'", data + offset + 6); } } @@ -407,8 +425,7 @@ static int yymmdd(const unsigned char *data, int data_len, int offset, int min, if (day == 0) { *p_err_no = 3; *p_err_posn = offset + 4 + 1; - sprintf(err_msg, "Invalid day '%.2s'", data + offset + 4); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid day '%.2s'", data + offset + 4); } } @@ -433,15 +450,13 @@ static int hhmi(const unsigned char *data, int data_len, int offset, int min, in if (hour > 23) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid hour of day '%.2s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid hour of day '%.2s'", data + offset); } mins = to_int(data + offset + 2, 2); if (mins > 59) { *p_err_no = 3; *p_err_posn = offset + 2 + 1; - sprintf(err_msg, "Invalid minutes in the hour '%.2s'", data + offset + 2); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid minutes in the hour '%.2s'", data + offset + 2); } } @@ -464,8 +479,7 @@ static int hh(const unsigned char *data, int data_len, int offset, int min, int if (hour > 23) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid hour of day '%.2s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid hour of day '%.2s'", data + offset); } } @@ -488,8 +502,7 @@ static int mi(const unsigned char *data, int data_len, int offset, int min, int if (mins > 59) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid minutes in the hour '%.2s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid minutes in the hour '%.2s'", data + offset); } } @@ -512,8 +525,7 @@ static int ss(const unsigned char *data, int data_len, int offset, int min, int if (secs > 59) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid seconds in the minute '%.2s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid seconds in the minute '%.2s'", data + offset); } } @@ -542,8 +554,7 @@ static int iso3166(const unsigned char *data, int data_len, int offset, int min, if (!iso3166_numeric(to_int(data + offset, 3))) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Unknown country code '%.3s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Unknown country code '%.3s'", data + offset); } } @@ -566,8 +577,7 @@ static int iso3166999(const unsigned char *data, int data_len, int offset, int m if (cc != 999 && !iso3166_numeric(cc)) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Unknown country code '%.3s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Unknown country code '%.3s'", data + offset); } } @@ -589,8 +599,7 @@ static int iso3166alpha2(const unsigned char *data, int data_len, int offset, in if (!iso3166_alpha2((const char *) (data + offset))) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Unknown country code '%.2s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Unknown country code '%.2s'", data + offset); } } @@ -615,8 +624,7 @@ static int iso4217(const unsigned char *data, int data_len, int offset, int min, if (!iso4217_numeric(to_int(data + offset, 3))) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Unknown currency code '%.3s'", data + offset); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Unknown currency code '%.3s'", data + offset); } } @@ -644,14 +652,12 @@ static int pcenc(const unsigned char *data, int data_len, int offset, int min, i if (de - d < 3) { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Invalid % escape"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid % escape"); } if (strchr(hex_chars, *(++d)) == NULL || strchr(hex_chars, *(++d)) == NULL) { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Invalid character for percent encoding"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid character for percent encoding"); } } } @@ -675,8 +681,7 @@ static int yesno(const unsigned char *data, int data_len, int offset, int min, i if (data[offset] != '0' && data[offset] != '1') { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Neither 0 nor 1 for yes or no"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Neither 0 nor 1 for yes or no"); } } @@ -701,8 +706,7 @@ static int importeridx(const unsigned char *data, int data_len, int offset, int if ((*d < '0' && *d != '-') || (*d > '9' && *d < 'A') || (*d > 'Z' && *d < 'a' && *d != '_') || *d > 'z') { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid importer index '%c'", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid importer index '%c'", *d); } } @@ -725,8 +729,7 @@ static int nonzero(const unsigned char *data, int data_len, int offset, int min, if (val == 0) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Zero not permitted"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Zero not permitted"); } } @@ -748,8 +751,7 @@ static int winding(const unsigned char *data, int data_len, int offset, int min, if (data[offset] != '0' && data[offset] != '1' && data[offset] != '9') { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid winding direction '%c'", data[offset]); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid winding direction '%c'", data[offset]); } } @@ -771,8 +773,7 @@ static int zero(const unsigned char *data, int data_len, int offset, int min, in if (data[offset] != '0') { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Zero is required"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Zero is required"); } } @@ -797,21 +798,19 @@ static int pieceoftotal(const unsigned char *data, int data_len, int offset, int if (pieces == 0) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Piece number cannot be zero"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Piece number cannot be zero"); } total = to_int(data + offset + 2, 2); if (total == 0) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Total number cannot be zero"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Total number cannot be zero"); } if (pieces > total) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Piece number '%.2s' exceeds total '%.2s'", data + offset, data + offset + 2); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Piece number '%.2s' exceeds total '%.2s'", + data + offset, data + offset + 2); } } @@ -843,22 +842,19 @@ static int iban(const unsigned char *data, int data_len, int offset, int min, in if (!z_isupper(d[0]) || !z_isupper(d[1])) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Non-alphabetic IBAN country code '%.2s'", d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Non-alphabetic IBAN country code '%.2s'", d); } if (!iso3166_alpha2((const char *) d)) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Invalid IBAN country code '%.2s'", d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid IBAN country code '%.2s'", d); } d += 2; /* 2nd 2 chars numeric checksum */ if (!z_isdigit(d[0]) || !z_isdigit(d[1])) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Non-numeric IBAN checksum '%.2s'", d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Non-numeric IBAN checksum '%.2s'", d); } given_checksum = to_int(d, 2); d += 2; @@ -867,8 +863,7 @@ static int iban(const unsigned char *data, int data_len, int offset, int min, in if (*d < '0' || (*d > '9' && *d < 'A') || *d > 'Z') { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Invalid IBAN character '%c'", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid IBAN character '%c'", *d); } if (*d >= 'A') { checksum = checksum * 100 + *d - 'A' + 10; @@ -890,8 +885,8 @@ static int iban(const unsigned char *data, int data_len, int offset, int min, in if (checksum != given_checksum) { *p_err_no = 3; *p_err_posn = offset + 2 + 1; - sprintf(err_msg, "Bad IBAN checksum '%.2s', expected '%02d'", data + offset + 2, checksum); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Bad IBAN checksum '%.2s', expected '%02d'", + data + offset + 2, checksum); } } @@ -915,8 +910,7 @@ static int nozeroprefix(const unsigned char *data, int data_len, int offset, int if (data[0] == '0' && data_len != 1) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Zero prefix is not permitted"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Zero prefix is not permitted"); } } @@ -934,7 +928,7 @@ static const unsigned char *coupon_vli(const unsigned char *data, const int data if (d - data + 1 > data_len) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "%s VLI missing", name); + (void) gs1_err_msg_printf_nochk(err_msg, "%s VLI missing", name); return NULL; } vli = to_int(d, 1); @@ -942,9 +936,9 @@ static const unsigned char *coupon_vli(const unsigned char *data, const int data *p_err_no = 3; *p_err_posn = d - data + 1; if (vli < 0) { - sprintf(err_msg, "Non-numeric %s VLI '%c'", name, *d); + (void) gs1_err_msg_printf_nochk(err_msg, "Non-numeric %s VLI '%c'", name, *d); } else { - sprintf(err_msg, "Invalid %s VLI '%c'", name, *d); + (void) gs1_err_msg_printf_nochk(err_msg, "Invalid %s VLI '%c'", name, *d); } return NULL; } @@ -953,7 +947,7 @@ static const unsigned char *coupon_vli(const unsigned char *data, const int data if (d - data + vli + vli_offset > data_len) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "%s incomplete", name); + (void) gs1_err_msg_printf_nochk(err_msg, "%s incomplete", name); return NULL; } de = d + vli + vli_offset; @@ -961,7 +955,7 @@ static const unsigned char *coupon_vli(const unsigned char *data, const int data if (!z_isdigit(*d)) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Non-numeric %s '%c'", name, *d); + (void) gs1_err_msg_printf_nochk(err_msg, "Non-numeric %s '%c'", name, *d); return NULL; } } @@ -978,14 +972,14 @@ static const unsigned char *coupon_val(const unsigned char *data, const int data if (d - data + val_len > data_len) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "%s incomplete", name); + (void) gs1_err_msg_printf_nochk(err_msg, "%s incomplete", name); return NULL; } val = to_int(d, val_len); if (val < 0) { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Non-numeric %s", name); + (void) gs1_err_msg_printf_nochk(err_msg, "Non-numeric %s", name); return NULL; } d += val_len; @@ -1028,34 +1022,30 @@ static int couponcode(const unsigned char *data, int data_len, int offset, int m data_len += offset; /* Required fields */ - d = coupon_vli(data, data_len, d, "Primary GS1 Co. Prefix", 6, 0, 6, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "Primary GS1 Co. Prefix", 6, 0, 6, 0, p_err_no, p_err_posn, + err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "Offer Code", 6, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Offer Code", 6, NULL, p_err_no, p_err_posn, err_msg))) { return 0; } - d = coupon_vli(data, data_len, d, "Save Value", 0, 1, 5, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "Save Value", 0, 1, 5, 0, p_err_no, p_err_posn, err_msg))) { return 0; } - d = coupon_vli(data, data_len, d, "Primary Purch. Req.", 0, 1, 5, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "Primary Purch. Req.", 0, 1, 5, 0, p_err_no, p_err_posn, err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "Primary Purch. Req. Code", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Primary Purch. Req. Code", 1, &val, p_err_no, p_err_posn, + err_msg))) { return 0; } if (val > 5 && val < 9) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid Primary Purch. Req. Code '%c'", *(d - 1)); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid Primary Purch. Req. Code '%c'", *(d - 1)); } - d = coupon_val(data, data_len, d, "Primary Purch. Family Code", 3, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Primary Purch. Family Code", 3, NULL, p_err_no, p_err_posn, + err_msg))) { return 0; } @@ -1066,70 +1056,64 @@ static int couponcode(const unsigned char *data, int data_len, int offset, int m if (data_field == 1) { - d = coupon_val(data, data_len, d, "Add. Purch. Rules Code", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Add. Purch. Rules Code", 1, &val, p_err_no, p_err_posn, + err_msg))) { return 0; } if (val > 3) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid Add. Purch. Rules Code '%c'", *(d - 1)); + return gs1_err_msg_printf_nochk(err_msg, "Invalid Add. Purch. Rules Code '%c'", *(d - 1)); + } + if (!(d = coupon_vli(data, data_len, d, "2nd Purch. Req.", 0, 1, 5, 0, p_err_no, p_err_posn, + err_msg))) { return 0; } - d = coupon_vli(data, data_len, d, "2nd Purch. Req.", 0, 1, 5, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { - return 0; - } - d = coupon_val(data, data_len, d, "2nd Purch. Req. Code", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "2nd Purch. Req. Code", 1, &val, p_err_no, p_err_posn, + err_msg))) { return 0; } if (val > 4 && val < 9) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid 2nd Purch. Req. Code '%c'", *(d - 1)); + return gs1_err_msg_printf_nochk(err_msg, "Invalid 2nd Purch. Req. Code '%c'", *(d - 1)); + } + if (!(d = coupon_val(data, data_len, d, "2nd Purch. Family Code", 3, NULL, p_err_no, p_err_posn, + err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "2nd Purch. Family Code", 3, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { - return 0; - } - d = coupon_vli(data, data_len, d, "2nd Purch. GS1 Co. Prefix", 6, 0, 6, 1, p_err_no, p_err_posn, - err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "2nd Purch. GS1 Co. Prefix", 6, 0, 6, 1, p_err_no, p_err_posn, + err_msg))) { return 0; } } else if (data_field == 2) { - d = coupon_vli(data, data_len, d, "3rd Purch. Req.", 0, 1, 5, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "3rd Purch. Req.", 0, 1, 5, 0, p_err_no, p_err_posn, + err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "3rd Purch. Req. Code", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "3rd Purch. Req. Code", 1, &val, p_err_no, p_err_posn, + err_msg))) { return 0; } if (val > 4 && val < 9) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid 3rd Purch. Req. Code '%c'", *(d - 1)); + return gs1_err_msg_printf_nochk(err_msg, "Invalid 3rd Purch. Req. Code '%c'", *(d - 1)); + } + if (!(d = coupon_val(data, data_len, d, "3rd Purch. Family Code", 3, NULL, p_err_no, p_err_posn, + err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "3rd Purch. Family Code", 3, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { - return 0; - } - d = coupon_vli(data, data_len, d, "3rd Purch. GS1 Co. Prefix", 6, 0, 6, 1, p_err_no, p_err_posn, - err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "3rd Purch. GS1 Co. Prefix", 6, 0, 6, 1, p_err_no, p_err_posn, + err_msg))) { return 0; } } else if (data_field == 3) { - d = coupon_val(data, data_len, d, "Expiration Date", 6, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Expiration Date", 6, NULL, p_err_no, p_err_posn, err_msg))) { return 0; } if (!yymmd0(data, data_len, d - 6 - data, 6, 6, p_err_no, p_err_posn, err_msg, 0)) { @@ -1138,8 +1122,7 @@ static int couponcode(const unsigned char *data, int data_len, int offset, int m } else if (data_field == 4) { - d = coupon_val(data, data_len, d, "Start Date", 6, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Start Date", 6, NULL, p_err_no, p_err_posn, err_msg))) { return 0; } if (!yymmd0(data, data_len, d - 6 - data, 6, 6, p_err_no, p_err_posn, err_msg, 0)) { @@ -1148,53 +1131,48 @@ static int couponcode(const unsigned char *data, int data_len, int offset, int m } else if (data_field == 5) { - d = coupon_vli(data, data_len, d, "Serial Number", 6, 0, 9, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "Serial Number", 6, 0, 9, 0, p_err_no, p_err_posn, + err_msg))) { return 0; } } else if (data_field == 6) { - d = coupon_vli(data, data_len, d, "Retailer ID", 6, 1, 7, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "Retailer ID", 6, 1, 7, 0, p_err_no, p_err_posn, err_msg))) { return 0; } } else if (data_field == 9) { - d = coupon_val(data, data_len, d, "Save Value Code", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Save Value Code", 1, &val, p_err_no, p_err_posn, err_msg))) { return 0; } if ((val > 2 && val < 5) || val > 6) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid Save Value Code '%c'", *(d - 1)); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid Save Value Code '%c'", *(d - 1)); } - d = coupon_val(data, data_len, d, "Save Value Applies To", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Save Value Applies To", 1, &val, p_err_no, p_err_posn, + err_msg))) { return 0; } if (val > 2) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid Save Value Applies To '%c'", *(d - 1)); + return gs1_err_msg_printf_nochk(err_msg, "Invalid Save Value Applies To '%c'", *(d - 1)); + } + if (!(d = coupon_val(data, data_len, d, "Store Coupon Flag", 1, NULL, p_err_no, p_err_posn, + err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "Store Coupon Flag", 1, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { - return 0; - } - d = coupon_val(data, data_len, d, "Don't Multiply Flag", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Don't Multiply Flag", 1, &val, p_err_no, p_err_posn, + err_msg))) { return 0; } if (val > 1) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - sprintf(err_msg, "Invalid Don't Multiply Flag '%c'", *(d - 1)); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid Don't Multiply Flag '%c'", *(d - 1)); } } else { @@ -1202,9 +1180,9 @@ static int couponcode(const unsigned char *data, int data_len, int offset, int m *p_err_no = 3; *p_err_posn = d - 1 - data + 1; if (data_field < 0) { - sprintf(err_msg, "Non-numeric Data Field '%c'", *(d - 1)); + (void) gs1_err_msg_printf_nochk(err_msg, "Non-numeric Data Field '%c'", *(d - 1)); } else { - sprintf(err_msg, "Invalid Data Field '%c'", *(d - 1)); + (void) gs1_err_msg_printf_nochk(err_msg, "Invalid Data Field '%c'", *(d - 1)); } return 0; } @@ -1243,33 +1221,27 @@ static int couponposoffer(const unsigned char *data, int data_len, int offset, i const unsigned char *d = data + offset; int val; - d = coupon_val(data, data_len, d, "Coupon Format", 1, &val, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Coupon Format", 1, &val, p_err_no, p_err_posn, err_msg))) { return 0; } if (val != 0 && val != 1) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - strcpy(err_msg, "Coupon Format must be 0 or 1"); + return gs1_err_msg_cpy_nochk(err_msg, "Coupon Format must be 0 or 1"); + } + if (!(d = coupon_vli(data, data_len, d, "Coupon Funder ID", 6, 0, 6, 0, p_err_no, p_err_posn, err_msg))) { return 0; } - d = coupon_vli(data, data_len, d, "Coupon Funder ID", 6, 0, 6, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_val(data, data_len, d, "Offer Code", 6, NULL, p_err_no, p_err_posn, err_msg))) { return 0; } - d = coupon_val(data, data_len, d, "Offer Code", 6, NULL, p_err_no, p_err_posn, err_msg); - if (d == NULL) { - return 0; - } - d = coupon_vli(data, data_len, d, "Serial Number", 6, 0, 9, 0, p_err_no, p_err_posn, err_msg); - if (d == NULL) { + if (!(d = coupon_vli(data, data_len, d, "Serial Number", 6, 0, 9, 0, p_err_no, p_err_posn, err_msg))) { return 0; } if (d - data != data_len) { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Reserved trailing characters"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Reserved trailing characters"); } } @@ -1298,8 +1270,7 @@ static int latitude(const unsigned char *data, int data_len, int offset, int min if (lat > 1800000000) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - strcpy(err_msg, "Invalid latitude"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid latitude"); } } @@ -1328,8 +1299,7 @@ static int longitude(const unsigned char *data, int data_len, int offset, int mi if (lng > 3600000000) { *p_err_no = 3; *p_err_posn = d - 1 - data + 1; - strcpy(err_msg, "Invalid longitude"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid longitude"); } } @@ -1358,8 +1328,7 @@ static int mediatype(const unsigned char *data, int data_len, int offset, int mi if (val == 0 || (val > 10 && val < 80)) { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Invalid AIDC media type"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid AIDC media type"); } } @@ -1384,8 +1353,7 @@ static int hyphen(const unsigned char *data, int data_len, int offset, int min, if (*d != '-') { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Invalid temperature indicator (hyphen only)"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid temperature indicator (hyphen only)"); } } } @@ -1409,8 +1377,7 @@ static int iso5218(const unsigned char *data, int data_len, int offset, int min, if (data[offset] != '0' && data[offset] != '1' && data[offset] != '2' && data[offset] != '9') { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Invalid biological sex code (0, 1, 2 or 9 only)"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Invalid biological sex code (0, 1, 2 or 9 only)"); } } @@ -1438,20 +1405,17 @@ static int posinseqslash(const unsigned char *data, int data_len, int offset, in if (*d != '/') { *p_err_no = 3; *p_err_posn = d - data + 1; - sprintf(err_msg, "Invalid character '%c' in sequence", *d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid character '%c' in sequence", *d); } if (slash) { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Single sequence separator ('/') only"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Single sequence separator ('/') only"); } if (d == data + offset || d + 1 == de) { *p_err_no = 3; *p_err_posn = d - data + 1; - strcpy(err_msg, "Sequence separator '/' cannot start or end"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Sequence separator '/' cannot start or end"); } slash = d; } @@ -1459,28 +1423,24 @@ static int posinseqslash(const unsigned char *data, int data_len, int offset, in if (!slash) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "No sequence separator ('/')"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "No sequence separator ('/')"); } pos = to_int(data + offset, slash - (data + offset)); if (pos == 0) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Sequence position cannot be zero"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Sequence position cannot be zero"); } tot = to_int(slash + 1, de - (slash + 1)); if (tot == 0) { *p_err_no = 3; *p_err_posn = slash + 1 - data + 1; - strcpy(err_msg, "Sequence total cannot be zero"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Sequence total cannot be zero"); } if (pos > tot) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "Sequence position greater than total"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "Sequence position greater than total"); } } @@ -1507,8 +1467,7 @@ static int hasnondigit(const unsigned char *data, int data_len, int offset, int if (d == de) { *p_err_no = 3; *p_err_posn = offset + 1; - strcpy(err_msg, "A non-digit character is required"); - return 0; + return gs1_err_msg_cpy_nochk(err_msg, "A non-digit character is required"); } } @@ -1630,8 +1589,7 @@ static int packagetype(const unsigned char *data, int data_len, int offset, int if (!valid) { *p_err_no = 3; *p_err_posn = offset + 1; - sprintf(err_msg, "Invalid package type '%.*s'", data_len, d); - return 0; + return gs1_err_msg_printf_nochk(err_msg, "Invalid package type '%.*s'", data_len, d); } } @@ -1643,7 +1601,7 @@ static int packagetype(const unsigned char *data, int data_len, int offset, int /* Verify a GS1 input string */ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const int length, - unsigned char reduced[]) { + unsigned char reduced[], int *p_reduced_length) { int i, j; int error_value = 0; int bracket_level = 0, max_bracket_level = 0; @@ -1837,6 +1795,7 @@ INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[] } } reduced[j] = '\0'; + *p_reduced_length = j; /* The character '\x1D' (GS) in the reduced string refers to the FNC1 character */ return error_value; diff --git a/backend/gs1.h b/backend/gs1.h index d895d3d0..571f3eb3 100644 --- a/backend/gs1.h +++ b/backend/gs1.h @@ -1,7 +1,7 @@ /* gs1.h - Verifies GS1 data */ /* libzint - the open source barcode library - Copyright (C) 2009-2022 Robin Stuart + Copyright (C) 2009-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -37,9 +37,9 @@ extern "C" { #endif /* __cplusplus */ -INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const int src_len, - unsigned char reduced[]); -INTERNAL char gs1_check_digit(const unsigned char source[], const int src_len); +INTERNAL int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const int length, + unsigned char reduced[], int *p_reduced_length); +INTERNAL char gs1_check_digit(const unsigned char source[], const int length); INTERNAL int gs1_iso3166_alpha2(const unsigned char *cc); #ifdef __cplusplus diff --git a/backend/imail.c b/backend/imail.c index 820b2a15..29e5a503 100644 --- a/backend/imail.c +++ b/backend/imail.c @@ -30,6 +30,10 @@ */ /* SPDX-License-Identifier: BSD-3-Clause */ +/* USPS-B-3200 - Intelligent Mail Barcode 4-State 2015-04-20 Rev H + https://postalpro.usps.com/storages/2017-08/2190_USPSB3200IntelligentMailBarcode4State_0.pdf +*/ + /* The function "USPS_MSB_Math_CRC11GenerateFrameCheckSequence" is Copyright (C) 2006 United States Postal Service */ @@ -38,9 +42,9 @@ #define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */ -/* The following lookup tables were generated using the code in Appendix C */ +/* The following lookup tables were generated using the code in USPS-B-3200 Appendix C */ -/* Appendix D Table 1 - 5 of 13 characters */ +/* USPS-B-3200 Appendix D Table 1 - 5 of 13 characters */ static const unsigned short AppxD_I[1287] = { 0x001F, 0x1F00, 0x002F, 0x1E80, 0x0037, 0x1D80, 0x003B, 0x1B80, 0x003D, 0x1780, 0x003E, 0x0F80, 0x004F, 0x1E40, 0x0057, 0x1D40, 0x005B, 0x1B40, 0x005D, 0x1740, @@ -173,7 +177,7 @@ static const unsigned short AppxD_I[1287] = { 0x08E2, 0x064C, 0x0554, 0x04E4, 0x0358, 0x02E8, 0x01F0 }; -/* Appendix D Table II - 2 of 13 characters */ +/* USPS-B-3200 Appendix D Table II - 2 of 13 characters */ static const unsigned short AppxD_II[78] = { 0x0003, 0x1800, 0x0005, 0x1400, 0x0006, 0x0C00, 0x0009, 0x1200, 0x000A, 0x0A00, 0x000C, 0x0600, 0x0011, 0x1100, 0x0012, 0x0900, 0x0014, 0x0500, 0x0018, 0x0300, @@ -185,7 +189,7 @@ static const unsigned short AppxD_II[78] = { 0x0801, 0x1002, 0x1001, 0x0802, 0x0404, 0x0208, 0x0110, 0x00A0 }; -/* Appendix D Table IV - Bar-to-Character Mapping (reverse lookup) */ +/* USPS-B-3200 Appendix D Table IV - Bar-to-Character Mapping (reverse lookup) */ static const unsigned char AppxD_IV[130] = { 67, 6, 78, 16, 86, 95, 34, 40, 45, 113, 117, 121, 62, 87, 18, 104, 41, 76, 57, 119, 115, 72, 97, 2, 127, 26, 105, 35, 122, 52, 114, 7, 24, 82, 68, 63, 94, 44, 77, 112, @@ -248,7 +252,7 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int int error_number = 0; int i, j, read; char tracker[33] = {0}; /* Zero to prevent false warning from clang-tidy */ - char zip[33], temp[2]; + char zip[33]; large_uint accum; large_uint byte_array_reg; unsigned char byte_array[13]; @@ -256,7 +260,8 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int unsigned int codeword[10]; unsigned short characters[10]; short bar_map[130]; - int zip_len, len; + int zip_len; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 32) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 450, "Input length %d too long (maximum 32)", length); @@ -397,29 +402,22 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int /* *** Step 6 - Conversion from Characters to the Intelligent Mail Barcode *** */ for (i = 0; i < 10; i++) { for (j = 0; j < 13; j++) { - if (characters[i] & (1 << j)) { - bar_map[AppxD_IV[(13 * i) + j] - 1] = 1; - } else { - bar_map[AppxD_IV[(13 * i) + j] - 1] = 0; - } + bar_map[AppxD_IV[(13 * i) + j] - 1] = (characters[i] >> j) & 1; } } - data_pattern[0] = '\0'; - temp[1] = '\0'; for (i = 0; i < 65; i++) { j = 0; if (bar_map[i] == 0) j += 1; if (bar_map[i + 65] == 0) j += 2; - temp[0] = itoc(j); - strcat(data_pattern, temp); + data_pattern[i] = itoc(j); } /* Translate 4-state data pattern to symbol */ read = 0; - for (i = 0, len = (int) strlen(data_pattern); i < len; i++) { + for (i = 0; i < 65; i++) { if ((data_pattern[i] == '1') || (data_pattern[i] == '0')) { set_module(symbol, 0, read); } @@ -450,6 +448,11 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int } symbol->rows = 3; symbol->width = read - 1; + + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } + return error_number; } diff --git a/backend/library.c b/backend/library.c index 215dc207..492d7b8b 100644 --- a/backend/library.c +++ b/backend/library.c @@ -55,14 +55,14 @@ static void set_symbol_defaults(struct zint_symbol *symbol) { symbol->symbology = BARCODE_CODE128; symbol->scale = 1.0f; - strcpy(symbol->fgcolour, "000000"); + memcpy(symbol->fgcolour, "000000", 7); /* Include terminating NUL */ symbol->fgcolor = &symbol->fgcolour[0]; - strcpy(symbol->bgcolour, "ffffff"); + memcpy(symbol->bgcolour, "ffffff", 7); symbol->bgcolor = &symbol->bgcolour[0]; #ifdef ZINT_NO_PNG - strcpy(symbol->outfile, "out.gif"); + memcpy(symbol->outfile, "out.gif", 8); /* Include terminating NUL */ #else - strcpy(symbol->outfile, "out.png"); + memcpy(symbol->outfile, "out.png", 8); #endif symbol->option_1 = -1; symbol->show_hrt = 1; /* Show human readable text */ @@ -105,6 +105,7 @@ void ZBarcode_Clear(struct zint_symbol *symbol) { symbol->width = 0; memset(symbol->row_height, 0, sizeof(symbol->row_height)); memset(symbol->text, 0, sizeof(symbol->text)); + symbol->text_length = 0; symbol->errtxt[0] = '\0'; if (symbol->bitmap != NULL) { free(symbol->bitmap); @@ -370,6 +371,7 @@ static int hibc(struct zint_symbol *symbol, struct zint_seg segs[], const int se int counter, error_number = 0; char to_process[110 + 2 + 1]; int posns[110]; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; /* without "+" and check: max 110 characters in HIBC 2.6 */ if (length > 110) { @@ -401,16 +403,24 @@ static int hibc(struct zint_symbol *symbol, struct zint_seg segs[], const int se switch (symbol->symbology) { case BARCODE_HIBC_128: error_number = code128(symbol, segs[0].source, segs[0].length); - ustrcpy(symbol->text, "*"); - ustrcat(symbol->text, to_process); - ustrcat(symbol->text, "*"); + if (plain_hrt) { + hrt_cpy_nochk(symbol, segs[0].source, segs[0].length); + } else { + hrt_cpy_chr(symbol, '*'); + hrt_cat_nochk(symbol, segs[0].source, segs[0].length); + hrt_cat_chr_nochk(symbol, '*'); + } break; case BARCODE_HIBC_39: symbol->option_2 = 0; error_number = code39(symbol, segs[0].source, segs[0].length); - ustrcpy(symbol->text, "*"); - ustrcat(symbol->text, to_process); - ustrcat(symbol->text, "*"); + if (plain_hrt) { + hrt_cpy_nochk(symbol, segs[0].source, segs[0].length); + } else { + hrt_cpy_chr(symbol, '*'); + hrt_cat_nochk(symbol, segs[0].source, segs[0].length); + hrt_cat_chr_nochk(symbol, '*'); + } break; case BARCODE_HIBC_DM: error_number = datamatrix(symbol, segs, seg_count); @@ -1188,14 +1198,13 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[ } if (escape_mode && symbol->primary[0] && strchr(symbol->primary, '\\') != NULL) { - char primary[sizeof(symbol->primary)]; - int primary_len = (int) strlen(symbol->primary); + unsigned char primary[sizeof(symbol->primary)]; + int primary_len = (int) ustrlen(symbol->primary); if (primary_len >= (int) sizeof(symbol->primary)) { return error_tag(ZINT_ERROR_INVALID_DATA, symbol, 799, "Invalid primary string"); } - ustrcpy(primary, symbol->primary); - error_number = escape_char_process(symbol, (const unsigned char *) primary, &primary_len, - (unsigned char *) symbol->primary); + memcpy(primary, symbol->primary, primary_len); + error_number = escape_char_process(symbol, primary, &primary_len, (unsigned char *) symbol->primary); if (error_number != 0) { /* Only returns errors, not warnings */ return error_tag(error_number, symbol, -1, NULL); } @@ -1217,7 +1226,8 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[ handle it themselves */ if (is_composite(symbol->symbology) || !check_force_gs1(symbol->symbology)) { unsigned char *reduced = (unsigned char *) z_alloca(local_segs[0].length + 1); - error_number = gs1_verify(symbol, local_segs[0].source, local_segs[0].length, reduced); + error_number = gs1_verify(symbol, local_segs[0].source, local_segs[0].length, reduced, + &local_segs[0].length); if (error_number) { if (is_composite(symbol->symbology)) { errtxt_adj(0, symbol, "%1$s%2$s", " (2D component)"); @@ -1228,8 +1238,7 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[ } warn_number = error_number; /* Override any previous warning (errtxt has been overwritten) */ } - ustrcpy(local_segs[0].source, reduced); /* Cannot contain NUL char */ - local_segs[0].length = (int) ustrlen(reduced); + memcpy(local_segs[0].source, reduced, local_segs[0].length + 1); /* Include terminating NUL */ } } else { return error_tag(ZINT_ERROR_INVALID_OPTION, symbol, 210, "Selected symbology does not support GS1 mode"); @@ -1655,7 +1664,7 @@ int ZBarcode_BarcodeName(int symbol_id, char name[32]) { assert(symbol_id >= 0 && symbol_id < ARRAY_SIZE(names) && names[symbol_id][0]); memcpy(name, "BARCODE_", 8); - strcpy(name + 8, names[symbol_id]); + memcpy(name + 8, names[symbol_id], strlen(names[symbol_id]) + 1); /* Include terminating NUL */ return 0; } diff --git a/backend/mailmark.c b/backend/mailmark.c index 4a93fac8..79a1831b 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -171,7 +171,7 @@ INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, /* Royal Mail 4-state Mailmark */ INTERNAL int mailmark_4s(struct zint_symbol *symbol, unsigned char source[], int length) { - char local_source[28]; + unsigned char local_source[28]; int format; int version_id; int mail_class; @@ -192,35 +192,32 @@ INTERNAL int mailmark_4s(struct zint_symbol *symbol, unsigned char source[], int int i, j, len; rs_t rs; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 26) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 580, "Input length %d too long (maximum 26)", length); } - ustrcpy(local_source, source); + memcpy(local_source, source, length); if (length < 22) { if (length < 14) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 588, "Input length %d too short (minimum 14)", length); } - for (i = length; i <= 22; i++) { - strcat(local_source, " "); - } + memset(local_source + length, ' ', 22 - length); length = 22; } else if ((length > 22) && (length < 26)) { - for (i = length; i <= 26; i++) { - strcat(local_source, " "); - } + memset(local_source + length, ' ', 26 - length); length = 26; } - to_upper((unsigned char *) local_source, length); + to_upper(local_source, length); if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Producing 4-state Mailmark (%d): %s\n", length, local_source); + printf("Producing 4-state Mailmark (%d): %.*s\n", length, length, local_source); } - if ((i = not_sane(RUBIDIUM_F, (const unsigned char *) local_source, length))) { + if ((i = not_sane(RUBIDIUM_F, local_source, length))) { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 581, "Invalid character at position %d in input (alphanumerics and space only)", i); } @@ -503,6 +500,10 @@ INTERNAL int mailmark_4s(struct zint_symbol *symbol, unsigned char source[], int symbol->rows = 3; symbol->width = j - 1; + if (plain_hrt) { + hrt_cpy_nochk(symbol, local_source, length); + } + return error_number; } @@ -532,11 +533,11 @@ INTERNAL int mailmark_2d(struct zint_symbol *symbol, unsigned char source[], int if (length > 86) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 861, "Input length %d too long (maximum 86)", length); } - ustrcpy(local_source, "JGB "); - ustrcpy(local_source + 4, source); + memcpy(local_source, "JGB ", 4); + memcpy(local_source + 4, source, length); length += 4; } else { - ustrcpy(local_source, source); + memcpy(local_source, source, length); } if (length < 32) { @@ -544,16 +545,15 @@ INTERNAL int mailmark_2d(struct zint_symbol *symbol, unsigned char source[], int } if (length < 39) { /* Space-pad Return to Sender Post Code */ memset(local_source + length, ' ', 39 - length); - local_source[39] = '\0'; length = 39; } to_upper(local_source, 39); if (length < 45) { /* Space-pad Reserved */ memset(local_source + length, ' ', 45 - length); - local_source[45] = '\0'; length = 45; } + local_source[length] = '\0'; /* 8: 24 x 24, 10: 32 x 32, 30: 16 x 48 */ if (symbol->option_2) { diff --git a/backend/maxicode.c b/backend/maxicode.c index 571ca915..e63f5ba8 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -623,7 +623,7 @@ INTERNAL int maxicode(struct zint_symbol *symbol, struct zint_seg segs[], const if (countrycode == 840 && postcode_len == 5) { /* Annex B, section B.1, paragraph 4.a, "In the case of country code 840, if the "+4" is unknown, then fill with zeroes" (adapted from OkaiBarcode, stricter interpretation, props Daniel Gredler) */ - memcpy(postcode + 5, "0000", 5); /* Include NUL char */ + memcpy(postcode + 5, "0000", 5); /* Include terminating NUL */ postcode_len = 9; } mx_do_primary_2(codewords, postcode, postcode_len, countrycode, service); diff --git a/backend/medical.c b/backend/medical.c index 6c54a13b..6aeaab2f 100644 --- a/backend/medical.c +++ b/backend/medical.c @@ -57,6 +57,7 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng char *in = inter; char dest[64]; /* 17 * 2 + 1 */ char *d = dest; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 6) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 350, "Input length %d too long (maximum 6)", length); @@ -97,6 +98,10 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); } + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } + return error_number; } @@ -145,6 +150,7 @@ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int unsigned int loopey, h; int writer; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 8) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 354, "Input length %d too long (maximum 8)", length); @@ -182,16 +188,22 @@ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int (void) set_height(symbol, 0.0f, 10.0f, 0.0f, 1 /*no_errtxt*/); } + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } + return error_number; } /* Italian Pharmacode */ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length) { - static const char TABELLA[] = "0123456789BCDFGHJKLMNPQRSTUVWXYZ"; + static const unsigned char TABELLA[] = "0123456789BCDFGHJKLMNPQRSTUVWXYZ"; int i, zeroes, error_number = 0, checksum, checkpart, checkdigit; - char localstr[10], risultante[7]; + unsigned char local_source[10], risultante[7]; unsigned int pharmacode, devisor; int codeword[6]; + const int saved_option_2 = symbol->option_2; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; /* Validate the input */ if (length > 8) { @@ -204,15 +216,15 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng /* Add leading zeros as required */ zeroes = 8 - length; - memset(localstr, '0', zeroes); - ustrcpy(localstr + zeroes, source); + memset(local_source, '0', zeroes); + memcpy(local_source + zeroes, source, length); /* Calculate the check digit */ checksum = 0; for (i = 0; i < 4; i++) { - checkpart = ctoi(localstr[i * 2]); + checkpart = ctoi(local_source[i * 2]); checksum += checkpart; - checkpart = 2 * (ctoi(localstr[(i * 2) + 1])); + checkpart = 2 * (ctoi(local_source[(i * 2) + 1])); if (checkpart >= 10) { checksum += (checkpart - 10) + 1; } else { @@ -222,11 +234,10 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng /* Add check digit to data string */ checkdigit = checksum % 10; - localstr[8] = itoc(checkdigit); - localstr[9] = '\0'; + local_source[8] = itoc(checkdigit); /* Convert string into an integer value */ - pharmacode = atoi(localstr); + pharmacode = to_int(local_source, 9); /* Convert from decimal to base-32 */ devisor = 33554432; @@ -242,13 +253,17 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng for (i = 5; i >= 0; i--) { risultante[5 - i] = TABELLA[codeword[i]]; } - risultante[6] = '\0'; + + symbol->option_2 = 0; /* Need to overwrite this so `code39()` doesn't add a check digit itself */ + /* Plot the barcode using Code 39 */ - error_number = code39(symbol, (unsigned char *) risultante, 6); + error_number = code39(symbol, risultante, 6); if (error_number != 0) { /* Should never happen */ return error_number; /* Not reached */ } + symbol->option_2 = saved_option_2; /* Restore */ + if (symbol->output_options & COMPLIANT_HEIGHT) { /* Allegato A Caratteristiche tecniche del bollino farmaceutico (https://www.gazzettaufficiale.it/do/atto/serie_generale/caricaPdf?cdimg=14A0566800100010110001 @@ -261,9 +276,11 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/); } - /* Override the normal text output with the Pharmacode number */ - ustrcpy(symbol->text, "A"); - ustrcat(symbol->text, localstr); + if (!plain_hrt) { + /* Override the normal text output with the Pharmacode number */ + hrt_cpy_chr(symbol, 'A'); + hrt_cat_nochk(symbol, local_source, 9); + } return error_number; } @@ -277,8 +294,10 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) int i, error_number, zeroes; int count, check_digit; unsigned char have_check_digit = '\0'; - char localstr[1 + 8 + 1]; /* '-' prefix + 8 digits + NUL */ + unsigned char local_source[1 + 8]; /* '-' prefix + 8 digits */ const int pzn7 = symbol->option_2 == 1; + const int saved_option_2 = symbol->option_2; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 8 - pzn7) { return ZEXT errtxtf(ZINT_ERROR_TOO_LONG, symbol, 325, "Input length %1$d too long (maximum %2$d)", length, @@ -293,21 +312,21 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) "Invalid character at position %d in input (digits only)", i); } - localstr[0] = '-'; + local_source[0] = '-'; zeroes = 7 - pzn7 - length + 1; for (i = 1; i < zeroes; i++) - localstr[i] = '0'; - ustrcpy(localstr + zeroes, source); + local_source[i] = '0'; + memcpy(local_source + zeroes, source, length); count = 0; for (i = 1; i < 8 - pzn7; i++) { - count += (i + pzn7) * ctoi(localstr[i]); + count += (i + pzn7) * ctoi(local_source[i]); } check_digit = count % 11; if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("PZN: %s, check digit %d\n", localstr, (int) check_digit); + printf("PZN: %.*s, check digit %d\n", 8 - pzn7, local_source, (int) check_digit); } if (check_digit == 10) { @@ -318,21 +337,13 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) have_check_digit, itoc(check_digit)); } - localstr[8 - pzn7] = itoc(check_digit); - localstr[9 - pzn7] = '\0'; + local_source[8 - pzn7] = itoc(check_digit); - if (pzn7) { - symbol->option_2 = 0; /* Need to overwrite this so `code39()` doesn't add a check digit itself */ - } + symbol->option_2 = 0; /* Need to overwrite this so `code39()` doesn't add a check digit itself */ - error_number = code39(symbol, (unsigned char *) localstr, 9 - pzn7); + error_number = code39(symbol, local_source, 9 - pzn7); - if (pzn7) { - symbol->option_2 = 1; /* Restore */ - } - - ustrcpy(symbol->text, "PZN - "); /* Note changed to put space after hyphen */ - ustrcat(symbol->text, localstr + 1); + symbol->option_2 = saved_option_2; /* Restore */ if (symbol->output_options & COMPLIANT_HEIGHT) { /* Technical Information regarding PZN Coding V 2.1 (25 Feb 2019) Code size @@ -350,6 +361,11 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) } } + if (!plain_hrt) { + hrt_cpy_nochk(symbol, (const unsigned char *) "PZN - ", 6); /* Note changed to put space after hyphen */ + hrt_cat_nochk(symbol, local_source + 1, 9 - pzn7 - 1); + } + return error_number; } diff --git a/backend/output.c b/backend/output.c index 0fd4c5ae..08aa02d6 100644 --- a/backend/output.c +++ b/backend/output.c @@ -266,7 +266,7 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text case BARCODE_EANX_CC: case BARCODE_ISBNX: /* GS1 General Specifications 21.0.1 Section 5.2.3.4 */ - switch (ustrlen(symbol->text)) { + switch (symbol->text_length) { case 13: /* EAN-13/ISBN */ if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) { *left = comp_xoffset >= 10 ? 1.0f : 11.0f - comp_xoffset; /* Need at least 1X for CC-A/B */ @@ -311,14 +311,14 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text /* GS1 General Specifications 21.0.1 Section 5.2.3.4 */ if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) { *left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; /* Need at least 1X for CC-A/B */ - if (ustrlen(symbol->text) > 12) { /* UPC-A + add-on */ + if (symbol->text_length > 12) { /* UPC-A + add-on */ *right = 5.0f; } else { *right = 9.0f - (comp_xoffset != 0); } } else if (!hide_text) { *left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; /* Need for outside left digit */ - if (ustrlen(symbol->text) <= 12) { /* No add-on */ + if (symbol->text_length <= 12) { /* No add-on */ *right = 9.0f - (comp_xoffset != 0); /* Need for outside right digit */ } } @@ -330,14 +330,14 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text /* GS1 General Specifications 21.0.1 Section 5.2.3.4 */ if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) { *left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; - if (ustrlen(symbol->text) > 8) { /* UPC-E + add-on */ + if (symbol->text_length > 8) { /* UPC-E + add-on */ *right = 5.0f; } else { *right = 7.0f - (comp_xoffset != 0); } } else if (!hide_text) { *left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; /* Need for outside left digit */ - if (ustrlen(symbol->text) <= 8) { /* No add-on */ + if (symbol->text_length <= 8) { /* No add-on */ *right = 7.0f - (comp_xoffset != 0); /* Need for outside right digit */ } } @@ -747,12 +747,11 @@ INTERNAL int out_process_upcean(const struct zint_symbol *symbol, const int comp int main_width; /* Width of main linear symbol, excluding add-on */ int upceanflag; /* EAN/UPC type flag */ int i, j, latch; - const int text_length = (int) ustrlen(symbol->text); latch = 0; j = 0; /* Isolate add-on text */ - for (i = 6; i < text_length && j < 5; i++) { + for (i = 6; i < symbol->text_length && j < 5; i++) { if (latch == 1) { /* Use dummy space-filled add-on if no hrt */ addon[j] = symbol->show_hrt ? symbol->text[i] : ' '; @@ -776,7 +775,7 @@ INTERNAL int out_process_upcean(const struct zint_symbol *symbol, const int comp main_width = symbol->width; if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CHK) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) { - switch (text_length) { + switch (symbol->text_length) { case 13: /* EAN-13 */ case 16: /* EAN-13 + EAN-2 */ case 19: /* EAN-13 + EAN-5 */ @@ -889,7 +888,7 @@ INTERNAL float out_large_bar_height(struct zint_symbol *symbol, const int si, in /* Convert UTF-8 to Windows wide chars. Ticket #288, props Marcel */ #define utf8_to_wide(u, w, r) \ { \ - int lenW; /* Includes NUL terminator */ \ + int lenW; /* Includes terminating NUL */ \ if ((lenW = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, NULL, 0)) == 0) return r; \ w = (wchar_t *) z_alloca(sizeof(wchar_t) * lenW); \ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, w, lenW) == 0) return r; \ @@ -899,14 +898,14 @@ INTERNAL float out_large_bar_height(struct zint_symbol *symbol, const int si, in INTERNAL FILE *out_win_fopen(const char *filename, const char *mode) { wchar_t *filenameW, *modeW; - utf8_to_wide(filename, filenameW, NULL); + utf8_to_wide(filename, filenameW, NULL /*fail return*/); utf8_to_wide(mode, modeW, NULL); return _wfopen(filenameW, modeW); } #endif -/* Make a directory; already existing dir okay */ +/* Make a directory; already existing dir okay. Returns 0 on success */ /* Adapted from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950 and https://nachtimwald.com/2019/07/10/recursive-create-directory-in-c-revisited/ */ static int out_maybe_mkdir(const char *path) { @@ -915,7 +914,7 @@ static int out_maybe_mkdir(const char *path) { wchar_t *pathW; /* Assumes `path` is UTF-8 encoded */ - utf8_to_wide(path, pathW, 0); + utf8_to_wide(path, pathW, -1 /*fail return*/); /* Try to make the directory */ if (CreateDirectoryW(pathW, NULL) != 0) { /* Non-zero on success */ diff --git a/backend/pdf417.c b/backend/pdf417.c index f05ae89e..3f5dee5c 100644 --- a/backend/pdf417.c +++ b/backend/pdf417.c @@ -687,9 +687,12 @@ struct pdf_edge { ((edge)->previous ? (edges) + (edge)->previous : NULL) #if 0 -#define PDF_TRACE -#endif #include "pdf417_trace.h" +#else +#define PDF_TRACE_Edges(px, s, l, p, v) +#define PDF_TRACE_AddEdge(s, l, es, p, v, t, e) do { (void)(s); (void)(l); } while (0) +#define PDF_TRACE_NotAddEdge(s, l, es, p, v, t, e) do { (void)(s); (void)(l); } while (0) +#endif /* Initialize a new edge */ static int pdf_new_Edge(struct pdf_edge *edges, const int mode, const int from, const int len, const int t_table, diff --git a/backend/pdf417_trace.h b/backend/pdf417_trace.h index c5397396..f7570623 100644 --- a/backend/pdf417_trace.h +++ b/backend/pdf417_trace.h @@ -1,7 +1,7 @@ /* pdf417_trace.h - Trace routines for optimal PDF417 optimization algorithm */ /* libzint - the open source barcode library - Copyright (C) 2022-2023 Robin Stuart + Copyright (C) 2022-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -33,12 +33,6 @@ #ifndef Z_PDF417_TRACE_H #define Z_PDF417_TRACE_H -#ifndef PDF_TRACE -#define PDF_TRACE_Edges(px, s, l, p, v) -#define PDF_TRACE_AddEdge(s, l, es, p, v, t, e) do { (void)(s); (void)(l); } while (0) -#define PDF_TRACE_NotAddEdge(s, l, es, p, v, t, e) do { (void)(s); (void)(l); } while (0) -#else - static int PDF_TRACE_getPreviousMode(struct pdf_edge *edges, struct pdf_edge *edge) { struct pdf_edge *previous = PDF_PREVIOUS(edges, edge); return previous == NULL ? PDF_ALP : previous->mode; @@ -61,8 +55,9 @@ static void PDF_TRACE_EdgeToString(char *buf, const unsigned char *source, const static void PDF_TRACE_Path(const unsigned char *source, const int length, struct pdf_edge *edges, struct pdf_edge *edge, char *result, const int result_size) { + struct pdf_edge *current; PDF_TRACE_EdgeToString(result, source, length, edges, edge); - struct pdf_edge *current = PDF_PREVIOUS(edges, edge); + current = PDF_PREVIOUS(edges, edge); while (current) { char s[256]; char *pos; @@ -72,8 +67,7 @@ static void PDF_TRACE_Path(const unsigned char *source, const int length, struct assert(pos); len = strlen(result); if ((pos - s) + 1 + len + 1 >= result_size) { - result[result_size - 4] = '\0'; - strcat(result, "..."); + memcpy(result + result_size - 4, "...", 4); /* Include terminating NUL */ break; } memmove(result + (pos - s) + 1, result, len + 1); @@ -131,6 +125,5 @@ static void PDF_TRACE_NotAddEdge(const unsigned char *source, const int length, new_size, edge->units, edge->unit_size, edge->size); } -#endif /* PDF_TRACE */ /* vim: set ts=4 sw=4 et : */ #endif /* Z_PDF417_TRACE_H */ diff --git a/backend/plessey.c b/backend/plessey.c index d7044b50..106b7f77 100644 --- a/backend/plessey.c +++ b/backend/plessey.c @@ -1,7 +1,7 @@ /* plessey.c - Handles Plessey and MSI Plessey */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -59,7 +59,9 @@ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int len static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1}; char dest[570]; /* 8 + 67 * 8 + 2 * 8 + 9 + 1 = 570 */ char *d = dest; + unsigned int check_digits = 0; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 67) { /* 16 + 67 * 16 + 4 * 8 + 19 = 1139 */ return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 370, "Input length %d too long (maximum 67)", length); @@ -75,7 +77,7 @@ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int len /* Data area */ for (i = 0; i < length; i++, d += 8) { - unsigned int check = source[i] - '0' - (source[i] >> 6) * 7; + const unsigned int check = source[i] - '0' - (source[i] >> 6) * 7; memcpy(d, PlessTable[check], 8); checkptr[4 * i] = check & 1; checkptr[4 * i + 1] = (check >> 1) & 1; @@ -101,6 +103,7 @@ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int len break; case 1: memcpy(d, "31", 2); d += 2; + check_digits |= (1 << i); break; } } @@ -113,8 +116,13 @@ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int len /* TODO: Find documentation on BARCODE_PLESSEY dimensions/height */ - symbol->text[0] = '\0'; - ustrncat(symbol->text, source, length); + hrt_cpy_nochk(symbol, source, length); + if (symbol->option_2 == 1 || plain_hrt) { + const unsigned c1 = check_digits & 0xF; + const unsigned c2 = check_digits >> 4; + hrt_cat_chr_nochk(symbol, xtoc(c1)); + hrt_cat_chr_nochk(symbol, xtoc(c2)); + } return error_number; } @@ -164,8 +172,7 @@ static char *msi_plessey_nomod(struct zint_symbol *symbol, const unsigned char s memcpy(d, MSITable[source[i] - '0'], 8); } - symbol->text[0] = '\0'; - ustrncat(symbol->text, source, length); + hrt_cpy_nochk(symbol, source, length); return d; } @@ -176,23 +183,21 @@ static char *msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char s int i; char check_digit; - /* draw data section */ + /* Draw data section */ for (i = 0; i < length; i++, d += 8) { memcpy(d, MSITable[source[i] - '0'], 8); } - /* calculate check digit */ + /* Calculate check digit */ check_digit = msi_check_digit_mod10(source, length); - /* draw check digit */ + /* Draw check digit */ memcpy(d, MSITable[check_digit - '0'], 8); d += 8; - symbol->text[0] = '\0'; - ustrncat(symbol->text, source, length); + hrt_cpy_nochk(symbol, source, length); if (!no_checktext) { - symbol->text[length] = check_digit; - symbol->text[length + 1] = '\0'; + hrt_cat_chr_nochk(symbol, check_digit); } return d; @@ -203,25 +208,22 @@ static char *msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char const int no_checktext, char *d) { int i; - unsigned char temp[92 + 2 + 1]; + unsigned char local_source[92 + 2]; /* Append check digits */ - temp[0] = '\0'; - ustrncat(temp, source, length); - temp[length] = msi_check_digit_mod10(source, length); - temp[length + 1] = msi_check_digit_mod10(temp, length + 1); - temp[length + 2] = '\0'; + memcpy(local_source, source, length); + local_source[length] = msi_check_digit_mod10(source, length); + local_source[length + 1] = msi_check_digit_mod10(local_source, length + 1); - /* draw data section */ + /* Draw data section */ for (i = 0; i < length + 2; i++, d += 8) { - memcpy(d, MSITable[temp[i] - '0'], 8); + memcpy(d, MSITable[local_source[i] - '0'], 8); } if (no_checktext) { - symbol->text[0] = '\0'; - ustrncat(symbol->text, source, length); + hrt_cpy_nochk(symbol, source, length); } else { - ustrcpy(symbol->text, temp); + hrt_cpy_nochk(symbol, local_source, length + 2); } return d; @@ -234,7 +236,7 @@ static char *msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char s int i; char check_digit; - /* draw data section */ + /* Draw data section */ for (i = 0; i < length; i++, d += 8) { memcpy(d, MSITable[source[i] - '0'], 8); } @@ -251,14 +253,12 @@ static char *msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char s d += 8; } - symbol->text[0] = '\0'; - ustrncat(symbol->text, source, length); + hrt_cpy_nochk(symbol, source, length); if (!no_checktext) { if (check_digit == ':') { - ustrcat(symbol->text, "10"); + hrt_cat_nochk(symbol, (const unsigned char *) "10", 2); } else { - symbol->text[length] = check_digit; - symbol->text[length + 1] = '\0'; + hrt_cat_chr_nochk(symbol, check_digit); } } @@ -271,35 +271,33 @@ static char *msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ int i; char check_digit; - unsigned char temp[92 + 3 + 1]; - int temp_len = length; + unsigned char local_source[92 + 3 + 1]; + int local_length = length; - temp[0] = '\0'; - ustrncat(temp, source, length); + memcpy(local_source, source, length); /* Append first (mod 11) digit */ check_digit = msi_check_digit_mod11(source, length, wrap); if (check_digit == ':') { - temp[temp_len++] = '1'; - temp[temp_len++] = '0'; + local_source[local_length++] = '1'; + local_source[local_length++] = '0'; } else { - temp[temp_len++] = check_digit; + local_source[local_length++] = check_digit; } /* Append second (mod 10) check digit */ - temp[temp_len] = msi_check_digit_mod10(temp, temp_len); - temp[++temp_len] = '\0'; + local_source[local_length] = msi_check_digit_mod10(local_source, local_length); + local_length++; - /* draw data section */ - for (i = 0; i < temp_len; i++, d += 8) { - memcpy(d, MSITable[temp[i] - '0'], 8); + /* Draw data section */ + for (i = 0; i < local_length; i++, d += 8) { + memcpy(d, MSITable[local_source[i] - '0'], 8); } if (no_checktext) { - symbol->text[0] = '\0'; - ustrncat(symbol->text, source, length); + hrt_cpy_nochk(symbol, source, length); } else { - ustrcpy(symbol->text, temp); + hrt_cpy_nochk(symbol, local_source, local_length); } return d; @@ -312,6 +310,7 @@ INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int char *d = dest; int check_option = symbol->option_2; int no_checktext = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 92) { /* 3 (Start) + 92 * 12 + 3 * 12 + 4 (Stop) = 1147 */ return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 372, "Input length %d too long (maximum 92)", length); @@ -323,7 +322,7 @@ INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int if (check_option >= 11 && check_option <= 16) { /* +10 means don't print check digits in HRT */ check_option -= 10; - no_checktext = 1; + no_checktext = !plain_hrt; } if ((check_option < 0) || (check_option > 6)) { check_option = 0; diff --git a/backend/postal.c b/backend/postal.c index 6476704f..561c748e 100644 --- a/backend/postal.c +++ b/backend/postal.c @@ -1,7 +1,7 @@ /* postal.c - Handles POSTNET, PLANET, CEPNet, FIM. RM4SCC and Flattermarken */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Including bug fixes by Bryan Hatton Redistribution and use in source and binary forms, with or without @@ -141,6 +141,7 @@ static int usps_set_height(struct zint_symbol *symbol, const int no_errtxt) { static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[], char *d, const int length) { int i, sum, check_digit; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 38) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 480, "Input length %d too long (maximum 38)", length); @@ -163,7 +164,7 @@ static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[], } sum = 0; - /* start character */ + /* Start character */ *d++ = 'L'; for (i = 0; i < length; i++, d += 5) { @@ -178,8 +179,13 @@ static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[], if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); - /* stop character */ - strcpy(d, "L"); + /* Stop character */ + memcpy(d, "L", 2); /* Include terminating NUL */ + + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + hrt_cat_chr_nochk(symbol, check_digit + '0'); + } return error_number; } @@ -217,6 +223,7 @@ INTERNAL int postnet(struct zint_symbol *symbol, unsigned char source[], int len static int planet_enc(struct zint_symbol *symbol, const unsigned char source[], char *d, const int length) { int i, sum, check_digit; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 38) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 482, "Input length %d too long (maximum 38)", length); @@ -231,7 +238,7 @@ static int planet_enc(struct zint_symbol *symbol, const unsigned char source[], } sum = 0; - /* start character */ + /* Start character */ *d++ = 'L'; for (i = 0; i < length; i++, d += 5) { @@ -246,8 +253,13 @@ static int planet_enc(struct zint_symbol *symbol, const unsigned char source[], if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); - /* stop character */ - strcpy(d, "L"); + /* Stop character */ + memcpy(d, "L", 2); /* Include terminating NUL */ + + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + hrt_cat_chr_nochk(symbol, check_digit + '0'); + } return error_number; } @@ -284,7 +296,8 @@ INTERNAL int planet(struct zint_symbol *symbol, unsigned char source[], int leng /* Korean Postal Authority */ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int length) { int total, i, check, zeroes, error_number = 0; - char localstr[8], dest[80]; + unsigned char local_source[8]; + char dest[80]; char *d = dest; int posns[6]; @@ -296,20 +309,19 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l "Invalid character at position %d in input (digits only)", i); } zeroes = 6 - length; - memset(localstr, '0', zeroes); - ustrcpy(localstr + zeroes, source); + memset(local_source, '0', zeroes); + memcpy(local_source + zeroes, source, length); total = 0; for (i = 0; i < 6; i++) { - posns[i] = ctoi(localstr[i]); + posns[i] = ctoi(local_source[i]); total += posns[i]; } check = 10 - (total % 10); if (check == 10) { check = 0; } - localstr[6] = itoc(check); - localstr[7] = '\0'; + local_source[6] = itoc(check); for (i = 5; i >= 0; i--) { const char *const entry = KoreaTable[posns[i]]; @@ -321,10 +333,10 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l expand(symbol, dest, d - dest); - ustrcpy(symbol->text, localstr); - /* TODO: Find documentation on BARCODE_KOREAPOST dimensions/height */ + hrt_cpy_nochk(symbol, local_source, 7); + return error_number; } @@ -332,6 +344,7 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l glyphs from http://en.wikipedia.org/wiki/Facing_Identification_Mark */ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) { int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 1) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 486, "Input length %d too long (maximum 1)", length); @@ -364,6 +377,10 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) break; } + if (plain_hrt) { + hrt_cpy_chr(symbol, (const char) (z_islower(source[0]) ? source[0] & 0x5F : source[0])); + } + if (symbol->output_options & COMPLIANT_HEIGHT) { /* USPS Domestic Mail Manual (USPS DMM 300) Jan 8, 2006 (updated 2011) 708.9.3 X 0.03125" (1/32) +- 0.008" so X max 0.03925", height 0.625" (5/8) +- 0.125" (1/8) */ @@ -412,14 +429,15 @@ INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, } /* Handles the 4 State barcodes used in the UK by Royal Mail */ -static void rm4scc_enc(const struct zint_symbol *symbol, const int *posns, char *d, const int length) { +static void rm4scc_enc(struct zint_symbol *symbol, const int *posns, char *d, const int length) { int i; int top, bottom, row, column, check_digit; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; top = 0; bottom = 0; - /* start character */ + /* Start character */ *d++ = '1'; for (i = 0; i < length; i++, d += 4) { @@ -444,8 +462,12 @@ static void rm4scc_enc(const struct zint_symbol *symbol, const int *posns, char if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); - /* stop character */ - strcpy(d, "0"); + /* Stop character */ + memcpy(d, "0", 2); /* Include terminating NUL */ + + if (plain_hrt) { + hrt_cat_chr_nochk(symbol, KRSET[check_digit]); + } } /* Puts RM4SCC into the data matrix */ @@ -456,6 +478,7 @@ INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int leng int loopey, h; int writer; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 50) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 488, "Input length %d too long (maximum 50)", length); @@ -465,6 +488,9 @@ INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int leng return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 489, "Invalid character at position %d in input (alphanumerics only)", i); } + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } rm4scc_enc(symbol, posns, height_pattern, length); writer = 0; @@ -514,6 +540,7 @@ INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length) int loopey; int writer, i, h; int error_number = 0; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 18) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 490, "Input length %d too long (maximum 18)", length); @@ -558,6 +585,10 @@ INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length) symbol->rows = 3; symbol->width = writer - 1; + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } + return error_number; } @@ -567,6 +598,7 @@ INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length int posns[576]; int loopey; int writer; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 576) { /* 576 * 2 = 1152 */ return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 492, "Input length %d too long (maximum 576)", length); @@ -608,6 +640,10 @@ INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length symbol->rows = 3; symbol->width = writer - 1; + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } + return 0; } @@ -616,6 +652,7 @@ INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length int i, error_number = 0; char dest[512]; /* 128 * 4 = 512 */ char *d = dest; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 128) { /* 128 * 9 = 1152 */ return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 494, "Input length %d too long (maximum 128)", length); @@ -635,6 +672,10 @@ INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length /* TODO: Find documentation on BARCODE_FLAT dimensions/height */ + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + } + return error_number; } @@ -645,7 +686,8 @@ INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int l char *d = pattern; int writer, loopey, inter_posn, i, sum, check; char check_char; - char inter[20 + 1]; + unsigned char inter[20 + 1]; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 20) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 496, "Input length %d too long (maximum 20)", length); @@ -749,6 +791,11 @@ INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int l (void) daft_set_height(symbol, 0.0f, 0.0f); } + if (plain_hrt) { + hrt_cpy_nochk(symbol, source, length); + /* Note: check char is in KASUTSET and not truly representable in HRT's SHKASUTSET_F */ + } + return error_number; } diff --git a/backend/ps.c b/backend/ps.c index ec4cd597..ce92881f 100644 --- a/backend/ps.c +++ b/backend/ps.c @@ -187,7 +187,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { struct zint_vector_hexagon *hex; struct zint_vector_circle *circle; struct zint_vector_string *string; - int i, len; + int i; int ps_len = 0; int iso_latin1 = 0; int have_circles_with_width = 0, have_circles_without_width = 0; @@ -229,7 +229,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { draw_background = 0; } - for (i = 0, len = (int) ustrlen(symbol->text); i < len; i++) { + for (i = 0; i < symbol->text_length; i++) { switch (symbol->text[i]) { case '(': case ')': diff --git a/backend/raster.c b/backend/raster.c index b90201ed..f4aa0817 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -1,7 +1,7 @@ /* raster.c - Handles output to raster files */ /* libzint - the open source barcode library - Copyright (C) 2009-2024 Robin Stuart + Copyright (C) 2009-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -929,7 +929,7 @@ static void to_iso8859_1(const unsigned char source[], unsigned char preprocesse break; default: /* Process ASCII (< 80h), all other unicode points are ignored */ - if (source[i] < 128) { + if (z_isascii(source[i])) { preprocessed[j] = source[i]; j++; } @@ -999,7 +999,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl upceanflag = out_process_upcean(symbol, comp_xoffset, &main_width, addon, &addon_len, &addon_gap); } - hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0) || scaler < 1.0f); + hide_text = !symbol->show_hrt || symbol->text_length == 0 || scaler < 1.0f; out_set_whitespace_offsets(symbol, hide_text, comp_xoffset, &xoffset, &yoffset, &roffset, &boffset, NULL /*qz_right*/, si, &xoffset_si, &yoffset_si, &roffset_si, &boffset_si, &qz_right_si); diff --git a/backend/rss.c b/backend/rss.c index 428d44a7..2ff102f3 100644 --- a/backend/rss.c +++ b/backend/rss.c @@ -155,16 +155,17 @@ static void getRSSwidths(int widths[], int val, int n, const int elements, const /* Set GTIN-14 human readable text */ static void dbar_set_gtin14_hrt(struct zint_symbol *symbol, const unsigned char *source, const int length) { - unsigned char *hrt = symbol->text + 4; - const int leading_zeroes = 13 - length; + static const unsigned char zeroes_str[] = "0000000000000"; /* 13 zeroes */ + const int zeroes = 13 - length; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; - ustrcpy(symbol->text, "(01)"); - if (leading_zeroes) { - memset(hrt, '0', leading_zeroes); + if (plain_hrt) { + hrt_printf_nochk(symbol, "01%.*s%.*s", zeroes, zeroes_str, length, source); + hrt_cat_chr_nochk(symbol, gs1_check_digit(symbol->text + 2, 13)); + } else { + hrt_printf_nochk(symbol, "(01)%.*s%.*s", zeroes, zeroes_str, length, source); + hrt_cat_chr_nochk(symbol, gs1_check_digit(symbol->text + 4, 13)); } - memcpy(hrt + leading_zeroes, source, length); - hrt[13] = gs1_check_digit(hrt, 13); - hrt[14] = '\0'; } /* Expand from a width pattern to a bit pattern */ @@ -822,13 +823,12 @@ INTERNAL int dbar_date(const unsigned char source[], const int length, const int } /* Handles all data encodation from section 7.2.5 of ISO/IEC 24724 */ -static int dbar_exp_binary_string(struct zint_symbol *symbol, const unsigned char source[], char binary_string[], - int *p_cols_per_row, const int max_rows, int *p_bp) { +static int dbar_exp_binary_string(struct zint_symbol *symbol, const unsigned char source[], const int length, + char binary_string[], int *p_cols_per_row, const int max_rows, int *p_bp) { int encoding_method, i, j, read_posn, mode = NUMERIC; char last_digit = '\0'; int symbol_characters, characters_per_row = *p_cols_per_row * 2; int min_cols_per_row = 0; - int length = (int) ustrlen(source); const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); char *general_field = (char *) z_alloca(length + 1); int bp = *p_bp; @@ -1017,7 +1017,7 @@ static int dbar_exp_binary_string(struct zint_symbol *symbol, const unsigned cha } else if ((encoding_method >= 7) && (encoding_method <= 14)) { /* Encoding method fields "0111000" through "0111111" - variable weight item plus date */ int group_val; - char weight_str[8]; + unsigned char weight_str[7]; for (i = 3; i < 15; i += 3) { /* Leading "019" stripped, and final check digit excluded */ bp = bin_append_posn(to_int(source + i, 3), 10, binary_string, bp); @@ -1030,7 +1030,7 @@ static int dbar_exp_binary_string(struct zint_symbol *symbol, const unsigned cha } weight_str[6] = '\0'; - bp = bin_append_posn(atoi(weight_str), 20, binary_string, bp); + bp = bin_append_posn(to_int(weight_str, 6), 20, binary_string, bp); if (length == 34) { /* Date information is included */ @@ -1250,19 +1250,9 @@ static void dbar_exp_hrt(struct zint_symbol *symbol, unsigned char source[], con /* Max possible length is 77 digits so will fit */ if (symbol->input_mode & GS1PARENS_MODE) { - memcpy(symbol->text, source, length + 1); /* Include terminating NUL */ + hrt_cpy_nochk(symbol, source, length); } else { - int i; - /* Can't have square brackets in content so bracket level not required */ - for (i = 0; i <= length /* Include terminating NUL */; i++) { - if (source[i] == '[') { - symbol->text[i] = '('; - } else if (source[i] == ']') { - symbol->text[i] = ')'; - } else { - symbol->text[i] = source[i]; - } - } + hrt_conv_gs1_brackets_nochk(symbol, source, length); } } @@ -1283,18 +1273,20 @@ INTERNAL int dbar_exp_cc(struct zint_symbol *symbol, unsigned char source[], int int stack_rows = 1; const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); unsigned char *reduced = (unsigned char *) z_alloca(length + 1); + int reduced_length; char *binary_string = (char *) z_alloca(bin_len); + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; separator_row = 0; - error_number = gs1_verify(symbol, source, length, reduced); + error_number = gs1_verify(symbol, source, length, reduced, &reduced_length); if (error_number >= ZINT_ERROR) { return error_number; } warn_number = error_number; if (debug_print) { - printf("Reduced (%d): %s\n", (int) ustrlen(reduced), reduced); + printf("Reduced (%d): %s\n", reduced_length, reduced); } if ((symbol->symbology == BARCODE_DBAR_EXP_CC) || (symbol->symbology == BARCODE_DBAR_EXPSTK_CC)) { @@ -1325,7 +1317,8 @@ INTERNAL int dbar_exp_cc(struct zint_symbol *symbol, unsigned char source[], int } } - error_number = dbar_exp_binary_string(symbol, reduced, binary_string, &cols_per_row, max_rows, &bp); + error_number = dbar_exp_binary_string(symbol, reduced, reduced_length, binary_string, &cols_per_row, max_rows, + &bp); if (error_number != 0) { return error_number; } @@ -1468,7 +1461,11 @@ INTERNAL int dbar_exp_cc(struct zint_symbol *symbol, unsigned char source[], int } symbol->rows = symbol->rows + 1; - dbar_exp_hrt(symbol, source, length); + if (plain_hrt) { + hrt_cpy_nochk(symbol, reduced, reduced_length); + } else { + dbar_exp_hrt(symbol, source, length); + } } else { int current_row, current_block, left_to_right; diff --git a/backend/svg.c b/backend/svg.c index 55bd5fc9..048e6fb8 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -53,7 +53,7 @@ static void svg_pick_colour(const int colour, char colour_code[7]) { "000000", /* 6: Black (7) */ "ffffff", /* 7: White (8) */ }; - strcpy(colour_code, rgbs[idx]); + memcpy(colour_code, rgbs[idx], 7); /* Include terminating NUL */ } /* Convert text to use HTML entity codes */ @@ -62,27 +62,27 @@ static void svg_make_html_friendly(const unsigned char *string, char *html_versi for (; *string; string++) { switch (*string) { case '>': - strcpy(html_version, ">"); + memcpy(html_version, ">", 4); html_version += 4; break; case '<': - strcpy(html_version, "<"); + memcpy(html_version, "<", 4); html_version += 4; break; case '&': - strcpy(html_version, "&"); + memcpy(html_version, "&", 5); html_version += 5; break; case '"': - strcpy(html_version, """); + memcpy(html_version, """, 6); html_version += 6; break; case '\'': - strcpy(html_version, "'"); + memcpy(html_version, "'", 6); html_version += 6; break; @@ -133,7 +133,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { struct zint_vector_string *string; char colour_code[7]; - int len, html_len; + int html_len; const int upcean = is_upcean(symbol->symbology); char *html_string; @@ -149,10 +149,9 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { } sprintf(bgcolour_string, "%02X%02X%02X", bgred, bggreen, bgblue); - len = (int) ustrlen(symbol->text); - html_len = len + 1; + html_len = symbol->text_length + 1; - for (i = 0; i < len; i++) { + for (i = 0; i < symbol->text_length; i++) { switch (symbol->text[i]) { case '>': case '<': diff --git a/backend/telepen.c b/backend/telepen.c index 74629a3f..3d7709dc 100644 --- a/backend/telepen.c +++ b/backend/telepen.c @@ -1,7 +1,7 @@ /* telepen.c - Handles Telepen and Telepen numeric */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -91,6 +91,7 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int len int error_number; char dest[1145]; /* 12 (Start) + 69 * 16 (max for DELs) + 16 (Check) + 12 (stop) + 1 = 1145 */ char *d = dest; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; error_number = 0; @@ -137,14 +138,11 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int len (void) set_height(symbol, 0.0f, 50.0f, 0, 1 /*no_errtxt*/); } - for (i = 0; i < length; i++) { - if (source[i] == '\0') { - symbol->text[i] = ' '; - } else { - symbol->text[i] = source[i]; - } + hrt_cpy_iso8859_1(symbol, source, length); + if (plain_hrt) { + hrt_cat_chr_nochk(symbol, check_digit); } - symbol->text[length] = '\0'; + return error_number; } @@ -154,7 +152,8 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int int i; char dest[1129]; /* 12 (Start) + 68 * 16 (max for DELs) + 16 (Check) + 12 (Stop) + 1 = 1129 */ char *d = dest; - unsigned char temp[137]; + unsigned char local_source[137]; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; count = 0; @@ -168,29 +167,28 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int /* Add a leading zero if required */ if (length & 1) { - memcpy(temp + 1, source, length++); - temp[0] = '0'; + memcpy(local_source + 1, source, length++); + local_source[0] = '0'; } else { - memcpy(temp, source, length); + memcpy(local_source, source, length); } - temp[length] = '\0'; - to_upper(temp, length); + to_upper(local_source, length); /* Start character */ memcpy(d, TeleTable['_'], 12); d += 12; for (i = 0; i < length; i += 2) { - if (temp[i] == 'X') { + if (local_source[i] == 'X') { return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 394, "Invalid odd position %d of \"X\" in Telepen data", i + 1); } - if (temp[i + 1] == 'X') { - glyph = ctoi(temp[i]) + 17; + if (local_source[i + 1] == 'X') { + glyph = ctoi(local_source[i]) + 17; count += glyph; } else { - glyph = (10 * ctoi(temp[i])) + ctoi(temp[i + 1]); + glyph = (10 * ctoi(local_source[i])) + ctoi(local_source[i + 1]); glyph += 27; count += glyph; } @@ -219,7 +217,11 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int (void) set_height(symbol, 0.0f, 50.0f, 0, 1 /*no_errtxt*/); } - ustrcpy(symbol->text, temp); + hrt_cpy_nochk(symbol, local_source, length); + if (plain_hrt) { + hrt_cat_chr_nochk(symbol, check_digit); + } + return error_number; } diff --git a/backend/tests/fuzz/fuzz.h b/backend/tests/fuzz/fuzz.h index a1bbe481..b845e6a5 100644 --- a/backend/tests/fuzz/fuzz.h +++ b/backend/tests/fuzz/fuzz.h @@ -1,7 +1,7 @@ /* fuzz.h - common functions for fuzzing libzint */ /* libzint - the open source barcode library - Copyright (C) 2024 Robin Stuart + Copyright (C) 2024-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -311,6 +311,8 @@ static const struct settings_item settings[] = { { 143, BARCODE_UPNQR, 0, 0, -1, 0, -1, ZINT_FULL_MULTIBYTE, 1, 411 }, { 144, BARCODE_ULTRA, 0, -1, 5, 0, 2, ULTRA_COMPRESSION, 1, 504 }, { 145, BARCODE_RMQR, 0, -1, 4, 0, 38, 0, 1, 361 }, + { 146, BARCODE_BC412, ARSENIC_F, 0, -1, 0, -1, 0, 7, 18 }, + { 147, BARCODE_DXFILMEDGE, SILVER_F, 0, -1, 0, -1, 0, 1, 10 }, }; /* Make sure value `v` is between `min` and `max` */ diff --git a/backend/tests/test_2of5.c b/backend/tests/test_2of5.c index bcca5104..d32899c4 100644 --- a/backend/tests/test_2of5.c +++ b/backend/tests/test_2of5.c @@ -115,39 +115,65 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int option_2; + int output_options; const char *data; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_C25STANDARD, -1, "123456789", "123456789" }, - /* 1*/ { BARCODE_C25STANDARD, 1, "123456789", "1234567895" }, - /* 2*/ { BARCODE_C25STANDARD, 2, "123456789", "123456789" }, /* Suppresses printing of check digit */ - /* 3*/ { BARCODE_C25INTER, -1, "123456789", "0123456789" }, /* Adds leading zero if odd */ - /* 4*/ { BARCODE_C25INTER, 1, "123456789", "1234567895" }, /* Unless check digit added when it becomes even */ - /* 5*/ { BARCODE_C25INTER, 2, "123456789", "123456789" }, - /* 6*/ { BARCODE_C25INTER, -1, "1234567890", "1234567890" }, /* No leading zero if even */ - /* 7*/ { BARCODE_C25INTER, 1, "1234567890", "012345678905" }, /* Unless check digit added when it becomes odd */ - /* 8*/ { BARCODE_C25INTER, 2, "1234567890", "01234567890" }, - /* 9*/ { BARCODE_C25IATA, -1, "123456789", "123456789" }, - /* 10*/ { BARCODE_C25IATA, 1, "123456789", "1234567895" }, - /* 11*/ { BARCODE_C25IATA, 2, "123456789", "123456789" }, - /* 12*/ { BARCODE_C25LOGIC, -1, "123456789", "123456789" }, - /* 13*/ { BARCODE_C25LOGIC, 1, "123456789", "1234567895" }, - /* 14*/ { BARCODE_C25LOGIC, 2, "123456789", "123456789" }, - /* 15*/ { BARCODE_C25IND, -1, "123456789", "123456789" }, - /* 16*/ { BARCODE_C25IND, 1, "123456789", "1234567895" }, - /* 17*/ { BARCODE_C25IND, 2, "123456789", "123456789" }, - /* 18*/ { BARCODE_DPLEIT, -1, "123456789", "00001.234.567.890" }, /* Leading zeroes added to make 13 + appended checksum */ - /* 19*/ { BARCODE_DPLEIT, -1, "1234567890123", "12345.678.901.236" }, - /* 20*/ { BARCODE_DPIDENT, -1, "123456789", "00.12 3.456.789 0" }, /* Leading zeroes added to make 11 + appended checksum */ - /* 21*/ { BARCODE_DPIDENT, -1, "12345678901", "12.34 5.678.901 6" }, - /* 22*/ { BARCODE_ITF14, -1, "123456789", "00001234567895" }, /* Leading zeroes added to make 13 + appended checksum */ - /* 23*/ { BARCODE_ITF14, -1, "1234567890123", "12345678901231" }, + /* 0*/ { BARCODE_C25STANDARD, -1, -1, "123456789", "123456789" }, + /* 1*/ { BARCODE_C25STANDARD, -1, BARCODE_PLAIN_HRT, "123456789", "123456789" }, + /* 2*/ { BARCODE_C25STANDARD, 1, -1, "123456789", "1234567895" }, + /* 3*/ { BARCODE_C25STANDARD, 1, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 4*/ { BARCODE_C25STANDARD, 2, -1, "123456789", "123456789" }, /* Suppresses printing of check digit */ + /* 5*/ { BARCODE_C25STANDARD, 2, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, /* Unless plain HRT */ + /* 6*/ { BARCODE_C25INTER, -1, -1, "123456789", "0123456789" }, /* Adds leading zero if odd */ + /* 6*/ { BARCODE_C25INTER, -1, BARCODE_PLAIN_HRT, "123456789", "0123456789" }, + /* 7*/ { BARCODE_C25INTER, 1, -1, "123456789", "1234567895" }, /* Unless check digit added when it becomes even */ + /* 8*/ { BARCODE_C25INTER, 1, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 9*/ { BARCODE_C25INTER, 2, -1, "123456789", "123456789" }, + /* 10*/ { BARCODE_C25INTER, 2, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 11*/ { BARCODE_C25INTER, -1, -1, "1234567890", "1234567890" }, /* No leading zero if even */ + /* 12*/ { BARCODE_C25INTER, -1, BARCODE_PLAIN_HRT, "1234567890", "1234567890" }, + /* 13*/ { BARCODE_C25INTER, 1, -1, "1234567890", "012345678905" }, /* Unless check digit added when it becomes odd */ + /* 14*/ { BARCODE_C25INTER, 1, BARCODE_PLAIN_HRT, "1234567890", "012345678905" }, + /* 15*/ { BARCODE_C25INTER, 2, -1, "1234567890", "01234567890" }, + /* 16*/ { BARCODE_C25INTER, 2, BARCODE_PLAIN_HRT, "1234567890", "012345678905" }, + /* 17*/ { BARCODE_C25IATA, -1, -1, "123456789", "123456789" }, + /* 18*/ { BARCODE_C25IATA, -1, BARCODE_PLAIN_HRT, "123456789", "123456789" }, + /* 19*/ { BARCODE_C25IATA, 1, -1, "123456789", "1234567895" }, + /* 20*/ { BARCODE_C25IATA, 1, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 21*/ { BARCODE_C25IATA, 2, -1, "123456789", "123456789" }, + /* 22*/ { BARCODE_C25IATA, 2, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 23*/ { BARCODE_C25LOGIC, -1, -1, "123456789", "123456789" }, + /* 24*/ { BARCODE_C25LOGIC, -1, BARCODE_PLAIN_HRT, "123456789", "123456789" }, + /* 25*/ { BARCODE_C25LOGIC, 1, -1, "123456789", "1234567895" }, + /* 26*/ { BARCODE_C25LOGIC, 1, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 27*/ { BARCODE_C25LOGIC, 2, -1, "123456789", "123456789" }, + /* 28*/ { BARCODE_C25LOGIC, 2, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 29*/ { BARCODE_C25IND, -1, -1, "123456789", "123456789" }, + /* 30*/ { BARCODE_C25IND, -1, BARCODE_PLAIN_HRT, "123456789", "123456789" }, + /* 31*/ { BARCODE_C25IND, 1, -1, "123456789", "1234567895" }, + /* 32*/ { BARCODE_C25IND, 1, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 33*/ { BARCODE_C25IND, 2, -1, "123456789", "123456789" }, + /* 34*/ { BARCODE_C25IND, 2, BARCODE_PLAIN_HRT, "123456789", "1234567895" }, + /* 35*/ { BARCODE_DPLEIT, -1, -1, "123456789", "00001.234.567.890" }, /* Leading zeroes added to make 13 + appended checksum */ + /* 36*/ { BARCODE_DPLEIT, -1, BARCODE_PLAIN_HRT, "123456789", "00001234567890" }, + /* 37*/ { BARCODE_DPLEIT, -1, -1, "1234567890123", "12345.678.901.236" }, + /* 38*/ { BARCODE_DPLEIT, -1, BARCODE_PLAIN_HRT, "1234567890123", "12345678901236" }, + /* 39*/ { BARCODE_DPIDENT, -1, -1, "123456789", "00.12 3.456.789 0" }, /* Leading zeroes added to make 11 + appended checksum */ + /* 40*/ { BARCODE_DPIDENT, -1, BARCODE_PLAIN_HRT, "123456789", "001234567890" }, + /* 41*/ { BARCODE_DPIDENT, -1, -1, "12345678901", "12.34 5.678.901 6" }, + /* 42*/ { BARCODE_DPIDENT, -1, BARCODE_PLAIN_HRT, "12345678901", "123456789016" }, + /* 43*/ { BARCODE_ITF14, -1, -1, "123456789", "00001234567895" }, /* Leading zeroes added to make 13 + appended checksum */ + /* 44*/ { BARCODE_ITF14, -1, BARCODE_PLAIN_HRT, "123456789", "00001234567895" }, + /* 45*/ { BARCODE_ITF14, -1, -1, "1234567890123", "12345678901231" }, + /* 46*/ { BARCODE_ITF14, -1, BARCODE_PLAIN_HRT, "1234567890123", "12345678901231" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -158,12 +184,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_auspost.c b/backend/tests/test_auspost.c index 0fa07e86..f953c758 100644 --- a/backend/tests/test_auspost.c +++ b/backend/tests/test_auspost.c @@ -100,17 +100,42 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; + int output_options; const char *data; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_AUSPOST, "12345678901234567890123", "" }, /* None */ + /* 0*/ { BARCODE_AUSPOST, -1, "12345678", "" }, /* None */ + /* 1*/ { BARCODE_AUSPOST, BARCODE_PLAIN_HRT, "12345678", "1112345678" }, + /* 2*/ { BARCODE_AUSPOST, -1, "1234567890123", "" }, /* None */ + /* 3*/ { BARCODE_AUSPOST, BARCODE_PLAIN_HRT, "1234567890123", "591234567890123" }, + /* 4*/ { BARCODE_AUSPOST, -1, "1234567890123456", "" }, /* None */ + /* 5*/ { BARCODE_AUSPOST, BARCODE_PLAIN_HRT, "1234567890123456", "591234567890123456" }, + /* 6*/ { BARCODE_AUSPOST, -1, "123456789012345678", "" }, /* None */ + /* 7*/ { BARCODE_AUSPOST, BARCODE_PLAIN_HRT, "123456789012345678", "62123456789012345678" }, + /* 8*/ { BARCODE_AUSPOST, -1, "12345678901234567890123", "" }, /* None */ + /* 9*/ { BARCODE_AUSPOST, BARCODE_PLAIN_HRT, "12345678901234567890123", "6212345678901234567890123" }, + /* 10*/ { BARCODE_AUSREPLY, -1, "1234567", "" }, /* None */ + /* 11*/ { BARCODE_AUSREPLY, BARCODE_PLAIN_HRT, "1234567", "4501234567" }, + /* 12*/ { BARCODE_AUSREPLY, -1, "12345678", "" }, /* None */ + /* 13*/ { BARCODE_AUSREPLY, BARCODE_PLAIN_HRT, "12345678", "4512345678" }, + /* 14*/ { BARCODE_AUSROUTE, -1, "123456", "" }, /* None */ + /* 15*/ { BARCODE_AUSROUTE, BARCODE_PLAIN_HRT, "123456", "8700123456" }, + /* 16*/ { BARCODE_AUSROUTE, -1, "12345678", "" }, /* None */ + /* 17*/ { BARCODE_AUSROUTE, BARCODE_PLAIN_HRT, "12345678", "8712345678" }, + /* 18*/ { BARCODE_AUSROUTE, -1, "12345", "" }, /* None */ + /* 19*/ { BARCODE_AUSROUTE, BARCODE_PLAIN_HRT, "12345", "8700012345" }, + /* 20*/ { BARCODE_AUSREDIRECT, -1, "12345678", "" }, /* None */ + /* 21*/ { BARCODE_AUSREDIRECT, BARCODE_PLAIN_HRT, "12345678", "9212345678" }, + /* 22*/ { BARCODE_AUSREDIRECT, -1, "1234", "" }, /* None */ + /* 23*/ { BARCODE_AUSREDIRECT, BARCODE_PLAIN_HRT, "1234", "9200001234" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -121,12 +146,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_bc412.c b/backend/tests/test_bc412.c index 94d18fa4..4cf26373 100644 --- a/backend/tests/test_bc412.c +++ b/backend/tests/test_bc412.c @@ -36,8 +36,7 @@ static void test_input(const testCtx *const p_ctx) { struct item { int input_mode; - int option_1; - int option_2; + int output_options; const char *data; int length; int ret; @@ -48,32 +47,39 @@ static void test_input(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, -1, "123456", -1, ZINT_ERROR_TOO_LONG, -1, -1, "Error 792: Input length 6 too short (minimum 7)", "" }, - /* 1*/ { UNICODE_MODE, -1, -1, "1234567890123456789", -1, ZINT_ERROR_TOO_LONG, -1, -1, "Error 790: Input length 19 too long (maximum 18)", "" }, - /* 2*/ { UNICODE_MODE, -1, -1, "1234567", -1, 0, 1, 102, "1U234567", "" }, - /* 3*/ { UNICODE_MODE, -1, -1, "1234567 ", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 791: Invalid character at position 8 in input (alphanumerics only, excluding \"O\")", "" }, - /* 4*/ { UNICODE_MODE, -1, -1, "ABCDEFGHIJKLMNOPQR", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 791: Invalid character at position 15 in input (alphanumerics only, excluding \"O\")", "" }, - /* 5*/ { UNICODE_MODE, -1, -1, "ABCDEFGHIJKLMNPQRS", -1, 0, 1, 234, "AQBCDEFGHIJKLMNPQRS", "" }, - /* 6*/ { UNICODE_MODE, -1, -1, "STUVWXYZ1234567890", -1, 0, 1, 234, "SCTUVWXYZ1234567890", "" }, - /* 7*/ { UNICODE_MODE, -1, -1, "abcdefghijklmnpqrs", -1, 0, 1, 234, "AQBCDEFGHIJKLMNPQRS", "" }, - /* 8*/ { UNICODE_MODE, -1, -1, "123456789012345678", -1, 0, 1, 234, "1223456789012345678", "" }, - /* 9*/ { UNICODE_MODE, -1, -1, "MMMMMMMMMMMMMMMMMM", -1, 0, 1, 234, "MTMMMMMMMMMMMMMMMMM", "" }, - /* 10*/ { UNICODE_MODE, -1, -1, "00000000", -1, 0, 1, 114, "000000000", "" }, - /* 11*/ { UNICODE_MODE, -1, -1, "000000000", -1, 0, 1, 126, "0000000000", "" }, - /* 12*/ { UNICODE_MODE, -1, -1, "000S0S000S", -1, 0, 1, 138, "0S00S0S000S", "" }, - /* 13*/ { UNICODE_MODE, -1, -1, "ZYXWVUTSRQP", -1, 0, 1, 150, "Z0YXWVUTSRQP", "" }, - /* 14*/ { UNICODE_MODE, -1, -1, "0R9GLVHA8EZ4", -1, 0, 1, 162, "0DR9GLVHA8EZ4", "" }, - /* 15*/ { UNICODE_MODE, -1, -1, "NTS1J2Q6C7DYK", -1, 0, 1, 174, "NRTS1J2Q6C7DYK", "" }, - /* 16*/ { UNICODE_MODE, -1, -1, "TS1J2Q6C7DYKBU", -1, 0, 1, 186, "TWS1J2Q6C7DYKBU", "" }, - /* 17*/ { UNICODE_MODE, -1, -1, "IX3FWP5M0R9GLVH", -1, 0, 1, 198, "IBX3FWP5M0R9GLVH", "" }, - /* 18*/ { UNICODE_MODE, -1, -1, "R9GLVHA8EZ4NTS1J", -1, 0, 1, 210, "RY9GLVHA8EZ4NTS1J", "" }, - /* 19*/ { UNICODE_MODE, -1, -1, "M5PWF3XIUBKYD7C6Q", -1, 0, 1, 222, "M35PWF3XIUBKYD7C6Q", "" }, - /* 20*/ { UNICODE_MODE, -1, -1, "2J1STN4ZE8AHVLG90R", -1, 0, 1, 234, "2PJ1STN4ZE8AHVLG90R", "" }, - /* 21*/ { UNICODE_MODE, -1, -1, "JJJJJJJJJJJJJJJJJJ", -1, 0, 1, 234, "J9JJJJJJJJJJJJJJJJJ", "" }, + /* 0*/ { UNICODE_MODE, -1, "123456", -1, ZINT_ERROR_TOO_LONG, -1, -1, "Error 792: Input length 6 too short (minimum 7)", "" }, + /* 1*/ { UNICODE_MODE, -1, "1234567890123456789", -1, ZINT_ERROR_TOO_LONG, -1, -1, "Error 790: Input length 19 too long (maximum 18)", "" }, + /* 2*/ { UNICODE_MODE, -1, "1234567", -1, 0, 1, 102, "1U234567", "" }, + /* 3*/ { UNICODE_MODE, BARCODE_PLAIN_HRT, "1234567", -1, 0, 1, 102, "1U234567", "" }, /* No difference */ + /* 4*/ { UNICODE_MODE, -1, "1234567 ", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 791: Invalid character at position 8 in input (alphanumerics only, excluding \"O\")", "" }, + /* 5*/ { UNICODE_MODE, -1, "ABCDEFGHIJKLMNOPQR", -1, ZINT_ERROR_INVALID_DATA, -1, -1, "Error 791: Invalid character at position 15 in input (alphanumerics only, excluding \"O\")", "" }, + /* 6*/ { UNICODE_MODE, -1, "ABCDEFGHIJKLMNPQRS", -1, 0, 1, 234, "AQBCDEFGHIJKLMNPQRS", "" }, + /* 7*/ { UNICODE_MODE, BARCODE_PLAIN_HRT, "ABCDEFGHIJKLMNPQRS", -1, 0, 1, 234, "AQBCDEFGHIJKLMNPQRS", "" }, /* No difference */ + /* 8*/ { UNICODE_MODE, -1, "STUVWXYZ1234567890", -1, 0, 1, 234, "SCTUVWXYZ1234567890", "" }, + /* 9*/ { UNICODE_MODE, -1, "abcdefghijklmnpqrs", -1, 0, 1, 234, "AQBCDEFGHIJKLMNPQRS", "" }, + /* 10*/ { UNICODE_MODE, BARCODE_PLAIN_HRT, "abcdefghijklmnpqrs", -1, 0, 1, 234, "AQBCDEFGHIJKLMNPQRS", "" }, /* No difference */ + /* 11*/ { UNICODE_MODE, -1, "123456789012345678", -1, 0, 1, 234, "1223456789012345678", "" }, + /* 12*/ { UNICODE_MODE, -1, "MMMMMMMMMMMMMMMMMM", -1, 0, 1, 234, "MTMMMMMMMMMMMMMMMMM", "" }, + /* 13*/ { UNICODE_MODE, -1, "00000000", -1, 0, 1, 114, "000000000", "" }, + /* 14*/ { UNICODE_MODE, BARCODE_PLAIN_HRT, "00000000", -1, 0, 1, 114, "000000000", "" }, /* No difference */ + /* 15*/ { UNICODE_MODE, -1, "000000000", -1, 0, 1, 126, "0000000000", "" }, + /* 16*/ { UNICODE_MODE, BARCODE_PLAIN_HRT, "000000000", -1, 0, 1, 126, "0000000000", "" }, /* No difference */ + /* 17*/ { UNICODE_MODE, -1, "000S0S000S", -1, 0, 1, 138, "0S00S0S000S", "" }, + /* 18*/ { UNICODE_MODE, -1, "ZYXWVUTSRQP", -1, 0, 1, 150, "Z0YXWVUTSRQP", "" }, + /* 19*/ { UNICODE_MODE, -1, "0R9GLVHA8EZ4", -1, 0, 1, 162, "0DR9GLVHA8EZ4", "" }, + /* 20*/ { UNICODE_MODE, -1, "NTS1J2Q6C7DYK", -1, 0, 1, 174, "NRTS1J2Q6C7DYK", "" }, + /* 21*/ { UNICODE_MODE, -1, "TS1J2Q6C7DYKBU", -1, 0, 1, 186, "TWS1J2Q6C7DYKBU", "" }, + /* 22*/ { UNICODE_MODE, -1, "IX3FWP5M0R9GLVH", -1, 0, 1, 198, "IBX3FWP5M0R9GLVH", "" }, + /* 23*/ { UNICODE_MODE, -1, "R9GLVHA8EZ4NTS1J", -1, 0, 1, 210, "RY9GLVHA8EZ4NTS1J", "" }, + /* 24*/ { UNICODE_MODE, -1, "M5PWF3XIUBKYD7C6Q", -1, 0, 1, 222, "M35PWF3XIUBKYD7C6Q", "" }, + /* 25*/ { UNICODE_MODE, -1, "2J1STN4ZE8AHVLG90R", -1, 0, 1, 234, "2PJ1STN4ZE8AHVLG90R", "" }, + /* 26*/ { UNICODE_MODE, -1, "JJJJJJJJJJJJJJJJJJ", -1, 0, 1, 234, "J9JJJJJJJJJJJJJJJJJ", "" }, + /* 27*/ { UNICODE_MODE, BARCODE_PLAIN_HRT, "JJJJJJJJJJJJJJJJJJ", -1, 0, 1, 234, "J9JJJJJJJJJJJJJJJJJ", "" }, /* No difference */ }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; char bwipp_buf[8192]; char bwipp_msg[1024]; @@ -89,20 +95,28 @@ static void test_input(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, BARCODE_BC412, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, BARCODE_BC412, data[i].input_mode, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, data[i].length, debug); + expected_length = (int) strlen(data[i].expected); 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); if (ret < ZINT_ERROR) { - assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, 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((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", + i, symbol->rows, data[i].expected_rows, 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_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); - if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { char modules_dump[8192 + 1]; assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, modules_dump); @@ -124,8 +138,6 @@ static void test_encode(const testCtx *const p_ctx) { struct item { int input_mode; - int option_1; - int option_2; const char *data; int ret; @@ -136,10 +148,10 @@ static void test_encode(const testCtx *const p_ctx) { const char *expected; }; static const struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, -1, "AQ45670", 0, 1, 102, 1, "SEMI T1-95 Figure 2, same", + /* 0*/ { UNICODE_MODE, "AQ45670", 0, 1, 102, 1, "SEMI T1-95 Figure 2, same", "100101000100100100010101000100010101000101010000010101001010000101001001000101001000100101010100000101" }, - /* 1*/ { UNICODE_MODE, -1, -1, "A6BC1234", 0, 1, 114, 1, "https://www.grapecity.co.jp, same", + /* 1*/ { UNICODE_MODE, "A6BC1234", 0, 1, 114, 1, "https://www.grapecity.co.jp, same", "100101000100100100100010100101001001000101000100010101000010100101010010000101010001000101010000100101010000010101" }, }; @@ -162,14 +174,14 @@ static void test_encode(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, BARCODE_BC412, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_BC412, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -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); if (p_ctx->generate) { - printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, %d, %d, %d, \"%s\",\n", - i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, + printf(" /*%3d*/ { %s, \"%s\", %s, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); testUtilModulesPrint(symbol, " ", "\n"); @@ -184,11 +196,11 @@ static void test_encode(const testCtx *const p_ctx) { ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); - if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { if (!data[i].bwipp_cmp) { if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); } else { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); diff --git a/backend/tests/test_channel.c b/backend/tests/test_channel.c index a52c1b5d..c3927d46 100644 --- a/backend/tests/test_channel.c +++ b/backend/tests/test_channel.c @@ -36,6 +36,7 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int option_2; + int output_options; const char *data; int length; @@ -43,31 +44,43 @@ static void test_hrt(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { -1, "1", -1, "01" }, - /* 1*/ { 3, "1", -1, "01" }, - /* 2*/ { 3, "12", -1, "12" }, - /* 3*/ { 4, "123", -1, "123" }, - /* 4*/ { 5, "123", -1, "0123" }, - /* 5*/ { 5, "12", -1, "0012" }, - /* 6*/ { 5, "1", -1, "0001" }, - /* 7*/ { 5, "1234", -1, "1234" }, - /* 8*/ { 6, "1234", -1, "01234" }, - /* 9*/ { 6, "123", -1, "00123" }, - /* 10*/ { 6, "12", -1, "00012" }, - /* 11*/ { 6, "1", -1, "00001" }, - /* 12*/ { 7, "1234", -1, "001234" }, - /* 13*/ { 7, "12345", -1, "012345" }, - /* 14*/ { 7, "123456", -1, "123456" }, - /* 15*/ { 7, "1", -1, "000001" }, - /* 16*/ { 8, "12345", -1, "0012345" }, - /* 17*/ { 8, "123456", -1, "0123456" }, - /* 18*/ { 8, "1234567", -1, "1234567" }, - /* 19*/ { 8, "12", -1, "0000012" }, - /* 20*/ { 8, "1", -1, "0000001" }, + /* 0*/ { -1, -1, "1", -1, "01" }, + /* 1*/ { -1, BARCODE_PLAIN_HRT, "1", -1, "01" }, /* No difference */ + /* 2*/ { 3, -1, "1", -1, "01" }, + /* 3*/ { 3, BARCODE_PLAIN_HRT, "1", -1, "01" }, + /* 4*/ { 3, -1, "12", -1, "12" }, + /* 5*/ { 3, BARCODE_PLAIN_HRT, "12", -1, "12" }, + /* 6*/ { 4, -1, "123", -1, "123" }, + /* 7*/ { 4, BARCODE_PLAIN_HRT, "123", -1, "123" }, + /* 8*/ { 5, -1, "123", -1, "0123" }, + /* 9*/ { 5, BARCODE_PLAIN_HRT, "123", -1, "0123" }, + /* 10*/ { 5, -1, "12", -1, "0012" }, + /* 11*/ { 5, BARCODE_PLAIN_HRT, "12", -1, "0012" }, + /* 12*/ { 5, -1, "1", -1, "0001" }, + /* 13*/ { 5, -1, "1234", -1, "1234" }, + /* 14*/ { 6, -1, "1234", -1, "01234" }, + /* 15*/ { 6, -1, "123", -1, "00123" }, + /* 16*/ { 6, -1, "12", -1, "00012" }, + /* 17*/ { 6, -1, "1", -1, "00001" }, + /* 18*/ { 7, -1, "1234", -1, "001234" }, + /* 19*/ { 7, -1, "12345", -1, "012345" }, + /* 20*/ { 7, -1, "123456", -1, "123456" }, + /* 21*/ { 7, -1, "1", -1, "000001" }, + /* 22*/ { 8, -1, "12345", -1, "0012345" }, + /* 23*/ { 8, BARCODE_PLAIN_HRT, "12345", -1, "0012345" }, + /* 24*/ { 8, -1, "123456", -1, "0123456" }, + /* 25*/ { 8, BARCODE_PLAIN_HRT, "123456", -1, "0123456" }, + /* 26*/ { 8, -1, "1234567", -1, "1234567" }, + /* 27*/ { 8, BARCODE_PLAIN_HRT, "1234567", -1, "1234567" }, + /* 28*/ { 8, -1, "12", -1, "0000012" }, + /* 29*/ { 8, BARCODE_PLAIN_HRT, "12", -1, "0000012" }, + /* 30*/ { 8, -1, "1", -1, "0000001" }, + /* 31*/ { 8, BARCODE_PLAIN_HRT, "1", -1, "0000001" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -78,12 +91,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, BARCODE_CHANNEL, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, BARCODE_CHANNEL, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1, data[i].output_options, + data[i].data, data[i].length, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_codabar.c b/backend/tests/test_codabar.c index 22ce64f2..8b81bd8e 100644 --- a/backend/tests/test_codabar.c +++ b/backend/tests/test_codabar.c @@ -92,22 +92,30 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int option_2; + int output_options; const char *data; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODABAR, -1, "A1234B", "A1234B" }, - /* 1*/ { BARCODE_CODABAR, -1, "a1234c", "A1234C" }, /* Converts to upper */ - /* 2*/ { BARCODE_CODABAR, 1, "A1234B", "A1234B" }, /* Check not included */ - /* 3*/ { BARCODE_CODABAR, 2, "A1234B", "A12345B" }, /* Check included */ - /* 4*/ { BARCODE_CODABAR, 1, "A123456A", "A123456A" }, /* Check not included */ - /* 5*/ { BARCODE_CODABAR, 2, "A123456A", "A123456$A" }, /* Check included */ + /* 0*/ { BARCODE_CODABAR, -1, -1, "A1234B", "A1234B" }, + /* 1*/ { BARCODE_CODABAR, -1, BARCODE_PLAIN_HRT, "A1234B", "A1234B" }, + /* 2*/ { BARCODE_CODABAR, -1, -1, "a1234c", "A1234C" }, /* Converts to upper */ + /* 3*/ { BARCODE_CODABAR, -1, BARCODE_PLAIN_HRT, "a1234c", "A1234C" }, + /* 4*/ { BARCODE_CODABAR, 1, -1, "A1234B", "A1234B" }, /* Check not included */ + /* 5*/ { BARCODE_CODABAR, 1, BARCODE_PLAIN_HRT, "A1234B", "A12345B" }, + /* 6*/ { BARCODE_CODABAR, 2, -1, "A1234B", "A12345B" }, /* Check included */ + /* 7*/ { BARCODE_CODABAR, 2, BARCODE_PLAIN_HRT, "A1234B", "A12345B" }, + /* 8*/ { BARCODE_CODABAR, 1, -1, "A123456A", "A123456A" }, /* Check not included */ + /* 9*/ { BARCODE_CODABAR, 1, BARCODE_PLAIN_HRT, "A123456A", "A123456$A" }, + /* 10*/ { BARCODE_CODABAR, 2, -1, "A123456A", "A123456$A" }, /* Check included */ + /* 11*/ { BARCODE_CODABAR, 2, BARCODE_PLAIN_HRT, "A123456A", "A123456$A" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -118,12 +126,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_codablock.c b/backend/tests/test_codablock.c index 6570f74d..e4d6a5b8 100644 --- a/backend/tests/test_codablock.c +++ b/backend/tests/test_codablock.c @@ -254,6 +254,58 @@ static void test_reader_init(const testCtx *const p_ctx) { testFinish(); } +static void test_hrt(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_1; + int option_2; + int output_options; + const char *data; + + const char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_CODABLOCKF, -1, -1, -1, "12345623456", "" }, /* None */ + /* 1*/ { BARCODE_CODABLOCKF, -1, -1, BARCODE_PLAIN_HRT, "12345623456", "" }, /* No difference */ + /* 2*/ { BARCODE_CODABLOCKF, 1, -1, -1, "12345623456", "" }, /* None (CODE128) */ + /* 3*/ { BARCODE_CODABLOCKF, 1, -1, BARCODE_PLAIN_HRT, "12345623456", "" }, /* No difference */ + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + int expected_length; + + testStartSymbol("test_hrt", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + data[i].option_1, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); + + ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(memcmp(symbol->text, data[i].expected, expected_length), "i:%d memcmp(%s, %s, %d) != 0\n", + i, symbol->text, data[i].expected, expected_length); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_input(const testCtx *const p_ctx) { int debug = p_ctx->debug; @@ -681,6 +733,7 @@ int main(int argc, char *argv[]) { { "test_large", test_large }, { "test_options", test_options }, { "test_reader_init", test_reader_init }, + { "test_hrt", test_hrt }, { "test_input", test_input }, { "test_encode", test_encode }, { "test_fuzz", test_fuzz }, diff --git a/backend/tests/test_code.c b/backend/tests/test_code.c index 0ea200c4..20343b92 100644 --- a/backend/tests/test_code.c +++ b/backend/tests/test_code.c @@ -111,47 +111,84 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int option_2; + int output_options; const char *data; int length; const char *expected; + int expected_length; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODE39, -1, "ABC1234", -1, "*ABC1234*" }, - /* 1*/ { BARCODE_CODE39, 1, "ABC1234", -1, "*ABC12340*" }, /* With visible check digit */ - /* 2*/ { BARCODE_CODE39, -1, "abc1234", -1, "*ABC1234*" }, /* Converts to upper */ - /* 3*/ { BARCODE_CODE39, 1, "abc1234", -1, "*ABC12340*" }, /* Converts to upper */ - /* 4*/ { BARCODE_CODE39, -1, "123456789", -1, "*123456789*" }, - /* 5*/ { BARCODE_CODE39, 1, "123456789", -1, "*1234567892*" }, /* With visible check digit */ - /* 6*/ { BARCODE_CODE39, 2, "123456789", -1, "*123456789*" }, /* With hidden check digit */ - /* 7*/ { BARCODE_EXCODE39, -1, "ABC1234", -1, "ABC1234" }, - /* 8*/ { BARCODE_EXCODE39, 1, "ABC1234", -1, "ABC12340" }, /* With visible check digit */ - /* 9*/ { BARCODE_EXCODE39, -1, "abc1234", -1, "abc1234" }, - /* 10*/ { BARCODE_EXCODE39, 1, "abc1234", -1, "abc1234." }, /* With visible check digit (previously was hidden) */ - /* 11*/ { BARCODE_EXCODE39, 2, "abc1234", -1, "abc1234" }, /* With hidden check digit */ - /* 12*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~" }, /* NUL, ctrls and DEL replaced with spaces */ - /* 13*/ { BARCODE_EXCODE39, 1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~L" }, /* With visible check digit */ - /* 14*/ { BARCODE_EXCODE39, 2, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~" }, /* With hidden check digit */ - /* 15*/ { BARCODE_LOGMARS, -1, "ABC1234", -1, "ABC1234" }, - /* 16*/ { BARCODE_LOGMARS, -1, "abc1234", -1, "ABC1234" }, /* Converts to upper */ - /* 17*/ { BARCODE_LOGMARS, 1, "abc1234", -1, "ABC12340" }, /* With check digit */ - /* 18*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, "12345/ABCDET" }, /* With visible check digit */ - /* 19*/ { BARCODE_LOGMARS, 2, "12345/ABCDE", -1, "12345/ABCDE" }, /* With hidden check digit */ - /* 20*/ { BARCODE_CODE93, -1, "ABC1234", -1, "ABC1234" }, /* No longer shows 2 check chars added (same as BWIPP and TEC-IT) */ - /* 21*/ { BARCODE_CODE93, 1, "ABC1234", -1, "ABC1234S5" }, /* Unless requested */ - /* 22*/ { BARCODE_CODE93, -1, "abc1234", -1, "abc1234" }, - /* 23*/ { BARCODE_CODE93, 1, "abc1234", -1, "abc1234ZG" }, - /* 24*/ { BARCODE_CODE93, -1, "A\001a\000b\177d\037e", 9, "A a b d e" }, /* NUL, ctrls and DEL replaced with spaces */ - /* 25*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, "1FTCR10UXTPA78180" }, - /* 26*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, "2FTPX28L0XCA15511" }, /* Include Import char - no change */ - /* 27*/ { BARCODE_HIBC_39, -1, "ABC1234", -1, "*+ABC1234+*" }, - /* 28*/ { BARCODE_HIBC_39, -1, "abc1234", -1, "*+ABC1234+*" }, /* Converts to upper */ - /* 29*/ { BARCODE_HIBC_39, -1, "123456789", -1, "*+1234567890*" }, + /* 0*/ { BARCODE_CODE39, -1, -1, "ABC1234", -1, "*ABC1234*", -1 }, + /* 1*/ { BARCODE_CODE39, -1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC1234", -1 }, + /* 2*/ { BARCODE_CODE39, 1, -1, "ABC1234", -1, "*ABC12340*", -1 }, /* With visible check digit */ + /* 3*/ { BARCODE_CODE39, 1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC12340", -1 }, + /* 4*/ { BARCODE_CODE39, -1, -1, "abc1234", -1, "*ABC1234*", -1 }, /* Converts to upper */ + /* 5*/ { BARCODE_CODE39, -1, BARCODE_PLAIN_HRT, "abc1234", -1, "ABC1234", -1 }, + /* 6*/ { BARCODE_CODE39, 1, -1, "abc1234", -1, "*ABC12340*", -1 }, /* Converts to upper */ + /* 7*/ { BARCODE_CODE39, 1, BARCODE_PLAIN_HRT, "abc1234", -1, "ABC12340", -1 }, + /* 8*/ { BARCODE_CODE39, 1, -1, "ab", -1, "*ABL*", -1 }, /* Converts to upper */ + /* 9*/ { BARCODE_CODE39, 1, BARCODE_PLAIN_HRT, "ab", -1, "ABL", -1 }, + /* 10*/ { BARCODE_CODE39, -1, -1, "123456789", -1, "*123456789*", -1 }, + /* 11*/ { BARCODE_CODE39, -1, BARCODE_PLAIN_HRT, "123456789", -1, "123456789", -1 }, + /* 12*/ { BARCODE_CODE39, 1, -1, "123456789", -1, "*1234567892*", -1 }, /* With visible check digit */ + /* 13*/ { BARCODE_CODE39, 1, BARCODE_PLAIN_HRT, "123456789", -1, "1234567892", -1 }, + /* 14*/ { BARCODE_CODE39, 2, -1, "123456789", -1, "*123456789*", -1 }, /* With hidden check digit */ + /* 15*/ { BARCODE_CODE39, 2, BARCODE_PLAIN_HRT, "123456789", -1, "1234567892", -1 }, /* Includes check digit */ + /* 16*/ { BARCODE_EXCODE39, -1, -1, "ABC1234", -1, "ABC1234", -1 }, + /* 17*/ { BARCODE_EXCODE39, -1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC1234", -1 }, + /* 18*/ { BARCODE_EXCODE39, 1, -1, "ABC1234", -1, "ABC12340", -1 }, /* With visible check digit */ + /* 19*/ { BARCODE_EXCODE39, 1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC12340", -1 }, + /* 20*/ { BARCODE_EXCODE39, -1, -1, "abc1234", -1, "abc1234", -1 }, + /* 21*/ { BARCODE_EXCODE39, -1, BARCODE_PLAIN_HRT, "abc1234", -1, "abc1234", -1 }, + /* 22*/ { BARCODE_EXCODE39, 1, -1, "abc1234", -1, "abc1234.", -1 }, /* With visible check digit (previously was hidden) */ + /* 23*/ { BARCODE_EXCODE39, 1, BARCODE_PLAIN_HRT, "abc1234", -1, "abc1234.", -1 }, + /* 24*/ { BARCODE_EXCODE39, 2, -1, "abc1234", -1, "abc1234", -1 }, /* With hidden check digit */ + /* 25*/ { BARCODE_EXCODE39, 2, BARCODE_PLAIN_HRT, "abc1234", -1, "abc1234.", -1 }, /* Includes check digit */ + /* 26*/ { BARCODE_EXCODE39, -1, -1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~", -1 }, /* NUL, ctrls and DEL replaced with spaces */ + /* 27*/ { BARCODE_EXCODE39, -1, BARCODE_PLAIN_HRT, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a%\000\001$\177z\033\037!+/\\@A~", 16 }, /* No replacements */ + /* 28*/ { BARCODE_EXCODE39, 1, -1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~L", -1 }, /* With visible check digit */ + /* 29*/ { BARCODE_EXCODE39, 1, BARCODE_PLAIN_HRT, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a%\000\001$\177z\033\037!+/\\@A~L", 17 }, + /* 30*/ { BARCODE_EXCODE39, 2, -1, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a% $ z !+/\\@A~", -1 }, /* With hidden check digit */ + /* 31*/ { BARCODE_EXCODE39, 2, BARCODE_PLAIN_HRT, "a%\000\001$\177z\033\037!+/\\@A~", 16, "a%\000\001$\177z\033\037!+/\\@A~L", 17 }, /* Includes check digit */ + /* 32*/ { BARCODE_LOGMARS, -1, -1, "ABC1234", -1, "ABC1234", -1 }, + /* 33*/ { BARCODE_LOGMARS, -1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC1234", -1 }, + /* 34*/ { BARCODE_LOGMARS, -1, -1, "abc1234", -1, "ABC1234", -1 }, /* Converts to upper */ + /* 35*/ { BARCODE_LOGMARS, -1, BARCODE_PLAIN_HRT, "abc1234", -1, "ABC1234", -1 }, + /* 36*/ { BARCODE_LOGMARS, 1, -1, "abc1234", -1, "ABC12340", -1 }, /* With check digit */ + /* 37*/ { BARCODE_LOGMARS, 1, BARCODE_PLAIN_HRT, "abc1234", -1, "ABC12340", -1 }, + /* 38*/ { BARCODE_LOGMARS, 1, -1, "12345/ABCDE", -1, "12345/ABCDET", -1 }, /* With visible check digit */ + /* 39*/ { BARCODE_LOGMARS, 1, BARCODE_PLAIN_HRT, "12345/ABCDE", -1, "12345/ABCDET", -1 }, + /* 40*/ { BARCODE_LOGMARS, 2, -1, "12345/ABCDE", -1, "12345/ABCDE", -1 }, /* With hidden check digit */ + /* 41*/ { BARCODE_LOGMARS, 2, BARCODE_PLAIN_HRT, "12345/ABCDE", -1, "12345/ABCDET", -1 }, /* Includes check digit */ + /* 42*/ { BARCODE_CODE93, -1, -1, "ABC1234", -1, "ABC1234", -1 }, /* No longer shows 2 check chars added (same as BWIPP and TEC-IT) */ + /* 43*/ { BARCODE_CODE93, -1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC1234S5", -1 }, /* Unless BARCODE_PLAIN_HRT */ + /* 44*/ { BARCODE_CODE93, 1, -1, "ABC1234", -1, "ABC1234S5", -1 }, /* Unless requested */ + /* 45*/ { BARCODE_CODE93, 1, BARCODE_PLAIN_HRT, "ABC1234", -1, "ABC1234S5", -1 }, + /* 46*/ { BARCODE_CODE93, -1, -1, "abc1234", -1, "abc1234", -1 }, + /* 47*/ { BARCODE_CODE93, -1, BARCODE_PLAIN_HRT, "abc1234", -1, "abc1234ZG", -1 }, + /* 48*/ { BARCODE_CODE93, 1, -1, "abc1234", -1, "abc1234ZG", -1 }, + /* 49*/ { BARCODE_CODE93, 1, BARCODE_PLAIN_HRT, "abc1234", -1, "abc1234ZG", -1 }, + /* 50*/ { BARCODE_CODE93, -1, -1, "A\001a\000b\177d\037e", 9, "A a b d e", -1 }, /* NUL, ctrls and DEL replaced with spaces */ + /* 51*/ { BARCODE_CODE93, -1, BARCODE_PLAIN_HRT, "A\001a\000b\177d\037e", 9, "A\001a\000b\177d\037e1R", 11 }, /* No replacements */ + /* 52*/ { BARCODE_CODE93, 1, -1, "A\001a\000b\177d\037e", 9, "A a b d e1R", -1 }, + /* 53*/ { BARCODE_CODE93, 1, BARCODE_PLAIN_HRT, "A\001a\000b\177d\037e", 9, "A\001a\000b\177d\037e1R", 11 }, + /* 54*/ { BARCODE_VIN, -1, -1, "1FTCR10UXTPA78180", -1, "1FTCR10UXTPA78180", -1 }, + /* 55*/ { BARCODE_VIN, -1, BARCODE_PLAIN_HRT, "1FTCR10UXTPA78180", -1, "1FTCR10UXTPA78180", -1 }, + /* 56*/ { BARCODE_VIN, 1, -1, "2FTPX28L0XCA15511", -1, "2FTPX28L0XCA15511", -1 }, /* Include Import char - no change */ + /* 57*/ { BARCODE_VIN, 1, BARCODE_PLAIN_HRT, "2FTPX28L0XCA15511", -1, "I2FTPX28L0XCA15511", -1 }, /* Unless BARCODE_PLAIN_HRT */ + /* 58*/ { BARCODE_HIBC_39, -1, -1, "ABC1234", -1, "*+ABC1234+*", -1 }, + /* 59*/ { BARCODE_HIBC_39, -1, BARCODE_PLAIN_HRT, "ABC1234", -1, "+ABC1234+", -1 }, + /* 60*/ { BARCODE_HIBC_39, -1, -1, "abc1234", -1, "*+ABC1234+*", -1 }, /* Converts to upper */ + /* 61*/ { BARCODE_HIBC_39, -1, BARCODE_PLAIN_HRT, "abc1234", -1, "+ABC1234+", -1 }, + /* 62*/ { BARCODE_HIBC_39, -1, -1, "123456789", -1, "*+1234567890*", -1 }, + /* 63*/ { BARCODE_HIBC_39, -1, BARCODE_PLAIN_HRT, "123456789", -1, "+1234567890", -1 }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -162,12 +199,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, data[i].length, debug); + expected_length = data[i].expected_length == -1 ? (int) strlen(data[i].expected) : data[i].expected_length; ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(memcmp(symbol->text, data[i].expected, expected_length), "i:%d memcmp(%s, %s, %d) != 0\n", + i, symbol->text, data[i].expected, expected_length); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_code11.c b/backend/tests/test_code11.c index 55fc53bf..f74c467c 100644 --- a/backend/tests/test_code11.c +++ b/backend/tests/test_code11.c @@ -93,6 +93,7 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int option_2; + int output_options; const char *data; int length; @@ -100,14 +101,19 @@ static void test_hrt(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODE11, -1, "123-45", -1, "123-4552" }, /* 2 checksums */ - /* 1*/ { BARCODE_CODE11, 1, "123-45", -1, "123-455" }, /* 1 check digit */ - /* 2*/ { BARCODE_CODE11, 2, "123-45", -1, "123-45" }, /* No checksums */ - /* 3*/ { BARCODE_CODE11, -1, "123456789012", -1, "123456789012-8" }, /* First check digit 10 (A) goes to hyphen */ + /* 0*/ { BARCODE_CODE11, -1, -1, "123-45", -1, "123-4552" }, /* 2 checksums */ + /* 1*/ { BARCODE_CODE11, -1, BARCODE_PLAIN_HRT, "123-45", -1, "123-4552" }, /* No difference */ + /* 2*/ { BARCODE_CODE11, 1, -1, "123-45", -1, "123-455" }, /* 1 check digit */ + /* 3*/ { BARCODE_CODE11, 1, BARCODE_PLAIN_HRT, "123-45", -1, "123-455" }, /* No difference */ + /* 4*/ { BARCODE_CODE11, 2, -1, "123-45", -1, "123-45" }, /* No checksums */ + /* 5*/ { BARCODE_CODE11, 2, BARCODE_PLAIN_HRT, "123-45", -1, "123-45" }, /* No difference */ + /* 6*/ { BARCODE_CODE11, -1, -1, "123456789012", -1, "123456789012-8" }, /* First check digit 10 (A) goes to hyphen */ + /* 7*/ { BARCODE_CODE11, -1, BARCODE_PLAIN_HRT, "123456789012", -1, "123456789012-8" }, /* No difference */ }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -118,12 +124,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, data[i].length, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index bec423f5..34a71984 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -176,63 +176,84 @@ static void test_hrt(const testCtx *const p_ctx) { int symbology; int input_mode; int option_2; + int output_options; const char *data; int length; const char *expected; + int expected_length; }; /* é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII */ /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, "1234567890", -1, "1234567890" }, - /* 1*/ { BARCODE_CODE128, UNICODE_MODE, -1, "\000ABC\000DEF\000", 9, " ABC DEF " }, - /* 2*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, "12345\00067890", 11, "12345 67890" }, - /* 3*/ { BARCODE_CODE128, UNICODE_MODE, -1, "12345\01167890\037\177", -1, "12345 67890 " }, - /* 4*/ { BARCODE_CODE128, UNICODE_MODE, -1, "abcdé", -1, "abcdé" }, - /* 5*/ { BARCODE_CODE128, DATA_MODE, -1, "abcd\351", -1, "abcdé" }, - /* 6*/ { BARCODE_CODE128, DATA_MODE, -1, "ab\240cd\351", -1, "ab\302\240cdé" }, /* NBSP */ - /* 7*/ { BARCODE_CODE128, EXTRA_ESCAPE_MODE, -1, "\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C123456789012345678", -1, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678" }, /* Max length 198 + 19 special escapes = 99 + 19*3 = 255 */ - /* 8*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, "abcdé", -1, "abcdé" }, - /* 9*/ { BARCODE_CODE128AB, DATA_MODE, -1, "abcd\351", -1, "abcdé" }, - /* 10*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, "1234567890", -1, "*+12345678900*" }, - /* 11*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, "a99912345", -1, "*+A999123457*" }, /* Converts to upper */ - /* 12*/ { BARCODE_DPD, UNICODE_MODE, -1, "000393206219912345678101040", -1, "0003 932 0621 9912 3456 78 101 040 9" }, /* DPDAPPD 4.0.2 - Illustration 7 */ - /* 13*/ { BARCODE_DPD, UNICODE_MODE, -1, "007110601782532948375101276", -1, "0071 106 0178 2532 9483 75 101 276 X" }, /* DPDAPPD 4.0.2 - Illustration 6, figure's HRT seems incorrect */ - /* 14*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020028101276", -1, "0081 827 0998 0000 0200 28 101 276 B" }, /* DPDPLS Section 4 */ - /* 15*/ { BARCODE_DPD, UNICODE_MODE, -1, "007110601632532948375179276", -1, "0071 106 0163 2532 9483 75 179 276 A" }, /* DPDPLS Section 4.6 */ - /* 16*/ { BARCODE_DPD, UNICODE_MODE, -1, "001990009980000020084109203", -1, "0019 900 0998 0000 0200 84 109 203 1" }, /* DPDPLS Section 5.1 */ - /* 17*/ { BARCODE_DPD, UNICODE_MODE, 1, "007110601632532948375101276", -1, "0071 106 0163 2532 9483 75 101 276 O" }, /* DPDPLS Section 6.1.2 relabel, figure is actually 8.7.2 with mislabelled HRT */ - /* 18*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020029136276", -1, "0081 827 0998 0000 0200 29 136 276 3" }, /* DPDPLS Section 8.1 */ - /* 19*/ { BARCODE_DPD, UNICODE_MODE, -1, "001234509980000020031105276", -1, "0012 345 0998 0000 0200 31 105 276 L" }, /* DPDPLS Section 8.2 */ - /* 20*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020032154276", -1, "0081 827 0998 0000 0200 32 154 276 J" }, /* DPDPLS Section 8.3 */ - /* 21*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020030109276", -1, "0081 827 0998 0000 0200 30 109 276 W" }, /* DPDPLS Section 8.4 */ - /* 22*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020033350276", -1, "0081 827 0998 0000 0200 33 350 276 C" }, /* DPDPLS Section 8.5.1 */ - /* 23*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020034179276", -1, "0081 827 0998 0000 0200 34 179 276 I" }, /* DPDPLS Section 8.5.2 */ - /* 24*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020035225276", -1, "0081 827 0998 0000 0200 35 225 276 H" }, /* DPDPLS Section 8.5.3 */ - /* 25*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020036155276", -1, "0081 827 0998 0000 0200 36 155 276 5" }, /* DPDPLS Section 8.5.4 */ - /* 26*/ { BARCODE_DPD, UNICODE_MODE, -1, "000280009980000020037155056", -1, "0002 800 0998 0000 0200 37 155 056 6" }, /* DPDPLS Section 8.5.5 */ - /* 27*/ { BARCODE_DPD, UNICODE_MODE, -1, "007855009980000020041302840", -1, "0078 550 0998 0000 0200 41 302 840 U" }, /* DPDPLS Section 8.5.6 */ - /* 28*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020042102276", -1, "0081 827 0998 0000 0200 42 102 276 R" }, /* DPDPLS Section 8.6.1 */ - /* 29*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020043113276", -1, "0081 827 0998 0000 0200 43 113 276 Y" }, /* DPDPLS Section 8.7.1 */ - /* 30*/ { BARCODE_DPD, UNICODE_MODE, 1, "006376209980000020044118276", -1, "0063 762 0998 0000 0200 44 118 276 I" }, /* DPDPLS Section 8.7.2 relabel */ - /* 31*/ { BARCODE_DPD, UNICODE_MODE, -1, "007160009980000020050294276", -1, "0071 600 0998 0000 0200 50 294 276 C" }, /* DPDPLS Section 8.8 */ - /* 32*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020045327276", -1, "0081 827 0998 0000 0200 45 327 276 N" }, /* DPDPLS Section 8.9.1 */ - /* 33*/ { BARCODE_DPD, UNICODE_MODE, -1, "006374309980000020047337276", -1, "0063 743 0998 0000 0200 47 337 276 O" }, /* DPDPLS Section 8.9.2 */ - /* 34*/ { BARCODE_DPD, UNICODE_MODE, 1, "006374109980978004757332276", -1, "0063 741 0998 0978 0047 57 332 276 M" }, /* DPDPLS Section 8.9.3 relabel, figure's HRT seems incorrect */ - /* 35*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020051106276", -1, "0081 827 0998 0000 0200 51 106 276 M" }, /* DPDPLS Section 9.1 */ - /* 36*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020052110276", -1, "0081 827 0998 0000 0200 52 110 276 W" }, /* DPDPLS Section 9.2 */ - /* 37*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020053161276", -1, "0081 827 0998 0000 0200 53 161 276 O" }, /* DPDPLS Section 9.3 */ - /* 38*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020054352276", -1, "0081 827 0998 0000 0200 54 352 276 B" }, /* DPDPLS Section 9.4 */ - /* 39*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020055191276", -1, "0081 827 0998 0000 0200 55 191 276 A" }, /* DPDPLS Section 9.5 */ - /* 40*/ { BARCODE_DPD, UNICODE_MODE, -1, "008182709980000020056237276", -1, "0081 827 0998 0000 0200 56 237 276 K" }, /* DPDPLS Section 9.6 */ - /* 41*/ { BARCODE_UPU_S10, UNICODE_MODE, -1, "EE876543216CA", -1, "EE 876 543 216 CA" }, /* UPU S10 Annex A */ + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, -1, "1234567890", -1, "1234567890", -1 }, + /* 1*/ { BARCODE_CODE128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "1234567890", -1, "1234567890", -1 }, + /* 2*/ { BARCODE_CODE128, UNICODE_MODE, -1, -1, "\000ABC\000DEF\000", 9, " ABC DEF ", -1 }, + /* 3*/ { BARCODE_CODE128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "\000ABC\000DEF\000", 9, "\000ABC\000DEF\000", 9 }, /* No replacements */ + /* 4*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, -1, "12345\00067890", 11, "12345 67890", -1 }, + /* 5*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "12345\00067890", 11, "12345\00067890", 11 }, + /* 6*/ { BARCODE_CODE128, UNICODE_MODE, -1, -1, "12345\01167890\037\177", -1, "12345 67890 ", -1 }, + /* 7*/ { BARCODE_CODE128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "12345\01167890\037\177", -1, "12345\01167890\037\177", -1 }, + /* 8*/ { BARCODE_CODE128, UNICODE_MODE, -1, -1, "abcdé", -1, "abcdé", -1 }, + /* 9*/ { BARCODE_CODE128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "abcdé", -1, "abcdé", -1 }, + /* 10*/ { BARCODE_CODE128, UNICODE_MODE, -1, -1, "abcdé\302\240", -1, "abcdé\302\240", -1 }, /* \302\240 (U+A0) NBSP */ + /* 11*/ { BARCODE_CODE128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "abcdé\302\240", -1, "abcdé\302\240", -1 }, + /* 12*/ { BARCODE_CODE128, DATA_MODE, -1, -1, "abcd\351", -1, "abcdé", -1 }, + /* 13*/ { BARCODE_CODE128, DATA_MODE, -1, BARCODE_PLAIN_HRT, "abcd\351", -1, "abcdé", -1 }, + /* 14*/ { BARCODE_CODE128, DATA_MODE, -1, -1, "ab\240cd\351", -1, "ab\302\240cdé", -1 }, /* \240 (U+A0) NBSP */ + /* 15*/ { BARCODE_CODE128, DATA_MODE, -1, BARCODE_PLAIN_HRT, "ab\240cd\351", -1, "ab\302\240cdé", -1 }, + /* 16*/ { BARCODE_CODE128, DATA_MODE, -1, -1, "ab\200cd\351", -1, "ab cdé", -1 }, /* \200 (U+80) non-ISO/IEC 8859-1 */ + /* 17*/ { BARCODE_CODE128, DATA_MODE, -1, BARCODE_PLAIN_HRT, "ab\200cd\351", -1, "ab\302\200cdé", -1 }, + /* 18*/ { BARCODE_CODE128, EXTRA_ESCAPE_MODE, -1, -1, "\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C123456789012345678", -1, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", -1 }, /* Max length 198 + 19 special escapes = 99 + 19*3 = 255 */ + /* 19*/ { BARCODE_CODE128, EXTRA_ESCAPE_MODE, -1, BARCODE_PLAIN_HRT, "\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C1234567890\\^C123456789012345678", -1, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", -1 }, + /* 20*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, -1, "abcdé", -1, "abcdé", -1 }, + /* 21*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "abcdé", -1, "abcdé", -1 }, + /* 22*/ { BARCODE_CODE128AB, DATA_MODE, -1, -1, "abcd\351", -1, "abcdé", -1 }, + /* 23*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, -1, "1234567890", -1, "*+12345678900*", -1 }, + /* 24*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "1234567890", -1, "+12345678900", -1 }, + /* 25*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, -1, "a99912345", -1, "*+A999123457*", -1 }, /* Converts to upper */ + /* 26*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "a99912345", -1, "+A999123457", -1 }, + /* 27*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "000393206219912345678101040", -1, "0003 932 0621 9912 3456 78 101 040 9", -1 }, /* DPDAPPD 4.0.2 - Illustration 7 */ + /* 28*/ { BARCODE_DPD, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "000393206219912345678101040", -1, "0003932062199123456781010409", -1 }, /* No spaces */ + /* 29*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "007110601782532948375101276", -1, "0071 106 0178 2532 9483 75 101 276 X", -1 }, /* DPDAPPD 4.0.2 - Illustration 6, figure's HRT seems incorrect */ + /* 30*/ { BARCODE_DPD, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "007110601782532948375101276", -1, "007110601782532948375101276X", -1 }, + /* 31*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020028101276", -1, "0081 827 0998 0000 0200 28 101 276 B", -1 }, /* DPDPLS Section 4 */ + /* 32*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "007110601632532948375179276", -1, "0071 106 0163 2532 9483 75 179 276 A", -1 }, /* DPDPLS Section 4.6 */ + /* 33*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "001990009980000020084109203", -1, "0019 900 0998 0000 0200 84 109 203 1", -1 }, /* DPDPLS Section 5.1 */ + /* 34*/ { BARCODE_DPD, UNICODE_MODE, 1, -1, "007110601632532948375101276", -1, "0071 106 0163 2532 9483 75 101 276 O", -1 }, /* DPDPLS Section 6.1.2 relabel, figure is actually 8.7.2 with mislabelled HRT */ + /* 35*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020029136276", -1, "0081 827 0998 0000 0200 29 136 276 3", -1 }, /* DPDPLS Section 8.1 */ + /* 36*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "001234509980000020031105276", -1, "0012 345 0998 0000 0200 31 105 276 L", -1 }, /* DPDPLS Section 8.2 */ + /* 37*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020032154276", -1, "0081 827 0998 0000 0200 32 154 276 J", -1 }, /* DPDPLS Section 8.3 */ + /* 38*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020030109276", -1, "0081 827 0998 0000 0200 30 109 276 W", -1 }, /* DPDPLS Section 8.4 */ + /* 39*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020033350276", -1, "0081 827 0998 0000 0200 33 350 276 C", -1 }, /* DPDPLS Section 8.5.1 */ + /* 40*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020034179276", -1, "0081 827 0998 0000 0200 34 179 276 I", -1 }, /* DPDPLS Section 8.5.2 */ + /* 41*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020035225276", -1, "0081 827 0998 0000 0200 35 225 276 H", -1 }, /* DPDPLS Section 8.5.3 */ + /* 42*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020036155276", -1, "0081 827 0998 0000 0200 36 155 276 5", -1 }, /* DPDPLS Section 8.5.4 */ + /* 43*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "000280009980000020037155056", -1, "0002 800 0998 0000 0200 37 155 056 6", -1 }, /* DPDPLS Section 8.5.5 */ + /* 44*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "007855009980000020041302840", -1, "0078 550 0998 0000 0200 41 302 840 U", -1 }, /* DPDPLS Section 8.5.6 */ + /* 45*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020042102276", -1, "0081 827 0998 0000 0200 42 102 276 R", -1 }, /* DPDPLS Section 8.6.1 */ + /* 46*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020043113276", -1, "0081 827 0998 0000 0200 43 113 276 Y", -1 }, /* DPDPLS Section 8.7.1 */ + /* 47*/ { BARCODE_DPD, UNICODE_MODE, 1, -1, "006376209980000020044118276", -1, "0063 762 0998 0000 0200 44 118 276 I", -1 }, /* DPDPLS Section 8.7.2 relabel */ + /* 48*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "007160009980000020050294276", -1, "0071 600 0998 0000 0200 50 294 276 C", -1 }, /* DPDPLS Section 8.8 */ + /* 49*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020045327276", -1, "0081 827 0998 0000 0200 45 327 276 N", -1 }, /* DPDPLS Section 8.9.1 */ + /* 50*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "006374309980000020047337276", -1, "0063 743 0998 0000 0200 47 337 276 O", -1 }, /* DPDPLS Section 8.9.2 */ + /* 51*/ { BARCODE_DPD, UNICODE_MODE, 1, -1, "006374109980978004757332276", -1, "0063 741 0998 0978 0047 57 332 276 M", -1 }, /* DPDPLS Section 8.9.3 relabel, figure's HRT seems incorrect */ + /* 52*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020051106276", -1, "0081 827 0998 0000 0200 51 106 276 M", -1 }, /* DPDPLS Section 9.1 */ + /* 53*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020052110276", -1, "0081 827 0998 0000 0200 52 110 276 W", -1 }, /* DPDPLS Section 9.2 */ + /* 54*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020053161276", -1, "0081 827 0998 0000 0200 53 161 276 O", -1 }, /* DPDPLS Section 9.3 */ + /* 55*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020054352276", -1, "0081 827 0998 0000 0200 54 352 276 B", -1 }, /* DPDPLS Section 9.4 */ + /* 56*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020055191276", -1, "0081 827 0998 0000 0200 55 191 276 A", -1 }, /* DPDPLS Section 9.5 */ + /* 57*/ { BARCODE_DPD, UNICODE_MODE, -1, -1, "008182709980000020056237276", -1, "0081 827 0998 0000 0200 56 237 276 K", -1 }, /* DPDPLS Section 9.6 */ + /* 58*/ { BARCODE_UPU_S10, UNICODE_MODE, -1, -1, "EE876543216CA", -1, "EE 876 543 216 CA", -1 }, /* UPU S10 Annex A */ + /* 59*/ { BARCODE_UPU_S10, UNICODE_MODE, -1, BARCODE_PLAIN_HRT, "EE876543216CA", -1, "EE876543216CA", -1 }, /* No spaces */ /* BARCODE_GS1_128, BARCODE_EAN14, BARCODE_NVE18 hrt tested in test_gs1.c */ }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; char escaped[1024]; char escaped2[1024]; @@ -254,12 +275,18 @@ static void test_hrt(const testCtx *const p_ctx) { memset(symbol->text, 0xDD, sizeof(symbol->text)); /* Detect non-NUL terminated HRT */ - length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, data[i].length, debug); + expected_length = data[i].expected_length == -1 ? (int) strlen(data[i].expected) : data[i].expected_length; ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(memcmp(symbol->text, data[i].expected, expected_length), "i:%d memcmp(%s, %s, %d) != 0\n", + i, symbol->text, data[i].expected, expected_length); if (ret < ZINT_ERROR) { if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { @@ -964,27 +991,28 @@ static void test_dpd_input(const testCtx *const p_ctx) { /* 7*/ { -1, -1, "123456789012345678901234567,", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 299: Invalid character at position 27 in input (alphanumerics only after first)", "Alphanumerics only in body" }, /* 8*/ { -1, -1, "12345678901234567890123456,", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 300: Invalid character at position 27 in input (alphanumerics only)", "Alphanumerics only" }, /* 9*/ { -1, -1, ",234567890123456789012345678", 0, 211, 50, 1, "(19) 104 12 18 99 34 56 78 90 12 34 56 78 90 12 34 56 78 64 106", "Non-alphanumeric DPD ident tag (Barcode ID) allowed" }, - /* 10*/ { -1, -1, "\037234567890123456789012345678", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 343: Invalid DPD identification tag (first character), ASCII values 32 to 127 only", "Control char as DPD ident tag" }, - /* 11*/ { -1, -1, "é234567890123456789012345678", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 343: Invalid DPD identification tag (first character), ASCII values 32 to 127 only", "Extended ASCII as DPD ident tag" }, - /* 12*/ { -1, -1, "12345678901234567890123456A", ZINT_WARN_NONCOMPLIANT, 222, 50, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, - /* 13*/ { -1, -1, "%12345678901234567890123456A", ZINT_WARN_NONCOMPLIANT, 222, 50, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, - /* 14*/ { 1, -1, "12345678901234567890123456A", ZINT_WARN_NONCOMPLIANT, 200, 25, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, - /* 15*/ { -1, -1, "123456789012345678901234A67", ZINT_WARN_NONCOMPLIANT, 233, 50, 0, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "BWIPP different encodation (same width)" }, - /* 16*/ { -1, -1, "%123456789012345678901234A67", ZINT_WARN_NONCOMPLIANT, 233, 50, 0, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "BWIPP different encodation (same width)" }, - /* 17*/ { 1, -1, "123456789012345678901234A67", ZINT_WARN_NONCOMPLIANT, 211, 25, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, - /* 18*/ { -1, -1, "12345678901234567890123A567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, - /* 19*/ { -1, -1, "%12345678901234567890123A567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, - /* 20*/ { 1, -1, "12345678901234567890123A567", ZINT_WARN_NONCOMPLIANT, 222, 25, 1, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "" }, - /* 21*/ { -1, -1, "123456789012345678901A34567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, - /* 22*/ { -1, -1, "%123456789012345678901A34567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, - /* 23*/ { 1, -1, "123456789012345678901A34567", ZINT_WARN_NONCOMPLIANT, 222, 25, 1, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "" }, - /* 24*/ { -1, -1, "12345678901234567890A234567", ZINT_WARN_NONCOMPLIANT, 233, 50, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, - /* 25*/ { -1, -1, "%12345678901234567890A234567", ZINT_WARN_NONCOMPLIANT, 233, 50, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, - /* 26*/ { 1, -1, "12345678901234567890A234567", ZINT_WARN_NONCOMPLIANT, 211, 25, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, - /* 27*/ { -1, -1, "12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "BWIPP different encodation (same width)" }, - /* 28*/ { -1, -1, "%12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "BWIPP different encodation (same width)" }, - /* 29*/ { 1, -1, "12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 222, 25, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, - /* 30*/ { 1, COMPLIANT_HEIGHT, "12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 222, 33.333332, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, + /* 10*/ { -1, -1, "\037234567890123456789012345678", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 343: Invalid DPD identification tag (first character), ASCII values 32 to 126 only", "Control char as DPD ident tag" }, + /* 11*/ { -1, -1, "\177234567890123456789012345678", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 343: Invalid DPD identification tag (first character), ASCII values 32 to 126 only", " as DPD ident tag" }, + /* 12*/ { -1, -1, "é234567890123456789012345678", ZINT_ERROR_INVALID_DATA, -1, 0, 1, "Error 343: Invalid DPD identification tag (first character), ASCII values 32 to 126 only", "Extended ASCII as DPD ident tag" }, + /* 13*/ { -1, -1, "12345678901234567890123456A", ZINT_WARN_NONCOMPLIANT, 222, 50, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, + /* 14*/ { -1, -1, "%12345678901234567890123456A", ZINT_WARN_NONCOMPLIANT, 222, 50, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, + /* 15*/ { 1, -1, "12345678901234567890123456A", ZINT_WARN_NONCOMPLIANT, 200, 25, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, + /* 16*/ { -1, -1, "123456789012345678901234A67", ZINT_WARN_NONCOMPLIANT, 233, 50, 0, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "BWIPP different encodation (same width)" }, + /* 17*/ { -1, -1, "%123456789012345678901234A67", ZINT_WARN_NONCOMPLIANT, 233, 50, 0, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "BWIPP different encodation (same width)" }, + /* 18*/ { 1, -1, "123456789012345678901234A67", ZINT_WARN_NONCOMPLIANT, 211, 25, 1, "Warning 831: Destination Country Code (last 3 characters) should be numeric", "" }, + /* 19*/ { -1, -1, "12345678901234567890123A567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, + /* 20*/ { -1, -1, "%12345678901234567890123A567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, + /* 21*/ { 1, -1, "12345678901234567890123A567", ZINT_WARN_NONCOMPLIANT, 222, 25, 1, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "" }, + /* 22*/ { -1, -1, "123456789012345678901A34567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, + /* 23*/ { -1, -1, "%123456789012345678901A34567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "BWIPP different encodation (same width)" }, + /* 24*/ { 1, -1, "123456789012345678901A34567", ZINT_WARN_NONCOMPLIANT, 222, 25, 1, "Warning 832: Service Code (characters 6-4 from end) should be numeric", "" }, + /* 25*/ { -1, -1, "12345678901234567890A234567", ZINT_WARN_NONCOMPLIANT, 233, 50, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, + /* 26*/ { -1, -1, "%12345678901234567890A234567", ZINT_WARN_NONCOMPLIANT, 233, 50, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, + /* 27*/ { 1, -1, "12345678901234567890A234567", ZINT_WARN_NONCOMPLIANT, 211, 25, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, + /* 28*/ { -1, -1, "12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "BWIPP different encodation (same width)" }, + /* 29*/ { -1, -1, "%12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 244, 50, 0, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "BWIPP different encodation (same width)" }, + /* 30*/ { 1, -1, "12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 222, 25, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, + /* 31*/ { 1, COMPLIANT_HEIGHT, "12345678901A345678901234567", ZINT_WARN_NONCOMPLIANT, 222, 33.333332, 1, "Warning 833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric", "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_common.c b/backend/tests/test_common.c index 480303b1..cac8f5e5 100644 --- a/backend/tests/test_common.c +++ b/backend/tests/test_common.c @@ -155,6 +155,40 @@ static void test_chr_cnt(const testCtx *const p_ctx) { testFinish(); } +static void test_is_chr(const testCtx *const p_ctx) { + + struct item { + int flg; + int c; + int ret; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { NEON_F, '1', 1 }, + /* 1*/ { NEON_F, 'a', 0 }, + /* 2*/ { NEON_F, 0xFF, 0 }, + /* 3*/ { NEON_F, 0xFFF, 0 }, + /* 4*/ { NEON_F, 0xFFFF, 0 }, + /* 5*/ { IS_UPR_F, '1', 0 }, + /* 6*/ { IS_UPR_F, 'a', 0 }, + /* 7*/ { IS_UPR_F, 'A', 1 }, + }; + const int data_size = ARRAY_SIZE(data); + int i, ret; + + testStart("test_is_chr"); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + ret = is_chr(data[i].flg, data[i].c); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + } + + testFinish(); +} + static void test_not_sane(const testCtx *const p_ctx) { struct item { @@ -618,15 +652,16 @@ static void test_utf8_to_unicode(const testCtx *const p_ctx) { int ret; int ret_length; unsigned int expected_vals[20]; + const char *expected_errtxt; const char *comment; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { "", -1, 1, 0, 0, {0}, "" }, - /* 1*/ { "\000a\302\200\340\240\200", 7, 1, 0, 4, { 0, 'a', 0x80, 0x800 }, "NUL a C280 E0A080" }, - /* 2*/ { "\357\277\277", -1, 1, 0, 1, { 0xFFFF }, "EFBFBF" }, - /* 3*/ { "\360\220\200\200", -1, 1, ZINT_ERROR_INVALID_DATA, -1, {0}, "Four-byte F0908080" }, - /* 4*/ { "a\200b", -1, 1, ZINT_ERROR_INVALID_DATA, -1, {0}, "Orphan continuation 0x80" }, + /* 0*/ { "", -1, 1, 0, 0, {0}, "", "" }, + /* 1*/ { "\000a\302\200\340\240\200", 7, 1, 0, 4, { 0, 'a', 0x80, 0x800 }, "", "NUL a C280 E0A080" }, + /* 2*/ { "\357\277\277", -1, 1, 0, 1, { 0xFFFF }, "", "EFBFBF" }, + /* 3*/ { "\360\220\200\200", -1, 1, ZINT_ERROR_INVALID_DATA, -1, {0}, "242: Unicode sequences of more than 3 bytes not supported", "Four-byte F0908080" }, + /* 4*/ { "a\200b", -1, 1, ZINT_ERROR_INVALID_DATA, -1, {0}, "240: Corrupt Unicode data", "Orphan continuation 0x80" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -644,6 +679,8 @@ static void test_utf8_to_unicode(const testCtx *const p_ctx) { if (testContinue(p_ctx, i)) continue; + memset(symbol, 0, sizeof(*symbol)); + length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; ret_length = length; @@ -656,6 +693,8 @@ static void test_utf8_to_unicode(const testCtx *const p_ctx) { assert_equal(vals[j], data[i].expected_vals[j], "i:%d vals[%d] %04X != %04X\n", i, j, vals[j], data[i].expected_vals[j]); } } + assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->errtxt, data[i].expected_errtxt); } testFinish(); @@ -670,6 +709,8 @@ static void test_hrt_cpy_iso8859_1(const testCtx *const p_ctx) { int length; int ret; const char *expected; + const char *expected_plain; + int expected_plain_length; const char *comment; }; /* @@ -679,34 +720,36 @@ static void test_hrt_cpy_iso8859_1(const testCtx *const p_ctx) { */ /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { "", -1, 0, "", "" }, - /* 1*/ { "abc", -1, 0, "abc", "" }, - /* 2*/ { "\000A\001B\002\036\037C ~\177", 11, 0, " A B C ~ ", "" }, - /* 3*/ { "~\177\200\201\237\240", -1, 0, "~ \302\240", "" }, - /* 4*/ { "\241\242\243\244\257\260", -1, 0, "¡¢£¤¯°", "" }, - /* 5*/ { "\276\277\300\337\377", -1, 0, "¾¿Àßÿ", "" }, - /* 6*/ { "\351", -1, 0, "é", "" }, - /* 7*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 0, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", "127 \241" }, - /* 8*/ { "a\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 0, "a¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", "a + 127 \241" }, - /* 9*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241a", -1, 0, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡a", "127 \241 + a" }, - /* 10*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 1, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", "128 \241 (truncated)" }, - /* 11*/ { "a\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 1, "a¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", "a + 128 \241 (truncated)" }, - /* 12*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241a", -1, 1, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", "128 \241 + a (truncated)" }, - /* 13*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 1, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", "129 \241 (truncated)" }, - /* 14*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 0, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "127 \351" }, - /* 15*/ { "a\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 0, "aééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "a + 127 \351" }, - /* 16*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351a", -1, 0, "éééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééa", "127 \351 + a" }, - /* 17*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 1, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "128 \351 (truncated)" }, - /* 18*/ { "a\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 1, "aééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "a + 128 \351 (truncated)" }, - /* 19*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351a", -1, 1, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "128 \351 + a (truncated)" }, - /* 20*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 1, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", "129 \351 (truncated)" }, - /* 21*/ { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", -1, 1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "256 A (truncated)" }, + /* 0*/ { "", -1, 0, "", NULL, -1, "" }, + /* 1*/ { "abc", -1, 0, "abc", NULL, -1, "" }, + /* 2*/ { "\000A\001B\002\036\037C ~\177", 11, 0, " A B C ~ ", "\000A\001B\002\036\037C ~\177", 11, "" }, + /* 3*/ { "~\177\200\201\237\240", -1, 0, "~ \302\240", "~\177\302\200\302\201\302\237\302\240", -1, "" }, + /* 4*/ { "\241\242\243\244\257\260", -1, 0, "¡¢£¤¯°", NULL, -1, "" }, + /* 5*/ { "\276\277\300\337\377", -1, 0, "¾¿Àßÿ", NULL, -1, "" }, + /* 6*/ { "\351", -1, 0, "é", NULL, -1, "" }, + /* 7*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 0, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", NULL, -1, "127 \241" }, + /* 8*/ { "a\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 0, "a¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", NULL, -1, "a + 127 \241" }, + /* 9*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241a", -1, 0, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡a", NULL, -1, "127 \241 + a" }, + /* 10*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 1, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", NULL, -1, "128 \241 (truncated)" }, + /* 11*/ { "a\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 1, "a¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", NULL, -1, "a + 128 \241 (truncated)" }, + /* 12*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241a", -1, 1, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", NULL, -1, "128 \241 + a (truncated)" }, + /* 13*/ { "\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241\241", -1, 1, "¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡", NULL, -1, "129 \241 (truncated)" }, + /* 14*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 0, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", NULL, -1, "127 \351" }, + /* 15*/ { "a\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 0, "aééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", NULL, -1, "a + 127 \351" }, + /* 16*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351a", -1, 0, "éééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééa", NULL, -1, "127 \351 + a" }, + /* 17*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 1, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", NULL, -1, "128 \351 (truncated)" }, + /* 18*/ { "a\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 1, "aééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", NULL, -1, "a + 128 \351 (truncated)" }, + /* 19*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351a", -1, 1, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", NULL, -1, "128 \351 + a (truncated)" }, + /* 20*/ { "\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351\351", -1, 1, "ééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééé", NULL, -1, "129 \351 (truncated)" }, + /* 21*/ { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", -1, 1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", NULL, -1, "256 A (truncated)" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol s_symbol; struct zint_symbol *symbol = &s_symbol; + int expected_length; + const char *expected; testStart("test_hrt_cpy_iso8859_1"); @@ -717,17 +760,224 @@ static void test_hrt_cpy_iso8859_1(const testCtx *const p_ctx) { if (testContinue(p_ctx, i)) continue; + memset(symbol, 0, sizeof(*symbol)); + length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + expected_length = (int) strlen(data[i].expected); ret = hrt_cpy_iso8859_1(symbol, (unsigned char *) data[i].data, length); if (p_ctx->index != -1 && (debug & ZINT_DEBUG_TEST_PRINT)) { - for (j = 0; j < ret; j++) { + for (j = 0; j < symbol->text_length; j++) { fprintf(stderr, "symbol->text[%d] %2X\n", j, symbol->text[j]); } } assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); - assert_nonzero(testUtilIsValidUTF8(symbol->text, (int) ustrlen(symbol->text)), "i:%d testUtilIsValidUTF8(%s) != 1\n", i, symbol->text); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d symbol->text (%s) != expected (%s)\n", i, symbol->text, data[i].expected); + assert_nonzero(testUtilIsValidUTF8(symbol->text, symbol->text_length), "i:%d testUtilIsValidUTF8(%s) != 1\n", + i, symbol->text); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d symbol->text (%s) != expected (%s)\n", + i, symbol->text, data[i].expected); + + memset(symbol, 0, sizeof(*symbol)); + symbol->output_options = BARCODE_PLAIN_HRT; + + if (data[i].expected_plain == NULL) { + expected = data[i].expected; + expected_length = (int) strlen(expected); + } else { + expected = data[i].expected_plain; + expected_length = data[i].expected_plain_length == -1 ? (int) strlen(expected) : data[i].expected_plain_length; + } + + ret = hrt_cpy_iso8859_1(symbol, (unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + assert_nonzero(testUtilIsValidUTF8(symbol->text, symbol->text_length), "i:%d testUtilIsValidUTF8(%s) != 1\n", + i, symbol->text); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(memcmp(symbol->text, expected, symbol->text_length), "i:%d symbol->text (%s) != expected (%s)\n", i, symbol->text, expected); + } + + testFinish(); +} + +static void test_hrt_cpy_nochk(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + const char *cpy; /* hrt_cpy_nochk() */ + int cpy_length; + + const char cpy_chr; /* hrt_cpy_chr() */ + int cpy_chr_length; + + const char *cat; /* hrt_cat_nochk() */ + int cat_length; + + char cat_chr; /* hrt_cat_chr_nochk() */ + int cat_chr_length; + + const char *expected; + int expected_length; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { "", -1, 0, 0, "", -1, 0, 0, "", -1 }, /* All zero */ + /* 1*/ { "AB\000C", 4, 0, 0, "", -1, 0, 0, "AB\000C", 4 }, /* hrt_cpy_nochk() */ + /* 2*/ { "", -1, '\000', 1, "", -1, 0, 0, "\000", 1 }, /* hrt_chr() (NUL char) */ + /* 3*/ { "", -1, '\000', 1, "XYZ", -1, 0, 0, "\000XYZ", 4 }, /* hrt_chr() + hrt_cat_nochk() */ + /* 4*/ { "", -1, '\000', 1, "", -1, '\000', 1, "\000\000", 2 }, /* hrt_chr() + hrt_cat_chr_nochk() (both NULL char) */ + /* 5*/ { "", -1, '\000', 1, "XYZ", -1, '\001', 1, "\000XYZ\001", 5 }, /* hrt_chr() + hrt_cat_chr_nochk() + hrt_cat_nochk() */ + /* 6*/ { "ABC\000", 4, 0, 0, "\000XYZ\177", 5, 0, 0, "ABC\000\000XYZ\177", 9 }, /* hrt_cpy_nochk() + hrt_cat_nochk() */ + /* 7*/ { "ABC\000", 4, 0, 0, "", -1, '\177', 1, "ABC\000\177", 5 }, /* hrt_cpy_nochk() + hrt_cat_chr_nochk() */ + /* 8*/ { "ABC\000", 4, 0, 0, "X\001Y\002Z", 5, '\003', 1, "ABC\000X\001Y\002Z\003", 10 }, /* hrt_cpy_nochk() + hrt_cat_chr_nochk() + hrt_cat_chr_nochk() */ + /* 9*/ { "1234567890123456789012345678901234567890123456789012345", -1, 0, 0, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", -1, 0, 0, "123456789012345678901234567890123456789012345678901234512345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", -1 }, /* hrt_cpy_nochk() + hrt_cat_nochk() - max 255 */ + }; + const int data_size = ARRAY_SIZE(data); + int i, length; + + struct zint_symbol s_symbol; + struct zint_symbol *symbol = &s_symbol; + int expected_length; + + testStart("test_hrt_cpy_nochk"); + + symbol->debug = debug; + + for (i = 0; i < data_size; i++) { + int j; + + if (testContinue(p_ctx, i)) continue; + + memset(symbol, 0, sizeof(*symbol)); + + expected_length = data[i].expected_length == -1 ? (int) strlen(data[i].expected) : data[i].expected_length; + + if ((length = data[i].cpy_length == -1 ? (int) strlen(data[i].cpy) : data[i].cpy_length)) { + hrt_cpy_nochk(symbol, TCU(data[i].cpy), length); + } + if (data[i].cpy_chr_length) { + hrt_cpy_chr(symbol, data[i].cpy_chr); + } + if ((length = data[i].cat_length == -1 ? (int) strlen(data[i].cat) : data[i].cat_length)) { + hrt_cat_nochk(symbol, TCU(data[i].cat), length); + } + if (data[i].cat_chr_length) { + hrt_cat_chr_nochk(symbol, data[i].cat_chr); + } + + if (p_ctx->index != -1 && (debug & ZINT_DEBUG_TEST_PRINT)) { + for (j = 0; j < symbol->text_length; j++) { + fprintf(stderr, "symbol->text[%d] %2X\n", j, symbol->text[j]); + } + } + + assert_nonzero(testUtilIsValidUTF8(symbol->text, (int) ustrlen(symbol->text)), + "i:%d testUtilIsValidUTF8(%s) != 1\n", i, symbol->text); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(memcmp(symbol->text, data[i].expected, expected_length), "i:%d memcmp(%s, %s, %d) != 0\n", + i, symbol->text, data[i].expected, expected_length); + } + + testFinish(); +} + +static void test_hrt_printf_nochk(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + const char *fmt; + int num_args; + const char *data1; + const char *data2; + const char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { "", 1, "", "", "" }, + /* 1*/ { "*%s*", 1, "gosh", "", "*gosh*" }, + /* 2*/ { "%.1s.%.2s", 2, "gosh", "wow", "g.wo" }, + /* 3*/ { "ABCDEFGHIJKLMNOPQRST%sABCDEFGHIJKLMNOPQRST%sABCDEFGHIJKLMNO", 2, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", "ABCDEFGHIJKLMNOPQRST1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890ABCDEFGHIJKLMNOPQRST1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890ABCDEFGHIJKLMNO" }, /* Max 255 - 1 more and overflow */ + }; + const int data_size = ARRAY_SIZE(data); + int i; + + struct zint_symbol s_symbol; + struct zint_symbol *symbol = &s_symbol; + + testStart("test_hrt_printf_nochk"); + + symbol->debug = debug; + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + memset(symbol, 0, sizeof(*symbol)); + + if (data[i].num_args == 1) { + hrt_printf_nochk(symbol, data[i].fmt, data[i].data1); + } else if (data[i].num_args == 2) { + hrt_printf_nochk(symbol, data[i].fmt, data[i].data1, data[i].data2); + } else { + assert_zero(1, "i:%d, bad num_args\n", i); + } + + assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(\"%s\", \"%s\") != 0\n", + i, symbol->text, data[i].expected); + } + + testFinish(); +} + +static void test_hrt_conv_gs1_brackets_nochk(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + const char *data; + const char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { "", "" }, + /* 1*/ { "[", "(" }, /* Converts mismatched opening */ + /* 2*/ { "]", "]" }, /* But not mismatched closing */ + /* 3*/ { "[]", "()" }, + /* 4*/ { "(", "(" }, + /* 5*/ { ")", ")" }, + /* 6*/ { "[[]", "(()" }, + /* 7*/ { "[]]", "()]" }, + /* 8*/ { "[[]]", "(())" }, + /* 9*/ { "[[]][", "(())(" }, + /* 10*/ { "[[]]]", "(())]" }, + /* 11*/ { "[[]][]", "(())()" }, + /* 12*/ { "[[[[]]][]]", "(((()))())" }, + /* 13*/ { "[[[[]]]][]]", "(((())))()]" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length; + + struct zint_symbol s_symbol; + struct zint_symbol *symbol = &s_symbol; + + testStart("test_hrt_conv_gs1_brackets_nochk"); + + symbol->debug = debug; + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + memset(symbol, 0, sizeof(*symbol)); + + length = (int) strlen(data[i].data); + + hrt_conv_gs1_brackets_nochk(symbol, TCU(data[i].data), length); + + assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(\"%s\", \"%s\") != 0\n", + i, symbol->text, data[i].expected); } testFinish(); @@ -835,9 +1085,10 @@ static void test_debug_test_codeword_dump_int(const testCtx *const p_ctx) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func */ - { "test_chr_cnt", test_chr_cnt }, { "test_to_int", test_to_int }, { "test_to_upper", test_to_upper }, + { "test_chr_cnt", test_chr_cnt }, + { "test_is_chr", test_is_chr }, { "test_not_sane", test_not_sane }, { "test_not_sane_lookup", test_not_sane_lookup }, { "test_errtxt", test_errtxt }, @@ -846,6 +1097,9 @@ int main(int argc, char *argv[]) { { "test_is_valid_utf8", test_is_valid_utf8 }, { "test_utf8_to_unicode", test_utf8_to_unicode }, { "test_hrt_cpy_iso8859_1", test_hrt_cpy_iso8859_1 }, + { "test_hrt_cpy_nochk", test_hrt_cpy_nochk }, + { "test_hrt_printf_nochk", test_hrt_printf_nochk }, + { "test_hrt_conv_gs1_brackets_nochk", test_hrt_conv_gs1_brackets_nochk }, { "test_set_height", test_set_height }, { "test_debug_test_codeword_dump_int", test_debug_test_codeword_dump_int }, }; diff --git a/backend/tests/test_composite.c b/backend/tests/test_composite.c index 2d26195d..d5781100 100644 --- a/backend/tests/test_composite.c +++ b/backend/tests/test_composite.c @@ -3220,6 +3220,7 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int input_mode; + int output_options; const char *data; const char *composite; @@ -3228,45 +3229,60 @@ static void test_hrt(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_EANX_CC, -1, "1234567", "[20]12", 0, "12345670" }, /* EAN-8 */ - /* 1*/ { BARCODE_EANX_CC, -1, "123456789012", "[20]12", 0, "1234567890128" }, /* EAN-13 */ - /* 2*/ { BARCODE_EANX_CC, -1, "1234567890128", "[20]12", 0, "1234567890128" }, - /* 3*/ { BARCODE_EANX_CC, -1, "1234567890123", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, - /* 4*/ { BARCODE_EANX_CC, GS1NOCHECK_MODE, "1234567890123", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ - /* 5*/ { BARCODE_EANX_CC, -1, "1234567890128", "[20]1A", ZINT_WARN_NONCOMPLIANT, "1234567890128" }, /* AI (20) should be 2 nos. */ - /* 6*/ { BARCODE_EANX_CC, GS1NOCHECK_MODE, "1234567890128", "[20]1A", 0, "1234567890128" }, - /* 7*/ { BARCODE_DBAR_OMN_CC, -1, "1234567890123", "[20]12", 0, "(01)12345678901231" }, - /* 8*/ { BARCODE_DBAR_OMN_CC, -1, "12345678901231", "[20]12", 0, "(01)12345678901231" }, - /* 9*/ { BARCODE_DBAR_OMN_CC, -1, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, - /* 10*/ { BARCODE_DBAR_OMN_CC, GS1NOCHECK_MODE, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ - /* 11*/ { BARCODE_DBAR_OMN_CC, -1, "12345678901231", "[20]1A", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231" }, /* AI (20) should be 2 nos. */ - /* 12*/ { BARCODE_DBAR_OMN_CC, GS1NOCHECK_MODE, "12345678901231", "[20]1A", 0, "(01)12345678901231" }, - /* 13*/ { BARCODE_DBAR_LTD_CC, -1, "1234567890123", "[20]12", 0, "(01)12345678901231" }, - /* 14*/ { BARCODE_DBAR_LTD_CC, -1, "12345678901231", "[20]12", 0, "(01)12345678901231" }, - /* 15*/ { BARCODE_DBAR_LTD_CC, -1, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, - /* 16*/ { BARCODE_DBAR_LTD_CC, GS1NOCHECK_MODE, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ - /* 17*/ { BARCODE_DBAR_LTD_CC, -1, "12345678901231", "[20]1A", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231" }, /* AI (20) should be 2 nos. */ - /* 18*/ { BARCODE_DBAR_LTD_CC, GS1NOCHECK_MODE, "12345678901231", "[20]1A", 0, "(01)12345678901231" }, - /* 19*/ { BARCODE_UPCA_CC, -1, "12345678901", "[20]12", 0, "123456789012" }, - /* 20*/ { BARCODE_UPCA_CC, -1, "123456789012", "[20]12", 0, "123456789012" }, - /* 21*/ { BARCODE_UPCA_CC, -1, "123456789013", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, - /* 22*/ { BARCODE_UPCA_CC, GS1NOCHECK_MODE, "123456789013", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ - /* 23*/ { BARCODE_UPCA_CC, -1, "123456789012", "[20]1A", ZINT_WARN_NONCOMPLIANT, "123456789012" }, /* AI (20) should be 2 nos. */ - /* 24*/ { BARCODE_UPCA_CC, GS1NOCHECK_MODE, "123456789012", "[20]1A", 0, "123456789012" }, - /* 25*/ { BARCODE_UPCE_CC, -1, "123456", "[20]12", 0, "01234565" }, - /* 26*/ { BARCODE_UPCE_CC, -1, "1234567", "[20]12", 0, "12345670" }, - /* 27*/ { BARCODE_UPCE_CC, -1, "12345670", "[20]12", 0, "12345670" }, - /* 28*/ { BARCODE_UPCE_CC, -1, "12345671", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, - /* 29*/ { BARCODE_UPCE_CC, GS1NOCHECK_MODE, "12345671", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ - /* 30*/ { BARCODE_UPCE_CC, -1, "12345670", "[20]12", 0, "12345670" }, /* Check digit can now be given for UPCE_CC, like UPCA_CC */ - /* 31*/ { BARCODE_UPCE_CC, -1, "1234567", "[20]1A", ZINT_WARN_NONCOMPLIANT, "12345670" }, /* AI (20) should be 2 nos. */ - /* 32*/ { BARCODE_UPCE_CC, GS1NOCHECK_MODE, "1234567", "[20]1A", 0, "12345670" }, - /* 33*/ { BARCODE_DBAR_STK_CC, -1, "12345678901231", "[20]12", 0, "" }, /* No HRT for stacked symbologies */ - /* 34*/ { BARCODE_DBAR_OMNSTK_CC, -1, "12345678901231", "[20]12", 0, "" }, + /* 0*/ { BARCODE_EANX_CC, -1, -1, "1234567", "[20]12", 0, "12345670" }, /* EAN-8 */ + /* 1*/ { BARCODE_EANX_CC, -1, BARCODE_PLAIN_HRT, "1234567", "[20]12", 0, "12345670" }, /* EAN-8 */ + /* 2*/ { BARCODE_EANX_CC, -1, -1, "123456789012", "[20]12", 0, "1234567890128" }, /* EAN-13 */ + /* 3*/ { BARCODE_EANX_CC, -1, BARCODE_PLAIN_HRT, "123456789012", "[20]12", 0, "1234567890128" }, /* EAN-13 */ + /* 4*/ { BARCODE_EANX_CC, -1, -1, "1234567890128", "[20]12", 0, "1234567890128" }, + /* 5*/ { BARCODE_EANX_CC, -1, -1, "1234567890123", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, + /* 6*/ { BARCODE_EANX_CC, GS1NOCHECK_MODE, -1, "1234567890123", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ + /* 7*/ { BARCODE_EANX_CC, -1, -1, "1234567890128", "[20]1A", ZINT_WARN_NONCOMPLIANT, "1234567890128" }, /* AI (20) should be 2 nos. */ + /* 8*/ { BARCODE_EANX_CC, GS1NOCHECK_MODE, -1, "1234567890128", "[20]1A", 0, "1234567890128" }, + /* 9*/ { BARCODE_EANX_CC, -1, -1, "1234567890128+12", "[20]12", 0, "1234567890128+12" }, + /* 10*/ { BARCODE_EANX_CC, -1, BARCODE_PLAIN_HRT, "1234567890128+12", "[20]12", 0, "123456789012812" }, + /* 11*/ { BARCODE_DBAR_OMN_CC, -1, -1, "1234567890123", "[20]12", 0, "(01)12345678901231" }, + /* 12*/ { BARCODE_DBAR_OMN_CC, -1, BARCODE_PLAIN_HRT, "1234567890123", "[20]12", 0, "0112345678901231" }, + /* 13*/ { BARCODE_DBAR_OMN_CC, -1, -1, "12345678901231", "[20]12", 0, "(01)12345678901231" }, + /* 14*/ { BARCODE_DBAR_OMN_CC, -1, -1, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, + /* 15*/ { BARCODE_DBAR_OMN_CC, GS1NOCHECK_MODE, -1, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ + /* 16*/ { BARCODE_DBAR_OMN_CC, -1, -1, "12345678901231", "[20]1A", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231" }, /* AI (20) should be 2 nos. */ + /* 17*/ { BARCODE_DBAR_OMN_CC, GS1NOCHECK_MODE, -1, "12345678901231", "[20]1A", 0, "(01)12345678901231" }, + /* 18*/ { BARCODE_DBAR_LTD_CC, -1, -1, "1234567890123", "[20]12", 0, "(01)12345678901231" }, + /* 19*/ { BARCODE_DBAR_LTD_CC, -1, BARCODE_PLAIN_HRT, "1234567890123", "[20]12", 0, "0112345678901231" }, + /* 20*/ { BARCODE_DBAR_LTD_CC, -1, -1, "12345678901231", "[20]12", 0, "(01)12345678901231" }, + /* 21*/ { BARCODE_DBAR_LTD_CC, -1, -1, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, + /* 22*/ { BARCODE_DBAR_LTD_CC, GS1NOCHECK_MODE, -1, "12345678901232", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ + /* 23*/ { BARCODE_DBAR_LTD_CC, -1, -1, "12345678901231", "[20]1A", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231" }, /* AI (20) should be 2 nos. */ + /* 24*/ { BARCODE_DBAR_LTD_CC, GS1NOCHECK_MODE, -1, "12345678901231", "[20]1A", 0, "(01)12345678901231" }, + /* 25*/ { BARCODE_UPCA_CC, -1, -1, "12345678901", "[20]12", 0, "123456789012" }, + /* 26*/ { BARCODE_UPCA_CC, -1, BARCODE_PLAIN_HRT, "12345678901", "[20]12", 0, "123456789012" }, + /* 27*/ { BARCODE_UPCA_CC, -1, -1, "123456789012", "[20]12", 0, "123456789012" }, + /* 28*/ { BARCODE_UPCA_CC, -1, -1, "123456789013", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, + /* 29*/ { BARCODE_UPCA_CC, GS1NOCHECK_MODE, -1, "123456789013", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ + /* 30*/ { BARCODE_UPCA_CC, -1, -1, "123456789012", "[20]1A", ZINT_WARN_NONCOMPLIANT, "123456789012" }, /* AI (20) should be 2 nos. */ + /* 31*/ { BARCODE_UPCA_CC, GS1NOCHECK_MODE, -1, "123456789012", "[20]1A", 0, "123456789012" }, + /* 32*/ { BARCODE_UPCA_CC, -1, -1, "123456789012+123", "[20]12", 0, "123456789012+00123" }, + /* 33*/ { BARCODE_UPCA_CC, -1, BARCODE_PLAIN_HRT, "123456789012+123", "[20]12", 0, "12345678901200123" }, + /* 34*/ { BARCODE_UPCE_CC, -1, -1, "123456", "[20]12", 0, "01234565" }, + /* 35*/ { BARCODE_UPCE_CC, -1, BARCODE_PLAIN_HRT, "123456", "[20]12", 0, "01234565" }, + /* 36*/ { BARCODE_UPCE_CC, -1, -1, "1234567", "[20]12", 0, "12345670" }, + /* 37*/ { BARCODE_UPCE_CC, -1, -1, "12345670", "[20]12", 0, "12345670" }, + /* 38*/ { BARCODE_UPCE_CC, -1, -1, "12345671", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, + /* 39*/ { BARCODE_UPCE_CC, GS1NOCHECK_MODE, -1, "12345671", "[20]12", ZINT_ERROR_INVALID_CHECK, "" }, /* Still checked */ + /* 40*/ { BARCODE_UPCE_CC, -1, -1, "12345670", "[20]12", 0, "12345670" }, /* Check digit can now be given for UPCE_CC, like UPCA_CC */ + /* 41*/ { BARCODE_UPCE_CC, -1, -1, "1234567", "[20]1A", ZINT_WARN_NONCOMPLIANT, "12345670" }, /* AI (20) should be 2 nos. */ + /* 42*/ { BARCODE_UPCE_CC, GS1NOCHECK_MODE, -1, "1234567", "[20]1A", 0, "12345670" }, + /* 43*/ { BARCODE_UPCE_CC, -1, -1, "1234567+2", "[20]12", 0, "12345670+02" }, + /* 44*/ { BARCODE_UPCE_CC, -1, BARCODE_PLAIN_HRT, "1234567+2", "[20]12", 0, "1234567002" }, + /* 45*/ { BARCODE_DBAR_STK_CC, -1, -1, "12345678901231", "[20]12", 0, "" }, /* No HRT for stacked symbologies */ + /* 46*/ { BARCODE_DBAR_STK_CC, -1, BARCODE_PLAIN_HRT, "12345678901231", "[20]12", 0, "" }, + /* 47*/ { BARCODE_DBAR_OMNSTK_CC, -1, -1, "12345678901231", "[20]12", 0, "" }, + /* 48*/ { BARCODE_DBAR_OMNSTK_CC, -1, BARCODE_PLAIN_HRT, "12345678901231", "[20]12", 0, "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, composite_length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -3277,15 +3293,21 @@ static void test_hrt(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, -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 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); assert_zero(length >= 128, "i:%d length %d >= 128\n", i, length); strcpy(symbol->primary, data[i].data); + expected_length = (int) strlen(data[i].expected); + composite_length = (int) strlen(data[i].composite); ret = ZBarcode_Encode(symbol, TCU(data[i].composite), composite_length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, data[i].ret, ret, symbol->errtxt); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); diff --git a/backend/tests/test_dmatrix.c b/backend/tests/test_dmatrix.c index c7dde9c9..022b2d6e 100644 --- a/backend/tests/test_dmatrix.c +++ b/backend/tests/test_dmatrix.c @@ -1175,9 +1175,8 @@ static void test_input(const testCtx *const p_ctx) { data[i].expected_rows * data[i].expected_width, data[i - 1].expected_rows * data[i - 1].expected_width); if ((data[i].input_mode & 0x07) == GS1_MODE) { - ret = gs1_verify(symbol, (unsigned char *) data[i].data, length, reduced); + ret = gs1_verify(symbol, (unsigned char *) data[i].data, length, reduced, &length); assert_zero(ret, "i:%d gs1_verify() ret %d != 0 (%s)\n", i, ret, symbol->errtxt); - length = (int) ustrlen(reduced); text = reduced; } else { text = (unsigned char *) data[i].data; diff --git a/backend/tests/test_dxfilmedge.c b/backend/tests/test_dxfilmedge.c index eecbeccd..552e98d5 100644 --- a/backend/tests/test_dxfilmedge.c +++ b/backend/tests/test_dxfilmedge.c @@ -31,6 +31,135 @@ #include "testcommon.h" +static void test_hrt(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int output_options; + const char *data; + + const char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { -1, "79-7", "" }, /* None */ + /* 1*/ { BARCODE_PLAIN_HRT, "79-7", "1271" }, + /* 2*/ { -1, "1271", "" }, /* None */ + /* 3*/ { BARCODE_PLAIN_HRT, "1271", "1271" }, + /* 4*/ { -1, "012710", "" }, /* None */ + /* 5*/ { BARCODE_PLAIN_HRT, "012710", "1271" }, + /* 6*/ { -1, "1-0", "" }, /* None */ + /* 7*/ { BARCODE_PLAIN_HRT, "1-0", "0016" }, + /* 8*/ { -1, "2047/63A", "" }, /* None */ + /* 9*/ { BARCODE_PLAIN_HRT, "2047/63A", "204763A" }, + /* 10*/ { -1, "79-7/1", "" }, /* None */ + /* 11*/ { BARCODE_PLAIN_HRT, "79-7/1", "12711" }, + /* 12*/ { -1, "79-7/sa", "" }, /* None */ + /* 13*/ { BARCODE_PLAIN_HRT, "79-7/sa", "127162A" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + int expected_length; + + testStartSymbol("test_hrt", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, BARCODE_DXFILMEDGE, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); + + ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d (%s)\n", + i, symbol->text_length, expected_length, symbol->text); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int input_mode; + const char *data; + int ret; + int expected_rows; + int expected_width; + const char *expected_errtxt; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_DXFILMEDGE, -1, "79-1/123A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 972: Frame number part length 4 too long (maximum 3)" }, + /* 1*/ { BARCODE_DXFILMEDGE, -1, "79-1/1@A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 973: Frame number \"1@A\" is invalid (expected digits, optionally followed by a single \"A\")" }, + /* 2*/ { BARCODE_DXFILMEDGE, -1, "012312365", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 974: DX information length 9 too long (maximum 6)" }, + /* 3*/ { BARCODE_DXFILMEDGE, -1, "12-", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 977: Wrong format for DX parts 1 and 2 (expected format: NNN-NN, digits)" }, + /* 4*/ { BARCODE_DXFILMEDGE, -1, "01234/00A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 980: DX number \"01234\" is incorrect; expected 4 digits (DX extract) or 6 digits (DX full)" }, + /* 5*/ { BARCODE_DXFILMEDGE, -1, "0123/0AA", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 983: Frame number \"0AA\" is invalid (expected digits, optionally followed by a single \"A\")" }, + /* 6*/ { BARCODE_DXFILMEDGE, -1, "128-0/24", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 978: DX part 1 \"128\" out of range (1 to 127)" }, + /* 7*/ { BARCODE_DXFILMEDGE, -1, "127-16", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 979: DX part 2 \"16\" out of range (0 to 15)" }, + /* 8*/ { BARCODE_DXFILMEDGE, -1, "79-2/A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 983: Frame number \"A\" is invalid (expected digits, optionally followed by a single \"A\")" }, + /* 9*/ { BARCODE_DXFILMEDGE, -1, "79-2/-1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 984: Frame number \"-1\" out of range (0 to 63)" }, + /* 10*/ { BARCODE_DXFILMEDGE, -1, "79-2/64", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 984: Frame number \"64\" out of range (0 to 63)" }, + /* 11*/ { BARCODE_DXFILMEDGE, -1, "79-2-1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 976: The \"-\" is used to separate DX parts 1 and 2, and should be used no more than once" }, + /* 12*/ { BARCODE_DXFILMEDGE, -1, "110-2/2B", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 985: Frame number \"2B\" is invalid (expected digits, optionally followed by a single \"A\")" }, + /* 13*/ { BARCODE_DXFILMEDGE, -1, "099990/123A", ZINT_ERROR_TOO_LONG, -1, -1, "Error 986: Input length 11 too long (maximum 10)" }, + /* 14*/ { BARCODE_DXFILMEDGE, -1, "0123123/1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 971: DX information length 7 too long (maximum 6)" }, + /* 15*/ { BARCODE_DXFILMEDGE, -1, "120481", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 981: DX extract \"2048\" out of range (16 to 2047)" }, + /* 16*/ { BARCODE_DXFILMEDGE, -1, "100151", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 981: DX extract \"15\" out of range (16 to 2047)" }, + /* 17*/ { BARCODE_DXFILMEDGE, -1, "15", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 981: DX extract \"15\" out of range (16 to 2047)" }, + /* 18*/ { BARCODE_DXFILMEDGE, -1, "12-12A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 975: Invalid character at position 6 in DX info (digits and \"-\" character only)" }, + /* 19*/ { BARCODE_DXFILMEDGE, -1, "012X", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 975: Invalid character at position 4 in DX info (digits and \"-\" character only)" }, + /* 20*/ { BARCODE_DXFILMEDGE, -1, "110-2/", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 982: Frame number indicator \"/\" at position 6, but frame number is empty" }, + /* 21*/ { BARCODE_DXFILMEDGE, -1, "/", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 970: Invalid first character \"/\", DX code should start with a number" }, + /* 22*/ { BARCODE_DXFILMEDGE, -1, "-12", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 970: Invalid first character \"-\", DX code should start with a number" }, + /* 23*/ { BARCODE_DXFILMEDGE, -1, "X1234X", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 970: Invalid first character \"X\", DX code should start with a number" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + + testStartSymbol("test_input", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + 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); + + 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); + + 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); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_encode(const testCtx *const p_ctx) { int debug = p_ctx->debug; @@ -206,79 +335,10 @@ static void test_encode(const testCtx *const p_ctx) { testFinish(); } -static void test_input(const testCtx *const p_ctx) { - int debug = p_ctx->debug; - - struct item { - int symbology; - int input_mode; - const char *data; - int ret; - int expected_rows; - int expected_width; - const char *expected_errtxt; - }; - /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ - static const struct item data[] = { - /* 0*/ { BARCODE_DXFILMEDGE, -1, "79-1/123A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 972: Frame number part length 4 too long (maximum 3)" }, - /* 1*/ { BARCODE_DXFILMEDGE, -1, "79-1/1@A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 973: Frame number \"1@A\" is invalid (expected digits, optionally followed by a single \"A\")" }, - /* 2*/ { BARCODE_DXFILMEDGE, -1, "012312365", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 974: DX information length 9 too long (maximum 6)" }, - /* 3*/ { BARCODE_DXFILMEDGE, -1, "12-", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 977: Wrong format for DX parts 1 and 2 (expected format: NNN-NN, digits)" }, - /* 4*/ { BARCODE_DXFILMEDGE, -1, "01234/00A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 980: DX number \"01234\" is incorrect; expected 4 digits (DX extract) or 6 digits (DX full)" }, - /* 5*/ { BARCODE_DXFILMEDGE, -1, "0123/0AA", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 983: Frame number \"0AA\" is invalid (expected digits, optionally followed by a single \"A\")" }, - /* 6*/ { BARCODE_DXFILMEDGE, -1, "128-0/24", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 978: DX part 1 \"128\" out of range (1 to 127)" }, - /* 7*/ { BARCODE_DXFILMEDGE, -1, "127-16", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 979: DX part 2 \"16\" out of range (0 to 15)" }, - /* 8*/ { BARCODE_DXFILMEDGE, -1, "79-2/A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 983: Frame number \"A\" is invalid (expected digits, optionally followed by a single \"A\")" }, - /* 9*/ { BARCODE_DXFILMEDGE, -1, "79-2/-1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 984: Frame number \"-1\" out of range (0 to 63)" }, - /* 10*/ { BARCODE_DXFILMEDGE, -1, "79-2/64", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 984: Frame number \"64\" out of range (0 to 63)" }, - /* 11*/ { BARCODE_DXFILMEDGE, -1, "79-2-1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 976: The \"-\" is used to separate DX parts 1 and 2, and should be used no more than once" }, - /* 12*/ { BARCODE_DXFILMEDGE, -1, "110-2/2B", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 985: Frame number \"2B\" is invalid (expected digits, optionally followed by a single \"A\")" }, - /* 13*/ { BARCODE_DXFILMEDGE, -1, "099990/123A", ZINT_ERROR_TOO_LONG, -1, -1, "Error 986: Input length 11 too long (maximum 10)" }, - /* 14*/ { BARCODE_DXFILMEDGE, -1, "0123123/1", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 971: DX information length 7 too long (maximum 6)" }, - /* 15*/ { BARCODE_DXFILMEDGE, -1, "120481", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 981: DX extract \"2048\" out of range (16 to 2047)" }, - /* 16*/ { BARCODE_DXFILMEDGE, -1, "100151", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 981: DX extract \"15\" out of range (16 to 2047)" }, - /* 17*/ { BARCODE_DXFILMEDGE, -1, "15", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 981: DX extract \"15\" out of range (16 to 2047)" }, - /* 18*/ { BARCODE_DXFILMEDGE, -1, "12-12A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 975: Invalid character at position 6 in DX info (digits and \"-\" character only)" }, - /* 19*/ { BARCODE_DXFILMEDGE, -1, "012X", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 975: Invalid character at position 4 in DX info (digits and \"-\" character only)" }, - /* 20*/ { BARCODE_DXFILMEDGE, -1, "110-2/", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 982: Frame number indicator \"/\" at position 6, but frame number is empty" }, - /* 21*/ { BARCODE_DXFILMEDGE, -1, "/", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 970: Invalid first character \"/\", DX code should start with a number" }, - /* 22*/ { BARCODE_DXFILMEDGE, -1, "-12", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 970: Invalid first character \"-\", DX code should start with a number" }, - /* 23*/ { BARCODE_DXFILMEDGE, -1, "X1234X", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 970: Invalid first character \"X\", DX code should start with a number" }, - }; - const int data_size = ARRAY_SIZE(data); - int i, length, ret; - struct zint_symbol *symbol = NULL; - - testStartSymbol("test_input", &symbol); - - for (i = 0; i < data_size; i++) { - - if (testContinue(p_ctx, i)) continue; - - 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); - - 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); - - 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); - } - - ZBarcode_Delete(symbol); - } - - testFinish(); -} - int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func */ + { "test_hrt", test_hrt }, { "test_input", test_input }, { "test_encode", test_encode }, }; diff --git a/backend/tests/test_gs1.c b/backend/tests/test_gs1.c index 771aff08..f8ef9a45 100644 --- a/backend/tests/test_gs1.c +++ b/backend/tests/test_gs1.c @@ -265,6 +265,7 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int input_mode; + int output_options; const char *data; const char *composite; @@ -273,64 +274,96 @@ static void test_hrt(const testCtx *const p_ctx) { }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_GS1_128, -1, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* Incorrect check digit */ - /* 1*/ { BARCODE_GS1_128, GS1NOCHECK_MODE, "[01]12345678901234[20]12", "", 0, "(01)12345678901234(20)12" }, - /* 2*/ { BARCODE_GS1_128, -1, "[01]12345678901231[20]12", "", 0, "(01)12345678901231(20)12" }, - /* 3*/ { BARCODE_GS1_128, -1, "[01]12345678901231[10]12[20]AB", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)12(20)AB" }, /* AI (20) should be 2 nos. */ - /* 4*/ { BARCODE_GS1_128, GS1NOCHECK_MODE, "[01]12345678901231[10]10[20]AB", "", 0, "(01)12345678901231(10)10(20)AB" }, - /* 5*/ { BARCODE_GS1_128, -1, "[01]12345678901231[10]AB[20]12", "", 0, "(01)12345678901231(10)AB(20)12" }, - /* 6*/ { BARCODE_GS1_128, -1, "[91]ABCDEF]GH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDEF]GH" }, /* Invalid CSET 82 character */ - /* 7*/ { BARCODE_GS1_128, GS1NOCHECK_MODE, "[91]ABCDEF]GH", "", 0, "(91)ABCDEF]GH" }, - /* 8*/ { BARCODE_GS1_128, -1, "[91]ABCDEF)GH", "", 0, "(91)ABCDEF)GH" }, - /* 9*/ { BARCODE_GS1_128, -1, "[91]ABCDEF(GH", "", 0, "(91)ABCDEF(GH" }, - /* 10*/ { BARCODE_GS1_128, -1, "[91]ABCDE(20)12", "", 0, "(91)ABCDE(20)12" }, - /* 11*/ { BARCODE_GS1_128, GS1PARENS_MODE, "(91)ABCDEF]GH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDEF]GH" }, /* Invalid CSET 82 character */ - /* 12*/ { BARCODE_GS1_128, GS1PARENS_MODE | GS1NOCHECK_MODE, "(91)ABCDEF]GH", "", 0, "(91)ABCDEF]GH" }, - /* 13*/ { BARCODE_GS1_128, GS1PARENS_MODE, "(91)ABCDEF)GH", "", 0, "(91)ABCDEF)GH" }, - /* 14*/ { BARCODE_GS1_128, GS1PARENS_MODE, "(91)ABCDE[FGH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDE[FGH" }, /* Invalid CSET 82 character */ - /* 15*/ { BARCODE_GS1_128, GS1PARENS_MODE | GS1NOCHECK_MODE, "(91)ABCDE[FGH", "", 0, "(91)ABCDE[FGH" }, - /* 16*/ { BARCODE_GS1_128, GS1PARENS_MODE, "(91)ABCDE[92]GH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDE[92]GH" }, /* Invalid CSET 82 character */ - /* 17*/ { BARCODE_GS1_128, GS1PARENS_MODE | GS1NOCHECK_MODE, "(91)ABCDE[92]GH", "", 0, "(91)ABCDE[92]GH" }, - /* 18*/ { BARCODE_GS1_128_CC, -1, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* Incorrect check digit */ - /* 19*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, "[01]12345678901234[20]12", "[21]12345", 0, "(01)12345678901234(20)12" }, - /* 20*/ { BARCODE_GS1_128_CC, -1, "[01]12345678901231[20]12", "[21]12345", 0, "(01)12345678901231(20)12" }, - /* 21*/ { BARCODE_GS1_128_CC, -1, "[01]12345678901231[10]12[20]AB", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)12(20)AB" }, /* AI (20) should be 2 nos. */ - /* 22*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, "[01]12345678901231[10]12[20]AB", "[21]12345", 0, "(01)12345678901231(10)12(20)AB" }, - /* 23*/ { BARCODE_GS1_128_CC, -1, "[01]12345678901231[10]AB[20]12", "[21]12345", 0, "(01)12345678901231(10)AB(20)12" }, - /* 24*/ { BARCODE_GS1_128_CC, -1, "[01]12345678901231[10]AB[20]12", "[30]1234567A", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)AB(20)12" }, - /* 25*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, "[01]12345678901231[10]AB[20]12", "[30]1234567A", 0, "(01)12345678901231(10)AB(20)12" }, - /* 26*/ { BARCODE_EAN14, -1, "1234567890123", "", 0, "(01)12345678901231" }, - /* 27*/ { BARCODE_EAN14, -1, "1234", "", 0, "(01)00000000012348" }, - /* 28*/ { BARCODE_EAN14, -1, "12345", "", 0, "(01)00000000123457" }, - /* 29*/ { BARCODE_EAN14, -1, "12340", "", 0, "(01)00000000123402" }, - /* 30*/ { BARCODE_NVE18, -1, "12345678901234567", "", 0, "(00)123456789012345675" }, - /* 31*/ { BARCODE_NVE18, -1, "1234", "", 0, "(00)000000000000012348" }, - /* 32*/ { BARCODE_NVE18, -1, "12345", "", 0, "(00)000000000000123457" }, - /* 33*/ { BARCODE_NVE18, -1, "12340", "", 0, "(00)000000000000123402" }, - /* 34*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* Incorrect check digit */ - /* 35*/ { BARCODE_DBAR_EXP, GS1NOCHECK_MODE, "[01]12345678901234[20]12", "", 0, "(01)12345678901234(20)12" }, - /* 36*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[20]12", "", 0, "(01)12345678901231(20)12" }, - /* 37*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[10]12[20]AB", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)12(20)AB" }, /* AI (20) should be 2 nos. */ - /* 38*/ { BARCODE_DBAR_EXP, GS1NOCHECK_MODE, "[01]12345678901231[10]12[20]AB", "", 0, "(01)12345678901231(10)12(20)AB" }, - /* 39*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[10]AB[20]12", "", 0, "(01)12345678901231(10)AB(20)12" }, - /* 40*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[10]AB[20]12[90]ABC(2012", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC(2012" }, - /* 41*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[10]AB[20]12[90]ABC20)12", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC20)12" }, - /* 42*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[10]AB[20]12[90]ABC(20)12", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC(20)12" }, - /* 43*/ { BARCODE_DBAR_EXP_CC, -1, "[01]12345678901234", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234" }, - /* 44*/ { BARCODE_DBAR_EXP_CC, GS1NOCHECK_MODE, "[01]12345678901234", "[21]12345", 0, "(01)12345678901234" }, - /* 45*/ { BARCODE_DBAR_EXP_CC, -1, "[01]12345678901231", "[21]12345", 0, "(01)12345678901231" }, - /* 46*/ { BARCODE_DBAR_EXP_CC, -1, "[01]12345678901231[20]12[21]12345", "[21]12345", 0, "(01)12345678901231(20)12(21)12345" }, - /* 47*/ { BARCODE_DBAR_EXPSTK, -1, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "" }, - /* 48*/ { BARCODE_DBAR_EXPSTK, GS1NOCHECK_MODE, "[01]12345678901234[20]12", "", 0, "" }, - /* 49*/ { BARCODE_DBAR_EXPSTK, -1, "[01]12345678901231[20]12", "", 0, "" }, - /* 50*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231[20]12[90]ABC(20)12", "", 0, "(01)12345678901231(20)12(90)ABC(20)12" }, - /* 51*/ { BARCODE_DBAR_EXPSTK_CC, -1, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "" }, - /* 52*/ { BARCODE_DBAR_EXPSTK_CC, GS1NOCHECK_MODE, "[01]12345678901234[20]12", "[21]12345", 0, "" }, - /* 53*/ { BARCODE_DBAR_EXPSTK_CC, -1, "[01]12345678901231[20]12", "[21]12345", 0, "" }, + /* 0*/ { BARCODE_GS1_128, -1, -1, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* Incorrect check digit */ + /* 1*/ { BARCODE_GS1_128, GS1NOCHECK_MODE, -1, "[01]12345678901234[20]12", "", 0, "(01)12345678901234(20)12" }, + /* 2*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "01123456789012342012" }, + /* 3*/ { BARCODE_GS1_128, -1, -1, "[01]12345678901231[20]12", "", 0, "(01)12345678901231(20)12" }, + /* 4*/ { BARCODE_GS1_128, -1, -1, "[01]12345678901231[10]12[20]AB", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)12(20)AB" }, /* AI (20) should be 2 nos. */ + /* 5*/ { BARCODE_GS1_128, GS1NOCHECK_MODE, -1, "[01]12345678901231[10]10[20]AB", "", 0, "(01)12345678901231(10)10(20)AB" }, + /* 6*/ { BARCODE_GS1_128, -1, -1, "[01]12345678901231[10]AB[20]12", "", 0, "(01)12345678901231(10)AB(20)12" }, + /* 7*/ { BARCODE_GS1_128, -1, -1, "[91]ABCDEF]GH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDEF]GH" }, /* Invalid CSET 82 character */ + /* 8*/ { BARCODE_GS1_128, GS1NOCHECK_MODE, -1, "[91]ABCDEF]GH", "", 0, "(91)ABCDEF]GH" }, + /* 9*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[91]ABCDEF]GH", "", ZINT_WARN_NONCOMPLIANT, "91ABCDEF]GH" }, + /* 10*/ { BARCODE_GS1_128, -1, -1, "[91]ABCDEF)GH", "", 0, "(91)ABCDEF)GH" }, + /* 11*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[91]ABCDEF)GH", "", 0, "91ABCDEF)GH" }, + /* 12*/ { BARCODE_GS1_128, -1, -1, "[91]ABCDEF(GH", "", 0, "(91)ABCDEF(GH" }, + /* 13*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[91]ABCDEF(GH", "", 0, "91ABCDEF(GH" }, + /* 14*/ { BARCODE_GS1_128, -1, -1, "[91]ABCDE(20)12", "", 0, "(91)ABCDE(20)12" }, + /* 15*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[91]ABCDE(20)12", "", 0, "91ABCDE(20)12" }, + /* 16*/ { BARCODE_GS1_128, -1, -1, "[90]1234[91]ABCDE(20)12", "", 0, "(90)1234(91)ABCDE(20)12" }, + /* 17*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[90]1234[91]ABCDE(20)12", "", 0, "901234\03591ABCDE(20)12" }, + /* 18*/ { BARCODE_GS1_128, -1, -1, "[90]1234[91]ABCDE(20)12[20]12", "", 0, "(90)1234(91)ABCDE(20)12(20)12" }, + /* 19*/ { BARCODE_GS1_128, -1, BARCODE_PLAIN_HRT, "[90]1234[91]ABCDE(20)12[20]12", "", 0, "901234\03591ABCDE(20)12\0352012" }, + /* 20*/ { BARCODE_GS1_128, GS1PARENS_MODE, -1, "(91)ABCDEF]GH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDEF]GH" }, /* Invalid CSET 82 character */ + /* 21*/ { BARCODE_GS1_128, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "(91)ABCDEF]GH", "", 0, "(91)ABCDEF]GH" }, + /* 22*/ { BARCODE_GS1_128, GS1PARENS_MODE, BARCODE_PLAIN_HRT, "(91)ABCDEF]GH", "", ZINT_WARN_NONCOMPLIANT, "91ABCDEF]GH" }, + /* 23*/ { BARCODE_GS1_128, GS1PARENS_MODE, -1, "(91)ABCDEF)GH", "", 0, "(91)ABCDEF)GH" }, + /* 24*/ { BARCODE_GS1_128, GS1PARENS_MODE, BARCODE_PLAIN_HRT, "(91)ABCDEF)GH", "", 0, "91ABCDEF)GH" }, + /* 25*/ { BARCODE_GS1_128, GS1PARENS_MODE, -1, "(91)ABCDE[FGH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDE[FGH" }, /* Invalid CSET 82 character */ + /* 26*/ { BARCODE_GS1_128, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "(91)ABCDE[FGH", "", 0, "(91)ABCDE[FGH" }, + /* 27*/ { BARCODE_GS1_128, GS1PARENS_MODE, BARCODE_PLAIN_HRT, "(91)ABCDE[FGH", "", ZINT_WARN_NONCOMPLIANT, "91ABCDE[FGH" }, + /* 28*/ { BARCODE_GS1_128, GS1PARENS_MODE, -1, "(91)ABCDE[92]GH", "", ZINT_WARN_NONCOMPLIANT, "(91)ABCDE[92]GH" }, /* Invalid CSET 82 character */ + /* 29*/ { BARCODE_GS1_128, GS1PARENS_MODE | GS1NOCHECK_MODE, -1, "(91)ABCDE[92]GH", "", 0, "(91)ABCDE[92]GH" }, + /* 30*/ { BARCODE_GS1_128, GS1PARENS_MODE, BARCODE_PLAIN_HRT, "(91)ABCDE[92]GH", "", ZINT_WARN_NONCOMPLIANT, "91ABCDE[92]GH" }, + /* 31*/ { BARCODE_GS1_128_CC, -1, -1, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* Incorrect check digit */ + /* 32*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, -1, "[01]12345678901234[20]12", "[21]12345", 0, "(01)12345678901234(20)12" }, + /* 33*/ { BARCODE_GS1_128_CC, -1, BARCODE_PLAIN_HRT, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "01123456789012342012" }, + /* 34*/ { BARCODE_GS1_128_CC, -1, -1, "[01]12345678901231[20]12", "[21]12345", 0, "(01)12345678901231(20)12" }, + /* 35*/ { BARCODE_GS1_128_CC, -1, -1, "[01]12345678901231[10]12[20]AB", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)12(20)AB" }, /* AI (20) should be 2 nos. */ + /* 36*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, -1, "[01]12345678901231[10]12[20]AB", "[21]12345", 0, "(01)12345678901231(10)12(20)AB" }, + /* 37*/ { BARCODE_GS1_128_CC, -1, -1, "[01]12345678901231[10]AB[20]12", "[21]12345", 0, "(01)12345678901231(10)AB(20)12" }, + /* 38*/ { BARCODE_GS1_128_CC, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]AB[20]12", "[21]12345", 0, "011234567890123110AB\0352012" }, + /* 39*/ { BARCODE_GS1_128_CC, -1, -1, "[01]12345678901231[10]AB[20]12", "[30]1234567A", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)AB(20)12" }, + /* 40*/ { BARCODE_GS1_128_CC, GS1NOCHECK_MODE, -1, "[01]12345678901231[10]AB[20]12", "[30]1234567A", 0, "(01)12345678901231(10)AB(20)12" }, + /* 41*/ { BARCODE_EAN14, -1, -1, "1234567890123", "", 0, "(01)12345678901231" }, + /* 42*/ { BARCODE_EAN14, -1, BARCODE_PLAIN_HRT, "1234567890123", "", 0, "0112345678901231" }, + /* 43*/ { BARCODE_EAN14, -1, -1, "1234", "", 0, "(01)00000000012348" }, + /* 44*/ { BARCODE_EAN14, -1, BARCODE_PLAIN_HRT, "1234", "", 0, "0100000000012348" }, + /* 45*/ { BARCODE_EAN14, -1, -1, "12345", "", 0, "(01)00000000123457" }, + /* 46*/ { BARCODE_EAN14, -1, -1, "12340", "", 0, "(01)00000000123402" }, + /* 47*/ { BARCODE_NVE18, -1, -1, "12345678901234567", "", 0, "(00)123456789012345675" }, + /* 48*/ { BARCODE_NVE18, -1, BARCODE_PLAIN_HRT, "12345678901234567", "", 0, "00123456789012345675" }, + /* 49*/ { BARCODE_NVE18, -1, -1, "1234", "", 0, "(00)000000000000012348" }, + /* 50*/ { BARCODE_NVE18, -1, BARCODE_PLAIN_HRT, "1234", "", 0, "00000000000000012348" }, + /* 51*/ { BARCODE_NVE18, -1, -1, "12345", "", 0, "(00)000000000000123457" }, + /* 52*/ { BARCODE_NVE18, -1, -1, "12340", "", 0, "(00)000000000000123402" }, + /* 53*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234(20)12" }, /* Incorrect check digit */ + /* 54*/ { BARCODE_DBAR_EXP, GS1NOCHECK_MODE, -1, "[01]12345678901234[20]12", "", 0, "(01)12345678901234(20)12" }, + /* 55*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "01123456789012342012" }, + /* 56*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[20]12", "", 0, "(01)12345678901231(20)12" }, + /* 57*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[20]12", "", 0, "01123456789012312012" }, + /* 58*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[10]12[20]AB", "", ZINT_WARN_NONCOMPLIANT, "(01)12345678901231(10)12(20)AB" }, /* AI (20) should be 2 nos. */ + /* 59*/ { BARCODE_DBAR_EXP, GS1NOCHECK_MODE, -1, "[01]12345678901231[10]12[20]AB", "", 0, "(01)12345678901231(10)12(20)AB" }, + /* 60*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]12[20]AB", "", ZINT_WARN_NONCOMPLIANT, "01123456789012311012\03520AB" }, + /* 61*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[10]AB[20]12", "", 0, "(01)12345678901231(10)AB(20)12" }, + /* 62*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]AB[20]12", "", 0, "011234567890123110AB\0352012" }, + /* 63*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[10]AB[20]12[90]ABC(2012", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC(2012" }, + /* 64*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]AB[20]12[90]ABC(2012", "", 0, "011234567890123110AB\035201290ABC(2012" }, + /* 65*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[10]AB[20]12[90]ABC20)12", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC20)12" }, + /* 66*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]AB[20]12[90]ABC20)12", "", 0, "011234567890123110AB\035201290ABC20)12" }, + /* 67*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[10]AB[20]12[90]ABC(20)12", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC(20)12" }, + /* 68*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]AB[20]12[90]ABC(20)12", "", 0, "011234567890123110AB\035201290ABC(20)12" }, + /* 69*/ { BARCODE_DBAR_EXP, -1, -1, "[01]12345678901231[10]AB[20]12[90]ABC(20)12[91]12(", "", 0, "(01)12345678901231(10)AB(20)12(90)ABC(20)12(91)12(" }, + /* 70*/ { BARCODE_DBAR_EXP, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[10]AB[20]12[90]ABC(20)12[91]12(", "", 0, "011234567890123110AB\035201290ABC(20)12\0359112(" }, + /* 71*/ { BARCODE_DBAR_EXP_CC, -1, -1, "[01]12345678901234", "[21]12345", ZINT_WARN_NONCOMPLIANT, "(01)12345678901234" }, + /* 72*/ { BARCODE_DBAR_EXP_CC, GS1NOCHECK_MODE, -1, "[01]12345678901234", "[21]12345", 0, "(01)12345678901234" }, + /* 73*/ { BARCODE_DBAR_EXP_CC, -1, BARCODE_PLAIN_HRT, "[01]12345678901234", "[21]12345", ZINT_WARN_NONCOMPLIANT, "0112345678901234" }, + /* 74*/ { BARCODE_DBAR_EXP_CC, -1, -1, "[01]12345678901231", "[21]12345", 0, "(01)12345678901231" }, + /* 75*/ { BARCODE_DBAR_EXP_CC, -1, -1, "[01]12345678901231[20]12[21]12345", "[21]12345", 0, "(01)12345678901231(20)12(21)12345" }, + /* 76*/ { BARCODE_DBAR_EXP_CC, -1, BARCODE_PLAIN_HRT, "[01]12345678901231[20]12[21]12345", "[21]12345", 0, "011234567890123120122112345" }, + /* 77*/ { BARCODE_DBAR_EXPSTK, -1, -1, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "" }, + /* 78*/ { BARCODE_DBAR_EXPSTK, GS1NOCHECK_MODE, -1, "[01]12345678901234[20]12", "", 0, "" }, + /* 79*/ { BARCODE_DBAR_EXPSTK, -1, BARCODE_PLAIN_HRT, "[01]12345678901234[20]12", "", ZINT_WARN_NONCOMPLIANT, "" }, + /* 80*/ { BARCODE_DBAR_EXPSTK, -1, -1, "[01]12345678901231[20]12", "", 0, "" }, + /* 81*/ { BARCODE_DBAR_EXPSTK_CC, -1, -1, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "" }, + /* 82*/ { BARCODE_DBAR_EXPSTK_CC, GS1NOCHECK_MODE, -1, "[01]12345678901234[20]12", "[21]12345", 0, "" }, + /* 83*/ { BARCODE_DBAR_EXPSTK_CC, -1, BARCODE_PLAIN_HRT, "[01]12345678901234[20]12", "[21]12345", ZINT_WARN_NONCOMPLIANT, "" }, + /* 84*/ { BARCODE_DBAR_EXPSTK_CC, -1, -1, "[01]12345678901231[20]12", "[21]12345", 0, "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; const char *text; @@ -349,12 +382,18 @@ static void test_hrt(const testCtx *const p_ctx) { } else { text = data[i].data; } - length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, text, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + text, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(text), length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, data[i].ret, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } @@ -1407,6 +1446,7 @@ static void test_gs1_verify(const testCtx *const p_ctx) { const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int reduced_length; char reduced[1024]; char escaped[1024]; @@ -1422,7 +1462,7 @@ static void test_gs1_verify(const testCtx *const p_ctx) { length = (int) strlen(data[i].data); - ret = gs1_verify(symbol, (unsigned char *) data[i].data, length, (unsigned char *) reduced); + ret = gs1_verify(symbol, (unsigned char *) data[i].data, length, (unsigned char *) reduced, &reduced_length); if (p_ctx->generate) { printf(" /*%3d*/ { \"%s\", %s, \"%s\", \"%s\" },\n", @@ -1435,6 +1475,8 @@ static void test_gs1_verify(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { assert_zero(strcmp(reduced, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, reduced, data[i].expected); + assert_equal(reduced_length, (int) strlen(reduced), "i:%d reduced_length %d != strlen %d\n", + i, reduced_length, (int) strlen(reduced)); } assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt); @@ -2112,6 +2154,7 @@ static void test_gs1_lint(const testCtx *const p_ctx) { const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int reduced_length; char reduced[1024]; @@ -2126,11 +2169,13 @@ static void test_gs1_lint(const testCtx *const p_ctx) { length = (int) strlen(data[i].data); - ret = gs1_verify(symbol, (unsigned char *) data[i].data, length, (unsigned char *) reduced); + ret = gs1_verify(symbol, (unsigned char *) data[i].data, length, (unsigned char *) reduced, &reduced_length); assert_equal(ret, data[i].ret, "i:%d ret %d != %d (length %d \"%s\") (%s)\n", i, ret, data[i].ret, length, data[i].data, symbol->errtxt); if (ret < ZINT_ERROR) { assert_zero(strcmp(reduced, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, reduced, data[i].expected); + assert_equal(reduced_length, (int) strlen(reduced), "i:%d reduced_length %d != strlen %d\n", + i, reduced_length, (int) strlen(reduced)); } assert_zero(strcmp(symbol->errtxt, data[i].expected_errtxt), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected_errtxt); diff --git a/backend/tests/test_imail.c b/backend/tests/test_imail.c index e915c178..8eed57f1 100644 --- a/backend/tests/test_imail.c +++ b/backend/tests/test_imail.c @@ -167,16 +167,19 @@ static void test_hrt(const testCtx *const p_ctx) { int debug = p_ctx->debug; struct item { + int output_options; const char *data; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { "53379777234994544928-51135759461", "" }, /* None */ + /* 0*/ { -1, "53379777234994544928-51135759461", "" }, /* None */ + /* 1*/ { BARCODE_PLAIN_HRT, "53379777234994544928-51135759461", "53379777234994544928-51135759461" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -187,12 +190,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, BARCODE_USPS_IMAIL, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_USPS_IMAIL, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_mailmark.c b/backend/tests/test_mailmark.c index ad59abac..ef6075f1 100644 --- a/backend/tests/test_mailmark.c +++ b/backend/tests/test_mailmark.c @@ -31,6 +31,61 @@ #include "testcommon.h" +static void test_4s_hrt(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int output_options; + const char *data; + + const char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { -1, "1100000000000XY11", "" }, /* None */ + /* 1*/ { BARCODE_PLAIN_HRT, "1100000000000XY11", "1100000000000XY11 " }, + /* 2*/ { -1, "1100000000000XY11 ", "" }, /* None */ + /* 3*/ { BARCODE_PLAIN_HRT, "1100000000000XY11 ", "1100000000000XY11 " }, + /* 4*/ { -1, "0100000000000A00AA0A", "" }, /* None */ + /* 5*/ { BARCODE_PLAIN_HRT, "0100000000000A00AA0A", "0100000000000A00AA0A " }, /* None */ + /* 6*/ { -1, "41038422416563762XY11 ", "" }, /* None */ + /* 7*/ { BARCODE_PLAIN_HRT, "41038422416563762XY11 ", "41038422416563762XY11 " }, + /* 8*/ { -1, "01000000000000000AA000AA0A", "" }, /* None */ + /* 9*/ { BARCODE_PLAIN_HRT, "01000000000000000AA000AA0A", "01000000000000000AA000AA0A" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + int expected_length; + + testStartSymbol("test_4s_hrt", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, BARCODE_MAILMARK_4S, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); + + ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d (%s)\n", + i, symbol->text_length, expected_length, symbol->text); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_4s_input(const testCtx *const p_ctx) { int debug = p_ctx->debug; @@ -604,6 +659,7 @@ static void test_2d_encode(const testCtx *const p_ctx) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func */ + { "test_4s_hrt", test_4s_hrt }, { "test_4s_input", test_4s_input }, { "test_4s_encode_vector", test_4s_encode_vector }, { "test_4s_encode", test_4s_encode }, diff --git a/backend/tests/test_medical.c b/backend/tests/test_medical.c index 76cf10f6..d78ebea5 100644 --- a/backend/tests/test_medical.c +++ b/backend/tests/test_medical.c @@ -99,28 +99,48 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int option_2; + int output_options; const char *data; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_PHARMA, -1, "123456", "" }, /* None */ - /* 1*/ { BARCODE_PHARMA_TWO, -1, "123456", "" }, /* None */ - /* 2*/ { BARCODE_CODE32, -1, "123456", "A001234564" }, - /* 3*/ { BARCODE_CODE32, -1, "12345678", "A123456788" }, - /* 4*/ { BARCODE_PZN, -1, "12345", "PZN - 00123458" }, /* Pads with zeroes if length < 7 */ - /* 5*/ { BARCODE_PZN, -1, "123456", "PZN - 01234562" }, - /* 6*/ { BARCODE_PZN, -1, "1234567", "PZN - 12345678" }, - /* 7*/ { BARCODE_PZN, -1, "12345678", "PZN - 12345678" }, - /* 8*/ { BARCODE_PZN, 1, "1234", "PZN - 0012345" }, /* PZN7, pads with zeroes if length < 6 */ - /* 9*/ { BARCODE_PZN, 1, "12345", "PZN - 0123458" }, - /* 10*/ { BARCODE_PZN, 1, "123456", "PZN - 1234562" }, - /* 11*/ { BARCODE_PZN, 1, "1234562", "PZN - 1234562" }, + /* 0*/ { BARCODE_PHARMA, -1, -1, "123456", "" }, /* None */ + /* 1*/ { BARCODE_PHARMA, -1, BARCODE_PLAIN_HRT, "123456", "123456" }, + /* 2*/ { BARCODE_PHARMA_TWO, -1, -1, "123456", "" }, /* None */ + /* 3*/ { BARCODE_PHARMA_TWO, -1, BARCODE_PLAIN_HRT, "123456", "123456" }, + /* 4*/ { BARCODE_CODE32, -1, -1, "123456", "A001234564" }, + /* 5*/ { BARCODE_CODE32, -1, BARCODE_PLAIN_HRT, "123456", "015PN4" }, /* Actual encoded CODE39 value */ + /* 6*/ { BARCODE_CODE32, -1, -1, "12345678", "A123456788" }, + /* 7*/ { BARCODE_CODE32, -1, BARCODE_PLAIN_HRT, "12345678", "3PRM8N" }, + /* 8*/ { BARCODE_CODE32, 1, -1, "12345678", "A123456788" }, /* Ignore option_2 re check digits */ + /* 9*/ { BARCODE_CODE32, 1, BARCODE_PLAIN_HRT, "12345678", "3PRM8N" }, + /* 10*/ { BARCODE_CODE32, 2, -1, "12345678", "A123456788" }, /* Ignore option_2 re check digits */ + /* 11*/ { BARCODE_CODE32, 2, BARCODE_PLAIN_HRT, "12345678", "3PRM8N" }, + /* 12*/ { BARCODE_PZN, -1, -1, "12345", "PZN - 00123458" }, /* Pads with zeroes if length < 7 */ + /* 13*/ { BARCODE_PZN, -1, BARCODE_PLAIN_HRT, "12345", "-00123458" }, /* Actual encoded CODE39 value */ + /* 14*/ { BARCODE_PZN, -1, -1, "123456", "PZN - 01234562" }, + /* 15*/ { BARCODE_PZN, -1, BARCODE_PLAIN_HRT, "123456", "-01234562" }, + /* 16*/ { BARCODE_PZN, -1, -1, "1234567", "PZN - 12345678" }, + /* 17*/ { BARCODE_PZN, -1, BARCODE_PLAIN_HRT, "1234567", "-12345678" }, + /* 18*/ { BARCODE_PZN, -1, -1, "12345678", "PZN - 12345678" }, + /* 19*/ { BARCODE_PZN, -1, BARCODE_PLAIN_HRT, "12345678", "-12345678" }, + /* 20*/ { BARCODE_PZN, 1, -1, "1234", "PZN - 0012345" }, /* PZN7, pads with zeroes if length < 6 */ + /* 21*/ { BARCODE_PZN, 1, BARCODE_PLAIN_HRT, "1234", "-0012345" }, + /* 22*/ { BARCODE_PZN, 1, -1, "12345", "PZN - 0123458" }, + /* 23*/ { BARCODE_PZN, 1, BARCODE_PLAIN_HRT, "12345", "-0123458" }, + /* 24*/ { BARCODE_PZN, 1, -1, "123456", "PZN - 1234562" }, + /* 25*/ { BARCODE_PZN, 1, BARCODE_PLAIN_HRT, "123456", "-1234562" }, + /* 26*/ { BARCODE_PZN, 1, -1, "1234562", "PZN - 1234562" }, + /* 27*/ { BARCODE_PZN, 1, BARCODE_PLAIN_HRT, "1234562", "-1234562" }, + /* 28*/ { BARCODE_PZN, 2, -1, "12345", "PZN - 00123458" }, /* Ignore option_2 re check digits */ + /* 29*/ { BARCODE_PZN, 2, BARCODE_PLAIN_HRT, "12345", "-00123458" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -131,12 +151,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d (%s)\n", + i, symbol->text_length, expected_length, symbol->text); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } @@ -270,15 +296,24 @@ static void test_encode(const testCtx *const p_ctx) { /* 4*/ { BARCODE_CODE32, -1, "34567890", 0, 1, 103, "Verified manually against TEC-IT", "1001011011010101101001011010110010110101011011010010101100101101011010010101101010101100110100101101101" }, - /* 5*/ { BARCODE_PZN, -1, "1234567", 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against TEC-IT", + /* 5*/ { BARCODE_CODE32, 1, "34567890", 0, 1, 103, "Make sure option_2 doesn't add extra check digit", + "1001011011010101101001011010110010110101011011010010101100101101011010010101101010101100110100101101101" + }, + /* 6*/ { BARCODE_CODE32, 2, "34567890", 0, 1, 103, "Make sure option_2 doesn't add extra check digit", + "1001011011010101101001011010110010110101011011010010101100101101011010010101101010101100110100101101101" + }, + /* 7*/ { BARCODE_PZN, -1, "1234567", 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against TEC-IT", "1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101" }, - /* 6*/ { BARCODE_PZN, -1, "2758089", 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against TEC-IT", + /* 8*/ { BARCODE_PZN, -1, "2758089", 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against TEC-IT", "1001011011010100101011011010110010101101010010110110110100110101011010010110101010011011010110100101101010110010110101011001011010100101101101" }, - /* 7*/ { BARCODE_PZN, 1, "123456", 0, 1, 129, "Example from BWIPP; verified manually against TEC-IT", + /* 9*/ { BARCODE_PZN, 1, "123456", 0, 1, 129, "Example from BWIPP; verified manually against TEC-IT", "100101101101010010101101101101001010110101100101011011011001010101010011010110110100110101010110011010101011001010110100101101101" }, + /* 10*/ { BARCODE_PZN, 2, "1234567", 0, 1, 142, "Make sure option_2 ignored for check digit", + "1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101" + }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_output.c b/backend/tests/test_output.c index c3d3d0a2..d81158fb 100644 --- a/backend/tests/test_output.c +++ b/backend/tests/test_output.c @@ -346,6 +346,9 @@ static void test_fopen(const testCtx *const p_ctx) { /* 13*/ { "out_test\\", "\\out_test_subdir\\", "out.png", 1 }, /* 14*/ { "", "", "outé.png", 1 }, /* 15*/ { "outé_test", "", "outé.png", 1 }, +#ifdef _WIN32 + /* 16*/ { "out\351_test", "", "out.png", 0 }, /* Invalid UTF-8 */ +#endif }; const int data_size = ARRAY_SIZE(data); int i, len; diff --git a/backend/tests/test_plessey.c b/backend/tests/test_plessey.c index f07c5948..866873ea 100644 --- a/backend/tests/test_plessey.c +++ b/backend/tests/test_plessey.c @@ -109,45 +109,93 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; int option_2; + int output_options; const char *data; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_MSI_PLESSEY, -1, "1234567", "1234567" }, - /* 1*/ { BARCODE_MSI_PLESSEY, 0, "1234567", "1234567" }, - /* 2*/ { BARCODE_MSI_PLESSEY, 1, "1234567", "12345674" }, - /* 3*/ { BARCODE_MSI_PLESSEY, 1 + 10, "1234567", "1234567" }, - /* 4*/ { BARCODE_MSI_PLESSEY, 1, "9999999999", "99999999990" }, - /* 5*/ { BARCODE_MSI_PLESSEY, 2, "1234567", "123456741" }, - /* 6*/ { BARCODE_MSI_PLESSEY, 2 + 10, "1234567", "1234567" }, - /* 7*/ { BARCODE_MSI_PLESSEY, 2, "9999999999", "999999999900" }, - /* 8*/ { BARCODE_MSI_PLESSEY, 3, "1234567", "12345674" }, - /* 9*/ { BARCODE_MSI_PLESSEY, 3 + 10, "1234567", "1234567" }, - /* 10*/ { BARCODE_MSI_PLESSEY, 3, "9999999999", "99999999995" }, - /* 11*/ { BARCODE_MSI_PLESSEY, 4, "1234567", "123456741" }, - /* 12*/ { BARCODE_MSI_PLESSEY, 4 + 10, "1234567", "1234567" }, - /* 13*/ { BARCODE_MSI_PLESSEY, 4, "9999999999", "999999999959" }, - /* 14*/ { BARCODE_MSI_PLESSEY, 5, "1234567", "12345679" }, - /* 15*/ { BARCODE_MSI_PLESSEY, 5 + 10, "1234567", "1234567" }, - /* 16*/ { BARCODE_MSI_PLESSEY, 5, "9999999999", "999999999910" }, - /* 17*/ { BARCODE_MSI_PLESSEY, 6, "1234567", "123456790" }, - /* 18*/ { BARCODE_MSI_PLESSEY, 6 + 10, "1234567", "1234567" }, - /* 19*/ { BARCODE_MSI_PLESSEY, 6, "9999999999", "9999999999109" }, - /* 20*/ { BARCODE_MSI_PLESSEY, 1, "123456", "1234566" }, - /* 21*/ { BARCODE_MSI_PLESSEY, 2, "123456", "12345666" }, - /* 22*/ { BARCODE_MSI_PLESSEY, 3, "123456", "1234560" }, - /* 23*/ { BARCODE_MSI_PLESSEY, 4, "123456", "12345609" }, - /* 24*/ { BARCODE_MSI_PLESSEY, 3, "2211", "221110" }, /* Mod-11 check digit '10' */ - /* 25*/ { BARCODE_MSI_PLESSEY, 3 + 10, "2211", "2211" }, /* Mod-11 check digit '10' */ - /* 26*/ { BARCODE_MSI_PLESSEY, 4, "2211", "2211100" }, - /* 27*/ { BARCODE_MSI_PLESSEY, 4 + 10, "2211", "2211" }, - /* 28*/ { BARCODE_PLESSEY, -1, "0123456789ABCDEF", "0123456789ABCDEF" }, + /* 0*/ { BARCODE_MSI_PLESSEY, -1, -1, "1234567", "1234567" }, + /* 1*/ { BARCODE_MSI_PLESSEY, -1, BARCODE_PLAIN_HRT, "1234567", "1234567" }, + /* 2*/ { BARCODE_MSI_PLESSEY, 0, -1, "1234567", "1234567" }, + /* 3*/ { BARCODE_MSI_PLESSEY, 0, BARCODE_PLAIN_HRT, "1234567", "1234567" }, + /* 4*/ { BARCODE_MSI_PLESSEY, 1, -1, "1234567", "12345674" }, + /* 5*/ { BARCODE_MSI_PLESSEY, 1, BARCODE_PLAIN_HRT, "1234567", "12345674" }, + /* 6*/ { BARCODE_MSI_PLESSEY, 1 + 10, -1, "1234567", "1234567" }, + /* 7*/ { BARCODE_MSI_PLESSEY, 1 + 10, BARCODE_PLAIN_HRT, "1234567", "12345674" }, + /* 8*/ { BARCODE_MSI_PLESSEY, 1, -1, "9999999999", "99999999990" }, + /* 9*/ { BARCODE_MSI_PLESSEY, 1, BARCODE_PLAIN_HRT, "9999999999", "99999999990" }, + /* 10*/ { BARCODE_MSI_PLESSEY, 2, -1, "1234567", "123456741" }, + /* 11*/ { BARCODE_MSI_PLESSEY, 2, BARCODE_PLAIN_HRT, "1234567", "123456741" }, + /* 12*/ { BARCODE_MSI_PLESSEY, 2 + 10, -1, "1234567", "1234567" }, + /* 13*/ { BARCODE_MSI_PLESSEY, 2 + 10, BARCODE_PLAIN_HRT, "1234567", "123456741" }, + /* 14*/ { BARCODE_MSI_PLESSEY, 2, -1, "9999999999", "999999999900" }, + /* 15*/ { BARCODE_MSI_PLESSEY, 2, BARCODE_PLAIN_HRT, "9999999999", "999999999900" }, + /* 16*/ { BARCODE_MSI_PLESSEY, 3, -1, "1234567", "12345674" }, + /* 17*/ { BARCODE_MSI_PLESSEY, 3, BARCODE_PLAIN_HRT, "1234567", "12345674" }, + /* 18*/ { BARCODE_MSI_PLESSEY, 3 + 10, -1, "1234567", "1234567" }, + /* 19*/ { BARCODE_MSI_PLESSEY, 3 + 10, BARCODE_PLAIN_HRT, "1234567", "12345674" }, + /* 20*/ { BARCODE_MSI_PLESSEY, 3, -1, "9999999999", "99999999995" }, + /* 21*/ { BARCODE_MSI_PLESSEY, 3, BARCODE_PLAIN_HRT, "9999999999", "99999999995" }, + /* 22*/ { BARCODE_MSI_PLESSEY, 4, -1, "1234567", "123456741" }, + /* 23*/ { BARCODE_MSI_PLESSEY, 4, BARCODE_PLAIN_HRT, "1234567", "123456741" }, + /* 24*/ { BARCODE_MSI_PLESSEY, 4 + 10, -1, "1234567", "1234567" }, + /* 25*/ { BARCODE_MSI_PLESSEY, 4 + 10, BARCODE_PLAIN_HRT, "1234567", "123456741" }, + /* 26*/ { BARCODE_MSI_PLESSEY, 4, -1, "9999999999", "999999999959" }, + /* 27*/ { BARCODE_MSI_PLESSEY, 4, BARCODE_PLAIN_HRT, "9999999999", "999999999959" }, + /* 28*/ { BARCODE_MSI_PLESSEY, 5, -1, "1234567", "12345679" }, + /* 29*/ { BARCODE_MSI_PLESSEY, 5, BARCODE_PLAIN_HRT, "1234567", "12345679" }, + /* 30*/ { BARCODE_MSI_PLESSEY, 5 + 10, -1, "1234567", "1234567" }, + /* 31*/ { BARCODE_MSI_PLESSEY, 5 + 10, BARCODE_PLAIN_HRT, "1234567", "12345679" }, + /* 32*/ { BARCODE_MSI_PLESSEY, 5, -1, "9999999999", "999999999910" }, + /* 33*/ { BARCODE_MSI_PLESSEY, 5, BARCODE_PLAIN_HRT, "9999999999", "999999999910" }, + /* 34*/ { BARCODE_MSI_PLESSEY, 6, -1, "1234567", "123456790" }, + /* 35*/ { BARCODE_MSI_PLESSEY, 6, BARCODE_PLAIN_HRT, "1234567", "123456790" }, + /* 36*/ { BARCODE_MSI_PLESSEY, 6 + 10, -1, "1234567", "1234567" }, + /* 37*/ { BARCODE_MSI_PLESSEY, 6 + 10, BARCODE_PLAIN_HRT, "1234567", "123456790" }, + /* 38*/ { BARCODE_MSI_PLESSEY, 6, -1, "9999999999", "9999999999109" }, + /* 39*/ { BARCODE_MSI_PLESSEY, 6, BARCODE_PLAIN_HRT, "9999999999", "9999999999109" }, + /* 40*/ { BARCODE_MSI_PLESSEY, 1, -1, "123456", "1234566" }, + /* 41*/ { BARCODE_MSI_PLESSEY, 1, BARCODE_PLAIN_HRT, "123456", "1234566" }, + /* 42*/ { BARCODE_MSI_PLESSEY, 2, -1, "123456", "12345666" }, + /* 43*/ { BARCODE_MSI_PLESSEY, 2, BARCODE_PLAIN_HRT, "123456", "12345666" }, + /* 44*/ { BARCODE_MSI_PLESSEY, 3, -1, "123456", "1234560" }, + /* 45*/ { BARCODE_MSI_PLESSEY, 3, BARCODE_PLAIN_HRT, "123456", "1234560" }, + /* 46*/ { BARCODE_MSI_PLESSEY, 4, -1, "123456", "12345609" }, + /* 47*/ { BARCODE_MSI_PLESSEY, 4, BARCODE_PLAIN_HRT, "123456", "12345609" }, + /* 48*/ { BARCODE_MSI_PLESSEY, 3, -1, "2211", "221110" }, /* Mod-11 check digit '10' */ + /* 49*/ { BARCODE_MSI_PLESSEY, 3, BARCODE_PLAIN_HRT, "2211", "221110" }, + /* 50*/ { BARCODE_MSI_PLESSEY, 3 + 10, -1, "2211", "2211" }, /* Mod-11 check digit '10' */ + /* 51*/ { BARCODE_MSI_PLESSEY, 3 + 10, BARCODE_PLAIN_HRT, "2211", "221110" }, + /* 52*/ { BARCODE_MSI_PLESSEY, 4, -1, "2211", "2211100" }, + /* 53*/ { BARCODE_MSI_PLESSEY, 4, BARCODE_PLAIN_HRT, "2211", "2211100" }, + /* 54*/ { BARCODE_MSI_PLESSEY, 4 + 10, -1, "2211", "2211" }, + /* 55*/ { BARCODE_MSI_PLESSEY, 4 + 10, BARCODE_PLAIN_HRT, "2211", "2211100" }, + /* 56*/ { BARCODE_PLESSEY, -1, -1, "0123456789ABCDEF", "0123456789ABCDEF" }, + /* 57*/ { BARCODE_PLESSEY, -1, BARCODE_PLAIN_HRT, "0123456789ABCDEF", "0123456789ABCDEF90" }, + /* 58*/ { BARCODE_PLESSEY, 1, -1, "0123456789ABCDEF", "0123456789ABCDEF90" }, + /* 59*/ { BARCODE_PLESSEY, 1, BARCODE_PLAIN_HRT, "0123456789ABCDEF", "0123456789ABCDEF90" }, + /* 60*/ { BARCODE_PLESSEY, -1, -1, "1", "1" }, + /* 61*/ { BARCODE_PLESSEY, -1, BARCODE_PLAIN_HRT, "1", "173" }, + /* 62*/ { BARCODE_PLESSEY, 1, -1, "1", "173" }, + /* 63*/ { BARCODE_PLESSEY, 1, BARCODE_PLAIN_HRT, "1", "173" }, + /* 64*/ { BARCODE_PLESSEY, -1, -1, "7", "7" }, + /* 65*/ { BARCODE_PLESSEY, -1, BARCODE_PLAIN_HRT, "7", "758" }, + /* 66*/ { BARCODE_PLESSEY, 1, -1, "7", "758" }, + /* 67*/ { BARCODE_PLESSEY, 1, BARCODE_PLAIN_HRT, "7", "758" }, + /* 68*/ { BARCODE_PLESSEY, -1, -1, "75", "75" }, + /* 69*/ { BARCODE_PLESSEY, -1, BARCODE_PLAIN_HRT, "75", "7580" }, + /* 70*/ { BARCODE_PLESSEY, 1, -1, "75", "7580" }, + /* 71*/ { BARCODE_PLESSEY, 1, BARCODE_PLAIN_HRT, "75", "7580" }, + /* 72*/ { BARCODE_PLESSEY, -1, -1, "993", "993" }, + /* 73*/ { BARCODE_PLESSEY, -1, BARCODE_PLAIN_HRT, "993", "993AA" }, + /* 74*/ { BARCODE_PLESSEY, 1, -1, "993", "993AA" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -158,12 +206,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_postal.c b/backend/tests/test_postal.c index 571779a7..b7579566 100644 --- a/backend/tests/test_postal.c +++ b/backend/tests/test_postal.c @@ -214,6 +214,74 @@ static void test_japanpost(const testCtx *const p_ctx) { testFinish(); } +static void test_hrt(const testCtx *const p_ctx) { + int debug = p_ctx->debug; + + struct item { + int symbology; + int option_2; + int output_options; + const char *data; + + const char *expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + static const struct item data[] = { + /* 0*/ { BARCODE_FLAT, -1, -1, "12345", "" }, /* None */ + /* 1*/ { BARCODE_FLAT, -1, BARCODE_PLAIN_HRT, "12345", "12345" }, + /* 2*/ { BARCODE_POSTNET, -1, -1, "12345", "" }, /* None */ + /* 3*/ { BARCODE_POSTNET, -1, BARCODE_PLAIN_HRT, "12345", "123455" }, + /* 4*/ { BARCODE_FIM, -1, -1, "e", "" }, /* None */ + /* 5*/ { BARCODE_FIM, -1, BARCODE_PLAIN_HRT, "e", "E" }, + /* 6*/ { BARCODE_CEPNET, -1, -1, "12345678", "" }, /* None */ + /* 7*/ { BARCODE_CEPNET, -1, BARCODE_PLAIN_HRT, "12345678", "123456784" }, + /* 8*/ { BARCODE_RM4SCC, -1, -1, "BX11LT1A", "" }, /* None*/ + /* 9*/ { BARCODE_RM4SCC, -1, BARCODE_PLAIN_HRT, "BX11LT1A", "BX11LT1AI" }, + /* 10*/ { BARCODE_JAPANPOST, -1, -1, "1234", "" }, /* None*/ + /* 11*/ { BARCODE_JAPANPOST, -1, BARCODE_PLAIN_HRT, "1234", "1234" }, /* Note check char not included */ + /* 12*/ { BARCODE_JAPANPOST, -1, BARCODE_PLAIN_HRT, "123456-AB", "123456-AB" }, /* Ditto */ + /* 13*/ { BARCODE_KOREAPOST, -1, -1, "123456", "1234569" }, + /* 14*/ { BARCODE_KOREAPOST, -1, BARCODE_PLAIN_HRT, "123456", "1234569" }, /* No difference */ + /* 15*/ { BARCODE_PLANET, -1, -1, "12345678901", "" }, /* None */ + /* 16*/ { BARCODE_PLANET, -1, BARCODE_PLAIN_HRT, "12345678901", "123456789014" }, + /* 17*/ { BARCODE_KIX, -1, -1, "0123456789ABCDEFGH", "" }, /* None */ + /* 18*/ { BARCODE_KIX, -1, BARCODE_PLAIN_HRT, "0123456789ABCDEFGH", "0123456789ABCDEFGH" }, + /* 19*/ { BARCODE_DAFT, -1, -1, "DAFT", "" }, /* None */ + /* 20*/ { BARCODE_DAFT, -1, BARCODE_PLAIN_HRT, "DAFT", "DAFT" }, + }; + const int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol = NULL; + int expected_length; + + testStartSymbol("test_hrt", &symbol); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); + + ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); + assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); + + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_input(const testCtx *const p_ctx) { int debug = p_ctx->debug; @@ -641,6 +709,7 @@ int main(int argc, char *argv[]) { { "test_large", test_large }, { "test_koreapost", test_koreapost }, { "test_japanpost", test_japanpost }, + { "test_hrt", test_hrt }, { "test_input", test_input }, { "test_encode", test_encode }, { "test_perf", test_perf }, diff --git a/backend/tests/test_rss.c b/backend/tests/test_rss.c index 4b3acaa8..dda5a344 100644 --- a/backend/tests/test_rss.c +++ b/backend/tests/test_rss.c @@ -1301,7 +1301,7 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; - int input_mode; + int output_options; const char *data; int ret; @@ -1310,18 +1310,28 @@ static void test_hrt(const testCtx *const p_ctx) { /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { /* 0*/ { BARCODE_DBAR_OMN, -1, "1234567890123", 0, "(01)12345678901231" }, - /* 1*/ { BARCODE_DBAR_OMN, -1, "12345678901231", 0, "(01)12345678901231" }, + /* 1*/ { BARCODE_DBAR_OMN, BARCODE_PLAIN_HRT, "1234567890123", 0, "0112345678901231" }, + /* 2*/ { BARCODE_DBAR_OMN, -1, "12345678901231", 0, "(01)12345678901231" }, + /* 3*/ { BARCODE_DBAR_OMN, BARCODE_PLAIN_HRT, "12345678901231", 0, "0112345678901231" }, /* 4*/ { BARCODE_DBAR_OMN, -1, "1000000000009", 0, "(01)10000000000090" }, - /* 5*/ { BARCODE_DBAR_LTD, -1, "1341056790138", 0, "(01)13410567901384" }, - /* 6*/ { BARCODE_DBAR_LTD, -1, "13410567901384", 0, "(01)13410567901384" }, - /* 9*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231", 0, "(01)12345678901231" }, /* See test_hrt() in "test_gs1.c" for full HRT tests */ - /* 10*/ { BARCODE_DBAR_STK, -1, "12345678901231", 0, "" }, /* No HRT for stacked */ - /* 11*/ { BARCODE_DBAR_OMNSTK, -1, "10000000000090", 0, "" }, - /* 12*/ { BARCODE_DBAR_EXPSTK, -1, "[01]12345678901231", 0, "" }, + /* 5*/ { BARCODE_DBAR_OMN, BARCODE_PLAIN_HRT, "1000000000009", 0, "0110000000000090" }, + /* 6*/ { BARCODE_DBAR_LTD, -1, "1341056790138", 0, "(01)13410567901384" }, + /* 7*/ { BARCODE_DBAR_LTD, BARCODE_PLAIN_HRT, "1341056790138", 0, "0113410567901384" }, + /* 8*/ { BARCODE_DBAR_LTD, -1, "13410567901384", 0, "(01)13410567901384" }, + /* 9*/ { BARCODE_DBAR_LTD, BARCODE_PLAIN_HRT, "13410567901384", 0, "0113410567901384" }, + /* 10*/ { BARCODE_DBAR_EXP, -1, "[01]12345678901231", 0, "(01)12345678901231" }, /* See test_hrt() in "test_gs1.c" for full HRT tests */ + /* 11*/ { BARCODE_DBAR_EXP, BARCODE_PLAIN_HRT, "[01]12345678901231", 0, "0112345678901231" }, + /* 12*/ { BARCODE_DBAR_STK, -1, "12345678901231", 0, "" }, /* No HRT for stacked */ + /* 13*/ { BARCODE_DBAR_STK, BARCODE_PLAIN_HRT, "12345678901231", 0, "" }, + /* 14*/ { BARCODE_DBAR_OMNSTK, -1, "10000000000090", 0, "" }, + /* 15*/ { BARCODE_DBAR_OMNSTK, BARCODE_PLAIN_HRT, "10000000000090", 0, "" }, + /* 16*/ { BARCODE_DBAR_EXPSTK, -1, "[01]12345678901231", 0, "" }, + /* 17*/ { BARCODE_DBAR_EXPSTK, BARCODE_PLAIN_HRT, "[01]12345678901231", 0, "" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -1332,12 +1342,18 @@ static void test_hrt(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, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); 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, data[i].ret, ret, symbol->errtxt); - assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_telepen.c b/backend/tests/test_telepen.c index e31c59b7..80d28a77 100644 --- a/backend/tests/test_telepen.c +++ b/backend/tests/test_telepen.c @@ -91,25 +91,38 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; + int output_options; const char *data; int length; const char *expected; + int expected_length; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_TELEPEN, "ABC1234.;$", -1, "ABC1234.;$" }, - /* 1*/ { BARCODE_TELEPEN, "abc1234.;$", -1, "abc1234.;$" }, - /* 2*/ { BARCODE_TELEPEN, "ABC1234\001", -1, "ABC1234\001" }, - /* 3*/ { BARCODE_TELEPEN, "ABC\0001234", 8, "ABC 1234" }, - /* 4*/ { BARCODE_TELEPEN_NUM, "1234", -1, "1234" }, - /* 5*/ { BARCODE_TELEPEN_NUM, "123X", -1, "123X" }, - /* 6*/ { BARCODE_TELEPEN_NUM, "123x", -1, "123X" }, /* Converts to upper */ - /* 7*/ { BARCODE_TELEPEN_NUM, "12345", -1, "012345" }, /* Adds leading zero if odd */ + /* 0*/ { BARCODE_TELEPEN, -1, "ABC1234.;$", -1, "ABC1234.;$", -1 }, + /* 1*/ { BARCODE_TELEPEN, BARCODE_PLAIN_HRT, "ABC1234.;$", -1, "ABC1234.;$^", -1 }, + /* 2*/ { BARCODE_TELEPEN, -1, "abc1234.;$", -1, "abc1234.;$", -1 }, + /* 3*/ { BARCODE_TELEPEN, BARCODE_PLAIN_HRT, "abc1234.;$", -1, "abc1234.;$}", -1 }, + /* 4*/ { BARCODE_TELEPEN, -1, "ABC1234\001", -1, "ABC1234 ", -1 }, /* Note used to put control chars (apart from NUL) in HRT */ + /* 5*/ { BARCODE_TELEPEN, BARCODE_PLAIN_HRT, "ABC1234\001", -1, "ABC1234\001k", -1 }, + /* 6*/ { BARCODE_TELEPEN, -1, "ABC\0001234", 8, "ABC 1234", -1 }, + /* 7*/ { BARCODE_TELEPEN, BARCODE_PLAIN_HRT, "ABC\0001234", 8, "ABC\0001234l", 9 }, + /* 8*/ { BARCODE_TELEPEN, -1, "ABK0", -1, "ABK0", -1 }, + /* 9*/ { BARCODE_TELEPEN, BARCODE_PLAIN_HRT, "ABK0", -1, "ABK0\000", 5 }, + /* 10*/ { BARCODE_TELEPEN_NUM, -1, "1234", -1, "1234", -1 }, + /* 11*/ { BARCODE_TELEPEN_NUM, BARCODE_PLAIN_HRT, "1234", -1, "1234\033", -1 }, + /* 12*/ { BARCODE_TELEPEN_NUM, -1, "123X", -1, "123X", -1 }, + /* 13*/ { BARCODE_TELEPEN_NUM, BARCODE_PLAIN_HRT, "123X", -1, "123XD", -1 }, + /* 14*/ { BARCODE_TELEPEN_NUM, -1, "123x", -1, "123X", -1 }, /* Converts to upper */ + /* 15*/ { BARCODE_TELEPEN_NUM, BARCODE_PLAIN_HRT, "123x", -1, "123XD", -1 }, + /* 16*/ { BARCODE_TELEPEN_NUM, -1, "12345", -1, "012345", -1 }, /* Adds leading zero if odd */ + /* 17*/ { BARCODE_TELEPEN_NUM, BARCODE_PLAIN_HRT, "12345", -1, "012345h", -1 }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -120,12 +133,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, data[i].length, debug); + expected_length = data[i].expected_length == -1 ? (int) strlen(data[i].expected) : data[i].expected_length; ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt); - assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(memcmp(symbol->text, data[i].expected, expected_length), "i:%d memcmp(%s, %s, %d) != 0\n", + i, symbol->text, data[i].expected, expected_length); ZBarcode_Delete(symbol); } diff --git a/backend/tests/test_upcean.c b/backend/tests/test_upcean.c index 311a849b..a67b1218 100644 --- a/backend/tests/test_upcean.c +++ b/backend/tests/test_upcean.c @@ -650,73 +650,110 @@ static void test_hrt(const testCtx *const p_ctx) { struct item { int symbology; + int output_options; const char *data; int ret; const char *expected; }; /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ static const struct item data[] = { - /* 0*/ { BARCODE_EANX, "12345678901", 0, "0123456789012" }, - /* 1*/ { BARCODE_EANX, "123456789012", 0, "1234567890128" }, - /* 2*/ { BARCODE_EANX, "1234567890128", 0, "1234567890128" }, /* EANX accepts CHK (treated as such if no leading zeroes required) */ - /* 3*/ { BARCODE_EANX_CHK, "1234567890128", 0, "1234567890128" }, - /* 4*/ { BARCODE_EANX_CHK, "123456789012", 0, "0123456789012" }, /* '2' happens to be correct check digit for "012345678901" */ - /* 5*/ { BARCODE_EANX, "1234567890128+1", 0, "1234567890128+01" }, - /* 6*/ { BARCODE_EANX_CHK, "1234567890128+1", 0, "1234567890128+01" }, - /* 7*/ { BARCODE_EANX, "12345678", 0, "0000123456784" }, - /* 8*/ { BARCODE_EANX, "1234567", 0, "12345670" }, /* EAN-8 */ - /* 9*/ { BARCODE_EANX_CHK, "12345670", 0, "12345670" }, /* EAN-8 */ - /* 10*/ { BARCODE_EANX, "123456", 0, "01234565" }, /* EAN-8 */ - /* 11*/ { BARCODE_EANX_CHK, "123457", 0, "00123457" }, /* EAN-8 */ - /* 12*/ { BARCODE_EANX, "12345", 0, "12345" }, /* EAN-5 */ - /* 13*/ { BARCODE_EANX, "123", 0, "00123" }, /* EAN-5 */ - /* 14*/ { BARCODE_EANX, "12", 0, "12" }, /* EAN-2 */ - /* 15*/ { BARCODE_EANX, "1", 0, "01" }, /* EAN-2 */ - /* 16*/ { BARCODE_EANX, "0", 0, "00" }, /* EAN-2 */ - /* 17*/ { BARCODE_ISBNX, "0", 0, "9780000000002" }, - /* 18*/ { BARCODE_ISBNX, "123456789X", 0, "9781234567897" }, - /* 19*/ { BARCODE_ISBNX, "9781234567897", 0, "9781234567897" }, - /* 20*/ { BARCODE_ISBNX, "9791234567896+12", 0, "9791234567896+12" }, - /* 21*/ { BARCODE_UPCA, "12345678901", 0, "123456789012" }, - /* 22*/ { BARCODE_UPCA, "123456789012", 0, "123456789012" }, - /* 23*/ { BARCODE_UPCA_CHK, "123456789012", 0, "123456789012" }, - /* 24*/ { BARCODE_UPCA, "12345678905+1", 0, "123456789050+01" }, - /* 25*/ { BARCODE_UPCA_CHK, "123456789050+1", 0, "123456789050+01" }, - /* 26*/ { BARCODE_UPCA, "123456789050+123", 0, "123456789050+00123" }, - /* 27*/ { BARCODE_UPCA_CHK, "123456789050+123", 0, "123456789050+00123" }, - /* 28*/ { BARCODE_UPCE, "12345", 0, "00123457" }, /* equivalent: 00123400005, hrt: 00123457, Check digit: 7 */ - /* 29*/ { BARCODE_UPCE_CHK, "12344", 0, "00012344" }, /* equivalent: 00012000003, hrt: 00012344, Check digit: 4 */ - /* 30*/ { BARCODE_UPCE, "123456", 0, "01234565" }, /* equivalent: 01234500006, hrt: 01234565, Check digit: 5 */ - /* 31*/ { BARCODE_UPCE_CHK, "123457", 0, "00123457" }, /* equivalent: 00123400005, hrt: 00123457, Check digit: 7 */ - /* 32*/ { BARCODE_UPCE, "1234567", 0, "12345670" }, /* equivalent: 12345600007, hrt: 12345670, Check digit: 0 */ - /* 33*/ { BARCODE_UPCE_CHK, "1234565", 0, "01234565" }, /* equivalent: 01234500006, hrt: 01234565, Check digit: 5 */ - /* 34*/ { BARCODE_UPCE_CHK, "12345670", 0, "12345670" }, /* equivalent: 12345600007, hrt: 12345670, Check digit: 0 */ - /* 35*/ { BARCODE_UPCE, "2345678", 0, "03456781" }, /* 2 ignored, equivalent: 03456700008, hrt: 03456781, Check digit: 1 */ - /* 36*/ { BARCODE_UPCE_CHK, "23456781", 0, "03456781" }, /* 2 ignored, equivalent: 03456700008, hrt: 03456781, Check digit: 1 */ - /* 37*/ { BARCODE_UPCE, "123455", 0, "01234558" }, /* equivalent: 01234500005, hrt: 01234558, Check digit: 8 (BS 797 Rule 3 (a)) */ - /* 38*/ { BARCODE_UPCE_CHK, "1234558", 0, "01234558" }, /* equivalent: 01234500005, hrt: 01234558, Check digit: 8 (BS 797 Rule 3 (a)) */ - /* 39*/ { BARCODE_UPCE, "456784", 0, "04567840" }, /* equivalent: 04567000008, hrt: 04567840, Check digit: 0 (BS 797 Rule 3 (b)) */ - /* 40*/ { BARCODE_UPCE_CHK, "4567840", 0, "04567840" }, /* equivalent: 04567000008, hrt: 04567840, Check digit: 0 (BS 797 Rule 3 (b)) */ - /* 41*/ { BARCODE_UPCE, "345670", 0, "03456703" }, /* equivalent: 03400000567, hrt: 03456703, Check digit: 3 (BS 797 Rule 3 (c)) */ - /* 42*/ { BARCODE_UPCE_CHK, "3456703", 0, "03456703" }, /* equivalent: 03400000567, hrt: 03456703, Check digit: 3 (BS 797 Rule 3 (c)) */ - /* 43*/ { BARCODE_UPCE, "984753", 0, "09847531" }, /* equivalent: 09840000075, hrt: 09847531, Check digit: 1 (BS 797 Rule 3 (d)) */ - /* 44*/ { BARCODE_UPCE_CHK, "9847531", 0, "09847531" }, /* equivalent: 09840000075, hrt: 09847531, Check digit: 1 (BS 797 Rule 3 (d)) */ - /* 45*/ { BARCODE_UPCE, "123453", 0, "01234531" }, - /* 46*/ { BARCODE_UPCE, "000000", 0, "00000000" }, - /* 47*/ { BARCODE_UPCE, "0000000", 0, "00000000" }, - /* 48*/ { BARCODE_UPCE, "1000000", 0, "10000007" }, - /* 49*/ { BARCODE_UPCE, "2000000", 0, "00000000" }, /* First char 2-9 ignored, replaced with 0 */ - /* 50*/ { BARCODE_UPCE, "3000000", 0, "00000000" }, - /* 51*/ { BARCODE_UPCE, "8000000", 0, "00000000" }, - /* 52*/ { BARCODE_UPCE, "9000000", 0, "00000000" }, - /* 53*/ { BARCODE_UPCE, "1234567+1", 0, "12345670+01" }, - /* 54*/ { BARCODE_UPCE, "12345670+1", 0, "12345670+01" }, - /* 55*/ { BARCODE_UPCE_CHK, "12345670+1", 0, "12345670+01" }, - /* 56*/ { BARCODE_UPCE_CHK, "1234565+1", 0, "01234565+01" }, + /* 0*/ { BARCODE_EANX, -1, "12345678901", 0, "0123456789012" }, + /* 1*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "12345678901", 0, "0123456789012" }, + /* 2*/ { BARCODE_EANX, -1, "123456789012", 0, "1234567890128" }, + /* 3*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "123456789012", 0, "1234567890128" }, + /* 4*/ { BARCODE_EANX, -1, "1234567890128", 0, "1234567890128" }, /* EANX accepts CHK (treated as such if no leading zeroes required) */ + /* 5*/ { BARCODE_EANX_CHK, -1, "1234567890128", 0, "1234567890128" }, + /* 6*/ { BARCODE_EANX_CHK, BARCODE_PLAIN_HRT, "1234567890128", 0, "1234567890128" }, + /* 7*/ { BARCODE_EANX_CHK, -1, "123456789012", 0, "0123456789012" }, /* '2' happens to be correct check digit for "012345678901" */ + /* 8*/ { BARCODE_EANX, -1, "1234567890128+1", 0, "1234567890128+01" }, + /* 9*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "1234567890128+1", 0, "123456789012801" }, + /* 10*/ { BARCODE_EANX_CHK, -1, "1234567890128+1", 0, "1234567890128+01" }, + /* 11*/ { BARCODE_EANX_CHK, BARCODE_PLAIN_HRT, "1234567890128+1", 0, "123456789012801" }, + /* 12*/ { BARCODE_EANX, -1, "12345678", 0, "0000123456784" }, + /* 13*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "12345678", 0, "0000123456784" }, + /* 14*/ { BARCODE_EANX, -1, "1234567", 0, "12345670" }, /* EAN-8 */ + /* 15*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "1234567", 0, "12345670" }, + /* 16*/ { BARCODE_EANX_CHK, -1, "12345670", 0, "12345670" }, /* EAN-8 */ + /* 17*/ { BARCODE_EANX_CHK, BARCODE_PLAIN_HRT, "12345670", 0, "12345670" }, + /* 18*/ { BARCODE_EANX, -1, "123456", 0, "01234565" }, /* EAN-8 */ + /* 19*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "123456", 0, "01234565" }, + /* 20*/ { BARCODE_EANX_CHK, -1, "123457", 0, "00123457" }, /* EAN-8 */ + /* 21*/ { BARCODE_EANX, -1, "12345", 0, "12345" }, /* EAN-5 */ + /* 22*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "12345", 0, "12345" }, + /* 23*/ { BARCODE_EANX, -1, "123", 0, "00123" }, /* EAN-5 */ + /* 24*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "123", 0, "00123" }, + /* 25*/ { BARCODE_EANX, -1, "12", 0, "12" }, /* EAN-2 */ + /* 26*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "12", 0, "12" }, + /* 27*/ { BARCODE_EANX, -1, "1", 0, "01" }, /* EAN-2 */ + /* 28*/ { BARCODE_EANX, BARCODE_PLAIN_HRT, "1", 0, "01" }, + /* 29*/ { BARCODE_EANX, -1, "0", 0, "00" }, /* EAN-2 */ + /* 30*/ { BARCODE_ISBNX, -1, "0", 0, "9780000000002" }, + /* 31*/ { BARCODE_ISBNX, BARCODE_PLAIN_HRT, "0", 0, "9780000000002" }, + /* 32*/ { BARCODE_ISBNX, -1, "123456789X", 0, "9781234567897" }, + /* 33*/ { BARCODE_ISBNX, BARCODE_PLAIN_HRT, "123456789X", 0, "9781234567897" }, + /* 34*/ { BARCODE_ISBNX, -1, "9781234567897", 0, "9781234567897" }, + /* 35*/ { BARCODE_ISBNX, BARCODE_PLAIN_HRT, "9781234567897", 0, "9781234567897" }, + /* 36*/ { BARCODE_ISBNX, -1, "9791234567896+12", 0, "9791234567896+12" }, + /* 37*/ { BARCODE_ISBNX, BARCODE_PLAIN_HRT, "9791234567896+12", 0, "979123456789612" }, + /* 38*/ { BARCODE_UPCA, -1, "12345678901", 0, "123456789012" }, + /* 39*/ { BARCODE_UPCA, BARCODE_PLAIN_HRT, "12345678901", 0, "123456789012" }, + /* 40*/ { BARCODE_UPCA, -1, "123456789012", 0, "123456789012" }, + /* 41*/ { BARCODE_UPCA, BARCODE_PLAIN_HRT, "123456789012", 0, "123456789012" }, + /* 42*/ { BARCODE_UPCA_CHK, -1, "123456789012", 0, "123456789012" }, + /* 43*/ { BARCODE_UPCA_CHK, BARCODE_PLAIN_HRT, "123456789012", 0, "123456789012" }, + /* 44*/ { BARCODE_UPCA, -1, "12345678905+1", 0, "123456789050+01" }, + /* 45*/ { BARCODE_UPCA, BARCODE_PLAIN_HRT, "12345678905+1", 0, "12345678905001" }, + /* 46*/ { BARCODE_UPCA_CHK, -1, "123456789050+1", 0, "123456789050+01" }, + /* 47*/ { BARCODE_UPCA_CHK, BARCODE_PLAIN_HRT, "123456789050+1", 0, "12345678905001" }, + /* 48*/ { BARCODE_UPCA, -1, "123456789050+123", 0, "123456789050+00123" }, + /* 49*/ { BARCODE_UPCA, BARCODE_PLAIN_HRT, "123456789050+123", 0, "12345678905000123" }, + /* 50*/ { BARCODE_UPCA_CHK, -1, "123456789050+123", 0, "123456789050+00123" }, + /* 51*/ { BARCODE_UPCE, -1, "12345", 0, "00123457" }, /* equivalent: 00123400005, hrt: 00123457, Check digit: 7 */ + /* 52*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "12345", 0, "00123457" }, + /* 53*/ { BARCODE_UPCE_CHK, -1, "12344", 0, "00012344" }, /* equivalent: 00012000003, hrt: 00012344, Check digit: 4 */ + /* 54*/ { BARCODE_UPCE_CHK, BARCODE_PLAIN_HRT, "12344", 0, "00012344" }, + /* 55*/ { BARCODE_UPCE, -1, "123456", 0, "01234565" }, /* equivalent: 01234500006, hrt: 01234565, Check digit: 5 */ + /* 56*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "123456", 0, "01234565" }, + /* 57*/ { BARCODE_UPCE_CHK, -1, "123457", 0, "00123457" }, /* equivalent: 00123400005, hrt: 00123457, Check digit: 7 */ + /* 58*/ { BARCODE_UPCE_CHK, BARCODE_PLAIN_HRT, "123457", 0, "00123457" }, + /* 59*/ { BARCODE_UPCE, -1, "1234567", 0, "12345670" }, /* equivalent: 12345600007, hrt: 12345670, Check digit: 0 */ + /* 60*/ { BARCODE_UPCE_CHK, -1, "1234565", 0, "01234565" }, /* equivalent: 01234500006, hrt: 01234565, Check digit: 5 */ + /* 61*/ { BARCODE_UPCE_CHK, -1, "12345670", 0, "12345670" }, /* equivalent: 12345600007, hrt: 12345670, Check digit: 0 */ + /* 62*/ { BARCODE_UPCE, -1, "2345678", 0, "03456781" }, /* 2 ignored, equivalent: 03456700008, hrt: 03456781, Check digit: 1 */ + /* 63*/ { BARCODE_UPCE_CHK, -1, "23456781", 0, "03456781" }, /* 2 ignored, equivalent: 03456700008, hrt: 03456781, Check digit: 1 */ + /* 64*/ { BARCODE_UPCE, -1, "123455", 0, "01234558" }, /* equivalent: 01234500005, hrt: 01234558, Check digit: 8 (BS 797 Rule 3 (a)) */ + /* 65*/ { BARCODE_UPCE_CHK, -1, "1234558", 0, "01234558" }, /* equivalent: 01234500005, hrt: 01234558, Check digit: 8 (BS 797 Rule 3 (a)) */ + /* 66*/ { BARCODE_UPCE, -1, "456784", 0, "04567840" }, /* equivalent: 04567000008, hrt: 04567840, Check digit: 0 (BS 797 Rule 3 (b)) */ + /* 67*/ { BARCODE_UPCE_CHK, -1, "4567840", 0, "04567840" }, /* equivalent: 04567000008, hrt: 04567840, Check digit: 0 (BS 797 Rule 3 (b)) */ + /* 68*/ { BARCODE_UPCE, -1, "345670", 0, "03456703" }, /* equivalent: 03400000567, hrt: 03456703, Check digit: 3 (BS 797 Rule 3 (c)) */ + /* 69*/ { BARCODE_UPCE_CHK, -1, "3456703", 0, "03456703" }, /* equivalent: 03400000567, hrt: 03456703, Check digit: 3 (BS 797 Rule 3 (c)) */ + /* 70*/ { BARCODE_UPCE, -1, "984753", 0, "09847531" }, /* equivalent: 09840000075, hrt: 09847531, Check digit: 1 (BS 797 Rule 3 (d)) */ + /* 71*/ { BARCODE_UPCE_CHK, -1, "9847531", 0, "09847531" }, /* equivalent: 09840000075, hrt: 09847531, Check digit: 1 (BS 797 Rule 3 (d)) */ + /* 72*/ { BARCODE_UPCE, -1, "123453", 0, "01234531" }, + /* 73*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "123453", 0, "01234531" }, + /* 74*/ { BARCODE_UPCE, -1, "000000", 0, "00000000" }, + /* 75*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "000000", 0, "00000000" }, + /* 76*/ { BARCODE_UPCE, -1, "0000000", 0, "00000000" }, + /* 77*/ { BARCODE_UPCE, -1, "1000000", 0, "10000007" }, + /* 78*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "1000000", 0, "10000007" }, + /* 79*/ { BARCODE_UPCE, -1, "2000000", 0, "00000000" }, /* First char 2-9 ignored, replaced with 0 */ + /* 80*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "2000000", 0, "00000000" }, + /* 81*/ { BARCODE_UPCE, -1, "3000000", 0, "00000000" }, + /* 82*/ { BARCODE_UPCE, -1, "8000000", 0, "00000000" }, + /* 83*/ { BARCODE_UPCE, -1, "9000000", 0, "00000000" }, + /* 84*/ { BARCODE_UPCE, -1, "1234567+1", 0, "12345670+01" }, + /* 85*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "1234567+1", 0, "1234567001" }, + /* 86*/ { BARCODE_UPCE, -1, "12345670+1", 0, "12345670+01" }, + /* 87*/ { BARCODE_UPCE, BARCODE_PLAIN_HRT, "12345670+1", 0, "1234567001" }, + /* 88*/ { BARCODE_UPCE_CHK, -1, "12345670+1", 0, "12345670+01" }, + /* 89*/ { BARCODE_UPCE_CHK, BARCODE_PLAIN_HRT, "12345670+1", 0, "1234567001" }, + /* 90*/ { BARCODE_UPCE_CHK, -1, "1234565+1", 0, "01234565+01" }, + /* 91*/ { BARCODE_UPCE_CHK, BARCODE_PLAIN_HRT, "1234565+1", 0, "0123456501" }, }; const int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol = NULL; + int expected_length; testStartSymbol("test_hrt", &symbol); @@ -727,12 +764,18 @@ static void test_hrt(const testCtx *const p_ctx) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, + -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options, + data[i].data, -1, debug); + expected_length = (int) strlen(data[i].expected); ret = ZBarcode_Encode(symbol, TCU(data[i].data), length); assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); - assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected); + assert_equal(symbol->text_length, expected_length, "i:%d text_length %d != expected_length %d\n", + i, symbol->text_length, expected_length); + assert_zero(strcmp((const char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", + i, symbol->text, data[i].expected); ZBarcode_Delete(symbol); } diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 5195c242..ade4562c 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -52,6 +52,8 @@ #include "../eci.h" #include "../output.h" +#define ustrcpy(target, source) strcpy((char *) (target), (const char *) (source)) + static int testTests = 0; static int testFailed = 0; static int testSkipped = 0; @@ -124,7 +126,7 @@ void assert_notequal(int e1, int e2, const char *fmt, ...) { #ifdef _WIN32 #define utf8_to_wide(u, w) \ { \ - int lenW; /* Includes NUL terminator */ \ + int lenW; /* Includes terminating NUL */ \ if ((lenW = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, NULL, 0)) == 0) return 0; \ w = (wchar_t *) z_alloca(sizeof(wchar_t) * lenW); \ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, u, -1, w, lenW) == 0) return 0; \ @@ -681,6 +683,8 @@ const char *testUtilOutputOptionsName(int output_options) { { "COMPLIANT_HEIGHT", COMPLIANT_HEIGHT, 0x2000 }, { "EANUPC_GUARD_WHITESPACE", EANUPC_GUARD_WHITESPACE, 0x4000 }, { "EMBED_VECTOR_FONT", EMBED_VECTOR_FONT, 0x8000 }, + { "BARCODE_MEMORY_FILE", BARCODE_MEMORY_FILE, 0x10000 }, + { "BARCODE_PLAIN_HRT", BARCODE_PLAIN_HRT, 0x20000 }, }; static int const data_size = ARRAY_SIZE(data); int set = 0; @@ -4183,12 +4187,12 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in expected = escaped; } if (gs1 && symbology != BARCODE_EAN14 && symbology != BARCODE_NVE18) { - ret = gs1_verify(symbol, (const unsigned char *) expected, expected_len, (unsigned char *) reduced); + ret = gs1_verify(symbol, (const unsigned char *) expected, expected_len, (unsigned char *) reduced, + &expected_len); if (ret >= ZINT_ERROR) { sprintf(msg, "gs1_verify %d != 0", ret); return 4; } - expected_len = (int) strlen(reduced); expected = reduced; if (primary) { /* TODO: */ @@ -4450,7 +4454,7 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in /* Add hyphen at start */ pzn[0] = '-'; memcpy(pzn + 1, expected, expected_len); - if ((symbol->option_2 == 0 && expected_len != 8) || (symbol->option_2 == 1 && expected_len != 7)) { + if ((symbol->option_2 != 1 && expected_len != 8) || (symbol->option_2 == 1 && expected_len != 7)) { cmp_len--; /* Don't bother with check digit */ } expected = pzn; diff --git a/backend/upcean.c b/backend/upcean.c index 116b9944..216674c1 100644 --- a/backend/upcean.c +++ b/backend/upcean.c @@ -1,4 +1,4 @@ -/* upcean.c - Handles UPC, EAN and ISBN */ +/* upcean.c - Handles UPC, EAN and ISBN */ /* libzint - the open source barcode library Copyright (C) 2008-2025 Robin Stuart @@ -85,19 +85,18 @@ static const char EANsetB[10][4] = { }; /* UPC A is usually used for 12 digit numbers, but this function takes a source of any length */ -static void upca_draw(const unsigned char source[], const int length, char *d) { +static void upca_set_dest(const unsigned char source[], const int length, char *d) { int i, half_way; half_way = length / 2; - /* start character */ + /* Start character */ memcpy(d, "111", 3); d += 3; for (i = 0; i < length; i++, d += 4) { if (i == half_way) { - /* middle character - separates manufacturer no. from product no. */ - /* also inverts right hand characters */ + /* Middle character - separates manufacturer no. from product no. - also inverts right hand characters */ memcpy(d, "11111", 5); d += 5; } @@ -105,20 +104,19 @@ static void upca_draw(const unsigned char source[], const int length, char *d) { memcpy(d, EANsetA[source[i] - '0'], 4); } - /* stop character */ - strcpy(d, "111"); + /* Stop character */ + memcpy(d, "111", 4); /* Include terminating NUL */ } /* Make a UPC-A barcode, allowing for composite if `cc_rows` set */ static int upca_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[], int cc_rows) { - unsigned char *gtin = symbol->text; + const unsigned char *gtin = symbol->text; int error_number = 0; - ustrcpy(gtin, source); + hrt_cpy_nochk(symbol, source, length); if (length == 11) { - gtin[length++] = gs1_check_digit(gtin, 11); - gtin[length] = '\0'; + hrt_cat_chr_nochk(symbol, gs1_check_digit(gtin, 11)); } else { if (source[length - 1] != gs1_check_digit(gtin, 11)) { return ZEXT errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 270, "Invalid check digit '%1$c', expecting '%2$c'", @@ -126,11 +124,10 @@ static int upca_cc(struct zint_symbol *symbol, const unsigned char source[], int } } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("UPC-A: %s, gtin: %s, Check digit: %c\n", source, gtin, - length == 11 ? gtin[length] : gtin[length - 1]); + printf("UPC-A: %s, gtin: %s, Check digit: %c\n", source, gtin, gtin[symbol->text_length - 1]); } - upca_draw(gtin, length, dest); + upca_set_dest(gtin, symbol->text_length, dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24, @@ -165,7 +162,7 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt const char *parity; char src_check_digit = '\0'; unsigned char equivalent[12]; - unsigned char *hrt = symbol->text; + const unsigned char *hrt = symbol->text; int error_number = 0; if (length == 8 || symbol->symbology == BARCODE_UPCE_CHK) { @@ -174,22 +171,22 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt } /* Two number systems can be used - system 0 and system 1 */ - hrt[0] = '\0'; if (length == 7) { switch (source[0]) { case '0': num_system = 0; - ustrncat(hrt, source, length); + hrt_cpy_nochk(symbol, source, length); break; case '1': num_system = 1; - ustrncat(hrt, source, length); + hrt_cpy_nochk(symbol, source, length); break; default: num_system = 0; + /* Overwrite HRT first char with '0' to correct TODO: error/warn in future */ + hrt_cpy_chr(symbol, '0'); /* First source char ignored */ - ustrncat(hrt, source, length); - hrt[0] = '0'; /* Overwrite HRT first char with '0' to correct TODO: error/warn in future */ + hrt_cat_nochk(symbol, source + 1, length - 1); break; } for (i = 1; i <= length; i++) { @@ -199,22 +196,18 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt } else { /* Length 6, insert leading zero */ num_system = 0; - hrt[0] = '0'; - hrt[1] = '\0'; - ustrncat(hrt, source, length); + hrt_cpy_chr(symbol, '0'); + hrt_cat_nochk(symbol, source, length); } /* Expand the zero-compressed UPCE code to make a UPCA equivalent (EN Table 5) */ emode = source[5]; - for (i = 0; i < 11; i++) { - equivalent[i] = '0'; - } + memset(equivalent, '0', 11); if (num_system == 1) { equivalent[0] = hrt[0]; } equivalent[1] = source[0]; equivalent[2] = source[1]; - equivalent[11] = '\0'; switch (emode) { case '0': @@ -283,7 +276,7 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt /* Take all this information and make the barcode pattern */ - /* start character */ + /* Start character */ memcpy(d, "111", 3); d += 3; @@ -298,14 +291,13 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt } } - /* stop character */ - strcpy(d, "111111"); + /* Stop character */ + memcpy(d, "111111", 7); /* Include terminating NUL */ - hrt[7] = check_digit; - hrt[8] = '\0'; + hrt_cat_chr_nochk(symbol, check_digit); if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("UPC-E: %s, equivalent: %s, hrt: %s, Check digit: %c\n", source, equivalent, hrt, check_digit); + printf("UPC-E: %s, equivalent: %.11s, hrt: %.8s, Check digit: %c\n", source, equivalent, hrt, check_digit); } if (symbol->output_options & COMPLIANT_HEIGHT) { @@ -397,16 +389,15 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in int cc_rows) { int i, half_way; const char *parity; - unsigned char *gtin = symbol->text; + const unsigned char *gtin = symbol->text; int error_number = 0; - ustrcpy(gtin, source); + hrt_cpy_nochk(symbol, source, length); /* Add the appropriate check digit */ if (length == 12) { - gtin[length++] = gs1_check_digit(gtin, 12); - gtin[length] = '\0'; + hrt_cat_chr_nochk(symbol, gs1_check_digit(gtin, 12)); } else { if (source[length - 1] != gs1_check_digit(gtin, 12)) { return ZEXT errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 275, "Invalid check digit '%1$c', expecting '%2$c'", @@ -414,7 +405,7 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in } } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("EAN-13: %s, gtin: %s, Check digit: %c\n", source, gtin, gtin[length - 1]); + printf("EAN-13: %s, gtin: %s, Check digit: %c\n", source, gtin, gtin[symbol->text_length - 1]); } /* Get parity for first half of the symbol */ @@ -423,14 +414,13 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in /* Now get on with the cipher */ half_way = 7; - /* start character */ + /* Start character */ memcpy(d, "111", 3); d += 3; - for (i = 1; i < length; i++, d += 4) { + for (i = 1; i < symbol->text_length; i++, d += 4) { if (i == half_way) { - /* middle character - separates manufacturer no. from product no. */ - /* also inverses right hand characters */ + /* Middle character - separates manufacturer no. from product no. - also inverts right hand characters */ memcpy(d, "11111", 5); d += 5; } @@ -442,8 +432,8 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in } } - /* stop character */ - strcpy(d, "111"); + /* Stop character */ + memcpy(d, "111", 4); /* Include terminating NUL */ if (symbol->output_options & COMPLIANT_HEIGHT) { /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24, @@ -472,14 +462,13 @@ static int ean13(struct zint_symbol *symbol, const unsigned char source[], int l static int ean8_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[], int cc_rows) { /* EAN-8 is basically the same as UPC-A but with fewer digits */ - unsigned char *gtin = symbol->text; + const unsigned char *gtin = symbol->text; int error_number = 0; - ustrcpy(gtin, source); + hrt_cpy_nochk(symbol, source, length); if (length == 7) { - gtin[length++] = gs1_check_digit(gtin, 7); - gtin[length] = '\0'; + hrt_cat_chr_nochk(symbol, gs1_check_digit(gtin, 7)); } else { if (source[length - 1] != gs1_check_digit(gtin, 7)) { return ZEXT errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 276, "Invalid check digit '%1$c', expecting '%2$c'", @@ -491,7 +480,7 @@ static int ean8_cc(struct zint_symbol *symbol, const unsigned char source[], int length == 7 ? gtin[length] : gtin[length - 1]); } - upca_draw(gtin, length, dest); + upca_set_dest(gtin, symbol->text_length, dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* BS EN 797:1996 4.5.1 Nominal dimensions 18.23mm / 0.33mm (X) ~ 55.24, @@ -608,15 +597,14 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int l } /* Add leading zeroes to EAN and UPC strings */ -INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], +INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], const int length, unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part, unsigned char *zsecond_part) { unsigned char first_part[14], second_part[6]; int with_addon = 0; - int first_len = 0, second_len = 0, zfirst_len = 0, zsecond_len = 0, i, h; + int first_len = 0, second_len = 0, zfirst_len = 0, zsecond_len = 0, i; - h = (int) ustrlen(source); - for (i = 0; i < h; i++) { + for (i = 0; i < length; i++) { if (source[i] == '+') { with_addon = 1; } else { @@ -735,20 +723,20 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char for (i = 0; i < (zfirst_len - first_len); i++) { local_source[i] = '0'; } - ustrcpy(local_source + i, first_part); + memcpy(local_source + i, first_part, first_len + 1); /* Include terminating NUL */ if (zfirst_part) { - ustrcpy(zfirst_part, local_source); + memcpy(zfirst_part, local_source, ustrlen(local_source) + 1); } if (with_addon) { - h = (int) ustrlen(local_source); + int h = (int) ustrlen(local_source); local_source[h++] = '+'; for (i = 0; i < (zsecond_len - second_len); i++) { local_source[h + i] = '0'; } - ustrcpy(local_source + h + i, second_part); + memcpy(local_source + h + i, second_part, second_len + 1); /* Include terminating NUL */ if (zsecond_part) { - ustrcpy(zsecond_part, local_source + h); + memcpy(zsecond_part, local_source + h, ustrlen(local_source + h) + 1); } } else if (zsecond_part) { *zsecond_part = '\0'; @@ -769,6 +757,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int len int error_number = 0, i, plus_count; int addon_gap = 0; int first_part_len, second_part_len; + const int plain_hrt = symbol->output_options & BARCODE_PLAIN_HRT; if (length > 19) { return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 283, "Input length %d too long (maximum 19)", length); @@ -799,7 +788,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int len } /* Add leading zeroes, checking max lengths of parts */ - if (!ean_leading_zeroes(symbol, source, local_source, &with_addon, first_part, second_part)) { + if (!ean_leading_zeroes(symbol, source, length, local_source, &with_addon, first_part, second_part)) { return ZINT_ERROR_TOO_LONG; /* `ean_leading_zeroes()` sets `errtxt` */ } @@ -821,7 +810,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int len case 2: case 5: ean_add_on(first_part, first_part_len, dest, 0); - ustrcpy(symbol->text, first_part); + hrt_cpy_nochk(symbol, first_part, first_part_len); if (symbol->output_options & COMPLIANT_HEIGHT) { /* 21.9mm from GS1 General Specifications 5.2.6.6, Figure 5.2.6.6-6 */ const float height = 66.3636398f; /* 21.9 / 0.33 */ @@ -952,8 +941,10 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int len if (second_part_len) { ean_add_on(second_part, second_part_len, dest, addon_gap); - ustrcat(symbol->text, "+"); - ustrcat(symbol->text, second_part); + if (!plain_hrt) { + hrt_cat_chr_nochk(symbol, '+'); + } + hrt_cat_nochk(symbol, second_part, second_part_len); } expand(symbol, dest, (int) strlen(dest)); @@ -962,7 +953,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int len case BARCODE_EANX_CC: case BARCODE_UPCA_CC: case BARCODE_UPCE_CC: - /* shift the symbol to the right one space to allow for separator bars */ + /* Shift the symbol to the right one space to allow for separator bars */ for (i = (symbol->width + 1); i >= 1; i--) { if (module_is_set(symbol, symbol->rows - 1, i - 1)) { set_module(symbol, symbol->rows - 1, i); diff --git a/backend/vector.c b/backend/vector.c index fefdc25b..b06e94a1 100644 --- a/backend/vector.c +++ b/backend/vector.c @@ -1,7 +1,7 @@ /* vector.c - Creates vector image objects */ /* libzint - the open source barcode library - Copyright (C) 2018-2024 Robin Stuart + Copyright (C) 2018-2025 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -467,7 +467,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ main_width -= comp_xoffset + comp_roffset; } - hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0)); + hide_text = !symbol->show_hrt || symbol->text_length == 0; out_set_whitespace_offsets(symbol, hide_text, comp_xoffset, &xoffset, &yoffset, &roffset, &boffset, &qz_right, 0 /*scaler*/, NULL, NULL, NULL, NULL, NULL); @@ -877,7 +877,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ if (text_yposn < 0.0f) { text_yposn = 0.0f; } - addon_len = (int) ustrlen(symbol->text); + addon_len = symbol->text_length; textwidth = addon_len * 8.5f; if (!vector_add_string(symbol, symbol->text, addon_len, text_xposn, text_yposn, font_height, textwidth, 0 /*centre align*/, &last_string)) return ZINT_ERROR_MEMORY; diff --git a/backend/zint.h b/backend/zint.h index bb931534..d8c53d4a 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -123,6 +123,7 @@ extern "C" { int warn_level; /* Affects error/warning value returned by Zint API (see WARN_XXX below) */ int debug; /* Debugging flags */ unsigned char text[256]; /* Human Readable Text (HRT) (if any), UTF-8, NUL-terminated (output only) */ + int text_length; /* Length of `text`, useful if BARCODE_PLAIN_HRT when HRT may have NULs (output only) */ int rows; /* Number of rows used by the symbol (output only) */ int width; /* Width of the generated symbol (output only) */ unsigned char encoded_data[200][144]; /* Encoded data (output only). Allows for rows of 1152 modules */ @@ -298,6 +299,9 @@ extern "C" { #define EANUPC_GUARD_WHITESPACE 0x04000 /* Add quiet zone indicators ("<"/">") to HRT whitespace (EAN/UPC) */ #define EMBED_VECTOR_FONT 0x08000 /* Embed font in vector output - currently only for SVG output */ #define BARCODE_MEMORY_FILE 0x10000 /* Write output to in-memory buffer `memfile` instead of to `outfile` */ +#define BARCODE_PLAIN_HRT 0x20000 /* Set HRT with no decoration (GS1 data will not have parentheses but GS + separators as needed), complete with any control chars and check chars, and + for all linear symbologies, including those that normally don't set it */ /* Input data types (`symbol->input_mode`) */ #define DATA_MODE 0 /* Binary */ diff --git a/backend_qt/qzint.cpp b/backend_qt/qzint.cpp index fe21155e..cad3a084 100644 --- a/backend_qt/qzint.cpp +++ b/backend_qt/qzint.cpp @@ -1,7 +1,7 @@ /*************************************************************************** * Copyright (C) 2008 by BogDan Vatra * * bogdan@licentia.eu * - * Copyright (C) 2010-2024 Robin Stuart * + * Copyright (C) 2010-2025 Robin Stuart * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -35,6 +35,8 @@ #include "../backend/fonts/normal_ttf.h" /* Arimo */ #include "../backend/fonts/upcean_ttf.h" /* OCR-B subset (digits, "<", ">") */ +#define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0]))) + // Shorthand #define QSL QStringLiteral #define QSEmpty QLatin1String("") @@ -75,6 +77,12 @@ namespace Zint { return upceanFontID; } + /* Helper to copy byte array up to max `max` into `buf` which must be NUL filled & at least `max` size */ + static void cpy_bytearray_left(char *buf, const QByteArray &ba, const int max) { + QByteArray left = ba.left(max); + memcpy(buf, left, left.size()); + } + /* Helper to convert QColor to RGB(A) hex string */ static QString qcolor_to_str(const QColor &color) { if (color.alpha() == 0xFF) { @@ -253,9 +261,9 @@ namespace Zint { if (m_embed_vector_font) { m_zintSymbol->output_options |= EMBED_VECTOR_FONT; } - strcpy(m_zintSymbol->fgcolour, m_fgStr.toLatin1().left(15)); - strcpy(m_zintSymbol->bgcolour, m_bgStr.toLatin1().left(15)); - strcpy(m_zintSymbol->primary, m_primaryMessage.toLatin1().left(127)); + cpy_bytearray_left(m_zintSymbol->fgcolour, m_fgStr.toLatin1(), ARRAY_SIZE(m_zintSymbol->fgcolour) - 1); + cpy_bytearray_left(m_zintSymbol->bgcolour, m_bgStr.toLatin1(), ARRAY_SIZE(m_zintSymbol->fgcolour) - 1); + cpy_bytearray_left(m_zintSymbol->primary, m_primaryMessage.toLatin1(), ARRAY_SIZE(m_zintSymbol->primary) - 1); m_zintSymbol->option_1 = m_option_1; m_zintSymbol->option_2 = m_option_2; m_zintSymbol->option_3 = m_option_3; @@ -466,15 +474,8 @@ namespace Zint { m_structapp.index = index; memset(m_structapp.id, 0, sizeof(m_structapp.id)); if (!id.isEmpty()) { - QByteArray idArr = id.toLatin1(); -#if defined(__GNUC__) && __GNUC__ >= 8 && !defined(__clang__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wstringop-truncation" -#endif - strncpy(m_structapp.id, idArr, sizeof(m_structapp.id)); -#if defined(__GNUC__) && !defined(__clang__) -#pragma GCC diagnostic pop -#endif + /* Note may not have NUL terminator */ + cpy_bytearray_left(m_structapp.id, id.toLatin1(), ARRAY_SIZE(m_structapp.id)); } } else { clearStructApp(); @@ -906,7 +907,7 @@ namespace Zint { bool QZint::save_to_file(const QString& filename) { if (resetSymbol()) { - strcpy(m_zintSymbol->outfile, filename.toUtf8().left(255)); + cpy_bytearray_left(m_zintSymbol->outfile, filename.toUtf8(), ARRAY_SIZE(m_zintSymbol->outfile) - 1); if (m_segs.empty()) { QByteArray bstr = m_text.toUtf8(); m_error = ZBarcode_Encode_and_Print(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), diff --git a/backend_tcl/zint.c b/backend_tcl/zint.c index 2138c734..1404be57 100644 --- a/backend_tcl/zint.c +++ b/backend_tcl/zint.c @@ -180,6 +180,8 @@ - Added DXFILMEDGE 2025-01-29 GL - MSVC: suppress warning 4996 (_CRT_SECURE_NO_WARNINGS) +2025-02-15 GL +- strcpy() -> memcpy(); sizeof(primary); tabs -> spaces */ #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) @@ -620,60 +622,60 @@ DLLEXPORT int Zint_Init (Tcl_Interp *interp) /*------------------------------------------------------------------------*/ /* Add build info */ if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) { - Tcl_CreateObjCommand(interp, "::zint::build-info", - info.objProc, (void *)( - PACKAGE_VERSION "+" STRINGIFY(SAMPLE_VERSION_UUID) + Tcl_CreateObjCommand(interp, "::zint::build-info", + info.objProc, (void *)( + PACKAGE_VERSION "+" STRINGIFY(SAMPLE_VERSION_UUID) #if defined(__clang__) && defined(__clang_major__) - ".clang-" STRINGIFY(__clang_major__) + ".clang-" STRINGIFY(__clang_major__) #if __clang_minor__ < 10 - "0" + "0" #endif - STRINGIFY(__clang_minor__) + STRINGIFY(__clang_minor__) #endif #if defined(__cplusplus) && !defined(__OBJC__) - ".cplusplus" + ".cplusplus" #endif #ifndef NDEBUG - ".debug" + ".debug" #endif #if !defined(__clang__) && !defined(__INTEL_COMPILER) && defined(__GNUC__) - ".gcc-" STRINGIFY(__GNUC__) + ".gcc-" STRINGIFY(__GNUC__) #if __GNUC_MINOR__ < 10 - "0" + "0" #endif - STRINGIFY(__GNUC_MINOR__) + STRINGIFY(__GNUC_MINOR__) #endif #ifdef __INTEL_COMPILER - ".icc-" STRINGIFY(__INTEL_COMPILER) + ".icc-" STRINGIFY(__INTEL_COMPILER) #endif #ifdef TCL_MEM_DEBUG - ".memdebug" + ".memdebug" #endif #if defined(_MSC_VER) - ".msvc-" STRINGIFY(_MSC_VER) + ".msvc-" STRINGIFY(_MSC_VER) #endif #ifdef USE_NMAKE - ".nmake" + ".nmake" #endif #ifndef TCL_CFG_OPTIMIZED - ".no-optimize" + ".no-optimize" #endif #ifdef __OBJC__ - ".objective-c" + ".objective-c" #if defined(__cplusplus) - "plusplus" + "plusplus" #endif #endif #ifdef TCL_CFG_PROFILED - ".profile" + ".profile" #endif #ifdef PURIFY - ".purify" + ".purify" #endif #ifdef STATIC_BUILD - ".static" + ".static" #endif - ), NULL); + ), NULL); } /*------------------------------------------------------------------------*/ /* This procedure is called once per thread and any thread local data */ @@ -684,7 +686,7 @@ DLLEXPORT int Zint_Init (Tcl_Interp *interp) *tkFlagPtr = 0; Tcl_CallWhenDeleted(interp, InterpCleanupProc, (ClientData)tkFlagPtr); /*------------------------------------------------------------------------*/ - /* FIXME: to unload even on command rename, capture the tolken, put it in */ + /* FIXME: to unload even on command rename, capture the token, put it in */ /* the client data and use it to delete the command. */ Tcl_CreateObjCommand(interp, "zint", ZintCmd, (ClientData)tkFlagPtr, (Tcl_CmdDeleteProc *)NULL); @@ -987,12 +989,11 @@ static int Encode(Tcl_Interp *interp, int objc, } break; case iPrimary: - /* > Primary String up to 90 characters */ - /* > Output filename up to 250 characters */ + /* > Primary String up to 127 characters */ Tcl_DStringInit(& dString); pStr = Tcl_GetStringFromObj(objv[optionPos+1], &lStr); Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &dString); - if (Tcl_DStringLength(&dString) > (optionIndex==iPrimary?90:250)) { + if (Tcl_DStringLength(&dString) >= (int) sizeof(my_symbol->primary)) { Tcl_DStringFree(&dString); Tcl_SetObjResult(interp,Tcl_NewStringObj("String too long", -1)); fError = 1; @@ -1181,8 +1182,8 @@ static int Encode(Tcl_Interp *interp, int objc, break; case iReverse: if (intValue) { - strcpy(my_symbol->fgcolour, "ffffff"); - strcpy(my_symbol->bgcolour, "000000"); + memcpy(my_symbol->fgcolour, "ffffff", 7); /* Include terminating NUL */ + memcpy(my_symbol->bgcolour, "000000", 7); } break; case iWError: @@ -1200,7 +1201,7 @@ static int Encode(Tcl_Interp *interp, int objc, break; case iNoBackground: if (intValue) { - strcpy(my_symbol->bgcolour, "ffffff00"); + memcpy(my_symbol->bgcolour, "ffffff00", 9); /* Include terminating NUL */ } break; case iNoQuietZones: @@ -1372,7 +1373,8 @@ static int Encode(Tcl_Interp *interp, int objc, } break; case iPrimary: - strcpy(my_symbol->primary, Tcl_DStringValue( &dString ) ); + /* Include terminating NUL */ + memcpy(my_symbol->primary, Tcl_DStringValue(&dString), Tcl_DStringLength(&dString) + 1); Tcl_DStringFree(&dString); break; case iRotate: diff --git a/docs/README b/docs/README index a011d5e7..c97e9ce8 100644 --- a/docs/README +++ b/docs/README @@ -1,11 +1,11 @@ -% docs/README 2025-01-18 +% docs/README 2025-02-15 For generation of "docs/manual.pdf" and "docs/manual.txt" from "manual.pmd" using a recent version of pandoc On Ubuntu/Debian (tested on Ubuntu 22.04 and Ubuntu 24.04) - wget https://github.com/jgm/pandoc/releases/download/3.6.2/pandoc-3.6.2-1-amd64.deb - sudo dpkg -i pandoc-3.6.2-1-amd64.deb + wget https://github.com/jgm/pandoc/releases/download/3.6.3/pandoc-3.6.3-1-amd64.deb + sudo dpkg -i pandoc-3.6.3-1-amd64.deb For Ubuntu 22.04 (python < 3.12) sudo apt install python3-pip pip install pandoc-tablenos --user @@ -27,9 +27,9 @@ Then On Fedora (tested on Fedora Linux 38 (Workstation Edition) and Fedora Linux 40 (Workstation Edition)) - wget https://github.com/jgm/pandoc/releases/download/3.6.2/pandoc-3.6.2-linux-amd64.tar.gz - tar xf pandoc-3.6.2-linux-amd64.tar.gz - sudo mv -i pandoc-3.6.2/bin/pandoc /usr/local/bin + wget https://github.com/jgm/pandoc/releases/download/3.6.3/pandoc-3.6.3-linux-amd64.tar.gz + tar xf pandoc-3.6.3-linux-amd64.tar.gz + sudo mv -i pandoc-3.6.3/bin/pandoc /usr/local/bin sudo dnf install python3-pip pip install pandoc-tablenos --user export PATH=~/.local/bin:"$PATH" diff --git a/docs/manual.html b/docs/manual.html index 7a2fd92b..7450eba2 100644 --- a/docs/manual.html +++ b/docs/manual.html @@ -1440,8 +1440,8 @@ is hexadecimal (000000-10FFFF)

(Special escape sequences are available for Code 128 only to manually -switch Code Sets and insert special FNC1 characters - see 6.1.10.1 Standard Code 128 (ISO +switch Code Sets and insert special FNC1 characters - see +6.1.10.1 Standard Code 128 (ISO 15417) for details.)

Input data can be read directly from file using the -i or --input switch as shown below. The input file is assumed @@ -3555,6 +3555,12 @@ with a terminating NUL. "" (empty) (output only) +text_length +integer +Length of text. +0 (output only) + + rows integer Number of rows used by the symbol. @@ -3891,8 +3897,8 @@ than squares. GS1_GS_SEPARATOR -Use GS (Group Separator) instead of FNC1 -as GS1 separator (Data Matrix only). +Use GS (Group Separator) +instead of FNC1 as GS1 separator (Data Matrix only). OUT_BUFFER_INTERMEDIATE @@ -3934,6 +3940,18 @@ available for SVG output only. symbol->memfile instead of to outfile file. + +BARCODE_PLAIN_HRT +Set HRT with no decoration,13 +complete with any control characters14 and check +characters,15 and for all linear symbologies, +including those that normally don’t set it.16 + @@ -3967,7 +3985,7 @@ binary data. GS1_MODE -Encodes GS1 data using FNC1 +Encodes GS1 data using FNC1 characters. @@ -4195,8 +4213,8 @@ Text? ZINT_CAP_EANUPC13 +href="#fn17" class="footnote-ref" id="fnref17" +role="doc-noteref">17 Is the symbology EAN/UPC? @@ -4421,13 +4439,13 @@ aria-hidden="true">zint -b UPCA --compliantheight -d "72527270270"<

UPC-A is used in the United States for retail applications. The symbol requires an 11-digit article number. The check digit is calculated by Zint. In addition EAN-2 and EAN-5 add-on symbols can be -added using the + character. For example, to draw a UPC-A symbol with -the data 72527270270 with an EAN-5 add-on showing the data 12345 use the -command:

+added using the + character. For example, to draw a UPC-A +symbol with the data 72527270270 with an EAN-5 add-on showing the data +12345 use the command:

zint -b UPCA -d "72527270270+12345"
-

or using the API encode a data string with the + character -included:

+

or using the API encode a data string with the + +character included:

my_symbol->symbology = BARCODE_UPCA;
 error = ZBarcode_Encode_and_Print(my_symbol, "72527270270+12345", 0, 0);
@@ -4515,8 +4533,8 @@ aria-hidden="true">zint -b EANX --compliantheight -d "4512345678906" +symbols can be added to EAN-8 and EAN-13 symbols using the ++ character as with UPC symbols. For example:

zint -b EANX -d "54321"
@@ -4578,9 +4596,10 @@ alt="zint -b ISBNX --compliantheight -d "9789295055124" --guardwhitesp
-

EAN-2 and EAN-5 add-on symbols can be added using the + character, -and there are options to adjust the add-on gap and the guard bar descent -height - see 6.1.3.2 UPC Version E.

+

EAN-2 and EAN-5 add-on symbols can be added using the + +character, and there are options to adjust the add-on gap and the guard +bar descent height - see 6.1.3.2 UPC Version +E.

6.1.5 Plessey

6.1.5.1 UK Plessey

@@ -4591,8 +4610,10 @@ aria-hidden="true">zint -b PLESSEY -d "C64"

Also known as Plessey Code, this symbology was developed by the Plessey Company Ltd. in the UK. The symbol can encode data consisting of -digits (0-9) or letters A-F up to a maximum of 67 characters and -includes a hidden CRC check digit.

+digits (0-9) or letters A-F (i.e. hexadecimal digits) up to a maximum of +67 characters and includes two hidden CRC check digits, which may be +shown in the Human Readable Text by setting --vers=1 (API +option_2 |= 1).

6.1.5.2 MSI Plessey

^). For instance

class="sourceCode bash">zint -b CODE128 -d "\^AABC\^^BDEF" --extraesc

will encode the data "ABC\^BDEF" in Code Set A.

There is also the extra escape \^1, which will encode a -special Function Code 1 character (FNC1) anywhere you chose in the data, -for instance

+special Function Code 1 character (FNC1) anywhere you chose +in the data, for instance

zint -b CODE128 -d "A\^1BC\^1DEF" --extraesc

Zint can encode a maximum of 102 symbol characters, which allows for @@ -4868,8 +4889,8 @@ aria-hidden="true">zint -b CODE128AB -d "130170X178"

It is sometimes advantageous to stop Code 128 from using Code Set C which compresses numerical data. The BARCODE_CODE128AB14 variant (symbology 60) suppresses +href="#fn18" class="footnote-ref" id="fnref18" +role="doc-noteref">18 variant (symbology 60) suppresses Code Set C in favour of Code Sets A and B.

Note that the special extra escapes mentioned above are not available for this variant (nor for any other).

@@ -5609,8 +5630,8 @@ the 6-digit version the first and last digit are ignored, leaving a 2047. The second format "NNN-NN" represents the DX Extract as two numbers separated by a dash (-), the first number being 1 to 3 digits (range 1 to 127) and the second 1 to 2 digits (range -0 to 15).15

+0 to 15).19

The optional frame number is a number in the range 0 to 63, and may have a half frame indicator "A" appended. Special character sequences (with or without a half frame indicator appended) may also be @@ -5762,16 +5783,16 @@ characters, producing a symbol with 66 or 78 bars respectively. The rules for the input data are complex, as summarized in the following table.

----+++ @@ -6108,9 +6129,10 @@ generated with the following values as before:

DMRE symbol sizes may be activated in automatic size mode using the option --dmre (API option_3 = DM_DMRE).

-

GS1 data may be encoded using FNC1 (default) or GS (Group Separator, -ASCII 29) as separator. Use the option --gssep to change to -GS (API output_options |= GS1_GS_SEPARATOR).

+

GS1 data may be encoded using FNC1 (default) or +GS (Group Separator, ASCII 29) as separator. Use the option +--gssep to change to GS (API +output_options |= GS1_GS_SEPARATOR).

By default Zint uses a “de facto” codeword placement for symbols of size 144 x 144 (version 24). To override this and use the now clarified ISO/IEC standard placement, use option --dmiso144 (API @@ -8227,7 +8249,7 @@ Interpretations Part 1: Identification Schemes and Protocol (Released 24th May 2004)

  • AIM ITS/04-023 International Technical Standard - Extended Channel Interpretations Part 3: Register (Version 2, February 2022)
  • -
  • GS1 General Specifications Release 24.0 (Jan 2024)
  • +
  • GS1 General Specifications Release 25.0 (Jan 2025)
  • ANSI/HIBC 2.6-2016 - The Health Industry Bar Code (HIBC) Supplier Labeling Standard
  • @@ -9315,6 +9337,7 @@ Code 39 1 or 2 (add visible or hidden check digit) Code 93 1 (show the default check characters) EXCODE39 1 or 2 (add visible or hidden check digit) LOGMARS 1 or 2 (add visible or hidden check digit) +UK Plessey 1 (show the default check characters) MSI Plessey 0 to 6 (none to various visible options) 1, 2 (mod-10, mod-10 + mod-10) 3, 4 (mod-11 IBM, mod-11 IBM + mod-10) @@ -9522,16 +9545,36 @@ class="footnote-back" role="doc-backlink">↩︎

  • Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and UPC-E have compliant quiet zones added by default.↩︎

  • -
  • ZINT_CAP_EANUPC was previously named +

  • In particular no parentheses will appear in the HRT for +GS1 symbologies, and GS separators will be added as +required. Also for EAN/UPC symbologies, any add-on data will directly +follow the main data, i.e. will not be separated by a + +character.↩︎

  • +
  • Normally control characters (including +DEL) and non-ISO/IEC 8859-1 are replaced by spaces in the +HRT.↩︎

  • +
  • Except for Japanese Postal Code, whose check character +is not truly representable in HRT.↩︎

  • +
  • HRT is normally not set for the postal codes Australia +Post (all variants), USPS Intelligent Mail, POSTNET and PLANET, +Brazilian CEPNet, Royal Mail 4-State Customer Code and 4-State Mailmark, +Dutch Post KIX Code, Japanese Postal Code, DAFT Code, Flattermarken and +FIM, the pharma codes Pharmacode One-Track and Pharmacode Two-Track, and +DX Film Edge Barcode.↩︎

  • +
  • ZINT_CAP_EANUPC was previously named ZINT_CAP_EXTENDABLE, which is still recognised.↩︎

  • -
  • BARCODE_CODE128AB previously used the name +href="#fnref17" class="footnote-back" role="doc-backlink">↩︎

  • +
  • BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still recognised.↩︎

  • -
  • The DX number may be looked up in The (Modified) Big +href="#fnref18" class="footnote-back" role="doc-backlink">↩︎

  • +
  • The DX number may be looked up in The (Modified) Big Film Database at https://thebigfilmdatabase.merinorus.com.↩︎

  • +href="#fnref19" class="footnote-back" role="doc-backlink">↩︎

    diff --git a/docs/manual.pmd b/docs/manual.pmd index 446e6e31..c0476dc3 100644 --- a/docs/manual.pmd +++ b/docs/manual.pmd @@ -573,7 +573,7 @@ codeset from U+0000 to U+D7FF and U+E000 to U+FFFF (i.e. excluding surrogates). Not to be confused with the Windows Bitmap file format BMP! (Special escape sequences are available for Code 128 only to manually switch -Code Sets and insert special FNC1 characters - see [6.1.10.1 Standard Code 128 +Code Sets and insert special `FNC1` characters - see [6.1.10.1 Standard Code 128 (ISO 15417)] for details.) Input data can be read directly from file using the `-i` or `--input` switch as @@ -2037,6 +2037,8 @@ Member Name Type Meaning Default Value formatting, with a terminating `NUL`. +`text_length` integer Length of `text`. 0 (output only) + `rows` integer Number of rows used by (output only) the symbol. @@ -2297,7 +2299,7 @@ Value Effect `BARCODE_DOTTY_MODE` Plot a matrix symbol using dots rather than squares. -`GS1_GS_SEPARATOR` Use GS (Group Separator) instead of FNC1 as GS1 +`GS1_GS_SEPARATOR` Use `GS` (Group Separator) instead of `FNC1` as GS1 separator (Data Matrix only). `OUT_BUFFER_INTERMEDIATE` Return the bitmap buffer as ASCII values instead of @@ -2320,6 +2322,11 @@ Value Effect `BARCODE_MEMORY_FILE` Write output to in-memory buffer `symbol->memfile` instead of to `outfile` file. + +`BARCODE_PLAIN_HRT` Set HRT with no decoration,[^13] complete with any + control characters[^14] and check characters,[^15] + and for all linear symbologies, including those + that normally don't set it.[^16] ------------------------------------------------------------------------------ Table: API `output_options` Values {#tbl:api_output_options tag="$ $"} @@ -2333,6 +2340,23 @@ Code]. [^12]: Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and UPC-E have compliant quiet zones added by default. +[^13]: In particular no parentheses will appear in the HRT for GS1 symbologies, +and `GS` separators will be added as required. Also for EAN/UPC symbologies, any +add-on data will directly follow the main data, i.e. will not be separated by a +`+` character. + +[^14]: Normally control characters (including `DEL`) and non-ISO/IEC 8859-1 are +replaced by spaces in the HRT. + +[^15]: Except for Japanese Postal Code, whose check character is not truly +representable in HRT. + +[^16]: HRT is normally not set for the postal codes Australia Post (all +variants), USPS Intelligent Mail, POSTNET and PLANET, Brazilian CEPNet, Royal +Mail 4-State Customer Code and 4-State Mailmark, Dutch Post KIX Code, Japanese +Postal Code, DAFT Code, Flattermarken and FIM, the pharma codes Pharmacode +One-Track and Pharmacode Two-Track, and DX Film Edge Barcode. + ## 5.11 Setting the Input Mode The way in which the input data is encoded can be set using the `input_mode` @@ -2345,7 +2369,7 @@ Value Effect `UNICODE_MODE` Uses UTF-8 input. -`GS1_MODE` Encodes GS1 data using FNC1 characters. +`GS1_MODE` Encodes GS1 data using `FNC1` characters. _The above are exclusive, the following optional and OR-ed._ @@ -2585,7 +2609,7 @@ Value Meaning `ZINT_CAP_STACKABLE` Is the symbology stackable? -`ZINT_CAP_EANUPC`[^13] Is the symbology EAN/UPC? +`ZINT_CAP_EANUPC`[^17] Is the symbology EAN/UPC? `ZINT_CAP_COMPOSITE` Does the symbology support composite data? (see [6.3 GS1 Composite Symbols (ISO 24723)] below) @@ -2616,7 +2640,7 @@ Value Meaning Table: {#tbl:api_cap tag=": API Capability Flags"} -[^13]: `ZINT_CAP_EANUPC` was previously named `ZINT_CAP_EXTENDABLE`, which is +[^17]: `ZINT_CAP_EANUPC` was previously named `ZINT_CAP_EXTENDABLE`, which is still recognised. For example: @@ -2774,15 +2798,15 @@ Zint adds a check digit. UPC-A is used in the United States for retail applications. The symbol requires an 11-digit article number. The check digit is calculated by Zint. In addition -EAN-2 and EAN-5 add-on symbols can be added using the + character. For example, -to draw a UPC-A symbol with the data 72527270270 with an EAN-5 add-on showing -the data 12345 use the command: +EAN-2 and EAN-5 add-on symbols can be added using the `+` character. For +example, to draw a UPC-A symbol with the data 72527270270 with an EAN-5 add-on +showing the data 12345 use the command: ```bash zint -b UPCA -d "72527270270+12345" ``` -or using the API encode a data string with the + character included: +or using the API encode a data string with the `+` character included: ```c my_symbol->symbology = BARCODE_UPCA; @@ -2873,7 +2897,7 @@ The EAN system is used in retail across Europe and includes standards for EAN-2, EAN-5, EAN-8 and EAN-13 which encode 2, 5, 7 or 12-digit numbers respectively. Zint will decide which symbology to use depending on the length of the input data. In addition EAN-2 and EAN-5 add-on symbols can be added to EAN-8 and -EAN-13 symbols using the + character as with UPC symbols. For example: +EAN-13 symbols using the `+` character as with UPC symbols. For example: ```bash zint -b EANX -d "54321" @@ -2932,9 +2956,9 @@ As with EAN-13, a quiet zone indicator can be added using `--guardwhitespace`: ![`zint -b ISBNX --compliantheight -d "9789295055124" --guardwhitespace`](images/isbnx_gws.svg){.upcean} -EAN-2 and EAN-5 add-on symbols can be added using the + character, and there are -options to adjust the add-on gap and the guard bar descent height - see [6.1.3.2 -UPC Version E]. +EAN-2 and EAN-5 add-on symbols can be added using the `+` character, and there +are options to adjust the add-on gap and the guard bar descent height - see +[6.1.3.2 UPC Version E]. ### 6.1.5 Plessey @@ -2944,7 +2968,9 @@ UPC Version E]. Also known as Plessey Code, this symbology was developed by the Plessey Company Ltd. in the UK. The symbol can encode data consisting of digits (0-9) or letters -A-F up to a maximum of 67 characters and includes a hidden CRC check digit. +A-F (i.e. hexadecimal digits) up to a maximum of 67 characters and includes two +hidden CRC check digits, which may be shown in the Human Readable Text by +setting `--vers=1` (API `option_2 |= 1`). #### 6.1.5.2 MSI Plessey @@ -3142,7 +3168,7 @@ zint -b CODE128 -d "\^AABC\^^BDEF" --extraesc will encode the data `"ABC\^BDEF"` in Code Set A. There is also the extra escape `\^1`, which will encode a special Function Code -1 character (FNC1) anywhere you chose in the data, for instance +1 character (`FNC1`) anywhere you chose in the data, for instance ```bash zint -b CODE128 -d "A\^1BC\^1DEF" --extraesc @@ -3157,13 +3183,13 @@ alphanumerics) are not recommended. ![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg){.lin} It is sometimes advantageous to stop Code 128 from using Code Set C which -compresses numerical data. The `BARCODE_CODE128AB`[^14] variant (symbology 60) +compresses numerical data. The `BARCODE_CODE128AB`[^18] variant (symbology 60) suppresses Code Set C in favour of Code Sets A and B. Note that the special extra escapes mentioned above are not available for this variant (nor for any other). -[^14]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is +[^18]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is still recognised. #### 6.1.10.3 GS1-128 @@ -3755,7 +3781,7 @@ first and last digit are ignored, leaving a 4-digit DX Extract number in any case, which must be in the range 16 to 2047. The second format `"NNN-NN"` represents the DX Extract as two numbers separated by a dash (`-`), the first number being 1 to 3 digits (range 1 to 127) and the second 1 to 2 digits (range -0 to 15).[^15] +0 to 15).[^19] The optional frame number is a number in the range 0 to 63, and may have a half frame indicator `"A"` appended. Special character sequences (with or without a @@ -3765,7 +3791,7 @@ number 62, `"K"` or `"00"` means frame number 63, and `"F"` means frame number A parity bit is automatically added by Zint. -[^15]: The DX number may be looked up in The (Modified) Big Film Database at +[^19]: The DX number may be looked up in The (Modified) Big Film Database at [https://thebigfilmdatabase.merinorus.com]( https://thebigfilmdatabase.merinorus.com). @@ -3856,13 +3882,13 @@ Solomon error correction. Input is a pre-formatted alphanumeric string of 22 78 bars respectively. The rules for the input data are complex, as summarized in the following table. ---------------------------------------------------------------------------- -Format Version Class Supply Chain ID Item ID Destination+DPS +----------------------------------------------------------------------------- +Format Version Class Supply Chain ID Item ID Destination+DPS ID -------- ------- ----------- --------------- -------- ----------------- -1 digit 1 digit 1 alphanum. 2 digits (C) or 8 digits 9 alphanumerics -(0-4) (0-3) (0-9A-E) 6 digits (L) (1 of 6 patterns) ---------------------------------------------------------------------------- +------- ------- ----------- --------------- -------- ----------------- +1 digit 1 digit 1 alphanum. 2 digits (C) or 8 digits 9 alphanumerics +(0-4) (0-3) (0-9A-E) 6 digits (L) (1 of 6 patterns) +----------------------------------------------------------------------------- Table: {#tbl:mailmark_4s_input_fields tag=": Royal Mail 4-State Mailmark Input Fields"} @@ -4000,9 +4026,9 @@ Table: {#tbl:dmre_sizes tag=": DMRE Sizes"} DMRE symbol sizes may be activated in automatic size mode using the option `--dmre` (API `option_3 = DM_DMRE`). -GS1 data may be encoded using FNC1 (default) or GS (Group Separator, ASCII 29) -as separator. Use the option `--gssep` to change to GS (API `output_options |= -GS1_GS_SEPARATOR`). +GS1 data may be encoded using `FNC1` (default) or `GS` (Group Separator, ASCII +29) as separator. Use the option `--gssep` to change to `GS` (API +`output_options |= GS1_GS_SEPARATOR`). By default Zint uses a "de facto" codeword placement for symbols of size 144 x 144 (version 24). To override this and use the now clarified ISO/IEC standard @@ -4899,7 +4925,7 @@ company references in particular. May 2004) - AIM ITS/04-023 International Technical Standard - Extended Channel Interpretations Part 3: Register (Version 2, February 2022) -- GS1 General Specifications Release 24.0 (Jan 2024) +- GS1 General Specifications Release 25.0 (Jan 2025) - ANSI/HIBC 2.6-2016 - The Health Industry Bar Code (HIBC) Supplier Labeling Standard diff --git a/docs/manual.txt b/docs/manual.txt index cd39d766..9e3f03aa 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -2053,6 +2053,8 @@ the following members: formatting, with a terminating NUL. + text_length integer Length of text. 0 (output only) + rows integer Number of rows used by the (output only) symbol. @@ -2311,6 +2313,11 @@ together when adjusting this value: BARCODE_MEMORY_FILE Write output to in-memory buffer symbol->memfile instead of to outfile file. + + BARCODE_PLAIN_HRT Set HRT with no decoration,[13] complete with any + control characters[14] and check characters,[15] + and for all linear symbologies, including those + that normally don’t set it.[16] ------------------------------------------------------------------------------ : Table  : API output_options Values @@ -2539,7 +2546,7 @@ see which are set. ZINT_CAP_STACKABLE Is the symbology stackable? - ZINT_CAP_EANUPC[13] Is the symbology EAN/UPC? + ZINT_CAP_EANUPC[17] Is the symbology EAN/UPC? ZINT_CAP_COMPOSITE Does the symbology support composite data? (see 6.3 GS1 Composite Symbols (ISO 24723) below) @@ -2854,7 +2861,9 @@ UPC Version E. Also known as Plessey Code, this symbology was developed by the Plessey Company Ltd. in the UK. The symbol can encode data consisting of digits (0-9) or letters -A-F up to a maximum of 67 characters and includes a hidden CRC check digit. +A-F (i.e. hexadecimal digits) up to a maximum of 67 characters and includes two +hidden CRC check digits, which may be shown in the Human Readable Text by +setting --vers=1 (API option_2 |= 1). 6.1.5.2 MSI Plessey @@ -3053,7 +3062,7 @@ alphanumerics) are not recommended. [zint -b CODE128AB -d "130170X178"] It is sometimes advantageous to stop Code 128 from using Code Set C which -compresses numerical data. The BARCODE_CODE128AB[14] variant (symbology 60) +compresses numerical data. The BARCODE_CODE128AB[18] variant (symbology 60) suppresses Code Set C in favour of Code Sets A and B. Note that the special extra escapes mentioned above are not available for this @@ -3605,7 +3614,7 @@ first and last digit are ignored, leaving a 4-digit DX Extract number in any case, which must be in the range 16 to 2047. The second format "NNN-NN" represents the DX Extract as two numbers separated by a dash (-), the first number being 1 to 3 digits (range 1 to 127) and the second 1 to 2 digits (range -0 to 15).[15] +0 to 15).[19] The optional frame number is a number in the range 0 to 63, and may have a half frame indicator "A" appended. Special character sequences (with or without a @@ -3697,14 +3706,14 @@ Solomon error correction. Input is a pre-formatted alphanumeric string of 22 78 bars respectively. The rules for the input data are complex, as summarized in the following table. - ---------------------------------------------------------------------------- - Format Version Class Supply Chain ID Item ID Destination+DPS + ------------------------------------------------------------------------------ + Format Version Class Supply Chain ID Item ID Destination+DPS ID - -------- --------- ------------ ---------------- --------- ----------------- - 1 digit 1 digit 1 alphanum. 2 digits (C) or 8 digits 9 alphanumerics - (0-4) (0-3) (0-9A-E) 6 digits (L) (1 of 6 patterns) + -------- --------- ------------ ----------------- ---------- ----------------- + 1 digit 1 digit 1 alphanum. 2 digits (C) or 6 8 digits 9 alphanumerics + (0-4) (0-3) (0-9A-E) digits (L) (1 of 6 patterns) - ---------------------------------------------------------------------------- + ------------------------------------------------------------------------------ Table : Royal Mail 4-State Mailmark Input Fields @@ -4710,7 +4719,7 @@ company references in particular. May 2004) - AIM ITS/04-023 International Technical Standard - Extended Channel Interpretations Part 3: Register (Version 2, February 2022) -- GS1 General Specifications Release 24.0 (Jan 2024) +- GS1 General Specifications Release 25.0 (Jan 2025) - ANSI/HIBC 2.6-2016 - The Health Industry Bar Code (HIBC) Supplier Labeling Standard @@ -5431,6 +5440,7 @@ OPTIONS Code 93 1 (show the default check characters) EXCODE39 1 or 2 (add visible or hidden check digit) LOGMARS 1 or 2 (add visible or hidden check digit) + UK Plessey 1 (show the default check characters) MSI Plessey 0 to 6 (none to various visible options) 1, 2 (mod-10, mod-10 + mod-10) 3, 4 (mod-11 IBM, mod-11 IBM + mod-10) @@ -5612,11 +5622,28 @@ Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14. [12] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and UPC-E have compliant quiet zones added by default. -[13] ZINT_CAP_EANUPC was previously named ZINT_CAP_EXTENDABLE, which is still +[13] In particular no parentheses will appear in the HRT for GS1 symbologies, +and GS separators will be added as required. Also for EAN/UPC symbologies, any +add-on data will directly follow the main data, i.e. will not be separated by +a + character. + +[14] Normally control characters (including DEL) and non-ISO/IEC 8859-1 are +replaced by spaces in the HRT. + +[15] Except for Japanese Postal Code, whose check character is not truly +representable in HRT. + +[16] HRT is normally not set for the postal codes Australia Post (all variants), +USPS Intelligent Mail, POSTNET and PLANET, Brazilian CEPNet, Royal Mail 4-State +Customer Code and 4-State Mailmark, Dutch Post KIX Code, Japanese Postal Code, +DAFT Code, Flattermarken and FIM, the pharma codes Pharmacode One-Track and +Pharmacode Two-Track, and DX Film Edge Barcode. + +[17] ZINT_CAP_EANUPC was previously named ZINT_CAP_EXTENDABLE, which is still recognised. -[14] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still +[18] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still recognised. -[15] The DX number may be looked up in The (Modified) Big Film Database at +[19] The DX number may be looked up in The (Modified) Big Film Database at https://thebigfilmdatabase.merinorus.com. diff --git a/docs/zint.1 b/docs/zint.1 index 8a61ad7e..6a83d17a 100644 --- a/docs/zint.1 +++ b/docs/zint.1 @@ -1,4 +1,4 @@ -.\" Automatically generated by Pandoc 3.6.2 +.\" Automatically generated by Pandoc 3.6.3 .\" .TH "ZINT" "1" "February 2025" "Version 2.14.0.9" .SH NAME @@ -591,6 +591,7 @@ Code 39 1 or 2 (add visible or hidden check digit) Code 93 1 (show the default check characters) EXCODE39 1 or 2 (add visible or hidden check digit) LOGMARS 1 or 2 (add visible or hidden check digit) +UK Plessey 1 (show the default check characters) MSI Plessey 0 to 6 (none to various visible options) 1, 2 (mod\-10, mod\-10 + mod\-10) 3, 4 (mod\-11 IBM, mod\-11 IBM + mod\-10) diff --git a/docs/zint.1.pmd b/docs/zint.1.pmd index 55232531..bb6d358a 100644 --- a/docs/zint.1.pmd +++ b/docs/zint.1.pmd @@ -523,6 +523,7 @@ Paintbrush (`PCX`), Portable Network Format (`PNG`), Scalable Vector Graphic (`S Code 93 1 (show the default check characters) EXCODE39 1 or 2 (add visible or hidden check digit) LOGMARS 1 or 2 (add visible or hidden check digit) + UK Plessey 1 (show the default check characters) MSI Plessey 0 to 6 (none to various visible options) 1, 2 (mod-10, mod-10 + mod-10) 3, 4 (mod-11 IBM, mod-11 IBM + mod-10) diff --git a/frontend/main.c b/frontend/main.c index 41bb3398..f44e73f1 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -1,7 +1,7 @@ /* main.c - Command line handling routines for Zint */ /* libzint - the open source barcode library - Copyright (C) 2008-2024 Robin Stuart + Copyright (C) 2008-2025 Robin Stuart This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -257,6 +257,23 @@ static void show_eci(void) { "899: 8-bit binary data\n", stdout); } +/* Do buffer-checking `strcpy()`-like copy */ +static void cpy_str(char *buf, const int buf_size, const char *str) { + const int str_len = (int) strlen(str); + const int max_len = str_len >= buf_size ? buf_size - 1 : str_len; + memcpy(buf, str, max_len); + buf[max_len] = '\0'; +} + +/* Do buffer-checking `strncpy()`-like copy */ +static void ncpy_str(char *buf, const int buf_size, const char *str, const int str_max) { + const int str_len = (int) strlen(str); + const int max_str_len = str_len > str_max ? str_max : str_len; + const int max_len = max_str_len >= buf_size ? buf_size - 1 : max_str_len; + memcpy(buf, str, max_len); + buf[max_len] = '\0'; +} + /* Verifies that a string (length <= 9) only uses digits. On success returns value in arg */ static int validate_int(const char source[], int len, int *p_val) { int val = 0; @@ -290,7 +307,7 @@ static int validate_float(const char source[], const int allow_neg, float *p_val if (*source == '+' || *source == '-') { if (*source == '-') { if (!allow_neg) { - strcpy(errbuf, "negative value not permitted"); + cpy_str(errbuf, 64, "negative value not permitted"); return 0; } neg = 1; @@ -300,18 +317,18 @@ static int validate_float(const char source[], const int allow_neg, float *p_val int_len = dot ? (int) (dot - source) : (int) strlen(source); if (int_len > 9) { - strcpy(errbuf, "integer part must be 7 digits maximum"); /* Say 7 not 9 to "manage expections" */ + cpy_str(errbuf, 64, "integer part must be 7 digits maximum"); /* Say 7 not 9 to "manage expections" */ return 0; } if (int_len) { int tmp_val; if (!validate_int(source, int_len, &val)) { - strcpy(errbuf, "integer part must be digits only"); + cpy_str(errbuf, 64, "integer part must be digits only"); return 0; } for (int_len = 0, tmp_val = val; tmp_val; tmp_val /= 10, int_len++); /* log10(val) */ if (int_len > 7) { - strcpy(errbuf, "integer part must be 7 digits maximum"); + cpy_str(errbuf, 64, "integer part must be 7 digits maximum"); return 0; } } @@ -322,18 +339,18 @@ static int validate_float(const char source[], const int allow_neg, float *p_val fract_len = (int) (e + 1 - dot); if (fract_len) { if (fract_len > 7) { - strcpy(errbuf, "fractional part must be 7 digits maximum"); + cpy_str(errbuf, 64, "fractional part must be 7 digits maximum"); return 0; } if (!validate_int(dot, fract_len, &val2)) { - strcpy(errbuf, "fractional part must be digits only"); + cpy_str(errbuf, 64, "fractional part must be digits only"); return 0; } if (val2 && int_len + fract_len > 7) { if (val) { - strcpy(errbuf, "7 significant digits maximum"); + cpy_str(errbuf, 64, "7 significant digits maximum"); } else { - strcpy(errbuf, "fractional part must be 7 digits maximum"); + cpy_str(errbuf, 64, "fractional part must be 7 digits maximum"); } return 0; } @@ -583,11 +600,11 @@ static int get_barcode_name(const char *barcode_name) { }; int s = 0, e = ARRAY_SIZE(names) - 1; - char n[30] = {0}; + char n[30]; int i, j, length; /* Ignore case and any "BARCODE" prefix */ - strncpy(n, barcode_name, 29); + cpy_str(n, ARRAY_SIZE(n), barcode_name); to_lower(n); length = (int) strlen(n); if (strncmp(n, "barcode", 7) == 0) { @@ -626,13 +643,13 @@ static int supported_filetype(const char *filetype, const int no_png, int *png_r static const char filetypes[][4] = { "bmp", "emf", "eps", "gif", "pcx", "png", "svg", "tif", "txt", }; - char lc_filetype[4] = {0}; + char lc_filetype[4]; int i; if (png_refused) { *png_refused = 0; } - strncpy(lc_filetype, filetype, 3); + ncpy_str(lc_filetype, ARRAY_SIZE(lc_filetype), filetype, 3); to_lower(lc_filetype); if (no_png && strcmp(lc_filetype, "png") == 0) { @@ -663,28 +680,30 @@ static char *get_extension(const char *file) { /* Set extension of `file` to `filetype`, replacing existing extension if any. * Does nothing if file already has `filetype` extension */ -static void set_extension(char *file, const char *filetype) { - char lc_filetype[4] = {0}; +static void set_extension(char file[256], const char *filetype) { + char lc_filetype[4]; char *extension; char lc_extension[4]; + int file_len; - strncpy(lc_filetype, filetype, 3); + cpy_str(lc_filetype, ARRAY_SIZE(lc_filetype), filetype); to_lower(lc_filetype); extension = get_extension(file); if (extension) { - strcpy(lc_extension, extension); + cpy_str(lc_extension, ARRAY_SIZE(lc_extension), extension); to_lower(lc_extension); if (strcmp(lc_filetype, lc_extension) == 0) { return; } *(extension - 1) = '\0'; /* Cut off at dot */ } - if (strlen(file) > 251) { - file[251] = '\0'; + file_len = (int) strlen(file); + if (file_len > 251) { + file_len = 251; } - strcat(file, "."); - strncat(file, filetype, 3); + file[file_len++] = '.'; + ncpy_str(file + file_len, 256 - file_len, filetype, 3); } /* Whether `filetype` is raster type */ @@ -693,12 +712,12 @@ static int is_raster(const char *filetype, const int no_png) { "bmp", "gif", "pcx", "png", "tif", }; int i; - char lc_filetype[4] = {0}; + char lc_filetype[4]; if (filetype == NULL) { return 0; } - strcpy(lc_filetype, filetype); + cpy_str(lc_filetype, ARRAY_SIZE(lc_filetype), filetype); to_lower(lc_filetype); if (no_png && strcmp(lc_filetype, "png") == 0) { @@ -738,8 +757,8 @@ static int validate_units(char *buf, const char units[][5], int units_size) { static int validate_scalexdimdp(const char *arg, float *p_x_dim_mm, float *p_dpmm) { static const char x_units[][5] = { "mm", "in" }; static const char r_units[][5] = { "dpmm", "dpi" }; - char x_buf[7 + 1 + 4 + 1] = {0}; /* Allow for 7 digits + dot + 4-char unit + NUL */ - char r_buf[7 + 1 + 4 + 1] = {0}; /* As above */ + char x_buf[7 + 1 + 4 + 1]; /* Allow for 7 digits + dot + 4-char unit + NUL */ + char r_buf[7 + 1 + 4 + 1]; /* As above */ int units_i; /* For `validate_units()` */ char errbuf[64]; /* For `validate_float()` */ const char *comma = strchr(arg, ','); @@ -748,19 +767,19 @@ static int validate_scalexdimdp(const char *arg, float *p_x_dim_mm, float *p_dpm fprintf(stderr, "Error 174: scalexdimdp X-dim too %s\n", comma == arg ? "short" : "long"); return 0; } - strncpy(x_buf, arg, comma - arg); + ncpy_str(x_buf, ARRAY_SIZE(x_buf), arg, (int) (comma - arg)); comma++; if (!*comma || strlen(comma) >= ARRAY_SIZE(r_buf)) { fprintf(stderr, "Error 175: scalexdimdp resolution too %s\n", !*comma ? "short" : "long"); return 0; } - strcpy(r_buf, comma); + cpy_str(r_buf, ARRAY_SIZE(r_buf), comma); } else { if (!*arg || strlen(arg) >= ARRAY_SIZE(x_buf)) { fprintf(stderr, "Error 176: scalexdimdp X-dim too %s\n", !*arg ? "short" : "long"); return 0; } - strcpy(x_buf, arg); + cpy_str(x_buf, ARRAY_SIZE(x_buf), arg); } if ((units_i = validate_units(x_buf, x_units, ARRAY_SIZE(x_units))) == -2) { fprintf(stderr, "Error 177: scalexdimdp X-dim units must occur at end\n"); @@ -796,7 +815,7 @@ static int validate_scalexdimdp(const char *arg, float *p_x_dim_mm, float *p_dpm /* Parse and validate Structured Append argument "index,count[,ID]" to "--structapp" */ static int validate_structapp(const char *arg, struct zint_structapp *structapp) { - char index[10] = {0}, count[10] = {0}; + char index[10], count[10]; const char *comma = strchr(arg, ','); const char *comma2; if (!comma) { @@ -807,27 +826,31 @@ static int validate_structapp(const char *arg, struct zint_structapp *structapp) fprintf(stderr, "Error 156: Structured Append index too %s\n", comma == arg ? "short" : "long"); return 0; } - strncpy(index, arg, comma - arg); + ncpy_str(index, ARRAY_SIZE(index), arg, (int) (comma - arg)); comma++; comma2 = strchr(comma, ','); if (comma2) { + int i; if (comma2 == comma || comma2 - comma > 9) { fprintf(stderr, "Error 157: Structured Append count too %s\n", comma2 == comma ? "short" : "long"); return 0; } - strncpy(count, comma, comma2 - comma); + ncpy_str(count, ARRAY_SIZE(count), comma, (int) (comma2 - comma)); comma2++; if (!*comma2 || strlen(comma2) > 32) { fprintf(stderr, "Error 158: Structured Append ID too %s\n", !*comma2 ? "short" : "long"); return 0; } - strncpy(structapp->id, comma2, 32); + /* Do `strncat()`-like copy with no NUL terminator if ID length 32 */ + for (i = 0; i < ARRAY_SIZE(structapp->id) && comma2[i]; i++) { + structapp->id[i] = comma2[i]; + } } else { if (!*comma || strlen(comma) > 9) { fprintf(stderr, "Error 159: Structured Append count too %s\n", !*comma ? "short" : "long"); return 0; } - strcpy(count, comma); + cpy_str(count, ARRAY_SIZE(count), comma); } if (!validate_int(index, -1 /*len*/, &structapp->index)) { fprintf(stderr, "Error 160: Invalid Structured Append index (digits only)\n"); @@ -853,13 +876,13 @@ static int validate_structapp(const char *arg, struct zint_structapp *structapp) /* Parse and validate the segment argument "ECI,DATA" to "--segN" */ static int validate_seg(const char *arg, const int N, struct zint_seg segs[10]) { - char eci[10] = {0}; + char eci[10]; const char *comma = strchr(arg, ','); if (!comma || comma == arg || comma - arg > 9 || *(comma + 1) == '\0') { fprintf(stderr, "Error 166: Invalid segment argument, expect \"ECI,DATA\"\n"); return 0; } - strncpy(eci, arg, comma - arg); + ncpy_str(eci, ARRAY_SIZE(eci), arg, (int) (comma - arg)); if (!validate_int(eci, -1 /*len*/, &segs[N].eci)) { fprintf(stderr, "Error 167: Invalid segment ECI (digits only)\n"); return 0; @@ -884,12 +907,9 @@ static int batch_process(struct zint_symbol *symbol, const char *filename, const unsigned char buffer[ZINT_MAX_DATA_LEN] = {0}; /* Maximum HanXin input */ unsigned char character = 0; int buf_posn = 0, error_number = 0, warn_number = 0, line_count = 1; - char output_file[256]; - char number[12], reverse_number[12]; - int inpos, local_line_count; - char format_string[256], reversed_string[256], format_char; + char output_file[ARRAY_SIZE(symbol->outfile)]; + char format_string[ARRAY_SIZE(symbol->outfile)]; int format_len, i, o, mirror_start_o = 0; - char adjusted[2] = {0}; const int from_stdin = strcmp(filename, "-") == 0; /* Suppress clang-19 warning clang-analyzer-unix.Stream */ if (mirror_mode) { @@ -918,10 +938,10 @@ static int batch_process(struct zint_symbol *symbol, const char *filename, const } } else { if (symbol->outfile[0] == '\0' || !output_given) { - strcpy(format_string, "~~~~~."); - strncat(format_string, filetype, 3); + cpy_str(format_string, ARRAY_SIZE(format_string), "~~~~~."); + ncpy_str(format_string + 6, ARRAY_SIZE(format_string) - 6, filetype, 3); } else { - strcpy(format_string, symbol->outfile); + cpy_str(format_string, ARRAY_SIZE(format_string), symbol->outfile); set_extension(format_string, filetype); } } @@ -951,23 +971,20 @@ static int batch_process(struct zint_symbol *symbol, const char *filename, const if (character == '\n') { if (buf_posn > 0 && buffer[buf_posn - 1] == '\r') { /* CR+LF - assume Windows formatting and remove CR */ - buf_posn--; - buffer[buf_posn] = '\0'; + buffer[--buf_posn] = '\0'; } if (mirror_mode == 0) { - inpos = 0; - local_line_count = line_count; - memset(number, 0, sizeof(number)); - memset(reverse_number, 0, sizeof(reverse_number)); - memset(reversed_string, 0, sizeof(reversed_string)); - memset(output_file, 0, sizeof(output_file)); + char number[12], reverse_number[12]; + char reversed_string[ARRAY_SIZE(output_file)]; + char *rs = reversed_string; + int inpos = 0; + int local_line_count = line_count; + memset(output_file, 0, ARRAY_SIZE(output_file)); do { - number[inpos] = (local_line_count % 10) + '0'; + number[inpos++] = (local_line_count % 10) + '0'; local_line_count /= 10; - inpos++; } while (local_line_count > 0); - number[inpos] = '\0'; for (i = 0; i < inpos; i++) { reverse_number[i] = number[inpos - i - 1]; @@ -975,42 +992,42 @@ static int batch_process(struct zint_symbol *symbol, const char *filename, const format_len = (int) strlen(format_string); for (i = format_len; i > 0; i--) { - format_char = format_string[i - 1]; + char adjusted; - switch (format_char) { + switch (format_string[i - 1]) { case '#': if (inpos > 0) { - adjusted[0] = reverse_number[inpos - 1]; + adjusted = reverse_number[inpos - 1]; inpos--; } else { - adjusted[0] = ' '; + adjusted = ' '; } break; case '~': if (inpos > 0) { - adjusted[0] = reverse_number[inpos - 1]; + adjusted = reverse_number[inpos - 1]; inpos--; } else { - adjusted[0] = '0'; + adjusted = '0'; } break; case '@': if (inpos > 0) { - adjusted[0] = reverse_number[inpos - 1]; + adjusted = reverse_number[inpos - 1]; inpos--; } else { #ifndef _WIN32 - adjusted[0] = '*'; + adjusted = '*'; #else - adjusted[0] = '+'; + adjusted = '+'; #endif } break; default: - adjusted[0] = format_string[i - 1]; + adjusted = format_string[i - 1]; break; } - strcat(reversed_string, adjusted); + *rs++ = adjusted; } for (i = 0; i < format_len; i++) { @@ -1063,12 +1080,10 @@ static int batch_process(struct zint_symbol *symbol, const char *filename, const /* Add file extension */ output_file[o] = '.'; - output_file[o + 1] = '\0'; - - strncat(output_file, filetype, 3); + ncpy_str(output_file + o + 1, ARRAY_SIZE(output_file) - o - 1, filetype, 3); } - strcpy(symbol->outfile, output_file); + cpy_str(symbol->outfile, ARRAY_SIZE(symbol->outfile), output_file); warn_number = ZBarcode_Encode_and_Print(symbol, buffer, buf_posn, rotate_angle); if (warn_number != 0) { fprintf(stderr, "On line %d: %s\n", line_count, symbol->errtxt); @@ -1078,14 +1093,13 @@ static int batch_process(struct zint_symbol *symbol, const char *filename, const } } ZBarcode_Clear(symbol); - memset(buffer, 0, sizeof(buffer)); + memset(buffer, 0, ARRAY_SIZE(buffer)); buf_posn = 0; line_count++; } else { - buffer[buf_posn] = character; - buf_posn++; + buffer[buf_posn++] = character; } - if (buf_posn >= (int) sizeof(buffer)) { + if (buf_posn >= ARRAY_SIZE(buffer)) { fprintf(stderr, "On line %d: Error 103: Input data too long\n", line_count); fflush(stderr); do { @@ -1381,7 +1395,7 @@ static void win_args(int *p_argc, char ***p_argv) { static FILE *win_fopen(const char *filename, const char *mode) { wchar_t *filenameW, *modeW; - utf8_to_wide(filename, filenameW, NULL); + utf8_to_wide(filename, filenameW, NULL /*fail return*/); utf8_to_wide(mode, modeW, NULL); return _wfopen(filenameW, modeW); @@ -1574,7 +1588,7 @@ int main(int argc, char **argv) { } break; case OPT_BG: - strncpy(my_symbol->bgcolour, optarg, 15); /* Allow for "CCC,MMM,YYY,KKK" */ + cpy_str(my_symbol->bgcolour, ARRAY_SIZE(my_symbol->bgcolour), optarg); break; case OPT_BINARY: my_symbol->input_mode = (my_symbol->input_mode & ~0x07) | DATA_MODE; @@ -1653,7 +1667,7 @@ int main(int argc, char **argv) { break; case OPT_DUMP: my_symbol->output_options |= BARCODE_STDOUT; - strcpy(my_symbol->outfile, "dummy.txt"); + cpy_str(my_symbol->outfile, ARRAY_SIZE(my_symbol->outfile), "dummy.txt"); break; case OPT_ECI: if (!validate_int(optarg, -1 /*len*/, &val)) { @@ -1681,12 +1695,12 @@ int main(int argc, char **argv) { my_symbol->input_mode |= FAST_MODE; break; case OPT_FG: - strncpy(my_symbol->fgcolour, optarg, 15); /* Allow for "CCC,MMM,YYY,KKK" */ + cpy_str(my_symbol->fgcolour, ARRAY_SIZE(my_symbol->fgcolour), optarg); break; case OPT_FILETYPE: /* Select the type of output file */ if (supported_filetype(optarg, no_png, &png_refused)) { - strncpy(filetype, optarg, (size_t) 3); + ncpy_str(filetype, ARRAY_SIZE(filetype), optarg, 3); } else { if (png_refused) { fprintf(stderr, "Warning 152: PNG format disabled at compile time, ignoring\n"); @@ -1781,7 +1795,7 @@ int main(int argc, char **argv) { } break; case OPT_NOBACKGROUND: - strcpy(my_symbol->bgcolour, "ffffff00"); + cpy_str(my_symbol->bgcolour, ARRAY_SIZE(my_symbol->bgcolour), "ffffff00"); break; case OPT_NOQUIETZONES: my_symbol->output_options |= BARCODE_NO_QUIET_ZONES; @@ -1790,12 +1804,11 @@ int main(int argc, char **argv) { my_symbol->show_hrt = 0; break; case OPT_PRIMARY: - if (strlen(optarg) <= 127) { - strcpy(my_symbol->primary, optarg); - } else { - strncpy(my_symbol->primary, optarg, 127); + cpy_str(my_symbol->primary, ARRAY_SIZE(my_symbol->primary), optarg); + if (strlen(optarg) >= ARRAY_SIZE(my_symbol->primary)) { fprintf(stderr, - "Warning 115: Primary data string too long (127 character maximum), truncating\n"); + "Warning 115: Primary data string too long (%d character maximum), truncating\n", + ARRAY_SIZE(my_symbol->primary) - 1); fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; } @@ -2065,13 +2078,13 @@ int main(int argc, char **argv) { break; case 'o': - strncpy(my_symbol->outfile, optarg, 255); + cpy_str(my_symbol->outfile, ARRAY_SIZE(my_symbol->outfile), optarg); output_given = 1; break; case 'r': - strcpy(my_symbol->fgcolour, "ffffff"); - strcpy(my_symbol->bgcolour, "000000"); + cpy_str(my_symbol->fgcolour, ARRAY_SIZE(my_symbol->fgcolour), "ffffff"); + cpy_str(my_symbol->bgcolour, ARRAY_SIZE(my_symbol->bgcolour), "000000"); break; case '?': @@ -2157,10 +2170,10 @@ int main(int argc, char **argv) { } if (filetype[0] == '\0') { outfile_extension = get_extension(my_symbol->outfile); - if (outfile_extension && supported_filetype(outfile_extension, no_png, NULL)) { - strcpy(filetype, outfile_extension); + if (outfile_extension && supported_filetype(outfile_extension, no_png, NULL /*png_refused*/)) { + cpy_str(filetype, ARRAY_SIZE(filetype), outfile_extension); } else { - strcpy(filetype, no_png ? "gif" : "png"); + cpy_str(filetype, ARRAY_SIZE(filetype), no_png ? "gif" : "png"); } } if (dpmm) { /* Allow `x_dim_mm` to be zero */ diff --git a/frontend_qt/CMakeLists.txt b/frontend_qt/CMakeLists.txt index 2a147b64..b5e7ca76 100644 --- a/frontend_qt/CMakeLists.txt +++ b/frontend_qt/CMakeLists.txt @@ -19,11 +19,11 @@ else() qt5_wrap_ui(zint-qt_SRCS mainWindow.ui extCLI.ui extData.ui extScale.ui extSequence.ui extExport.ui) endif() -# grpAztec.ui grpC39.ui grpCodablockF.ui grpDotCode.ui grpMailmark2D.ui grpPDF417.ui grpUPCA.ui -# grpC11.ui grpC49.ui grpCodeOne.ui grpDPD.ui grpMaxicode.ui grpPZN.ui grpUPCEAN.ui -# grpC128.ui grpC93.ui grpDAFT.ui grpGrid.ui grpMicroPDF.ui grpQR.ui grpUPNQR.ui -# grpC16k.ui grpChannel.ui grpDBExtend.ui grpHX.ui grpMQR.ui grpRMQR.ui grpVIN.ui -# grpC25.ui grpCodabar.ui grpDM.ui grpITF14.ui grpMSICheck.ui grpUltra.ui +# grpAztec.ui grpC39.ui grpCodablockF.ui grpDotCode.ui grpMailmark2D.ui grpPDF417.ui grpUltra.ui +# grpC11.ui grpC49.ui grpCodeOne.ui grpDPD.ui grpMaxicode.ui grpPlessey.ui grpUPCA.ui +# grpC128.ui grpC93.ui grpDAFT.ui grpGrid.ui grpMicroPDF.ui grpPZN.ui grpUPCEAN.ui +# grpC16k.ui grpChannel.ui grpDBExtend.ui grpHX.ui grpMQR.ui grpQR.ui grpUPNQR.ui +# grpC25.ui grpCodabar.ui grpDM.ui grpITF14.ui grpMSICheck.ui grpRMQR.ui grpVIN.ui if(APPLE) # https://doc.qt.io/qt-5/appicon.html diff --git a/frontend_qt/frontend_qt.pro b/frontend_qt/frontend_qt.pro index 18aeb594..f6011354 100644 --- a/frontend_qt/frontend_qt.pro +++ b/frontend_qt/frontend_qt.pro @@ -52,6 +52,7 @@ FORMS += extCLI.ui \ grpMQR.ui \ grpMSICheck.ui \ grpPDF417.ui \ + grpPlessey.ui \ grpPZN.ui \ grpQR.ui \ grpRMQR.ui \ diff --git a/frontend_qt/frontend_qt_zintdll.pro b/frontend_qt/frontend_qt_zintdll.pro index f4ac2dbe..0e7803b1 100644 --- a/frontend_qt/frontend_qt_zintdll.pro +++ b/frontend_qt/frontend_qt_zintdll.pro @@ -44,6 +44,7 @@ FORMS += extCLI.ui \ grpMQR.ui \ grpMSICheck.ui \ grpPDF417.ui \ + grpPlessey.ui \ grpPZN.ui \ grpQR.ui \ grpRMQR.ui \ diff --git a/frontend_qt/grpPlessey.ui b/frontend_qt/grpPlessey.ui new file mode 100644 index 00000000..ae4095a3 --- /dev/null +++ b/frontend_qt/grpPlessey.ui @@ -0,0 +1,50 @@ + + + grpPlessey + + + + 0 + 0 + 254 + 131 + + + + Form + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Show Chec&k Characters in Text + + + Display the 2 check characters in +the Human Readable Text + + + false + + + + + + + + diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index ea7e47bf..c70715db 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -2206,6 +2206,17 @@ void MainWindow::change_options() connect(m_btnHeightPerRowDisable, SIGNAL(clicked(bool)), SLOT(height_per_row_disable())); connect(m_btnHeightPerRowDefault, SIGNAL(clicked(bool)), SLOT(height_per_row_default())); + } else if (symbology == BARCODE_PLESSEY) { + QFile file(QSL(":/grpPlessey.ui")); + if (file.open(QIODevice::ReadOnly)) { + m_optionWidget = uiload.load(&file); + file.close(); + load_sub_settings(settings, symbology); + vLayoutSpecific->addWidget(m_optionWidget); + grpSpecific->show(); + connect(get_widget(QSL("chkPlesseyShowChecks")), SIGNAL(toggled(bool)), SLOT(update_preview())); + } + } else if (symbology == BARCODE_ULTRA) { QFile file(QSL(":/grpUltra.ui")); if (!file.open(QIODevice::ReadOnly)) @@ -3239,6 +3250,13 @@ void MainWindow::update_preview() } break; + case BARCODE_PLESSEY: + m_bc.bc.setSymbol(BARCODE_PLESSEY); + if (get_chk_val(QSL("chkPlesseyShowChecks"))) { + m_bc.bc.setOption2(1); + } + break; + case BARCODE_ULTRA: m_bc.bc.setSymbol(BARCODE_ULTRA); if (get_rad_val(QSL("radUltraEcc"))) @@ -4385,6 +4403,10 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) settings.setValue(QSL("studio/bc/dbar_expstk/height_per_row"), get_dspn_val(QSL("spnDBESHeightPerRow"))); break; + case BARCODE_PLESSEY: + settings.setValue(QSL("studio/bc/plessey/chk_show_checks"), get_chk_val(QSL("chkPlesseyShowChecks"))); + break; + case BARCODE_ULTRA: settings.setValue(QSL("studio/bc/ultra/autoresizing"), get_rad_grp_index( QStringList() << QSL("radUltraAuto") << QSL("radUltraEcc"))); @@ -4824,6 +4846,10 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) 0.0f); break; + case BARCODE_PLESSEY: + set_chk_from_setting(settings, QSL("studio/bc/plessey/chk_show_checks"), QSL("chkPlesseyShowChecks")); + break; + case BARCODE_ULTRA: set_rad_from_setting(settings, QSL("studio/bc/ultra/autoresizing"), QStringList() << QSL("radUltraAuto") << QSL("radUltraEcc")); diff --git a/frontend_qt/resources.qrc b/frontend_qt/resources.qrc index bd791cc0..dacdb75e 100644 --- a/frontend_qt/resources.qrc +++ b/frontend_qt/resources.qrc @@ -26,6 +26,7 @@ grpMQR.ui grpMSICheck.ui grpPDF417.ui + grpPlessey.ui grpPZN.ui grpQR.ui grpRMQR.ui
    Table : Royal Mail 4-State Mailmark Input Fields