diff --git a/CMakeLists.txt b/CMakeLists.txt index ad8e2980..c598c6b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,6 +18,7 @@ add_definitions(-DZINT_VERSION=\"${ZINT_VERSION}\") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") option(ZINT_DEBUG "Set debug compile flags" OFF) +option(ZINT_NOOPT "Set no optimize compile flags" OFF) option(ZINT_SANITIZE "Set sanitize compile/link flags" OFF) option(ZINT_TEST "Set test compile flag" OFF) option(ZINT_COVERAGE "Set code coverage flags" OFF) @@ -52,32 +53,15 @@ if(ZINT_DEBUG) if(CXX_COMPILER_FLAG_G) add_compile_options("-g") endif() +endif() +if(ZINT_NOOPT) check_cxx_compiler_flag("-O0" CXX_COMPILER_FLAG_O0) if(CXX_COMPILER_FLAG_O0) add_compile_options("-O0") endif() endif() -if(ZINT_TEST) - enable_testing() -endif() - -if(ZINT_COVERAGE) - set(CMAKE_REQUIRED_LIBRARIES -fprofile-arcs) - check_cxx_compiler_flag(--coverage CXX_COMPILER_FLAG_COVERAGE) - unset(CMAKE_REQUIRED_LIBRARIES) - if(CXX_COMPILER_FLAG_COVERAGE) - add_compile_options(--coverage) - link_libraries(-fprofile-arcs) - - check_cxx_compiler_flag(-O0 CXX_COMPILER_FLAG_O0) - if(CXX_COMPILER_FLAG_O0) - add_compile_options(-O0) - endif() - endif() -endif() - if(ZINT_SANITIZE) if(MSVC) if(MSVC_VERSION GREATER_EQUAL 1920) @@ -105,6 +89,25 @@ if(ZINT_SANITIZE) endif() endif() +if(ZINT_TEST) + enable_testing() +endif() + +if(ZINT_COVERAGE) + set(CMAKE_REQUIRED_LIBRARIES -fprofile-arcs) + check_cxx_compiler_flag(--coverage CXX_COMPILER_FLAG_COVERAGE) + unset(CMAKE_REQUIRED_LIBRARIES) + if(CXX_COMPILER_FLAG_COVERAGE) + add_compile_options(--coverage) + link_libraries(-fprofile-arcs) + + check_cxx_compiler_flag(-O0 CXX_COMPILER_FLAG_O0) + if(CXX_COMPILER_FLAG_O0) + add_compile_options(-O0) + endif() + endif() +endif() + if(APPLE) if(UNIVERSAL) # TODO: make universal binary if(NOT ZINT_HAS_BEEN_RUN_BEFORE) diff --git a/ChangeLog b/ChangeLog index b9020712..73d60fe9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,8 @@ Version 2.10.0.9 (dev) not released yet NOTE: will return error if values outside ranges - raster.c: Bug fix for heap-buffer-overflow (#204 ARM-Cortex) NOTE: may cause single-pixel changes to height depending on height/scale used +- JAPANPOST: return error if input data would be truncated + NOTE: previously was silently truncated Changes ------- @@ -31,6 +33,8 @@ Changes - GUI: add Menu, copy to clipboard EMF/GIF/PNG/TIF, errtxt bar and status bar, icons (feathericons) - CODABAR: add show check digit option +- DAFT: max chars 50 -> 100 +- CMake: separate no-optimize from ZINT_DEBUG into new ZINT_NOOPT option Bugs ---- @@ -43,7 +47,7 @@ Bugs also ceilf(large_bar_height * si); also avoid distributive multiplication with floats to lessen chances of platform variation (#204 ARM-Cortex crash) -- raster/vector.c: use new stripf() func to workaround gcc 32-bit +- common/emf/output/raster/vector.c: use new stripf() func to workaround float variations - raster.c: Don't add height offset for text if scale < 1.0 (as won't print) - ISBNX: fix not returning error number (warning) correctly diff --git a/backend/2of5.c b/backend/2of5.c index 64d6aa84..2873038d 100644 --- a/backend/2of5.c +++ b/backend/2of5.c @@ -35,38 +35,42 @@ #include "common.h" #include "gs1.h" -static const char *C25MatrixTable[10] = { - "113311", "311131", "131131", "331111", "113131", - "313111", "133111", "111331", "311311", "131311" +static const char C25MatrixTable[10][6] = { + {'1','1','3','3','1','1'}, {'3','1','1','1','3','1'}, {'1','3','1','1','3','1'}, {'3','3','1','1','1','1'}, + {'1','1','3','1','3','1'}, {'3','1','3','1','1','1'}, {'1','3','3','1','1','1'}, {'1','1','1','3','3','1'}, + {'3','1','1','3','1','1'}, {'1','3','1','3','1','1'} }; +static const char C25IndustTable[10][10] = { + {'1','1','1','1','3','1','3','1','1','1'}, {'3','1','1','1','1','1','1','1','3','1'}, + {'1','1','3','1','1','1','1','1','3','1'}, {'3','1','3','1','1','1','1','1','1','1'}, + {'1','1','1','1','3','1','1','1','3','1'}, {'3','1','1','1','3','1','1','1','1','1'}, + {'1','1','3','1','3','1','1','1','1','1'}, {'1','1','1','1','1','1','3','1','3','1'}, + {'3','1','1','1','1','1','3','1','1','1'}, {'1','1','3','1','1','1','3','1','1','1'} +}; + +/* Note `c25_common()` assumes Stop string length one less than Start */ static const char *C25MatrixStartStop[2] = { "411111", "41111" }; - -static const char *C25IndustTable[10] = { - "1111313111", "3111111131", "1131111131", "3131111111", "1111311131", - "3111311111", "1131311111", "1111113131", "3111113111", "1131113111" -}; - static const char *C25IndustStartStop[2] = { "313111", "31113" }; - static const char *C25IataLogicStartStop[2] = { "1111", "311" }; -static const char *C25InterTable[10] = { - "11331", "31113", "13113", "33111", "11313", - "31311", "13311", "11133", "31131", "13131" +static const char C25InterTable[10][5] = { + {'1','1','3','3','1'}, {'3','1','1','1','3'}, {'1','3','1','1','3'}, {'3','3','1','1','1'}, {'1','1','3','1','3'}, + {'3','1','3','1','1'}, {'1','3','3','1','1'}, {'1','1','1','3','3'}, {'3','1','1','3','1'}, {'1','3','1','3','1'} }; -static char check_digit(const unsigned int count) { +static char c25_check_digit(const unsigned int count) { return itoc((10 - (count % 10)) % 10); } /* Common to Standard (Matrix), Industrial, IATA, and Data Logic */ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], int length, const int max, - const char *table[10], const char *start_stop[2], const int error_base) { + const int is_matrix, const char *start_stop[2], const int start_length, const int error_base) { int i; - char dest[512]; /* Largest destination 6 + (80 + 1) * 6 + 5 + 1 = 498 */ - unsigned char temp[80 + 1 + 1]; /* Largest maximum 80 */ + char dest[500]; /* Largest destination 6 + (80 + 1) * 6 + 5 + 1 = 498 */ + char *d = dest; + unsigned char temp[80 + 1 + 1]; /* Largest maximum 80 + optional check digit */ int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2; if (length > max) { @@ -74,7 +78,7 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], sprintf(symbol->errtxt, "%d: Input too long (%d character maximum)", error_base, max); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { /* errtxt 302: 304: 306: 308: */ sprintf(symbol->errtxt, "%d: Invalid character in data (digits only)", error_base + 1); return ZINT_ERROR_INVALID_DATA; @@ -88,17 +92,25 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], temp[++length] = '\0'; } - /* start character */ - strcpy(dest, start_stop[0]); + /* Start character */ + memcpy(d, start_stop[0], start_length); + d += start_length; - for (i = 0; i < length; i++) { - lookup(NEON, table, temp[i], dest); + if (is_matrix) { + for (i = 0; i < length; i++, d += 6) { + memcpy(d, C25MatrixTable[temp[i] - '0'], 6); + } + } else { + for (i = 0; i < length; i++, d += 10) { + memcpy(d, C25IndustTable[temp[i] - '0'], 10); + } } /* Stop character */ - strcat(dest, start_stop[1]); + memcpy(d, start_stop[1], start_length - 1); + d += start_length - 1; - expand(symbol, dest); + expand(symbol, dest, d - dest); ustrcpy(symbol->text, temp); if (symbol->option_2 == 2) { @@ -111,29 +123,30 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[], /* Code 2 of 5 Standard (Code 2 of 5 Matrix) */ INTERNAL int c25standard(struct zint_symbol *symbol, unsigned char source[], int length) { - return c25_common(symbol, source, length, 80, C25MatrixTable, C25MatrixStartStop, 301); + return c25_common(symbol, source, length, 80, 1 /*is_matrix*/, C25MatrixStartStop, 6, 301); } /* Code 2 of 5 Industrial */ INTERNAL int c25ind(struct zint_symbol *symbol, unsigned char source[], int length) { - return c25_common(symbol, source, length, 45, C25IndustTable, C25IndustStartStop, 303); + return c25_common(symbol, source, length, 45, 0 /*is_matrix*/, C25IndustStartStop, 6, 303); } /* Code 2 of 5 IATA */ INTERNAL int c25iata(struct zint_symbol *symbol, unsigned char source[], int length) { - return c25_common(symbol, source, length, 45, C25IndustTable, C25IataLogicStartStop, 305); + return c25_common(symbol, source, length, 45, 0 /*is_matrix*/, C25IataLogicStartStop, 4, 305); } /* Code 2 of 5 Data Logic */ INTERNAL int c25logic(struct zint_symbol *symbol, unsigned char source[], int length) { - return c25_common(symbol, source, length, 80, C25MatrixTable, C25IataLogicStartStop, 307); + return c25_common(symbol, source, length, 80, 1 /*is_matrix*/, C25IataLogicStartStop, 4, 307); } /* Common to Interleaved, ITF-14, DP Leitcode, DP Identcode */ -static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], int length, +static int c25_inter_common(struct zint_symbol *symbol, unsigned char source[], int length, const int dont_set_height) { int i, j, error_number = 0; - char bars[7], spaces[7], mixed[14], dest[512]; /* 4 + (90 + 2) * 5 + 3 + 1 = 468 */ + char dest[468]; /* 4 + (90 + 2) * 5 + 3 + 1 = 468 */ + char *d = dest; unsigned char temp[90 + 2 + 1]; int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2; @@ -141,7 +154,7 @@ static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], i strcpy(symbol->errtxt, "309: Input too long (90 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "310: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -163,31 +176,26 @@ static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], i } /* start character */ - strcpy(dest, "1111"); + memcpy(d, "1111", 4); + d += 4; for (i = 0; i < length; i += 2) { - int k = 0; - /* look up the bars and the spaces and put them in two strings */ - bars[0] = '\0'; - lookup(NEON, C25InterTable, temp[i], bars); - spaces[0] = '\0'; - lookup(NEON, C25InterTable, temp[i + 1], spaces); + /* look up the bars and the spaces */ + const char *const bars = C25InterTable[temp[i] - '0']; + const char *const spaces = C25InterTable[temp[i + 1] - '0']; /* then merge (interlace) the strings together */ - for (j = 0; j <= 4; j++) { - mixed[k] = bars[j]; - k++; - mixed[k] = spaces[j]; - k++; + for (j = 0; j < 5; j++) { + *d++ = bars[j]; + *d++ = spaces[j]; } - mixed[k] = '\0'; - strcat(dest, mixed); } /* Stop character */ - strcat(dest, "311"); + memcpy(d, "311", 3); + d += 3; - expand(symbol, dest); + expand(symbol, dest, d - dest); ustrcpy(symbol->text, temp); if (symbol->option_2 == 2) { @@ -219,7 +227,7 @@ static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], i /* Code 2 of 5 Interleaved ISO/IEC 16390:2007 */ INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length) { - return c25inter_common(symbol, source, length, 0 /*dont_set_height*/); + return c25_inter_common(symbol, source, length, 0 /*dont_set_height*/); } /* Interleaved 2-of-5 (ITF-14) */ @@ -232,7 +240,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "312: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -247,7 +255,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt /* Calculate the check digit - the same method used for EAN-13 */ localstr[13] = gs1_check_digit(localstr, 13); localstr[14] = '\0'; - error_number = c25inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); + error_number = c25_inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); ustrcpy(symbol->text, localstr); if (!((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND))) { @@ -277,6 +285,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { int i, error_number; unsigned int count; + int factor; unsigned char localstr[16] = {0}; int zeroes; @@ -285,7 +294,7 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "313: Input wrong length (13 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "314: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -295,16 +304,14 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng localstr[i] = '0'; ustrcpy(localstr + zeroes, source); + factor = 4; for (i = 12; i >= 0; i--) { - count += 4 * ctoi(localstr[i]); - - if (i & 1) { - count += 5 * ctoi(localstr[i]); - } + count += factor * ctoi(localstr[i]); + factor ^= 0x0D; /* Toggles 4 and 9 */ } - localstr[13] = check_digit(count); + localstr[13] = c25_check_digit(count); localstr[14] = '\0'; - error_number = c25inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); + error_number = c25_inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); ustrcpy(symbol->text, localstr); // TODO: Find documentation on BARCODE_DPLEIT dimensions/height @@ -316,6 +323,7 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { int i, error_number, zeroes; unsigned int count; + int factor; unsigned char localstr[16] = {0}; count = 0; @@ -323,7 +331,7 @@ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int len strcpy(symbol->errtxt, "315: Input wrong length (11 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "316: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -333,16 +341,14 @@ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int len localstr[i] = '0'; ustrcpy(localstr + zeroes, source); + factor = 4; for (i = 10; i >= 0; i--) { - count += 4 * ctoi(localstr[i]); - - if (i & 1) { - count += 5 * ctoi(localstr[i]); - } + count += factor * ctoi(localstr[i]); + factor ^= 0x0D; /* Toggles 4 and 9 */ } - localstr[11] = check_digit(count); + localstr[11] = c25_check_digit(count); localstr[12] = '\0'; - error_number = c25inter_common(symbol, localstr, 12, 1 /*dont_set_height*/); + error_number = c25_inter_common(symbol, localstr, 12, 1 /*dont_set_height*/); ustrcpy(symbol->text, localstr); // TODO: Find documentation on BARCODE_DPIDENT dimensions/height diff --git a/backend/auspost.c b/backend/auspost.c index f9a52d3f..b3225686 100644 --- a/backend/auspost.c +++ b/backend/auspost.c @@ -31,61 +31,74 @@ */ /* vim: set ts=4 sw=4 et : */ -#define GDSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" +static const char GDSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #"; +#define GDSET_F (IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F) -static const char *AusNTable[10] = { - "00", "01", "02", "10", "11", "12", "20", "21", "22", "30" +static const char AusNTable[10][2] = { + {'0','0'}, {'0','1'}, {'0','2'}, {'1','0'}, {'1','1'}, {'1','2'}, {'2','0'}, {'2','1'}, {'2','2'}, {'3','0'} }; -static const char *AusCTable[64] = { - "222", "300", "301", "302", "310", "311", "312", "320", "321", "322", - "000", "001", "002", "010", "011", "012", "020", "021", "022", "100", "101", "102", "110", - "111", "112", "120", "121", "122", "200", "201", "202", "210", "211", "212", "220", "221", - "023", "030", "031", "032", "033", "103", "113", "123", "130", "131", "132", "133", "203", - "213", "223", "230", "231", "232", "233", "303", "313", "323", "330", "331", "332", "333", - "003", "013" +static const char AusCTable[64][3] = { + {'2','2','2'}, {'3','0','0'}, {'3','0','1'}, {'3','0','2'}, {'3','1','0'}, {'3','1','1'}, + {'3','1','2'}, {'3','2','0'}, {'3','2','1'}, {'3','2','2'}, {'0','0','0'}, {'0','0','1'}, + {'0','0','2'}, {'0','1','0'}, {'0','1','1'}, {'0','1','2'}, {'0','2','0'}, {'0','2','1'}, + {'0','2','2'}, {'1','0','0'}, {'1','0','1'}, {'1','0','2'}, {'1','1','0'}, {'1','1','1'}, + {'1','1','2'}, {'1','2','0'}, {'1','2','1'}, {'1','2','2'}, {'2','0','0'}, {'2','0','1'}, + {'2','0','2'}, {'2','1','0'}, {'2','1','1'}, {'2','1','2'}, {'2','2','0'}, {'2','2','1'}, + {'0','2','3'}, {'0','3','0'}, {'0','3','1'}, {'0','3','2'}, {'0','3','3'}, {'1','0','3'}, + {'1','1','3'}, {'1','2','3'}, {'1','3','0'}, {'1','3','1'}, {'1','3','2'}, {'1','3','3'}, + {'2','0','3'}, {'2','1','3'}, {'2','2','3'}, {'2','3','0'}, {'2','3','1'}, {'2','3','2'}, + {'2','3','3'}, {'3','0','3'}, {'3','1','3'}, {'3','2','3'}, {'3','3','0'}, {'3','3','1'}, + {'3','3','2'}, {'3','3','3'}, {'0','0','3'}, {'0','1','3'} }; -static const char *AusBarTable[64] = { - "000", "001", "002", "003", "010", "011", "012", "013", "020", "021", - "022", "023", "030", "031", "032", "033", "100", "101", "102", "103", "110", "111", "112", - "113", "120", "121", "122", "123", "130", "131", "132", "133", "200", "201", "202", "203", - "210", "211", "212", "213", "220", "221", "222", "223", "230", "231", "232", "233", "300", - "301", "302", "303", "310", "311", "312", "313", "320", "321", "322", "323", "330", "331", - "332", "333" +static const char AusBarTable[64][3] = { + {'0','0','0'}, {'0','0','1'}, {'0','0','2'}, {'0','0','3'}, {'0','1','0'}, {'0','1','1'}, + {'0','1','2'}, {'0','1','3'}, {'0','2','0'}, {'0','2','1'}, {'0','2','2'}, {'0','2','3'}, + {'0','3','0'}, {'0','3','1'}, {'0','3','2'}, {'0','3','3'}, {'1','0','0'}, {'1','0','1'}, + {'1','0','2'}, {'1','0','3'}, {'1','1','0'}, {'1','1','1'}, {'1','1','2'}, {'1','1','3'}, + {'1','2','0'}, {'1','2','1'}, {'1','2','2'}, {'1','2','3'}, {'1','3','0'}, {'1','3','1'}, + {'1','3','2'}, {'1','3','3'}, {'2','0','0'}, {'2','0','1'}, {'2','0','2'}, {'2','0','3'}, + {'2','1','0'}, {'2','1','1'}, {'2','1','2'}, {'2','1','3'}, {'2','2','0'}, {'2','2','1'}, + {'2','2','2'}, {'2','2','3'}, {'2','3','0'}, {'2','3','1'}, {'2','3','2'}, {'2','3','3'}, + {'3','0','0'}, {'3','0','1'}, {'3','0','2'}, {'3','0','3'}, {'3','1','0'}, {'3','1','1'}, + {'3','1','2'}, {'3','1','3'}, {'3','2','0'}, {'3','2','1'}, {'3','2','2'}, {'3','2','3'}, + {'3','3','0'}, {'3','3','1'}, {'3','3','2'}, {'3','3','3'} }; #include #include "common.h" #include "reedsol.h" -static char convert_pattern(char data, int shift) { +static char aus_convert_pattern(char data, int shift) { return (data - '0') << shift; } /* Adds Reed-Solomon error correction to auspost */ -static void rs_error(char data_pattern[]) { - int reader, len, triple_writer = 0; +static char *aus_rs_error(char data_pattern[], char *d) { + int reader, length, triple_writer = 0; unsigned char triple[31]; unsigned char result[5]; rs_t rs; - for (reader = 2, len = (int) strlen(data_pattern); reader < len; reader += 3, triple_writer++) { - triple[triple_writer] = convert_pattern(data_pattern[reader], 4) - + convert_pattern(data_pattern[reader + 1], 2) - + convert_pattern(data_pattern[reader + 2], 0); + for (reader = 2, length = d - data_pattern; reader < length; reader += 3, triple_writer++) { + triple[triple_writer] = aus_convert_pattern(data_pattern[reader], 4) + + aus_convert_pattern(data_pattern[reader + 1], 2) + + aus_convert_pattern(data_pattern[reader + 2], 0); } rs_init_gf(&rs, 0x43); rs_init_code(&rs, 4, 1); rs_encode(&rs, triple_writer, triple, result); - for (reader = 4; reader > 0; reader--) { - strcat(data_pattern, AusBarTable[(int) result[reader - 1]]); + for (reader = 4; reader > 0; reader--, d += 3) { + memcpy(d, AusBarTable[(int) result[reader - 1]], 3); } + + return d; } -INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height); +INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height); /* Handles Australia Posts's 4 State Codes */ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length) { @@ -104,17 +117,29 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len int h; char data_pattern[200]; - char fcc[3] = {0, 0, 0}, dpid[10]; + char *d = data_pattern; + char fcc[3] = {0}, dpid[10]; char localstr[30]; + /* Do all of the length checking first to avoid stack smashing */ + if (symbol->symbology == BARCODE_AUSPOST) { + if (length != 8 && length != 13 && length != 16 && length != 18 && length != 23) { + strcpy(symbol->errtxt, "401: Auspost input is wrong length (8, 13, 16, 18 or 23 characters only)"); + return ZINT_ERROR_TOO_LONG; + } + } else if (length > 8) { + strcpy(symbol->errtxt, "403: Auspost input is too long (8 character maximum)"); + return ZINT_ERROR_TOO_LONG; + } + /* Check input immediately to catch nuls */ - if (is_sane(GDSET, source, length) != 0) { + if (!is_sane(GDSET_F, source, length)) { strcpy(symbol->errtxt, "404: Invalid character in data (alphanumerics, space and \"#\" only)"); return ZINT_ERROR_INVALID_DATA; } - strcpy(localstr, ""); - /* Do all of the length checking first to avoid stack smashing */ + localstr[0] = '\0'; + if (symbol->symbology == BARCODE_AUSPOST) { /* Format control code (FCC) */ switch (length) { @@ -126,7 +151,7 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len break; case 16: strcpy(fcc, "59"); - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "402: Invalid character in data (digits only for length 16)"); return ZINT_ERROR_INVALID_DATA; } @@ -136,21 +161,14 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len break; case 23: strcpy(fcc, "62"); - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "406: Invalid character in data (digits only for length 23)"); return ZINT_ERROR_INVALID_DATA; } break; - default: - strcpy(symbol->errtxt, "401: Auspost input is wrong length (8, 13, 16, 18 or 23 characters only)"); - return ZINT_ERROR_TOO_LONG; } } else { int zeroes; - if (length > 8) { - strcpy(symbol->errtxt, "403: Auspost input is too long (8 character maximum)"); - return ZINT_ERROR_TOO_LONG; - } switch (symbol->symbology) { case BARCODE_AUSREPLY: strcpy(fcc, "45"); break; @@ -175,58 +193,60 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len /* Verify that the first 8 characters are numbers */ memcpy(dpid, localstr, 8); dpid[8] = '\0'; - if (is_sane(NEON, (unsigned char *) dpid, 8) != 0) { + if (!is_sane(NEON_F, (unsigned char *) dpid, 8)) { strcpy(symbol->errtxt, "405: Invalid character in DPID (first 8 characters) (digits only)"); return ZINT_ERROR_INVALID_DATA; } /* Start character */ - strcpy(data_pattern, "13"); + memcpy(d, "13", 2); + d += 2; /* Encode the FCC */ - for (reader = 0; reader < 2; reader++) { - lookup(NEON, AusNTable, fcc[reader], data_pattern); + for (reader = 0; reader < 2; reader++, d += 2) { + memcpy(d, AusNTable[fcc[reader] - '0'], 2); } /* Delivery Point Identifier (DPID) */ - for (reader = 0; reader < 8; reader++) { - lookup(NEON, AusNTable, dpid[reader], data_pattern); + for (reader = 0; reader < 8; reader++, d += 2) { + memcpy(d, AusNTable[dpid[reader] - '0'], 2); } /* Customer Information */ if (h > 8) { if ((h == 13) || (h == 18)) { - for (reader = 8; reader < h; reader++) { - lookup(GDSET, AusCTable, localstr[reader], data_pattern); + for (reader = 8; reader < h; reader++, d += 3) { + memcpy(d, AusCTable[posn(GDSET, localstr[reader])], 3); } } else if ((h == 16) || (h == 23)) { - for (reader = 8; reader < h; reader++) { - lookup(NEON, AusNTable, localstr[reader], data_pattern); + for (reader = 8; reader < h; reader++, d += 2) { + memcpy(d, AusNTable[localstr[reader] - '0'], 2); } } } /* Filler bar */ - h = (int) strlen(data_pattern); + h = d - data_pattern; switch (h) { case 22: case 37: case 52: - strcat(data_pattern, "3"); + *d++ = '3'; break; default: break; } /* Reed Solomon error correction */ - rs_error(data_pattern); + d = aus_rs_error(data_pattern, d); /* Stop character */ - strcat(data_pattern, "13"); + memcpy(d, "13", 2); + d += 2; /* Turn the symbol into a bar pattern ready for plotting */ writer = 0; - h = (int) strlen(data_pattern); + h = d - data_pattern; for (loopey = 0; loopey < h; loopey++) { if ((data_pattern[loopey] == '1') || (data_pattern[loopey] == '0')) { set_module(symbol, 0, writer); diff --git a/backend/aztec.c b/backend/aztec.c index 9bfdd244..7161864f 100644 --- a/backend/aztec.c +++ b/backend/aztec.c @@ -1447,7 +1447,7 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int lengt /* Encodes Aztec runes as specified in ISO/IEC 24778:2008 Annex A */ INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int length) { unsigned int input_value; - int error_number, i, y, x, r; + int i, y, x, r; char binary_string[28]; unsigned char data_codewords[3], ecc_codewords[6]; int bp = 0; @@ -1459,8 +1459,7 @@ INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "507: Input too large (3 character maximum)"); return ZINT_ERROR_TOO_LONG; } - error_number = is_sane(NEON, source, length); - if (error_number != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "508: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } diff --git a/backend/codablock.c b/backend/codablock.c index f16c1d27..940b52c4 100644 --- a/backend/codablock.c +++ b/backend/codablock.c @@ -38,8 +38,7 @@ #endif #include #include "common.h" - -INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length); +#include "code128.h" #define uchar unsigned char @@ -65,23 +64,6 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len #define aCodeC (uchar)(134) #define aShift (uchar)(135) -static const char *C128Table[107] = { - /* Code 128 character encodation - Table 1 */ - "212222", "222122", "222221", "121223", "121322", "131222", "122213", - "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222", - "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222", - "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323", - "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133", - "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113", - "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111", - "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", - "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", - "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", - "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311", - "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232", - "2331112" -}; - /* Code F Analysing-Chart */ typedef struct sCharacterSetTable { @@ -953,11 +935,14 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int /* Paint the C128 patterns */ for (r = 0; r < rows; r++) { - strcpy(dest, ""); - for(c = 0; c < columns; c++) { - strcat(dest, C128Table[pOutput[r * columns + c]]); + const int rc = r * columns; + char *d = dest; + for (c = 0; c < columns - 1; c++, d += 6) { + memcpy(d, C128Table[pOutput[rc + c]], 6); } - expand(symbol, dest); + memcpy(d, "2331112", 7); /* Stop character (106, not in C128Table) */ + d += 7; + expand(symbol, dest, d - dest); } if (symbol->output_options & COMPLIANT_HEIGHT) { diff --git a/backend/code.c b/backend/code.c index f05cf163..26157419 100644 --- a/backend/code.c +++ b/backend/code.c @@ -1,8 +1,4 @@ /* code.c - Handles Code 11, 39, 39+, 93, PZN, Channel and VIN */ -/* LOGMARS MIL-STD-1189 Rev. B https://apps.dtic.mil/dtic/tr/fulltext/u2/a473534.pdf */ -/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf */ -/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/ - IFA-Info_Check_Digit_Calculations_PZN_PPN_UDI_EN.pdf */ /* libzint - the open source barcode library @@ -41,61 +37,95 @@ #include #include "common.h" -#define SODIUM "0123456789-" -#define SILVER "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd" -#define ARSENIC "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" +#define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */ -static const char *C11Table[11] = { - "111121", "211121", "121121", "221111", "112121", "212111", "122111", - "111221", "211211", "211111", "112111" +/* Same as TECHNETIUM (HIBC) with "abcd" added for CODE93 */ +static const char SILVER[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd"; + +#define ARSENIC_F (IS_NUM_F | IS_ARS_F) /* ARSENIC "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" */ + +static const char C11Table[11][6] = { + {'1','1','1','1','2','1'}, {'2','1','1','1','2','1'}, {'1','2','1','1','2','1'}, {'2','2','1','1','1','1'}, + {'1','1','2','1','2','1'}, {'2','1','2','1','1','1'}, {'1','2','2','1','1','1'}, {'1','1','1','2','2','1'}, + {'2','1','1','2','1','1'}, {'2','1','1','1','1','1'}, {'1','1','2','1','1','1'} }; /* Code 39 tables checked against ISO/IEC 16388:2007 */ /* Incorporates Table A1 */ -static const char *C39Table[43] = { +static const char C39Table[43][10] = { /* Code 39 character assignments (Table 1) */ - "1112212111", "2112111121", "1122111121", "2122111111", "1112211121", - "2112211111", "1122211111", "1112112121", "2112112111", "1122112111", "2111121121", - "1121121121", "2121121111", "1111221121", "2111221111", "1121221111", "1111122121", - "2111122111", "1121122111", "1111222111", "2111111221", "1121111221", "2121111211", - "1111211221", "2111211211", "1121211211", "1111112221", "2111112211", "1121112211", - "1111212211", "2211111121", "1221111121", "2221111111", "1211211121", "2211211111", - "1221211111", "1211112121", "2211112111", "1221112111", "1212121111", "1212111211", - "1211121211", "1112121211" + {'1','1','1','2','2','1','2','1','1','1'}, {'2','1','1','2','1','1','1','1','2','1'}, + {'1','1','2','2','1','1','1','1','2','1'}, {'2','1','2','2','1','1','1','1','1','1'}, + {'1','1','1','2','2','1','1','1','2','1'}, {'2','1','1','2','2','1','1','1','1','1'}, + {'1','1','2','2','2','1','1','1','1','1'}, {'1','1','1','2','1','1','2','1','2','1'}, + {'2','1','1','2','1','1','2','1','1','1'}, {'1','1','2','2','1','1','2','1','1','1'}, + {'2','1','1','1','1','2','1','1','2','1'}, {'1','1','2','1','1','2','1','1','2','1'}, + {'2','1','2','1','1','2','1','1','1','1'}, {'1','1','1','1','2','2','1','1','2','1'}, + {'2','1','1','1','2','2','1','1','1','1'}, {'1','1','2','1','2','2','1','1','1','1'}, + {'1','1','1','1','1','2','2','1','2','1'}, {'2','1','1','1','1','2','2','1','1','1'}, + {'1','1','2','1','1','2','2','1','1','1'}, {'1','1','1','1','2','2','2','1','1','1'}, + {'2','1','1','1','1','1','1','2','2','1'}, {'1','1','2','1','1','1','1','2','2','1'}, + {'2','1','2','1','1','1','1','2','1','1'}, {'1','1','1','1','2','1','1','2','2','1'}, + {'2','1','1','1','2','1','1','2','1','1'}, {'1','1','2','1','2','1','1','2','1','1'}, + {'1','1','1','1','1','1','2','2','2','1'}, {'2','1','1','1','1','1','2','2','1','1'}, + {'1','1','2','1','1','1','2','2','1','1'}, {'1','1','1','1','2','1','2','2','1','1'}, + {'2','2','1','1','1','1','1','1','2','1'}, {'1','2','2','1','1','1','1','1','2','1'}, + {'2','2','2','1','1','1','1','1','1','1'}, {'1','2','1','1','2','1','1','1','2','1'}, + {'2','2','1','1','2','1','1','1','1','1'}, {'1','2','2','1','2','1','1','1','1','1'}, + {'1','2','1','1','1','1','2','1','2','1'}, {'2','2','1','1','1','1','2','1','1','1'}, + {'1','2','2','1','1','1','2','1','1','1'}, {'1','2','1','2','1','2','1','1','1','1'}, + {'1','2','1','2','1','1','1','2','1','1'}, {'1','2','1','1','1','2','1','2','1','1'}, + {'1','1','1','2','1','2','1','2','1','1'} }; -static const char *EC39Ctrl[128] = { +static const char EC39Ctrl[128][2] = { /* Encoding the full ASCII character set in Code 39 (Table A2) */ - "%U", "$A", "$B", "$C", "$D", "$E", "$F", "$G", "$H", "$I", "$J", "$K", - "$L", "$M", "$N", "$O", "$P", "$Q", "$R", "$S", "$T", "$U", "$V", "$W", "$X", "$Y", "$Z", - "%A", "%B", "%C", "%D", "%E", " ", "/A", "/B", "/C", "/D", "/E", "/F", "/G", "/H", "/I", "/J", - "/K", "/L", "-", ".", "/O", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "/Z", "%F", - "%G", "%H", "%I", "%J", "%V", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "%K", "%L", "%M", "%N", "%O", - "%W", "+A", "+B", "+C", "+D", "+E", "+F", "+G", "+H", "+I", "+J", "+K", "+L", "+M", "+N", "+O", - "+P", "+Q", "+R", "+S", "+T", "+U", "+V", "+W", "+X", "+Y", "+Z", "%P", "%Q", "%R", "%S", "%T" + {'%','U'}, {'$','A'}, {'$','B'}, {'$','C'}, {'$','D'}, {'$','E'}, {'$','F'}, {'$','G'}, {'$','H'}, {'$','I'}, + {'$','J'}, {'$','K'}, {'$','L'}, {'$','M'}, {'$','N'}, {'$','O'}, {'$','P'}, {'$','Q'}, {'$','R'}, {'$','S'}, + {'$','T'}, {'$','U'}, {'$','V'}, {'$','W'}, {'$','X'}, {'$','Y'}, {'$','Z'}, {'%','A'}, {'%','B'}, {'%','C'}, + {'%','D'}, {'%','E'}, { " " }, {'/','A'}, {'/','B'}, {'/','C'}, {'/','D'}, {'/','E'}, {'/','F'}, {'/','G'}, + {'/','H'}, {'/','I'}, {'/','J'}, {'/','K'}, {'/','L'}, { "-" }, { "." }, {'/','O'}, { "0" }, { "1" }, + { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" }, { "8" }, { "9" }, {'/','Z'}, {'%','F'}, + {'%','G'}, {'%','H'}, {'%','I'}, {'%','J'}, {'%','V'}, { "A" }, { "B" }, { "C" }, { "D" }, { "E" }, + { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" }, + { "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" }, + { "Z" }, {'%','K'}, {'%','L'}, {'%','M'}, {'%','N'}, {'%','O'}, {'%','W'}, {'+','A'}, {'+','B'}, {'+','C'}, + {'+','D'}, {'+','E'}, {'+','F'}, {'+','G'}, {'+','H'}, {'+','I'}, {'+','J'}, {'+','K'}, {'+','L'}, {'+','M'}, + {'+','N'}, {'+','O'}, {'+','P'}, {'+','Q'}, {'+','R'}, {'+','S'}, {'+','T'}, {'+','U'}, {'+','V'}, {'+','W'}, + {'+','X'}, {'+','Y'}, {'+','Z'}, {'%','P'}, {'%','Q'}, {'%','R'}, {'%','S'}, {'%','T'} }; -static const char *C93Ctrl[128] = { - "bU", "aA", "aB", "aC", "aD", "aE", "aF", "aG", "aH", "aI", "aJ", "aK", - "aL", "aM", "aN", "aO", "aP", "aQ", "aR", "aS", "aT", "aU", "aV", "aW", "aX", "aY", "aZ", - "bA", "bB", "bC", "bD", "bE", " ", "cA", "cB", "cC", "$", "%", "cF", "cG", "cH", "cI", "cJ", - "+", "cL", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "cZ", "bF", - "bG", "bH", "bI", "bJ", "bV", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bK", "bL", "bM", "bN", "bO", - "bW", "dA", "dB", "dC", "dD", "dE", "dF", "dG", "dH", "dI", "dJ", "dK", "dL", "dM", "dN", "dO", - "dP", "dQ", "dR", "dS", "dT", "dU", "dV", "dW", "dX", "dY", "dZ", "bP", "bQ", "bR", "bS", "bT" +static const char C93Ctrl[128][2] = { + {'b','U'}, {'a','A'}, {'a','B'}, {'a','C'}, {'a','D'}, {'a','E'}, {'a','F'}, {'a','G'}, {'a','H'}, {'a','I'}, + {'a','J'}, {'a','K'}, {'a','L'}, {'a','M'}, {'a','N'}, {'a','O'}, {'a','P'}, {'a','Q'}, {'a','R'}, {'a','S'}, + {'a','T'}, {'a','U'}, {'a','V'}, {'a','W'}, {'a','X'}, {'a','Y'}, {'a','Z'}, {'b','A'}, {'b','B'}, {'b','C'}, + {'b','D'}, {'b','E'}, { " " }, {'c','A'}, {'c','B'}, {'c','C'}, { "$" }, { "%" }, {'c','F'}, {'c','G'}, + {'c','H'}, {'c','I'}, {'c','J'}, { "+" }, {'c','L'}, { "-" }, { "." }, { "/" }, { "0" }, { "1" }, + { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" }, { "8" }, { "9" }, {'c','Z'}, {'b','F'}, + {'b','G'}, {'b','H'}, {'b','I'}, {'b','J'}, {'b','V'}, { "A" }, { "B" }, { "C" }, { "D" }, { "E" }, + { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" }, + { "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" }, + { "Z" }, {'b','K'}, {'b','L'}, {'b','M'}, {'b','N'}, {'b','O'}, {'b','W'}, {'d','A'}, {'d','B'}, {'d','C'}, + {'d','D'}, {'d','E'}, {'d','F'}, {'d','G'}, {'d','H'}, {'d','I'}, {'d','J'}, {'d','K'}, {'d','L'}, {'d','M'}, + {'d','N'}, {'d','O'}, {'d','P'}, {'d','Q'}, {'d','R'}, {'d','S'}, {'d','T'}, {'d','U'}, {'d','V'}, {'d','W'}, + {'d','X'}, {'d','Y'}, {'d','Z'}, {'b','P'}, {'b','Q'}, {'b','R'}, {'b','S'}, {'b','T'} }; -static const char *C93Table[47] = { - "131112", "111213", "111312", "111411", "121113", "121212", "121311", - "111114", "131211", "141111", "211113", "211212", "211311", "221112", "221211", "231111", - "112113", "112212", "112311", "122112", "132111", "111123", "111222", "111321", "121122", - "131121", "212112", "212211", "211122", "211221", "221121", "222111", "112122", "112221", - "122121", "123111", "121131", "311112", "311211", "321111", "112131", "113121", "211131", - "121221", "312111", "311121", "122211" +static const char C93Table[47][6] = { + {'1','3','1','1','1','2'}, {'1','1','1','2','1','3'}, {'1','1','1','3','1','2'}, {'1','1','1','4','1','1'}, + {'1','2','1','1','1','3'}, {'1','2','1','2','1','2'}, {'1','2','1','3','1','1'}, {'1','1','1','1','1','4'}, + {'1','3','1','2','1','1'}, {'1','4','1','1','1','1'}, {'2','1','1','1','1','3'}, {'2','1','1','2','1','2'}, + {'2','1','1','3','1','1'}, {'2','2','1','1','1','2'}, {'2','2','1','2','1','1'}, {'2','3','1','1','1','1'}, + {'1','1','2','1','1','3'}, {'1','1','2','2','1','2'}, {'1','1','2','3','1','1'}, {'1','2','2','1','1','2'}, + {'1','3','2','1','1','1'}, {'1','1','1','1','2','3'}, {'1','1','1','2','2','2'}, {'1','1','1','3','2','1'}, + {'1','2','1','1','2','2'}, {'1','3','1','1','2','1'}, {'2','1','2','1','1','2'}, {'2','1','2','2','1','1'}, + {'2','1','1','1','2','2'}, {'2','1','1','2','2','1'}, {'2','2','1','1','2','1'}, {'2','2','2','1','1','1'}, + {'1','1','2','1','2','2'}, {'1','1','2','2','2','1'}, {'1','2','2','1','2','1'}, {'1','2','3','1','1','1'}, + {'1','2','1','1','3','1'}, {'3','1','1','1','1','2'}, {'3','1','1','2','1','1'}, {'3','2','1','1','1','1'}, + {'1','1','2','1','3','1'}, {'1','1','3','1','2','1'}, {'2','1','1','1','3','1'}, {'1','2','1','2','2','1'}, + {'3','1','2','1','1','1'}, {'3','1','1','1','2','1'}, {'1','2','2','2','1','1'} }; /* *********************** CODE 11 ******************** */ @@ -105,8 +135,10 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count; int weight[122], error_number = 0; char dest[750]; /* 6 + 121 * 6 + 2 * 6 + 5 + 1 == 750 */ - char checkstr[3]; + char *d = dest; int num_check_digits; + char checkstr[3] = {0}; + static char checkchrs[11] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' }; /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */ assert(length > 0); @@ -115,7 +147,7 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "320: Input too long (121 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(SODIUM, source, length) != 0) { + if (!is_sane(SODIUM_MNS_F, source, length)) { strcpy(symbol->errtxt, "321: Invalid character in data (digits and \"-\" only)"); return ZINT_ERROR_INVALID_DATA; } @@ -138,15 +170,16 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng k_count = 0; /* start character */ - strcpy(dest, "112211"); + memcpy(d, "112211", 6); + d += 6; /* Draw main body of barcode */ - for (i = 0; i < length; i++) { - lookup(SODIUM, C11Table, source[i], dest); + for (i = 0; i < length; i++, d += 6) { if (source[i] == '-') weight[i] = 10; else weight[i] = ctoi(source[i]); + memcpy(d, C11Table[weight[i]], 6); } if (num_check_digits) { @@ -161,14 +194,11 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng } c_digit = c_count % 11; - if (num_check_digits == 1) { - checkstr[0] = itoc(c_digit); - if (checkstr[0] == 'A') { - checkstr[0] = '-'; - } - checkstr[1] = '\0'; - lookup(SODIUM, C11Table, checkstr[0], dest); - } else { + checkstr[0] = checkchrs[c_digit]; + memcpy(d, C11Table[c_digit], 6); + d += 6; + + if (num_check_digits == 2) { weight[length] = c_digit; /* Calculate K checksum */ @@ -182,17 +212,9 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng } k_digit = k_count % 11; - checkstr[0] = itoc(c_digit); - checkstr[1] = itoc(k_digit); - if (checkstr[0] == 'A') { - checkstr[0] = '-'; - } - if (checkstr[1] == 'A') { - checkstr[1] = '-'; - } - checkstr[2] = '\0'; - lookup(SODIUM, C11Table, checkstr[0], dest); - lookup(SODIUM, C11Table, checkstr[1], dest); + checkstr[1] = checkchrs[k_digit]; + memcpy(d, C11Table[k_digit], 6); + d += 6; } } @@ -201,9 +223,10 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng } /* Stop character */ - strcat(dest, "11221"); + memcpy(d, "11221", 5); + d += 5; - expand(symbol, dest); + expand(symbol, dest, d - dest); // TODO: Find documentation on BARCODE_CODE11 dimensions/height @@ -219,7 +242,9 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng int i; int counter; int error_number = 0; + int posns[85]; char dest[880]; /* 10 (Start) + 85 * 10 + 10 (Check) + 9 (Stop) + 1 = 880 */ + char *d = dest; char localstr[2] = {0}; counter = 0; @@ -228,6 +253,7 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng symbol->option_2 = 0; } + /* LOGMARS MIL-STD-1189 Rev. B https://apps.dtic.mil/dtic/tr/fulltext/u2/a473534.pdf */ if ((symbol->symbology == BARCODE_LOGMARS) && (length > 30)) { /* MIL-STD-1189 Rev. B Section 5.2.6.2 */ strcpy(symbol->errtxt, "322: Input too long (30 character maximum)"); return ZINT_ERROR_TOO_LONG; @@ -240,18 +266,20 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "323: Input too long (85 character maximum)"); return ZINT_ERROR_TOO_LONG; } - to_upper(source); - if (is_sane(SILVER, source, length) != 0) { + + to_upper(source, length); + if (!is_sane_lookup(SILVER, 43, source, length, posns)) { strcpy(symbol->errtxt, "324: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)"); return ZINT_ERROR_INVALID_DATA; } /* Start character */ - strcpy(dest, "1211212111"); + memcpy(d, "1211212111", 10); + d += 10; - for (i = 0; i < length; i++) { - lookup(SILVER, C39Table, source[i], dest); - counter += posn(SILVER, source[i]); + for (i = 0; i < length; i++, d += 10) { + memcpy(d, C39Table[posns[i]], 10); + counter += posns[i]; } if (symbol->option_2 == 1) { @@ -259,7 +287,8 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng char check_digit; counter %= 43; check_digit = SILVER[counter]; - lookup(SILVER, C39Table, check_digit, dest); + memcpy(d, C39Table[counter], 10); + d += 10; /* Display a space check digit as _, otherwise it looks like an error */ if (check_digit == ' ') { @@ -271,11 +300,12 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng } /* Stop character */ - strcat(dest, "121121211"); + memcpy(d, "121121211", 9); + d += 9; if ((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_HIBC_39)) { /* LOGMARS uses wider 'wide' bars than normal Code 39 */ - counter = (int) strlen(dest); + counter = d - dest; for (i = 0; i < counter; i++) { if (dest[i] == '2') { dest[i] = '3'; @@ -283,11 +313,11 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng } } - if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Barspaces: %s\n", dest); - } + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Barspaces: %.*s\n", (int) (d - dest), dest); + } - expand(symbol, dest); + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->symbology == BARCODE_LOGMARS) { @@ -324,6 +354,9 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng } /* Pharmazentral Nummer (PZN) */ +/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf */ +/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/ + IFA-Info_Check_Digit_Calculations_PZN_PPN_UDI_EN.pdf */ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) { int i, error_number, zeroes; @@ -334,7 +367,7 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) strcpy(symbol->errtxt, "325: Input wrong length (7 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "326: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -387,6 +420,7 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int length) { unsigned char buffer[85 * 2 + 1] = {0}; + unsigned char *b = buffer; int i; int error_number; @@ -402,11 +436,17 @@ INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int le strcpy(symbol->errtxt, "329: Invalid character in data, extended ASCII not allowed"); return ZINT_ERROR_INVALID_DATA; } - ustrcat(buffer, EC39Ctrl[source[i]]); + memcpy(b, EC39Ctrl[source[i]], 2); + b += EC39Ctrl[source[i]][1] ? 2 : 1; } + if (b - buffer > 85) { + strcpy(symbol->errtxt, "317: Expanded input too long (85 symbol character maximum)"); + return ZINT_ERROR_TOO_LONG; + } + *b = '\0'; /* Then sends the buffer to the C39 function */ - error_number = code39(symbol, buffer, (int) ustrlen(buffer)); + error_number = code39(symbol, buffer, b - buffer); for (i = 0; i < length; i++) symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; @@ -424,10 +464,11 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng int i; int h, weight, c, k, error_number = 0; - int values[108]; /* 107 + 1 (1st check) */ + int values[110]; /* 107 + 2 (Checks) */ char buffer[216]; /* 107*2 (107 full ASCII) + 1 = 215 */ + char *b = buffer; char dest[668]; /* 6 (Start) + 107*6 + 2*6 (Checks) + 7 (Stop) + 1 (NUL) = 668 */ - char set_copy[] = SILVER; + char *d = dest; /* Suppresses clang-tidy clang-analyzer-core.CallAndMessage warning */ assert(length > 0); @@ -437,8 +478,6 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng return ZINT_ERROR_TOO_LONG; } - *buffer = '\0'; - /* Message Content */ for (i = 0; i < length; i++) { if (source[i] > 127) { @@ -446,14 +485,15 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "331: Invalid character in data, extended ASCII not allowed"); return ZINT_ERROR_INVALID_DATA; } - strcat(buffer, C93Ctrl[source[i]]); + 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 */ - h = (int) strlen(buffer); + h = b - buffer; if (h > 107) { - strcpy(symbol->errtxt, "332: Input too long (107 symbol character maximum)"); + strcpy(symbol->errtxt, "332: Expanded input too long (107 symbol character maximum)"); return ZINT_ERROR_TOO_LONG; } @@ -474,7 +514,6 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng } c = c % 47; values[h] = c; - buffer[h] = set_copy[c]; /* Check digit K */ k = 0; @@ -486,19 +525,26 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng weight = 1; } k = k % 47; - buffer[++h] = set_copy[k]; - buffer[++h] = '\0'; + values[h + 1] = k; + h += 2; + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Check digit c: %d, k: %d\n", c, k); + } /* Start character */ - strcpy(dest, "111141"); + memcpy(d, "111141", 6); + d += 6; - for (i = 0; i < h; i++) { - lookup(SILVER, C93Table, buffer[i], dest); + for (i = 0; i < h; i++, d += 6) { + memcpy(d, C93Table[values[i]], 6); } /* Stop character */ - strcat(dest, "1111411"); - expand(symbol, dest); + memcpy(d, "1111411", 7); + d += 7; + + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* ANSI/AIM BC5-1995 Section 2.6 minimum height 0.2" or 15% of symbol length, whichever is greater @@ -511,8 +557,8 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng } if (symbol->option_2 == 1) { - symbol->text[length] = set_copy[c]; - symbol->text[length + 1] = set_copy[k]; + symbol->text[length] = SILVER[c]; + symbol->text[length + 1] = SILVER[k]; symbol->text[length + 2] = '\0'; } @@ -658,16 +704,16 @@ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int len static int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 }; int S[8] = {0}, B[8] = {0}; long target_value = 0; - char pattern[30]; + char dest[30]; + char *d = dest; int channels, i; int error_number = 0, zeroes; - char hrt[9]; if (length > 7) { strcpy(symbol->errtxt, "333: Input too long (7 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "334: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -713,24 +759,23 @@ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int len CHNCHR(channels, target_value, B, S); - strcpy(pattern, "111111111"); /* Finder pattern */ + memcpy(d, "111111111", 9); /* Finder pattern */ + d += 9; for (i = 8 - channels; i < 8; i++) { - char part[3]; - part[0] = itoc(S[i]); - part[1] = itoc(B[i]); - part[2] = '\0'; - strcat(pattern, part); + *d++ = itoc(S[i]); + *d++ = itoc(B[i]); } zeroes = channels - 1 - length; if (zeroes < 0) { zeroes = 0; } - memset(hrt, '0', zeroes); - ustrcpy(hrt + zeroes, source); - ustrcpy(symbol->text, hrt); + if (zeroes) { + memset(symbol->text, '0', zeroes); + } + ustrcpy(symbol->text + zeroes, source); - expand(symbol, pattern); + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* ANSI/AIM BC12-1998 gives min height as 5mm or 15% of length; X left as application specification so use @@ -750,11 +795,10 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) /* This code verifies the check digit present in North American VIN codes */ - char local_source[18]; char dest[200]; /* 10 + 10 + 17 * 10 + 9 + 1 = 200 */ + char *d = dest; char input_check; char output_check; - int value[17]; int weight[17] = {8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2}; int sum; int i; @@ -766,34 +810,30 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) } // Check input characters, I, O and Q are not allowed - if (is_sane(ARSENIC, source, length) != 0) { - sprintf(symbol->errtxt, "337: Invalid character in data (\"%s\" only)", ARSENIC); + if (!is_sane(ARSENIC_F, source, length)) { + strcpy(symbol->errtxt, "337: Invalid character in data (alphanumerics only, excluding \"I\", \"O\" and \"Q\")"); return ZINT_ERROR_INVALID_DATA; } - ustrcpy(local_source, source); - - to_upper((unsigned char *) local_source); + to_upper(source, length); // Check digit only valid for North America - if (local_source[0] >= '1' && local_source[0] <= '5') { - input_check = local_source[8]; - - for (i = 0; i < 17; i++) { - if ((local_source[i] >= '0') && (local_source[i] <= '9')) { - value[i] = local_source[i] - '0'; - } else if ((local_source[i] >= 'A') && (local_source[i] <= 'I')) { - value[i] = (local_source[i] - 'A') + 1; - } else if ((local_source[i] >= 'J') && (local_source[i] <= 'R')) { - value[i] = (local_source[i] - 'J') + 1; - } else if ((local_source[i] >= 'S') && (local_source[i] <= 'Z')) { - value[i] = (local_source[i] - 'S') + 2; - } - } + if (source[0] >= '1' && source[0] <= '5') { + input_check = source[8]; sum = 0; for (i = 0; i < 17; i++) { - sum += value[i] * weight[i]; + int value; + if (source[i] <= '9') { + value = source[i] - '0'; + } else if (source[i] <= 'H') { + value = (source[i] - 'A') + 1; + } else if (source[i] <= 'R') { + value = (source[i] - 'J') + 1; + } else { /* (source[i] >= 'S') && (source[i] <= 'Z') */ + value = (source[i] - 'S') + 2; + } + sum += value * weight[i]; } output_check = '0' + (sum % 11); @@ -804,33 +844,39 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length) } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Producing VIN code: %s\n", local_source); + printf("Producing VIN code: %s\n", source); printf("Input check was %c, calculated check is %c\n", input_check, output_check); } if (input_check != output_check) { - sprintf(symbol->errtxt, "338: Invalid check digit '%c', expecting '%c'", input_check, output_check); + sprintf(symbol->errtxt, "338: Invalid check digit '%c' (position 9), expecting '%c'", + input_check, output_check); return ZINT_ERROR_INVALID_CHECK; } } /* Start character */ - strcpy(dest, "1211212111"); + memcpy(d, "1211212111", 10); + d += 10; /* Import character 'I' prefix? */ if (symbol->option_2 & 1) { - strcat(dest, "1121122111"); + memcpy(d, C39Table[18], 10); + d += 10; } // Copy glyphs to symbol - for (i = 0; i < 17; i++) { - lookup(SILVER, C39Table, local_source[i], dest); + for (i = 0; i < 17; i++, d += 10) { + memcpy(d, C39Table[posn(SILVER, source[i])], 10); } - strcat(dest, "121121211"); + /* Stop character */ + memcpy(d, "121121211", 9); + d += 9; - ustrcpy(symbol->text, local_source); - expand(symbol, dest); + expand(symbol, dest, d - dest); + + ustrcpy(symbol->text, source); /* Specification of dimensions/height for BARCODE_VIN unlikely */ diff --git a/backend/code1.c b/backend/code1.c index f0f1cf74..0bf3882b 100644 --- a/backend/code1.c +++ b/backend/code1.c @@ -319,7 +319,7 @@ static int is_last_single_ascii(const unsigned char string[], const int length, if (length - sp == 1 && string[sp] <= 127) { return 1; } - if (length - sp == 2 && istwodigits(string, length, sp)) { + if (length - sp == 2 && is_twodigits(string, length, sp)) { return 1; } return 0; @@ -591,7 +591,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if (next_mode == C1_ASCII) { - if (istwodigits(source, length, sp)) { + if (is_twodigits(source, length, sp)) { if (debug_print) printf("ASCII double-digits "); /* Step B3 */ @@ -753,7 +753,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne if (codewords_remaining(symbol, tp) == 1 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) { if (can_ascii) { /* Encode last character or last 2 digits as ASCII */ - if (istwodigits(source, length, sp)) { + if (is_twodigits(source, length, sp)) { target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; sp += 2; } else { @@ -864,7 +864,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne target[tp++] = 255; /* Unlatch */ for (; sp < length; sp++) { - if (istwodigits(source, length, sp)) { + if (is_twodigits(source, length, sp)) { target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; sp++; } else if (source[sp] & 0x80) { @@ -1005,7 +1005,7 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len strcpy(symbol->errtxt, "514: Input data too long for Version S"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "515: Invalid input data (Version S encodes numeric input only)"); return ZINT_ERROR_INVALID_DATA; } diff --git a/backend/code1.h b/backend/code1.h index aaf48984..99ade65d 100644 --- a/backend/code1.h +++ b/backend/code1.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2021 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,6 +29,7 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* vim: set ts=4 sw=4 et : */ static const char c40_shift[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -94,9 +95,9 @@ static const unsigned short int c1_grid_height[] = { 5, 7, 10, 15, 21, 30, 46, 68 }; -#define C1_ASCII 1 -#define C1_C40 2 -#define C1_DECIMAL 3 -#define C1_TEXT 4 -#define C1_EDI 5 -#define C1_BYTE 6 +#define C1_ASCII 1 +#define C1_C40 2 +#define C1_DECIMAL 3 +#define C1_TEXT 4 +#define C1_EDI 5 +#define C1_BYTE 6 diff --git a/backend/code128.c b/backend/code128.c index 147f10da..71346329 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -41,42 +41,60 @@ #include "code128.h" #include "gs1.h" +static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +#define KRSET_F (IS_NUM_F | IS_UPR_F) + /* Code 128 tables checked against ISO/IEC 15417:2007 */ -static const char *C128Table[107] = { - /* Code 128 character encodation - Table 1 */ - /* 0 1 2 3 4 5 6 7 8 9 */ - "212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212", "221213", /* 0 */ - "221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221", "223211", "221132", /* 10 */ - "221231", "213212", "223112", "312131", "311222", "321122", "321221", "312212", "322112", "322211", /* 20 */ - "212123", "212321", "232121", "111323", "131123", "131321", "112313", "132113", "132311", "211313", /* 30 */ - "231113", "231311", "112133", "112331", "132131", "113123", "113321", "133121", "313121", "211331", /* 40 */ - "231131", "213113", "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", /* 50 */ - "314111", "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", /* 60 */ - "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111", /* 70 */ - "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141", /* 80 */ - "214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311", "113141", /* 90 */ - "114131", "311141", "411131", "211412", "211214", "211232", "2331112" /*100 */ +INTERNAL_DATA const char C128Table[107][6] = { /* Used by CODABLOCKF and CODE16K also */ + /* Code 128 character encodation - Table 1 (with final CODE16K-only character in place of Stop character) */ + {'2','1','2','2','2','2'}, {'2','2','2','1','2','2'}, {'2','2','2','2','2','1'}, {'1','2','1','2','2','3'}, + {'1','2','1','3','2','2'}, {'1','3','1','2','2','2'}, {'1','2','2','2','1','3'}, {'1','2','2','3','1','2'}, + {'1','3','2','2','1','2'}, {'2','2','1','2','1','3'}, {'2','2','1','3','1','2'}, {'2','3','1','2','1','2'}, + {'1','1','2','2','3','2'}, {'1','2','2','1','3','2'}, {'1','2','2','2','3','1'}, {'1','1','3','2','2','2'}, + {'1','2','3','1','2','2'}, {'1','2','3','2','2','1'}, {'2','2','3','2','1','1'}, {'2','2','1','1','3','2'}, + {'2','2','1','2','3','1'}, {'2','1','3','2','1','2'}, {'2','2','3','1','1','2'}, {'3','1','2','1','3','1'}, + {'3','1','1','2','2','2'}, {'3','2','1','1','2','2'}, {'3','2','1','2','2','1'}, {'3','1','2','2','1','2'}, + {'3','2','2','1','1','2'}, {'3','2','2','2','1','1'}, {'2','1','2','1','2','3'}, {'2','1','2','3','2','1'}, + {'2','3','2','1','2','1'}, {'1','1','1','3','2','3'}, {'1','3','1','1','2','3'}, {'1','3','1','3','2','1'}, + {'1','1','2','3','1','3'}, {'1','3','2','1','1','3'}, {'1','3','2','3','1','1'}, {'2','1','1','3','1','3'}, + {'2','3','1','1','1','3'}, {'2','3','1','3','1','1'}, {'1','1','2','1','3','3'}, {'1','1','2','3','3','1'}, + {'1','3','2','1','3','1'}, {'1','1','3','1','2','3'}, {'1','1','3','3','2','1'}, {'1','3','3','1','2','1'}, + {'3','1','3','1','2','1'}, {'2','1','1','3','3','1'}, {'2','3','1','1','3','1'}, {'2','1','3','1','1','3'}, + {'2','1','3','3','1','1'}, {'2','1','3','1','3','1'}, {'3','1','1','1','2','3'}, {'3','1','1','3','2','1'}, + {'3','3','1','1','2','1'}, {'3','1','2','1','1','3'}, {'3','1','2','3','1','1'}, {'3','3','2','1','1','1'}, + {'3','1','4','1','1','1'}, {'2','2','1','4','1','1'}, {'4','3','1','1','1','1'}, {'1','1','1','2','2','4'}, + {'1','1','1','4','2','2'}, {'1','2','1','1','2','4'}, {'1','2','1','4','2','1'}, {'1','4','1','1','2','2'}, + {'1','4','1','2','2','1'}, {'1','1','2','2','1','4'}, {'1','1','2','4','1','2'}, {'1','2','2','1','1','4'}, + {'1','2','2','4','1','1'}, {'1','4','2','1','1','2'}, {'1','4','2','2','1','1'}, {'2','4','1','2','1','1'}, + {'2','2','1','1','1','4'}, {'4','1','3','1','1','1'}, {'2','4','1','1','1','2'}, {'1','3','4','1','1','1'}, + {'1','1','1','2','4','2'}, {'1','2','1','1','4','2'}, {'1','2','1','2','4','1'}, {'1','1','4','2','1','2'}, + {'1','2','4','1','1','2'}, {'1','2','4','2','1','1'}, {'4','1','1','2','1','2'}, {'4','2','1','1','1','2'}, + {'4','2','1','2','1','1'}, {'2','1','2','1','4','1'}, {'2','1','4','1','2','1'}, {'4','1','2','1','2','1'}, + {'1','1','1','1','4','3'}, {'1','1','1','3','4','1'}, {'1','3','1','1','4','1'}, {'1','1','4','1','1','3'}, + {'1','1','4','3','1','1'}, {'4','1','1','1','1','3'}, {'4','1','1','3','1','1'}, {'1','1','3','1','4','1'}, + {'1','1','4','1','3','1'}, {'3','1','1','1','4','1'}, {'4','1','1','1','3','1'}, {'2','1','1','4','1','2'}, + {'2','1','1','2','1','4'}, {'2','1','1','2','3','2'}, {/* Only used by CODE16K */ '2','1','1','1','3','3'} }; /* Determine appropriate mode for a given character */ -INTERNAL int parunmodd(const unsigned char llyth) { +INTERNAL int c128_parunmodd(const unsigned char llyth) { int modd; if (llyth <= 31) { - modd = SHIFTA; + modd = C128_SHIFTA; } else if ((llyth >= 48) && (llyth <= 57)) { - modd = ABORC; + modd = C128_ABORC; } else if (llyth <= 95) { - modd = AORB; + modd = C128_AORB; } else if (llyth <= 127) { - modd = SHIFTB; + modd = C128_SHIFTB; } else if (llyth <= 159) { - modd = SHIFTA; + modd = C128_SHIFTA; } else if (llyth <= 223) { - modd = AORB; + modd = C128_AORB; } else { - modd = SHIFTB; + modd = C128_SHIFTB; } return modd; @@ -114,11 +132,11 @@ static void grwp(int list[2][C128_MAX], int *indexliste) { /** * Implements rules from ISO 15417 Annex E */ -INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) { +INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *indexliste) { int i, last, next; for (i = 0; i < *(indexliste); i++) { - int current = list[1][i]; /* Either ABORC, AORB, SHIFTA or SHIFTB */ + int current = list[1][i]; /* Either C128_ABORC, C128_AORB, C128_SHIFTA or C128_SHIFTB */ int length = list[0][i]; if (i != 0) { last = list[1][i - 1]; @@ -132,71 +150,71 @@ INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) { } if (i == 0) { /* first block */ - if (current == ABORC) { + if (current == C128_ABORC) { if ((*(indexliste) == 1) && (length == 2)) { /* Rule 1a */ - list[1][i] = LATCHC; - current = LATCHC; + list[1][i] = C128_LATCHC; + current = C128_LATCHC; } else if (length >= 4) { /* Rule 1b */ - list[1][i] = LATCHC; - current = LATCHC; + list[1][i] = C128_LATCHC; + current = C128_LATCHC; } else { - current = AORB; /* Determine below */ + current = C128_AORB; /* Determine below */ } } - if (current == AORB) { - if (next == SHIFTA) { + if (current == C128_AORB) { + if (next == C128_SHIFTA) { /* Rule 1c */ - list[1][i] = LATCHA; + list[1][i] = C128_LATCHA; } else { /* Rule 1d */ - list[1][i] = LATCHB; + list[1][i] = C128_LATCHB; } - } else if (current == SHIFTA) { + } else if (current == C128_SHIFTA) { /* Rule 1c */ - list[1][i] = LATCHA; - } else if (current == SHIFTB) { /* Unless LATCHC set above, can only be SHIFTB */ + list[1][i] = C128_LATCHA; + } else if (current == C128_SHIFTB) { /* Unless C128_LATCHC set above, can only be C128_SHIFTB */ /* Rule 1d */ - list[1][i] = LATCHB; + list[1][i] = C128_LATCHB; } } else { - if (current == ABORC) { + if (current == C128_ABORC) { if (length >= 4) { /* Rule 3 */ - list[1][i] = LATCHC; - current = LATCHC; + list[1][i] = C128_LATCHC; + current = C128_LATCHC; } else { - current = AORB; /* Determine below */ + current = C128_AORB; /* Determine below */ } } - if (current == AORB) { - if (last == LATCHA || last == SHIFTB) { /* Maintain state */ - list[1][i] = LATCHA; - } else if (last == LATCHB || last == SHIFTA) { /* Maintain state */ - list[1][i] = LATCHB; - } else if (next == SHIFTA) { - list[1][i] = LATCHA; + if (current == C128_AORB) { + if (last == C128_LATCHA || last == C128_SHIFTB) { /* Maintain state */ + list[1][i] = C128_LATCHA; + } else if (last == C128_LATCHB || last == C128_SHIFTA) { /* Maintain state */ + list[1][i] = C128_LATCHB; + } else if (next == C128_SHIFTA) { + list[1][i] = C128_LATCHA; } else { - list[1][i] = LATCHB; + list[1][i] = C128_LATCHB; } - } else if (current == SHIFTA) { + } else if (current == C128_SHIFTA) { if (length > 1) { /* Rule 4 */ - list[1][i] = LATCHA; - } else if (last == LATCHA || last == SHIFTB) { /* Maintain state */ - list[1][i] = LATCHA; - } else if (last == LATCHC) { - list[1][i] = LATCHA; + list[1][i] = C128_LATCHA; + } else if (last == C128_LATCHA || last == C128_SHIFTB) { /* Maintain state */ + list[1][i] = C128_LATCHA; + } else if (last == C128_LATCHC) { + list[1][i] = C128_LATCHA; } - } else if (current == SHIFTB) { /* Unless LATCHC set above, can only be SHIFTB */ + } else if (current == C128_SHIFTB) { /* Unless C128_LATCHC set above, can only be C128_SHIFTB */ if (length > 1) { /* Rule 5 */ - list[1][i] = LATCHB; - } else if (last == LATCHB || last == SHIFTA) { /* Maintain state */ - list[1][i] = LATCHB; - } else if (last == LATCHC) { - list[1][i] = LATCHB; + list[1][i] = C128_LATCHB; + } else if (last == C128_LATCHB || last == C128_SHIFTA) { /* Maintain state */ + list[1][i] = C128_LATCHB; + } else if (last == C128_LATCHC) { + list[1][i] = C128_LATCHB; } } } /* Rule 2 is implemented elsewhere, Rule 6 is implied */ @@ -209,22 +227,18 @@ INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) { * Translate Code 128 Set A characters into barcodes. * This set handles all control characters NUL to US. */ -static void c128_set_a(const unsigned char source, char dest[], int values[], int *bar_chars) { +INTERNAL void c128_set_a(const unsigned char source, int values[], int *bar_chars) { if (source > 127) { if (source < 160) { - strcat(dest, C128Table[(source - 128) + 64]); values[(*bar_chars)] = (source - 128) + 64; } else { - strcat(dest, C128Table[(source - 128) - 32]); values[(*bar_chars)] = (source - 128) - 32; } } else { if (source < 32) { - strcat(dest, C128Table[source + 64]); values[(*bar_chars)] = source + 64; } else { - strcat(dest, C128Table[source - 32]); values[(*bar_chars)] = source - 32; } } @@ -236,14 +250,12 @@ static void c128_set_a(const unsigned char source, char dest[], int values[], in * This set handles all characters which are not part of long numbers and not * control characters. */ -static int c128_set_b(const unsigned char source, char dest[], int values[], int *bar_chars) { +INTERNAL int c128_set_b(const unsigned char source, int values[], int *bar_chars) { if (source >= 128 + 32) { - strcat(dest, C128Table[source - 32 - 128]); values[(*bar_chars)] = source - 32 - 128; } else if (source >= 128) { /* Should never happen */ return 0; /* Not reached */ } else if (source >= 32) { - strcat(dest, C128Table[source - 32]); values[(*bar_chars)] = source - 32; } else { /* Should never happen */ return 0; /* Not reached */ @@ -255,16 +267,80 @@ static int c128_set_b(const unsigned char source, char dest[], int values[], int /* Translate Code 128 Set C characters into barcodes * This set handles numbers in a compressed form */ -static void c128_set_c(const unsigned char source_a, const unsigned char source_b, char dest[], int values[], - int *bar_chars) { +INTERNAL void c128_set_c(const unsigned char source_a, const unsigned char source_b, int values[], int *bar_chars) { int weight; weight = (10 * ctoi(source_a)) + ctoi(source_b); - strcat(dest, C128Table[weight]); values[(*bar_chars)] = weight; (*bar_chars)++; } +/* Put set data into set[]. If source given (GS1_MODE) then resolves odd C blocks */ +INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char set[C128_MAX], + unsigned char *source) { + int read = 0; + int i, j; + + for (i = 0; i < indexliste; i++) { + for (j = 0; j < list[0][i]; j++) { + switch (list[1][i]) { + case C128_SHIFTA: set[read] = 'a'; + break; + case C128_LATCHA: set[read] = 'A'; + break; + case C128_SHIFTB: set[read] = 'b'; + break; + case C128_LATCHB: set[read] = 'B'; + break; + case C128_LATCHC: set[read] = 'C'; + break; + } + read++; + } + } + if (source) { + /* Watch out for odd-length Mode C blocks */ + int c_count = 0; + for (i = 0; i < read; i++) { + if (set[i] == 'C') { + if (source[i] == '[') { + if (c_count & 1) { + if ((i - c_count) != 0) { + set[i - c_count] = 'B'; + } else { + set[i - 1] = 'B'; + } + } + c_count = 0; + } else { + c_count++; + } + } else { + if (c_count & 1) { + if ((i - c_count) != 0) { + set[i - c_count] = 'B'; + } else { + set[i - 1] = 'B'; + } + } + c_count = 0; + } + } + if (c_count & 1) { + if ((i - c_count) != 0) { + set[i - c_count] = 'B'; + } else { + set[i - 1] = 'B'; + } + } + for (i = 1; i < read - 1; i++) { + if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) { + set[i] = 'B'; + } + } + } +} + /* Treats source as ISO 8859-1 and copies into symbol->text, converting to UTF-8. Returns length of symbol->text */ STATIC_UNLESS_ZINT_TEST int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char *source, const int source_len) { @@ -308,12 +384,12 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set = ' '; float glyph_count; char dest[1000]; + char *d = dest; /* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */ assert(length > 0); error_number = 0; - strcpy(dest, ""); sourcelen = length; @@ -378,9 +454,9 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len indexliste = 0; indexchaine = 0; - mode = parunmodd(source[indexchaine]); - if ((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { - mode = AORB; + mode = c128_parunmodd(source[indexchaine]); + if ((symbol->symbology == BARCODE_CODE128B) && (mode == C128_ABORC)) { + mode = C128_AORB; } do { @@ -391,30 +467,30 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len if (indexchaine == sourcelen) { break; } - mode = parunmodd(source[indexchaine]); - if ((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { - mode = AORB; + mode = c128_parunmodd(source[indexchaine]); + if ((symbol->symbology == BARCODE_CODE128B) && (mode == C128_ABORC)) { + mode = C128_AORB; } } indexliste++; } while (indexchaine < sourcelen); - dxsmooth(list, &indexliste); + c128_dxsmooth(list, &indexliste); - /* Resolve odd length LATCHC blocks */ - if ((list[1][0] == LATCHC) && (list[0][0] & 1)) { + /* Resolve odd length C128_LATCHC blocks */ + if ((list[1][0] == C128_LATCHC) && (list[0][0] & 1)) { /* Rule 2 */ list[0][1]++; list[0][0]--; if (indexliste == 1) { list[0][1] = 1; - list[1][1] = LATCHB; + list[1][1] = C128_LATCHB; indexliste = 2; } } if (indexliste > 1) { for (i = 1; i < indexliste; i++) { - if ((list[1][i] == LATCHC) && (list[0][i] & 1)) { + if ((list[1][i] == C128_LATCHC) && (list[0][i] & 1)) { /* Rule 3b */ list[0][i - 1]++; list[0][i]--; @@ -422,26 +498,8 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len } } - /* Put set data into set[] */ - - read = 0; - for (i = 0; i < indexliste; i++) { - for (j = 0; j < list[0][i]; j++) { - switch (list[1][i]) { - case SHIFTA: set[read] = 'a'; - break; - case LATCHA: set[read] = 'A'; - break; - case SHIFTB: set[read] = 'b'; - break; - case LATCHB: set[read] = 'B'; - break; - case LATCHC: set[read] = 'C'; - break; - } - read++; - } - } + /* Put set data into set[]. Giving NULL as source as used to resolve odd C blocks which has been done above */ + c128_put_in_set(list, indexliste, set, NULL /*source*/); if (symbol->debug & ZINT_DEBUG_PRINT) { printf("Data: %.*s (%d)\n", sourcelen, source, sourcelen); @@ -495,29 +553,19 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len /* Reader Initialisation mode */ switch (set[0]) { case 'A': /* Start A */ - strcat(dest, C128Table[103]); - values[0] = 103; + values[bar_characters++] = 103; current_set = 'A'; - strcat(dest, C128Table[96]); /* FNC3 */ - values[1] = 96; - bar_characters++; + values[bar_characters++] = 96; /* FNC3 */ break; case 'B': /* Start B */ - strcat(dest, C128Table[104]); - values[0] = 104; + values[bar_characters++] = 104; current_set = 'B'; - strcat(dest, C128Table[96]); /* FNC3 */ - values[1] = 96; - bar_characters++; + values[bar_characters++] = 96; /* FNC3 */ break; case 'C': /* Start C */ - strcat(dest, C128Table[104]); /* Start B */ - values[0] = 104; - strcat(dest, C128Table[96]); /* FNC3 */ - values[1] = 96; - strcat(dest, C128Table[99]); /* Code C */ - values[2] = 99; - bar_characters += 2; + values[bar_characters++] = 104; /* Start B */ + values[bar_characters++] = 96; /* FNC3 */ + values[bar_characters++] = 99; /* Code C */ current_set = 'C'; break; } @@ -525,40 +573,31 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len /* Normal mode */ switch (set[0]) { case 'A': /* Start A */ - strcat(dest, C128Table[103]); - values[0] = 103; + values[bar_characters++] = 103; current_set = 'A'; break; case 'B': /* Start B */ - strcat(dest, C128Table[104]); - values[0] = 104; + values[bar_characters++] = 104; current_set = 'B'; break; case 'C': /* Start C */ - strcat(dest, C128Table[105]); - values[0] = 105; + values[bar_characters++] = 105; current_set = 'C'; break; } } - bar_characters++; if (fset[0] == 'F') { switch (current_set) { case 'A': - strcat(dest, C128Table[101]); - strcat(dest, C128Table[101]); - values[bar_characters] = 101; - values[bar_characters + 1] = 101; + values[bar_characters++] = 101; + values[bar_characters++] = 101; break; case 'B': - strcat(dest, C128Table[100]); - strcat(dest, C128Table[100]); - values[bar_characters] = 100; - values[bar_characters + 1] = 100; + values[bar_characters++] = 100; + values[bar_characters++] = 100; break; } - bar_characters += 2; f_state = 1; } @@ -569,19 +608,16 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len if ((read != 0) && (set[read] != current_set)) { /* Latch different code set */ switch (set[read]) { - case 'A': strcat(dest, C128Table[101]); - values[bar_characters] = 101; - bar_characters++; + case 'A': + values[bar_characters++] = 101; current_set = 'A'; break; - case 'B': strcat(dest, C128Table[100]); - values[bar_characters] = 100; - bar_characters++; + case 'B': + values[bar_characters++] = 100; current_set = 'B'; break; - case 'C': strcat(dest, C128Table[99]); - values[bar_characters] = 99; - bar_characters++; + case 'C': + values[bar_characters++] = 99; current_set = 'C'; break; } @@ -592,38 +628,28 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len /* Latch beginning of extended mode */ switch (current_set) { case 'A': - strcat(dest, C128Table[101]); - strcat(dest, C128Table[101]); - values[bar_characters] = 101; - values[bar_characters + 1] = 101; + values[bar_characters++] = 101; + values[bar_characters++] = 101; break; case 'B': - strcat(dest, C128Table[100]); - strcat(dest, C128Table[100]); - values[bar_characters] = 100; - values[bar_characters + 1] = 100; + values[bar_characters++] = 100; + values[bar_characters++] = 100; break; } - bar_characters += 2; f_state = 1; } if ((fset[read] == ' ') && (f_state == 1)) { /* Latch end of extended mode */ switch (current_set) { case 'A': - strcat(dest, C128Table[101]); - strcat(dest, C128Table[101]); - values[bar_characters] = 101; - values[bar_characters + 1] = 101; + values[bar_characters++] = 101; + values[bar_characters++] = 101; break; case 'B': - strcat(dest, C128Table[100]); - strcat(dest, C128Table[100]); - values[bar_characters] = 100; - values[bar_characters + 1] = 100; + values[bar_characters++] = 100; + values[bar_characters++] = 100; break; } - bar_characters += 2; f_state = 0; } } @@ -632,54 +658,53 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len /* Shift to or from extended mode */ switch (current_set) { case 'A': - strcat(dest, C128Table[101]); /* FNC 4 */ - values[bar_characters] = 101; + values[bar_characters++] = 101; /* FNC 4 */ break; case 'B': - strcat(dest, C128Table[100]); /* FNC 4 */ - values[bar_characters] = 100; + values[bar_characters++] = 100; /* FNC 4 */ break; } - bar_characters++; } if ((set[read] == 'a') || (set[read] == 'b')) { /* Insert shift character */ - strcat(dest, C128Table[98]); - values[bar_characters] = 98; - bar_characters++; + values[bar_characters++] = 98; } switch (set[read]) { /* Encode data characters */ case 'a': - case 'A': c128_set_a(source[read], dest, values, &bar_characters); + case 'A': c128_set_a(source[read], values, &bar_characters); read++; break; case 'b': - case 'B': (void) c128_set_b(source[read], dest, values, &bar_characters); + case 'B': (void) c128_set_b(source[read], values, &bar_characters); read++; break; - case 'C': c128_set_c(source[read], source[read + 1], dest, values, &bar_characters); + case 'C': c128_set_c(source[read], source[read + 1], values, &bar_characters); read += 2; break; } } while (read < sourcelen); - /* check digit calculation */ - total_sum = values[0] % 103; /* Mod as we go along to avoid overflow */ + /* Destination setting and check digit calculation */ + memcpy(d, C128Table[values[0]], 6); + d += 6; + total_sum = values[0]; - for (i = 1; i < bar_characters; i++) { - total_sum = (total_sum + values[i] * i) % 103; + for (i = 1; i < bar_characters; i++, d += 6) { + memcpy(d, C128Table[values[i]], 6); + total_sum += values[i] * i; /* Note can't overflow as 106 * 60 * 60 = 381600 */ } - strcat(dest, C128Table[total_sum]); - values[bar_characters] = total_sum; - bar_characters++; + total_sum %= 103; + memcpy(d, C128Table[total_sum], 6); + d += 6; + values[bar_characters++] = total_sum; /* Stop character */ - strcat(dest, C128Table[106]); - values[bar_characters] = 106; - bar_characters++; + memcpy(d, "2331112", 7); + d += 7; + values[bar_characters++] = 106; if (symbol->debug & ZINT_DEBUG_PRINT) { printf("Codewords:"); @@ -695,7 +720,7 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len } #endif - expand(symbol, dest); + expand(symbol, dest, d - dest); /* ISO/IEC 15417:2007 leaves dimensions/height as application specification */ @@ -707,13 +732,14 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len /* Handle EAN-128 (Now known as GS1-128), and composite version if `cc_mode` set */ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode, const int cc_rows) { - int i, j, values[C128_MAX] = {0}, bar_characters, read, total_sum; + int i, values[C128_MAX] = {0}, bar_characters, read, total_sum; int error_number, warn_number = 0, indexchaine, indexliste; int list[2][C128_MAX] = {{0}}; char set[C128_MAX] = {0}, mode, last_set; float glyph_count; char dest[1000]; - int separator_row, linkage_flag, c_count; + char *d = dest; + int separator_row, linkage_flag; int reduced_length; #ifndef _MSC_VER unsigned char reduced[length + 1]; @@ -721,7 +747,6 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int unsigned char *reduced = (unsigned char *) _alloca(length + 1); #endif - strcpy(dest, ""); linkage_flag = 0; bar_characters = 0; @@ -752,7 +777,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int indexliste = 0; indexchaine = 0; - mode = parunmodd(reduced[indexchaine]); + mode = c128_parunmodd(reduced[indexchaine]); do { list[1][indexliste] = mode; @@ -762,76 +787,18 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int if (indexchaine == reduced_length) { break; } - mode = parunmodd(reduced[indexchaine]); + mode = c128_parunmodd(reduced[indexchaine]); if (reduced[indexchaine] == '[') { - mode = ABORC; + mode = C128_ABORC; } } indexliste++; } while (indexchaine < reduced_length); - dxsmooth(list, &indexliste); + c128_dxsmooth(list, &indexliste); - /* Put set data into set[] */ - /* Note as control chars not permitted in GS1, no reason to ever be in Set A, but cases left in anyway */ - read = 0; - for (i = 0; i < indexliste; i++) { - for (j = 0; j < list[0][i]; j++) { - switch (list[1][i]) { - case SHIFTA: set[read] = 'a'; /* Not reached */ - break; - case LATCHA: set[read] = 'A'; /* Not reached */ - break; - case SHIFTB: set[read] = 'b'; /* Not reached */ - break; - case LATCHB: set[read] = 'B'; - break; - case LATCHC: set[read] = 'C'; - break; - } - read++; - } - } - - /* Watch out for odd-length Mode C blocks */ - c_count = 0; - for (i = 0; i < read; i++) { - if (set[i] == 'C') { - if (reduced[i] == '[') { - if (c_count & 1) { - if ((i - c_count) != 0) { - set[i - c_count] = 'B'; - } else { - set[i - 1] = 'B'; - } - } - c_count = 0; - } else { - c_count++; - } - } else { - if (c_count & 1) { - if ((i - c_count) != 0) { - set[i - c_count] = 'B'; - } else { - set[i - 1] = 'B'; - } - } - c_count = 0; - } - } - if (c_count & 1) { - if ((i - c_count) != 0) { - set[i - c_count] = 'B'; - } else { - set[i - 1] = 'B'; - } - } - for (i = 1; i < read - 1; i++) { - if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) { - set[i] = 'B'; - } - } + /* Put set data into set[], resolving odd C blocks */ + c128_put_in_set(list, indexliste, set, reduced); if (symbol->debug & ZINT_DEBUG_PRINT) { printf("Data: %s (%d)\n", reduced, reduced_length); @@ -866,23 +833,17 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int /* So now we know what start character to use - we can get on with it! */ switch (set[0]) { case 'A': /* Start A */ - strcat(dest, C128Table[103]); /* Not reached */ - values[0] = 103; + values[bar_characters++] = 103; /* Not reached */ break; case 'B': /* Start B */ - strcat(dest, C128Table[104]); - values[0] = 104; + values[bar_characters++] = 104; break; case 'C': /* Start C */ - strcat(dest, C128Table[105]); - values[0] = 105; + values[bar_characters++] = 105; break; } - bar_characters++; - strcat(dest, C128Table[102]); - values[1] = 102; - bar_characters++; + values[bar_characters++] = 102; /* Encode the data */ read = 0; @@ -890,49 +851,42 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int if ((read != 0) && (set[read] != set[read - 1])) { /* Latch different code set */ switch (set[read]) { - case 'A': strcat(dest, C128Table[101]); /* Not reached */ - values[bar_characters] = 101; - bar_characters++; + case 'A': + values[bar_characters++] = 101; /* Not reached */ break; - case 'B': strcat(dest, C128Table[100]); - values[bar_characters] = 100; - bar_characters++; + case 'B': + values[bar_characters++] = 100; break; - case 'C': strcat(dest, C128Table[99]); - values[bar_characters] = 99; - bar_characters++; + case 'C': + values[bar_characters++] = 99; break; } } if ((set[read] == 'a') || (set[read] == 'b')) { /* Insert shift character */ - strcat(dest, C128Table[98]); /* Not reached */ - values[bar_characters] = 98; - bar_characters++; + values[bar_characters++] = 98; /* Not reached */ } if (reduced[read] != '[') { switch (set[read]) { /* Encode data characters */ case 'A': case 'a': - c128_set_a(reduced[read], dest, values, &bar_characters); /* Not reached */ + c128_set_a(reduced[read], values, &bar_characters); /* Not reached */ read++; break; case 'B': case 'b': - (void) c128_set_b(reduced[read], dest, values, &bar_characters); + (void) c128_set_b(reduced[read], values, &bar_characters); read++; break; case 'C': - c128_set_c(reduced[read], reduced[read + 1], dest, values, &bar_characters); + c128_set_c(reduced[read], reduced[read + 1], values, &bar_characters); read += 2; break; } } else { - strcat(dest, C128Table[102]); - values[bar_characters] = 102; - bar_characters++; + values[bar_characters++] = 102; read++; } } while (read < reduced_length); @@ -969,25 +923,27 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int } if (linkage_flag != 0) { - strcat(dest, C128Table[linkage_flag]); - values[bar_characters] = linkage_flag; - bar_characters++; + values[bar_characters++] = linkage_flag; } - /* check digit calculation */ - total_sum = values[0] % 103; /* Mod as we go along to avoid overflow */ + /* Destination setting and check digit calculation */ + memcpy(d, C128Table[values[0]], 6); + d += 6; + total_sum = values[0]; - for (i = 1; i < bar_characters; i++) { - total_sum = (total_sum + values[i] * i) % 103; + for (i = 1; i < bar_characters; i++, d += 6) { + memcpy(d, C128Table[values[i]], 6); + total_sum += values[i] * i; /* Note can't overflow as 106 * 60 * 60 = 381600 */ } - strcat(dest, C128Table[total_sum]); - values[bar_characters] = total_sum; - bar_characters++; + total_sum %= 103; + memcpy(d, C128Table[total_sum], 6); + d += 6; + values[bar_characters++] = total_sum; /* Stop character */ - strcat(dest, C128Table[106]); - values[bar_characters] = 106; - bar_characters++; + memcpy(d, "2331112", 7); + d += 7; + values[bar_characters++] = 106; if (symbol->debug & ZINT_DEBUG_PRINT) { printf("Codewords:"); @@ -1003,7 +959,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int } #endif - expand(symbol, dest); + expand(symbol, dest, d - dest); /* Add the separator pattern for composite symbols */ if (symbol->symbology == BARCODE_GS1_128_CC) { @@ -1057,6 +1013,7 @@ INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int len INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length) { int i, count, check_digit; int error_number, zeroes; + int factor; unsigned char ean128_equiv[23]; if (length > 17) { @@ -1064,7 +1021,7 @@ INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int lengt return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "346: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -1075,8 +1032,10 @@ INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int lengt ustrcpy(ean128_equiv + 4 + zeroes, source); count = 0; + factor = 3; for (i = 20; i >= 4; i--) { - count += i & 1 ? ctoi(ean128_equiv[i]) : 3 * ctoi(ean128_equiv[i]); + count += ctoi(ean128_equiv[i]) * factor; + factor ^= 2; /* Toggles 1 and 3 */ } check_digit = 10 - count % 10; if (check_digit == 10) { @@ -1101,7 +1060,7 @@ INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int lengt return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "348: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -1144,8 +1103,8 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) identifier = source[0]; - to_upper(source + 1); - if (is_sane(KRSET, source + 1, length - 1) != 0) { + to_upper(source + 1, length - 1); + if (!is_sane(KRSET_F, source + 1, length - 1)) { strcpy(symbol->errtxt, "300: Invalid character in DPD data (alphanumerics only)"); return ZINT_ERROR_INVALID_DATA; } diff --git a/backend/code128.h b/backend/code128.h index 3d553e53..93336241 100644 --- a/backend/code128.h +++ b/backend/code128.h @@ -38,19 +38,26 @@ extern "C" { #define C128_MAX 160 -#define SHIFTA 90 -#define LATCHA 91 -#define SHIFTB 92 -#define LATCHB 93 -#define SHIFTC 94 -#define LATCHC 95 -#define AORB 96 -#define ABORC 97 +#define C128_SHIFTA 90 +#define C128_LATCHA 91 +#define C128_SHIFTB 92 +#define C128_LATCHB 93 +#define C128_SHIFTC 94 +#define C128_LATCHC 95 +#define C128_AORB 96 +#define C128_ABORC 97 -#define KRSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length); -INTERNAL int parunmodd(const unsigned char llyth); -INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste); +INTERNAL int c128_parunmodd(const unsigned char llyth); +INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *indexliste); +INTERNAL void c128_set_a(const unsigned char source, int values[], int *bar_chars); +INTERNAL int c128_set_b(const unsigned char source, int values[], int *bar_chars); +INTERNAL void c128_set_c(const unsigned char source_a, const unsigned char source_b, int values[], int *bar_chars); +INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char set[C128_MAX], + unsigned char *source); + +INTERNAL_DATA_EXTERN const char C128Table[107][6]; #ifdef __cplusplus } diff --git a/backend/code16k.c b/backend/code16k.c index a4de2bbe..fbcf6d0e 100644 --- a/backend/code16k.c +++ b/backend/code16k.c @@ -40,27 +40,12 @@ #include "common.h" #include "code128.h" -static const char *C16KTable[107] = { - /* EN 12323 Table 1 - "Code 16K" character encodations */ - "212222", "222122", "222221", "121223", "121322", "131222", "122213", - "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222", - "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222", - "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323", - "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133", - "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113", - "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111", - "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", - "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", - "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", - "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311", - "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232", - "211133" -}; +/* Note using C128Table with extra entry at 106 (Triple Shift) for C16KTable */ - -static const char *C16KStartStop[8] = { +static const char C16KStartStop[8][4] = { /* EN 12323 Table 3 and Table 4 - Start patterns and stop patterns */ - "3211", "2221", "2122", "1411", "1132", "1231", "1114", "3112" + {'3','2','1','1'}, {'2','2','2','1'}, {'2','1','2','2'}, {'1','4','1','1'}, + {'1','1','3','2'}, {'1','2','3','1'}, {'1','1','1','4'}, {'3','1','1','2'} }; /* EN 12323 Table 5 - Start and stop values defining row numbers */ @@ -72,58 +57,23 @@ static const int C16KStopValues[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3 }; -static void c16k_set_a(const unsigned char source, int values[], int *bar_chars) { - if (source > 127) { - if (source < 160) { - values[(*bar_chars)] = source + 64 - 128; - } else { - values[(*bar_chars)] = source - 32 - 128; - } - } else { - if (source < 32) { - values[(*bar_chars)] = source + 64; - } else { - values[(*bar_chars)] = source - 32; - } - } - (*bar_chars)++; -} - -static void c16k_set_b(const unsigned char source, int values[], int *bar_chars) { - if (source > 127) { - values[(*bar_chars)] = source - 32 - 128; - } else { - values[(*bar_chars)] = source - 32; - } - (*bar_chars)++; -} - -static void c16k_set_c(const unsigned char source_a, unsigned char source_b, int values[], int *bar_chars) { - int weight; - - weight = (10 * ctoi(source_a)) + ctoi(source_b); - values[(*bar_chars)] = weight; - (*bar_chars)++; -} - INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int length) { char width_pattern[100]; int current_row, rows, looper, first_check, second_check; int indexchaine; int list[2][C128_MAX] = {{0}}; char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set; - int pads_needed, indexliste, i, j, m, read, mx_reader; + int pads_needed, indexliste, i, m, read, mx_reader; int values[C128_MAX] = {0}; int bar_characters; float glyph_count; int error_number = 0, first_sum, second_sum; int input_length; - int gs1, c_count; + int gs1; /* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */ assert(length > 0); - strcpy(width_pattern, ""); input_length = length; if ((symbol->input_mode & 0x07) == GS1_MODE) { @@ -149,7 +99,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len indexliste = 0; indexchaine = 0; - mode = parunmodd(source[indexchaine]); + mode = c128_parunmodd(source[indexchaine]); do { list[1][indexliste] = mode; @@ -159,75 +109,18 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len if (indexchaine == input_length) { break; } - mode = parunmodd(source[indexchaine]); + mode = c128_parunmodd(source[indexchaine]); if ((gs1) && (source[indexchaine] == '[')) { - mode = ABORC; + mode = C128_ABORC; } /* FNC1 */ } indexliste++; } while (indexchaine < input_length); - dxsmooth(list, &indexliste); + c128_dxsmooth(list, &indexliste); - /* Put set data into set[] */ - read = 0; - for (i = 0; i < indexliste; i++) { - for (j = 0; j < list[0][i]; j++) { - switch (list[1][i]) { - case SHIFTA: set[read] = 'a'; - break; - case LATCHA: set[read] = 'A'; - break; - case SHIFTB: set[read] = 'b'; - break; - case LATCHB: set[read] = 'B'; - break; - case LATCHC: set[read] = 'C'; - break; - } - read++; - } - } - - /* Watch out for odd-length Mode C blocks */ - c_count = 0; - for (i = 0; i < read; i++) { - if (set[i] == 'C') { - if (source[i] == '[') { - if (c_count & 1) { - if ((i - c_count) != 0) { - set[i - c_count] = 'B'; - } else { - set[i - 1] = 'B'; - } - } - c_count = 0; - } else { - c_count++; - } - } else { - if (c_count & 1) { - if ((i - c_count) != 0) { - set[i - c_count] = 'B'; - } else { - set[i - 1] = 'B'; - } - } - c_count = 0; - } - } - if (c_count & 1) { - if ((i - c_count) != 0) { - set[i - c_count] = 'B'; - } else { - set[i - 1] = 'B'; - } - } - for (i = 1; i < read - 1; i++) { - if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) { - set[i] = 'B'; - } - } + /* Put set data into set[], resolving odd C blocks */ + c128_put_in_set(list, indexliste, set, source); if (symbol->debug & ZINT_DEBUG_PRINT) { printf("Data: %.*s\n", input_length, source); @@ -394,15 +287,15 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len switch (set[read]) { /* Encode data characters */ case 'A': case 'a': - c16k_set_a(source[read], values, &bar_characters); + c128_set_a(source[read], values, &bar_characters); read++; break; case 'B': case 'b': - c16k_set_b(source[read], values, &bar_characters); + c128_set_b(source[read], values, &bar_characters); read++; break; - case 'C': c16k_set_c(source[read], source[read + 1], values, &bar_characters); + case 'C': c128_set_c(source[read], source[read + 1], values, &bar_characters); read += 2; break; } @@ -456,19 +349,21 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len int writer; int flip_flop; int len; + char *d = width_pattern; - strcpy(width_pattern, ""); - strcat(width_pattern, C16KStartStop[C16KStartValues[current_row]]); - strcat(width_pattern, "1"); - for (i = 0; i < 5; i++) { - strcat(width_pattern, C16KTable[values[(current_row * 5) + i]]); + memcpy(d, C16KStartStop[C16KStartValues[current_row]], 4); + d += 4; + *d++ = '1'; + for (i = 0; i < 5; i++, d += 6) { + memcpy(d, C128Table[values[(current_row * 5) + i]], 6); } - strcat(width_pattern, C16KStartStop[C16KStopValues[current_row]]); + memcpy(d, C16KStartStop[C16KStopValues[current_row]], 4); + d += 4; /* Write the information into the symbol */ writer = 0; flip_flop = 1; - for (mx_reader = 0, len = (int) strlen(width_pattern); mx_reader < len; mx_reader++) { + for (mx_reader = 0, len = d - width_pattern; mx_reader < len; mx_reader++) { for (looper = 0; looper < ctoi(width_pattern[mx_reader]); looper++) { if (flip_flop == 1) { set_module(symbol, current_row, writer); diff --git a/backend/code49.c b/backend/code49.c index 50f69aaf..64bcf80c 100644 --- a/backend/code49.c +++ b/backend/code49.c @@ -35,20 +35,22 @@ #include "common.h" #include "code49.h" -#define INSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*" +static const char C49_INSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*"; /* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length) { int i, j, rows, M, x_count, y_count, z_count, posn_val, local_value; char intermediate[170] = ""; + char *d = intermediate; int codewords[170], codeword_count; int c_grid[8][8]; /* Refers to table 3 */ int w_grid[8][4]; /* Refets to table 2 */ int pad_count = 0; char pattern[80]; + int bp; int gs1; - int h, len; + int h; int error_number = 0; if (length > 81) { @@ -57,7 +59,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng } if ((symbol->input_mode & 0x07) == GS1_MODE) { gs1 = 1; - strcpy(intermediate, "*"); /* FNC1 */ + *d++ = '*'; /* FNC1 */ } else { gs1 = 0; } @@ -67,15 +69,18 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng strcpy(symbol->errtxt, "431: Invalid character in input data, extended ASCII not allowed"); return ZINT_ERROR_INVALID_DATA; } - if (gs1 && (source[i] == '[')) - strcat(intermediate, "*"); /* FNC1 */ - else - strcat(intermediate, c49_table7[source[i]]); + if (gs1 && (source[i] == '[')) { + *d++ = '*'; /* FNC1 */ + } else { + const char *const entry = c49_table7[source[i]]; + memcpy(d, entry, 2); + d += entry[1] ? 2 : 1; + } } codeword_count = 0; i = 0; - h = (int) strlen(intermediate); + h = d - intermediate; do { if ((intermediate[i] >= '0') && (intermediate[i] <= '9')) { /* Numeric data */ @@ -142,7 +147,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng switch (block_remain) { case 1: /* Rule (a) */ - codewords[codeword_count] = posn(INSET, intermediate[i]); + codewords[codeword_count] = posn(C49_INSET, intermediate[i]); codeword_count++; i++; break; @@ -184,12 +189,12 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng codeword_count++; } } else { - codewords[codeword_count] = posn(INSET, intermediate[i]); + codewords[codeword_count] = posn(C49_INSET, intermediate[i]); codeword_count++; i++; } } else { - codewords[codeword_count] = posn(INSET, intermediate[i]); + codewords[codeword_count] = posn(C49_INSET, intermediate[i]); codeword_count++; i++; } @@ -321,25 +326,26 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng } for (i = 0; i < rows; i++) { - strcpy(pattern, "10"); /* Start character */ + bp = 0; + bp = bin_append_posn(2, 2, pattern, bp); /* Start character "10" */ for (j = 0; j < 4; j++) { if (i != (rows - 1)) { if (c49_table4[i][j] == 'E') { /* Even Parity */ - bin_append(c49_even_bitpattern[w_grid[i][j]], 16, pattern); + bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp); } else { /* Odd Parity */ - bin_append(c49_odd_bitpattern[w_grid[i][j]], 16, pattern); + bp = bin_append_posn(c49_odd_bitpattern[w_grid[i][j]], 16, pattern, bp); } } else { /* Last row uses all even parity */ - bin_append(c49_even_bitpattern[w_grid[i][j]], 16, pattern); + bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp); } } - strcat(pattern, "1111"); /* Stop character */ + bp = bin_append_posn(15, 4, pattern, bp); /* Stop character "1111" */ /* Expand into symbol */ - for (j = 0, len = (int) strlen(pattern); j < len; j++) { + for (j = 0; j < bp; j++) { if (pattern[j] == '1') { set_module(symbol, i, j); } @@ -347,7 +353,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng } symbol->rows = rows; - symbol->width = (int) strlen(pattern); + symbol->width = bp; if (symbol->output_options & COMPLIANT_HEIGHT) { /* ANSI/AIM BC6-2000 Section 2.6 minimum 8X; use 10X as default diff --git a/backend/code49.h b/backend/code49.h index 01dec462..f781a9e7 100644 --- a/backend/code49.h +++ b/backend/code49.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2021 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,21 +29,25 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* vim: set ts=4 sw=4 et : */ /* This data set taken from ANSI/AIM-BC6-2000, 4th April 2000 */ -static const char *c49_table7[128] = { +static const char c49_table7[128][2] = { /* Table 7: Code 49 ASCII Chart */ - "! ", "!A", "!B", "!C", "!D", "!E", "!F", "!G", "!H", "!I", "!J", "!K", "!L", - "!M", "!N", "!O", "!P", "!Q", "!R", "!S", "!T", "!U", "!V", "!W", "!X", "!Y", - "!Z", "!1", "!2", "!3", "!4", "!5", " ", "!6", "!7", "!8", "$", "%", "!9", "!0", - "!-", "!.", "!$", "+", "!/", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", - "7", "8", "9", "!+", "&1", "&2", "&3", "&4", "&5", "&6", "A", "B", "C", "D", "E", - "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", - "V", "W", "X", "Y", "Z", "&7", "&8", "&9", "&0", "&-", "&.", "&A", "&B", "&C", - "&D", "&E", "&F", "&G", "&H", "&I", "&J", "&K", "&L", "&M", "&N", "&O", "&P", - "&Q", "&R", "&S", "&T", "&U", "&V", "&W", "&X", "&Y", "&Z", "&$", "&/", "&+", - "&%", "& " + {'!',' '}, {'!','A'}, {'!','B'}, {'!','C'}, {'!','D'}, {'!','E'}, {'!','F'}, {'!','G'}, {'!','H'}, {'!','I'}, + {'!','J'}, {'!','K'}, {'!','L'}, {'!','M'}, {'!','N'}, {'!','O'}, {'!','P'}, {'!','Q'}, {'!','R'}, {'!','S'}, + {'!','T'}, {'!','U'}, {'!','V'}, {'!','W'}, {'!','X'}, {'!','Y'}, {'!','Z'}, {'!','1'}, {'!','2'}, {'!','3'}, + {'!','4'}, {'!','5'}, { " " }, {'!','6'}, {'!','7'}, {'!','8'}, { "$" }, { "%" }, {'!','9'}, {'!','0'}, + {'!','-'}, {'!','.'}, {'!','$'}, { "+" }, {'!','/'}, { "-" }, { "." }, { "/" }, { "0" }, { "1" }, + { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" }, { "8" }, { "9" }, {'!','+'}, {'&','1'}, + {'&','2'}, {'&','3'}, {'&','4'}, {'&','5'}, {'&','6'}, { "A" }, { "B" }, { "C" }, { "D" }, { "E" }, + { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" }, + { "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" }, + { "Z" }, {'&','7'}, {'&','8'}, {'&','9'}, {'&','0'}, {'&','-'}, {'&','.'}, {'&','A'}, {'&','B'}, {'&','C'}, + {'&','D'}, {'&','E'}, {'&','F'}, {'&','G'}, {'&','H'}, {'&','I'}, {'&','J'}, {'&','K'}, {'&','L'}, {'&','M'}, + {'&','N'}, {'&','O'}, {'&','P'}, {'&','Q'}, {'&','R'}, {'&','S'}, {'&','T'}, {'&','U'}, {'&','V'}, {'&','W'}, + {'&','X'}, {'&','Y'}, {'&','Z'}, {'&','$'}, {'&','/'}, {'&','+'}, {'&','%'}, {'&',' '} }; /* Table 5: Check Character Weighting Values */ @@ -62,9 +66,10 @@ static const char c49_z_weight[] = { 13, 5, 41, 33, 36, 8, 4, 32, 3, 19, 40, 25, 29, 10, 24, 30 }; -static const char *c49_table4[8] = { +static const char c49_table4[8][4] = { /* Table 4: Row Parity Pattern for Code 49 Symbols */ - "OEEO", "EOEO", "OOEE", "EEOO", "OEOE", "EOOE", "OOOO", "EEEE" + {'O','E','E','O'}, {'E','O','E','O'}, {'O','O','E','E'}, {'E','E','O','O'}, + {'O','E','O','E'}, {'E','O','O','E'}, {'O','O','O','O'}, {'E','E','E','E'} }; static const unsigned short int c49_even_bitpattern[] = { diff --git a/backend/common.c b/backend/common.c index dc45dd01..7b4bbf8d 100644 --- a/backend/common.c +++ b/backend/common.c @@ -75,10 +75,10 @@ INTERNAL int to_int(const unsigned char source[], const int length) { } /* Converts lower case characters to upper case in a string source[] */ -INTERNAL void to_upper(unsigned char source[]) { - int i, src_len = (int) ustrlen(source); +INTERNAL void to_upper(unsigned char source[], const int length) { + int i; - for (i = 0; i < src_len; i++) { + for (i = 0; i < length; i++) { if ((source[i] >= 'a') && (source[i] <= 'z')) { source[i] = (source[i] - 'a') + 'A'; } @@ -98,59 +98,80 @@ INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsig } /* Verifies that a string only uses valid characters */ -INTERNAL int is_sane(const char test_string[], const unsigned char source[], const int length) { - int i, j, lt = (int) strlen(test_string); +INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length) { + #define IS_CLS_F (IS_CLI_F | IS_SIL_F) + static unsigned short flgs[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00-1F*/ + IS_SPC_F, IS_C82_F, IS_C82_F, IS_HSH_F, /*20-23*/ /* !"# */ + IS_CLS_F, IS_SIL_F | IS_C82_F, IS_C82_F, IS_C82_F, /*24-27*/ /* $%&' */ + IS_C82_F, IS_C82_F, IS_C82_F, IS_PLS_F, /*28-2B*/ /* ()*+ */ + IS_C82_F, IS_MNS_F, IS_CLS_F | IS_C82_F, IS_CLS_F | IS_C82_F, /*2B-2F*/ /* ,-./ */ + IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*30-33*/ /* 0123 */ + IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*34-37*/ /* 4567 */ + IS_NUM_F, IS_NUM_F, IS_CLI_F | IS_C82_F, IS_C82_F, /*38-3B*/ /* 89:; */ + IS_C82_F, IS_C82_F, IS_C82_F, IS_C82_F, /*3B-3F*/ /* <=>? */ + 0, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, /*40-43*/ /* @ABC */ + IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*44-47*/ /* DEFG */ + IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*48-4B*/ /* HIJK */ + IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F, /*4B-4F*/ /* LMNO */ + IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*50-53*/ /* PQRS */ + IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*53-57*/ /* TUVW */ + IS_UX__F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, 0, /*58-5B*/ /* XYZ[ */ + 0, 0, 0, IS_C82_F, /*5B-5F*/ /* \]^_ */ + 0, IS_LHX_F, IS_LHX_F, IS_LHX_F, /*60-63*/ /* `abc */ + IS_LHX_F, IS_LHX_F, IS_LHX_F, IS_LWO_F, /*64-67*/ /* defg */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*68-6B*/ /* hijk */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*6B-6F*/ /* lmno */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*70-73*/ /* pqrs */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*74-77*/ /* tuvw */ + IS_LX__F, IS_LWO_F, IS_LWO_F, 0, /*78-7B*/ /* xyz{ */ + 0, 0, 0, 0, /*7B-7F*/ /* |}~D */ + }; + int i; for (i = 0; i < length; i++) { - unsigned int latch = FALSE; - for (j = 0; j < lt; j++) { - if (source[i] == test_string[j]) { - latch = TRUE; - break; - } - } - if (!(latch)) { - return ZINT_ERROR_INVALID_DATA; + if (!(flgs[source[i]] & flg)) { + return 0; } } - - return 0; + return 1; } /* Replaces huge switch statements for looking up in tables */ -INTERNAL void lookup(const char set_string[], const char *table[], const char data, char dest[]) { - int i, n = (int) strlen(set_string); +/* Verifies that a string only uses valid characters, and returns `test_string` position of each in `posns` array */ +INTERNAL int is_sane_lookup(const char test_string[], const int test_length, const unsigned char source[], + const int length, int *posns) { + int i, j; - for (i = 0; i < n; i++) { - if (data == set_string[i]) { - strcat(dest, table[i]); - break; + for (i = 0; i < length; i++) { + posns[i] = -1; + for (j = 0; j < test_length; j++) { + if (source[i] == test_string[j]) { + posns[i] = j; + break; + } + } + if (posns[i] == -1) { + return 0; } } + + return 1; } /* Returns the position of data in set_string */ INTERNAL int posn(const char set_string[], const char data) { - int i, n = (int) strlen(set_string); + const char *s; - for (i = 0; i < n; i++) { - if (data == set_string[i]) { - return i; + for (s = set_string; *s; s++) { + if (data == *s) { + return s - set_string; } } return -1; } -/* Convert an integer value to a string representing its binary equivalent */ -INTERNAL void bin_append(const int arg, const int length, char *binary) { - int bin_posn = (int) strlen(binary); - - bin_append_posn(arg, length, binary, bin_posn); - - binary[bin_posn + length] = '\0'; -} - -/* Convert an integer value to a string representing its binary equivalent at a set position */ +/* Convert an integer value to a string representing its binary equivalent and place at a given position */ INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn) { int i; int start; @@ -195,20 +216,23 @@ INTERNAL void unset_module(struct zint_symbol *symbol, const int y_coord, const } /* Expands from a width pattern to a bit pattern */ -INTERNAL void expand(struct zint_symbol *symbol, const char data[]) { +INTERNAL void expand(struct zint_symbol *symbol, const char data[], const int length) { - int reader, n = (int) strlen(data); + int reader; int writer, i; int latch, num; + int row = symbol->rows; + + symbol->rows++; writer = 0; latch = 1; - for (reader = 0; reader < n; reader++) { + for (reader = 0; reader < length; reader++) { num = ctoi(data[reader]); for (i = 0; i < num; i++) { if (latch) { - set_module(symbol, symbol->rows, writer); + set_module(symbol, row, writer); } writer++; } @@ -216,17 +240,9 @@ INTERNAL void expand(struct zint_symbol *symbol, const char data[]) { latch = !latch; } - if (symbol->symbology != BARCODE_PHARMA) { - if (writer > symbol->width) { - symbol->width = writer; - } - } else { - /* Pharmacode One ends with a space - adjust for this */ - if (writer > symbol->width + 2) { - symbol->width = writer - 2; - } + if (writer > symbol->width) { + symbol->width = writer; } - symbol->rows = symbol->rows + 1; } /* Indicates which symbologies can have row binding */ @@ -281,7 +297,7 @@ INTERNAL int is_composite(const int symbology) { } /* Whether next two characters are digits */ -INTERNAL int istwodigits(const unsigned char source[], const int length, const int position) { +INTERNAL int is_twodigits(const unsigned char source[], const int length, const int position) { if ((position + 1 < length) && (source[position] >= '0') && (source[position] <= '9') && (source[position + 1] >= '0') && (source[position + 1] <= '9')) { return 1; @@ -415,7 +431,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height, if (row_height < 0.5f) { /* Absolute minimum */ row_height = 0.5f; } - if (min_row_height && row_height < min_row_height) { + if (min_row_height && stripf(row_height) < stripf(min_row_height)) { error_number = ZINT_WARN_NONCOMPLIANT; if (!no_errtxt) { strcpy(symbol->errtxt, "247: Height not compliant with standards"); @@ -425,7 +441,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height, } else { symbol->height = stripf(fixed_height); /* Ignore any given height */ } - if (max_height && symbol->height > max_height) { + if (max_height && stripf(symbol->height) > stripf(max_height)) { error_number = ZINT_WARN_NONCOMPLIANT; if (!no_errtxt) { strcpy(symbol->errtxt, "248: Height not compliant with standards"); diff --git a/backend/common.h b/backend/common.h index a7a98405..84af5798 100644 --- a/backend/common.h +++ b/backend/common.h @@ -42,8 +42,28 @@ #define TRUE 1 #endif +/* `is_sane()` flags */ +#define IS_SPC_F 0x0001 /* Space */ +#define IS_HSH_F 0x0002 /* Hash sign # */ +#define IS_PLS_F 0x0004 /* Plus sign + */ +#define IS_MNS_F 0x0008 /* Minus sign - */ +#define IS_NUM_F 0x0010 /* Number 0-9 */ +#define IS_UPO_F 0x0020 /* Uppercase letter, apart from A-F and X */ +#define IS_UHX_F 0x0040 /* Uppercase hex A-F */ +#define IS_UX__F 0x0080 /* Uppercase X */ +#define IS_LWO_F 0x0100 /* Lowercase letter, apart from a-f and x */ +#define IS_LHX_F 0x0200 /* Lowercase hex a-f */ +#define IS_LX__F 0x0400 /* Lowercase x */ +#define IS_C82_F 0x0800 /* CSET82 punctuation (apart from - and +) */ +#define IS_SIL_F 0x1000 /* SILVER/TECHNETIUM punctuation .$/% (apart from space, - and +) */ +#define IS_CLI_F 0x2000 /* CALCIUM INNER punctuation $:/. (apart from - and +) (Codabar) */ +#define IS_ARS_F 0x4000 /* ARSENIC uppercase subset (VIN) */ + +#define IS_UPR_F (IS_UPO_F | IS_UHX_F | IS_UX__F) /* Uppercase letters */ +#define IS_LWR_F (IS_LWO_F | IS_LHX_F | IS_LX__F) /* Lowercase letters */ + /* The most commonly used set */ -#define NEON "0123456789" +#define NEON_F IS_NUM_F /* NEON "0123456789" */ #include "zint.h" #include "zintconfig.h" @@ -83,6 +103,14 @@ # define INTERNAL #endif +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MINGW32__) +# define INTERNAL_DATA_EXTERN __attribute__ ((visibility ("hidden"))) extern +# define INTERNAL_DATA __attribute__ ((visibility ("hidden"))) +#else +# define INTERNAL_DATA_EXTERN extern +# define INTERNAL_DATA +#endif + #ifdef ZINT_TEST #define STATIC_UNLESS_ZINT_TEST INTERNAL #else @@ -112,14 +140,14 @@ extern "C" { INTERNAL int ctoi(const char source); INTERNAL char itoc(const int source); INTERNAL int to_int(const unsigned char source[], const int length); - INTERNAL void to_upper(unsigned char source[]); + INTERNAL void to_upper(unsigned char source[], const int length); INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsigned char c); - INTERNAL int is_sane(const char test_string[], const unsigned char source[], const int length); - INTERNAL void lookup(const char set_string[], const char *table[], const char data, char dest[]); + INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length); + INTERNAL int is_sane_lookup(const char test_string[], const int test_length, const unsigned char source[], + const int length, int *posns); INTERNAL int posn(const char set_string[], const char data); - INTERNAL void bin_append(const int arg, const int length, char *binary); INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn); #ifndef COMMON_INLINE @@ -130,12 +158,14 @@ extern "C" { const int colour); #endif INTERNAL void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord); - INTERNAL void expand(struct zint_symbol *symbol, const char data[]); + + INTERNAL void expand(struct zint_symbol *symbol, const char data[], const int length); INTERNAL int is_stackable(const int symbology); INTERNAL int is_extendable(const int symbology); INTERNAL int is_composite(const int symbology); - INTERNAL int istwodigits(const unsigned char source[], const int length, const int position); + + INTERNAL int is_twodigits(const unsigned char source[], const int length, const int position); INTERNAL unsigned int decode_utf8(unsigned int *state, unsigned int *codep, const unsigned char byte); INTERNAL int is_valid_utf8(const unsigned char source[], const int length); diff --git a/backend/composite.c b/backend/composite.c index 2febeedf..980b9d2f 100644 --- a/backend/composite.c +++ b/backend/composite.c @@ -68,7 +68,8 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int 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[], - unsigned char local_source[], int *p_with_addon); + unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part, + unsigned char *zsecond_part); INTERNAL int dbar_omnstk_set_height(struct zint_symbol *symbol, const int first_row); INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); @@ -1331,8 +1332,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]; - padded_pri[0] = '\0'; - if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon)) { + if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon, NULL, + NULL)) { sprintf(symbol->errtxt, "448: Input too long (%s) in linear component", with_addon ? "5 character maximum for add-on" : "13 character maximum"); return ZINT_ERROR_TOO_LONG; diff --git a/backend/dllversion.c b/backend/dllversion.c index d5cca9d0..62b02698 100644 --- a/backend/dllversion.c +++ b/backend/dllversion.c @@ -1,4 +1,35 @@ /* Sed: http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/versions.asp */ + +/* + libzint - the open source barcode library + Copyright (C) 2008 - 2021 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ #if defined (_WIN32) && (defined(_USRDLL) || defined(DLL_EXPORT) || defined(PIC)) #include #include @@ -17,17 +48,18 @@ __declspec(dllexport) HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi); HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi) { - if (!pdvi || (sizeof(*pdvi) != pdvi->info1.cbSize)) - return (E_INVALIDARG); + if (!pdvi || (sizeof(*pdvi) != pdvi->info1.cbSize)) + return (E_INVALIDARG); - pdvi->info1.dwMajorVersion = ZINT_VERSION_MAJOR; - pdvi->info1.dwMinorVersion = ZINT_VERSION_MINOR; - pdvi->info1.dwBuildNumber = ZINT_VERSION_RELEASE; - pdvi->info1.dwPlatformID = DLLVER_PLATFORM_WINDOWS; - if (sizeof(DLLVERSIONINFO2) == pdvi->info1.cbSize) - pdvi->ullVersion = MAKEDLLVERULL(ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE, ZINT_VERSION_BUILD); + pdvi->info1.dwMajorVersion = ZINT_VERSION_MAJOR; + pdvi->info1.dwMinorVersion = ZINT_VERSION_MINOR; + pdvi->info1.dwBuildNumber = ZINT_VERSION_RELEASE; + pdvi->info1.dwPlatformID = DLLVER_PLATFORM_WINDOWS; + if (sizeof(DLLVERSIONINFO2) == pdvi->info1.cbSize) + pdvi->ullVersion = MAKEDLLVERULL(ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE, + ZINT_VERSION_BUILD); - return S_OK; + return S_OK; } #else /* https://stackoverflow.com/a/26541331 Suppresses gcc warning ISO C forbids an empty translation unit */ diff --git a/backend/dmatrix.c b/backend/dmatrix.c index 44680a5f..927cbb10 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -779,7 +779,7 @@ static int dm200encode(struct zint_symbol *symbol, const unsigned char source[], if (current_mode == DM_ASCII) { next_mode = DM_ASCII; - if (istwodigits(source, inputlen, sp)) { + if (is_twodigits(source, inputlen, sp)) { target[tp] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130); if (debug) printf("N%02d ", target[tp] - 130); tp++; @@ -1029,7 +1029,7 @@ static int dm200encode(struct zint_symbol *symbol, const unsigned char source[], target[tp++] = 254; // Unlatch if (debug) printf("ASC "); for (; sp < inputlen; sp++) { - if (istwodigits(source, inputlen, sp)) { + if (is_twodigits(source, inputlen, sp)) { target[tp++] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130); if (debug) printf("N%02d ", target[tp - 1] - 130); sp++; diff --git a/backend/dotcode.c b/backend/dotcode.c index 67658d36..957367da 100644 --- a/backend/dotcode.c +++ b/backend/dotcode.c @@ -584,7 +584,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha } // Prevent encodation as a macro if a special character is in first position - if (strchr(lead_specials, source[input_position]) != NULL) { + if (posn(lead_specials, source[input_position]) != -1) { codeword_array[array_length] = 101; // Latch A array_length++; codeword_array[array_length] = source[input_position] + 64; diff --git a/backend/emf.c b/backend/emf.c index c1738788..775db073 100644 --- a/backend/emf.c +++ b/backend/emf.c @@ -46,7 +46,7 @@ #include "emf.h" /* Multiply truncating to 3 decimal places (avoids rounding differences on various platforms) */ -#define mul3dpf(m, arg) (roundf(m * arg * 1000.0) / 1000.0f) +#define mul3dpf(m, arg) stripf(roundf(m * arg * 1000.0) / 1000.0f) static int count_rectangles(struct zint_symbol *symbol) { int rectangles = 0; @@ -453,9 +453,9 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { rectangle[this_rectangle].type = 0x0000002b; // EMR_RECTANGLE rectangle[this_rectangle].size = 24; rectangle[this_rectangle].box.top = (int32_t) rect->y; - rectangle[this_rectangle].box.bottom = (int32_t) (rect->y + rect->height); + rectangle[this_rectangle].box.bottom = (int32_t) stripf(rect->y + rect->height); rectangle[this_rectangle].box.left = (int32_t) rect->x; - rectangle[this_rectangle].box.right = (int32_t) (rect->x + rect->width); + rectangle[this_rectangle].box.right = (int32_t) stripf(rect->x + rect->width); this_rectangle++; bytecount += 24; recordcount++; @@ -475,10 +475,10 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { } circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE circle[this_circle].size = 24; - circle[this_circle].box.top = (int32_t) (circ->y - radius); - circle[this_circle].box.bottom = (int32_t) (circ->y + radius); - circle[this_circle].box.left = (int32_t) (circ->x - radius); - circle[this_circle].box.right = (int32_t) (circ->x + radius); + circle[this_circle].box.top = (int32_t) stripf(circ->y - radius); + circle[this_circle].box.bottom = (int32_t) stripf(circ->y + radius); + circle[this_circle].box.left = (int32_t) stripf(circ->x - radius); + circle[this_circle].box.right = (int32_t) stripf(circ->x + radius); this_circle++; bytecount += 24; recordcount++; @@ -487,10 +487,10 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { float inner_radius = radius - circ->width; circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE circle[this_circle].size = 24; - circle[this_circle].box.top = (int32_t) (circ->y - inner_radius); - circle[this_circle].box.bottom = (int32_t) (circ->y + inner_radius); - circle[this_circle].box.left = (int32_t) (circ->x - inner_radius); - circle[this_circle].box.right = (int32_t) (circ->x + inner_radius); + circle[this_circle].box.top = (int32_t) stripf(circ->y - inner_radius); + circle[this_circle].box.bottom = (int32_t) stripf(circ->y + inner_radius); + circle[this_circle].box.left = (int32_t) stripf(circ->x - inner_radius); + circle[this_circle].box.right = (int32_t) stripf(circ->x + inner_radius); this_circle++; bytecount += 24; recordcount++; @@ -516,18 +516,18 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { } /* Note rotation done via world transform */ - hexagon[this_hexagon].a_points_a.x = (int32_t) (hex->x); - hexagon[this_hexagon].a_points_a.y = (int32_t) (hex->y + radius); - hexagon[this_hexagon].a_points_b.x = (int32_t) (hex->x + half_sqrt3_radius); - hexagon[this_hexagon].a_points_b.y = (int32_t) (hex->y + half_radius); - hexagon[this_hexagon].a_points_c.x = (int32_t) (hex->x + half_sqrt3_radius); - hexagon[this_hexagon].a_points_c.y = (int32_t) (hex->y - half_radius); - hexagon[this_hexagon].a_points_d.x = (int32_t) (hex->x); - hexagon[this_hexagon].a_points_d.y = (int32_t) (hex->y - radius); - hexagon[this_hexagon].a_points_e.x = (int32_t) (hex->x - half_sqrt3_radius); - hexagon[this_hexagon].a_points_e.y = (int32_t) (hex->y - half_radius); - hexagon[this_hexagon].a_points_f.x = (int32_t) (hex->x - half_sqrt3_radius); - hexagon[this_hexagon].a_points_f.y = (int32_t) (hex->y + half_radius); + hexagon[this_hexagon].a_points_a.x = (int32_t) hex->x; + hexagon[this_hexagon].a_points_a.y = (int32_t) stripf(hex->y + radius); + hexagon[this_hexagon].a_points_b.x = (int32_t) stripf(hex->x + half_sqrt3_radius); + hexagon[this_hexagon].a_points_b.y = (int32_t) stripf(hex->y + half_radius); + hexagon[this_hexagon].a_points_c.x = (int32_t) stripf(hex->x + half_sqrt3_radius); + hexagon[this_hexagon].a_points_c.y = (int32_t) stripf(hex->y - half_radius); + hexagon[this_hexagon].a_points_d.x = (int32_t) hex->x; + hexagon[this_hexagon].a_points_d.y = (int32_t) stripf(hex->y - radius); + hexagon[this_hexagon].a_points_e.x = (int32_t) stripf(hex->x - half_sqrt3_radius); + hexagon[this_hexagon].a_points_e.y = (int32_t) stripf(hex->y - half_radius); + hexagon[this_hexagon].a_points_f.x = (int32_t) stripf(hex->x - half_sqrt3_radius); + hexagon[this_hexagon].a_points_f.y = (int32_t) stripf(hex->y + half_radius); hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y; hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y; diff --git a/backend/emf.h b/backend/emf.h index a10aa629..cb073887 100644 --- a/backend/emf.h +++ b/backend/emf.h @@ -28,11 +28,12 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* vim: set ts=4 sw=4 et : */ #ifndef EMF_H -#define EMF_H +#define EMF_H -#ifdef __cplusplus +#ifdef __cplusplus extern "C" { #endif @@ -243,10 +244,8 @@ extern "C" { #pragma pack() -#ifdef __cplusplus +#ifdef __cplusplus } #endif -#endif /* EMF_H */ - - +#endif /* EMF_H */ diff --git a/backend/font.h b/backend/font.h index a01abaf7..e7126e26 100644 --- a/backend/font.h +++ b/backend/font.h @@ -448,7 +448,8 @@ static font_item small_font[] = { * release of ocr-b only granted rights for non-commercial use; that * restriction is now lifted." * - * Used OCRB.otf with FontForge to create OCRB-18.bdf (normal) and OCRB-16.bdf (small) and then touched up using gbdfed + * Used OCRB.otf with FontForge to create OCRB-18.bdf (normal) and OCRB-16.bdf (small) and then touched up + * using gbdfed * Note there's no bold version of OCR-B. */ diff --git a/backend/general_field.c b/backend/general_field.c index 7c450c60..d8a85069 100644 --- a/backend/general_field.c +++ b/backend/general_field.c @@ -36,16 +36,17 @@ static const char alphanum_puncs[] = "*,-./"; static const char isoiec_puncs[] = "!\"%&'()*+,-./:;<=>?_ "; /* Note contains space, not in cset82 */ +#define IS_ISOIEC_F (IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F) /* Returns type of char at `i`. FNC1 counted as NUMERIC. Returns 0 if invalid char */ static int general_field_type(const char *general_field, const int i) { if (general_field[i] == '[' || (general_field[i] >= '0' && general_field[i] <= '9')) { return NUMERIC; } - if ((general_field[i] >= 'A' && general_field[i] <= 'Z') || strchr(alphanum_puncs, general_field[i])) { + if ((general_field[i] >= 'A' && general_field[i] <= 'Z') || posn(alphanum_puncs, general_field[i]) != -1) { return ALPHANUMERIC; } - if ((general_field[i] >= 'a' && general_field[i] <= 'z') || strchr(isoiec_puncs, general_field[i])) { + if (is_sane(IS_ISOIEC_F, (const unsigned char *) general_field + i, 1)) { return ISOIEC; } return 0; diff --git a/backend/gridmtx.c b/backend/gridmtx.c index 1f78960a..efc4b6f8 100644 --- a/backend/gridmtx.c +++ b/backend/gridmtx.c @@ -43,6 +43,10 @@ #include "gb2312.h" #include "eci.h" +static const char EUROPIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "; +static const char EUROPIUM_UPR[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "; +static const char EUROPIUM_LWR[] = "abcdefghijklmnopqrstuvwxyz "; + /* define_mode() stuff */ /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ @@ -68,7 +72,7 @@ static int in_numeral(const unsigned int gbdata[], const int length, const int i i++) { if (gbdata[i] >= '0' && gbdata[i] <= '9') { digit_cnt++; - } else if (strchr(numeral_nondigits, gbdata[i])) { + } else if (posn(numeral_nondigits, (const char) gbdata[i]) != -1) { if (nondigit) { break; } @@ -282,7 +286,7 @@ static void define_mode(char *mode, const unsigned int gbdata[], const int lengt /* Get optimal mode for each code point by tracing backwards */ for (i = length - 1, cm_i = i * GM_NUM_MODES; i >= 0; i--, cm_i -= GM_NUM_MODES) { - j = strchr(mode_types, cur_mode) - mode_types; + j = posn(mode_types, cur_mode); cur_mode = char_modes[cm_i + j]; mode[i] = cur_mode; } @@ -308,7 +312,7 @@ static int add_shift_char(char binary[], int bp, int shifty, int debug) { glyph = shifty; } else { for (i = 32; i < 64; i++) { - if (shift_set[i] == shifty) { + if (gm_shift_set[i] == shifty) { glyph = i; break; } @@ -577,7 +581,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con if ((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) { numbuf[p] = gbdata[sp]; p++; - } else if (strchr(numeral_nondigits, gbdata[sp])) { + } else if (posn(numeral_nondigits, (const char) gbdata[sp]) != -1) { if (ppos != -1) { break; } @@ -701,7 +705,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con if (shift == 0) { /* Upper Case character */ - glyph = posn("ABCDEFGHIJKLMNOPQRSTUVWXYZ ", (const char) gbdata[sp]); + glyph = posn(EUROPIUM_UPR, (const char) gbdata[sp]); if (debug & ZINT_DEBUG_PRINT) { printf("[%d] ", (int) glyph); } @@ -726,7 +730,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con if (shift == 0) { /* Lower Case character */ - glyph = posn("abcdefghijklmnopqrstuvwxyz ", (const char) gbdata[sp]); + glyph = posn(EUROPIUM_LWR, (const char) gbdata[sp]); if (debug & ZINT_DEBUG_PRINT) { printf("[%d] ", (int) glyph); } diff --git a/backend/gridmtx.h b/backend/gridmtx.h index f0d58c8b..65b99a48 100644 --- a/backend/gridmtx.h +++ b/backend/gridmtx.h @@ -1,7 +1,7 @@ /* gridmtx.h - definitions for Grid Matrix libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2021 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -30,9 +30,7 @@ */ /* vim: set ts=4 sw=4 et : */ -#define EUROPIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " - -static const char shift_set[] = { +static const char gm_shift_set[] = { /* From Table 7 - Encoding of control characters */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* NULL -> SI */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* DLE -> US */ diff --git a/backend/gs1.c b/backend/gs1.c index 17a18738..93eb4f54 100644 --- a/backend/gs1.c +++ b/backend/gs1.c @@ -52,7 +52,7 @@ static int numeric(const unsigned char *data, int data_len, int offset, int min, if (data_len) { const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len); + const unsigned char *const de = d + (data_len > max ? max : data_len); for (; d < de; d++) { if (*d < '0' || *d > '9') { @@ -90,7 +90,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min, if (data_len) { const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len); + const unsigned char *const de = d + (data_len > max ? max : data_len); for (; d < de; d++) { if (*d < '!' || *d > 'z' || c82[*d - '!'] == 82) { @@ -117,7 +117,7 @@ static int cset39(const unsigned char *data, int data_len, int offset, int min, if (data_len) { const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len); + const unsigned char *const de = d + (data_len > max ? max : data_len); for (; d < de; d++) { /* 0-9, A-Z and "#", "-", "/" */ @@ -145,13 +145,13 @@ static int csum(const unsigned char *data, int data_len, int offset, int min, in if (!length_only && data_len) { const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len) - 1; /* Note less last character */ + const unsigned char *const de = d + (data_len > max ? max : data_len) - 1; /* Note less last character */ int checksum = 0; int factor = (min & 1) ? 1 : 3; for (; d < de; d++) { checksum += (*d - '0') * factor; - factor = factor == 3 ? 1 : 3; + factor ^= 2; /* Toggles 1 and 3 */ } checksum = 10 - checksum % 10; if (checksum == 10) { @@ -189,7 +189,7 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83 }; const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len) - 2; /* Note less last 2 characters */ + const unsigned char *const de = d + (data_len > max ? max : data_len) - 2; /* Note less last 2 characters */ int checksum = 0, c1, c2; for (; d < de; d++) { @@ -549,7 +549,7 @@ static int pcenc(const unsigned char *data, int data_len, int offset, int min, i if (!length_only && data_len) { const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len); + const unsigned char *const de = d + (data_len > max ? max : data_len); for (; d < de; d++) { if (*d == '%') { @@ -746,7 +746,7 @@ static int iban(const unsigned char *data, int data_len, int offset, int min, in if (!length_only && data_len) { const unsigned char *d = data + offset; - const unsigned char *de = d + (data_len > max ? max : data_len); + const unsigned char *const de = d + (data_len > max ? max : data_len); int checksum = 0; int given_checksum; @@ -1394,7 +1394,7 @@ INTERNAL char gs1_check_digit(const unsigned char source[], const int length) { for (i = 0; i < length; i++) { count += factor * ctoi(source[i]); - factor = factor == 1 ? 3 : 1; + factor ^= 2; /* Toggles 1 and 3 */ } return itoc((10 - (count % 10)) % 10); diff --git a/backend/hanxin.c b/backend/hanxin.c index 3b7f6c25..c0adc0fb 100644 --- a/backend/hanxin.c +++ b/backend/hanxin.c @@ -474,7 +474,7 @@ static void hx_define_mode(char *mode, const unsigned int gbdata[], const int le /* Get optimal mode for each code point by tracing backwards */ for (i = length - 1, cm_i = i * HX_NUM_MODES; i >= 0; i--, cm_i -= HX_NUM_MODES) { - j = strchr(mode_types, cur_mode) - mode_types; + j = posn(mode_types, cur_mode); cur_mode = char_modes[cm_i + j]; mode[i] = cur_mode; } @@ -535,17 +535,17 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour while (i < block_length) { int first = 0; - first = posn(NEON, (char) source[position + i]); + first = ctoi((const char) source[position + i]); count = 1; encoding_value = first; if (i + 1 < block_length && mode[position + i + 1] == 'n') { - int second = posn(NEON, (char) source[position + i + 1]); + int second = ctoi((const char) source[position + i + 1]); count = 2; encoding_value = (encoding_value * 10) + second; if (i + 2 < block_length && mode[position + i + 2] == 'n') { - int third = posn(NEON, (char) source[position + i + 2]); + int third = ctoi((const char) source[position + i + 2]); count = 3; encoding_value = (encoding_value * 10) + third; } diff --git a/backend/imail.c b/backend/imail.c index be2db805..7e234614 100644 --- a/backend/imail.c +++ b/backend/imail.c @@ -38,7 +38,7 @@ #include "common.h" #include "large.h" -#define SODIUM "0123456789-" +#define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */ /* The following lookup tables were generated using the code in Appendix C */ @@ -242,11 +242,11 @@ static unsigned short USPS_MSB_Math_CRC11GenerateFrameCheckSequence(unsigned cha return FrameCheckSequence; } -INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height); +INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height); INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int length) { char data_pattern[200]; - int error_number; + int error_number = 0; int i, j, read; char zip[35], tracker[35], temp[2]; large_int accum; @@ -262,10 +262,9 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int strcpy(symbol->errtxt, "450: Input too long (32 character maximum)"); return ZINT_ERROR_TOO_LONG; } - error_number = is_sane(SODIUM, source, length); - if (error_number == ZINT_ERROR_INVALID_DATA) { + if (!is_sane(SODIUM_MNS_F, source, length)) { strcpy(symbol->errtxt, "451: Invalid character in data (digits and \"-\" only)"); - return error_number; + return ZINT_ERROR_INVALID_DATA; } strcpy(zip, ""); diff --git a/backend/large.c b/backend/large.c index 9df5a1be..127dca12 100644 --- a/backend/large.c +++ b/backend/large.c @@ -57,7 +57,7 @@ /* Convert decimal string `s` of (at most) length `length` to 64-bit and place in 128-bit `t` */ INTERNAL void large_load_str_u64(large_int *t, const unsigned char *s, const int length) { uint64_t val = 0; - const unsigned char *se = s + length; + const unsigned char *const se = s + length; for (; s < se && *s >= '0' && *s <= '9'; s++) { val *= 10; val += *s - '0'; diff --git a/backend/library.c b/backend/library.c index e17bb209..e18131ea 100644 --- a/backend/library.c +++ b/backend/library.c @@ -41,8 +41,6 @@ #include "gs1.h" #include "zfiletypes.h" -#define TECHNETIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" - /* It's assumed that int is at least 32 bits, the following will compile-time fail if not * https://stackoverflow.com/a/1980056 */ typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? -1 : 1]; @@ -51,11 +49,9 @@ typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? struct zint_symbol *ZBarcode_Create() { struct zint_symbol *symbol; - symbol = (struct zint_symbol *) malloc(sizeof(*symbol)); + symbol = (struct zint_symbol *) calloc(1, sizeof(*symbol)); if (!symbol) return NULL; - memset(symbol, 0, sizeof(*symbol)); - symbol->symbology = BARCODE_CODE128; symbol->scale = 1.0f; strcpy(symbol->fgcolour, "000000"); @@ -86,14 +82,12 @@ INTERNAL void vector_free(struct zint_symbol *symbol); /* Free vector structures /* Free any output buffers that may have been created and initialize output fields */ void ZBarcode_Clear(struct zint_symbol *symbol) { - int i, j; + int i; if (!symbol) return; for (i = 0; i < symbol->rows; i++) { - for (j = 0; j < symbol->width; j++) { - unset_module(symbol, i, j); - } + memset(symbol->encoded_data[i], 0, sizeof(symbol->encoded_data[0])); } symbol->rows = 0; symbol->width = 0; @@ -209,8 +203,8 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ STATIC_UNLESS_ZINT_TEST int error_tag(struct zint_symbol *symbol, int error_number, const char *error_string) { if (error_number != 0) { - static const char *error_fmt = "Error %.93s"; /* Truncate if too long */ - static const char *warn_fmt = "Warning %.91s"; /* Truncate if too long */ + static const char error_fmt[] = "Error %.93s"; /* Truncate if too long */ + static const char warn_fmt[] = "Warning %.91s"; /* Truncate if too long */ const char *fmt = error_number >= ZINT_ERROR ? error_fmt : warn_fmt; char error_buffer[100]; @@ -291,61 +285,36 @@ static int dump_plot(struct zint_symbol *symbol) { return 0; } +static const char TECHNETIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; /* Same as SILVER (CODE39) */ + /* Process health industry bar code data */ static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) { int i; int counter, error_number = 0; - char to_process[113], check_digit; + char to_process[110 + 2 + 1]; + int posns[110]; /* without "+" and check: max 110 characters in HIBC 2.6 */ if (length > 110) { strcpy(symbol->errtxt, "202: Data too long for HIBC LIC (110 character maximum)"); return ZINT_ERROR_TOO_LONG; } - to_upper(source); - if (is_sane(TECHNETIUM, source, length) != 0) { + to_upper(source, length); + if (!is_sane_lookup(TECHNETIUM, sizeof(TECHNETIUM) - 1, source, length, posns)) { strcpy(symbol->errtxt, "203: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)"); return ZINT_ERROR_INVALID_DATA; } counter = 41; for (i = 0; i < length; i++) { - counter += posn(TECHNETIUM, source[i]); + counter += posns[i]; } counter = counter % 43; - if (counter < 10) { - check_digit = itoc(counter); - } else { - if (counter < 36) { - check_digit = (counter - 10) + 'A'; - } else { - switch (counter) { - case 36: check_digit = '-'; - break; - case 37: check_digit = '.'; - break; - case 38: check_digit = ' '; - break; - case 39: check_digit = '$'; - break; - case 40: check_digit = '/'; - break; - case 41: check_digit = '+'; - break; - case 42: check_digit = '%'; - break; - default: check_digit = ' '; - break; /* Keep compiler happy */ - } - } - } - to_process[0] = '+'; memcpy(to_process + 1, source, length); - to_process[length + 1] = check_digit; - length += 2; - to_process[length] = '\0'; + to_process[++length] = TECHNETIUM[counter]; + to_process[++length] = '\0'; switch (symbol->symbology) { case BARCODE_HIBC_128: @@ -538,7 +507,7 @@ static int has_hrt(const int symbology) { /* Used for dispatching barcodes and for whether symbol id valid */ typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char *, int); -static const barcode_func_t barcode_funcs[146] = { +static const barcode_func_t barcode_funcs[BARCODE_LAST + 1] = { NULL, code11, c25standard, c25inter, c25iata, /*0-4*/ NULL, c25logic, c25ind, code39, excode39, /*5-9*/ NULL, NULL, NULL, eanx, eanx, /*10-14*/ @@ -895,7 +864,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int symbol->symbology = BARCODE_CODE128; } /* Everything from 128 up is Zint-specific */ - } else if (symbol->symbology > 145) { + } else if (symbol->symbology > BARCODE_LAST) { warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "216: Symbology out of range"); if (warn_number >= ZINT_ERROR) { return warn_number; @@ -1033,10 +1002,8 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int return error_number; } -/* Output a previously encoded symbol to file `symbol->outfile` */ -int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { - int error_number; - int len; +/* Helper for output routines to check `rotate_angle` and dottiness */ +static int check_output_args(struct zint_symbol *symbol, int rotate_angle) { if (!symbol) return ZINT_ERROR_INVALID_DATA; @@ -1051,10 +1018,20 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { break; } - if (symbol->output_options & BARCODE_DOTTY_MODE) { - if (!(is_dotty(symbol->symbology))) { - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "224: Selected symbology cannot be rendered as dots"); - } + if ((symbol->output_options & BARCODE_DOTTY_MODE) && !(is_dotty(symbol->symbology))) { + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "224: Selected symbology cannot be rendered as dots"); + } + + return 0; +} + +/* Output a previously encoded symbol to file `symbol->outfile` */ +int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { + int error_number; + int len; + + if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */ + return error_number; /* Already tagged */ } len = (int) strlen(symbol->outfile); @@ -1064,7 +1041,7 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { output[1] = symbol->outfile[len - 2]; output[2] = symbol->outfile[len - 1]; output[3] = '\0'; - to_upper((unsigned char *) output); + to_upper((unsigned char *) output, 3); if (!(strcmp(output, "PNG"))) { error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE); @@ -1107,23 +1084,8 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) { int error_number; - if (!symbol) return ZINT_ERROR_INVALID_DATA; - - switch (rotate_angle) { - case 0: - case 90: - case 180: - case 270: - break; - default: - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "228: Invalid rotation angle"); - break; - } - - if (symbol->output_options & BARCODE_DOTTY_MODE) { - if (!(is_dotty(symbol->symbology))) { - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "237: Selected symbology cannot be rendered as dots"); - } + if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */ + return error_number; /* Already tagged */ } error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER); @@ -1134,23 +1096,8 @@ int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) { int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) { int error_number; - if (!symbol) return ZINT_ERROR_INVALID_DATA; - - switch (rotate_angle) { - case 0: - case 90: - case 180: - case 270: - break; - default: - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "219: Invalid rotation angle"); - break; - } - - if (symbol->output_options & BARCODE_DOTTY_MODE) { - if (!(is_dotty(symbol->symbology))) { - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "238: Selected symbology cannot be rendered as dots"); - } + if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */ + return error_number; /* Already tagged */ } error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER); @@ -1350,7 +1297,7 @@ int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, const cha /* Checks whether a symbology is supported */ int ZBarcode_ValidID(int symbol_id) { - if (symbol_id <= 0 || symbol_id > 145) { + if (symbol_id <= 0 || symbol_id > BARCODE_LAST) { return 0; } @@ -1387,7 +1334,7 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) { result |= ZINT_CAP_DOTTY; } if (cap_flag & ZINT_CAP_QUIET_ZONES) { - switch (symbol_id) { /* See `quiet_zones()` in "output.c" */ + switch (symbol_id) { /* See `out_quiet_zones()` in "output.c" */ case BARCODE_CODE16K: case BARCODE_CODE49: case BARCODE_CODABLOCKF: diff --git a/backend/mailmark.c b/backend/mailmark.c index 79a92610..f80fb1e1 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -49,7 +49,7 @@ #include "large.h" #include "reedsol.h" -#define RUBIDIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " +#define RUBIDIUM_F (IS_NUM_F | IS_UPR_F | IS_SPC_F) /* RUBIDIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " */ // Allowed character values from Table 3 #define SET_F "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -57,8 +57,10 @@ #define SET_N "0123456789" #define SET_S " " -static const char *postcode_format[6] = { - "FNFNLLNLS", "FFNNLLNLS", "FFNNNLLNL", "FFNFNLLNL", "FNNLLNLSS", "FNNNLLNLS" +static const char postcode_format[6][9] = { + {'F','N','F','N','L','L','N','L','S'}, {'F','F','N','N','L','L','N','L','S'}, + {'F','F','N','N','N','L','L','N','L'}, {'F','F','N','F','N','L','L','N','L'}, + {'F','N','N','L','L','N','L','S','S'}, {'F','N','N','N','L','L','N','L','S'} }; // Data/Check Symbols from Table 5 @@ -109,9 +111,7 @@ static int verify_character(char input, char type) { static int verify_postcode(char *postcode, int type) { int i; - char pattern[11]; - - strcpy(pattern, postcode_format[type - 1]); + const char *const pattern = postcode_format[type - 1]; for (i = 0; i < 9; i++) { if (!(verify_character(postcode[i], pattern[i]))) { @@ -122,7 +122,7 @@ static int verify_postcode(char *postcode, int type) { return 0; } -INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height); +INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height); /* Royal Mail Mailmark */ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int length) { @@ -135,7 +135,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le unsigned int item_id; char postcode[10]; int postcode_type; - char pattern[10]; + const char *pattern; large_int destination_postcode; large_int b; large_int cdv; @@ -144,6 +144,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le unsigned char check[7]; unsigned int extender[27]; char bar[80]; + char *d = bar; int check_count; int i, j, len; rs_t rs; @@ -170,13 +171,13 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le length = 26; } - to_upper((unsigned char *) local_source); + to_upper((unsigned char *) local_source, length); if (symbol->debug & ZINT_DEBUG_PRINT) { printf("Producing Mailmark %s\n", local_source); } - if (is_sane(RUBIDIUM, (unsigned char *) local_source, length) != 0) { + if (!is_sane(RUBIDIUM_F, (unsigned char *) local_source, length)) { strcpy(symbol->errtxt, "581: Invalid character in data (alphanumerics and space only)"); return ZINT_ERROR_INVALID_DATA; } @@ -285,7 +286,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le large_load_u64(&destination_postcode, 0); if (postcode_type != 7) { - strcpy(pattern, postcode_format[postcode_type - 1]); + pattern = postcode_format[postcode_type - 1]; large_load_u64(&b, 0); @@ -440,45 +441,42 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le } // Conversion from Extender Groups to Bar Identifiers - strcpy(bar, ""); for (i = 0; i < length; i++) { for (j = 0; j < 3; j++) { switch (extender[i] & 0x24) { case 0x24: - strcat(bar, "F"); + *d++ = 'F'; break; case 0x20: if (i % 2) { - strcat(bar, "D"); + *d++ = 'D'; } else { - strcat(bar, "A"); + *d++ = 'A'; } break; case 0x04: if (i % 2) { - strcat(bar, "A"); + *d++ = 'A'; } else { - strcat(bar, "D"); + *d++ = 'D'; } break; default: - strcat(bar, "T"); + *d++ = 'T'; break; } extender[i] = extender[i] << 1; } } - bar[(length * 3)] = '\0'; - if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Bar pattern: %s\n", bar); + printf("Bar pattern: %.*s\n", (int) (d - bar), bar); } /* Translate 4-state data pattern to symbol */ j = 0; - for (i = 0, len = (int) strlen(bar); i < len; i++) { + for (i = 0, len = d - bar; i < len; i++) { if ((bar[i] == 'F') || (bar[i] == 'A')) { set_module(symbol, 0, j); } diff --git a/backend/maxicode.c b/backend/maxicode.c index 5e4a28a7..94034278 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -612,7 +612,7 @@ INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int le postcode[i] = ' '; } /* Upper-case and check for Code Set A characters only */ - to_upper(postcode); + to_upper(postcode, postcode_len); for (i = 0; i < 6; i++) { /* Don't allow Code Set A control characters CR, RS, GS and RS */ if (postcode[i] < ' ' || maxiCodeSet[postcode[i]] > 1) { diff --git a/backend/medical.c b/backend/medical.c index a488c7d6..b2477ba9 100644 --- a/backend/medical.c +++ b/backend/medical.c @@ -36,15 +36,18 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length); +static const char CALCIUM[] = "0123456789-$:/.+ABCD"; +#define CALCIUM_INNER_F (IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F) /* CALCIUM_INNER "0123456789-$:/.+" */ + /* Codabar table checked against EN 798:1995 */ - -#define CALCIUM "0123456789-$:/.+ABCD" -#define CALCIUM_INNER "0123456789-$:/.+" - -static const char *CodaTable[20] = { - "11111221", "11112211", "11121121", "22111111", "11211211", "21111211", - "12111121", "12112111", "12211111", "21121111", "11122111", "11221111", "21112121", "21211121", - "21212111", "11212121", "11221211", "12121121", "11121221", "11122211" +static const char CodaTable[20][8] = { + {'1','1','1','1','1','2','2','1'}, {'1','1','1','1','2','2','1','1'}, {'1','1','1','2','1','1','2','1'}, + {'2','2','1','1','1','1','1','1'}, {'1','1','2','1','1','2','1','1'}, {'2','1','1','1','1','2','1','1'}, + {'1','2','1','1','1','1','2','1'}, {'1','2','1','1','2','1','1','1'}, {'1','2','2','1','1','1','1','1'}, + {'2','1','1','2','1','1','1','1'}, {'1','1','1','2','2','1','1','1'}, {'1','1','2','2','1','1','1','1'}, + {'2','1','1','1','2','1','2','1'}, {'2','1','2','1','1','1','2','1'}, {'2','1','2','1','2','1','1','1'}, + {'1','1','2','1','2','1','2','1'}, {'1','1','2','2','1','2','1','1'}, {'1','2','1','2','1','1','2','1'}, + {'1','1','1','2','1','2','2','1'}, {'1','1','1','2','2','2','1','1'} }; INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int length) { @@ -61,22 +64,23 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng the specification at http://www.laetus.com/laetus.php?request=file&id=69 (http://www.gomaro.ch/ftproot/Laetus_PHARMA-CODE.pdf) */ - unsigned long int tester; + int tester; int counter, error_number = 0, h; char inter[18] = {0}; /* 131070 -> 17 bits */ + char *in = inter; char dest[64]; /* 17 * 2 + 1 */ + char *d = dest; if (length > 6) { strcpy(symbol->errtxt, "350: Input too long (6 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + tester = to_int(source, length); + if (tester == -1) { strcpy(symbol->errtxt, "351: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } - tester = atoi((char *) source); - if ((tester < 3) || (tester > 131070)) { strcpy(symbol->errtxt, "352: Data out of range (3 to 131070)"); return ZINT_ERROR_INVALID_DATA; @@ -84,25 +88,22 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng do { if (!(tester & 1)) { - strcat(inter, "W"); + *in++ = 'W'; tester = (tester - 2) / 2; } else { - strcat(inter, "N"); + *in++ = 'N'; tester = (tester - 1) / 2; } } while (tester != 0); - h = (int) strlen(inter) - 1; - *dest = '\0'; - for (counter = h; counter >= 0; counter--) { - if (inter[counter] == 'W') { - strcat(dest, "32"); - } else { - strcat(dest, "12"); - } + h = in - inter; + for (counter = h - 1; counter >= 0; counter--) { + *d++ = inter[counter] == 'W' ? '3' : '1'; + *d++ = '2'; } + *--d = '\0'; /* Chop off final bar */ - expand(symbol, dest); + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* Laetus Pharmacode Guide 1.2 Standard one-track height 8mm / 0.5mm (X) */ @@ -114,75 +115,66 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng return error_number; } -static int pharma_two_calc(struct zint_symbol *symbol, unsigned char source[], char dest[]) { +static int pharma_two_calc(int tester, char *d) { /* This code uses the Two Track Pharamacode defined in the document at http://www.laetus.com/laetus.php?request=file&id=69 and using a modified algorithm from the One Track system. This standard accepts integet values from 4 to 64570080. */ - unsigned long int tester; int counter, h; char inter[17]; - int error_number; + char *in = inter; - tester = atoi((char *) source); - - if ((tester < 4) || (tester > 64570080)) { - strcpy(symbol->errtxt, "353: Data out of range (4 to 64570080)"); - return ZINT_ERROR_INVALID_DATA; - } - error_number = 0; - strcpy(inter, ""); do { switch (tester % 3) { case 0: - strcat(inter, "3"); + *in++ = '3'; tester = (tester - 3) / 3; break; case 1: - strcat(inter, "1"); + *in++ = '1'; tester = (tester - 1) / 3; break; case 2: - strcat(inter, "2"); + *in++ = '2'; tester = (tester - 2) / 3; break; } } while (tester != 0); - h = (int) strlen(inter) - 1; - for (counter = h; counter >= 0; counter--) { - dest[h - counter] = inter[counter]; + h = in - inter; + for (counter = h - 1; counter >= 0; counter--) { + *d++ = inter[counter]; } - dest[h + 1] = '\0'; + *d = '\0'; - return error_number; + return h; } INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length) { /* Draws the patterns for two track pharmacode */ + int tester; char height_pattern[200]; unsigned int loopey, h; int writer; - int error_number; - - strcpy(height_pattern, ""); + int error_number = 0; if (length > 8) { strcpy(symbol->errtxt, "354: Input too long (8 character maximum"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + tester = to_int(source, length); + if (tester == -1) { strcpy(symbol->errtxt, "355: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } - error_number = pharma_two_calc(symbol, source, height_pattern); - if (error_number != 0) { - return error_number; + if ((tester < 4) || (tester > 64570080)) { + strcpy(symbol->errtxt, "353: Data out of range (4 to 64570080)"); + return ZINT_ERROR_INVALID_DATA; } + h = pharma_two_calc(tester, height_pattern); writer = 0; - h = (int) strlen(height_pattern); for (loopey = 0; loopey < h; loopey++) { if ((height_pattern[loopey] == '2') || (height_pattern[loopey] == '3')) { set_module(symbol, 0, writer); @@ -209,14 +201,13 @@ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int /* The Codabar system consisting of simple substitution */ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length) { - static const char calcium[] = CALCIUM; int i, error_number = 0; + int posns[60]; char dest[512]; + char *d = dest; int add_checksum, count = 0, checksum = 0; int d_chars = 0; - strcpy(dest, ""); - if (length > 60) { /* No stack smashing please */ strcpy(symbol->errtxt, "356: Input too long (60 character maximum)"); return ZINT_ERROR_TOO_LONG; @@ -227,7 +218,7 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len strcpy(symbol->errtxt, "362: Input too short (3 character minimum)"); return ZINT_ERROR_TOO_LONG; } - to_upper(source); + to_upper(source, length); /* Codabar must begin and end with the characters A, B, C or D */ if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C') @@ -240,14 +231,13 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len strcpy(symbol->errtxt, "359: Does not end with \"A\", \"B\", \"C\" or \"D\""); return ZINT_ERROR_INVALID_DATA; } - + if (!is_sane_lookup(CALCIUM, sizeof(CALCIUM) - 1, source, length, posns)) { + sprintf(symbol->errtxt, "357: Invalid character in data (\"%s\" only)", CALCIUM); + return ZINT_ERROR_INVALID_DATA; + } /* And must not use A, B, C or D otherwise (BS EN 798:1995 4.3.2) */ - if (is_sane(CALCIUM_INNER, source + 1, length - 2) != 0) { - if (is_sane(calcium, source + 1, length - 2) == 0) { - strcpy(symbol->errtxt, "363: Cannot contain \"A\", \"B\", \"C\" or \"D\""); - } else { - sprintf(symbol->errtxt, "357: Invalid character in data (\"%s\" only)", calcium); - } + if (!is_sane(CALCIUM_INNER_F, source + 1, length - 2)) { + strcpy(symbol->errtxt, "363: Cannot contain \"A\", \"B\", \"C\" or \"D\""); return ZINT_ERROR_INVALID_DATA; } @@ -255,29 +245,30 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len (unfortunately to maintain back-compatibility, this is reverse of C25) */ add_checksum = symbol->option_2 == 1 || symbol->option_2 == 2; - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++, d += 8) { if (add_checksum) { /* BS EN 798:1995 A.3 suggests using ISO 7064 algorithm but leaves it application defined. Following BWIPP and TEC-IT, use this simple mod-16 algorithm (not in ISO 7064) */ - count += strchr(calcium, source[i]) - calcium; + count += posns[i]; if (i + 1 == length) { checksum = count % 16; if (checksum) { checksum = 16 - checksum; } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("Codabar: %s, count %d, checksum %d (%c)\n", source, count, checksum, calcium[checksum]); + printf("Codabar: %s, count %d, checksum %d (%c)\n", source, count, checksum, CALCIUM[checksum]); } - strcat(dest, CodaTable[checksum]); + memcpy(d, CodaTable[checksum], 8); + d += 8; } } - lookup(calcium, CodaTable, source[i], dest); + memcpy(d, CodaTable[posns[i]], 8); if (source[i] == '/' || source[i] == ':' || source[i] == '.' || source[i] == '+') { /* Wide data characters */ d_chars++; } } - expand(symbol, dest); + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.191mm (X) ~ 26.178 or 15% of width where (taking N = narrow/wide @@ -297,7 +288,7 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len 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 - 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'; } @@ -307,18 +298,18 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len /* Italian Pharmacode */ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length) { + static const char TABELLA[] = "0123456789BCDFGHJKLMNPQRSTUVWXYZ"; int i, zeroes, error_number = 0, checksum, checkpart, checkdigit; char localstr[10], risultante[7]; long int pharmacode, devisor; int codeword[6]; - char tabella[34]; /* Validate the input */ if (length > 8) { strcpy(symbol->errtxt, "360: Input too long (8 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "361: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -360,13 +351,12 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng } /* Look up values in 'Tabella di conversione' */ - strcpy(tabella, "0123456789BCDFGHJKLMNPQRSTUVWXYZ"); for (i = 5; i >= 0; i--) { - risultante[5 - i] = tabella[codeword[i]]; + risultante[5 - i] = TABELLA[codeword[i]]; } risultante[6] = '\0'; /* Plot the barcode using Code 39 */ - error_number = code39(symbol, (unsigned char *) risultante, (int) strlen(risultante)); + error_number = code39(symbol, (unsigned char *) risultante, 6); if (error_number != 0) { /* Should never happen */ return error_number; /* Not reached */ } diff --git a/backend/output.c b/backend/output.c index b0a563cb..19e8922f 100644 --- a/backend/output.c +++ b/backend/output.c @@ -35,32 +35,31 @@ #include "output.h" #include "font.h" -#define SSET "0123456789ABCDEF" +#define SSET_F (IS_NUM_F | IS_UHX_F) /* SSET "0123456789ABCDEF" */ /* Check colour options are good. Note: using raster.c error nos 651-654 */ -INTERNAL int output_check_colour_options(struct zint_symbol *symbol) { - int error_number; +INTERNAL int out_check_colour_options(struct zint_symbol *symbol) { + int fg_len = (int) strlen(symbol->fgcolour); + int bg_len = (int) strlen(symbol->bgcolour); - if ((strlen(symbol->fgcolour) != 6) && (strlen(symbol->fgcolour) != 8)) { + if ((fg_len != 6) && (fg_len != 8)) { strcpy(symbol->errtxt, "651: Malformed foreground colour target"); return ZINT_ERROR_INVALID_OPTION; } - if ((strlen(symbol->bgcolour) != 6) && (strlen(symbol->bgcolour) != 8)) { + if ((bg_len != 6) && (bg_len != 8)) { strcpy(symbol->errtxt, "652: Malformed background colour target"); return ZINT_ERROR_INVALID_OPTION; } - to_upper((unsigned char *) symbol->fgcolour); - to_upper((unsigned char *) symbol->bgcolour); + to_upper((unsigned char *) symbol->fgcolour, fg_len); + to_upper((unsigned char *) symbol->bgcolour, bg_len); - error_number = is_sane(SSET, (unsigned char *) symbol->fgcolour, (int) strlen(symbol->fgcolour)); - if (error_number == ZINT_ERROR_INVALID_DATA) { + if (!is_sane(SSET_F, (unsigned char *) symbol->fgcolour, fg_len)) { strcpy(symbol->errtxt, "653: Malformed foreground colour target"); return ZINT_ERROR_INVALID_OPTION; } - error_number = is_sane(SSET, (unsigned char *) symbol->bgcolour, (int) strlen(symbol->bgcolour)); - if (error_number == ZINT_ERROR_INVALID_DATA) { + if (!is_sane(SSET_F, (unsigned char *) symbol->bgcolour, bg_len)) { strcpy(symbol->errtxt, "654: Malformed background colour target"); return ZINT_ERROR_INVALID_OPTION; } @@ -69,7 +68,7 @@ INTERNAL int output_check_colour_options(struct zint_symbol *symbol) { } /* Return minimum quiet zones for each symbology */ -STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const int hide_text, +STATIC_UNLESS_ZINT_TEST int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text, float *left, float *right, float *top, float *bottom) { int done = 0; @@ -192,7 +191,7 @@ STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const /* Only do others if flag set */ if (!(symbol->output_options & BARCODE_QUIET_ZONES) || (symbol->output_options & BARCODE_NO_QUIET_ZONES)) { - return done; + return 0; } switch (symbol->symbology) { @@ -471,12 +470,12 @@ STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const } /* Set left (x), top (y), right and bottom offsets for whitespace */ -INTERNAL void output_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, +INTERNAL void out_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler, int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si) { float qz_left, qz_right, qz_top, qz_bottom; - quiet_zones(symbol, hide_text, &qz_left, &qz_right, &qz_top, &qz_bottom); + out_quiet_zones(symbol, hide_text, &qz_left, &qz_right, &qz_top, &qz_bottom); *xoffset = symbol->whitespace_width + qz_left; *roffset = symbol->whitespace_width + qz_right; @@ -510,7 +509,7 @@ INTERNAL void output_set_whitespace_offsets(const struct zint_symbol *symbol, co /* Set composite offset and main width excluding addon (for start of addon calc) and addon text, returning UPC/EAN type */ -INTERNAL int output_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset, +INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset, unsigned char addon[6], int *p_addon_gap) { int main_width; /* Width of main linear symbol, excluding addon */ int comp_xoffset; /* Whitespace offset (if any) of main linear symbol due to having composite */ @@ -588,9 +587,9 @@ INTERNAL int output_process_upcean(const struct zint_symbol *symbol, int *p_main } /* Calculate large bar height i.e. linear bars with zero row height that respond to the symbol height. - If scaler `si` non-zero (raster), then large_bar_height if non-zero or else row heights will be rounded to nearest - pixel and symbol height adjusted */ -INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) { + If scaler `si` non-zero (raster), then large_bar_height if non-zero or else row heights will be rounded + to nearest pixel and symbol height adjusted */ +INTERNAL float out_large_bar_height(struct zint_symbol *symbol, int si) { float fixed_height = 0.0f; int zero_count = 0; int round_rows = 0; @@ -609,15 +608,14 @@ INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) { } if (zero_count) { - large_bar_height = (symbol->height - fixed_height) / zero_count; + large_bar_height = stripf((symbol->height - fixed_height) / zero_count); if (large_bar_height <= 0.0f) { /* Shouldn't happen but protect against memory access violations */ large_bar_height = 0.0078125f; /* Token positive value (exact float 2**-6) */ - symbol->height = large_bar_height * zero_count + fixed_height; } if (si && !isfintf(large_bar_height * si)) { - large_bar_height = roundf(large_bar_height * si) / si; - symbol->height = large_bar_height * zero_count + fixed_height; + large_bar_height = stripf(roundf(large_bar_height * si) / si); } + symbol->height = stripf(large_bar_height * zero_count + fixed_height); /* Note should never happen that have both zero_count and round_rows */ } else { large_bar_height = 0.0f; /* Not used if zero_count zero */ @@ -629,7 +627,7 @@ INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) { } fixed_height += symbol->row_height[i]; } - symbol->height = fixed_height; + symbol->height = stripf(fixed_height); } } @@ -637,7 +635,7 @@ INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) { } /* Split UPC/EAN add-on text into various constituents */ -INTERNAL void output_upcean_split_text(int upceanflag, unsigned char text[], +INTERNAL void out_upcean_split_text(int upceanflag, unsigned char text[], unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7], unsigned char textpart4[2]) { int i; diff --git a/backend/output.h b/backend/output.h index fadaf1d2..99da9e5f 100644 --- a/backend/output.h +++ b/backend/output.h @@ -37,14 +37,14 @@ extern "C" { #endif /* __cplusplus */ -INTERNAL int output_check_colour_options(struct zint_symbol *symbol); -INTERNAL void output_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, +INTERNAL int out_check_colour_options(struct zint_symbol *symbol); +INTERNAL void out_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler, int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si); -INTERNAL int output_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset, +INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset, unsigned char addon[6], int *p_addon_gap); -INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si); -INTERNAL void output_upcean_split_text(int upceanflag, unsigned char text[], +INTERNAL float out_large_bar_height(struct zint_symbol *symbol, int si); +INTERNAL void out_upcean_split_text(int upceanflag, unsigned char text[], unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7], unsigned char textpart4[2]); diff --git a/backend/plessey.c b/backend/plessey.c index 70322c8d..4471ea0e 100644 --- a/backend/plessey.c +++ b/backend/plessey.c @@ -34,50 +34,51 @@ #include #include "common.h" -#define SSET "0123456789ABCDEF" +#define SSET_F (IS_NUM_F | IS_UHX_F) /* SSET "0123456789ABCDEF" */ -static const char *PlessTable[16] = { - "13131313", "31131313", "13311313", "31311313", - "13133113", "31133113", "13313113", "31313113", - "13131331", "31131331", "13311331", "31311331", - "13133131", "31133131", "13313131", "31313131" +static const char PlessTable[16][8] = { + {'1','3','1','3','1','3','1','3'}, {'3','1','1','3','1','3','1','3'}, {'1','3','3','1','1','3','1','3'}, + {'3','1','3','1','1','3','1','3'}, {'1','3','1','3','3','1','1','3'}, {'3','1','1','3','3','1','1','3'}, + {'1','3','3','1','3','1','1','3'}, {'3','1','3','1','3','1','1','3'}, {'1','3','1','3','1','3','3','1'}, + {'3','1','1','3','1','3','3','1'}, {'1','3','3','1','1','3','3','1'}, {'3','1','3','1','1','3','3','1'}, + {'1','3','1','3','3','1','3','1'}, {'3','1','1','3','3','1','3','1'}, {'1','3','3','1','3','1','3','1'}, + {'3','1','3','1','3','1','3','1'} }; -static const char *MSITable[10] = { - "12121212", "12121221", "12122112", "12122121", "12211212", - "12211221", "12212112", "12212121", "21121212", "21121221" +static const char MSITable[10][8] = { + {'1','2','1','2','1','2','1','2'}, {'1','2','1','2','1','2','2','1'}, {'1','2','1','2','2','1','1','2'}, + {'1','2','1','2','2','1','2','1'}, {'1','2','2','1','1','2','1','2'}, {'1','2','2','1','1','2','2','1'}, + {'1','2','2','1','2','1','1','2'}, {'1','2','2','1','2','1','2','1'}, {'2','1','1','2','1','2','1','2'}, + {'2','1','1','2','1','2','2','1'} }; /* Not MSI/Plessey but the older Plessey standard */ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int length) { int i; - unsigned char *checkptr; + unsigned char checkptr[65 * 4 + 8] = {0}; static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1}; char dest[554]; /* 8 + 65 * 8 + 8 * 2 + 9 + 1 = 554 */ + char *d = dest; int error_number = 0; if (length > 65) { strcpy(symbol->errtxt, "370: Input too long (65 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(SSET, source, length) != 0) { + if (!is_sane(SSET_F, source, length)) { strcpy(symbol->errtxt, "371: Invalid character in data (digits and \"ABCDEF\" only)"); return ZINT_ERROR_INVALID_DATA; } - if (!(checkptr = (unsigned char *) calloc(1, length * 4 + 8))) { - strcpy(symbol->errtxt, "373: Insufficient memory for check digit CRC buffer"); - return ZINT_ERROR_MEMORY; - } - /* Start character */ - strcpy(dest, "31311331"); + memcpy(d, "31311331", 8); + d += 8; /* Data area */ - for (i = 0; i < length; i++) { - unsigned int check = posn(SSET, source[i]); - lookup(SSET, PlessTable, source[i], dest); + for (i = 0; i < length; i++, d += 8) { + 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; checkptr[4 * i + 2] = (check >> 2) & 1; @@ -97,24 +98,26 @@ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int len for (i = 0; i < 8; i++) { switch (checkptr[length * 4 + i]) { - case 0: strcat(dest, "13"); + case 0: memcpy(d, "13", 2); + d += 2; break; - case 1: strcat(dest, "31"); + case 1: memcpy(d, "31", 2); + d += 2; break; } } /* Stop character */ - strcat(dest, "331311313"); + memcpy(d, "331311313", 9); + d += 9; - expand(symbol, dest); + expand(symbol, dest, d - dest); // TODO: Find documentation on BARCODE_PLESSEY dimensions/height symbol->text[0] = '\0'; ustrncat(symbol->text, source, length); - free(checkptr); return error_number; } @@ -154,35 +157,38 @@ static char msi_check_digit_mod11(const unsigned char source[], const int length } /* Plain MSI Plessey - does not calculate any check character */ -static void msi_plessey_nomod(struct zint_symbol *symbol, const unsigned char source[], const int length, - char dest[]) { +static char *msi_plessey_nomod(struct zint_symbol *symbol, const unsigned char source[], const int length, + char *d) { int i; - for (i = 0; i < length; i++) { - lookup(NEON, MSITable, source[i], dest); + for (i = 0; i < length; i++, d += 8) { + memcpy(d, MSITable[source[i] - '0'], 8); } symbol->text[0] = '\0'; ustrncat(symbol->text, source, length); + + return d; } /* MSI Plessey with Modulo 10 check digit */ -static void msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char source[], const int length, - const int no_checktext, char dest[]) { +static char *msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int no_checktext, char *d) { int i; char check_digit; /* draw data section */ - for (i = 0; i < length; i++) { - lookup(NEON, MSITable, source[i], dest); + for (i = 0; i < length; i++, d += 8) { + memcpy(d, MSITable[source[i] - '0'], 8); } /* calculate check digit */ check_digit = msi_check_digit_mod10(source, length); /* draw check digit */ - lookup(NEON, MSITable, check_digit, dest); + memcpy(d, MSITable[check_digit - '0'], 8); + d += 8; symbol->text[0] = '\0'; ustrncat(symbol->text, source, length); @@ -190,11 +196,13 @@ static void msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char so symbol->text[length] = check_digit; symbol->text[length + 1] = '\0'; } + + return d; } /* MSI Plessey with two Modulo 10 check digits */ -static void msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char source[], const int length, - const int no_checktext, char dest[]) { +static char *msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int no_checktext, char *d) { int i; unsigned char temp[65 + 2 + 1]; @@ -207,8 +215,8 @@ static void msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char temp[length + 2] = '\0'; /* draw data section */ - for (i = 0; i < length + 2; i++) { - lookup(NEON, MSITable, temp[i], dest); + for (i = 0; i < length + 2; i++, d += 8) { + memcpy(d, MSITable[temp[i] - '0'], 8); } if (no_checktext) { @@ -217,27 +225,32 @@ static void msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char } else { ustrcpy(symbol->text, temp); } + + return d; } /* MSI Plessey with Modulo 11 check digit */ -static void msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char source[], const int length, - const int no_checktext, const int wrap, char dest[]) { +static char *msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int no_checktext, const int wrap, char *d) { /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ int i; char check_digit; /* draw data section */ - for (i = 0; i < length; i++) { - lookup(NEON, MSITable, source[i], dest); + for (i = 0; i < length; i++, d += 8) { + memcpy(d, MSITable[source[i] - '0'], 8); } /* Append check digit */ check_digit = msi_check_digit_mod11(source, length, wrap); if (check_digit == 'A') { - lookup(NEON, MSITable, '1', dest); - lookup(NEON, MSITable, '0', dest); + memcpy(d, MSITable[1], 8); + d += 8; + memcpy(d, MSITable[0], 8); + d += 8; } else { - lookup(NEON, MSITable, check_digit, dest); + memcpy(d, MSITable[check_digit - '0'], 8); + d += 8; } symbol->text[0] = '\0'; @@ -250,11 +263,13 @@ static void msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char so symbol->text[length + 1] = '\0'; } } + + return d; } /* MSI Plessey with Modulo 11 check digit and Modulo 10 check digit */ -static void msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char source[], const int length, - const int no_checktext, const int wrap, char dest[]) { +static char *msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int no_checktext, const int wrap, char *d) { /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ int i; char check_digit; @@ -278,8 +293,8 @@ static void msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char temp[++temp_len] = '\0'; /* draw data section */ - for (i = 0; i < temp_len; i++) { - lookup(NEON, MSITable, temp[i], dest); + for (i = 0; i < temp_len; i++, d += 8) { + memcpy(d, MSITable[temp[i] - '0'], 8); } if (no_checktext) { @@ -288,11 +303,14 @@ static void msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char } else { ustrcpy(symbol->text, temp); } + + return d; } INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) { int error_number = 0; char dest[550]; /* 2 + 65 * 8 + 3 * 8 + 3 + 1 = 550 */ + char *d = dest; int check_option = symbol->option_2; int no_checktext = 0; @@ -300,7 +318,7 @@ INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int strcpy(symbol->errtxt, "372: Input too long (65 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "377: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -314,29 +332,31 @@ INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int } /* Start character */ - strcpy(dest, "21"); + memcpy(d, "21", 2); + d += 2; switch (check_option) { - case 0: msi_plessey_nomod(symbol, source, length, dest); + case 0: d = msi_plessey_nomod(symbol, source, length, d); break; - case 1: msi_plessey_mod10(symbol, source, length, no_checktext, dest); + case 1: d = msi_plessey_mod10(symbol, source, length, no_checktext, d); break; - case 2: msi_plessey_mod1010(symbol, source, length, no_checktext, dest); + case 2: d = msi_plessey_mod1010(symbol, source, length, no_checktext, d); break; - case 3: msi_plessey_mod11(symbol, source, length, no_checktext, 7 /*IBM wrap*/, dest); + case 3: d = msi_plessey_mod11(symbol, source, length, no_checktext, 7 /*IBM wrap*/, d); break; - case 4: msi_plessey_mod1110(symbol, source, length, no_checktext, 7 /*IBM wrap*/, dest); + case 4: d = msi_plessey_mod1110(symbol, source, length, no_checktext, 7 /*IBM wrap*/, d); break; - case 5: msi_plessey_mod11(symbol, source, length, no_checktext, 9 /*NCR wrap*/, dest); + case 5: d = msi_plessey_mod11(symbol, source, length, no_checktext, 9 /*NCR wrap*/, d); break; - case 6: msi_plessey_mod1110(symbol, source, length, no_checktext, 9 /*NCR wrap*/, dest); + case 6: d = msi_plessey_mod1110(symbol, source, length, no_checktext, 9 /*NCR wrap*/, d); break; } /* Stop character */ - strcat(dest, "121"); + memcpy(d, "121", 3); + d += 3; - expand(symbol, dest); + expand(symbol, dest, d - dest); // TODO: Find documentation on BARCODE_MSI_PLESSEY dimensions/height diff --git a/backend/png.c b/backend/png.c index 0ebfa752..65a51f86 100644 --- a/backend/png.c +++ b/backend/png.c @@ -46,8 +46,6 @@ #include #include -#define SSET "0123456789ABCDEF" - /* Note if change this need to change "backend/tests/test_png.c" definition also */ struct wpng_error_type { struct zint_symbol *symbol; @@ -300,26 +298,34 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) pb = pixelbuf; if (bit_depth == 1) { for (row = 0; row < symbol->bitmap_height; row++) { - unsigned char *image_data = outdata; - for (column = 0; column < symbol->bitmap_width; column += 8, image_data++) { - unsigned char byte = 0; - for (i = 0; i < 8 && column + i < symbol->bitmap_width; i++, pb++) { - byte |= map[*pb] << (7 - i); + if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) { + pb += symbol->bitmap_width; + } else { + unsigned char *image_data = outdata; + for (column = 0; column < symbol->bitmap_width; column += 8, image_data++) { + unsigned char byte = 0; + for (i = 0; i < 8 && column + i < symbol->bitmap_width; i++, pb++) { + byte |= map[*pb] << (7 - i); + } + *image_data = byte; } - *image_data = byte; } /* write row contents to file */ png_write_row(png_ptr, outdata); } } else { /* Bit depth 4 */ for (row = 0; row < symbol->bitmap_height; row++) { - unsigned char *image_data = outdata; - for (column = 0; column < symbol->bitmap_width; column += 2, image_data++) { - unsigned char byte = map[*pb++] << 4; - if (column + 1 < symbol->bitmap_width) { - byte |= map[*pb++]; + if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) { + pb += symbol->bitmap_width; + } else { + unsigned char *image_data = outdata; + for (column = 0; column < symbol->bitmap_width; column += 2, image_data++) { + unsigned char byte = map[*pb++] << 4; + if (column + 1 < symbol->bitmap_width) { + byte |= map[*pb++]; + } + *image_data = byte; } - *image_data = byte; } /* write row contents to file */ png_write_row(png_ptr, outdata); diff --git a/backend/postal.c b/backend/postal.c index 7204b531..9a75d4ab 100644 --- a/backend/postal.c +++ b/backend/postal.c @@ -38,49 +38,58 @@ #endif #include "common.h" -#define DAFTSET "DAFT" -#define KRSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -#define KASUTSET "1234567890-abcdefgh" -#define CHKASUTSET "0123456789-abcdefgh" -#define SHKASUTSET "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" +static const char DAFTSET[] = "FADT"; +static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +static const char KASUTSET[] = "1234567890-abcdefgh"; +static const char CHKASUTSET[] = "0123456789-abcdefgh"; +#define SHKASUTSET_F (IS_NUM_F | IS_MNS_F | IS_UPR_F) /* SHKASUTSET "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" */ /* PostNet number encoding table - In this table L is long as S is short */ -static const char *PNTable[10] = { - "LLSSS", "SSSLL", "SSLSL", "SSLLS", "SLSSL", "SLSLS", "SLLSS", "LSSSL", - "LSSLS", "LSLSS" +static const char PNTable[10][5] = { + {'L','L','S','S','S'}, {'S','S','S','L','L'}, {'S','S','L','S','L'}, {'S','S','L','L','S'}, {'S','L','S','S','L'}, + {'S','L','S','L','S'}, {'S','L','L','S','S'}, {'L','S','S','S','L'}, {'L','S','S','L','S'}, {'L','S','L','S','S'} }; -static const char *PLTable[10] = { - "SSLLL", "LLLSS", "LLSLS", "LLSSL", "LSLLS", "LSLSL", "LSSLL", "SLLLS", - "SLLSL", "SLSLL" +static const char PLTable[10][5] = { + {'S','S','L','L','L'}, {'L','L','L','S','S'}, {'L','L','S','L','S'}, {'L','L','S','S','L'}, {'L','S','L','L','S'}, + {'L','S','L','S','L'}, {'L','S','S','L','L'}, {'S','L','L','L','S'}, {'S','L','L','S','L'}, {'S','L','S','L','L'} }; -static const char *RoyalValues[36] = { - "11", "12", "13", "14", "15", "10", "21", "22", "23", "24", "25", - "20", "31", "32", "33", "34", "35", "30", "41", "42", "43", "44", "45", "40", "51", "52", - "53", "54", "55", "50", "01", "02", "03", "04", "05", "00" +static const char RoyalValues[36][2] = { + { 1, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, { 2, 4 }, + { 2, 5 }, { 2, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 }, { 3, 4 }, { 3, 5 }, { 3, 0 }, { 4, 1 }, { 4, 2 }, + { 4, 3 }, { 4, 4 }, { 4, 5 }, { 4, 0 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 5, 4 }, { 5, 5 }, { 5, 0 }, + { 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 0 } }; /* 0 = Full, 1 = Ascender, 2 = Descender, 3 = Tracker */ -static const char *RoyalTable[36] = { - "3300", "3210", "3201", "2310", "2301", "2211", "3120", "3030", "3021", - "2130", "2121", "2031", "3102", "3012", "3003", "2112", "2103", "2013", "1320", "1230", - "1221", "0330", "0321", "0231", "1302", "1212", "1203", "0312", "0303", "0213", "1122", - "1032", "1023", "0132", "0123", "0033" +static const char RoyalTable[36][4] = { + {'3','3','0','0'}, {'3','2','1','0'}, {'3','2','0','1'}, {'2','3','1','0'}, {'2','3','0','1'}, {'2','2','1','1'}, + {'3','1','2','0'}, {'3','0','3','0'}, {'3','0','2','1'}, {'2','1','3','0'}, {'2','1','2','1'}, {'2','0','3','1'}, + {'3','1','0','2'}, {'3','0','1','2'}, {'3','0','0','3'}, {'2','1','1','2'}, {'2','1','0','3'}, {'2','0','1','3'}, + {'1','3','2','0'}, {'1','2','3','0'}, {'1','2','2','1'}, {'0','3','3','0'}, {'0','3','2','1'}, {'0','2','3','1'}, + {'1','3','0','2'}, {'1','2','1','2'}, {'1','2','0','3'}, {'0','3','1','2'}, {'0','3','0','3'}, {'0','2','1','3'}, + {'1','1','2','2'}, {'1','0','3','2'}, {'1','0','2','3'}, {'0','1','3','2'}, {'0','1','2','3'}, {'0','0','3','3'} }; -static const char *FlatTable[10] = { - "0504", "18", "0117", "0216", "0315", "0414", "0513", "0612", "0711", "0810" +static const char FlatTable[10][4] = { + {'0','5','0','4'}, { "18" }, {'0','1','1','7'}, {'0','2','1','6'}, {'0','3','1','5'}, + {'0','4','1','4'}, {'0','5','1','3'}, {'0','6','1','2'}, {'0','7','1','1'}, {'0','8','1','0'} }; -static const char *KoreaTable[10] = { - "1313150613", "0713131313", "0417131313", "1506131313", - "0413171313", "17171313", "1315061313", "0413131713", "17131713", "13171713" +static const char KoreaTable[10][10] = { + {'1','3','1','3','1','5','0','6','1','3'}, {'0','7','1','3','1','3','1','3','1','3'}, + {'0','4','1','7','1','3','1','3','1','3'}, {'1','5','0','6','1','3','1','3','1','3'}, + {'0','4','1','3','1','7','1','3','1','3'}, { "17171313" }, + {'1','3','1','5','0','6','1','3','1','3'}, {'0','4','1','3','1','3','1','7','1','3'}, + { "17131713" }, { "13171713" } }; -static const char *JapanTable[19] = { - "114", "132", "312", "123", "141", "321", "213", "231", "411", "144", - "414", "324", "342", "234", "432", "243", "423", "441", "111" +static const char JapanTable[19][3] = { + {'1','1','4'}, {'1','3','2'}, {'3','1','2'}, {'1','2','3'}, {'1','4','1'}, + {'3','2','1'}, {'2','1','3'}, {'2','3','1'}, {'4','1','1'}, {'1','4','4'}, + {'4','1','4'}, {'3','2','4'}, {'3','4','2'}, {'2','3','4'}, {'4','3','2'}, + {'2','4','3'}, {'4','2','3'}, {'4','4','1'}, {'1','1','1'} }; /* Set height for POSTNET/PLANET codes, maintaining ratio */ @@ -127,7 +136,7 @@ static int usps_set_height(struct zint_symbol *symbol, const int no_errtxt) { } /* Handles the PostNet system used for Zip codes in the US */ -static int postnet_enc(struct zint_symbol *symbol, unsigned char source[], char dest[], int length) { +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; @@ -139,25 +148,27 @@ static int postnet_enc(struct zint_symbol *symbol, unsigned char source[], char strcpy(symbol->errtxt, "479: Input length is not standard (5, 9 or 11 characters)"); error_number = ZINT_WARN_NONCOMPLIANT; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "481: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } sum = 0; /* start character */ - strcpy(dest, "L"); + *d++ = 'L'; - for (i = 0; i < length; i++) { - lookup(NEON, PNTable, source[i], dest); - sum += ctoi(source[i]); + for (i = 0; i < length; i++, d += 5) { + const int val = source[i] - '0'; + memcpy(d, PNTable[val], 5); + sum += val; } check_digit = (10 - (sum % 10)) % 10; - strcat(dest, PNTable[check_digit]); + memcpy(d, PNTable[check_digit], 5); + d += 5; /* stop character */ - strcat(dest, "L"); + strcpy(d, "L"); return error_number; } @@ -191,7 +202,7 @@ INTERNAL int postnet(struct zint_symbol *symbol, unsigned char source[], int len } /* Handles the PLANET system used for item tracking in the US */ -static int planet_enc(struct zint_symbol *symbol, unsigned char source[], char dest[], int length) { +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; @@ -203,25 +214,27 @@ static int planet_enc(struct zint_symbol *symbol, unsigned char source[], char d strcpy(symbol->errtxt, "478: Input length is not standard (11 or 13 characters)"); error_number = ZINT_WARN_NONCOMPLIANT; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "483: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } sum = 0; /* start character */ - strcpy(dest, "L"); + *d++ = 'L'; - for (i = 0; i < length; i++) { - lookup(NEON, PLTable, source[i], dest); - sum += ctoi(source[i]); + for (i = 0; i < length; i++, d += 5) { + const int val = source[i] - '0'; + memcpy(d, PLTable[val], 5); + sum += val; } check_digit = (10 - (sum % 10)) % 10; - strcat(dest, PLTable[check_digit]); + memcpy(d, PLTable[check_digit], 5); + d += 5; /* stop character */ - strcat(dest, "L"); + strcpy(d, "L"); return error_number; } @@ -258,12 +271,14 @@ INTERNAL int planet(struct zint_symbol *symbol, unsigned char source[], int leng INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int length) { int total, loop, check, zeroes, error_number = 0; char localstr[8], dest[80]; + char *d = dest; + int posns[6]; if (length > 6) { strcpy(symbol->errtxt, "484: Input too long (6 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "485: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -273,7 +288,8 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l total = 0; for (loop = 0; loop < 6; loop++) { - total += ctoi(localstr[loop]); + posns[loop] = ctoi(localstr[loop]); + total += posns[loop]; } check = 10 - (total % 10); if (check == 10) { @@ -281,12 +297,17 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l } localstr[6] = itoc(check); localstr[7] = '\0'; - *dest = '\0'; + for (loop = 5; loop >= 0; loop--) { - lookup(NEON, KoreaTable, localstr[loop], dest); + const char *const entry = KoreaTable[posns[loop]]; + memcpy(d, entry, 10); + d += entry[8] ? 10 : 8; } - lookup(NEON, KoreaTable, localstr[6], dest); - expand(symbol, dest); + memcpy(d, KoreaTable[check], 10); + d += KoreaTable[check][8] ? 10 : 8; + + expand(symbol, dest, d - dest); + ustrcpy(symbol->text, localstr); // TODO: Find documentation on BARCODE_KOREAPOST dimensions/height @@ -298,7 +319,6 @@ 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; - char dest[16] = {0}; if (length > 1) { strcpy(symbol->errtxt, "486: Input too long (1 character maximum)"); @@ -308,19 +328,19 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) switch ((char) source[0]) { case 'a': case 'A': - strcpy(dest, "111515111"); + expand(symbol, "111515111", 9); break; case 'b': case 'B': - strcpy(dest, "13111311131"); + expand(symbol, "13111311131", 11); break; case 'c': case 'C': - strcpy(dest, "11131313111"); + expand(symbol, "11131313111", 11); break; case 'd': case 'D': - strcpy(dest, "1111131311111"); + expand(symbol, "1111131311111", 13); break; default: strcpy(symbol->errtxt, "487: Invalid character in data (\"A\", \"B\", \"C\" or \"D\" only)"); @@ -328,8 +348,6 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) break; } - expand(symbol, dest); - 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) */ @@ -344,7 +362,7 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) /* Set height for DAFT-type codes, maintaining ratio. Expects row_height[0] & row_height[1] to be set */ /* Used by auspost.c also */ -INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height) { +INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height) { int error_number = 0; float t_ratio; /* Tracker ratio */ @@ -376,22 +394,21 @@ INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float } /* Handles the 4 State barcodes used in the UK by Royal Mail */ -static char rm4scc_enc(unsigned char source[], char dest[], int length) { +static void rm4scc_enc(const int *posns, char *d, const int length) { int i; int top, bottom, row, column, check_digit; - char values[3], set_copy[] = KRSET; top = 0; bottom = 0; /* start character */ - strcpy(dest, "1"); + *d++ = '1'; - for (i = 0; i < length; i++) { - lookup(KRSET, RoyalTable, source[i], dest); - strcpy(values, RoyalValues[posn(KRSET, source[i])]); - top += ctoi(values[0]); - bottom += ctoi(values[1]); + for (i = 0; i < length; i++, d += 4) { + const int p = posns[i]; + memcpy(d, RoyalTable[p], 4); + top += RoyalValues[p][0]; + bottom += RoyalValues[p][1]; } /* Calculate the check digit */ @@ -404,32 +421,31 @@ static char rm4scc_enc(unsigned char source[], char dest[], int length) { column = 5; } check_digit = (6 * row) + column; - strcat(dest, RoyalTable[check_digit]); + memcpy(d, RoyalTable[check_digit], 4); + d += 4; /* stop character */ - strcat(dest, "0"); - - return set_copy[check_digit]; + strcpy(d, "0"); } /* Puts RM4SCC into the data matrix */ INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int length) { char height_pattern[210]; + int posns[50]; int loopey, h; int writer; int error_number = 0; - strcpy(height_pattern, ""); if (length > 50) { strcpy(symbol->errtxt, "488: Input too long (50 character maximum)"); return ZINT_ERROR_TOO_LONG; } - to_upper(source); - if (is_sane(KRSET, source, length) != 0) { + to_upper(source, length); + if (!is_sane_lookup(KRSET, 36, source, length, posns)) { strcpy(symbol->errtxt, "489: Invalid character in data (alphanumerics only)"); return ZINT_ERROR_INVALID_DATA; } - /*check = */rm4scc_enc(source, height_pattern, length); + rm4scc_enc(posns, height_pattern, length); writer = 0; h = (int) strlen(height_pattern); @@ -467,34 +483,33 @@ INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int leng } /* Handles Dutch Post TNT KIX symbols - The same as RM4SCC but without check digit + The same as RM4SCC but without check digit or stop/start chars Specification at http://www.tntpost.nl/zakelijk/klantenservice/downloads/kIX_code/download.aspx */ INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length) { - char height_pattern[75], localstr[20]; + char height_pattern[75]; + char *d = height_pattern; + int posns[18]; int loopey; int writer, i, h; int error_number = 0; - strcpy(height_pattern, ""); if (length > 18) { strcpy(symbol->errtxt, "490: Input too long (18 character maximum)"); return ZINT_ERROR_TOO_LONG; } - to_upper(source); - if (is_sane(KRSET, source, length) != 0) { + to_upper(source, length); + if (!is_sane_lookup(KRSET, 36, source, length, posns)) { strcpy(symbol->errtxt, "491: Invalid character in data (alphanumerics only)"); return ZINT_ERROR_INVALID_DATA; } - ustrcpy(localstr, source); - /* Encode data */ - for (i = 0; i < length; i++) { - lookup(KRSET, RoyalTable, localstr[i], height_pattern); + for (i = 0; i < length; i++, d += 4) { + memcpy(d, RoyalTable[posns[i]], 4); } writer = 0; - h = (int) strlen(height_pattern); + h = d - height_pattern; for (loopey = 0; loopey < h; loopey++) { if ((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0')) { set_module(symbol, 0, writer); @@ -525,45 +540,28 @@ INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length) /* Handles DAFT Code symbols */ INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length) { - char height_pattern[100]; - unsigned int loopey, h; - int writer, i; - strcpy(height_pattern, ""); + int posns[100]; + int loopey; + int writer; - if (length > 50) { - strcpy(symbol->errtxt, "492: Input too long (50 character maximum)"); + if (length > 100) { + strcpy(symbol->errtxt, "492: Input too long (100 character maximum)"); return ZINT_ERROR_TOO_LONG; } - to_upper(source); + to_upper(source, length); - if (is_sane(DAFTSET, source, length) != 0) { + if (!is_sane_lookup(DAFTSET, 4, source, length, posns)) { strcpy(symbol->errtxt, "493: Invalid character in data (\"D\", \"A\", \"F\" and \"T\" only)"); return ZINT_ERROR_INVALID_DATA; } - for (i = 0; i < length; i++) { - if (source[i] == 'D') { - strcat(height_pattern, "2"); - } - if (source[i] == 'A') { - strcat(height_pattern, "1"); - } - if (source[i] == 'F') { - strcat(height_pattern, "0"); - } - if (source[i] == 'T') { - strcat(height_pattern, "3"); - } - } - writer = 0; - h = (int) strlen(height_pattern); - for (loopey = 0; loopey < h; loopey++) { - if ((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0')) { + for (loopey = 0; loopey < length; loopey++) { + if ((posns[loopey] == 1) || (posns[loopey] == 0)) { set_module(symbol, 0, writer); } set_module(symbol, 1, writer); - if ((height_pattern[loopey] == '2') || (height_pattern[loopey] == '0')) { + if ((posns[loopey] == 2) || (posns[loopey] == 0)) { set_module(symbol, 2, writer); } writer += 2; @@ -594,21 +592,24 @@ INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length) { int loop, error_number = 0; char dest[512]; /* 90 * 4 + 1 ~ */ + char *d = dest; if (length > 90) { strcpy(symbol->errtxt, "494: Input too long (90 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, length) != 0) { + if (!is_sane(NEON_F, source, length)) { strcpy(symbol->errtxt, "495: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } - *dest = '\0'; + for (loop = 0; loop < length; loop++) { - lookup(NEON, FlatTable, source[loop], dest); + const char *const entry = FlatTable[source[loop] - '0']; + memcpy(d, entry, 4); + d += entry[2] ? 4 : 2; } - expand(symbol, dest); + expand(symbol, dest, d - dest); // TODO: Find documentation on BARCODE_FLAT dimensions/height @@ -619,25 +620,19 @@ INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int length) { int error_number = 0, h; char pattern[69]; + char *d = pattern; int writer, loopey, inter_posn, i, sum, check; char check_char; - char inter[23]; - -#ifndef _MSC_VER - unsigned char local_source[length + 1]; -#else - unsigned char *local_source = (unsigned char *) _alloca(length + 1); -#endif + char inter[20 + 1]; if (length > 20) { strcpy(symbol->errtxt, "496: Input too long (20 character maximum)"); return ZINT_ERROR_TOO_LONG; } - ustrcpy(local_source, source); - to_upper(local_source); + to_upper(source, length); - if (is_sane(SHKASUTSET, local_source, length) != 0) { + if (!is_sane(SHKASUTSET_F, source, length)) { strcpy(symbol->errtxt, "497: Invalid character in data (alphanumerics and \"-\" only)"); return ZINT_ERROR_INVALID_DATA; } @@ -647,35 +642,36 @@ INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int l i = 0; inter_posn = 0; do { - if (((local_source[i] >= '0') && (local_source[i] <= '9')) || (local_source[i] == '-')) { - inter[inter_posn] = local_source[i]; + if (((source[i] >= '0') && (source[i] <= '9')) || (source[i] == '-')) { + inter[inter_posn] = source[i]; inter_posn++; } else { - if ((local_source[i] >= 'A') && (local_source[i] <= 'J')) { + if (source[i] <= 'J') { inter[inter_posn] = 'a'; - inter[inter_posn + 1] = local_source[i] - 'A' + '0'; - inter_posn += 2; - } - if ((local_source[i] >= 'K') && (local_source[i] <= 'T')) { + inter[inter_posn + 1] = source[i] - 'A' + '0'; + } else if (source[i] <= 'T') { inter[inter_posn] = 'b'; - inter[inter_posn + 1] = local_source[i] - 'K' + '0'; - inter_posn += 2; - } - if ((local_source[i] >= 'U') && (local_source[i] <= 'Z')) { + inter[inter_posn + 1] = source[i] - 'K' + '0'; + } else { /* (source[i] >= 'U') && (source[i] <= 'Z') */ inter[inter_posn] = 'c'; - inter[inter_posn + 1] = local_source[i] - 'U' + '0'; - inter_posn += 2; + inter[inter_posn + 1] = source[i] - 'U' + '0'; } + inter_posn += 2; } i++; } while ((i < length) && (inter_posn < 20)); - inter[20] = '\0'; - strcpy(pattern, "13"); /* Start */ + if (i != length || inter[20] != '\0') { + strcpy(symbol->errtxt, "477: Input too long (20 symbol character maximum)"); + return ZINT_ERROR_TOO_LONG; + } + + memcpy(d, "13", 2); /* Start */ + d += 2; sum = 0; - for (i = 0; i < 20; i++) { - strcat(pattern, JapanTable[posn(KASUTSET, inter[i])]); + for (i = 0; i < 20; i++, d += 3) { + memcpy(d, JapanTable[posn(KASUTSET, inter[i])], 3); sum += posn(CHKASUTSET, inter[i]); } @@ -691,15 +687,17 @@ INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int l } else { check_char = (check - 11) + 'a'; } - strcat(pattern, JapanTable[posn(KASUTSET, check_char)]); + memcpy(d, JapanTable[posn(KASUTSET, check_char)], 3); + d += 3; if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check: %d, char: %c\n", check, check_char); - strcat(pattern, "31"); /* Stop */ + memcpy(d, "31", 2); /* Stop */ + d += 2; /* Resolve pattern to 4-state symbols */ writer = 0; - h = (int) strlen(pattern); + h = d - pattern; for (loopey = 0; loopey < h; loopey++) { if ((pattern[loopey] == '2') || (pattern[loopey] == '1')) { set_module(symbol, 0, writer); diff --git a/backend/qr.c b/backend/qr.c index 65ec479f..4af59b72 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -305,7 +305,7 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int /* Get optimal mode for each code point by tracing backwards */ for (i = length - 1, cm_i = i * QR_NUM_MODES; i >= 0; i--, cm_i -= QR_NUM_MODES) { - j = strchr(mode_types, cur_mode) - mode_types; + j = posn(mode_types, cur_mode); cur_mode = char_modes[cm_i + j]; mode[i] = cur_mode; } @@ -327,7 +327,7 @@ static int mode_indicator(const int version, const int mode) { { 0, 1, 2, 3, }, }; - int mode_index = strchr(mode_types, mode) - mode_types; + int mode_index = posn(mode_types, (const char) mode); if (version < RMQR_VERSION) { return mode_indicators[0][mode_index]; /* QRCODE */ @@ -364,7 +364,7 @@ static int cci_bits(const int version, const int mode) { static const unsigned short int *rmqr_ccis[QR_NUM_MODES] = { rmqr_numeric_cci, rmqr_alphanum_cci, rmqr_byte_cci, rmqr_kanji_cci, }; - int mode_index = strchr(mode_types, mode) - mode_types; + int mode_index = posn(mode_types, (const char) mode); if (version < RMQR_VERSION) { /* QRCODE */ if (version < 10) { @@ -393,7 +393,7 @@ static int terminator_bits(const int version) { } /* Convert input data to a binary stream and add padding */ -static void qr_binary(unsigned char datastream[], const int version, const int target_codewords, const char mode[], +static int qr_binary(unsigned char datastream[], const int version, const int target_codewords, const char mode[], const unsigned int jisdata[], const int length, const struct zint_structapp *p_structapp, const int gs1, const int eci, const int est_binlen, const int debug_print) { int position = 0; @@ -406,8 +406,9 @@ static void qr_binary(unsigned char datastream[], const int version, const int t #ifndef _MSC_VER char binary[est_binlen + 12]; #else - char *binary = (char *) _alloca(est_binlen + 12); + char *binary= (char *) _alloca(est_binlen + 12); #endif + *binary = '\0'; bp = 0; @@ -641,17 +642,17 @@ static void qr_binary(unsigned char datastream[], const int version, const int t int count; int first = 0, prod; - first = posn(NEON, (char) jisdata[position + i]); + first = ctoi((const char) jisdata[position + i]); count = 1; prod = first; if (i + 1 < short_data_block_length && mode[position + i + 1] == 'N') { - int second = posn(NEON, (char) jisdata[position + i + 1]); + int second = ctoi((const char) jisdata[position + i + 1]); count = 2; prod = (prod * 10) + second; if (i + 2 < short_data_block_length && mode[position + i + 2] == 'N') { - int third = posn(NEON, (char) jisdata[position + i + 2]); + int third = ctoi((const char) jisdata[position + i + 2]); count = 3; prod = (prod * 10) + third; } @@ -678,9 +679,8 @@ static void qr_binary(unsigned char datastream[], const int version, const int t if (version >= MICROQR_VERSION && version < MICROQR_VERSION + 4) { /* MICROQR does its own terminating/padding */ - binary[bp] = '\0'; - ustrcpy(datastream, binary); - return; + memcpy(datastream, binary, bp); + return bp; } /* Terminator */ @@ -738,6 +738,8 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } printf("\n"); } + + return 0; /* Not used */ } /* Split data into blocks, add error correction and then interleave the blocks and error correction data */ @@ -769,7 +771,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] ecc_block_length = ecc_cw / blocks; /* Suppress some clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.Assign warnings */ - assert(short_data_block_length >= 0); + assert(short_data_block_length > 0); assert(ecc_block_length * blocks == ecc_cw); #ifndef _MSC_VER @@ -842,7 +844,6 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] fullstream[j] = interleaved_data[j]; } for (j = 0; j < ecc_cw; j++) { - // NOLINTNEXTLINE suppress clang-tidy warning: interleaved_ecc[ecc_cw] fully set fullstream[j + data_cw] = interleaved_ecc[j]; } @@ -1788,8 +1789,8 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); #endif - qr_binary(datastream, version, target_codewords, mode, jisdata, length, p_structapp, gs1, symbol->eci, - est_binlen, debug_print); + (void) qr_binary(datastream, version, target_codewords, mode, jisdata, length, p_structapp, gs1, symbol->eci, + est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif @@ -1833,7 +1834,7 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng return 0; } -static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { +static int micro_qr_m1(struct zint_symbol *symbol, char binary_data[], int bp) { int i, j, latch; int bits_total, bits_left; int data_codewords, ecc_codewords; @@ -1844,26 +1845,26 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { latch = 0; /* Add terminator */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left <= 3) { - for (i = 0; i < bits_left; i++) { - strcat(binary_data, "0"); + if (bits_left) { + bp = bin_append_posn(0, bits_left, binary_data, bp); } latch = 1; } else { - strcat(binary_data, "000"); + bp = bin_append_posn(0, 3, binary_data, bp); } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("M1 Terminated binary (%d): %s (bits_left %d)\n", (int) strlen(binary_data), binary_data, bits_left); + printf("M1 Terminated binary (%d): %s (bits_left %d)\n", bp, binary_data, bits_left); } if (latch == 0) { /* Manage last (4-bit) block */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left <= 4) { - for (i = 0; i < bits_left; i++) { - strcat(binary_data, "0"); + if (bits_left) { + bp = bin_append_posn(0, bits_left, binary_data, bp); } latch = 1; } @@ -1871,23 +1872,20 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { if (latch == 0) { /* Complete current byte */ - int remainder = 8 - (strlen(binary_data) % 8); - if (remainder == 8) { - remainder = 0; - } - for (i = 0; i < remainder; i++) { - strcat(binary_data, "0"); + int remainder = 8 - (bp % 8); + if (remainder != 8) { + bp = bin_append_posn(0, remainder, binary_data, bp); } /* Add padding */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left > 4) { remainder = (bits_left - 4) / 8; for (i = 0; i < remainder; i++) { - strcat(binary_data, (i & 1) ? "00010001" : "11101100"); + bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp); } } - bin_append(0, 4, binary_data); + bp = bin_append_posn(0, 4, binary_data, bp); } data_codewords = 3; @@ -1919,14 +1917,16 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { - bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); + bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp); } + + return bp; } -static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const int ecc_mode) { +static int micro_qr_m2(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_mode) { int i, j, latch; - int bits_total=0, bits_left; - int data_codewords=0, ecc_codewords=0; + int bits_total = 0, bits_left; + int data_codewords = 0, ecc_codewords = 0; unsigned char data_blocks[6], ecc_blocks[7]; rs_t rs; @@ -1941,35 +1941,32 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in else assert(0); /* Add terminator */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left <= 5) { - for (i = 0; i < bits_left; i++) { - strcat(binary_data, "0"); + if (bits_left) { + bp = bin_append_posn(0, bits_left, binary_data, bp); } latch = 1; } else { - bin_append(0, 5, binary_data); + bp = bin_append_posn(0, 5, binary_data, bp); } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("M2 Terminated binary (%d): %s (bits_left %d)\n", (int) strlen(binary_data), binary_data, bits_left); + printf("M2 Terminated binary (%d): %s (bits_left %d)\n", bp, binary_data, bits_left); } if (latch == 0) { /* Complete current byte */ - int remainder = 8 - (strlen(binary_data) % 8); - if (remainder == 8) { - remainder = 0; - } - for (i = 0; i < remainder; i++) { - strcat(binary_data, "0"); + int remainder = 8 - (bp % 8); + if (remainder != 8) { + bp = bin_append_posn(0, remainder, binary_data, bp); } /* Add padding */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; remainder = bits_left / 8; for (i = 0; i < remainder; i++) { - strcat(binary_data, (i & 1) ? "00010001" : "11101100"); + bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp); } } @@ -2004,16 +2001,16 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { - bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); + bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp); } - return; + return bp; } -static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const int ecc_mode) { +static int micro_qr_m3(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_mode) { int i, j, latch; - int bits_total=0, bits_left; - int data_codewords=0, ecc_codewords=0; + int bits_total = 0, bits_left; + int data_codewords = 0, ecc_codewords = 0; unsigned char data_blocks[12], ecc_blocks[9]; rs_t rs; @@ -2028,26 +2025,26 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in else assert(0); /* Add terminator */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left <= 7) { - for (i = 0; i < bits_left; i++) { - strcat(binary_data, "0"); + if (bits_left) { + bp = bin_append_posn(0, bits_left, binary_data, bp); } latch = 1; } else { - bin_append(0, 7, binary_data); + bp = bin_append_posn(0, 7, binary_data, bp); } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("M3 Terminated binary (%d): %s (bits_left %d)\n", (int) strlen(binary_data), binary_data, bits_left); + printf("M3 Terminated binary (%d): %s (bits_left %d)\n", bp, binary_data, bits_left); } if (latch == 0) { /* Manage last (4-bit) block */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left <= 4) { - for (i = 0; i < bits_left; i++) { - strcat(binary_data, "0"); + if (bits_left) { + bp = bin_append_posn(0, bits_left, binary_data, bp); } latch = 1; } @@ -2055,23 +2052,20 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in if (latch == 0) { /* Complete current byte */ - int remainder = 8 - (strlen(binary_data) % 8); - if (remainder == 8) { - remainder = 0; - } - for (i = 0; i < remainder; i++) { - strcat(binary_data, "0"); + int remainder = 8 - (bp % 8); + if (remainder != 8) { + bp = bin_append_posn(0, remainder, binary_data, bp); } /* Add padding */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left > 4) { remainder = (bits_left - 4) / 8; for (i = 0; i < remainder; i++) { - strcat(binary_data, (i & 1) ? "00010001" : "11101100"); + bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp); } } - bin_append(0, 4, binary_data); + bp = bin_append_posn(0, 4, binary_data, bp); } if (ecc_mode == LEVEL_L) { @@ -2123,16 +2117,16 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { - bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); + bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp); } - return; + return bp; } -static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const int ecc_mode) { +static int micro_qr_m4(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_mode) { int i, j, latch; - int bits_total=0, bits_left; - int data_codewords=0, ecc_codewords=0; + int bits_total = 0, bits_left; + int data_codewords = 0, ecc_codewords = 0; unsigned char data_blocks[17], ecc_blocks[15]; rs_t rs; @@ -2150,14 +2144,14 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in else assert(0); /* Add terminator */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; if (bits_left <= 9) { - for (i = 0; i < bits_left; i++) { - strcat(binary_data, "0"); + if (bits_left) { + bp = bin_append_posn(0, bits_left, binary_data, bp); } latch = 1; } else { - bin_append(0, 9, binary_data); + bp = bin_append_posn(0, 9, binary_data, bp); } if (symbol->debug & ZINT_DEBUG_PRINT) { @@ -2166,19 +2160,16 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in if (latch == 0) { /* Complete current byte */ - int remainder = 8 - (strlen(binary_data) % 8); - if (remainder == 8) { - remainder = 0; - } - for (i = 0; i < remainder; i++) { - strcat(binary_data, "0"); + int remainder = 8 - (bp % 8); + if (remainder != 8) { + bp = bin_append_posn(0, remainder, binary_data, bp); } /* Add padding */ - bits_left = bits_total - (int) strlen(binary_data); + bits_left = bits_total - bp; remainder = bits_left / 8; for (i = 0; i < remainder; i++) { - strcat(binary_data, (i & 1) ? "00010001" : "11101100"); + bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp); } } @@ -2217,8 +2208,10 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { - bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); + bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp); } + + return bp; } static void micro_setup_grid(unsigned char *grid, const int size) { @@ -2256,13 +2249,12 @@ static void micro_setup_grid(unsigned char *grid, const int size) { grid[(8 * size) + 8] |= 20; } -static void micro_populate_grid(unsigned char *grid, const int size, const char full_stream[]) { +static void micro_populate_grid(unsigned char *grid, const int size, const char full_stream[], int bp) { int direction = 1; /* up */ int row = 0; /* right hand side */ - int n, i; + int i; int y; - n = (int) strlen(full_stream); y = size - 1; i = 0; do { @@ -2277,7 +2269,7 @@ static void micro_populate_grid(unsigned char *grid, const int size, const char i++; } - if (i < n) { + if (i < bp) { if (!(grid[(y * size) + x] & 0xf0)) { if (full_stream[i] == '1') { grid[(y * size) + x] = 0x01; @@ -2305,7 +2297,7 @@ static void micro_populate_grid(unsigned char *grid, const int size, const char y = size - 1; direction = 1; } - } while (i < n); + } while (i < bp); } static int micro_evaluate(const unsigned char *grid, const int size, const int pattern) { @@ -2432,6 +2424,7 @@ static int micro_apply_bitmask(unsigned char *grid, const int size, const int us INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length) { int i, size, j; char full_stream[200]; + int bp; int full_multibyte; int user_mask; @@ -2614,19 +2607,19 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len qr_define_mode(mode, jisdata, length, 0 /*gs1*/, MICROQR_VERSION + version, debug_print); - qr_binary((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, jisdata, length, - NULL /*p_structapp*/, 0 /*gs1*/, 0 /*eci*/, binary_count[version], debug_print); + bp = qr_binary((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, jisdata, + length, NULL /*p_structapp*/, 0 /*gs1*/, 0 /*eci*/, binary_count[version], debug_print); - if (debug_print) printf("Binary (%d): %s\n", (int) strlen(full_stream), full_stream); + if (debug_print) printf("Binary (%d): %s\n", bp, full_stream); switch (version) { - case 0: micro_qr_m1(symbol, full_stream); + case 0: bp = micro_qr_m1(symbol, full_stream, bp); break; - case 1: micro_qr_m2(symbol, full_stream, ecc_level); + case 1: bp = micro_qr_m2(symbol, full_stream, bp, ecc_level); break; - case 2: micro_qr_m3(symbol, full_stream, ecc_level); + case 2: bp = micro_qr_m3(symbol, full_stream, bp, ecc_level); break; - case 3: micro_qr_m4(symbol, full_stream, ecc_level); + case 3: bp = micro_qr_m4(symbol, full_stream, bp, ecc_level); break; } @@ -2641,7 +2634,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len memset(grid, 0, size_squared); micro_setup_grid(grid, size); - micro_populate_grid(grid, size, full_stream); + micro_populate_grid(grid, size, full_stream, bp); bitmask = micro_apply_bitmask(grid, size, user_mask, debug_print); /* Add format data */ @@ -2814,8 +2807,8 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); #endif - qr_binary(datastream, version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, 0 /*gs1*/, - symbol->eci, est_binlen, debug_print); + (void) qr_binary(datastream, version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, 0 /*gs1*/, + symbol->eci, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif @@ -3145,8 +3138,8 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length fullstream = (unsigned char *) _alloca(rmqr_total_codewords[version] + 1); #endif - qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, gs1, - symbol->eci, est_binlen, debug_print); + (void) qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, + NULL /*p_structapp*/, gs1, symbol->eci, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif diff --git a/backend/raster.c b/backend/raster.c index 14869343..da3582d2 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -77,7 +77,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf }; int row; int plot_alpha = 0; - unsigned char *bitmap; + const size_t bm_bitmap_width = (size_t) symbol->bitmap_width * 3; map[DEFAULT_INK][0] = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); map[DEFAULT_INK][1] = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); @@ -110,7 +110,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf symbol->alphamap = NULL; } - symbol->bitmap = (unsigned char *) malloc((size_t) symbol->bitmap_width * symbol->bitmap_height * 3); + symbol->bitmap = (unsigned char *) malloc(bm_bitmap_width * symbol->bitmap_height); if (symbol->bitmap == NULL) { strcpy(symbol->errtxt, "661: Insufficient memory for bitmap buffer"); return ZINT_ERROR_MEMORY; @@ -124,21 +124,31 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf } for (row = 0; row < symbol->bitmap_height; row++) { int p = row * symbol->bitmap_width; - const int pe = p + symbol->bitmap_width; - bitmap = symbol->bitmap + p * 3; - for (; p < pe; p++, bitmap += 3) { - memcpy(bitmap, map[pixelbuf[p]], 3); - symbol->alphamap[p] = pixelbuf[p] == DEFAULT_PAPER ? bgalpha : fgalpha; + const unsigned char *pb = pixelbuf + p; + unsigned char *bitmap = symbol->bitmap + p * 3; + if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) { + memcpy(bitmap, bitmap - bm_bitmap_width, bm_bitmap_width); + memcpy(symbol->alphamap + p, symbol->alphamap + p - symbol->bitmap_width, symbol->bitmap_width); + } else { + const int pe = p + symbol->bitmap_width; + for (; p < pe; p++, bitmap += 3) { + memcpy(bitmap, map[pixelbuf[p]], 3); + symbol->alphamap[p] = pixelbuf[p] == DEFAULT_PAPER ? bgalpha : fgalpha; + } } } } else { for (row = 0; row < symbol->bitmap_height; row++) { const int r = row * symbol->bitmap_width; const unsigned char *pb = pixelbuf + r; - const unsigned char *const pe = pb + symbol->bitmap_width; - bitmap = symbol->bitmap + r * 3; - for (; pb < pe; pb++, bitmap += 3) { - memcpy(bitmap, map[*pb], 3); + unsigned char *bitmap = symbol->bitmap + r * 3; + if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) { + memcpy(bitmap, bitmap - bm_bitmap_width, bm_bitmap_width); + } else { + const unsigned char *const pbe = pb + symbol->bitmap_width; + for (; pb < pbe; pb++, bitmap += 3) { + memcpy(bitmap, map[*pb], 3); + } } } } @@ -262,15 +272,39 @@ static void draw_pt(unsigned char *buf, const int buf_width, const int buf_heigh } } +/* Draw the first line of a bar, to be completed by `copy_bar_line()`; more performant than multiple `draw_bar()`s */ +static void draw_bar_line(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos, + const int image_width, const char fill) { + unsigned char *pb = pixelbuf + ((size_t) image_width * ypos) + xpos; + + memset(pb, fill, xlen); +} + +/* Fill out a bar code row by copying the first line (called after multiple `draw_bar_line()`s) */ +static void copy_bar_line(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos, const int ylen, + const int image_width, const int image_height) { + int y; + const int ye = ypos + ylen > image_height ? image_height : ypos + ylen; /* Defensive, should never happen */ + unsigned char *pb = pixelbuf + ((size_t) image_width * ypos) + xpos; + + assert(ypos + ylen <= image_height); // Trigger assert if "should never happen" happens + + for (y = ypos + 1; y < ye; y++) { + memcpy(pixelbuf + ((size_t) image_width * y) + xpos, pb, xlen); + } +} + /* Draw a rectangle */ static void draw_bar(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos, const int ylen, const int image_width, const int image_height, const char fill) { int y; const int ye = ypos + ylen > image_height ? image_height : ypos + ylen; /* Defensive, should never happen */ - assert(ypos + ylen <= image_height); // Trigger assert if happens + unsigned char *pb = pixelbuf + ((size_t) image_width * ypos) + xpos; - for (y = ypos; y < ye; y++) { - memset(pixelbuf + ((size_t) image_width * y) + xpos, fill, xlen); + assert(ypos + ylen <= image_height); // Trigger assert if "should never happen" happens + + for (y = ypos; y < ye; y++, pb += image_width) { + memset(pb, fill, xlen); } } @@ -682,7 +716,7 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, const int rotate_ang } scaler *= 10.0f; - output_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler, + out_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler, &xoffset_si, &yoffset_si, &roffset_si, &boffset_si); hex_width = (int) roundf(scaler); /* Short diameter, X in ISO/IEC 16023:2000 Figure 8 (same as W) */ @@ -779,7 +813,7 @@ static int plot_raster_dotty(struct zint_symbol *symbol, const int rotate_angle, dot_radius_s = (symbol->dot_size * scaler) / 2.0f; dot_radius_si = (int) dot_radius_s; - output_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler, + out_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler, &xoffset_si, &yoffset_si, &roffset_si, &boffset_si); /* TODO: Revisit this overspill stuff, it's hacky */ @@ -884,6 +918,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl unsigned char textpart1[5], textpart2[7], textpart3[7], textpart4[2]; int hide_text; int i, r; + int block_width = 0; int text_height; /* Font pixel size (so whole integers) */ float text_gap; /* Gap between barcode and text */ float guard_descent; @@ -910,20 +945,22 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl si = 2; } - large_bar_height = output_large_bar_height(symbol, si /*Round to scale*/); + large_bar_height = out_large_bar_height(symbol, si /*Round to scale*/); symbol_height_si = (int) ceilf(symbol->height * si); main_width = symbol->width; if (is_extendable(symbol->symbology)) { - upceanflag = output_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap); + upceanflag = out_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap); } hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0) || scaler < 1.0f); - output_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, si, + out_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, si, &xoffset_si, &yoffset_si, &roffset_si, &boffset_si); + comp_xoffset_si = xoffset_si + comp_xoffset * si; + /* Note font sizes halved as in pixels */ if (upceanflag) { textflags = UPCEAN_TEXT | (symbol->output_options & SMALL_TEXT); /* Bold not available for UPC/EAN */ @@ -960,40 +997,41 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl yposn = yoffset; /* Plot the body of the symbol to the pixel buffer */ - for (r = 0; r < symbol->rows; r++) { - int yposn_si = yposn * si; - float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; - int row_height_si = (int) ceilf(row_height * si); + if (symbol->symbology == BARCODE_ULTRA) { + for (r = 0; r < symbol->rows; r++) { + int yposn_si = yposn * si; + float row_height = symbol->row_height[r]; + int row_height_si = (int) ceilf(row_height * si); - i = 0; - - if (symbol->symbology == BARCODE_ULTRA) { - do { - int module_fill = module_colour_is_set(symbol, r, i); - int block_width = 0; - do { - block_width++; - } while ((i + block_width < symbol->width) - && module_colour_is_set(symbol, r, i + block_width) == module_fill); - if (module_fill) { + for (i = 0; i < symbol->width; i += block_width) { + int fill = module_colour_is_set(symbol, r, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_colour_is_set(symbol, r, i + block_width) == fill; block_width++); + if (fill) { /* a colour block */ - draw_bar(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, row_height_si, - image_width, image_height, ultra_colour[module_fill]); + draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, image_width, + ultra_colour[fill]); } - i += block_width; + } + copy_bar_line(pixelbuf, xoffset_si, image_width - xoffset_si - roffset_si, yposn_si, row_height_si, + image_width, image_height); + yposn += row_height; + } - } while (i < symbol->width); - } else { - do { - float addon_row_height; - int module_fill = module_is_set(symbol, r, i); - int block_width = 0; - do { - block_width++; - } while ((i + block_width < symbol->width) - && module_is_set(symbol, r, i + block_width) == module_fill); + } else if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */ + for (r = 0; r < symbol->rows; r++) { + int yposn_si = yposn * si; + float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; + int row_height_si = (int) ceilf(row_height * si); - if (upceanflag && (addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) { + for (i = 0; i < symbol->width; i += block_width) { + int fill = module_is_set(symbol, r, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_is_set(symbol, r, i + block_width) == fill; block_width++); + if ((r == (symbol->rows - 1)) && (i > main_width) && (addon_latch == 0)) { + float addon_row_height; + copy_bar_line(pixelbuf, xoffset_si, main_width * si, yposn_si, row_height_si, image_width, + image_height); yposn_si += (text_height + text_gap) * si; addon_text_yposn = yposn * si; addon_row_height = row_height - (text_height + text_gap); @@ -1006,127 +1044,110 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl row_height_si = addon_row_height * si; addon_latch = 1; } - if (module_fill) { + if (fill) { /* a bar */ - draw_bar(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, row_height_si, image_width, - image_height, DEFAULT_INK); + draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, image_width, + DEFAULT_INK); } - i += block_width; - - } while (i < symbol->width); + } + if (addon_latch) { + copy_bar_line(pixelbuf, xoffset_si + main_width * si, + image_width - main_width * si - xoffset_si - roffset_si, yposn_si, row_height_si, + image_width, image_height); + } else { + copy_bar_line(pixelbuf, xoffset_si, image_width - xoffset_si - roffset_si, yposn_si, row_height_si, + image_width, image_height); + } + yposn += row_height; + } + + } else { + for (r = 0; r < symbol->rows; r++) { + int yposn_si = yposn * si; + float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; + int row_height_si = (int) ceilf(row_height * si); + + for (i = 0; i < symbol->width; i += block_width) { + int fill = module_is_set(symbol, r, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_is_set(symbol, r, i + block_width) == fill; block_width++); + if (fill) { + /* a bar */ + draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, image_width, + DEFAULT_INK); + } + } + copy_bar_line(pixelbuf, xoffset_si, image_width - xoffset_si - roffset_si, yposn_si, row_height_si, + image_width, image_height); + yposn += row_height; } - yposn += row_height; } - comp_xoffset_si = xoffset_si + comp_xoffset * si; - - if (upceanflag) { + if (guard_descent && upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */ /* Guard bar extension */ int guard_yoffset_si = yoffset_si + symbol_height_si; int guard_descent_si = guard_descent * si; if (upceanflag == 6) { /* UPC-E */ - draw_bar(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 50 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); + draw_bar_line(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 50 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); } else if (upceanflag == 8) { /* EAN-8 */ - draw_bar(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 32 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 34 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 64 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 66 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); + draw_bar_line(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 32 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 34 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 64 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 66 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); } else if (upceanflag == 12) { /* UPC-A */ - int latch = 1; - - i = 0 + comp_xoffset; - do { - int module_fill = module_is_set(symbol, symbol->rows - 1, i); - int block_width = 0; - do { - block_width++; - } while ((i + block_width < symbol->width) - && module_is_set(symbol, symbol->rows - 1, i + block_width) == module_fill); - if (latch == 1) { - /* a bar */ - draw_bar(pixelbuf, i * si + xoffset_si, block_width * si, - guard_yoffset_si, guard_descent_si, image_width, image_height, DEFAULT_INK); - latch = 0; - } else { - /* a space */ - latch = 1; + for (i = 0 + comp_xoffset; i < 11 + comp_xoffset; i += block_width) { + int fill = module_is_set(symbol, symbol->rows - 1, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_is_set(symbol, symbol->rows - 1, i + block_width) == fill; + block_width++); + if (fill) { + draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, guard_yoffset_si, image_width, + DEFAULT_INK); } - i += block_width; - } while (i < 11 + comp_xoffset); - draw_bar(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - latch = 1; - i = 85 + comp_xoffset; - do { - int module_fill = module_is_set(symbol, symbol->rows - 1, i); - int block_width = 0; - do { - block_width++; - } while ((i + block_width < symbol->width) - && module_is_set(symbol, symbol->rows - 1, i + block_width) == module_fill); - if (latch == 1) { - /* a bar */ - draw_bar(pixelbuf, i * si + xoffset_si, block_width * si, - guard_yoffset_si, guard_descent_si, image_width, image_height, DEFAULT_INK); - latch = 0; - } else { - /* a space */ - latch = 1; + } + draw_bar_line(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + for (i = 85 + comp_xoffset; i < 96 + comp_xoffset; i += block_width) { + int fill = module_is_set(symbol, symbol->rows - 1, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_is_set(symbol, symbol->rows - 1, i + block_width) == fill; + block_width++); + if (fill) { + draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, guard_yoffset_si, image_width, + DEFAULT_INK); } - i += block_width; - } while (i < 96 + comp_xoffset); + } - } else if (upceanflag == 13) { /* EAN-13 */ - draw_bar(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 92 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 94 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, - image_width, image_height, DEFAULT_INK); + } else { /* EAN-13 */ + draw_bar_line(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 92 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); + draw_bar_line(pixelbuf, 94 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK); } + copy_bar_line(pixelbuf, comp_xoffset_si, image_width - comp_xoffset_si - roffset_si, guard_yoffset_si, + guard_descent_si, image_width, image_height); } /* Add the text */ if (!hide_text) { - int textdone = 0; - int text_xposn; - int text_yposn; - - text_yposn = yoffset_si + symbol_height_si + (int) (text_gap * si); /* Calculated to top of text */ + int text_yposn = yoffset_si + symbol_height_si + (int) (text_gap * si); /* Calculated to top of text */ if (symbol->border_width > 0 && (symbol->output_options & (BARCODE_BOX | BARCODE_BIND))) { text_yposn += symbol->border_width * si; } - if (upceanflag) { + if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */ /* Note font sizes halved as in pixels */ @@ -1136,10 +1157,10 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl /* Halved again to get middle position that draw_string() expects */ int ean_width_adj = (UPCEAN_FONT_WIDTH + 3) / 4; - output_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4); + out_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4); if (upceanflag == 6) { /* UPC-E */ - text_xposn = -(5 + upcea_width_adj) * si + comp_xoffset_si; + int text_xposn = -(5 + upcea_width_adj) * si + comp_xoffset_si; draw_string(pixelbuf, textpart1, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, image_width, image_height, si); text_xposn = 24 * si + comp_xoffset_si; @@ -1147,7 +1168,6 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl text_xposn = (51 + 3 + upcea_width_adj) * si + comp_xoffset_si; draw_string(pixelbuf, textpart3, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, image_width, image_height, si); - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = (61 + addon_gap) * si + comp_xoffset_si; @@ -1162,11 +1182,10 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl } } else if (upceanflag == 8) { /* EAN-8 */ - text_xposn = 17 * si + comp_xoffset_si; + int text_xposn = 17 * si + comp_xoffset_si; draw_string(pixelbuf, textpart1, text_xposn, text_yposn, textflags, image_width, image_height, si); text_xposn = 50 * si + comp_xoffset_si; draw_string(pixelbuf, textpart2, text_xposn, text_yposn, textflags, image_width, image_height, si); - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = (77 + addon_gap) * si + comp_xoffset_si; @@ -1181,7 +1200,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl } } else if (upceanflag == 12) { /* UPC-A */ - text_xposn = (-(5 + upcea_width_adj)) * si + comp_xoffset_si; + int text_xposn = (-(5 + upcea_width_adj)) * si + comp_xoffset_si; draw_string(pixelbuf, textpart1, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, image_width, image_height, si); text_xposn = 27 * si + comp_xoffset_si; @@ -1191,7 +1210,6 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl text_xposn = (95 + 5 + upcea_width_adj) * si + comp_xoffset_si; draw_string(pixelbuf, textpart4, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, image_width, image_height, si); - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = (105 + addon_gap) * si + comp_xoffset_si; @@ -1205,14 +1223,13 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl break; } - } else if (upceanflag == 13) { /* EAN-13 */ - text_xposn = (-(5 + ean_width_adj)) * si + comp_xoffset_si; + } else { /* EAN-13 */ + int text_xposn = (-(5 + ean_width_adj)) * si + comp_xoffset_si; draw_string(pixelbuf, textpart1, text_xposn, text_yposn, textflags, image_width, image_height, si); text_xposn = 24 * si + comp_xoffset_si; draw_string(pixelbuf, textpart2, text_xposn, text_yposn, textflags, image_width, image_height, si); text_xposn = 71 * si + comp_xoffset_si; draw_string(pixelbuf, textpart3, text_xposn, text_yposn, textflags, image_width, image_height, si); - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = (105 + addon_gap) * si + comp_xoffset_si; @@ -1226,14 +1243,12 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl break; } } - } - - if (!textdone) { + } else { + int text_xposn = (main_width / 2) * si + comp_xoffset_si; /* Suppress clang-analyzer-core.CallAndMessage warning */ unsigned char local_text[sizeof(symbol->text)] = {0}; to_iso8859_1(symbol->text, local_text); /* Put the human readable text at the bottom */ - text_xposn = (main_width / 2) * si + comp_xoffset_si; draw_string(pixelbuf, local_text, text_xposn, text_yposn, textflags, image_width, image_height, si); } } @@ -1319,7 +1334,7 @@ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_ } #endif /* NO_PNG */ - error = output_check_colour_options(symbol); + error = out_check_colour_options(symbol); if (error != 0) { return error; } diff --git a/backend/reedsol.c b/backend/reedsol.c index 53aea312..d54d2ad5 100644 --- a/backend/reedsol.c +++ b/backend/reedsol.c @@ -106,8 +106,8 @@ INTERNAL void rs_init_gf(rs_t *rs, const unsigned int prime_poly) { INTERNAL void rs_init_code(rs_t *rs, const int nsym, int index) { int i, k; - const unsigned char *logt = rs->logt; - const unsigned char *alog = rs->alog; + const unsigned char *const logt = rs->logt; + const unsigned char *const alog = rs->alog; unsigned char *rspoly = rs->rspoly; rs->nsym = nsym; @@ -129,9 +129,9 @@ INTERNAL void rs_init_code(rs_t *rs, const int nsym, int index) { * and places them in reverse order in res */ INTERNAL void rs_encode(const rs_t *rs, const int datalen, const unsigned char *data, unsigned char *res) { int i, k; - const unsigned char *logt = rs->logt; - const unsigned char *alog = rs->alog; - const unsigned char *rspoly = rs->rspoly; + const unsigned char *const logt = rs->logt; + const unsigned char *const alog = rs->alog; + const unsigned char *const rspoly = rs->rspoly; const int nsym = rs->nsym; memset(res, 0, nsym); @@ -157,9 +157,9 @@ INTERNAL void rs_encode(const rs_t *rs, const int datalen, const unsigned char * INTERNAL void rs_encode_uint(const rs_t *rs, const int datalen, const unsigned int *data, unsigned int *res) { int i, k; - const unsigned char *logt = rs->logt; - const unsigned char *alog = rs->alog; - const unsigned char *rspoly = rs->rspoly; + const unsigned char *const logt = rs->logt; + const unsigned char *const alog = rs->alog; + const unsigned char *const rspoly = rs->rspoly; const int nsym = rs->nsym; memset(res, 0, sizeof(unsigned int) * nsym); diff --git a/backend/rss.c b/backend/rss.c index cac8d13b..3199727c 100644 --- a/backend/rss.c +++ b/backend/rss.c @@ -177,18 +177,20 @@ static void dbar_set_gtin14_hrt(struct zint_symbol *symbol, const unsigned char /* Expand from a width pattern to a bit pattern */ static int dbar_expand(struct zint_symbol *symbol, int writer, int *p_latch, const int width) { int j; - int latch = *p_latch; - for (j = 0; j < width; j++) { - if (latch) { + if (*p_latch) { + for (j = 0; j < width; j++) { set_module(symbol, symbol->rows, writer); - } else { - unset_module(symbol, symbol->rows, writer); + writer++; + } + } else { + for (j = 0; j < width; j++) { + unset_module(symbol, symbol->rows, writer); + writer++; } - writer++; } - *p_latch = !latch; + *p_latch = !*p_latch; return writer; } @@ -304,7 +306,7 @@ INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int strcpy(symbol->errtxt, "380: Input too long (14 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, src_len) != 0) { + if (!is_sane(NEON_F, source, src_len)) { strcpy(symbol->errtxt, "381: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -641,7 +643,7 @@ INTERNAL int dbar_ltd_cc(struct zint_symbol *symbol, unsigned char source[], int strcpy(symbol->errtxt, "382: Input too long (14 character maximum)"); return ZINT_ERROR_TOO_LONG; } - if (is_sane(NEON, source, src_len) != 0) { + if (!is_sane(NEON_F, source, src_len)) { strcpy(symbol->errtxt, "383: Invalid character in data (digits only)"); return ZINT_ERROR_INVALID_DATA; } diff --git a/backend/svg.c b/backend/svg.c index 5df16051..ee22d8fe 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -128,7 +128,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { int bg_alpha = 0xff; int fg_alpha = 0xff; float fg_alpha_opacity = 0.0f, bg_alpha_opacity = 0.0f; - const char *font_family = "Helvetica, sans-serif"; + const char font_family[] = "Helvetica, sans-serif"; int bold; struct zint_vector_rect *rect; @@ -317,7 +317,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { && (!is_extendable(symbol->symbology) || (symbol->output_options & SMALL_TEXT)); string = symbol->vector->strings; while (string) { - const char *halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle"; + const char *const halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle"; fprintf(fsvg, " x, string->y, halign); fprintf(fsvg, " font-family=\"%s\" font-size=\"%.1f\"", font_family, string->fsize); if (bold) { diff --git a/backend/telepen.c b/backend/telepen.c index 00895d0b..24c8f3f4 100644 --- a/backend/telepen.c +++ b/backend/telepen.c @@ -34,50 +34,63 @@ /* Telepen Barcode Symbology information and History (BSiH) https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf */ -#define SODIUM "0123456789X" +#define SODIUM_X_F (IS_NUM_F | IS_UX__F) /* SODIUM "0123456789X" */ #include #include "common.h" -static char *TeleTable[] = { - "31313131", "1131313111", "33313111", "1111313131", - "3111313111", "11333131", "13133131", "111111313111", - "31333111", "1131113131", "33113131", "1111333111", - "3111113131", "1113133111", "1311133111", "111111113131", - "3131113111", "11313331", "333331", "111131113111", - "31113331", "1133113111", "1313113111", "1111113331", - "31131331", "113111113111", "3311113111", "1111131331", - "311111113111", "1113111331", "1311111331", "11111111113111", - "31313311", "1131311131", "33311131", "1111313311", - "3111311131", "11333311", "13133311", "111111311131", - "31331131", "1131113311", "33113311", "1111331131", - "3111113311", "1113131131", "1311131131", "111111113311", - "3131111131", "1131131311", "33131311", "111131111131", - "3111131311", "1133111131", "1313111131", "111111131311", - "3113111311", "113111111131", "3311111131", "111113111311", - "311111111131", "111311111311", "131111111311", "11111111111131", - "3131311111", "11313133", "333133", "111131311111", - "31113133", "1133311111", "1313311111", "1111113133", - "313333", "113111311111", "3311311111", "11113333", - "311111311111", "11131333", "13111333", "11111111311111", - "31311133", "1131331111", "33331111", "1111311133", - "3111331111", "11331133", "13131133", "111111331111", - "3113131111", "1131111133", "33111133", "111113131111", - "3111111133", "111311131111", "131111131111", "111111111133", - "31311313", "113131111111", "3331111111", "1111311313", - "311131111111", "11331313", "13131313", "11111131111111", - "3133111111", "1131111313", "33111313", "111133111111", - "3111111313", "111313111111", "131113111111", "111111111313", - "313111111111", "1131131113", "33131113", "11113111111111", - "3111131113", "113311111111", "131311111111", "111111131113", - "3113111113", "11311111111111", "331111111111", "111113111113", - "31111111111111", "111311111113", "131111111113", "1111111111111111", +static char TeleTable[128][16] = { + { "31313131" }, { "1131313111" }, { "33313111" }, { "1111313131" }, + { "3111313111" }, { "11333131" }, { "13133131" }, { "111111313111" }, + { "31333111" }, { "1131113131" }, { "33113131" }, { "1111333111" }, + { "3111113131" }, { "1113133111" }, { "1311133111" }, { "111111113131" }, + { "3131113111" }, { "11313331" }, { "333331" }, { "111131113111" }, + { "31113331" }, { "1133113111" }, { "1313113111" }, { "1111113331" }, + { "31131331" }, { "113111113111" }, { "3311113111" }, { "1111131331" }, + { "311111113111" }, { "1113111331" }, { "1311111331" }, { "11111111113111" }, + { "31313311" }, { "1131311131" }, { "33311131" }, { "1111313311" }, + { "3111311131" }, { "11333311" }, { "13133311" }, { "111111311131" }, + { "31331131" }, { "1131113311" }, { "33113311" }, { "1111331131" }, + { "3111113311" }, { "1113131131" }, { "1311131131" }, { "111111113311" }, + { "3131111131" }, { "1131131311" }, { "33131311" }, { "111131111131" }, + { "3111131311" }, { "1133111131" }, { "1313111131" }, { "111111131311" }, + { "3113111311" }, { "113111111131" }, { "3311111131" }, { "111113111311" }, + { "311111111131" }, { "111311111311" }, { "131111111311" }, { "11111111111131" }, + { "3131311111" }, { "11313133" }, { "333133" }, { "111131311111" }, + { "31113133" }, { "1133311111" }, { "1313311111" }, { "1111113133" }, + { "313333" }, { "113111311111" }, { "3311311111" }, { "11113333" }, + { "311111311111" }, { "11131333" }, { "13111333" }, { "11111111311111" }, + { "31311133" }, { "1131331111" }, { "33331111" }, { "1111311133" }, + { "3111331111" }, { "11331133" }, { "13131133" }, { "111111331111" }, + { "3113131111" }, { "1131111133" }, { "33111133" }, { "111113131111" }, + { "3111111133" }, { "111311131111" }, { "131111131111" }, { "111111111133" }, + { "31311313" }, { "113131111111" }, { "3331111111" }, { "1111311313" }, + { "311131111111" }, { "11331313" }, { "13131313" }, { "11111131111111" }, + { "3133111111" }, { "1131111313" }, { "33111313" }, { "111133111111" }, + { "3111111313" }, { "111313111111" }, { "131113111111" }, { "111111111313" }, + { "313111111111" }, { "1131131113" }, { "33131113" }, { "11113111111111" }, + { "3111131113" }, { "113311111111" }, { "131311111111" }, { "111111131113" }, + { "3113111113" }, { "11311111111111" }, { "331111111111" }, { "111113111113" }, + { "31111111111111" }, { "111311111113" }, { "131111111113" }, + {'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'}, +}; +/* Generated by "backend/tests/test_telepen -f generate_lens -g" */ +static const char TeleLens[128] = { + 8, 10, 8, 10, 10, 8, 8, 12, 8, 10, 8, 10, 10, 10, 10, 12, + 10, 8, 6, 12, 8, 10, 10, 10, 8, 12, 10, 10, 12, 10, 10, 14, + 8, 10, 8, 10, 10, 8, 8, 12, 8, 10, 8, 10, 10, 10, 10, 12, + 10, 10, 8, 12, 10, 10, 10, 12, 10, 12, 10, 12, 12, 12, 12, 14, + 10, 8, 6, 12, 8, 10, 10, 10, 6, 12, 10, 8, 12, 8, 8, 14, + 8, 10, 8, 10, 10, 8, 8, 12, 10, 10, 8, 12, 10, 12, 12, 12, + 8, 12, 10, 10, 12, 8, 8, 14, 10, 10, 8, 12, 10, 12, 12, 12, + 12, 10, 8, 14, 10, 12, 12, 12, 10, 14, 12, 12, 14, 12, 12, 16 }; INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src_len) { int i, count, check_digit; int error_number; char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */ + char *d = dest; error_number = 0; @@ -88,7 +101,8 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src return ZINT_ERROR_TOO_LONG; } /* Start character */ - strcpy(dest, TeleTable['_']); + memcpy(d, TeleTable['_'], 12); + d += 12; for (i = 0; i < src_len; i++) { if (source[i] > 127) { @@ -96,7 +110,8 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src strcpy(symbol->errtxt, "391: Invalid character in input data, extended ASCII not allowed"); return ZINT_ERROR_INVALID_DATA; } - strcat(dest, TeleTable[source[i]]); + memcpy(d, TeleTable[source[i]], TeleLens[source[i]]); + d += TeleLens[source[i]]; count += source[i]; } @@ -104,14 +119,16 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src if (check_digit == 127) { check_digit = 0; } - strcat(dest, TeleTable[check_digit]); + memcpy(d, TeleTable[check_digit], TeleLens[check_digit]); + d += TeleLens[check_digit]; if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); /* Stop character */ - strcat(dest, TeleTable['z']); + memcpy(d, TeleTable['z'], 14); + d += 14; - expand(symbol, dest); + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { /* Default height from various Telepen docs is based on default 26pt at X 0.01125" @@ -137,6 +154,7 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int int error_number = 0; int i; char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */ + char *d = dest; unsigned char temp[64]; count = 0; @@ -146,8 +164,8 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int return ZINT_ERROR_TOO_LONG; } ustrcpy(temp, source); - to_upper(temp); - if (is_sane(SODIUM, temp, src_len) != 0) { + to_upper(temp, src_len); + if (!is_sane(SODIUM_X_F, temp, src_len)) { strcpy(symbol->errtxt, "393: Invalid character in data (digits and \"X\" only)"); return ZINT_ERROR_INVALID_DATA; } @@ -161,7 +179,8 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int } /* Start character */ - strcpy(dest, TeleTable['_']); + memcpy(d, TeleTable['_'], 12); + d += 12; for (i = 0; i < src_len; i += 2) { if (temp[i] == 'X') { @@ -177,21 +196,24 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int glyph += 27; count += glyph; } - strcat(dest, TeleTable[glyph]); + memcpy(d, TeleTable[glyph], TeleLens[glyph]); + d += TeleLens[glyph]; } check_digit = 127 - (count % 127); if (check_digit == 127) { check_digit = 0; } - strcat(dest, TeleTable[check_digit]); + memcpy(d, TeleTable[check_digit], TeleLens[check_digit]); + d += TeleLens[check_digit]; if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); /* Stop character */ - strcat(dest, TeleTable['z']); + memcpy(d, TeleTable['z'], 14); + d += 14; - expand(symbol, dest); + expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { (void) set_height(symbol, 0.0f, 32.0f, 0, 1 /*no_errtxt*/); /* Same as alphanumeric Telepen */ diff --git a/backend/tests/test_2of5.c b/backend/tests/test_2of5.c index 1b56a437..d5a1161a 100644 --- a/backend/tests/test_2of5.c +++ b/backend/tests/test_2of5.c @@ -236,61 +236,67 @@ static void test_encode(int index, int generate, int debug) { /* 1*/ { BARCODE_C25STANDARD, 1, "87654321", 0, 1, 107, "With check digit", "11110101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011110101" }, - /* 2*/ { BARCODE_C25INTER, -1, "87654321", 0, 1, 81, "Interleaved Code 2 of 5, even; verified manually against tec-it", + /* 2*/ { BARCODE_C25STANDARD, -1, "1234567890", 0, 1, 117, "", + "111101010111010111010001011101110001010101110111011101110101000111010101000111011101000101000100010101110001011110101" + }, + /* 3*/ { BARCODE_C25INTER, -1, "87654321", 0, 1, 81, "Interleaved Code 2 of 5, even; verified manually against tec-it", "101011101010111000100010001110111000101010001000111010111010001110101011100011101" }, - /* 3*/ { BARCODE_C25INTER, 1, "87654321", 0, 1, 99, "With check digit", + /* 4*/ { BARCODE_C25INTER, 1, "87654321", 0, 1, 99, "With check digit", "101010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101" }, - /* 4*/ { BARCODE_C25INTER, -1, "7654321", 0, 1, 81, "Interleaved Code 2 of 5, odd", + /* 5*/ { BARCODE_C25INTER, -1, "7654321", 0, 1, 81, "Interleaved Code 2 of 5, odd", "101010101110111000100010001110111000101010001000111010111010001110101011100011101" }, - /* 5*/ { BARCODE_C25INTER, 1, "7654321", 0, 1, 81, "With check digit", + /* 6*/ { BARCODE_C25INTER, 1, "7654321", 0, 1, 81, "With check digit", "101010100010001110111011101011100010100011101110001010100011101010001000111011101" }, - /* 6*/ { BARCODE_C25INTER, -1, "602003", 0, 1, 63, "DX cartridge barcode https://en.wikipedia.org/wiki/Interleaved_2_of_5 example", + /* 7*/ { BARCODE_C25INTER, -1, "602003", 0, 1, 63, "DX cartridge barcode https://en.wikipedia.org/wiki/Interleaved_2_of_5 example", "101010111011100010001010111010001000111010001000111011101011101" }, - /* 7*/ { BARCODE_C25IATA, -1, "87654321", 0, 1, 121, "IATA Code 2 of 5; verified manually against tec-it", + /* 8*/ { BARCODE_C25IATA, -1, "87654321", 0, 1, 121, "IATA Code 2 of 5; verified manually against tec-it", "1010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111011101" }, - /* 8*/ { BARCODE_C25IATA, 1, "87654321", 0, 1, 135, "With check digit", + /* 9*/ { BARCODE_C25IATA, 1, "87654321", 0, 1, 135, "With check digit", "101011101010111010101010111011101011101110101011101011101010101011101011101110111010101010111010101110111010101011101011101010111011101" }, - /* 9*/ { BARCODE_C25LOGIC, -1, "87654321", 0, 1, 89, "Code 2 of 5 Data Logic; verified manually against tec-it", + /* 10*/ { BARCODE_C25LOGIC, -1, "87654321", 0, 1, 89, "Code 2 of 5 Data Logic; verified manually against tec-it", "10101110100010101000111010001110101110111010101110111011100010101000101110111010111011101" }, - /* 10*/ { BARCODE_C25LOGIC, 1, "87654321", 0, 1, 99, "With check digit", + /* 11*/ { BARCODE_C25LOGIC, 1, "87654321", 0, 1, 99, "With check digit", "101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011101" }, - /* 11*/ { BARCODE_C25IND, -1, "87654321", 0, 1, 131, "Industrial Code 2 of 5; verified manually against tec-it", + /* 12*/ { BARCODE_C25IND, -1, "87654321", 0, 1, 131, "Industrial Code 2 of 5; verified manually against tec-it", "11101110101110101011101010101011101110101110111010101110101110101010101110101110111011101010101011101010111011101010101110111010111" }, - /* 12*/ { BARCODE_C25IND, 1, "87654321", 0, 1, 145, "With check digit", + /* 13*/ { BARCODE_C25IND, 1, "87654321", 0, 1, 145, "With check digit", "1110111010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111010111010101110111010111" }, - /* 13*/ { BARCODE_DPLEIT, -1, "0000087654321", 0, 1, 135, "Deutsche Post Leitcode; verified manually against tec-it", + /* 14*/ { BARCODE_C25IND, -1, "1234567890", 0, 1, 159, "", + "111011101011101010101110101110101011101110111010101010101110101110111010111010101011101110101010101011101110111010101110101011101011101010101110111010111010111" + }, + /* 15*/ { BARCODE_DPLEIT, -1, "0000087654321", 0, 1, 135, "Deutsche Post Leitcode; verified manually against tec-it", "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101" }, - /* 14*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example", + /* 16*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example", "101011101011100010001011101000101110100011101110100010001010101110111000100010100011101110100011101010001110001010001011100011101011101" }, - /* 15*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it", + /* 17*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it", "101010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101" }, - /* 16*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example", + /* 18*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example", "101011101110001010001010111011100010001011100010001010111011100010001010111010001011101011100010101110001000111011101" }, - /* 17*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it", + /* 19*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it", "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101" }, - /* 18*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2", + /* 20*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2", "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001010001000111011101011101" }, - /* 19*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1", + /* 21*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1", "101011100010100010111010101110001000111010001011101110100010001011101011100010001110101000111011101010111000100010001110001110101011101" }, - /* 20*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1", + /* 22*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1", "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001011101010001000111011101" }, }; @@ -351,6 +357,107 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITER_MILLES 5 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC) + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_C25INTER, -1, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", 0, 1, 819, "C25INTER 90" }, + /* 1*/ { BARCODE_C25INTER, -1, "1234567890", 0, 1, 99, "C25INTER 10" }, + /* 2*/ { BARCODE_C25STANDARD, -1, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 0, 1, 817, "C25STANDARD 80" }, + /* 3*/ { BARCODE_C25STANDARD, -1, "1234567890", 0, 1, 117, "C25STANDARD 10" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (index != -1 && i != index) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + 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->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); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -358,6 +465,7 @@ int main(int argc, char *argv[]) { { "test_hrt", test_hrt, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_auspost.c b/backend/tests/test_auspost.c index f9c6b2c0..e0674aa1 100644 --- a/backend/tests/test_auspost.c +++ b/backend/tests/test_auspost.c @@ -236,17 +236,42 @@ static void test_encode(int index, int generate, int debug) { "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "0000101010100010101010101000100000101010000010100010100010101010001010000010001010100000100010101000000000101000001010100000000010000" }, - /* 5*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it", + /* 5*/ { BARCODE_AUSPOST, "12345678DEGHJKLMNO", 0, 3, 133, "62 Custom 3 C encoding GDSET 1st part", + "1000001010001010100010101010100000100010000010101010101010001010001010101010101010100010101010101010100000001010000010000000000010100" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "0000101010101000101000100000001010101000101010001010000010101010100000101000100000101000001000000000001000001010000010001010001010000" + }, + /* 6*/ { BARCODE_AUSPOST, "23456789PQRSTUVWXY", 0, 3, 133, "62 Custom 3 C encoding GDSET 2nd part", + "1000001010001000101010101000001000100000001010001010001010000000101000101000100000101000101000100000001000101000101010101000101010100" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "0000101010101010001000000010101010001010001000101000100000101010101010100010101010001010000010001010101000000010001000001010101000000" + }, + /* 7*/ { BARCODE_AUSPOST, "34567890Zcefgijklm", 0, 3, 133, "62 Custom 3 C encoding GDSET 3rd part", + "1000001010001010101010000010001000000010101000001010001010000010100010100010001010001010000010000000100000101000100000001010001010100" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "0000101010100010000000101010100010100010101010100010000010000000100000000000001000000000001000000010100000101000000010101010100010000" + }, + /* 8*/ { BARCODE_AUSPOST, "12345678lnopqrstuv", 0, 3, 133, "62 Custom 3 C encoding GDSET 4th part", + "1000001010001010100010101010100000100010000010000000100000000000001000001000000000000000100000100000000000001010001010101000000010100" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "0000101010101000101000100000001010101000101000000010000010100010001010000010001010000000100000000000100000100000001010001000100000000" + }, + /* 9*/ { BARCODE_AUSPOST, "09876543wxy# ", 0, 3, 103, "59 Custom 2 C encoding GDSET 5th part", + "1000100000101010001000000010001010001010101000001000001000000010100010100000100010000000000010100010100" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "0000001000101010001010101000101000100000001000001000000000001010000010100000001010001000001000100000000" + }, + /* 10*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it", "1000101010001010100010101010100000100010000000001000001000000000100010100" "1010101010101010101010101010101010101010101010101010101010101010101010101" "0000000000101000101000100000001010101000101000000000100010101000101000000" }, - /* 6*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it", + /* 11*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it", "1000000000101010101010000010001000000010101000100010101010000000101000100" "1010101010101010101010101010101010101010101010101010101010101010101010101" "0000101010000010000000101010100010100010101000100010101010001010001000000" }, - /* 7*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it", + /* 12*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it", "1000001010000010000000100010100010101010100000101010101000100010100010100" "1010101010101010101010101010101010101010101010101010101010101010101010101" "0000001010100010101010001010001000000010101000000000001010101000001010000" diff --git a/backend/tests/test_channel.c b/backend/tests/test_channel.c index 3e1bc881..917abc85 100644 --- a/backend/tests/test_channel.c +++ b/backend/tests/test_channel.c @@ -31,6 +31,65 @@ #include "testcommon.h" +static void test_hrt(int index, int debug) { + + struct item { + int option_2; + char *data; + int length; + + char *expected; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + 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" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + testStart("test_hrt"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + 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); + + ret = ZBarcode_Encode(symbol, (unsigned char *) 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); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_input(int index, int debug) { struct item { @@ -436,6 +495,7 @@ static void test_generate(int generate) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_hrt", test_hrt, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, { "test_generate", test_generate, 0, 1, 0 }, diff --git a/backend/tests/test_codablock.c b/backend/tests/test_codablock.c index 5ee3b65e..2cf653ee 100644 --- a/backend/tests/test_codablock.c +++ b/backend/tests/test_codablock.c @@ -428,12 +428,25 @@ static void test_encode(int index, int generate, int debug) { "1101000010010111101110110001001001011000111011011001100100011000101101100110011011101000110110111101111011101010010000110100100111101100011101011" "1101000010010111101110101100111001000111101011001010000100011110101001101000011011011110101110111101000011001011011101110101001111001100011101011" }, - /* 11*/ { BARCODE_HIBC_BLOCKF, 3, -1, "A123BJC5D6E71", 0, 3, 123, 0, "Verified manually against tec-it; differs from BWIPP (columns=6) which uses Code C for final 71 (same no. of codewords)", + /* 11*/ { BARCODE_CODABLOCKF, -1, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 0, 11, 156, 1, "Visible ASCII", + "110100001001011110111010000110100110110011001100110110011001100110100100110001001000110010001001100100110010001001100010010001100100101100011101100011101011" + "110100001001011110111011000100100110010010001100100010011000100100101100111001001101110010011001110101110011001001110110010011100110100001100101100011101011" + "110100001001011101111010001101110111011011101011101100010000101100110110111101011110111011100100110111011001001110011010011100110010100001001101100011101011" + "110100001001011110111010011011100110110110001101100011011000110110101000110001000101100010001000110101100010001000110100010001100010111100010101100011101011" + "110100001001011110111010011001110110100010001100010100011000100010101101110001011000111010001101110101110110001011100011010001110110100110111001100011101011" + "110100001001011110111010111001100111011101101101000111011000101110110111010001101110001011011101110111010110001110100011011100010110100001011001100011101011" + "110100001001011110111011100100110111011010001110110001011100011010111011110101100100001011110001010101001100001010000110010010110000100011000101100011101011" + "110100001001011110111011101100100100100001101000010110010000100110101100100001011000010010011010000100110000101000011010010000110010101011110001100011101011" + "110100001001011110111011100110100110000100101100101000011110111010110000101001000111101010100111100100101111001001001111010111100100101100011101100011101011" + "110100001001011110111011100110010100111101001001111001011110100100111100101001111001001011011011110110111101101111011011010101111000111101010001100011101011" + "110100001001011110111011011011000101000111101000101111010111011110101111011101011101111010111101110101110111101011100011011101101110101001100001100011101011" + }, + /* 12*/ { BARCODE_HIBC_BLOCKF, 3, -1, "A123BJC5D6E71", 0, 3, 123, 0, "Verified manually against tec-it; differs from BWIPP (columns=6) which uses Code C for final 71 (same no. of codewords)", "110100001001011110111010010110000110001001001010001100010011100110110011100101100101110010001011000100100001101100011101011" "110100001001011110111011000100100101101110001000100011011011100100101100010001100111010010001101000111001001101100011101011" "110100001001011110111010110011100111011011101001110011011010001000101110111101011100011011001110100100100110001100011101011" }, - /* 12*/ { BARCODE_HIBC_BLOCKF, -1, -1, "$$52001510X3G", 0, 4, 101, 1, "tec-it differs as adds unnecessary Code C at end of 1st line", + /* 13*/ { BARCODE_HIBC_BLOCKF, -1, -1, "$$52001510X3G", 0, 4, 101, 1, "tec-it differs as adds unnecessary Code C at end of 1st line", "11010000100101111011101001000011011000100100100100011001001000110011011100100101110011001100011101011" "11010000100101110111101011000111011001001110110011011001101110100010111101110100001100101100011101011" "11010000100101111011101011001110010011101100111000101101100101110011010001000100100011001100011101011" diff --git a/backend/tests/test_code.c b/backend/tests/test_code.c index a6d8163f..e6a2835e 100644 --- a/backend/tests/test_code.c +++ b/backend/tests/test_code.c @@ -185,38 +185,64 @@ static void test_input(int index, int debug) { // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { /* 0*/ { BARCODE_CODE11, -1, "-", -1, 0, 1, 37 }, - /* 1*/ { BARCODE_CODE11, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 2*/ { BARCODE_CODE11, 3, "1", -1, ZINT_ERROR_INVALID_OPTION, -1, -1 }, - /* 3*/ { BARCODE_CODE39, -1, "a", -1, 0, 1, 38 }, // Converts to upper - /* 4*/ { BARCODE_CODE39, -1, ",", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 5*/ { BARCODE_CODE39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 6*/ { BARCODE_CODE39, 0, "1", -1, 0, 1, 38 }, - /* 7*/ { BARCODE_CODE39, 1, "1", -1, 0, 1, 51 }, // Check digit - /* 8*/ { BARCODE_CODE39, 2, "1", -1, 0, 1, 38 }, // option_2 > 1 gnored - /* 9*/ { BARCODE_EXCODE39, -1, "A", -1, 0, 1, 38 }, - /* 10*/ { BARCODE_EXCODE39, -1, "a", -1, 0, 1, 51 }, - /* 11*/ { BARCODE_EXCODE39, -1, ",", -1, 0, 1, 51 }, - /* 12*/ { BARCODE_EXCODE39, -1, "\000", 1, 0, 1, 51 }, - /* 13*/ { BARCODE_EXCODE39, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, - /* 14*/ { BARCODE_LOGMARS, -1, "A", -1, 0, 1, 47 }, - /* 15*/ { BARCODE_LOGMARS, -1, "a", -1, 0, 1, 47 }, - /* 16*/ { BARCODE_LOGMARS, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, - /* 17*/ { BARCODE_LOGMARS, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, }, - /* 18*/ { BARCODE_CODE93, -1, "A", -1, 0, 1, 46 }, - /* 19*/ { BARCODE_CODE93, -1, "a", -1, 0, 1, 55 }, - /* 20*/ { BARCODE_CODE93, -1, ",", -1, 0, 1, 55 }, - /* 21*/ { BARCODE_CODE93, -1, "\000", 1, 0, 1, 55 }, - /* 22*/ { BARCODE_CODE93, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 23*/ { BARCODE_PZN, -1, "1", -1, 0, 1, 142 }, - /* 24*/ { BARCODE_PZN, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 25*/ { BARCODE_PZN, -1, "1000006", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // Check digit == 10 so can't be used - /* 26*/ { BARCODE_VIN, -1, "5GZCZ43D13S812715", -1, 0, 1, 246 }, - /* 27*/ { BARCODE_VIN, -1, "5GZCZ43D23S812715", -1, ZINT_ERROR_INVALID_CHECK, -1, -1 }, // North American with invalid check character - /* 28*/ { BARCODE_VIN, -1, "WP0ZZZ99ZTS392124", -1, 0, 1, 246 }, // Not North American so no check - /* 29*/ { BARCODE_VIN, -1, "WPOZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // O not allowed - /* 30*/ { BARCODE_HIBC_39, -1, "a", -1, 0, 1, 79 }, // Converts to upper - /* 31*/ { BARCODE_HIBC_39, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 32*/ { BARCODE_HIBC_39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 1*/ { BARCODE_CODE11, -1, "0123456789-", -1, 0, 1, 115 }, + /* 2*/ { BARCODE_CODE11, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 3*/ { BARCODE_CODE11, -1, "12+", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 4*/ { BARCODE_CODE11, -1, "1.2", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 5*/ { BARCODE_CODE11, -1, "12!", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 6*/ { BARCODE_CODE11, -1, " ", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 7*/ { BARCODE_CODE11, 3, "1", -1, ZINT_ERROR_INVALID_OPTION, -1, -1 }, + /* 8*/ { BARCODE_CODE39, -1, "a", -1, 0, 1, 38 }, // Converts to upper + /* 9*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584 }, + /* 10*/ { BARCODE_CODE39, -1, "AB!", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 11*/ { BARCODE_CODE39, -1, "A\"B", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 12*/ { BARCODE_CODE39, -1, "#AB", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 13*/ { BARCODE_CODE39, -1, "&", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 14*/ { BARCODE_CODE39, -1, "'", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 15*/ { BARCODE_CODE39, -1, "(", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 16*/ { BARCODE_CODE39, -1, ")", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 17*/ { BARCODE_CODE39, -1, "*", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 18*/ { BARCODE_CODE39, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 19*/ { BARCODE_CODE39, -1, ":", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 20*/ { BARCODE_CODE39, -1, "@", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 21*/ { BARCODE_CODE39, -1, "[", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 22*/ { BARCODE_CODE39, -1, "`", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 23*/ { BARCODE_CODE39, -1, "{", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 24*/ { BARCODE_CODE39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 25*/ { BARCODE_CODE39, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 26*/ { BARCODE_CODE39, 0, "1", -1, 0, 1, 38 }, + /* 27*/ { BARCODE_CODE39, 1, "1", -1, 0, 1, 51 }, // Check digit + /* 28*/ { BARCODE_CODE39, 2, "1", -1, 0, 1, 38 }, // option_2 > 1 gnored + /* 29*/ { BARCODE_EXCODE39, -1, "A", -1, 0, 1, 38 }, + /* 30*/ { BARCODE_EXCODE39, -1, "a", -1, 0, 1, 51 }, + /* 31*/ { BARCODE_EXCODE39, -1, ",", -1, 0, 1, 51 }, + /* 32*/ { BARCODE_EXCODE39, -1, "\000", 1, 0, 1, 51 }, + /* 33*/ { BARCODE_EXCODE39, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 34*/ { BARCODE_EXCODE39, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, + /* 35*/ { BARCODE_LOGMARS, -1, "A", -1, 0, 1, 47 }, + /* 36*/ { BARCODE_LOGMARS, -1, "a", -1, 0, 1, 47 }, + /* 37*/ { BARCODE_LOGMARS, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, + /* 38*/ { BARCODE_LOGMARS, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, }, + /* 39*/ { BARCODE_LOGMARS, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, + /* 40*/ { BARCODE_CODE93, -1, "A", -1, 0, 1, 46 }, + /* 41*/ { BARCODE_CODE93, -1, "a", -1, 0, 1, 55 }, + /* 42*/ { BARCODE_CODE93, -1, ",", -1, 0, 1, 55 }, + /* 43*/ { BARCODE_CODE93, -1, "\000", 1, 0, 1, 55 }, + /* 44*/ { BARCODE_CODE93, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 45*/ { BARCODE_CODE93, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 46*/ { BARCODE_PZN, -1, "1", -1, 0, 1, 142 }, + /* 47*/ { BARCODE_PZN, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 48*/ { BARCODE_PZN, -1, "1000006", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // Check digit == 10 so can't be used + /* 49*/ { BARCODE_VIN, -1, "5GZCZ43D13S812715", -1, 0, 1, 246 }, + /* 50*/ { BARCODE_VIN, -1, "5GZCZ43D23S812715", -1, ZINT_ERROR_INVALID_CHECK, -1, -1 }, // North American with invalid check character + /* 51*/ { BARCODE_VIN, -1, "WP0ZZZ99ZTS392124", -1, 0, 1, 246 }, // Not North American so no check + /* 52*/ { BARCODE_VIN, -1, "WP0ZZZ99ZTS392I24", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // I not allowed + /* 53*/ { BARCODE_VIN, -1, "WPOZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // O not allowed + /* 54*/ { BARCODE_VIN, -1, "WPQZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // Q not allowed + /* 55*/ { BARCODE_HIBC_39, -1, "a", -1, 0, 1, 79 }, // Converts to upper + /* 56*/ { BARCODE_HIBC_39, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 57*/ { BARCODE_HIBC_39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 58*/ { BARCODE_HIBC_39, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -310,67 +336,82 @@ static void test_encode(int index, int generate, int debug) { /* 15*/ { BARCODE_CODE39, -1, "+A/E%U$A/D%T+Z", -1, 0, 1, 207, "Same as BARCODE_EXCODE39 'a%\000\001$\177z' below", "100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101" }, - /* 16*/ { BARCODE_EXCODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", + /* 16*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584, "Full CODE39 set", + "10010110110101010011011010110100101011010110010101101101100101010101001101011011010011010101011001101010101001011011011010010110101011001011010110101001011010110100101101101101001010101011001011011010110010101011011001010101010011011011010100110101011010011010101011001101011010101001101011010100110110110101001010101101001101101011010010101101101001010101011001101101010110010101101011001010101101100101100101010110100110101011011001101010101001011010110110010110101010011011010101001010110110110010101101010011010110101001001001010100100101001010010100100101010010010010100101101101" + }, + /* 17*/ { BARCODE_EXCODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", "100101101101011010010101101101010010110100101101101" }, - /* 17*/ { BARCODE_EXCODE39, 1, "1A", -1, 0, 1, 64, "With check digit", + /* 18*/ { BARCODE_EXCODE39, 1, "1A", -1, 0, 1, 64, "With check digit", "1001011011010110100101011011010100101101011010010110100101101101" }, - /* 18*/ { BARCODE_EXCODE39, 1, "Z4", -1, 0, 1, 64, "Check digit $", + /* 19*/ { BARCODE_EXCODE39, 1, "Z4", -1, 0, 1, 64, "Check digit $", "1001011011010100110110101010100110101101001001001010100101101101" }, - /* 19*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z", 7, 0, 1, 207, "Verified manually against tec-it", + /* 20*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z", 7, 0, 1, 207, "Verified manually against tec-it", "100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101" }, - /* 20*/ { BARCODE_EXCODE39, -1, "\033\037!+/\\@A~", -1, 0, 1, 246, "Verified manually against tec-it", + /* 21*/ { BARCODE_EXCODE39, -1, "\033\037!+/\\@A~", -1, 0, 1, 246, "Verified manually against tec-it", "100101101101010100100100101101010010110101001001001011010110010101001001010010110101001011010010010100101101010100110100100101001011010110100101010010010010101101010011010100100100101001101010110110101001011010100100100101011010110010100101101101" }, - /* 21*/ { BARCODE_LOGMARS, -1, "1A", -1, 0, 1, 63, "Verified manually against tec-it", + /* 22*/ { BARCODE_EXCODE39, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]", -1, 0, 1, 1130, "Visible ASCII 1st 85 symbol chars", + "10010110110101001101011010100100101001011010100101101001001010010101101001011010010010100101101101001010100100101001010101100101101001001010010110101100101010010010100101011011001010100100101001010101001101101001001010010110101001101010010010100101011010011010100100101001010101100110101001001010010110101010011010010010100101011010100110100101011011011001010110101001001010010110101101001010100110110101101001010110101100101011011011001010101010011010110110100110101010110011010101010010110110110100101101010110010110101001001010010100110110101010100100100101011011001010101001001001010101001101101010010010010110101001101010100100100101011010011010101001001001010101100110101010010010010100110101011011010100101101011010010110110110100101010101100101101101011001010101101100101010101001101101101010011010101101001101010101100110101101010100110101101010011011011010100101010110100110110101101001010110110100101010101100110110101011001010110101100101010110110010110010101011010011010101101100110101010100101101011011001011010101001101101010101001001001011010101001101010010010010101101010011010100100100101101101010010100101101101" + }, + /* 23*/ { BARCODE_EXCODE39, -1, "^_`abcdefghijklmnopqrstuvwxyz{|}~", -1, 0, 1, 883, "Visible ASCII last part", + "1001011011010101001001001010101101001101010010010010110101101001010100100100101100110101010100101001001011010100101101001010010010101101001011010010100100101101101001010100101001001010101100101101001010010010110101100101010010100100101011011001010100101001001010101001101101001010010010110101001101010010100100101011010011010100101001001010101100110101001010010010110101010011010010100100101011010100110100101001001011011010100101001010010010101011010011010010100100101101011010010100101001001010110110100101001010010010101010110011010010100100101101010110010100101001001010110101100101001010010010101011011001010010100100101100101010110100101001001010011010101101001010010010110011010101010010100100101001011010110100101001001011001011010101001010010010100110110101010100100100101011011010010101001001001010101011001101010010010010110101011001010100100100101011010110010100101101101" + }, + /* 24*/ { BARCODE_LOGMARS, -1, "1A", -1, 0, 1, 63, "Verified manually against tec-it", "100010111011101011101000101011101110101000101110100010111011101" }, - /* 22*/ { BARCODE_LOGMARS, 1, "1A", -1, 0, 1, 79, "With check digit; verified manually against tec-it", + /* 25*/ { BARCODE_LOGMARS, 1, "1A", -1, 0, 1, 79, "With check digit; verified manually against tec-it", "1000101110111010111010001010111011101010001011101011101000101110100010111011101" }, - /* 23*/ { BARCODE_LOGMARS, -1, "ABC", -1, 0, 1, 79, "MIL-STD-1189 Rev. B Figure 1", + /* 26*/ { BARCODE_LOGMARS, -1, "ABC", -1, 0, 1, 79, "MIL-STD-1189 Rev. B Figure 1", "1000101110111010111010100010111010111010001011101110111010001010100010111011101" }, - /* 24*/ { BARCODE_LOGMARS, -1, "SAMPLE 1", -1, 0, 1, 159, "MIL-STD-1189 Rev. B Figure 2 top", + /* 27*/ { BARCODE_LOGMARS, -1, "SAMPLE 1", -1, 0, 1, 159, "MIL-STD-1189 Rev. B Figure 2 top", "100010111011101010111010111000101110101000101110111011101010001010111011101000101011101010001110111010111000101010001110101110101110100010101110100010111011101" }, - /* 25*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, 0, 1, 223, "MIL-STD-1189 Rev. B Section 6.2.1 check character example; verified manually against tec-it", + /* 28*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, 0, 1, 223, "MIL-STD-1189 Rev. B Section 6.2.1 check character example; verified manually against tec-it", "1000101110111010111010001010111010111000101011101110111000101010101000111010111011101000111010101000100010100010111010100010111010111010001011101110111010001010101011100010111011101011100010101010111011100010100010111011101" }, - /* 26*/ { BARCODE_CODE93, -1, "C93", -1, 0, 1, 64, "ANSI/AIM BC5-1995 Figure 1; verified manually against tec-it", + /* 29*/ { BARCODE_CODE93, -1, "C93", -1, 0, 1, 64, "ANSI/AIM BC5-1995 Figure 1; verified manually against tec-it", "1010111101101000101000010101010000101101010001110110101010111101" }, - /* 27*/ { BARCODE_CODE93, -1, "CODE\01593", -1, 0, 1, 109, "ANSI/AIM BC5-1995 Figure B1; verified manually against tec-it", + /* 30*/ { BARCODE_CODE93, -1, "CODE\01593", -1, 0, 1, 109, "ANSI/AIM BC5-1995 Figure B1; verified manually against tec-it", "1010111101101000101001011001100101001100100101001001101010011001000010101010000101100101001000101101010111101" }, - /* 28*/ { BARCODE_CODE93, -1, "1A", -1, 0, 1, 55, "Verified manually against tec-it", + /* 31*/ { BARCODE_CODE93, -1, "1A", -1, 0, 1, 55, "Verified manually against tec-it", "1010111101010010001101010001101000101001110101010111101" }, - /* 29*/ { BARCODE_CODE93, -1, "TEST93", -1, 0, 1, 91, "Verified manually against tec-it", + /* 32*/ { BARCODE_CODE93, -1, "TEST93", -1, 0, 1, 91, "Verified manually against tec-it", "1010111101101001101100100101101011001101001101000010101010000101011101101001000101010111101" }, - /* 30*/ { BARCODE_CODE93, -1, "\000a\177", 3, 0, 1, 91, "Verified manually against tec-it", + /* 33*/ { BARCODE_CODE93, -1, "\000a\177", 3, 0, 1, 91, "Verified manually against tec-it", "1010111101110110101100101101001100101101010001110110101101001101011011101010010001010111101" }, - /* 31*/ { BARCODE_PZN, -1, "1234567", -1, 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against tec-it", + /* 34*/ { BARCODE_CODE93, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghij", -1, 0, 1, 1000, "Visible ASCII 1st 107 symbol chars", + "1010111101110100101110101101101010001110101101101001001110101101101000101110010101101011101110101101100010101110101101011010001110101101011001001110101101011000101110101101001101001011101101110101101010110001001011101110101001011011101000101001010010001010001001010000101001010001001001001001000101010100001000100101000010101110101101001110101110110101100010101110110101011010001110110101011001001110110101011000101110110101001101001110110101100110101101010001101001001101000101100101001100100101100010101011010001011001001011000101001101001000110101010110001010011001010001101001011001000101101101101001101100101101011001101001101100101101100110101011011001011001101001101101001110101110110101000110101110110101010110001110110101010011001110110101010001101110110101001011001110110101011011001001100101101010001001100101101001001001100101101000101001100101100101001001100101100100101001100101100010101001100101011010001001100101011001001001100101011000101001100101001101001010001101101001101010111101" + }, + /* 35*/ { BARCODE_CODE93, -1, "klmnopqrstuvwxyz{|}~", -1, 0, 1, 397, "Visible ASCII last part", + "1010111101001100101000110101001100101010110001001100101010011001001100101010001101001100101001011001001100101000101101001100101101101001001100101101100101001100101101011001001100101101001101001100101100101101001100101100110101001100101011011001001100101011001101001100101001101101001100101001110101110110101000101101110110101101101001110110101101100101110110101101011001101001001101100101010111101" + }, + /* 36*/ { BARCODE_PZN, -1, "1234567", -1, 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against tec-it", "1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101" }, - /* 32*/ { BARCODE_PZN, -1, "2758089", -1, 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against tec-it", + /* 37*/ { BARCODE_PZN, -1, "2758089", -1, 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against tec-it", "1001011011010100101011011010110010101101010010110110110100110101011010010110101010011011010110100101101010110010110101011001011010100101101101" }, - /* 33*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, 0, 1, 246, "https://www.vinquery.com/img/vinbarcode/vinbarcode4.jpg", + /* 38*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, 0, 1, 246, "https://www.vinquery.com/img/vinbarcode/vinbarcode4.jpg", "100101101101011010010101101011011001010101011011001011011010010101101010110010110100101011010100110110101100101010110100101101011010101101100101011011010010110101001011010100101101101101001011010110100101011011010010110101010011011010100101101101" }, - /* 34*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, 0, 1, 259, "With Import 'I' prefix; https://www.vinquery.com/img/vinbarcode/vinbarcode1.jpg", + /* 39*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, 0, 1, 259, "With Import 'I' prefix; https://www.vinquery.com/img/vinbarcode/vinbarcode1.jpg", "1001011011010101101001101010110010101101011011001010101011011001010110110100101001011010110101100101011011010010110101011010100110101001101101010010110101101101101001010110101001011011010010101101101001101010110100110101011010010101101101001010110100101101101" }, - /* 35*/ { BARCODE_HIBC_39, -1, "A123BJC5D6E71", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 2, same", + /* 40*/ { BARCODE_HIBC_39, -1, "A123BJC5D6E71", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 2, same", "1000101110111010100010100010001011101010001011101110100010101110101110001010111011101110001010101011101000101110101011100011101011101110100010101110100011101010101011100010111010111000111010101110101110001010101000101110111011101000101011101010100011101110100010111011101" }, - /* 36*/ { BARCODE_HIBC_39, -1, "$$52001510X3G", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 6, same", + /* 41*/ { BARCODE_HIBC_39, -1, "$$52001510X3G", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 6, same", "1000101110111010100010100010001010001000100010101000100010001010111010001110101010111000101011101010001110111010101000111011101011101000101011101110100011101010111010001010111010100011101110101000101110101110111011100010101010101000111011101010111000101110100010111011101" }, }; @@ -431,6 +472,111 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITER_MILLES 5 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC) + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+", 0, 1, 1130, "CODE39 85" }, + /* 1*/ { BARCODE_CODE39, -1, "123456ABCD", 0, 1, 155, "CODE39 10" }, + /* 2*/ { BARCODE_CODE93, -1, + "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !\"#$%&'()*+,-./0123456789ABCDEFGHIJ", + 0, 1, 1000, "CODE93 107 symbol chars" }, + /* 3*/ { BARCODE_CODE93, -1, "123456ABCD", 0, 1, 127, "CODE93 10" }, + /* 4*/ { BARCODE_CODE11, -1, "1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-", 0, 1, 966, "CODE11 121" }, + /* 5*/ { BARCODE_CODE11, -1, "1234567890-", 0, 1, 116, "CODE11 5" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (index != -1 && i != index) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + 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->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); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -438,6 +584,7 @@ int main(int argc, char *argv[]) { { "test_hrt", test_hrt, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index 03624dd5..f48d0092 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -839,6 +839,105 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITER_MILLES 10 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) (((arg) * 1000.0) / CLOCKS_PER_SEC) + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + struct item { + int symbology; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_CODE128, "123456ABCD123456ABCD123456ABCD123456ABCD123456ABCD123456ABCD", 0, 1, 618, "CODE128 60" }, + /* 1*/ { BARCODE_CODE128, "123456ABCD", 0, 1, 123, "CODE128 10" }, + /* 2*/ { BARCODE_GS1_128, "[01]09501101530003", 0, 1, 134, "GS1_128 (01)" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (index != -1 && i != index) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + 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->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); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -852,6 +951,7 @@ int main(int argc, char *argv[]) { { "test_ean14_input", test_ean14_input, 1, 1, 1 }, { "test_dpd_input", test_dpd_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_common.c b/backend/tests/test_common.c index f23ec65f..e874d49e 100644 --- a/backend/tests/test_common.c +++ b/backend/tests/test_common.c @@ -31,6 +31,230 @@ #include "testcommon.h" +/* Original */ +static int is_sane_orig(const char test_string[], const unsigned char source[], const int length) { + int i, j, lt = (int) strlen(test_string); + + for (i = 0; i < length; i++) { + unsigned int latch = FALSE; + for (j = 0; j < lt; j++) { + if (source[i] == test_string[j]) { + latch = TRUE; + break; + } + } + if (!(latch)) { + return ZINT_ERROR_INVALID_DATA; + } + } + + return 0; +} + +static void test_is_sane(int index) { + + struct item { + unsigned int flg; + char *data; + int length; + int ret; + + char *orig_test; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { IS_SPC_F, " ", -1, 1, " " }, + /* 1*/ { IS_SPC_F, "\000", 1, 0, " " }, + /* 2*/ { IS_HSH_F, "#", -1, 1, "#" }, + /* 3*/ { IS_HSH_F, " ", -1, 0, "#" }, + /* 4*/ { IS_PLS_F, "+", -1, 1, "+" }, + /* 5*/ { IS_PLS_F, " ", -1, 0, "+" }, + /* 6*/ { IS_MNS_F, "-", -1, 1, "-" }, + /* 7*/ { IS_MNS_F, " ", -1, 0, "-" }, + /* 8*/ { IS_NUM_F, "0123456789", -1, 1, "0123456789" }, // NEON + /* 9*/ { IS_NUM_F, "0123456789 ", -1, 0, "0123456789" }, + /* 10*/ { IS_NUM_F, "012345678A9", -1, 0, "0123456789" }, + /* 11*/ { IS_UPO_F, "GHIJKLMNOPQRSTUVWYZ", -1, 1, "GHIJKLMNOPQRSTUVWYZ" }, + /* 12*/ { IS_UPO_F, "FGHIJKLMNOPQRSTUVWYZ", -1, 0, "GHIJKLMNOPQRSTUVWYZ" }, + /* 13*/ { IS_LWO_F, "ghijklmnopqrstuvwyz", -1, 1, "ghijklmnopqrstuvwyz" }, + /* 14*/ { IS_LWO_F, "fghijklmnopqrstuvwyz", -1, 0, "ghijklmnopqrstuvwyz" }, + /* 15*/ { IS_UHX_F, "ABCDEF", -1, 1, "ABCDEF" }, + /* 16*/ { IS_UHX_F, "ABCDEf", -1, 0, "ABCDEF" }, + /* 17*/ { IS_LHX_F, "abcdef", -1, 1, "abcdef" }, + /* 18*/ { IS_LHX_F, "abcdeF", -1, 0, "abcdef" }, + /* 19*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 20*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 21*/ { IS_UPR_F, "X", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 22*/ { IS_UPR_F, "x", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 23*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz", -1, 1, "abcdefghijklmnopqrstuvwxyz" }, + /* 24*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz ", -1, 0, "abcdefghijklmnopqrstuvwxyz" }, + /* 25*/ { IS_LWR_F, "x", -1, 1, "abcdefghijklmnopqrstuvwxyz" }, + /* 26*/ { IS_LWR_F, "X", -1, 0, "abcdefghijklmnopqrstuvwxyz" }, + /* 27*/ { IS_UX__F, "X", -1, 1, "X" }, + /* 28*/ { IS_UX__F, "x", -1, 0, "X" }, + /* 29*/ { IS_LX__F, "x", -1, 1, "x" }, + /* 30*/ { IS_LX__F, "X", -1, 0, "x" }, + /* 31*/ { IS_C82_F, "!\"%&'()*,./:;<=>?_", -1, 1, "!\"%&'()*,./:;<=>?_" }, // CSET82 punctuation less "-+" + /* 32*/ { IS_C82_F, "!\"%&'()*,./:;<=>?_ ", -1, 0, "!\"%&'()*,./:;<=>?_" }, + /* 33*/ { IS_C82_F, "-", -1, 0, "!\"%&'()*,./:;<=>?_" }, + /* 34*/ { IS_C82_F, "$", -1, 0, "!\"%&'()*,./:;<=>?_" }, + /* 35*/ { IS_SIL_F, ".$/%", -1, 1, ".$/%" }, // SILVER punctuation less " -+" + /* 36*/ { IS_SIL_F, ".$/% " , -1, 0, ".$/%" }, + /* 37*/ { IS_SIL_F, "-", -1, 0, ".$/%" }, + /* 38*/ { IS_CLI_F, "$:/.", -1, 1, "$:/." }, // CALCIUM INNER punctuation less "-+" + /* 39*/ { IS_CLI_F, "$:/. ", -1, 0, "$:/." }, + /* 40*/ { IS_CLI_F, "+", -1, 0, "$:/." }, + /* 41*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC uppercase + /* 42*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ ", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 43*/ { IS_ARS_F, "I", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 44*/ { IS_ARS_F, "O", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 45*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEF", -1, 1, "0123456789ABCDEF" }, // SSET + /* 46*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEf", -1, 0, "0123456789ABCDEF" }, + /* 47*/ { IS_NUM_F | IS_PLS_F, "0123456789+", -1, 1, "0123456789+" }, // SODIUM_PLS + /* 48*/ { IS_NUM_F | IS_PLS_F, "0123456789+-", -1, 0, "0123456789+" }, + /* 49*/ { IS_NUM_F | IS_UX__F, "0123456789X", -1, 1, "0123456789X" }, // ISBNX_SANE + /* 50*/ { IS_NUM_F | IS_UX__F, "0123456789x", -1, 0, "0123456789X" }, + /* 51*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+", -1, 1, "0123456789Xx+" }, // ISBNX_ADDON_SANE + /* 52*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+Y", -1, 0, "0123456789Xx+" }, + /* 53*/ { IS_NUM_F | IS_MNS_F, "0123456789-", -1, 1, "0123456789-" }, // SODIUM_MNS + /* 54*/ { IS_NUM_F | IS_MNS_F, "0123456789-+", -1, 0, "0123456789-" }, + /* 55*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz", -1, 1, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, // CSET82 + /* 56*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, " ", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 57*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "#", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 58*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "$", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 59*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "@", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 60*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ ", -1, 1, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, // IS_ISOIEC_F + /* 61*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ #", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, + /* 62*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "$", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, + /* 63*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/+%", -1, 1, "" }, + /* 64*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/!+%", -1, 0, "" }, + /* 65*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, // SILVER + /* 66*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%a", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, + /* 67*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC + /* 68*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 69*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYz", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 70*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, // GDSET + /* 71*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #!", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, + /* 72*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+", -1, 1, "0123456789-$:/.+" }, // CALCIUM_INNER + /* 73*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+ ", -1, 0, "0123456789-$:/.+" }, + /* 74*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+!", -1, 0, "0123456789-$:/.+" }, + /* 75*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // KRSET + /* 76*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 77*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, // RUBIDIUM + /* 78*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789aBCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, + /* 79*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // SHKASUTSET + /* 80*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + + testStart("test_is_sane"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + + ret = is_sane(data[i].flg, (const unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + + if (data[i].orig_test[0]) { + int orig_ret = is_sane_orig(data[i].orig_test, (const unsigned char *) data[i].data, length); + if (orig_ret == 0) { + assert_nonzero(ret, "i:%d orig_ret %d, ret %d == 0\n", i, orig_ret, ret); + } else { + assert_zero(ret, "i:%d orig_ret %d, ret %d != 0\n", i, orig_ret, ret); + } + } + } + + testFinish(); +} + +static void test_is_sane_lookup(int index) { + + struct item { + char *test_string; + int test_length; + char *data; + int length; + int ret; + + int posns[32]; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "1234567", -1, "7654321357", -1, 1, { 6, 5, 4, 3, 2, 1, 0, 2, 4, 6 } }, + /* 1*/ { "1234567", -1, "76543213578", -1, 0, {0} }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + int test_length; + int posns[32]; + + testStart("test_is_sane_lookup"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + test_length = data[i].test_length == -1 ? (int) strlen(data[i].test_string) : data[i].test_length; + length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + + ret = is_sane_lookup(data[i].test_string, test_length, (const unsigned char *) data[i].data, length, posns); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + + if (ret) { + int j; + for (j = 0; j < length; j++) { + assert_equal(posns[j], data[i].posns[j], "i:%d posns[%d] %d != expected posns[%d] %d\n", i, j, posns[j], j, data[i].posns[j]); + } + } + } + + testFinish(); +} + +static void test_is_valid_utf8(int index) { + + struct item { + char *data; + int length; + int ret; + char *comment; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "", -1, 1, "" }, + /* 1*/ { "abcdefghijklmnopqrstuvwxyz", -1, 1, "" }, + /* 2*/ { "éa", -1, 1, "" }, + /* 3*/ { "a\000b", 3, 1, "Embedded nul" }, + /* 4*/ { "\357\273\277a", -1, 1, "Bom" }, + + /* 5*/ { "a\xC2", -1, 0, "Missing 2nd byte" }, + /* 6*/ { "a\200b", -1, 0, "Orphan continuation 0x80" }, + /* 7*/ { "\300\201", -1, 0, "Overlong 0xC081" }, + /* 8*/ { "\355\240\200", -1, 0, "Surrogate 0xEDA080" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + + testStart("test_is_valid_utf8"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + + ret = is_valid_utf8((const unsigned char *) data[i].data, length); + assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); + } + + testFinish(); +} + static void test_utf8_to_unicode(int index, int debug) { struct item { @@ -142,45 +366,6 @@ static void test_set_height(int index, int debug) { testFinish(); } -static void test_is_valid_utf8(int index) { - - struct item { - char *data; - int length; - int ret; - char *comment; - }; - // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) - struct item data[] = { - /* 0*/ { "", -1, 1, "" }, - /* 1*/ { "abcdefghijklmnopqrstuvwxyz", -1, 1, "" }, - /* 2*/ { "éa", -1, 1, "" }, - /* 3*/ { "a\000b", 3, 1, "Embedded nul" }, - /* 4*/ { "\357\273\277a", -1, 1, "Bom" }, - - /* 5*/ { "a\xC2", -1, 0, "Missing 2nd byte" }, - /* 6*/ { "a\200b", -1, 0, "Orphan continuation 0x80" }, - /* 7*/ { "\300\201", -1, 0, "Overlong 0xC081" }, - /* 8*/ { "\355\240\200", -1, 0, "Surrogate 0xEDA080" }, - }; - int data_size = ARRAY_SIZE(data); - int i, length, ret; - - testStart("test_is_valid_utf8"); - - for (i = 0; i < data_size; i++) { - - if (index != -1 && i != index) continue; - - length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - - ret = is_valid_utf8((const unsigned char *) data[i].data, length); - assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); - } - - testFinish(); -} - static void test_debug_test_codeword_dump_int(int index, int debug) { struct item { @@ -217,9 +402,11 @@ static void test_debug_test_codeword_dump_int(int index, int debug) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_is_sane", test_is_sane, 1, 0, 0 }, + { "test_is_sane_lookup", test_is_sane_lookup, 1, 0, 0 }, + { "test_is_valid_utf8", test_is_valid_utf8, 1, 0, 0 }, { "test_utf8_to_unicode", test_utf8_to_unicode, 1, 0, 1 }, { "test_set_height", test_set_height, 1, 0, 1 }, - { "test_is_valid_utf8", test_is_valid_utf8, 1, 0, 0 }, { "test_debug_test_codeword_dump_int", test_debug_test_codeword_dump_int, 1, 0, 1 }, }; diff --git a/backend/tests/test_emf.c b/backend/tests/test_emf.c index 041380d2..25105887 100644 --- a/backend/tests/test_emf.c +++ b/backend/tests/test_emf.c @@ -146,7 +146,7 @@ static void test_print(int index, int generate, int debug) { ret = testUtilCmpBins(symbol->outfile, expected_file); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); - assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + if (index == -1) assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); } ZBarcode_Delete(symbol); diff --git a/backend/tests/test_imail.c b/backend/tests/test_imail.c index 52e5b636..b23c26b8 100644 --- a/backend/tests/test_imail.c +++ b/backend/tests/test_imail.c @@ -62,7 +62,7 @@ static void test_csv(int index, int debug) { assert_nonnull(fd, "fopen(%s) == NULL", csvfile); while (fgets(buffer, sizeof(buffer), fd) != NULL) { - char *b; + const char *b; struct zint_symbol *symbol; lc++; diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index 6cf47806..ea4e9de4 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -501,7 +501,7 @@ static void test_cap_compliant_height() { testStart("test_cap_compliant_height"); - for (symbol_id = 1; symbol_id <= BARCODE_RMQR; symbol_id++) { + for (symbol_id = 1; symbol_id <= BARCODE_LAST; symbol_id++) { if (!ZBarcode_ValidID(symbol_id)) continue; ret = ZBarcode_Cap(symbol_id, ZINT_CAP_COMPLIANT_HEIGHT); diff --git a/backend/tests/test_output.c b/backend/tests/test_output.c index e9709c02..2b5466d2 100644 --- a/backend/tests/test_output.c +++ b/backend/tests/test_output.c @@ -31,7 +31,7 @@ #include "testcommon.h" -STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const int hide_text, +STATIC_UNLESS_ZINT_TEST int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text, float *left, float *right, float *top, float *bottom); static void test_quiet_zones(void) { @@ -42,11 +42,11 @@ static void test_quiet_zones(void) { testStart("test_quiet_zones"); - for (i = BARCODE_CODE11; i <= BARCODE_RMQR; i++) { + for (i = 1; i <= BARCODE_LAST; i++) { if (!ZBarcode_ValidID(i)) continue; symbol.symbology = i; symbol.output_options = BARCODE_QUIET_ZONES; - ret = quiet_zones(&symbol, hide_text, &left, &right, &top, &bottom); + ret = out_quiet_zones(&symbol, hide_text, &left, &right, &top, &bottom); if (i != BARCODE_FLAT) { // Only one which isn't marked as done assert_nonzero(ret, "i:%d %s not done\n", i, testUtilBarcodeName(i)); } diff --git a/backend/tests/test_plessey.c b/backend/tests/test_plessey.c index 264e49e4..3b88b0a3 100644 --- a/backend/tests/test_plessey.c +++ b/backend/tests/test_plessey.c @@ -319,6 +319,107 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITER_MILLES 5 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC) + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_PLESSEY, -1, "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1", 0, 1, 1107, "PLESSEY 65" }, + /* 1*/ { BARCODE_PLESSEY, -1, "123456ABCD", 0, 1, 227, "PLESSEY 10" }, + /* 2*/ { BARCODE_MSI_PLESSEY, -1, "12345678901234567890123456789012345678901234567890123456789012345", 0, 1, 787, "MSI_PLESSEY 65" }, + /* 3*/ { BARCODE_MSI_PLESSEY, -1, "1234567890", 0, 1, 127, "MSI_PLESSEY 10" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (index != -1 && i != index) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + 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->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); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -326,6 +427,7 @@ int main(int argc, char *argv[]) { { "test_hrt", test_hrt, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_png.c b/backend/tests/test_png.c index 5399168f..1fbd58b0 100644 --- a/backend/tests/test_png.c +++ b/backend/tests/test_png.c @@ -385,6 +385,33 @@ static void test_wpng_error_handler(void) { testFinish(); } +// Check compliant height printable for max CODABLOCKF with 44 rows * ((62 cols) * 0.55 + 3)) = 1632.4 +static void test_large_compliant_height(void) { + int ret; + struct zint_symbol *symbol = NULL; + const char pattern[] = { "1" }; + const int codablockf_max = 2726; + char data_buf[2726 + 1]; + + testStart("test_large_compliant_height"); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->symbology = BARCODE_CODABLOCKF; + symbol->output_options |= COMPLIANT_HEIGHT; + testUtilStrCpyRepeat(data_buf, pattern, codablockf_max); + assert_equal(codablockf_max, (int) strlen(data_buf), "length %d != strlen(data_buf) %d\n", codablockf_max, (int) strlen(data_buf)); + + ret = ZBarcode_Encode_and_Print(symbol, (const unsigned char *) data_buf, codablockf_max, 0); + assert_zero(ret, "ZBarcode_Encode_and_Print ret %d != 0 (%s)\n", ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "remove(%s) != 0\n", symbol->outfile); + + ZBarcode_Delete(symbol); + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -392,6 +419,7 @@ int main(int argc, char *argv[]) { { "test_print", test_print, 1, 1, 1 }, { "test_outfile", test_outfile, 0, 0, 0 }, { "test_wpng_error_handler", test_wpng_error_handler, 0, 0, 0 }, + { "test_large_compliant_height", test_large_compliant_height, 0, 0, 0 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_postal.c b/backend/tests/test_postal.c index 92dfd49f..0a7d8adc 100644 --- a/backend/tests/test_postal.c +++ b/backend/tests/test_postal.c @@ -59,16 +59,18 @@ static void test_large(int index, int debug) { /* 9*/ { BARCODE_RM4SCC, "1", 51, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 10*/ { BARCODE_JAPANPOST, "1", 20, 0, 3, 133 }, /* 11*/ { BARCODE_JAPANPOST, "1", 21, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 12*/ { BARCODE_KOREAPOST, "1", 6, 0, 1, 162 }, - /* 13*/ { BARCODE_KOREAPOST, "1", 7, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 14*/ { BARCODE_PLANET, "1", 13, 0, 2, 143 }, - /* 15*/ { BARCODE_PLANET, "1", 14, ZINT_WARN_NONCOMPLIANT, 2, 153 }, - /* 16*/ { BARCODE_PLANET, "1", 38, ZINT_WARN_NONCOMPLIANT, 2, 393 }, - /* 17*/ { BARCODE_PLANET, "1", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 18*/ { BARCODE_KIX, "1", 18, 0, 3, 143 }, - /* 19*/ { BARCODE_KIX, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 20*/ { BARCODE_DAFT, "D", 50, 0, 3, 99 }, - /* 21*/ { BARCODE_DAFT, "D", 51, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 12*/ { BARCODE_JAPANPOST, "A", 10, 0, 3, 133 }, + /* 13*/ { BARCODE_JAPANPOST, "A", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 14*/ { BARCODE_KOREAPOST, "1", 6, 0, 1, 162 }, + /* 15*/ { BARCODE_KOREAPOST, "1", 7, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 16*/ { BARCODE_PLANET, "1", 13, 0, 2, 143 }, + /* 17*/ { BARCODE_PLANET, "1", 14, ZINT_WARN_NONCOMPLIANT, 2, 153 }, + /* 18*/ { BARCODE_PLANET, "1", 38, ZINT_WARN_NONCOMPLIANT, 2, 393 }, + /* 19*/ { BARCODE_PLANET, "1", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 20*/ { BARCODE_KIX, "1", 18, 0, 3, 143 }, + /* 21*/ { BARCODE_KIX, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 22*/ { BARCODE_DAFT, "D", 100, 0, 3, 199 }, + /* 23*/ { BARCODE_DAFT, "D", 101, ZINT_ERROR_TOO_LONG, -1, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -237,27 +239,31 @@ static void test_input(int index, int debug) { /* 17*/ { BARCODE_RM4SCC, -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 3, 299, 8 }, /* 18*/ { BARCODE_RM4SCC, -1, 0, "a", 0, 3, 19, 8 }, // Converts to upper /* 19*/ { BARCODE_RM4SCC, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, - /* 20*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCDEFGH", 0, 3, 133, 8 }, - /* 21*/ { BARCODE_JAPANPOST, -1, 0, "a", 0, 3, 133, 8 }, // Converts to upper - /* 22*/ { BARCODE_JAPANPOST, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, - /* 23*/ { BARCODE_KOREAPOST, -1, 0, "123456", 0, 1, 167, 50 }, - /* 24*/ { BARCODE_KOREAPOST, -1, 0, "A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, - /* 25*/ { BARCODE_PLANET, -1, 0, "12345678901", 0, 2, 123, 12 }, - /* 26*/ { BARCODE_PLANET, -1, 0, "1234567890123", 0, 2, 143, 12 }, - /* 27*/ { BARCODE_PLANET, -1, 0, "0", ZINT_WARN_NONCOMPLIANT, 2, 23, 12 }, - /* 28*/ { BARCODE_PLANET, -1, 0, "1234567890", ZINT_WARN_NONCOMPLIANT, 2, 113, 12 }, - /* 29*/ { BARCODE_PLANET, -1, 0, "123456789012", ZINT_WARN_NONCOMPLIANT, 2, 133, 12 }, - /* 30*/ { BARCODE_PLANET, -1, 0, "12345678901234", ZINT_WARN_NONCOMPLIANT, 2, 153, 12 }, - /* 31*/ { BARCODE_PLANET, -1, 0, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, - /* 32*/ { BARCODE_KIX, -1, 0, "0123456789ABCDEFGH", 0, 3, 143, 8 }, - /* 33*/ { BARCODE_KIX, -1, 0, "a", 0, 3, 7, 8 }, // Converts to upper - /* 34*/ { BARCODE_KIX, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, - /* 35*/ { BARCODE_DAFT, -1, 0, "DAFT", 0, 3, 7, 8 }, - /* 36*/ { BARCODE_DAFT, -1, 0, "a", 0, 3, 1, 8 }, // Converts to upper - /* 37*/ { BARCODE_DAFT, -1, 0, "B", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, - /* 38*/ { BARCODE_DAFT, -1, 1.9, "DAFT", 0, 3, 7, 2 }, - /* 39*/ { BARCODE_DAFT, 500, 0.9, "DAFT", 0, 3, 7, 2 }, // 50% ratio - /* 40*/ { BARCODE_DAFT, 500, 0.4, "DAFT", 0, 3, 7, 8 }, // 50% ratio + /* 20*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCD", 0, 3, 133, 8 }, // 19 symbol chars + /* 21*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCD1", 0, 3, 133, 8 }, // 20 symbol chars + /* 22*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCDE", ZINT_ERROR_TOO_LONG, -1, -1, -1 }, // 21 symbol chars + /* 23*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCD12", ZINT_ERROR_TOO_LONG, -1, -1, -1 }, // 21 symbol chars + /* 24*/ { BARCODE_JAPANPOST, -1, 0, "1234567890ABCDE", 0, 3, 133, 8 }, // 20 symbol chars + /* 25*/ { BARCODE_JAPANPOST, -1, 0, "a", 0, 3, 133, 8 }, // Converts to upper + /* 26*/ { BARCODE_JAPANPOST, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, + /* 27*/ { BARCODE_KOREAPOST, -1, 0, "123456", 0, 1, 167, 50 }, + /* 28*/ { BARCODE_KOREAPOST, -1, 0, "A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, + /* 29*/ { BARCODE_PLANET, -1, 0, "12345678901", 0, 2, 123, 12 }, + /* 30*/ { BARCODE_PLANET, -1, 0, "1234567890123", 0, 2, 143, 12 }, + /* 31*/ { BARCODE_PLANET, -1, 0, "0", ZINT_WARN_NONCOMPLIANT, 2, 23, 12 }, + /* 32*/ { BARCODE_PLANET, -1, 0, "1234567890", ZINT_WARN_NONCOMPLIANT, 2, 113, 12 }, + /* 33*/ { BARCODE_PLANET, -1, 0, "123456789012", ZINT_WARN_NONCOMPLIANT, 2, 133, 12 }, + /* 34*/ { BARCODE_PLANET, -1, 0, "12345678901234", ZINT_WARN_NONCOMPLIANT, 2, 153, 12 }, + /* 35*/ { BARCODE_PLANET, -1, 0, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, + /* 36*/ { BARCODE_KIX, -1, 0, "0123456789ABCDEFGH", 0, 3, 143, 8 }, + /* 37*/ { BARCODE_KIX, -1, 0, "a", 0, 3, 7, 8 }, // Converts to upper + /* 38*/ { BARCODE_KIX, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, + /* 39*/ { BARCODE_DAFT, -1, 0, "DAFT", 0, 3, 7, 8 }, + /* 40*/ { BARCODE_DAFT, -1, 0, "a", 0, 3, 1, 8 }, // Converts to upper + /* 41*/ { BARCODE_DAFT, -1, 0, "B", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, + /* 42*/ { BARCODE_DAFT, -1, 1.9, "DAFT", 0, 3, 7, 2 }, + /* 43*/ { BARCODE_DAFT, 500, 0.9, "DAFT", 0, 3, 7, 2 }, // 50% ratio + /* 44*/ { BARCODE_DAFT, 500, 0.4, "DAFT", 0, 3, 7, 8 }, // 50% ratio }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -329,60 +335,95 @@ static void test_encode(int index, int generate, int debug) { "101010101010101010101010101010101010101010101010101010101010101010101010101" "000010100000100010001000100000101010100000100000100000101000100010001010001" }, - /* 6*/ { BARCODE_JAPANPOST, "15400233-16-4-205", 0, 3, 133, "Zip/Barcode Manual p.6 1st example; verified manually against tec-it", + /* 6*/ { BARCODE_RM4SCC, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 3, 299, "Verified manually against tec-it", + "10000010100000101000001010000010100000101000001010001000100010001000100010001000100010001000100010001010000010100000101000001010000010100000101000100000101000001010000010100000101000001010000010100010001000100010001000100010001000100010001000101000001010000010100000101000001010000010100000101000001" + "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "00000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000101000001" + }, + /* 7*/ { BARCODE_JAPANPOST, "15400233-16-4-205", 0, 3, 133, "Zip/Barcode Manual p.6 1st example; verified manually against tec-it", "1000101000100010101000100000100000100010001010001010001000101000001010001000101000001000100010100000100010000010000010000010001010001" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101000100010100010100000100000101000101000101000001000101000100010001000100010001000101000100000100010001000001000001000100010101" }, - /* 7*/ { BARCODE_JAPANPOST, "350110622-1A308", 0, 3, 133, "Zip/Barcode Manual p.6 2nd example; verified manually against tec-it", + /* 8*/ { BARCODE_JAPANPOST, "350110622-1A308", 0, 3, 133, "Zip/Barcode Manual p.6 2nd example; verified manually against tec-it", "1000001010100010100000101000101000100000001010100010100010001000101000001000100000001010100000100010000010000010000010000010100010001" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101000100010100000101000101000100000100010101000101000001000101000100000100000101000100000001010001000001000001000001000100010101" }, - /* 8*/ { BARCODE_JAPANPOST, "12345671-2-3", 0, 3, 133, "Verified manually against tec-it", + /* 9*/ { BARCODE_JAPANPOST, "12345671-2-3", 0, 3, 133, "Verified manually against tec-it", "1000101000100010001010101000100010001010101000101000001000100010001000001010000010000010000010000010000010000010000010000010100010001" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101000101000101000100010100010100010001010101000001000101000001000101000001000001000001000001000001000001000001000001000100010101" }, - /* 9*/ { BARCODE_KOREAPOST, "010230", 0, 1, 167, "Verified manually against tec-it", + /* 10*/ { BARCODE_JAPANPOST, "1234567BCDEFG", 0, 3, 133, "Verified manually against tec-it", + "1000101000100010001010101000100010001010101000001000101000001000100010001000001010001000101000001000100010001000001010000010101000001" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "1010101000101000101000100010100010100010001010100000101000100000101000100000101000100000100010100000100010100000100010001000100010101" + }, + /* 11*/ { BARCODE_JAPANPOST, "8901234HIJKLM", 0, 3, 133, "Verified manually against tec-it", + "1000100010001010100000101000100010001010101000001000101000001000100010001000001010000010100000000010101000000010100010000010100000001" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "1010001010001010100000101000101000101000100010100000001010100000001010100000001010100000100000100000101000100000101000001000000010101" + }, + /* 12*/ { BARCODE_JAPANPOST, "0987654NOPQRS", 0, 3, 133, "Verified manually against tec-it", + "1000100000001010100010101000001010100010101000000010001010000010101000000010100010000010001010000010101000000010100010000010100000001" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "1010100000001010001010001010100010100010100010100000101000100000100010100000100010100000100010100000001010100000001010001000001000101" + }, + /* 13*/ { BARCODE_JAPANPOST, "3210987TUVWXY", 0, 3, 133, "Verified manually against tec-it", + "1000001010100010101000100000001010100010101000000010001010100000100000100000101000100000100010100000001010100000101000000010000010001" + "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "1010101000101000101000100000001010001010001010100000001010001000100000001000101000001000101000001000101000001000100010001000100000101" + }, + /* 14*/ { BARCODE_KOREAPOST, "010230", 0, 1, 167, "Verified manually against tec-it", "10001000100000000000100010000000000010001000100000001000000010001000100010001000100000000000100000000001000100010001000100010001000000000001000000010001000000010001000" }, - /* 10*/ { BARCODE_KOREAPOST, "923457", 0, 1, 168, "Verified manually against tec-it", + /* 15*/ { BARCODE_KOREAPOST, "923457", 0, 1, 168, "Verified manually against tec-it", "000010001000100000001000100000001000000010001000000010001000000010001000100000000000100010001000000010000000100010001000100010000000100000001000100010001000000000001000" }, - /* 11*/ { BARCODE_PLANET, "4012345235636", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 4; verified manually against tec-it", + /* 16*/ { BARCODE_PLANET, "4012345235636", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 4; verified manually against tec-it", "10100010100000001010101010100000101000100010100000101000101000100010001010100010001010000010100010001010000010101010000010100000101010000010101" "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" }, - /* 12*/ { BARCODE_PLANET, "40123452356", 0, 2, 123, "Verified manually against tec-it", + /* 17*/ { BARCODE_PLANET, "40123452356", 0, 2, 123, "Verified manually against tec-it", "101000101000000010101010101000001010001000101000001010001010001000100010101000100010100000101000100010100000101010001000101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" }, - /* 13*/ { BARCODE_PLANET, "5020140235635", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 6; verified manually against tec-it", + /* 18*/ { BARCODE_PLANET, "5020140235635", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 6; verified manually against tec-it", "10100010001000001010101010001000000010101010101000001000101000000010101010100010001010000010100010001010000010101010000010100010001010001010001" "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" }, - /* 14*/ { BARCODE_KIX, "2500GG30250", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 1", + /* 19*/ { BARCODE_KIX, "2500GG30250", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 1", "000010100000101000001010000010100010100000101000000010100000101000001010000010100000101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "001010001010000000001010000010101000100010001000100000100000101000101000101000000000101" }, - /* 15*/ { BARCODE_KIX, "2130VA80430", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 2", + /* 20*/ { BARCODE_KIX, "2130VA80430", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 2", "000010100000101000001010000010101010000000100010001000100000101000001010000010100000101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "001010000010001010000010000010100010001010001000001010000000101010001000100000100000101" }, - /* 16*/ { BARCODE_KIX, "1231GF156X2", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 3", + /* 21*/ { BARCODE_KIX, "1231GF156X2", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 3", "000010100000101000001010000010100010100000101000000010100000101000100010101000000000101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "001000100010100010000010001000101000100010000010001000101010000000001010100000100010100" }, - /* 17*/ { BARCODE_KIX, "1231FZ13Xhs", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 4", + /* 22*/ { BARCODE_KIX, "1231FZ13Xhs", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 4", "000010100000101000001010000010100010100010100000000010100000101010100000001010001000100" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "001000100010100010000010001000101000001010100000001000101000001010000010101000001000100" }, - /* 18*/ { BARCODE_DAFT, "DAFTTFADFATDTATFT", 0, 3, 33, "Verified manually against tec-it", + /* 23*/ { BARCODE_KIX, "1234567890ABCDEFGH", 0, 3, 143, "Verified manually against tec-it", + "00001010000010100000101000001010000010100010001000100010001000100010001000001010001000100010001000101000001010000010100000101000001010000010100" + "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "00100010001010001000001010001000101000000000101000100010001010001000001000001010100010001010000000001010001000100010100010000010100010001010000" + }, + /* 24*/ { BARCODE_KIX, "IJKLMNOPQRSTUVWXYZ", 0, 3, 143, "Verified manually against tec-it", + "10000010100000101000001010000010100000101000001010001000100010001000100010001000100010001000100010100000101000001010000010100000101000001010000" + "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "00001010001000100010100010000010100010001010000000001010001000100010100010000010100010001010000000001010001000100010100010000010100010001010000" + }, + /* 25*/ { BARCODE_DAFT, "DAFTTFADFATDTATFT", 0, 3, 33, "Verified manually against tec-it", "001010000010100010100000001000100" "101010101010101010101010101010101" "100010000010001010000010000000100" @@ -445,6 +486,106 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITER_MILLES 10 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC) + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_POSTNET, -1, "12345678901", 0, 2, 123, "POSTNET 11" }, + /* 1*/ { BARCODE_PLANET, -1, "1234567890123", 0, 2, 143, "PLANET 13" }, + /* 2*/ { BARCODE_KOREAPOST, -1, "123456", 0, 1, 167, "KOREAPOST 6" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (index != -1 && i != index) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + 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->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); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -453,6 +594,7 @@ int main(int argc, char *argv[]) { { "test_japanpost", test_japanpost, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_raster.c b/backend/tests/test_raster.c index 059f90ee..29298903 100644 --- a/backend/tests/test_raster.c +++ b/backend/tests/test_raster.c @@ -2518,7 +2518,9 @@ static void test_height(int index, int generate, int debug) { #include -#define TEST_PERF_ITERATIONS 1000 +#define TEST_PERF_ITER_MILLES 1 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) (((arg) * 1000.0) / CLOCKS_PER_SEC) // Not a real test, just performance indicator for scaling static void test_perf_scale(int index, int debug) { @@ -2547,28 +2549,38 @@ static void test_perf_scale(int index, int debug) { "HIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567" "890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcde" "fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO", - 0, 40, 307, "960 chars, text/numeric" }, - /* 1*/ { BARCODE_POSTNET, -1, -1, BARCODE_QUIET_ZONES, -1, -1, 0, 1.1, "12345", 0, 2, 63, "" }, - /* 2*/ { BARCODE_ITF14, -1, 4, BARCODE_BIND, -1, -1, 61.8, 3.1, "12345", 0, 1, 135, "" }, + 0, 40, 307, "PDF417 960 chars, text/numeric, 1.3" }, + /* 1*/ { BARCODE_POSTNET, -1, -1, BARCODE_QUIET_ZONES, -1, -1, 0, 1.1, "12345", 0, 2, 63, "POSTNET 5 chars, quiet zones, 1.1" }, + /* 2*/ { BARCODE_ITF14, -1, 4, BARCODE_BIND, -1, -1, 61.8, 3.1, "12345", 0, 1, 135, "ITF14 bind 4, height 61.8, 3.1" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; + struct zint_symbol *symbol; - clock_t start, total_encode = 0, total_buffer = 0, diff_encode, diff_buffer; + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ return; } + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + for (i = 0; i < data_size; i++) { int j; if (index != -1 && i != index) continue; - diff_encode = diff_buffer = 0; + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; for (j = 0; j < TEST_PERF_ITERATIONS; j++) { - struct zint_symbol *symbol = ZBarcode_Create(); + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; assert_nonnull(symbol, "Symbol not created\n"); length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, data[i].output_options, data[i].data, -1, debug); @@ -2592,16 +2604,34 @@ static void test_perf_scale(int index, int debug) { diff_buffer += clock() - start; assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + ZBarcode_Delete(symbol); } - printf("%s: diff_encode %gms, diff_buffer %gms\n", data[i].comment, diff_encode * 1000.0 / CLOCKS_PER_SEC, diff_buffer * 1000.0 / CLOCKS_PER_SEC); + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + total_create += diff_create; total_encode += diff_encode; total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; } - if (index != -1) { - printf("totals: encode %gms, buffer %gms\n", total_encode * 1000.0 / CLOCKS_PER_SEC, total_buffer * 1000.0 / CLOCKS_PER_SEC); + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); } } diff --git a/backend/tests/test_reedsol.c b/backend/tests/test_reedsol.c index d0ef01fa..8dff481a 100644 --- a/backend/tests/test_reedsol.c +++ b/backend/tests/test_reedsol.c @@ -34,28 +34,28 @@ // Print out the log/alog tables for "backend/reedsol_logs.h" static void print_logs(const char *name, int logmod, unsigned int *logt, unsigned int *alog, int u16, int last) { - int i; + int i; const char *type = u16 ? "short" : "char"; const char *format = u16 ? " 0x%04X," : " 0x%02X,"; - printf("static const unsigned %s logt_%s[%d] = {", type, name, logmod + 1); - for (i = 0; i < logmod + 1; i++) { - if (i % 16 == 0) printf("\n "); - printf(format, i ? logt[i] : 0); - } - printf("\n};\n"); + printf("static const unsigned %s logt_%s[%d] = {", type, name, logmod + 1); + for (i = 0; i < logmod + 1; i++) { + if (i % 16 == 0) printf("\n "); + printf(format, i ? logt[i] : 0); + } + printf("\n};\n"); - printf("static const unsigned %s alog_%s[%d] = {", type, name, logmod * 2); - for (i = 0; i < logmod; i++) { - if (i % 16 == 0) printf("\n "); - printf(format, alog[i]); - } + printf("static const unsigned %s alog_%s[%d] = {", type, name, logmod * 2); + for (i = 0; i < logmod; i++) { + if (i % 16 == 0) printf("\n "); + printf(format, alog[i]); + } // Double antilog table for (i = 0; i < logmod; i++) { if (i % 16 == 0) printf("\n "); printf(format, alog[i]); } - printf("\n};\n"); + printf("\n};\n"); if (!last) { printf("\n"); } diff --git a/backend/tests/test_telepen.c b/backend/tests/test_telepen.c index a55fe7fa..dea2c358 100644 --- a/backend/tests/test_telepen.c +++ b/backend/tests/test_telepen.c @@ -330,6 +330,62 @@ static void test_fuzz(int index, int debug) { testFinish(); } +static char TeleTable[128][16] = { + { "31313131" }, { "1131313111" }, { "33313111" }, { "1111313131" }, + { "3111313111" }, { "11333131" }, { "13133131" }, { "111111313111" }, + { "31333111" }, { "1131113131" }, { "33113131" }, { "1111333111" }, + { "3111113131" }, { "1113133111" }, { "1311133111" }, { "111111113131" }, + { "3131113111" }, { "11313331" }, { "333331" }, { "111131113111" }, + { "31113331" }, { "1133113111" }, { "1313113111" }, { "1111113331" }, + { "31131331" }, { "113111113111" }, { "3311113111" }, { "1111131331" }, + { "311111113111" }, { "1113111331" }, { "1311111331" }, { "11111111113111" }, + { "31313311" }, { "1131311131" }, { "33311131" }, { "1111313311" }, + { "3111311131" }, { "11333311" }, { "13133311" }, { "111111311131" }, + { "31331131" }, { "1131113311" }, { "33113311" }, { "1111331131" }, + { "3111113311" }, { "1113131131" }, { "1311131131" }, { "111111113311" }, + { "3131111131" }, { "1131131311" }, { "33131311" }, { "111131111131" }, + { "3111131311" }, { "1133111131" }, { "1313111131" }, { "111111131311" }, + { "3113111311" }, { "113111111131" }, { "3311111131" }, { "111113111311" }, + { "311111111131" }, { "111311111311" }, { "131111111311" }, { "11111111111131" }, + { "3131311111" }, { "11313133" }, { "333133" }, { "111131311111" }, + { "31113133" }, { "1133311111" }, { "1313311111" }, { "1111113133" }, + { "313333" }, { "113111311111" }, { "3311311111" }, { "11113333" }, + { "311111311111" }, { "11131333" }, { "13111333" }, { "11111111311111" }, + { "31311133" }, { "1131331111" }, { "33331111" }, { "1111311133" }, + { "3111331111" }, { "11331133" }, { "13131133" }, { "111111331111" }, + { "3113131111" }, { "1131111133" }, { "33111133" }, { "111113131111" }, + { "3111111133" }, { "111311131111" }, { "131111131111" }, { "111111111133" }, + { "31311313" }, { "113131111111" }, { "3331111111" }, { "1111311313" }, + { "311131111111" }, { "11331313" }, { "13131313" }, { "11111131111111" }, + { "3133111111" }, { "1131111313" }, { "33111313" }, { "111133111111" }, + { "3111111313" }, { "111313111111" }, { "131113111111" }, { "111111111313" }, + { "313111111111" }, { "1131131113" }, { "33131113" }, { "11113111111111" }, + { "3111131113" }, { "113311111111" }, { "131311111111" }, { "111111131113" }, + { "3113111113" }, { "11311111111111" }, { "331111111111" }, { "111113111113" }, + { "31111111111111" }, { "111311111113" }, { "131111111113" }, + {'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'}, +}; + +// Dummy to generate lengths table +static void test_generate_lens(int generate) { + + int i; + + if (!generate) { + return; + } + + printf("static const char TeleLens[128] = {"); + for (i = 0; i < 127; i++) { + if ((i % 16) == 0) { + printf("\n %2d,", (int) strlen(TeleTable[i])); + } else { + printf(" %2d,", (int) strlen(TeleTable[i])); + } + } + printf(" 16\n};\n"); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -338,6 +394,7 @@ int main(int argc, char *argv[]) { { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, + { "test_generate_lens", test_generate_lens, 0, 1, 0 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_tif.c b/backend/tests/test_tif.c index 4058e340..2f1cedf9 100644 --- a/backend/tests/test_tif.c +++ b/backend/tests/test_tif.c @@ -92,7 +92,7 @@ static void test_pixel_plot(int index, int debug) { char *tif = "out.tif"; - char data_buf[65536]; + char data_buf[ZINT_MAX_DATA_LEN * 2 + 1]; int have_tiffinfo = testUtilHaveTiffInfo(); int have_identify = testUtilHaveIdentify(); diff --git a/backend/tests/test_upcean.c b/backend/tests/test_upcean.c index 957a4f53..f98bc64f 100644 --- a/backend/tests/test_upcean.c +++ b/backend/tests/test_upcean.c @@ -266,150 +266,154 @@ static void test_upca_input(int index, int debug) { testFinish(); } -static void test_eanx_input(int index, int debug) { +static void test_eanx_input(int index, int generate, int debug) { struct item { int symbology; char *data; int ret; + char *ret_errtxt; + char *comment; }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { BARCODE_EANX, "123456789012", 0 }, - /* 1*/ { BARCODE_EANX, "12345678901A", ZINT_ERROR_INVALID_DATA }, - /* 2*/ { BARCODE_EANX, "12345678901", 0 }, - /* 3*/ { BARCODE_EANX, "1234567890128", 0 }, // EANX accepts CHK (treated as such if no leading zeroes required) - /* 4*/ { BARCODE_EANX, "1234567890120", ZINT_ERROR_INVALID_CHECK }, - /* 5*/ { BARCODE_EANX, "123456789012+1", 0 }, - /* 6*/ { BARCODE_EANX, "1234567890128+1", 0 }, - /* 7*/ { BARCODE_EANX, "1234567890121+1", ZINT_ERROR_INVALID_CHECK }, - /* 8*/ { BARCODE_EANX, "123456789012+12", 0 }, - /* 9*/ { BARCODE_EANX, "1234567890128+12", 0 }, - /* 10*/ { BARCODE_EANX, "1234567890122+12", ZINT_ERROR_INVALID_CHECK }, - /* 11*/ { BARCODE_EANX, "12345678901234+12", ZINT_ERROR_TOO_LONG }, - /* 12*/ { BARCODE_EANX, "123456789012345+12", ZINT_ERROR_TOO_LONG }, - /* 13*/ { BARCODE_EANX, "1234567890123456+12", ZINT_ERROR_TOO_LONG }, - /* 14*/ { BARCODE_EANX, "123456789012+123", 0 }, - /* 15*/ { BARCODE_EANX, "1234567890128+123", 0 }, - /* 16*/ { BARCODE_EANX, "1234567890123+123", ZINT_ERROR_INVALID_CHECK }, - /* 17*/ { BARCODE_EANX, "12345678901234+123", ZINT_ERROR_TOO_LONG }, - /* 18*/ { BARCODE_EANX, "123456789012345+123", ZINT_ERROR_TOO_LONG }, - /* 19*/ { BARCODE_EANX, "123456789012+1234", 0 }, - /* 20*/ { BARCODE_EANX, "1234567890128+1234", 0 }, - /* 21*/ { BARCODE_EANX, "1234567890124+1234", ZINT_ERROR_INVALID_CHECK }, - /* 22*/ { BARCODE_EANX, "12345678901234+1234", ZINT_ERROR_TOO_LONG }, - /* 23*/ { BARCODE_EANX, "123456789012+12345", 0 }, - /* 24*/ { BARCODE_EANX, "1234567890128+12345", 0 }, - /* 25*/ { BARCODE_EANX, "12345678901234+12345", ZINT_ERROR_TOO_LONG }, - /* 26*/ { BARCODE_EANX, "1234567890125+12345", ZINT_ERROR_INVALID_CHECK }, - /* 27*/ { BARCODE_EANX, "123456789012+123456", ZINT_ERROR_TOO_LONG }, - /* 28*/ { BARCODE_EANX, "1234567890128+123456", ZINT_ERROR_TOO_LONG }, - /* 29*/ { BARCODE_EANX, "12345678901+123456", ZINT_ERROR_TOO_LONG }, - /* 30*/ { BARCODE_EANX, "12345678901+1234567", ZINT_ERROR_TOO_LONG }, - /* 31*/ { BARCODE_EANX, "1234567890+123456", ZINT_ERROR_TOO_LONG }, - /* 32*/ { BARCODE_EANX, "1234567890+1234567", ZINT_ERROR_TOO_LONG }, - /* 33*/ { BARCODE_EANX, "123456789+123456", ZINT_ERROR_TOO_LONG }, - /* 34*/ { BARCODE_EANX, "123456789+1234567", ZINT_ERROR_TOO_LONG }, - /* 35*/ { BARCODE_EANX, "12345678+123456", ZINT_ERROR_TOO_LONG }, - /* 36*/ { BARCODE_EANX, "1234567+123456", ZINT_ERROR_TOO_LONG }, // EAN-8 - /* 37*/ { BARCODE_EANX, "123456+123456", ZINT_ERROR_TOO_LONG }, - /* 38*/ { BARCODE_EANX, "12345+123456", ZINT_ERROR_TOO_LONG }, - /* 39*/ { BARCODE_EANX, "1234+123456", ZINT_ERROR_TOO_LONG }, - /* 40*/ { BARCODE_EANX, "123+123456", ZINT_ERROR_TOO_LONG }, - /* 41*/ { BARCODE_EANX, "12+123456", ZINT_ERROR_TOO_LONG }, - /* 42*/ { BARCODE_EANX, "1+123456", ZINT_ERROR_TOO_LONG }, - /* 43*/ { BARCODE_EANX, "1+12345678901234", ZINT_ERROR_TOO_LONG }, - /* 44*/ { BARCODE_EANX, "1+12345", 0 }, - /* 45*/ { BARCODE_EANX, "1+", 0 }, // EAN-2 - /* 46*/ { BARCODE_EANX, "+1", 0 }, // EAN-8 - /* 47*/ { BARCODE_EANX, "+", 0 }, // EAN-2 - /* 48*/ { BARCODE_EANX, "1", 0 }, // EAN-2 - /* 49*/ { BARCODE_EANX, "12", 0 }, // EAN-2 - /* 50*/ { BARCODE_EANX, "123", 0 }, // EAN-5 - /* 51*/ { BARCODE_EANX, "12345678901234", ZINT_ERROR_TOO_LONG }, - /* 52*/ { BARCODE_EANX, "1234567890123A", ZINT_ERROR_INVALID_DATA }, - /* 53*/ { BARCODE_EANX, "123456789012345", ZINT_ERROR_TOO_LONG }, - /* 54*/ { BARCODE_EANX, "12345678901234A", ZINT_ERROR_INVALID_DATA }, - /* 55*/ { BARCODE_EANX, "1234567890123456", ZINT_ERROR_TOO_LONG }, - /* 56*/ { BARCODE_EANX, "12345678901234567", ZINT_ERROR_TOO_LONG }, - /* 57*/ { BARCODE_EANX, "123456789012345678", ZINT_ERROR_TOO_LONG }, - /* 58*/ { BARCODE_EANX, "1234567890123456789", ZINT_ERROR_TOO_LONG }, - /* 59*/ { BARCODE_EANX_CHK, "1234567890128", 0 }, - /* 60*/ { BARCODE_EANX_CHK, "1234567890126", ZINT_ERROR_INVALID_CHECK }, - /* 61*/ { BARCODE_EANX_CHK, "123456789012A", ZINT_ERROR_INVALID_DATA }, - /* 62*/ { BARCODE_EANX_CHK, "123456789012", 0 }, // Note: this is "0123456789012" with '2' happening to be the correct check digit - /* 63*/ { BARCODE_EANX_CHK, "123456789013", ZINT_ERROR_INVALID_CHECK }, - /* 64*/ { BARCODE_EANX_CHK, "12345678901", ZINT_ERROR_INVALID_CHECK }, - /* 65*/ { BARCODE_EANX_CHK, "12345678905", 0 }, - /* 66*/ { BARCODE_EANX_CHK, "1234567890", ZINT_ERROR_INVALID_CHECK }, - /* 67*/ { BARCODE_EANX_CHK, "123456789", ZINT_ERROR_INVALID_CHECK }, - /* 68*/ { BARCODE_EANX_CHK, "12345678", ZINT_ERROR_INVALID_CHECK }, // EAN-8 - /* 69*/ { BARCODE_EANX_CHK, "1234567", ZINT_ERROR_INVALID_CHECK }, - /* 70*/ { BARCODE_EANX_CHK, "123456", ZINT_ERROR_INVALID_CHECK }, - /* 71*/ { BARCODE_EANX_CHK, "12345", 0 }, // EAN-5 - /* 72*/ { BARCODE_EANX_CHK, "1234", 0 }, - /* 73*/ { BARCODE_EANX_CHK, "123", 0 }, - /* 74*/ { BARCODE_EANX_CHK, "12", 0 }, // EAN-2 - /* 75*/ { BARCODE_EANX_CHK, "1", 0 }, - /* 76*/ { BARCODE_EANX_CHK, "123456789012+1", 0 }, - /* 77*/ { BARCODE_EANX_CHK, "1234567890128+1", 0 }, - /* 78*/ { BARCODE_EANX_CHK, "1234567890127+1", ZINT_ERROR_INVALID_CHECK }, - /* 79*/ { BARCODE_EANX_CHK, "123456789012+12", 0 }, - /* 80*/ { BARCODE_EANX_CHK, "1234567890128+12", 0 }, - /* 81*/ { BARCODE_EANX_CHK, "1234567890129+12", ZINT_ERROR_INVALID_CHECK }, - /* 82*/ { BARCODE_EANX_CHK, "123456789012+123", 0 }, - /* 83*/ { BARCODE_EANX_CHK, "1234567890128+123", 0 }, - /* 84*/ { BARCODE_EANX_CHK, "1234567890120+1234", ZINT_ERROR_INVALID_CHECK }, - /* 85*/ { BARCODE_EANX_CHK, "123456789012+1234", 0 }, - /* 86*/ { BARCODE_EANX_CHK, "1234567890128+1234", 0 }, - /* 87*/ { BARCODE_EANX_CHK, "1234567890121+1234", ZINT_ERROR_INVALID_CHECK }, - /* 88*/ { BARCODE_EANX_CHK, "123456789012+12345", 0 }, - /* 89*/ { BARCODE_EANX_CHK, "1234567890128+12345", 0 }, - /* 90*/ { BARCODE_EANX_CHK, "1234567890122+12345", ZINT_ERROR_INVALID_CHECK }, - /* 91*/ { BARCODE_EANX_CHK, "1234567890122+1234A", ZINT_ERROR_INVALID_DATA }, - /* 92*/ { BARCODE_EANX_CHK, "123456789012+123456", ZINT_ERROR_TOO_LONG }, - /* 93*/ { BARCODE_EANX_CHK, "123456789012+12345A", ZINT_ERROR_INVALID_DATA }, - /* 94*/ { BARCODE_EANX_CHK, "1234567890128+123456", ZINT_ERROR_TOO_LONG }, - /* 95*/ { BARCODE_EANX_CHK, "12345678901+123456", ZINT_ERROR_TOO_LONG }, - /* 96*/ { BARCODE_EANX_CHK, "12345678901+1234567", ZINT_ERROR_TOO_LONG }, - /* 97*/ { BARCODE_EANX_CHK, "12345678901+12345", ZINT_ERROR_INVALID_CHECK }, - /* 98*/ { BARCODE_EANX_CHK, "1234567890+12345", ZINT_ERROR_INVALID_CHECK }, - /* 99*/ { BARCODE_EANX_CHK, "1234567890+123456", ZINT_ERROR_TOO_LONG }, - /*100*/ { BARCODE_EANX_CHK, "123456789+12345", ZINT_ERROR_INVALID_CHECK }, - /*101*/ { BARCODE_EANX_CHK, "12345678+12345", ZINT_ERROR_INVALID_CHECK }, // EAN-8 - /*102*/ { BARCODE_EANX_CHK, "12345670+12345", 0 }, - /*103*/ { BARCODE_EANX_CHK, "1234567+12345", ZINT_ERROR_INVALID_CHECK }, - /*104*/ { BARCODE_EANX_CHK, "1234565+12345", 0 }, - /*105*/ { BARCODE_EANX_CHK, "123456+12345", ZINT_ERROR_INVALID_CHECK }, - /*106*/ { BARCODE_EANX_CHK, "123457+12345", 0 }, - /*107*/ { BARCODE_EANX_CHK, "12345+12345", ZINT_ERROR_INVALID_CHECK }, - /*108*/ { BARCODE_EANX_CHK, "12348+12345", 0 }, - /*109*/ { BARCODE_EANX_CHK, "1234+12345", ZINT_ERROR_INVALID_CHECK }, - /*110*/ { BARCODE_EANX_CHK, "1236+12345", 0 }, - /*111*/ { BARCODE_EANX_CHK, "123+12345", 0 }, // 3 happens to be correct check digit - /*112*/ { BARCODE_EANX_CHK, "124+12345", ZINT_ERROR_INVALID_CHECK }, - /*113*/ { BARCODE_EANX_CHK, "12+12345", ZINT_ERROR_INVALID_CHECK }, - /*114*/ { BARCODE_EANX_CHK, "17+12345", 0 }, - /*115*/ { BARCODE_EANX_CHK, "1+12345", ZINT_ERROR_INVALID_CHECK }, - /*116*/ { BARCODE_EANX_CHK, "0+12345", 0 }, - /*117*/ { BARCODE_EANX_CHK, "0+123456", ZINT_ERROR_TOO_LONG }, - /*118*/ { BARCODE_EANX_CHK, "1+12345678901234", ZINT_ERROR_TOO_LONG }, - /*119*/ { BARCODE_EANX_CHK, "0+12345678901234", ZINT_ERROR_TOO_LONG }, - /*120*/ { BARCODE_EANX_CHK, "1+", 0 }, // EAN-2 - /*121*/ { BARCODE_EANX_CHK, "+1", 0 }, // EAN-8 - /*122*/ { BARCODE_EANX_CHK, "+", 0 }, // EAN-2 - /*123*/ { BARCODE_EANX_CHK, "12345678901234", ZINT_ERROR_TOO_LONG }, - /*124*/ { BARCODE_EANX_CHK, "1234567890123A", ZINT_ERROR_INVALID_DATA }, - /*125*/ { BARCODE_EANX_CHK, "123456789012345", ZINT_ERROR_TOO_LONG }, - /*126*/ { BARCODE_EANX_CHK, "1234567890123456", ZINT_ERROR_TOO_LONG }, - /*127*/ { BARCODE_EANX_CHK, "12345678901234567", ZINT_ERROR_TOO_LONG }, - /*128*/ { BARCODE_EANX_CHK, "123456789012345678", ZINT_ERROR_TOO_LONG }, - /*129*/ { BARCODE_EANX_CHK, "1234567890123456789", ZINT_ERROR_TOO_LONG }, + /* 0*/ { BARCODE_EANX, "123456789012", 0, "", "" }, + /* 1*/ { BARCODE_EANX, "12345678901A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /* 2*/ { BARCODE_EANX, "12345678901", 0, "", "" }, + /* 3*/ { BARCODE_EANX, "1234567890128", 0, "", "EANX accepts CHK (treated as such if no leading zeroes required)" }, + /* 4*/ { BARCODE_EANX, "1234567890120", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '8'", "" }, + /* 5*/ { BARCODE_EANX, "123456789012+1", 0, "", "" }, + /* 6*/ { BARCODE_EANX, "1234567890128+1", 0, "", "" }, + /* 7*/ { BARCODE_EANX, "1234567890121+1", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '8'", "" }, + /* 8*/ { BARCODE_EANX, "123456789012+12", 0, "", "" }, + /* 9*/ { BARCODE_EANX, "1234567890128+12", 0, "", "" }, + /* 10*/ { BARCODE_EANX, "1234567890122+12", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '2', expecting '8'", "" }, + /* 11*/ { BARCODE_EANX, "12345678901234+12", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 12*/ { BARCODE_EANX, "123456789012345+12", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 13*/ { BARCODE_EANX, "1234567890123456+12", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 14*/ { BARCODE_EANX, "123456789012+123", 0, "", "" }, + /* 15*/ { BARCODE_EANX, "1234567890128+123", 0, "", "" }, + /* 16*/ { BARCODE_EANX, "1234567890123+123", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '3', expecting '8'", "" }, + /* 17*/ { BARCODE_EANX, "12345678901234+123", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 18*/ { BARCODE_EANX, "123456789012345+123", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 19*/ { BARCODE_EANX, "123456789012+1234", 0, "", "" }, + /* 20*/ { BARCODE_EANX, "1234567890128+1234", 0, "", "" }, + /* 21*/ { BARCODE_EANX, "1234567890124+1234", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '4', expecting '8'", "" }, + /* 22*/ { BARCODE_EANX, "12345678901234+1234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 23*/ { BARCODE_EANX, "123456789012+12345", 0, "", "" }, + /* 24*/ { BARCODE_EANX, "1234567890128+12345", 0, "", "" }, + /* 25*/ { BARCODE_EANX, "12345678901234+12345", ZINT_ERROR_TOO_LONG, "Error 283: Input too long (19 character maximum)", "" }, + /* 26*/ { BARCODE_EANX, "1234567890125+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '5', expecting '8'", "" }, + /* 27*/ { BARCODE_EANX, "123456789012+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 28*/ { BARCODE_EANX, "1234567890128+123456", ZINT_ERROR_TOO_LONG, "Error 283: Input too long (19 character maximum)", "" }, + /* 29*/ { BARCODE_EANX, "12345678901+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 30*/ { BARCODE_EANX, "12345678901+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 31*/ { BARCODE_EANX, "1234567890+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 32*/ { BARCODE_EANX, "1234567890+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 33*/ { BARCODE_EANX, "123456789+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 34*/ { BARCODE_EANX, "123456789+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 35*/ { BARCODE_EANX, "12345678+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 36*/ { BARCODE_EANX, "1234567+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "EAN-8" }, + /* 37*/ { BARCODE_EANX, "123456+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 38*/ { BARCODE_EANX, "12345+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 39*/ { BARCODE_EANX, "1234+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 40*/ { BARCODE_EANX, "123+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 41*/ { BARCODE_EANX, "12+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 42*/ { BARCODE_EANX, "1+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 43*/ { BARCODE_EANX, "1+12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 44*/ { BARCODE_EANX, "1+12345", 0, "", "" }, + /* 45*/ { BARCODE_EANX, "1+", 0, "", "EAN-2" }, + /* 46*/ { BARCODE_EANX, "+1", 0, "", "EAN-8" }, + /* 47*/ { BARCODE_EANX, "+", 0, "", "EAN-2" }, + /* 48*/ { BARCODE_EANX, "1", 0, "", "EAN-2" }, + /* 49*/ { BARCODE_EANX, "12", 0, "", "EAN-2" }, + /* 50*/ { BARCODE_EANX, "123", 0, "", "EAN-5" }, + /* 51*/ { BARCODE_EANX, "12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 52*/ { BARCODE_EANX, "1234567890123A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /* 53*/ { BARCODE_EANX, "123456789012345", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 54*/ { BARCODE_EANX, "12345678901234A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /* 55*/ { BARCODE_EANX, "1234567890123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 56*/ { BARCODE_EANX, "12345678901234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 57*/ { BARCODE_EANX, "123456789012345678", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 58*/ { BARCODE_EANX, "1234567890123456789", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /* 59*/ { BARCODE_EANX_CHK, "1234567890128", 0, "", "" }, + /* 60*/ { BARCODE_EANX_CHK, "1234567890126", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '6', expecting '8'", "" }, + /* 61*/ { BARCODE_EANX_CHK, "123456789012A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /* 62*/ { BARCODE_EANX_CHK, "123456789012", 0, "", "Note: this is '0123456789012' with '2' happening to be the correct check digit" }, + /* 63*/ { BARCODE_EANX_CHK, "123456789013", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '3', expecting '2'", "" }, + /* 64*/ { BARCODE_EANX_CHK, "12345678901", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '5'", "" }, + /* 65*/ { BARCODE_EANX_CHK, "12345678905", 0, "", "" }, + /* 66*/ { BARCODE_EANX_CHK, "1234567890", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '5'", "" }, + /* 67*/ { BARCODE_EANX_CHK, "123456789", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '9', expecting '4'", "" }, + /* 68*/ { BARCODE_EANX_CHK, "12345678", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '8', expecting '0'", "EAN-8" }, + /* 69*/ { BARCODE_EANX_CHK, "1234567", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '7', expecting '5'", "" }, + /* 70*/ { BARCODE_EANX_CHK, "123456", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '6', expecting '7'", "" }, + /* 71*/ { BARCODE_EANX_CHK, "12345", 0, "", "EAN-5" }, + /* 72*/ { BARCODE_EANX_CHK, "1234", 0, "", "" }, + /* 73*/ { BARCODE_EANX_CHK, "123", 0, "", "" }, + /* 74*/ { BARCODE_EANX_CHK, "12", 0, "", "EAN-2" }, + /* 75*/ { BARCODE_EANX_CHK, "1", 0, "", "" }, + /* 76*/ { BARCODE_EANX_CHK, "123456789012+1", 0, "", "" }, + /* 77*/ { BARCODE_EANX_CHK, "1234567890128+1", 0, "", "" }, + /* 78*/ { BARCODE_EANX_CHK, "1234567890127+1", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '7', expecting '8'", "" }, + /* 79*/ { BARCODE_EANX_CHK, "123456789012+12", 0, "", "" }, + /* 80*/ { BARCODE_EANX_CHK, "1234567890128+12", 0, "", "" }, + /* 81*/ { BARCODE_EANX_CHK, "1234567890129+12", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '9', expecting '8'", "" }, + /* 82*/ { BARCODE_EANX_CHK, "123456789012+123", 0, "", "" }, + /* 83*/ { BARCODE_EANX_CHK, "1234567890128+123", 0, "", "" }, + /* 84*/ { BARCODE_EANX_CHK, "1234567890120+1234", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '8'", "" }, + /* 85*/ { BARCODE_EANX_CHK, "123456789012+1234", 0, "", "" }, + /* 86*/ { BARCODE_EANX_CHK, "1234567890128+1234", 0, "", "" }, + /* 87*/ { BARCODE_EANX_CHK, "1234567890121+1234", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '8'", "" }, + /* 88*/ { BARCODE_EANX_CHK, "123456789012+12345", 0, "", "" }, + /* 89*/ { BARCODE_EANX_CHK, "1234567890128+12345", 0, "", "" }, + /* 90*/ { BARCODE_EANX_CHK, "1234567890122+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '2', expecting '8'", "" }, + /* 91*/ { BARCODE_EANX_CHK, "1234567890122+1234A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /* 92*/ { BARCODE_EANX_CHK, "123456789012+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 93*/ { BARCODE_EANX_CHK, "123456789012+12345A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /* 94*/ { BARCODE_EANX_CHK, "1234567890128+123456", ZINT_ERROR_TOO_LONG, "Error 283: Input too long (19 character maximum)", "" }, + /* 95*/ { BARCODE_EANX_CHK, "12345678901+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 96*/ { BARCODE_EANX_CHK, "12345678901+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 97*/ { BARCODE_EANX_CHK, "12345678901+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '5'", "" }, + /* 98*/ { BARCODE_EANX_CHK, "1234567890+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '5'", "" }, + /* 99*/ { BARCODE_EANX_CHK, "1234567890+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /*100*/ { BARCODE_EANX_CHK, "123456789+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '9', expecting '4'", "" }, + /*101*/ { BARCODE_EANX_CHK, "12345678+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '8', expecting '0'", "EAN-8" }, + /*102*/ { BARCODE_EANX_CHK, "12345670+12345", 0, "", "" }, + /*103*/ { BARCODE_EANX_CHK, "1234567+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '7', expecting '5'", "" }, + /*104*/ { BARCODE_EANX_CHK, "1234565+12345", 0, "", "" }, + /*105*/ { BARCODE_EANX_CHK, "123456+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '6', expecting '7'", "" }, + /*106*/ { BARCODE_EANX_CHK, "123457+12345", 0, "", "" }, + /*107*/ { BARCODE_EANX_CHK, "12345+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '5', expecting '8'", "" }, + /*108*/ { BARCODE_EANX_CHK, "12348+12345", 0, "", "" }, + /*109*/ { BARCODE_EANX_CHK, "1234+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '4', expecting '6'", "" }, + /*110*/ { BARCODE_EANX_CHK, "1236+12345", 0, "", "" }, + /*111*/ { BARCODE_EANX_CHK, "123+12345", 0, "", "3 happens to be correct check digit" }, + /*112*/ { BARCODE_EANX_CHK, "124+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '4', expecting '3'", "" }, + /*113*/ { BARCODE_EANX_CHK, "12+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '2', expecting '7'", "" }, + /*114*/ { BARCODE_EANX_CHK, "17+12345", 0, "", "" }, + /*115*/ { BARCODE_EANX_CHK, "1+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '1', expecting '0'", "" }, + /*116*/ { BARCODE_EANX_CHK, "0+12345", 0, "", "" }, + /*117*/ { BARCODE_EANX_CHK, "0+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /*118*/ { BARCODE_EANX_CHK, "1+12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /*119*/ { BARCODE_EANX_CHK, "0+12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /*120*/ { BARCODE_EANX_CHK, "1+", 0, "", "EAN-2" }, + /*121*/ { BARCODE_EANX_CHK, "+1", 0, "", "EAN-8" }, + /*122*/ { BARCODE_EANX_CHK, "+", 0, "", "EAN-2" }, + /*123*/ { BARCODE_EANX_CHK, "12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /*124*/ { BARCODE_EANX_CHK, "1234567890123A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" }, + /*125*/ { BARCODE_EANX_CHK, "123456789012345", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /*126*/ { BARCODE_EANX_CHK, "1234567890123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /*127*/ { BARCODE_EANX_CHK, "12345678901234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /*128*/ { BARCODE_EANX_CHK, "123456789012345678", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, + /*129*/ { BARCODE_EANX_CHK, "1234567890123456789", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; + char errtxt_escaped[256]; + testStart("test_eanx_input"); for (i = 0; i < data_size; i++) { @@ -422,7 +426,16 @@ static void test_eanx_input(int index, int debug) { length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); - assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + printf(" /*%3d*/ { %s, \"%s\", %s, \"%s\", \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), data[i].data, testUtilErrorName(data[i].ret), + testUtilEscape(symbol->errtxt, (int) strlen(symbol->errtxt), errtxt_escaped, sizeof(errtxt_escaped)), + data[i].comment); + } else { + assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + assert_zero(strcmp(symbol->errtxt, data[i].ret_errtxt), "i:%d errtxt %s != %s\n", i, symbol->errtxt, data[i].ret_errtxt); + } ZBarcode_Delete(symbol); } @@ -430,125 +443,129 @@ static void test_eanx_input(int index, int debug) { testFinish(); } -static void test_isbn_input(int index, int debug) { +static void test_isbn_input(int index, int generate, int debug) { struct item { char *data; int ret_encode; int ret_vector; + char *ret_errtxt; + char *comment; }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { "0", 0, 0 }, // Left zero-padded if < 10 chars - /* 1*/ { "1", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 2*/ { "X", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 3*/ { "12", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 4*/ { "19", 0, 0, }, - /* 5*/ { "X9", ZINT_ERROR_INVALID_DATA, -1 }, - /* 6*/ { "123", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 7*/ { "124", 0, 0, }, - /* 8*/ { "1X4", ZINT_ERROR_INVALID_DATA, -1 }, - /* 9*/ { "1234", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 10*/ { "1236", 0, 0, }, - /* 11*/ { "12X6", ZINT_ERROR_INVALID_DATA, -1 }, - /* 12*/ { "12345", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 13*/ { "12343", 0, 0, }, - /* 14*/ { "123X3", ZINT_ERROR_INVALID_DATA, -1 }, - /* 15*/ { "123456", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 16*/ { "123455", 0, 0, }, - /* 17*/ { "1234X5", ZINT_ERROR_INVALID_DATA, -1 }, - /* 18*/ { "1234567", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 19*/ { "1234560", 0, 0, }, - /* 20*/ { "12345X0", ZINT_ERROR_INVALID_DATA, -1 }, - /* 21*/ { "12345678", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 22*/ { "12345679", 0, 0 }, // 9 is correct check digit - /* 23*/ { "98765434", 0, 0 }, // 4 is correct check digit - /* 24*/ { "123456X9", ZINT_ERROR_INVALID_DATA, -1 }, - /* 25*/ { "123456789", 0, 0 }, - /* 26*/ { "340013817", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 27*/ { "340013818", 0, 0 }, // 8 is correct check digit - /* 28*/ { "902888455", 0, 0 }, // 5 is correct check digit - /* 29*/ { "9028884X5", ZINT_ERROR_INVALID_DATA, -1 }, - /* 30*/ { "0123456789", 0, 0 }, - /* 31*/ { "1234567890", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 32*/ { "123456789X", 0, 0 }, // X is correct check digit - /* 33*/ { "123456789x", 0, 0 }, // x is correct check digit - /* 34*/ { "8175257660", 0, 0 }, // 0 is correct check digit - /* 35*/ { "0590764845", 0, 0 }, // 5 is correct check digit - /* 36*/ { "0906495741", 0, 0 }, // 1 is correct check digit - /* 37*/ { "0140430016", 0, 0 }, // 6 is correct check digit - /* 38*/ { "0571086187", 0, 0 }, // 7 is correct check digit - /* 39*/ { "0486600882", 0, 0 }, // 2 is correct check digit - /* 40*/ { "04866008X2", ZINT_ERROR_INVALID_DATA, -1 }, - /* 41*/ { "123456789A", ZINT_ERROR_INVALID_DATA, -1 }, - /* 42*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1 }, - /* 43*/ { "1234567890A", ZINT_ERROR_INVALID_DATA, -1 }, - /* 44*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1 }, - /* 45*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1 }, - /* 46*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1 }, - /* 47*/ { "1234567890123", ZINT_ERROR_INVALID_DATA, -1 }, - /* 48*/ { "9784567890123", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 49*/ { "9784567890120", 0, 0 }, // 0 is correct check digit - /* 50*/ { "9783161484100", 0, 0 }, // 0 is correct check digit - /* 51*/ { "9781846688225", 0, 0 }, // 5 is correct check digit - /* 52*/ { "9781847657954", 0, 0 }, // 4 is correct check digit - /* 53*/ { "9781846688188", 0, 0 }, // 8 is correct check digit - /* 54*/ { "9781847659293", 0, 0 }, // 3 is correct check digit - /* 55*/ { "97845678901201", ZINT_ERROR_TOO_LONG, -1 }, - /* 56*/ { "978456789012012", ZINT_ERROR_TOO_LONG, -1 }, - /* 57*/ { "3954994+12", 0, 0 }, - /* 58*/ { "3954994+1X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 59*/ { "39549X4+12", ZINT_ERROR_INVALID_DATA, -1 }, - /* 60*/ { "3954994+12345", 0, 0 }, - /* 61*/ { "3954994+1234X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 62*/ { "39549X4+12345", ZINT_ERROR_INVALID_DATA, -1 }, - /* 63*/ { "3954994+123456", ZINT_ERROR_TOO_LONG, -1 }, - /* 64*/ { "3954994+", 0, 0 }, - /* 65*/ { "3954X94+", ZINT_ERROR_INVALID_DATA, -1 }, - /* 66*/ { "61954993+1", 0, 0 }, - /* 67*/ { "61954993+X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 68*/ { "619549X3+1", ZINT_ERROR_INVALID_DATA, -1 }, - /* 69*/ { "61954992+123", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 70*/ { "61954993+123", 0, 0 }, - /* 71*/ { "61954993+12X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 72*/ { "619549X3+123", ZINT_ERROR_INVALID_DATA, -1 }, - /* 73*/ { "361954990+12", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 74*/ { "361954999+12", 0, 0 }, - /* 75*/ { "361954999+1X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 76*/ { "3619549X9+12", ZINT_ERROR_INVALID_DATA, -1 }, - /* 77*/ { "361954999+1234", 0, 0 }, - /* 78*/ { "361954999+123X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 79*/ { "3619549X9+1234", ZINT_ERROR_INVALID_DATA, -1 }, - /* 80*/ { "1999000030+12", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 81*/ { "199900003X+12", 0, 0 }, - /* 82*/ { "199900003x+12", 0, 0 }, - /* 83*/ { "19990000XX+12", ZINT_ERROR_INVALID_DATA, -1 }, - /* 84*/ { "199900003X+1X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 85*/ { "1999000031+12345", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 86*/ { "199900003X+12345", 0, 0 }, - /* 87*/ { "199900003x+12345", 0, 0 }, - /* 88*/ { "199900003X+1234X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 89*/ { "19990000XX+12345", ZINT_ERROR_INVALID_DATA, -1 }, - /* 90*/ { "199900003X+1234A", ZINT_ERROR_INVALID_DATA, -1 }, - /* 91*/ { "9791234567895+12", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 92*/ { "9791234567896+12", 0, 0 }, - /* 93*/ { "9791234567896+1X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 94*/ { "97912345678X6+12", ZINT_ERROR_INVALID_DATA, -1 }, - /* 95*/ { "9791234567897+12345", ZINT_ERROR_INVALID_CHECK, -1 }, - /* 96*/ { "9791234567896+12345", 0, 0 }, - /* 97*/ { "9791234567896+1234X", ZINT_ERROR_INVALID_DATA, -1 }, - /* 98*/ { "979123456X896+12345", ZINT_ERROR_INVALID_DATA, -1 }, - /* 99*/ { "9791234567892+", ZINT_ERROR_INVALID_CHECK, -1 }, - /*100*/ { "9791234567896+", 0, 0 }, - /*101*/ { "97912345678X6+", ZINT_ERROR_INVALID_DATA, -1 }, - /*102*/ { "97912345678961+", ZINT_ERROR_TOO_LONG, -1 }, - /*103*/ { "97912345678961+12345", ZINT_ERROR_TOO_LONG, -1 }, - /*104*/ { "9791234567896+123456", ZINT_ERROR_TOO_LONG, -1 }, + /* 0*/ { "0", 0, 0, "", "Left zero-padded if < 10 chars" }, + /* 1*/ { "1", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '1', expecting '0'", "" }, + /* 2*/ { "X", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit 'X', expecting '0'", "" }, + /* 3*/ { "12", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '2', expecting '9'", "" }, + /* 4*/ { "19", 0, 0, "", "" }, + /* 5*/ { "X9", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 6*/ { "123", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '3', expecting '4'", "" }, + /* 7*/ { "124", 0, 0, "", "" }, + /* 8*/ { "1X4", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 9*/ { "1234", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '4', expecting '6'", "" }, + /* 10*/ { "1236", 0, 0, "", "" }, + /* 11*/ { "12X6", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 12*/ { "12345", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '5', expecting '3'", "" }, + /* 13*/ { "12343", 0, 0, "", "" }, + /* 14*/ { "123X3", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 15*/ { "123456", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '6', expecting '5'", "" }, + /* 16*/ { "123455", 0, 0, "", "" }, + /* 17*/ { "1234X5", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 18*/ { "1234567", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '7', expecting '0'", "" }, + /* 19*/ { "1234560", 0, 0, "", "" }, + /* 20*/ { "12345X0", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 21*/ { "12345678", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '8', expecting '9'", "" }, + /* 22*/ { "12345679", 0, 0, "", "9 is correct check digit" }, + /* 23*/ { "98765434", 0, 0, "", "4 is correct check digit" }, + /* 24*/ { "123456X9", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 25*/ { "123456789", 0, 0, "", "" }, + /* 26*/ { "340013817", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '7', expecting '8'", "" }, + /* 27*/ { "340013818", 0, 0, "", "8 is correct check digit" }, + /* 28*/ { "902888455", 0, 0, "", "5 is correct check digit" }, + /* 29*/ { "9028884X5", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 30*/ { "0123456789", 0, 0, "", "" }, + /* 31*/ { "1234567890", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid ISBN check digit '0', expecting 'X'", "" }, + /* 32*/ { "123456789X", 0, 0, "", "X is correct check digit" }, + /* 33*/ { "123456789x", 0, 0, "", "x is correct check digit" }, + /* 34*/ { "8175257660", 0, 0, "", "0 is correct check digit" }, + /* 35*/ { "0590764845", 0, 0, "", "5 is correct check digit" }, + /* 36*/ { "0906495741", 0, 0, "", "1 is correct check digit" }, + /* 37*/ { "0140430016", 0, 0, "", "6 is correct check digit" }, + /* 38*/ { "0571086187", 0, 0, "", "7 is correct check digit" }, + /* 39*/ { "0486600882", 0, 0, "", "2 is correct check digit" }, + /* 40*/ { "04866008X2", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 41*/ { "123456789A", ZINT_ERROR_INVALID_DATA, -1, "Error 285: Invalid character in data (digits, \"X\" and \"+\" only)", "" }, + /* 42*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" }, + /* 43*/ { "1234567890A", ZINT_ERROR_INVALID_DATA, -1, "Error 285: Invalid character in data (digits, \"X\" and \"+\" only)", "" }, + /* 44*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" }, + /* 45*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" }, + /* 46*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" }, + /* 47*/ { "1234567890123", ZINT_ERROR_INVALID_DATA, -1, "Error 279: Invalid ISBN (must begin with \"978\" or \"979\")", "" }, + /* 48*/ { "9784567890123", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '3', expecting '0'", "" }, + /* 49*/ { "9784567890120", 0, 0, "", "0 is correct check digit" }, + /* 50*/ { "9783161484100", 0, 0, "", "0 is correct check digit" }, + /* 51*/ { "9781846688225", 0, 0, "", "5 is correct check digit" }, + /* 52*/ { "9781847657954", 0, 0, "", "4 is correct check digit" }, + /* 53*/ { "9781846688188", 0, 0, "", "8 is correct check digit" }, + /* 54*/ { "9781847659293", 0, 0, "", "3 is correct check digit" }, + /* 55*/ { "97845678901201", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (13 character maximum)", "" }, + /* 56*/ { "978456789012012", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (13 character maximum)", "" }, + /* 57*/ { "3954994+12", 0, 0, "", "" }, + /* 58*/ { "3954994+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 59*/ { "39549X4+12", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 60*/ { "3954994+12345", 0, 0, "", "" }, + /* 61*/ { "3954994+1234X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 62*/ { "39549X4+12345", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 63*/ { "3954994+123456", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (5 character maximum for add-on)", "" }, + /* 64*/ { "3954994+", 0, 0, "", "" }, + /* 65*/ { "3954X94+", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 66*/ { "61954993+1", 0, 0, "", "" }, + /* 67*/ { "61954993+X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 68*/ { "619549X3+1", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 69*/ { "61954992+123", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '2', expecting '3'", "" }, + /* 70*/ { "61954993+123", 0, 0, "", "" }, + /* 71*/ { "61954993+12X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 72*/ { "619549X3+123", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 73*/ { "361954990+12", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '0', expecting '9'", "" }, + /* 74*/ { "361954999+12", 0, 0, "", "" }, + /* 75*/ { "361954999+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 76*/ { "3619549X9+12", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 77*/ { "361954999+1234", 0, 0, "", "" }, + /* 78*/ { "361954999+123X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 79*/ { "3619549X9+1234", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 80*/ { "1999000030+12", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid ISBN check digit '0', expecting 'X'", "" }, + /* 81*/ { "199900003X+12", 0, 0, "", "" }, + /* 82*/ { "199900003x+12", 0, 0, "", "" }, + /* 83*/ { "19990000XX+12", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 84*/ { "199900003X+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 85*/ { "1999000031+12345", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid ISBN check digit '1', expecting 'X'", "" }, + /* 86*/ { "199900003X+12345", 0, 0, "", "" }, + /* 87*/ { "199900003x+12345", 0, 0, "", "" }, + /* 88*/ { "199900003X+1234X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 89*/ { "19990000XX+12345", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" }, + /* 90*/ { "199900003X+1234A", ZINT_ERROR_INVALID_DATA, -1, "Error 285: Invalid character in data (digits, \"X\" and \"+\" only)", "" }, + /* 91*/ { "9791234567895+12", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '5', expecting '6'", "" }, + /* 92*/ { "9791234567896+12", 0, 0, "", "" }, + /* 93*/ { "9791234567896+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 94*/ { "97912345678X6+12", ZINT_ERROR_INVALID_DATA, -1, "Error 282: Invalid character in data, \"X\" not allowed in ISBN-13", "" }, + /* 95*/ { "9791234567897+12345", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '7', expecting '6'", "" }, + /* 96*/ { "9791234567896+12345", 0, 0, "", "" }, + /* 97*/ { "9791234567896+1234X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" }, + /* 98*/ { "979123456X896+12345", ZINT_ERROR_INVALID_DATA, -1, "Error 282: Invalid character in data, \"X\" not allowed in ISBN-13", "" }, + /* 99*/ { "9791234567892+", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '2', expecting '6'", "" }, + /*100*/ { "9791234567896+", 0, 0, "", "" }, + /*101*/ { "97912345678X6+", ZINT_ERROR_INVALID_DATA, -1, "Error 282: Invalid character in data, \"X\" not allowed in ISBN-13", "" }, + /*102*/ { "97912345678961+", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (13 character maximum)", "" }, + /*103*/ { "97912345678961+12345", ZINT_ERROR_TOO_LONG, -1, "Error 283: Input too long (19 character maximum)", "" }, + /*104*/ { "9791234567896+123456", ZINT_ERROR_TOO_LONG, -1, "Error 283: Input too long (19 character maximum)", "" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; + char errtxt_escaped[256]; + testStart("test_isbn_input"); for (i = 0; i < data_size; i++) { @@ -562,11 +579,20 @@ static void test_isbn_input(int index, int debug) { length = testUtilSetSymbol(symbol, BARCODE_ISBNX, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); - assert_equal(ret, data[i].ret_encode, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret_encode, symbol->errtxt); - if (data[i].ret_vector != -1) { - ret = ZBarcode_Buffer_Vector(symbol, 0); - assert_equal(ret, data[i].ret_vector, "i:%d ZBarcode_Buffer_Vector ret %d != %d (%s)\n", i, ret, data[i].ret_vector, symbol->errtxt); + if (generate) { + printf(" /*%3d*/ { \"%s\", %s, %d, \"%s\", \"%s\" },\n", + i, data[i].data, testUtilErrorName(data[i].ret_encode), data[i].ret_vector, + testUtilEscape(symbol->errtxt, (int) strlen(symbol->errtxt), errtxt_escaped, sizeof(errtxt_escaped)), + data[i].comment); + } else { + assert_equal(ret, data[i].ret_encode, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret_encode, symbol->errtxt); + assert_zero(strcmp(symbol->errtxt, data[i].ret_errtxt), "i:%d errtxt %s != %s\n", i, symbol->errtxt, data[i].ret_errtxt); + + if (data[i].ret_vector != -1) { + ret = ZBarcode_Buffer_Vector(symbol, 0); + assert_equal(ret, data[i].ret_vector, "i:%d ZBarcode_Buffer_Vector ret %d != %d (%s)\n", i, ret, data[i].ret_vector, symbol->errtxt); + } } ZBarcode_Delete(symbol); @@ -955,18 +981,127 @@ static void test_fuzz(int index, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITER_MILLES 10 +#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000) +#define TEST_PERF_TIME(arg) (((arg) * 1000.0) / CLOCKS_PER_SEC) + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + struct item { + int symbology; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_EANX, -1, "123456789012+12345", 0, 1, 149, "EAN-13 add-on 5" }, + /* 1*/ { BARCODE_EANX, -1, "123456789012", 0, 1, 95, "EAN-13 no add-on" }, + /* 2*/ { BARCODE_UPCA, -1, "12345678901+12345", 0, 1, 151, "UPC-A add-on 5" }, + /* 3*/ { BARCODE_UPCA, -1, "12345678901", 0, 1, 95, "UPC-A no add-on" }, + /* 4*/ { BARCODE_EANX, -1, "1234567+12345", 0, 1, 121, "EAN-8 add-on 5" }, + /* 5*/ { BARCODE_EANX, -1, "1234567", 0, 1, 67, "EAN-8 no add-on" }, + /* 6*/ { BARCODE_UPCE, -1, "1234567+12", 0, 1, 78, "UPC-E add-on 2" }, + /* 7*/ { BARCODE_UPCE, -1, "1234567", 0, 1, 51, "UPC-E no add-on" }, + /* 8*/ { BARCODE_EANX, -1, "12345", 0, 1, 47, "EAN-5" }, + /* 9*/ { BARCODE_EANX, -1, "12", 0, 1, 20, "EAN-2" }, + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + struct zint_symbol *symbol; + + clock_t start; + clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0; + clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print; + int comment_max = 0; + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment); + + printf("Iterations %d\n", TEST_PERF_ITERATIONS); + + for (i = 0; i < data_size; i++) { + int j; + + if (index != -1 && i != index) continue; + + diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0; + + for (j = 0; j < TEST_PERF_ITERATIONS; j++) { + start = clock(); + symbol = ZBarcode_Create(); + diff_create += clock() - start; + assert_nonnull(symbol, "Symbol not created\n"); + + length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); + + start = clock(); + ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + diff_encode += clock() - start; + 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->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); + + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buffer += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + symbol->output_options |= OUT_BUFFER_INTERMEDIATE; + start = clock(); + ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/); + diff_buf_inter += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo + + start = clock(); + ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/); + diff_print += clock() - start; + assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + ZBarcode_Delete(symbol); + } + + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment, + TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create)); + + total_create += diff_create; + total_encode += diff_encode; + total_buffer += diff_buffer; + total_buf_inter += diff_buf_inter; + total_print += diff_print; + } + if (index == -1) { + printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals", + TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create)); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_upce_input", test_upce_input, 1, 0, 1 }, { "test_upca_print", test_upca_print, 1, 0, 1 }, { "test_upca_input", test_upca_input, 1, 0, 1 }, - { "test_eanx_input", test_eanx_input, 1, 0, 1 }, - { "test_isbn_input", test_isbn_input, 1, 0, 1 }, + { "test_eanx_input", test_eanx_input, 1, 1, 1 }, + { "test_isbn_input", test_isbn_input, 1, 1, 1 }, { "test_hrt", test_hrt, 1, 0, 1 }, { "test_vector_same", test_vector_same, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index a53d0d44..6b630db7 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -84,13 +84,13 @@ void assert_nonzero(int exp, const char *fmt, ...) { va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish(); } } -void assert_null(void *exp, const char *fmt, ...) { +void assert_null(const void *exp, const char *fmt, ...) { assertionNum++; if (exp != NULL) { va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish(); } } -void assert_nonnull(void *exp, const char *fmt, ...) { +void assert_nonnull(const void *exp, const char *fmt, ...) { assertionNum++; if (exp == NULL) { va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish(); @@ -683,7 +683,7 @@ const char *testUtilOutputOptionsName(int output_options) { } /* Convert modules spanning 3 rows to DAFT equivalents */ -int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size) { +int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, const int buffer_size) { int i; char *b = buffer; *b = '\0'; @@ -720,7 +720,7 @@ int testUtilIsValidUTF8(const unsigned char str[], const int length) { } /* Escape data for printing on generate test. Has a number of issues, e.g. need to use octal escapes */ -char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size) { +char *testUtilEscape(const char *buffer, const int length, char *escaped, const int escaped_size) { int i; unsigned char *b = (unsigned char *) buffer; unsigned char *be = b + length; @@ -767,9 +767,9 @@ char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size) } /* Helper to read a CSV field */ -char *testUtilReadCSVField(char *buffer, char *field, int field_size) { +const char *testUtilReadCSVField(const char *buffer, char *field, const int field_size) { int i; - char *b = buffer; + const char *b = buffer; for (i = 0; i < field_size && *b && *b != ',' && *b != '\n' && *b != '\r'; i++) { field[i] = *b++; } @@ -781,7 +781,7 @@ char *testUtilReadCSVField(char *buffer, char *field, int field_size) { } /* Helper to fill a buffer (for "large" tests) - single-byte filler only */ -void testUtilStrCpyRepeat(char *buffer, char *repeat, int size) { +void testUtilStrCpyRepeat(char *buffer, const char *repeat, const int size) { int i; int len = (int) strlen(repeat); int max = size - len; @@ -2046,7 +2046,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol { "identcode", BARCODE_DPIDENT, 22, 0, 0, 0, 0, 0, }, { "code16k", BARCODE_CODE16K, 23, 0, 0, 0, 8 /*linear_row_height*/, 0, }, { "code49", BARCODE_CODE49, 24, 0, 0, 0, 8 /*linear_row_height*/, 0, }, - { "code93", BARCODE_CODE93, 25, 0, 0, 0, 0, 0, }, + { "code93ext", BARCODE_CODE93, 25, 0, 0, 0, 0, 0, }, { "", -1, 26, 0, 0, 0, 0, 0, }, { "", -1, 27, 0, 0, 0, 0, 0, }, { "flattermarken", BARCODE_FLAT, 28, 0, 0, 0, 0, 0, }, @@ -2598,9 +2598,6 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int } else if (symbology == BARCODE_CODE93) { sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%sincludecheck", strlen(bwipp_opts_buf) ? " " : ""); - if (parse) { - bwipp_barcode = "code93ext"; - } bwipp_opts = bwipp_opts_buf; } else if (symbology == BARCODE_PZN) { sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%spzn8", strlen(bwipp_opts_buf) ? " " : ""); @@ -2681,7 +2678,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int || symbology == BARCODE_PHARMA_TWO) { for (r = 0; r < symbol->rows; r++) bwipp_row_height[r] = 1; /* Zap */ if (symbology == BARCODE_KIX) { - to_upper((unsigned char *) bwipp_data); + to_upper((unsigned char *) bwipp_data, (int) strlen(bwipp_data)); } else if (symbology == BARCODE_USPS_IMAIL) { char *dash = strchr(bwipp_data, '-'); if (dash) { diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index 5ea4ac0a..41be147d 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -96,8 +96,8 @@ void testRun(int argc, char *argv[], testFunction funcs[], int funcs_size); #include "../ms_stdint.h" void assert_zero(int exp, const char *fmt, ...); void assert_nonzero(int exp, const char *fmt, ...); -void assert_null(void *exp, const char *fmt, ...); -void assert_nonnull(void *exp, const char *fmt, ...); +void assert_null(const void *exp, const char *fmt, ...); +void assert_nonnull(const void *exp, const char *fmt, ...); void assert_equal(int e1, int e2, const char *fmt, ...); void assert_equalu64(uint64_t e1, uint64_t e2, const char *fmt, ...); void assert_notequal(int e1, int e2, ...); @@ -126,11 +126,11 @@ const char *testUtilInputModeName(int input_mode); const char *testUtilOption3Name(int option_3); const char *testUtilOutputOptionsName(int output_options); -int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size); +int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, const int buffer_size); int testUtilIsValidUTF8(const unsigned char str[], const int length); -char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size); -char *testUtilReadCSVField(char *buffer, char *field, int field_size); -void testUtilStrCpyRepeat(char *buffer, char *repeat, int size); +char *testUtilEscape(const char *buffer, const int length, char *escaped, const int escaped_size); +const char *testUtilReadCSVField(const char *buffer, char *field, const int field_size); +void testUtilStrCpyRepeat(char *buffer, const char *repeat, const int size); int testUtilSymbolCmp(const struct zint_symbol *a, const struct zint_symbol *b); struct zint_vector *testUtilVectorCpy(const struct zint_vector *in); diff --git a/backend/tests/tools/bwipp_dump.ps.tar.xz b/backend/tests/tools/bwipp_dump.ps.tar.xz index f2bec6ef..fe3f8d27 100644 Binary files a/backend/tests/tools/bwipp_dump.ps.tar.xz and b/backend/tests/tools/bwipp_dump.ps.tar.xz differ diff --git a/backend/ultra.c b/backend/ultra.c index 77dca6aa..4fbc23c9 100644 --- a/backend/ultra.c +++ b/backend/ultra.c @@ -46,7 +46,7 @@ #define GFMUL(i, j) ((((i) == 0)||((j) == 0)) ? 0 : gfPwr[(gfLog[i] + gfLog[j])]) -static const char fragment[27][14] = {"http://", "https://", "http://www.", "https://www.", +static const char fragment[27][13] = {"http://", "https://", "http://www.", "https://www.", "ftp://", "www.", ".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".mobi", ".coop", ".biz", ".info", "mailto:", "tel:", ".cgi", ".asp", ".aspx", ".php", ".htm", ".html", ".shtml", "file:"}; @@ -273,7 +273,7 @@ static float look_ahead_eightbit(unsigned char source[], int in_length, int in_l *cw_len = codeword_count; if (codeword_count == 0) { - return 0.0; + return 0.0f; } return (float) letters_encoded / (float) codeword_count; } @@ -362,7 +362,7 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn *cw_len = codeword_count; if (codeword_count == 0) { - return 0.0; + return 0.0f; } return (float) letters_encoded / (float) codeword_count; } @@ -372,8 +372,8 @@ static int c43_should_latch_other(const unsigned char data[], const int length, const int gs1) { int i, fraglen, predict_window; int cnt, alt_cnt, fragno; - const char *set = subset == 1 ? ultra_c43_set1 : ultra_c43_set2; - const char *alt_set = subset == 2 ? ultra_c43_set1 : ultra_c43_set2; + const char *const set = subset == 1 ? ultra_c43_set1 : ultra_c43_set2; + const char *const alt_set = subset == 2 ? ultra_c43_set1 : ultra_c43_set2; if (locn + 3 > length) { return 0; @@ -394,10 +394,10 @@ static int c43_should_latch_other(const unsigned char data[], const int length, } i += fraglen - 1; } else { - if (strchr(set, data[i]) != NULL) { + if (posn(set, data[i]) != -1) { cnt++; } - if (strchr(alt_set, data[i]) != NULL) { + if (posn(alt_set, data[i]) != -1) { alt_cnt++; } } @@ -612,7 +612,7 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, *cw_len = codeword_count; if (codeword_count == 0) { - return 0.0; + return 0.0f; } return (float) letters_encoded / (float) codeword_count; } diff --git a/backend/upcean.c b/backend/upcean.c index cbc6d410..3fbe2e90 100644 --- a/backend/upcean.c +++ b/backend/upcean.c @@ -30,12 +30,9 @@ */ /* vim: set ts=4 sw=4 et : */ -#define SODIUM "0123456789+" -#define ISBNX_SANE "0123456789X" -#define ISBNX_ADDON_SANE "0123456789Xx+" - -#define EAN2 102 -#define EAN5 105 +#define SODIUM_PLS_F (IS_NUM_F | IS_PLS_F) /* SODIUM "0123456789+" */ +#define ISBNX_SANE_F (IS_NUM_F | IS_UX__F) /* ISBNX_SANE "0123456789X" */ +#define ISBNX_ADDON_SANE_F (IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F) /* ISBNX_ADDON_SANE "0123456789Xx+" */ #include #include "common.h" @@ -43,66 +40,72 @@ /* UPC and EAN tables checked against EN 797:1996 */ -static const char *UPCParity0[10] = { +static const char UPCParity0[10][6] = { /* Number set for UPC-E symbol (EN Table 4) */ - "BBBAAA", "BBABAA", "BBAABA", "BBAAAB", "BABBAA", "BAABBA", "BAAABB", - "BABABA", "BABAAB", "BAABAB" + {'B','B','B','A','A','A'}, {'B','B','A','B','A','A'}, {'B','B','A','A','B','A'}, {'B','B','A','A','A','B'}, + {'B','A','B','B','A','A'}, {'B','A','A','B','B','A'}, {'B','A','A','A','B','B'}, {'B','A','B','A','B','A'}, + {'B','A','B','A','A','B'}, {'B','A','A','B','A','B'} }; -static const char *UPCParity1[10] = { +static const char UPCParity1[10][6] = { /* Not covered by BS EN 797:1995 */ - "AAABBB", "AABABB", "AABBAB", "AABBBA", "ABAABB", "ABBAAB", "ABBBAA", - "ABABAB", "ABABBA", "ABBABA" + {'A','A','A','B','B','B'}, {'A','A','B','A','B','B'}, {'A','A','B','B','A','B'}, {'A','A','B','B','B','A'}, + {'A','B','A','A','B','B'}, {'A','B','B','A','A','B'}, {'A','B','B','B','A','A'}, {'A','B','A','B','A','B'}, + {'A','B','A','B','B','A'}, {'A','B','B','A','B','A'} }; -static const char *EAN2Parity[4] = { +static const char EAN2Parity[4][2] = { /* Number sets for 2-digit add-on (EN Table 6) */ - "AA", "AB", "BA", "BB" + {'A','A'}, {'A','B'}, {'B','A'}, {'B','B'} }; -static const char *EAN5Parity[10] = { +static const char EAN5Parity[10][5] = { /* Number set for 5-digit add-on (EN Table 7) */ - "BBAAA", "BABAA", "BAABA", "BAAAB", "ABBAA", "AABBA", "AAABB", "ABABA", - "ABAAB", "AABAB" + {'B','B','A','A','A'}, {'B','A','B','A','A'}, {'B','A','A','B','A'}, {'B','A','A','A','B'}, {'A','B','B','A','A'}, + {'A','A','B','B','A'}, {'A','A','A','B','B'}, {'A','B','A','B','A'}, {'A','B','A','A','B'}, {'A','A','B','A','B'} }; -static const char *EAN13Parity[10] = { +static const char EAN13Parity[10][5] = { /* Left hand of the EAN-13 symbol (EN Table 3) */ - "AAAAA", "ABABB", "ABBAB", "ABBBA", "BAABB", "BBAAB", "BBBAA", "BABAB", - "BABBA", "BBABA" + {'A','A','A','A','A'}, {'A','B','A','B','B'}, {'A','B','B','A','B'}, {'A','B','B','B','A'}, {'B','A','A','B','B'}, + {'B','B','A','A','B'}, {'B','B','B','A','A'}, {'B','A','B','A','B'}, {'B','A','B','B','A'}, {'B','B','A','B','A'} }; -static const char *EANsetA[10] = { +static const char EANsetA[10][4] = { /* Representation set A and C (EN Table 1) */ - "3211", "2221", "2122", "1411", "1132", "1231", "1114", "1312", "1213", "3112" + {'3','2','1','1'}, {'2','2','2','1'}, {'2','1','2','2'}, {'1','4','1','1'}, {'1','1','3','2'}, + {'1','2','3','1'}, {'1','1','1','4'}, {'1','3','1','2'}, {'1','2','1','3'}, {'3','1','1','2'} }; -static const char *EANsetB[10] = { +static const char EANsetB[10][4] = { /* Representation set B (EN Table 1) */ - "1123", "1222", "2212", "1141", "2311", "1321", "4111", "2131", "3121", "2113" + {'1','1','2','3'}, {'1','2','2','2'}, {'2','2','1','2'}, {'1','1','4','1'}, {'2','3','1','1'}, + {'1','3','2','1'}, {'4','1','1','1'}, {'2','1','3','1'}, {'3','1','2','1'}, {'2','1','1','3'} }; /* 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 dest[]) { +static void upca_draw(const unsigned char source[], const int length, char *d) { int i, half_way; half_way = length / 2; /* start character */ - strcat(dest, "111"); + memcpy(d, "111", 3); + d += 3; - for (i = 0; i < length; i++) { + 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 */ - strcat(dest, "11111"); + memcpy(d, "11111", 5); + d += 5; } - lookup(NEON, EANsetA, source[i], dest); + memcpy(d, EANsetA[source[i] - '0'], 4); } /* stop character */ - strcat(dest, "111"); + strcpy(d, "111"); } /* Make a UPC-A barcode, allowing for composite if `cc_rows` set */ @@ -156,9 +159,10 @@ static int upca(struct zint_symbol *symbol, const unsigned char source[], int le } /* UPC-E, allowing for composite if `cc_rows` set */ -static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int length, char dest[], int cc_rows) { +static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int length, char *d, int cc_rows) { int i, num_system; - char emode, check_digit, parity[8]; + char emode, check_digit; + const char *parity; char src_check_digit = '\0'; unsigned char equivalent[12]; unsigned char *hrt = symbol->text; @@ -266,27 +270,28 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt /* Use the number system and check digit information to choose a parity scheme */ if (num_system == 1) { - strcpy(parity, UPCParity1[ctoi(check_digit)]); + parity = UPCParity1[ctoi(check_digit)]; } else { - strcpy(parity, UPCParity0[ctoi(check_digit)]); + parity = UPCParity0[ctoi(check_digit)]; } /* Take all this information and make the barcode pattern */ /* start character */ - strcat(dest, "111"); + memcpy(d, "111", 3); + d += 3; - for (i = 0; i < length; i++) { + for (i = 0; i < length; i++, d += 4) { switch (parity[i]) { - case 'A': lookup(NEON, EANsetA, source[i], dest); + case 'A': memcpy(d, EANsetA[source[i] - '0'], 4); break; - case 'B': lookup(NEON, EANsetB, source[i], dest); + case 'B': memcpy(d, EANsetB[source[i] - '0'], 4); break; } } /* stop character */ - strcat(dest, "111111"); + strcpy(d, "111111"); hrt[7] = check_digit; hrt[8] = '\0'; @@ -323,36 +328,27 @@ static int upce(struct zint_symbol *symbol, unsigned char source[], int length, /* EAN-2 and EAN-5 add-on codes */ static void ean_add_on(const unsigned char source[], const int length, char dest[], const int addon_gap) { - char parity[6]; - int i, code_type; + const char *parity; + int i; + char *d = dest + strlen(dest); /* If an add-on then append with space */ if (addon_gap != 0) { - i = (int) strlen(dest); - dest[i] = itoc(addon_gap); - dest[i + 1] = '\0'; + *d++ = itoc(addon_gap); } /* Start character */ - strcat(dest, "112"); + memcpy(d, "112", 3); + d += 3; - /* Determine EAN2 or EAN5 add-on */ - if (length == 2) { - code_type = EAN2; - } else { - code_type = EAN5; - } - - /* Calculate parity for EAN2 */ - if (code_type == EAN2) { + /* Calculate parity */ + if (length == 2) { /* EAN-2 */ int code_value, parity_bit; code_value = (10 * ctoi(source[0])) + ctoi(source[1]); parity_bit = code_value % 4; - strcpy(parity, EAN2Parity[parity_bit]); - } - - if (code_type == EAN5) { + parity = EAN2Parity[parity_bit]; + } else { /* EAN-5 */ int values[6], parity_sum, parity_bit; for (i = 0; i < 6; i++) { @@ -363,34 +359,37 @@ static void ean_add_on(const unsigned char source[], const int length, char dest parity_sum += (9 * (values[1] + values[3])); parity_bit = parity_sum % 10; - strcpy(parity, EAN5Parity[parity_bit]); + parity = EAN5Parity[parity_bit]; } for (i = 0; i < length; i++) { switch (parity[i]) { - case 'A': lookup(NEON, EANsetA, source[i], dest); + case 'A': memcpy(d, EANsetA[source[i] - '0'], 4); + d += 4; break; - case 'B': lookup(NEON, EANsetB, source[i], dest); + case 'B': memcpy(d, EANsetB[source[i] - '0'], 4); + d += 4; break; } /* Glyph separator */ if (i != (length - 1)) { - strcat(dest, "11"); + memcpy(d, "11", 2); + d += 2; } } + *d = '\0'; } /* ************************ EAN-13 ****************** */ -static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[], +static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char *d, int cc_rows) { int i, half_way; - char parity[6]; + const char *parity; unsigned char *gtin = symbol->text; int error_number = 0; - parity[0] = '\0'; ustrcpy(gtin, source); /* Add the appropriate check digit */ @@ -410,29 +409,32 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in } /* Get parity for first half of the symbol */ - lookup(SODIUM, EAN13Parity, gtin[0], parity); + parity = EAN13Parity[gtin[0] - '0']; /* Now get on with the cipher */ half_way = 7; /* start character */ - strcat(dest, "111"); - for (i = 1; i < length; i++) { + memcpy(d, "111", 3); + d += 3; + + for (i = 1; i < length; i++, d += 4) { if (i == half_way) { /* middle character - separates manufacturer no. from product no. */ /* also inverses right hand characters */ - strcat(dest, "11111"); + memcpy(d, "11111", 5); + d += 5; } if (((i > 1) && (i < 7)) && (parity[i - 2] == 'B')) { - lookup(NEON, EANsetB, gtin[i], dest); + memcpy(d, EANsetB[gtin[i] - '0'], 4); } else { - lookup(NEON, EANsetA, gtin[i], dest); + memcpy(d, EANsetA[gtin[i] - '0'], 4); } } /* stop character */ - strcat(dest, "111"); + strcpy(d, "111"); if (symbol->output_options & COMPLIANT_HEIGHT) { /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24, @@ -535,8 +537,8 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s int i; char check_digit; - to_upper(source); - if (is_sane(ISBNX_SANE, source, src_len) != 0) { + to_upper(source, src_len); + if (!is_sane(ISBNX_SANE_F, source, src_len)) { strcpy(symbol->errtxt, "277: Invalid character in data (digits and \"X\" only)"); return ZINT_ERROR_INVALID_DATA; } @@ -554,16 +556,15 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s return ZINT_ERROR_INVALID_DATA; } - /* "X" can only occur in last position */ - if (is_sane(NEON, source, 12) != 0) { - strcpy(symbol->errtxt, "282: Invalid character in data, \"X\" allowed in last position only"); + /* "X" cannot occur */ + if (!is_sane(NEON_F, source, 13)) { + strcpy(symbol->errtxt, "282: Invalid character in data, \"X\" not allowed in ISBN-13"); return ZINT_ERROR_INVALID_DATA; } check_digit = gs1_check_digit(source, 12); - if (source[src_len - 1] != check_digit) { - sprintf(symbol->errtxt, "280: Invalid ISBN check digit '%c', expecting '%c'", - source[src_len - 1], check_digit); + if (source[12] != check_digit) { + sprintf(symbol->errtxt, "280: Invalid ISBN check digit '%c', expecting '%c'", source[12], check_digit); return ZINT_ERROR_INVALID_CHECK; } source[12] = '\0'; @@ -578,7 +579,7 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s } /* "X" can only occur in last position */ - if (is_sane(NEON, source, 9) != 0) { + if (!is_sane(NEON_F, source, 9)) { strcpy(symbol->errtxt, "296: Invalid character in data, \"X\" allowed in last position only"); return ZINT_ERROR_INVALID_DATA; } @@ -589,7 +590,7 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s source[9], check_digit); return ZINT_ERROR_INVALID_CHECK; } - for (i = 11; i > 2; i--) { + for (i = 11; i > 2; i--) { /* This drops the check digit */ source[i] = source[i - 3]; } source[0] = '9'; @@ -603,8 +604,9 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s /* Add leading zeroes to EAN and UPC strings */ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], - unsigned char local_source[], int *p_with_addon) { - unsigned char first_part[14], second_part[6], zfirst_part[14], zsecond_part[6]; + 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; @@ -641,14 +643,10 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char /* Calculate target lengths */ if (second_len == 0) { zsecond_len = 0; + } else if (second_len <= 2) { + zsecond_len = 2; } else { - if (second_len <= 5) { - if (second_len <= 2) { - zsecond_len = 2; - } else { - zsecond_len = 5; - } - } + zsecond_len = 5; } switch (symbol->symbology) { case BARCODE_EANX: @@ -717,25 +715,29 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char break; } + /* Copy adjusted data back to local_source */ /* Add leading zeroes */ - zfirst_part[0] = '\0'; for (i = 0; i < (zfirst_len - first_len); i++) { - ustrcat(zfirst_part, "0"); + local_source[i] = '0'; } - ustrcat(zfirst_part, first_part); - - zsecond_part[0] = '\0'; - for (i = 0; i < (zsecond_len - second_len); i++) { - ustrcat(zsecond_part, "0"); + ustrcpy(local_source + i, first_part); + if (zfirst_part) { + ustrcpy(zfirst_part, local_source); } - ustrcat(zsecond_part, second_part); - /* Copy adjusted data back to local_source */ - ustrcat(local_source, zfirst_part); - if (*zsecond_part) { - ustrcat(local_source, "+"); - ustrcat(local_source, zsecond_part); + if (with_addon) { + 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); + if (zsecond_part) { + ustrcpy(zsecond_part, local_source + h); + } + } else if (zsecond_part) { + *zsecond_part = '\0'; } if (p_with_addon) { @@ -746,30 +748,26 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char } INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src_len, int cc_rows) { - unsigned char first_part[14] = {0}, second_part[6] = {0}; - unsigned char local_source[20] = {0}; /* Allow 13 + "+" + 5 + 1 */ + unsigned char first_part[14], second_part[6]; + unsigned char local_source[20]; /* Allow 13 + "+" + 5 + 1 */ char dest[1000] = {0}; - int latch, reader, writer; int with_addon; int error_number = 0, i, plus_count; int addon_gap = 0; int first_part_len, second_part_len; - latch = FALSE; - writer = 0; - if (src_len > 19) { strcpy(symbol->errtxt, "283: Input too long (19 character maximum)"); return ZINT_ERROR_TOO_LONG; } if (symbol->symbology != BARCODE_ISBNX) { /* ISBN has its own sanity routine */ - if (is_sane(SODIUM, source, src_len) != 0) { + if (!is_sane(SODIUM_PLS_F, source, src_len)) { strcpy(symbol->errtxt, "284: Invalid character in data (digits and \"+\" only)"); return ZINT_ERROR_INVALID_DATA; } } else { - if (is_sane(ISBNX_ADDON_SANE, source, src_len) != 0) { + if (!is_sane(ISBNX_ADDON_SANE_F, source, src_len)) { strcpy(symbol->errtxt, "285: Invalid character in data (digits, \"X\" and \"+\" only)"); return ZINT_ERROR_INVALID_DATA; } @@ -789,42 +787,19 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src } /* Add leading zeroes, checking max lengths of parts */ - if (!ean_leading_zeroes(symbol, source, local_source, &with_addon)) { + if (!ean_leading_zeroes(symbol, source, local_source, &with_addon, first_part, second_part)) { sprintf(symbol->errtxt, "294: Input too long (%s)", with_addon ? "5 character maximum for add-on" : "13 character maximum"); return ZINT_ERROR_TOO_LONG; } - reader = 0; if (with_addon) { - int local_length = (int) ustrlen(local_source); - do { - if (local_source[reader] == '+') { - first_part[writer] = '\0'; - latch = TRUE; - reader++; - writer = 0; - } - - if (latch) { - second_part[writer] = local_source[reader]; - reader++; - writer++; - } else { - first_part[writer] = local_source[reader]; - reader++; - writer++; - } - } while (reader <= local_length); - if (symbol->symbology == BARCODE_UPCA || symbol->symbology == BARCODE_UPCA_CHK || symbol->symbology == BARCODE_UPCA_CC) { addon_gap = symbol->option_2 >= 9 && symbol->option_2 <= 12 ? symbol->option_2 : 9; } else { addon_gap = symbol->option_2 >= 7 && symbol->option_2 <= 12 ? symbol->option_2 : 7; } - } else { - ustrcpy(first_part, local_source); } first_part_len = (int) ustrlen(first_part); @@ -960,7 +935,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src second_part_len = (int) ustrlen(second_part); if (symbol->symbology == BARCODE_ISBNX) { /* Need to further check that add-on numeric only */ - if (is_sane(NEON, second_part, second_part_len) != 0) { + if (!is_sane(NEON_F, second_part, second_part_len)) { strcpy(symbol->errtxt, "295: Invalid add-on data (digits only)"); return ZINT_ERROR_INVALID_DATA; } @@ -983,7 +958,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src return ZINT_ERROR_TOO_LONG; } - expand(symbol, (const char *) dest); + expand(symbol, dest, (int) strlen(dest)); switch (symbol->symbology) { case BARCODE_EANX_CC: diff --git a/backend/vector.c b/backend/vector.c index ec4426b1..296043ec 100644 --- a/backend/vector.c +++ b/backend/vector.c @@ -407,6 +407,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ unsigned char textpart1[5], textpart2[7], textpart3[7], textpart4[2]; int hide_text; int i, r; + int block_width = 0; int text_height; /* Font pixel size (so whole integers) */ float text_gap; /* Gap between barcode and text */ float guard_descent; @@ -415,7 +416,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ float digit_ascent_factor = 0.25f; /* Assuming digit ascent roughly 25% less than font size */ float dot_overspill = 0.0f; float dot_offset = 0.0f; - int rect_count, last_row_start = 0; + int rect_count = 0, last_row_start = 0; struct zint_vector *vector; struct zint_vector_rect *rect, *last_rectangle = NULL; @@ -427,7 +428,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ vector_free(symbol); // Sanity check colours - error_number = output_check_colour_options(symbol); + error_number = out_check_colour_options(symbol); if (error_number != 0) { return error_number; } @@ -443,17 +444,17 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ vector->circles = NULL; vector->strings = NULL; - large_bar_height = output_large_bar_height(symbol, 0 /*No rounding to scale*/); + large_bar_height = out_large_bar_height(symbol, 0 /*No rounding to scale*/); main_width = symbol->width; if (is_extendable(symbol->symbology)) { - upceanflag = output_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap); + upceanflag = out_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap); } hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0)); - output_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, 0 /*scaler*/, + out_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, 0 /*scaler*/, NULL, NULL, NULL, NULL); /* Note font sizes scaled by 2 so really twice these values */ @@ -540,12 +541,12 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ /* Hexagons */ for (r = 0; r < symbol->rows; r++) { const int odd_row = r & 1; /* Odd (reduced) row, even (full) row */ - const float yposn = r * yposn_offset + hex_yradius + yoffset; + const float hex_yposn = r * yposn_offset + hex_yradius + yoffset; const float xposn_offset = (odd_row ? hex_diameter : hex_radius) + xoffset; for (i = 0; i < symbol->width - odd_row; i++) { if (module_is_set(symbol, r, i)) { - const float xposn = i * hex_diameter + xposn_offset; - hexagon = vector_plot_create_hexagon(symbol, xposn, yposn, hex_diameter); + const float hex_xposn = i * hex_diameter + xposn_offset; + hexagon = vector_plot_create_hexagon(symbol, hex_xposn, hex_yposn, hex_diameter); if (!hexagon) return ZINT_ERROR_MEMORY; vector_plot_add_hexagon(symbol, hexagon, &last_hexagon); } @@ -564,79 +565,93 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ } } // Plot rectangles - most symbols created here - } else { - rect_count = 0; + } else if (symbol->symbology == BARCODE_ULTRA) { + yposn = yoffset; + for (r = 0; r < symbol->rows; r++) { + float row_height = symbol->row_height[r]; + last_row_start = rect_count; + + for (i = 0; i < symbol->width; i += block_width) { + int fill = module_colour_is_set(symbol, r, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_colour_is_set(symbol, r, i + block_width) == fill; block_width++); + if (fill) { + /* a colour block */ + rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height); + if (!rect) return ZINT_ERROR_MEMORY; + rect->colour = module_colour_is_set(symbol, r, i); + vector_plot_add_rect(symbol, rect, &last_rectangle); + rect_count++; + } + } + yposn += row_height; + } + + } else if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */ yposn = yoffset; for (r = 0; r < symbol->rows; r++) { float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; last_row_start = rect_count; - i = 0; + for (i = 0; i < symbol->width; i += block_width) { + float addon_row_height; + int fill = module_is_set(symbol, r, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_is_set(symbol, r, i + block_width) == fill; block_width++); - if (symbol->symbology == BARCODE_ULTRA) { - do { - int module_fill = module_colour_is_set(symbol, r, i); - int block_width = 0; - do { - block_width++; - } while (i + block_width < symbol->width - && module_colour_is_set(symbol, r, i + block_width) == module_fill); - if (module_fill) { - /* a colour block */ + if ((r == (symbol->rows - 1)) && (i > main_width) && (addon_latch == 0)) { + addon_text_yposn = yposn + text_height - text_height * digit_ascent_factor; + if (addon_text_yposn < 0.0f) { + addon_text_yposn = 0.0f; + } + addon_row_height = row_height - (addon_text_yposn - yposn) + text_gap; + if (upceanflag != 12 && upceanflag != 6) { /* UPC-A/E add-ons don't descend */ + addon_row_height += guard_descent; + } + if (addon_row_height < 0.5f) { + addon_row_height = 0.5f; + } + addon_latch = 1; + } + if (fill) { + /* a bar */ + if (addon_latch) { + rect = vector_plot_create_rect(symbol, i + xoffset, addon_text_yposn - text_gap, + block_width, addon_row_height); + } else { rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height); - if (!rect) return ZINT_ERROR_MEMORY; - rect->colour = module_colour_is_set(symbol, r, i); - vector_plot_add_rect(symbol, rect, &last_rectangle); - rect_count++; } - i += block_width; + if (!rect) return ZINT_ERROR_MEMORY; + vector_plot_add_rect(symbol, rect, &last_rectangle); + rect_count++; + } + } + yposn += row_height; + } - } while (i < symbol->width); - } else { - do { - float addon_row_height; - int module_fill = module_is_set(symbol, r, i); - int block_width = 0; - do { - block_width++; - } while (i + block_width < symbol->width - && module_is_set(symbol, r, i + block_width) == module_fill); + } else { + yposn = yoffset; + for (r = 0; r < symbol->rows; r++) { + float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; + last_row_start = rect_count; - if (upceanflag && (addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) { - addon_text_yposn = yposn + text_height - text_height * digit_ascent_factor; - if (addon_text_yposn < 0.0f) { - addon_text_yposn = 0.0f; - } - addon_row_height = row_height - (addon_text_yposn - yposn) + text_gap; - if (upceanflag != 12 && upceanflag != 6) { /* UPC-A/E add-ons don't descend */ - addon_row_height += guard_descent; - } - if (addon_row_height < 0.5f) { - addon_row_height = 0.5f; - } - addon_latch = 1; - } - if (module_fill) { - /* a bar */ - if (addon_latch == 0) { - rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height); - } else { - rect = vector_plot_create_rect(symbol, i + xoffset, addon_text_yposn - text_gap, - block_width, addon_row_height); - } - if (!rect) return ZINT_ERROR_MEMORY; - vector_plot_add_rect(symbol, rect, &last_rectangle); - rect_count++; - } - i += block_width; - - } while (i < symbol->width); + for (i = 0; i < symbol->width; i += block_width) { + int fill = module_is_set(symbol, r, i); + for (block_width = 1; (i + block_width < symbol->width) + && module_is_set(symbol, r, i + block_width) == fill; block_width++); + if (fill) { + /* a bar */ + rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height); + if (!rect) return ZINT_ERROR_MEMORY; + vector_plot_add_rect(symbol, rect, &last_rectangle); + rect_count++; + } } yposn += row_height; } } - if (upceanflag) { + if (guard_descent && upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */ /* Guard bar extension */ if (upceanflag == 6) { /* UPC-E */ i = 0; @@ -686,7 +701,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ } i++; } - } else if (upceanflag == 13) { /* EAN-13 */ + } else { /* EAN-13 */ i = 0; for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) { switch (i - last_row_start) { @@ -707,7 +722,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ /* Add the text */ if (!hide_text) { - int textdone = 0; float text_xposn; float text_yposn; @@ -718,10 +732,10 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ text_yposn += symbol->border_width; } - if (upceanflag) { + if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */ float textwidth; - output_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4); + out_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4); if (upceanflag == 6) { /* UPC-E */ text_xposn = -5.0f + xoffset; @@ -736,7 +750,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ textwidth = 6.2f; if (!vector_plot_add_string(symbol, textpart3, text_xposn, text_yposn, upcae_outside_text_height, textwidth, 1 /*left align*/, &last_string)) return ZINT_ERROR_MEMORY; - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = 61.0f + xoffset + addon_gap; @@ -760,7 +773,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ text_xposn = 50.0f + xoffset; if (!vector_plot_add_string(symbol, textpart2, text_xposn, text_yposn, text_height, textwidth, 0, &last_string)) return ZINT_ERROR_MEMORY; - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = 77.0f + xoffset + addon_gap; @@ -792,7 +804,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ textwidth = 6.2f; if (!vector_plot_add_string(symbol, textpart4, text_xposn, text_yposn, upcae_outside_text_height, textwidth, 1 /*left align*/, &last_string)) return ZINT_ERROR_MEMORY; - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = 105.0f + xoffset + addon_gap; @@ -808,7 +819,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ break; } - } else if (upceanflag == 13) { /* EAN-13 */ + } else { /* EAN-13 */ text_xposn = -5.0f + xoffset; textwidth = 8.5f; if (!vector_plot_add_string(symbol, textpart1, text_xposn, text_yposn, @@ -820,7 +831,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ text_xposn = 71.0f + xoffset; if (!vector_plot_add_string(symbol, textpart3, text_xposn, text_yposn, text_height, textwidth, 0, &last_string)) return ZINT_ERROR_MEMORY; - textdone = 1; switch (ustrlen(addon)) { case 2: text_xposn = 105.0f + xoffset + addon_gap; @@ -836,9 +846,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ break; } } - } - - if (!textdone) { + } else { /* Put normal human readable text at the bottom (and centered) */ // calculate start xoffset to center text text_xposn = main_width / 2.0f + xoffset; diff --git a/backend/zint.h b/backend/zint.h index b278f22e..1cb6e3b3 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -253,6 +253,7 @@ extern "C" { #define BARCODE_UPNQR 143 /* UPNQR (Univerzalnega Plačilnega Naloga QR) */ #define BARCODE_ULTRA 144 /* Ultracode */ #define BARCODE_RMQR 145 /* Rectangular Micro QR Code (rMQR) */ +#define BARCODE_LAST 145 /* Max barcode number marker, not barcode */ /* Output options (`symbol->output_options`) */ #define BARCODE_NO_ASCII 0x0001 /* Legacy (no-op) */ diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index 97f20aea..0c9d776d 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -111,7 +111,7 @@ static const struct bstyle_item bstyle_items[] = { { QSL("POSTNET"), BARCODE_POSTNET }, { QSL("QR Code (ISO 18004) (and HIBC)"), BARCODE_QRCODE }, { QSL("Rectangular Micro QR (rMQR)"), BARCODE_RMQR }, - { QSL("Royal Mail 4-state Barcode"), BARCODE_RM4SCC }, + { QSL("Royal Mail 4-state Barcode (RM4SCC)"), BARCODE_RM4SCC }, { QSL("Royal Mail 4-state Mailmark"), BARCODE_MAILMARK }, { QSL("Telepen"), BARCODE_TELEPEN }, { QSL("Telepen Numeric"), BARCODE_TELEPEN_NUM },