#209 font.h guard; improve gs1 c82 check, code1 num_digits

This commit is contained in:
gitlost 2021-02-09 02:51:36 +00:00
parent a91933cbdd
commit b3610d3c43
3 changed files with 65 additions and 61 deletions

View File

@ -311,20 +311,14 @@ static int is_last_single_ascii(const unsigned char string[], const int length,
return 0; return 0;
} }
/* Return length of numeric sequence from position `sp`, stopping after `max` if given (non-zero) */ /* Initialize number of digits array (taken from BWIPP) */
static int digits_ahead(const unsigned char string[], const int length, const int sp, const int max) { static void set_num_digits(const unsigned char source[], const int length, int *num_digits) {
int i, end; int i;
if (max && sp + max < length) { for (i = length - 1; i >= 0; i--) {
end = sp + max; if (source[i] >= '0' && source[i] <= '9') {
} else { num_digits[i] = num_digits[i + 1] + 1;
end = length;
}
for (i = sp; i < end; i++) {
if (string[i] < '0' || string[i] > '9') {
break;
} }
} }
return i - sp;
} }
/* Copy C40/TEXT/EDI triplets from buffer to target. Returns elements left in buffer (< 3) */ /* Copy C40/TEXT/EDI triplets from buffer to target. Returns elements left in buffer (< 3) */
@ -414,7 +408,7 @@ static int decimal_unlatch(char decimal_binary[24], int db_p, unsigned int targe
} }
/* Number of codewords remaining in a particular version (may be negative) */ /* Number of codewords remaining in a particular version (may be negative) */
static int codewords_remaining(struct zint_symbol *symbol, int tp) { static int codewords_remaining(struct zint_symbol *symbol, const int tp) {
int i; int i;
if (symbol->option_2 == 10) { /* Version T */ if (symbol->option_2 == 10) { /* Version T */
@ -455,7 +449,8 @@ static int c40text_cnt(const int current_mode, const int gs1, unsigned char inpu
} }
/* Copy `source` to `eci_buf` with "\NNNNNN" ECI indicator at start and backslashes escaped */ /* Copy `source` to `eci_buf` with "\NNNNNN" ECI indicator at start and backslashes escaped */
static void eci_escape(const int eci, unsigned char *source, const int length, unsigned char *eci_buf, const int eci_length) { static void eci_escape(const int eci, unsigned char *source, const int length, unsigned char *eci_buf,
const int eci_length) {
int i, j; int i, j;
j = sprintf((char *) eci_buf, "\\%06d", eci); j = sprintf((char *) eci_buf, "\\%06d", eci);
@ -482,12 +477,15 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
int eci_length = length + 7 + chr_cnt(source, length, '\\'); int eci_length = length + 7 + chr_cnt(source, length, '\\');
#ifndef _MSC_VER #ifndef _MSC_VER
unsigned char eci_buf[eci_length + 1]; unsigned char eci_buf[eci_length + 1];
int num_digits[eci_length + 1];
#else #else
unsigned char *eci_buf = (unsigned char *) _alloca(eci_length + 1); unsigned char *eci_buf = (unsigned char *) _alloca(eci_length + 1);
int *num_digits = (int *) _alloca(sizeof(int) * (eci_length + 1));
#endif #endif
sp = 0; sp = 0;
tp = 0; tp = 0;
memset(num_digits, 0, sizeof(int) * (eci_length + 1));
/* Step A */ /* Step A */
current_mode = C1_ASCII; current_mode = C1_ASCII;
@ -499,22 +497,26 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
gs1 = 0; gs1 = 0;
} }
if (gs1) { if (gs1) {
if (length >= 15 && digits_ahead(source, length, 0, 15) == 15) { set_num_digits(source, length, num_digits);
if (length >= 15 && num_digits[0] >= 15) {
target[tp++] = 236; /* FNC1 and change to Decimal */ target[tp++] = 236; /* FNC1 and change to Decimal */
next_mode = C1_DECIMAL; next_mode = C1_DECIMAL;
} else if (length >= 7 && digits_ahead(source, length, 0, 0) == length) { } else if (length >= 7 && num_digits[0] == length) {
target[tp++] = 236; /* FNC1 and change to Decimal */ target[tp++] = 236; /* FNC1 and change to Decimal */
next_mode = C1_DECIMAL; next_mode = C1_DECIMAL;
} else { } else {
target[tp++] = 232; /* FNC1 */ target[tp++] = 232; /* FNC1 */
} }
/* Note ignoring ECI if GS1 mode (up to caller to warn) */ /* Note ignoring ECI if GS1 mode (up to caller to warn) */
} else if (symbol->eci) { } else {
target[tp++] = 129; /* Pad */ if (symbol->eci) {
target[tp++] = '\\' + 1; /* Escape char */ target[tp++] = 129; /* Pad */
eci_escape(symbol->eci, source, length, eci_buf, eci_length); target[tp++] = '\\' + 1; /* Escape char */
source = eci_buf; eci_escape(symbol->eci, source, length, eci_buf, eci_length);
length = eci_length; source = eci_buf;
length = eci_length;
}
set_num_digits(source, length, num_digits);
} }
do { do {
@ -539,11 +541,11 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
/* Step B - ASCII encodation */ /* Step B - ASCII encodation */
next_mode = C1_ASCII; next_mode = C1_ASCII;
if ((length - sp) >= 21 && digits_ahead(source, length, sp, 21) == 21) { if ((length - sp) >= 21 && num_digits[sp] >= 21) {
/* Step B1 */ /* Step B1 */
next_mode = C1_DECIMAL; next_mode = C1_DECIMAL;
db_p = bin_append_posn(15, 4, decimal_binary, db_p); db_p = bin_append_posn(15, 4, decimal_binary, db_p);
} else if ((length - sp) >= 13 && digits_ahead(source, length, sp, 0) == (length - sp)) { } else if ((length - sp) >= 13 && num_digits[sp] == (length - sp)) {
/* Step B2 */ /* Step B2 */
next_mode = C1_DECIMAL; next_mode = C1_DECIMAL;
db_p = bin_append_posn(15, 4, decimal_binary, db_p); db_p = bin_append_posn(15, 4, decimal_binary, db_p);
@ -558,12 +560,12 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
sp += 2; sp += 2;
} else { } else {
if ((gs1) && (source[sp] == '[')) { if ((gs1) && (source[sp] == '[')) {
if (length - (sp + 1) >= 15 && digits_ahead(source, length, sp + 1, 15) == 15) { if (length - (sp + 1) >= 15 && num_digits[sp + 1] >= 15) {
/* Step B4 */ /* Step B4 */
target[tp++] = 236; /* FNC1 and change to Decimal */ target[tp++] = 236; /* FNC1 and change to Decimal */
sp++; sp++;
next_mode = C1_DECIMAL; next_mode = C1_DECIMAL;
} else if (length - (sp + 1) >= 7 && digits_ahead(source, length, sp + 1, 0) == length - (sp + 1)) { } else if (length - (sp + 1) >= 7 && num_digits[sp + 1] == length - (sp + 1)) {
/* Step B5 */ /* Step B5 */
target[tp++] = 236; /* FNC1 and change to Decimal */ target[tp++] = 236; /* FNC1 and change to Decimal */
sp++; sp++;
@ -602,10 +604,10 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
next_mode = current_mode; next_mode = current_mode;
if (cte_p == 0) { if (cte_p == 0) {
/* Step C/D1 */ /* Step C/D1 */
if ((length - sp) >= 12 && digits_ahead(source, length, sp, 12) == 12) { if ((length - sp) >= 12 && num_digits[sp] >= 12) {
/* Step C/D1a */ /* Step C/D1a */
next_mode = C1_ASCII; next_mode = C1_ASCII;
} else if ((length - sp) >= 8 && digits_ahead(source, length, sp, 0) == (length - sp)) { } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) {
/* Step C/D1b */ /* Step C/D1b */
next_mode = C1_ASCII; next_mode = C1_ASCII;
} else { } else {
@ -658,10 +660,10 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
next_mode = C1_EDI; next_mode = C1_EDI;
if (cte_p == 0) { if (cte_p == 0) {
/* Step E1 */ /* Step E1 */
if ((length - sp) >= 12 && digits_ahead(source, length, sp, 12) == 12) { if ((length - sp) >= 12 && num_digits[sp] >= 12) {
/* Step E1a */ /* Step E1a */
next_mode = C1_ASCII; next_mode = C1_ASCII;
} else if ((length - sp) >= 8 && digits_ahead(source, length, sp, 0) == (length - sp)) { } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) {
/* Step E1b */ /* Step E1b */
next_mode = C1_ASCII; next_mode = C1_ASCII;
} else if ((length - sp) < 3 || !isedi(source[sp]) || !isedi(source[sp + 1]) } else if ((length - sp) < 3 || !isedi(source[sp]) || !isedi(source[sp + 1])
@ -700,20 +702,17 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
} else if (current_mode == C1_DECIMAL) { } else if (current_mode == C1_DECIMAL) {
/* Step F - Decimal encodation */ /* Step F - Decimal encodation */
int decimal_count;
if (debug_print) printf("DECIMAL "); if (debug_print) printf("DECIMAL ");
next_mode = C1_DECIMAL; next_mode = C1_DECIMAL;
decimal_count = digits_ahead(source, length, sp, 3);
if (length - sp < 3) { if (length - sp < 3) {
/* Step F1 */ /* Step F1 */
int bits_left = 8 - db_p; int bits_left = 8 - db_p;
int single_ascii = bits_left == 8 && is_last_single_ascii(source, length, sp); int can_ascii = bits_left == 8 && is_last_single_ascii(source, length, sp);
if (codewords_remaining(symbol, tp) == 1 && (single_ascii || (decimal_count == 1 && bits_left >= 4))) { if (codewords_remaining(symbol, tp) == 1 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) {
if (single_ascii) { if (can_ascii) {
/* Encode last character or last 2 digits as ASCII */ /* Encode last character or last 2 digits as ASCII */
if (istwodigits(source, length, sp)) { if (istwodigits(source, length, sp)) {
target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130;
@ -732,15 +731,15 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
db_p = decimal_binary_transfer(decimal_binary, db_p, target, &tp); db_p = decimal_binary_transfer(decimal_binary, db_p, target, &tp);
} }
} else { } else {
db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, decimal_count, source, &sp); db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp);
current_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ current_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */
} }
next_mode = C1_ASCII; next_mode = C1_ASCII;
} else { } else {
if (decimal_count != 3) { if (num_digits[sp] < 3) {
/* Step F2 */ /* Step F2 */
db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, decimal_count, source, &sp); db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp);
current_mode = next_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ current_mode = next_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */
} else { } else {
/* Step F3 */ /* Step F3 */

View File

@ -2,7 +2,7 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2008 - 2020 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2008 - 2021 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
@ -31,6 +31,9 @@
*/ */
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */
#ifndef FONT_H
#define FONT_H
typedef const unsigned short font_item; typedef const unsigned short font_item;
#define NORMAL_FONT_WIDTH 7 #define NORMAL_FONT_WIDTH 7
@ -482,3 +485,5 @@ static font_item upcean_small_font[] = {
/*38*/ 0x3C, 0x7E, 0x66, 0x42, 0x66, 0x3C, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0x7E, 0x3C, /* 8 */ /*38*/ 0x3C, 0x7E, 0x66, 0x42, 0x66, 0x3C, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0x7E, 0x3C, /* 8 */
/*39*/ 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xE3, 0x7E, 0x1E, 0x0C, 0x18, 0x30, 0x60, /* 9 */ /*39*/ 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xC3, 0xE3, 0x7E, 0x1E, 0x0C, 0x18, 0x30, 0x60, /* 9 */
}; };
#endif /* FONT_H */

View File

@ -67,13 +67,21 @@ static int numeric(const unsigned char *data, int data_len, int offset, int min,
return 1; return 1;
} }
/* Validate of character set 82 (GS1 General Spec Figure 7.11-1) */ /* GS1 General Specifications 21.0.1 Figure 7.9.5-1. GS1 AI encodable character reference values.
Also used to determine if character in set 82 */
static const char c82[] = {
0, 1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, /*!-0*/
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -1, /*1-@*/
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, /*A-P*/
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -1, -1, -1, -1, 55, -1, /*Q-`*/
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /*a-p*/
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /*q-z*/
};
/* Validate of character set 82 (GS1 General Specifications Figure 7.11-1) */
static int cset82(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int cset82(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50]) { int *p_err_posn, char err_msg[50]) {
/* These 13 characters plus all <= ' ' = 13 + 33 = 46 + 82 = 128 */
static const char not_in_set82[] = "#$@[\\]^`{|}~\177";
data_len -= offset; data_len -= offset;
if (data_len < min) { if (data_len < min) {
@ -85,7 +93,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min,
const unsigned char *de = d + (data_len > max ? max : data_len); const unsigned char *de = d + (data_len > max ? max : data_len);
for (; d < de; d++) { for (; d < de; d++) {
if (*d <= ' ' || strchr(not_in_set82, *d) != NULL) { if (*d < '!' || *d > 'z' || c82[*d - '!'] == -1) {
*p_err_no = 3; *p_err_no = 3;
*p_err_posn = d - data + 1; *p_err_posn = d - data + 1;
sprintf(err_msg, "Invalid CSET 82 character '%c'", *d); sprintf(err_msg, "Invalid CSET 82 character '%c'", *d);
@ -97,7 +105,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min,
return 1; return 1;
} }
/* Validate of character set 39 (GS1 General Spec Figure 7.11-2) */ /* Validate of character set 39 (GS1 General Specifications Figure 7.11-2) */
static int cset39(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int cset39(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50]) { int *p_err_posn, char err_msg[50]) {
@ -125,7 +133,7 @@ static int cset39(const unsigned char *data, int data_len, int offset, int min,
return 1; return 1;
} }
/* Check a check digit (GS1 General Spec 7.9.1) */ /* Check a check digit (GS1 General Specifications 7.9.1) */
static int csum(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int csum(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50], const int length_only) { int *p_err_posn, char err_msg[50], const int length_only) {
@ -160,7 +168,7 @@ static int csum(const unsigned char *data, int data_len, int offset, int min, in
return 1; return 1;
} }
/* Check alphanumeric check characters (GS1 General Spec 7.9.5) */ /* Check alphanumeric check characters (GS1 General Specifications 7.9.5) */
static int csumalpha(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int csumalpha(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50], const int length_only) { int *p_err_posn, char err_msg[50], const int length_only) {
(void)max; (void)max;
@ -176,14 +184,6 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi
} }
if (!length_only && data_len) { if (!length_only && data_len) {
static const char c82[] = {
0, 1, -1, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, /*!-0*/
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, -1, /*1-@*/
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, /*A-P*/
45, 46, 47, 48, 49, 50, 51, 52, 53, 54, -1, -1, -1, -1, 55, -1, /*Q-`*/
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, /*a-p*/
72, 73, 74, 75, 76, 77, 78, 79, 80, 81, /*q-z*/
};
static const char c32[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ"; static const char c32[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
static const char weights[] = { static const char weights[] = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83
@ -215,7 +215,7 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi
return 1; return 1;
} }
/* Check for a GS1 Prefix (GS1 General Spec GS1 1.4.2) */ /* Check for a GS1 Prefix (GS1 General Specifications GS1 1.4.2) */
static int key(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int key(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50], const int length_only) { int *p_err_posn, char err_msg[50], const int length_only) {
(void)max; (void)max;
@ -278,7 +278,7 @@ static int yymmd0(const unsigned char *data, int data_len, int offset, int min,
} }
if (month == 2 && day == 29) { /* Leap year check */ if (month == 2 && day == 29) { /* Leap year check */
int year = to_int(data + offset, 2); int year = to_int(data + offset, 2);
if (year & 3) { /* Good until 2050 when 00 will mean 2100 (GS1 General Spec 7.12) */ if (year & 3) { /* Good until 2050 when 00 will mean 2100 (GS1 General Specifications 7.12) */
*p_err_no = 3; *p_err_no = 3;
*p_err_posn = offset + 4 + 1; *p_err_posn = offset + 4 + 1;
sprintf(err_msg, "Invalid day '%.2s'", data + offset + 4); sprintf(err_msg, "Invalid day '%.2s'", data + offset + 4);
@ -595,7 +595,7 @@ static int yesno(const unsigned char *data, int data_len, int offset, int min, i
return 1; return 1;
} }
/* Check for importer index (GS1 General Spec 3.8.17) */ /* Check for importer index (GS1 General Specifications 3.8.17) */
static int importeridx(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int importeridx(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50], const int length_only) { int *p_err_posn, char err_msg[50], const int length_only) {
(void)max; (void)max;
@ -645,7 +645,7 @@ static int nonzero(const unsigned char *data, int data_len, int offset, int min,
return 1; return 1;
} }
/* Check winding direction (0/1/9) (GS1 General Spec 3.9.1) */ /* Check winding direction (0/1/9) (GS1 General Specifications 3.9.1) */
static int winding(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int winding(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50], const int length_only) { int *p_err_posn, char err_msg[50], const int length_only) {
(void)max; (void)max;
@ -691,7 +691,7 @@ static int zero(const unsigned char *data, int data_len, int offset, int min, in
return 1; return 1;
} }
/* Check piece of a trade item (GS1 General Spec 3.9.6 and 3.9.17) */ /* Check piece of a trade item (GS1 General Specifications 3.9.6 and 3.9.17) */
static int pieceoftotal(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no, static int pieceoftotal(const unsigned char *data, int data_len, int offset, int min, int max, int *p_err_no,
int *p_err_posn, char err_msg[50], const int length_only) { int *p_err_posn, char err_msg[50], const int length_only) {
(void)max; (void)max;