test suite: zxing-cpp: adjust for returnCodabarStartEnd no-op;

allow for old "libpng" (`png_set_scale_16()` not available)
general: Solaris compat
library: use proper function ptr instead of `void *` for function
  table; warning suppression "-Wpedantic" -> "-Wstrict-prototypes"
GRIDMATRIX/HANXIN/QRCODE: `xx_define_mode()`: multi-dim `char_modes`
This commit is contained in:
gitlost 2024-02-06 13:01:35 +00:00
parent 7b41dfbee2
commit e167f5b534
8 changed files with 99 additions and 82 deletions

View file

@ -54,7 +54,8 @@ extern "C" {
# include <malloc.h> # include <malloc.h>
# define z_alloca(nmemb) _alloca(nmemb) # define z_alloca(nmemb) _alloca(nmemb)
#else #else
# if defined(ZINT_IS_C89) || defined(ZINT_IS_C99) || defined(__NuttX__) || defined(_AIX) # if defined(ZINT_IS_C89) || defined(ZINT_IS_C99) || defined(__NuttX__) || defined(_AIX) \
|| (defined(__sun) && defined(__SVR4) /*Solaris*/)
# include <alloca.h> # include <alloca.h>
# endif # endif
# define z_alloca(nmemb) alloca(nmemb) # define z_alloca(nmemb) alloca(nmemb)

View file

@ -1,7 +1,7 @@
/* gridmtx.c - Grid Matrix */ /* gridmtx.c - Grid Matrix */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -156,15 +156,15 @@ static void gm_define_mode(char *mode, const unsigned int ddata[], const int len
unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */ unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */
int double_byte, space, numeric, lower, upper, control, double_digit, eol; int double_byte, space, numeric, lower, upper, control, double_digit, eol;
int i, j, k, cm_i; int i, j, k;
unsigned int min_cost; unsigned int min_cost;
char cur_mode; char cur_mode;
unsigned int prev_costs[GM_NUM_MODES]; unsigned int prev_costs[GM_NUM_MODES];
unsigned int cur_costs[GM_NUM_MODES]; unsigned int cur_costs[GM_NUM_MODES];
char *char_modes = (char *) z_alloca(length * GM_NUM_MODES); char (*char_modes)[GM_NUM_MODES] = (char (*)[GM_NUM_MODES]) z_alloca(GM_NUM_MODES * length);
/* char_modes[i * GM_NUM_MODES + j] represents the mode to encode the code point at index i such that the final /* char_modes[i][j] represents the mode to encode the code point at index i such that the final segment
* segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ ends in mode_types[j] and the total number of bits is minimized over all possible choices */
memset(char_modes, 0, length * GM_NUM_MODES); memset(char_modes, 0, length * GM_NUM_MODES);
/* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT) /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT)
@ -172,7 +172,7 @@ static void gm_define_mode(char *mode, const unsigned int ddata[], const int len
memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int)); memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int));
/* Calculate costs using dynamic programming */ /* Calculate costs using dynamic programming */
for (i = 0, cm_i = 0; i < length; i++, cm_i += GM_NUM_MODES) { for (i = 0; i < length; i++) {
memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int)); memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int));
space = numeric = lower = upper = control = double_digit = eol = 0; space = numeric = lower = upper = control = double_digit = eol = 0;
@ -201,7 +201,7 @@ static void gm_define_mode(char *mode, const unsigned int ddata[], const int len
/* Hanzi mode can encode anything */ /* Hanzi mode can encode anything */
cur_costs[GM_H] = prev_costs[GM_H] + (double_digit || eol ? 39 : 78); /* (6.5 : 13) * GM_MULT */ cur_costs[GM_H] = prev_costs[GM_H] + (double_digit || eol ? 39 : 78); /* (6.5 : 13) * GM_MULT */
char_modes[cm_i + GM_H] = GM_CHINESE; char_modes[i][GM_H] = GM_CHINESE;
/* Byte mode can encode anything */ /* Byte mode can encode anything */
if (byte_count == 512 || (double_byte && byte_count == 511)) { if (byte_count == 512 || (double_byte && byte_count == 511)) {
@ -213,39 +213,39 @@ static void gm_define_mode(char *mode, const unsigned int ddata[], const int len
byte_count = 0; byte_count = 0;
} }
cur_costs[GM_B] += prev_costs[GM_B] + (double_byte ? 96 : 48); /* (16 : 8) * GM_MULT */ cur_costs[GM_B] += prev_costs[GM_B] + (double_byte ? 96 : 48); /* (16 : 8) * GM_MULT */
char_modes[cm_i + GM_B] = GM_BYTE; char_modes[i][GM_B] = GM_BYTE;
byte_count += double_byte ? 2 : 1; byte_count += double_byte ? 2 : 1;
if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) { if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) {
cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost; cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost;
char_modes[cm_i + GM_N] = GM_NUMBER; char_modes[i][GM_N] = GM_NUMBER;
} }
if (control) { if (control) {
cur_costs[GM_L] = prev_costs[GM_L] + 78; /* (7 + 6) * GM_MULT */ cur_costs[GM_L] = prev_costs[GM_L] + 78; /* (7 + 6) * GM_MULT */
char_modes[cm_i + GM_L] = GM_LOWER; char_modes[i][GM_L] = GM_LOWER;
cur_costs[GM_U] = prev_costs[GM_U] + 78; /* (7 + 6) * GM_MULT */ cur_costs[GM_U] = prev_costs[GM_U] + 78; /* (7 + 6) * GM_MULT */
char_modes[cm_i + GM_U] = GM_UPPER; char_modes[i][GM_U] = GM_UPPER;
cur_costs[GM_M] = prev_costs[GM_M] + 96; /* (10 + 6) * GM_MULT */ cur_costs[GM_M] = prev_costs[GM_M] + 96; /* (10 + 6) * GM_MULT */
char_modes[cm_i + GM_M] = GM_MIXED; char_modes[i][GM_M] = GM_MIXED;
} else { } else {
if (lower || space) { if (lower || space) {
cur_costs[GM_L] = prev_costs[GM_L] + 30; /* 5 * GM_MULT */ cur_costs[GM_L] = prev_costs[GM_L] + 30; /* 5 * GM_MULT */
char_modes[cm_i + GM_L] = GM_LOWER; char_modes[i][GM_L] = GM_LOWER;
} }
if (upper || space) { if (upper || space) {
cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */ cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */
char_modes[cm_i + GM_U] = GM_UPPER; char_modes[i][GM_U] = GM_UPPER;
} }
if (numeric || lower || upper || space) { if (numeric || lower || upper || space) {
cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */ cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */
char_modes[cm_i + GM_M] = GM_MIXED; char_modes[i][GM_M] = GM_MIXED;
} }
} }
if (i == length - 1) { /* Add end of data costs if last character */ if (i == length - 1) { /* Add end of data costs if last character */
for (j = 0; j < GM_NUM_MODES; j++) { for (j = 0; j < GM_NUM_MODES; j++) {
if (char_modes[cm_i + j]) { if (char_modes[i][j]) {
cur_costs[j] += eod_costs[j]; cur_costs[j] += eod_costs[j];
} }
} }
@ -254,11 +254,11 @@ static void gm_define_mode(char *mode, const unsigned int ddata[], const int len
/* Start new segment at the end to switch modes */ /* Start new segment at the end to switch modes */
for (j = 0; j < GM_NUM_MODES; j++) { /* To mode */ for (j = 0; j < GM_NUM_MODES; j++) { /* To mode */
for (k = 0; k < GM_NUM_MODES; k++) { /* From mode */ for (k = 0; k < GM_NUM_MODES; k++) { /* From mode */
if (j != k && char_modes[cm_i + k]) { if (j != k && char_modes[i][k]) {
const unsigned int new_cost = cur_costs[k] + switch_costs[k][j]; const unsigned int new_cost = cur_costs[k] + switch_costs[k][j];
if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { if (!char_modes[i][j] || new_cost < cur_costs[j]) {
cur_costs[j] = new_cost; cur_costs[j] = new_cost;
char_modes[cm_i + j] = mode_types[k]; char_modes[i][j] = mode_types[k];
} }
} }
} }
@ -278,9 +278,9 @@ static void gm_define_mode(char *mode, const unsigned int ddata[], const int len
} }
/* Get optimal mode for each code point by tracing backwards */ /* 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) { for (i = length - 1; i >= 0; i--) {
j = posn(mode_types, cur_mode); j = posn(mode_types, cur_mode);
cur_mode = char_modes[cm_i + j]; cur_mode = char_modes[i][j];
mode[i] = cur_mode; mode[i] = cur_mode;
} }

View file

@ -1,7 +1,7 @@
/* hanxin.c - Han Xin Code */ /* hanxin.c - Han Xin Code */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -384,28 +384,28 @@ static void hx_define_mode(char *mode, const unsigned int ddata[], const int len
unsigned int numeric_end = 0, numeric_cost = 0, text_submode = 1, fourbyte_end = 0, fourbyte_cost = 0; /* State */ unsigned int numeric_end = 0, numeric_cost = 0, text_submode = 1, fourbyte_end = 0, fourbyte_cost = 0; /* State */
int text1, text2; int text1, text2;
int i, j, k, cm_i; int i, j, k;
unsigned int min_cost; unsigned int min_cost;
char cur_mode; char cur_mode;
unsigned int prev_costs[HX_NUM_MODES]; unsigned int prev_costs[HX_NUM_MODES];
unsigned int cur_costs[HX_NUM_MODES]; unsigned int cur_costs[HX_NUM_MODES];
char *char_modes = (char *) z_alloca(length * HX_NUM_MODES); char (*char_modes)[HX_NUM_MODES] = (char (*)[HX_NUM_MODES]) z_alloca(HX_NUM_MODES * length);
/* char_modes[i * HX_NUM_MODES + j] represents the mode to encode the code point at index i such that the final /* char_modes[i][j] represents the mode to encode the code point at index i such that the final segment
* segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ ends in mode_types[j] and the total number of bits is minimized over all possible choices */
memset(char_modes, 0, length * HX_NUM_MODES); memset(char_modes, 0, HX_NUM_MODES * length);
/* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT) /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT)
* bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */
memcpy(prev_costs, head_costs, HX_NUM_MODES * sizeof(unsigned int)); memcpy(prev_costs, head_costs, HX_NUM_MODES * sizeof(unsigned int));
/* Calculate costs using dynamic programming */ /* Calculate costs using dynamic programming */
for (i = 0, cm_i = 0; i < length; i++, cm_i += HX_NUM_MODES) { for (i = 0; i < length; i++) {
memset(cur_costs, 0, HX_NUM_MODES * sizeof(unsigned int)); memset(cur_costs, 0, HX_NUM_MODES * sizeof(unsigned int));
if (hx_in_numeric(ddata, length, i, &numeric_end, &numeric_cost)) { if (hx_in_numeric(ddata, length, i, &numeric_end, &numeric_cost)) {
cur_costs[HX_N] = prev_costs[HX_N] + numeric_cost; cur_costs[HX_N] = prev_costs[HX_N] + numeric_cost;
char_modes[cm_i + HX_N] = 'n'; char_modes[i][HX_N] = 'n';
text1 = 1; text1 = 1;
text2 = 0; text2 = 0;
} else { } else {
@ -420,35 +420,35 @@ static void hx_define_mode(char *mode, const unsigned int ddata[], const int len
} else { } else {
cur_costs[HX_T] = prev_costs[HX_T] + 36; /* 6 * HX_MULT */ cur_costs[HX_T] = prev_costs[HX_T] + 36; /* 6 * HX_MULT */
} }
char_modes[cm_i + HX_T] = 't'; char_modes[i][HX_T] = 't';
} else { } else {
text_submode = 1; text_submode = 1;
} }
/* Binary mode can encode anything */ /* Binary mode can encode anything */
cur_costs[HX_B] = prev_costs[HX_B] + (ddata[i] > 0xFF ? 96 : 48); /* (16 : 8) * HX_MULT */ cur_costs[HX_B] = prev_costs[HX_B] + (ddata[i] > 0xFF ? 96 : 48); /* (16 : 8) * HX_MULT */
char_modes[cm_i + HX_B] = 'b'; char_modes[i][HX_B] = 'b';
if (hx_in_fourbyte(ddata, length, i, &fourbyte_end, &fourbyte_cost)) { if (hx_in_fourbyte(ddata, length, i, &fourbyte_end, &fourbyte_cost)) {
cur_costs[HX_F] = prev_costs[HX_F] + fourbyte_cost; cur_costs[HX_F] = prev_costs[HX_F] + fourbyte_cost;
char_modes[cm_i + HX_F] = 'f'; char_modes[i][HX_F] = 'f';
} else { } else {
if (hx_isDoubleByte(ddata[i])) { if (hx_isDoubleByte(ddata[i])) {
cur_costs[HX_D] = prev_costs[HX_D] + 90; /* 15 * HX_MULT */ cur_costs[HX_D] = prev_costs[HX_D] + 90; /* 15 * HX_MULT */
char_modes[cm_i + HX_D] = 'd'; char_modes[i][HX_D] = 'd';
if (hx_isRegion1(ddata[i])) { /* Subset */ if (hx_isRegion1(ddata[i])) { /* Subset */
cur_costs[HX_1] = prev_costs[HX_1] + 72; /* 12 * HX_MULT */ cur_costs[HX_1] = prev_costs[HX_1] + 72; /* 12 * HX_MULT */
char_modes[cm_i + HX_1] = '1'; char_modes[i][HX_1] = '1';
} else if (hx_isRegion2(ddata[i])) { /* Subset */ } else if (hx_isRegion2(ddata[i])) { /* Subset */
cur_costs[HX_2] = prev_costs[HX_2] + 72; /* 12 * HX_MULT */ cur_costs[HX_2] = prev_costs[HX_2] + 72; /* 12 * HX_MULT */
char_modes[cm_i + HX_2] = '2'; char_modes[i][HX_2] = '2';
} }
} }
} }
if (i == length - 1) { /* Add end of data costs if last character */ if (i == length - 1) { /* Add end of data costs if last character */
for (j = 0; j < HX_NUM_MODES; j++) { for (j = 0; j < HX_NUM_MODES; j++) {
if (char_modes[cm_i + j]) { if (char_modes[i][j]) {
cur_costs[j] += eod_costs[j]; cur_costs[j] += eod_costs[j];
} }
} }
@ -457,11 +457,11 @@ static void hx_define_mode(char *mode, const unsigned int ddata[], const int len
/* Start new segment at the end to switch modes */ /* Start new segment at the end to switch modes */
for (j = 0; j < HX_NUM_MODES; j++) { /* To mode */ for (j = 0; j < HX_NUM_MODES; j++) { /* To mode */
for (k = 0; k < HX_NUM_MODES; k++) { /* From mode */ for (k = 0; k < HX_NUM_MODES; k++) { /* From mode */
if (j != k && char_modes[cm_i + k]) { if (j != k && char_modes[i][k]) {
const unsigned int new_cost = cur_costs[k] + switch_costs[k][j]; const unsigned int new_cost = cur_costs[k] + switch_costs[k][j];
if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { if (!char_modes[i][j] || new_cost < cur_costs[j]) {
cur_costs[j] = new_cost; cur_costs[j] = new_cost;
char_modes[cm_i + j] = mode_types[k]; char_modes[i][j] = mode_types[k];
} }
} }
} }
@ -481,9 +481,9 @@ static void hx_define_mode(char *mode, const unsigned int ddata[], const int len
} }
/* Get optimal mode for each code point by tracing backwards */ /* 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) { for (i = length - 1; i >= 0; i--) {
j = posn(mode_types, cur_mode); j = posn(mode_types, cur_mode);
cur_mode = char_modes[cm_i + j]; cur_mode = char_modes[i][j];
mode[i] = cur_mode; mode[i] = cur_mode;
} }

View file

@ -568,16 +568,15 @@ static int has_hrt(const int symbology) {
return 1; return 1;
} }
/* Suppress warning ISO C forbids initialization between function pointer and void * */ /* Suppress clang warning: a function declaration without a prototype is deprecated in all versions of C
#if defined(__GNUC__) || defined(__clang__) (not included in gcc's "-wpedantic") */
#if defined(__clang__)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" #pragma GCC diagnostic ignored "-Wstrict-prototypes"
#endif #endif
/* Used for dispatching barcodes and for whether symbol id valid */ /* Used for dispatching barcodes and for whether symbol id valid */
typedef int (*barcode_segs_func_t)(struct zint_symbol *, struct zint_seg[], const int); static int (*const barcode_funcs[BARCODE_LAST + 1])() = {
typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char[], int);
static const void *barcode_funcs[BARCODE_LAST + 1] = {
NULL, code11, c25standard, c25inter, c25iata, /*0-4*/ NULL, code11, c25standard, c25inter, c25iata, /*0-4*/
NULL, c25logic, c25ind, code39, excode39, /*5-9*/ NULL, c25logic, c25ind, code39, excode39, /*5-9*/
NULL, NULL, NULL, eanx, eanx, /*10-14*/ NULL, NULL, NULL, eanx, eanx, /*10-14*/
@ -610,6 +609,12 @@ static const void *barcode_funcs[BARCODE_LAST + 1] = {
rmqr, bc412, rmqr, bc412,
}; };
#if defined(__clang__)
#pragma GCC diagnostic pop
#endif
typedef int (*barcode_segs_func_t)(struct zint_symbol *, struct zint_seg[], const int);
typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char[], int);
static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count);
/* Main dispatch, checking for barcodes which handle ECIs/character sets themselves, otherwise calling /* Main dispatch, checking for barcodes which handle ECIs/character sets themselves, otherwise calling
@ -688,10 +693,6 @@ static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], c
return error_number; return error_number;
} }
#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic pop
#endif
/* Remove Unicode BOM at start of data */ /* Remove Unicode BOM at start of data */
static void strip_bom(unsigned char *source, int *input_length) { static void strip_bom(unsigned char *source, int *input_length) {
int i; int i;

View file

@ -1,7 +1,7 @@
/* qr.c Handles QR Code, Micro QR Code, UPNQR and rMQR */ /* qr.c Handles QR Code, Micro QR Code, UPNQR and rMQR */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -237,18 +237,18 @@ static void qr_define_mode(char mode[], const unsigned int ddata[], const int le
}; };
int m1, m2; int m1, m2;
int i, j, k, cm_i; int i, j, k;
unsigned int min_cost; unsigned int min_cost;
char cur_mode; char cur_mode;
unsigned int prev_costs[QR_NUM_MODES]; unsigned int prev_costs[QR_NUM_MODES];
unsigned int cur_costs[QR_NUM_MODES]; unsigned int cur_costs[QR_NUM_MODES];
char *char_modes = (char *) z_alloca(length * QR_NUM_MODES); char (*char_modes)[QR_NUM_MODES] = (char (*)[QR_NUM_MODES]) z_alloca(QR_NUM_MODES * length);
state[QR_VER] = (unsigned int) version; state[QR_VER] = (unsigned int) version;
/* char_modes[i * QR_NUM_MODES + j] represents the mode to encode the code point at index i such that the final /* char_modes[i][j] represents the mode to encode the code point at index i such that the final segment
* segment ends in qr_mode_types[j] and the total number of bits is minimized over all possible choices */ ends in qr_mode_types[j] and the total number of bits is minimized over all possible choices */
memset(char_modes, 0, length * QR_NUM_MODES); memset(char_modes, 0, QR_NUM_MODES * length);
/* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/QR_MULT) /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/QR_MULT)
* bits needed to encode the entire string prefix of length i, and end in qr_mode_types[j] */ * bits needed to encode the entire string prefix of length i, and end in qr_mode_types[j] */
@ -257,13 +257,13 @@ static void qr_define_mode(char mode[], const unsigned int ddata[], const int le
#ifdef QR_DEBUG_DEFINE_MODE #ifdef QR_DEBUG_DEFINE_MODE
printf(" head"); printf(" head");
for (j = 0; j < QR_NUM_MODES; j++) { for (j = 0; j < QR_NUM_MODES; j++) {
printf(" %c(%c)=%d", qr_mode_types[j], char_modes[j], prev_costs[j]); printf(" %c(%c)=%d", qr_mode_types[j], char_modes[0][j], prev_costs[j]);
} }
printf("\n"); printf("\n");
#endif #endif
/* Calculate costs using dynamic programming */ /* Calculate costs using dynamic programming */
for (i = 0, cm_i = 0; i < length; i++, cm_i += QR_NUM_MODES) { for (i = 0; i < length; i++) {
memset(cur_costs, 0, QR_NUM_MODES * sizeof(unsigned int)); memset(cur_costs, 0, QR_NUM_MODES * sizeof(unsigned int));
m1 = version == MICROQR_VERSION; m1 = version == MICROQR_VERSION;
@ -271,31 +271,31 @@ static void qr_define_mode(char mode[], const unsigned int ddata[], const int le
if (ddata[i] > 0xFF) { if (ddata[i] > 0xFF) {
cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 96); /* 16 * QR_MULT */ cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 96); /* 16 * QR_MULT */
char_modes[cm_i + QR_B] = 'B'; char_modes[i][QR_B] = 'B';
cur_costs[QR_K] = prev_costs[QR_K] + ((m1 || m2) ? QR_MICROQR_MAX : 78); /* 13 * QR_MULT */ cur_costs[QR_K] = prev_costs[QR_K] + ((m1 || m2) ? QR_MICROQR_MAX : 78); /* 13 * QR_MULT */
char_modes[cm_i + QR_K] = 'K'; char_modes[i][QR_K] = 'K';
} else { } else {
if (qr_in_numeric(ddata, length, i, &state[QR_N_END], &state[QR_N_COST])) { if (qr_in_numeric(ddata, length, i, &state[QR_N_END], &state[QR_N_COST])) {
cur_costs[QR_N] = prev_costs[QR_N] + state[QR_N_COST]; cur_costs[QR_N] = prev_costs[QR_N] + state[QR_N_COST];
char_modes[cm_i + QR_N] = 'N'; char_modes[i][QR_N] = 'N';
} }
if (qr_in_alpha(ddata, length, i, &state[QR_A_END], &state[QR_A_COST], &state[QR_A_PCENT], if (qr_in_alpha(ddata, length, i, &state[QR_A_END], &state[QR_A_COST], &state[QR_A_PCENT],
&state[QR_A_PCCNT], gs1)) { &state[QR_A_PCCNT], gs1)) {
cur_costs[QR_A] = prev_costs[QR_A] + (m1 ? QR_MICROQR_MAX : state[QR_A_COST]); cur_costs[QR_A] = prev_costs[QR_A] + (m1 ? QR_MICROQR_MAX : state[QR_A_COST]);
char_modes[cm_i + QR_A] = 'A'; char_modes[i][QR_A] = 'A';
} }
cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 48); /* 8 * QR_MULT */ cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 48); /* 8 * QR_MULT */
char_modes[cm_i + QR_B] = 'B'; char_modes[i][QR_B] = 'B';
} }
/* Start new segment at the end to switch modes */ /* Start new segment at the end to switch modes */
for (j = 0; j < QR_NUM_MODES; j++) { /* To mode */ for (j = 0; j < QR_NUM_MODES; j++) { /* To mode */
for (k = 0; k < QR_NUM_MODES; k++) { /* From mode */ for (k = 0; k < QR_NUM_MODES; k++) { /* From mode */
if (j != k && char_modes[cm_i + k]) { if (j != k && char_modes[i][k]) {
const unsigned int new_cost = cur_costs[k] + state[j]; /* Switch costs same as head costs */ const unsigned int new_cost = cur_costs[k] + state[j]; /* Switch costs same as head costs */
if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { if (!char_modes[i][j] || new_cost < cur_costs[j]) {
cur_costs[j] = new_cost; cur_costs[j] = new_cost;
char_modes[cm_i + j] = qr_mode_types[k]; char_modes[i][j] = qr_mode_types[k];
} }
} }
} }
@ -306,10 +306,10 @@ static void qr_define_mode(char mode[], const unsigned int ddata[], const int le
int min_j = 0; int min_j = 0;
printf(" % 4d: curr", i); printf(" % 4d: curr", i);
for (j = 0; j < QR_NUM_MODES; j++) { for (j = 0; j < QR_NUM_MODES; j++) {
printf(" %c(%c)=%d", qr_mode_types[j], char_modes[cm_i + j], cur_costs[j]); printf(" %c(%c)=%d", qr_mode_types[j], char_modes[i][j], cur_costs[j]);
if (cur_costs[j] < cur_costs[min_j]) min_j = j; if (cur_costs[j] < cur_costs[min_j]) min_j = j;
} }
printf(" min %c(%c)=%d\n", qr_mode_types[min_j], char_modes[cm_i + min_j], cur_costs[min_j]); printf(" min %c(%c)=%d\n", qr_mode_types[min_j], char_modes[i][min_j], cur_costs[min_j]);
} }
#endif #endif
memcpy(prev_costs, cur_costs, QR_NUM_MODES * sizeof(unsigned int)); memcpy(prev_costs, cur_costs, QR_NUM_MODES * sizeof(unsigned int));
@ -326,9 +326,9 @@ static void qr_define_mode(char mode[], const unsigned int ddata[], const int le
} }
/* Get optimal mode for each code point by tracing backwards */ /* 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) { for (i = length - 1; i >= 0; i--) {
j = posn(qr_mode_types, cur_mode); j = posn(qr_mode_types, cur_mode);
cur_mode = char_modes[cm_i + j]; cur_mode = char_modes[i][j];
mode[i] = cur_mode; mode[i] = cur_mode;
} }

View file

@ -1,6 +1,6 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2023-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -109,7 +109,11 @@ static void test_svg(const testCtx *const p_ctx) {
testFinish(); testFinish();
} }
#ifndef _WIN32 #if defined(_WIN32) || (defined(__sun) && defined(__SVR4))
#define ZINT_TEST_NO_FMEMOPEN
#endif
#ifndef ZINT_TEST_NO_FMEMOPEN
extern FILE *fmemopen(void *buf, size_t size, const char *mode); extern FILE *fmemopen(void *buf, size_t size, const char *mode);
#endif #endif
@ -145,7 +149,7 @@ static void test_putsf(const testCtx *const p_ctx) {
struct zint_symbol *const symbol = &symbol_data; struct zint_symbol *const symbol = &symbol_data;
struct filemem fm; struct filemem fm;
struct filemem *const fmp = &fm; struct filemem *const fmp = &fm;
#ifndef _WIN32 #ifndef ZINT_TEST_NO_FMEMOPEN
FILE *fp; FILE *fp;
char buf[512] = {0}; /* Suppress clang-16/17 run-time exception MemorySanitizer: use-of-uninitialized-value */ char buf[512] = {0}; /* Suppress clang-16/17 run-time exception MemorySanitizer: use-of-uninitialized-value */
#endif #endif
@ -153,8 +157,8 @@ static void test_putsf(const testCtx *const p_ctx) {
testStart("test_putsf"); testStart("test_putsf");
for (j = 0; j < 2; j++) { /* 1st `memfile`, then file */ for (j = 0; j < 2; j++) { /* 1st `memfile`, then file */
#ifdef _WIN32 #ifdef ZINT_TEST_NO_FMEMOPEN
if (j == 1) break; /* Skip file test on Windows */ if (j == 1) break; /* Skip file test on Windows/Solaris */
#endif #endif
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
const char *locale = NULL; const char *locale = NULL;
@ -164,7 +168,7 @@ static void test_putsf(const testCtx *const p_ctx) {
ZBarcode_Reset(symbol); ZBarcode_Reset(symbol);
if (j == 1) { if (j == 1) {
#ifndef _WIN32 #ifndef ZINT_TEST_NO_FMEMOPEN
buf[0] = '\0'; buf[0] = '\0';
fp = fmemopen(buf, sizeof(buf), "w"); fp = fmemopen(buf, sizeof(buf), "w");
assert_nonnull(fp, "%d: fmemopen fail (%d, %s)\n", i, errno, strerror(errno)); assert_nonnull(fp, "%d: fmemopen fail (%d, %s)\n", i, errno, strerror(errno));
@ -174,7 +178,7 @@ static void test_putsf(const testCtx *const p_ctx) {
} }
assert_nonzero(fm_open(fmp, symbol, "w"), "i:%d: fm_open fail (%d, %s)\n", i, fmp->err, strerror(fmp->err)); assert_nonzero(fm_open(fmp, symbol, "w"), "i:%d: fm_open fail (%d, %s)\n", i, fmp->err, strerror(fmp->err));
if (j == 1) { if (j == 1) {
#ifndef _WIN32 #ifndef ZINT_TEST_NO_FMEMOPEN
/* Hack in `fmemopen()` fp */ /* Hack in `fmemopen()` fp */
assert_zero(fclose(fmp->fp), "i:%d fclose(fmp->fp) fail (%d, %s)\n", i, errno, strerror(errno)); assert_zero(fclose(fmp->fp), "i:%d fclose(fmp->fp) fail (%d, %s)\n", i, errno, strerror(errno));
fmp->fp = fp; fmp->fp = fp;
@ -200,7 +204,7 @@ static void test_putsf(const testCtx *const p_ctx) {
} }
if (j == 1) { if (j == 1) {
#ifndef _WIN32 #ifndef ZINT_TEST_NO_FMEMOPEN
assert_zero(strcmp(buf, data[i].expected), "%d: strcmp(%s, %s) != 0\n", i, buf, data[i].expected); assert_zero(strcmp(buf, data[i].expected), "%d: strcmp(%s, %s) != 0\n", i, buf, data[i].expected);
#endif #endif
} else { } else {

View file

@ -1685,7 +1685,11 @@ int testUtilCmpPngs(const char *png1, const char *png2) {
color_type1 = png_get_color_type(png_ptr1, info_ptr1); color_type1 = png_get_color_type(png_ptr1, info_ptr1);
bit_depth1 = png_get_bit_depth(png_ptr1, info_ptr1); bit_depth1 = png_get_bit_depth(png_ptr1, info_ptr1);
if (bit_depth1 == 16) { if (bit_depth1 == 16) {
#if defined(PNG_LIBPNG_VER) && PNG_LIBPNG_VER >= 10504
png_set_scale_16(png_ptr1); png_set_scale_16(png_ptr1);
#else
png_set_strip_16(png_ptr1);
#endif
} }
if (color_type1 == PNG_COLOR_TYPE_PALETTE) { if (color_type1 == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr1); png_set_palette_to_rgb(png_ptr1);
@ -1707,7 +1711,11 @@ int testUtilCmpPngs(const char *png1, const char *png2) {
color_type2 = png_get_color_type(png_ptr2, info_ptr2); color_type2 = png_get_color_type(png_ptr2, info_ptr2);
bit_depth2 = png_get_bit_depth(png_ptr2, info_ptr2); bit_depth2 = png_get_bit_depth(png_ptr2, info_ptr2);
if (bit_depth2 == 16) { if (bit_depth2 == 16) {
#if defined(PNG_LIBPNG_VER) && PNG_LIBPNG_VER >= 10504
png_set_scale_16(png_ptr2); png_set_scale_16(png_ptr2);
#else
png_set_strip_16(png_ptr2);
#endif
} }
if (color_type2 == PNG_COLOR_TYPE_PALETTE) { if (color_type2 == PNG_COLOR_TYPE_PALETTE) {
png_set_palette_to_rgb(png_ptr2); png_set_palette_to_rgb(png_ptr2);
@ -4036,7 +4044,9 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in
expected_len += maxi_len; expected_len += maxi_len;
} }
} else if (symbology == BARCODE_CODABAR) { } else if (symbology == BARCODE_CODABAR) {
/* Start A/B/C/D and stop A/B/C/D chars not returned by ZXing-C++ */ /* Ignore start A/B/C/D and stop A/B/C/D chars to avoid upper/lowercase issues */
cmp_buf++;
cmp_len -= 2;
expected++; expected++;
expected_len -= 2; expected_len -= 2;
if (symbol->option_2 == 1 || symbol->option_2 == 2) { if (symbol->option_2 == 1 || symbol->option_2 == 2) {

View file

@ -65,7 +65,8 @@ typedef char static_assert_int_at_least_32bits[sizeof(int) * CHAR_BIT < 32 ? -1
# include <malloc.h> # include <malloc.h>
# define z_alloca(nmemb) _alloca(nmemb) # define z_alloca(nmemb) _alloca(nmemb)
#else #else
# if defined(ZINT_IS_C89) || defined(ZINT_IS_C99) || defined(__NuttX__) || defined(_AIX) # if defined(ZINT_IS_C89) || defined(ZINT_IS_C99) || defined(__NuttX__) || defined(_AIX) \
|| (defined(__sun) && defined(__SVR4) /*Solaris*/)
# include <alloca.h> # include <alloca.h>
# endif # endif
# define z_alloca(nmemb) alloca(nmemb) # define z_alloca(nmemb) alloca(nmemb)