From b40393723f9e9c17d768cdefe2ab658b85c4c447 Mon Sep 17 00:00:00 2001
From: gitlost
Date: Wed, 22 Apr 2026 21:25:16 +0100
Subject: [PATCH] AUSPOST: support Null FCC (DPID all zeroes); TODO: BWIPP
support CODE128: properly fix not switching before FNC1 in 2nd position
after alpha (commit [7b0767]) PLANET/KIX: adapt POSTNET to cater for both
general: use static strings to save a few bytes (start/stop in particular);
various other code fiddles postal: move tables into funcs
---
ChangeLog | 3 +-
backend/2of5.c | 2 +
backend/2of5inter.c | 16 +-
backend/auspost.c | 118 +++++-----
backend/bc412.c | 5 +-
backend/channel.c | 5 +-
backend/codablock.c | 3 +-
backend/code.c | 105 +++++----
backend/code128.c | 14 +-
backend/dxfilmedge.c | 7 +-
backend/gs1.c | 11 +-
backend/library.c | 9 +-
backend/mailmark.c | 5 +-
backend/plessey.c | 18 +-
backend/postal.c | 420 ++++++++++++-----------------------
backend/svg.c | 18 +-
backend/tests/test_auspost.c | 148 +++++++-----
backend/tests/test_code128.c | 1 +
backend/tests/test_postal.c | 8 +-
backend/tests/testcommon.c | 5 +
backend/upcean.c | 31 ++-
docs/manual.html | 18 +-
docs/manual.pmd | 13 +-
docs/manual.txt | 13 +-
24 files changed, 479 insertions(+), 517 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 94f1d9c1..75fae057 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,4 @@
-Version 2.16.0.9 (dev) not released yet (2026-04-18)
+Version 2.16.0.9 (dev) not released yet (2026-04-22)
====================================================
**Incompatible changes**
@@ -35,6 +35,7 @@ Changes
(`option_3 = DM_C40_START`) to allow forcing of initial encodation for given
no. (`option_1`) of initial characters, with 0 meaning all
- DATAMATRIX: add manual FNC1 support
+- AUSPOST: support Null FCC (DPID all zeroes)
Bugs
----
diff --git a/backend/2of5.c b/backend/2of5.c
index dd629c2c..8c9e9f1e 100644
--- a/backend/2of5.c
+++ b/backend/2of5.c
@@ -90,10 +90,12 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[],
d += start_length;
if (is_matrix) {
+ /* Standard, Data Logic */
for (i = 0; i < length; i++, d += 6) {
memcpy(d, C25MatrixTable[local_source[i] - '0'], 6);
}
} else {
+ /* IATA, Industrial */
for (i = 0; i < length; i++, d += 10) {
memcpy(d, C25IndustTable[local_source[i] - '0'], 10);
}
diff --git a/backend/2of5inter.c b/backend/2of5inter.c
index 7873197c..55398b53 100644
--- a/backend/2of5inter.c
+++ b/backend/2of5inter.c
@@ -36,15 +36,15 @@
#include "common.h"
#include "gs1.h"
-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'}
-};
-
/* Common to Interleaved, and to ITF-14, DP Leitcode, DP Identcode */
INTERNAL int zint_c25_inter_common(struct zint_symbol *symbol, unsigned char source[], int length,
const int checkdigit_option, const int dont_set_height) {
+ 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 const char stop_start[5] = { '3','1','1','1','1' }; /* 1st 3 stop, last 4 start */
int i, j, error_number = 0;
char dest[638]; /* 4 + (125 + 1) * 5 + 3 + 1 = 638 */
char *d = dest;
@@ -77,7 +77,7 @@ INTERNAL int zint_c25_inter_common(struct zint_symbol *symbol, unsigned char sou
}
/* Start character */
- memcpy(d, "1111", 4);
+ memcpy(d, stop_start + 1, 4);
d += 4;
for (i = 0; i < length; i += 2) {
@@ -93,7 +93,7 @@ INTERNAL int zint_c25_inter_common(struct zint_symbol *symbol, unsigned char sou
}
/* Stop character */
- memcpy(d, "311", 3);
+ memcpy(d, stop_start, 3);
d += 3;
z_expand(symbol, dest, (int) (d - dest));
diff --git a/backend/auspost.c b/backend/auspost.c
index 2d2b562d..fb679ddb 100644
--- a/backend/auspost.c
+++ b/backend/auspost.c
@@ -33,36 +33,45 @@
static const char AusGDSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #";
#define AUS_GDSET_F (IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F)
+/* The contents of data_pattern conform to the following standard:
+ 0 = Tracker, Ascender and Descender
+ 1 = Tracker and Ascender
+ 2 = Tracker and Descender
+ 3 = Tracker only */
+
+/* N Encoding Table (numeric) */
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'}
+ { 0,0 }, { 0,1 }, { 0,2 }, { 1,0 }, { 1,1 }, { 1,2 }, { 2,0 }, { 2,1 }, { 2,2 }, { 3,0 }
};
+/* C Encoding Table (GDSET) */
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'}
+ { 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 }
};
+/* Bar to Decimal Conversion Table (Reed-Solomon) */
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'}
+ { 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
@@ -71,7 +80,7 @@ static const char AusBarTable[64][3] = {
#include "reedsol.h"
static unsigned char aus_convert_pattern(const char data, const int shift) {
- return (data - '0') << shift;
+ return data << shift;
}
/* Adds Reed-Solomon error correction to auspost */
@@ -104,15 +113,15 @@ INTERNAL int zint_daft_set_height(struct zint_symbol *symbol, const float min_he
/* Handles Australia Posts's 4 State Codes */
INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], int length) {
- /* Customer Standard Barcode, Barcode 2 or Barcode 3 system determined automatically
- (i.e. the FCC doesn't need to be specified by the user) dependent
+ /* Standard Customer Barcode, Customer Barcode 2 or Customer Barcode 3 system determined automatically
+ (i.e. the Format Control Code (FCC) doesn't need to be specified by the user) dependent
on the length of the input string */
+ static const unsigned char fccs[7][2] = {
+ /* Null Standard Barcode 2 Barcode 3 Reply Route Redirect */
+ { '0','0' }, { '1','1' }, { '5','9' }, { '6','2' }, { '4','5' }, { '8','7' }, { '9','2' }
+ };
+ static const char start_stop[2] = { 1,3 };
- /* The contents of data_pattern conform to the following standard:
- 0 = Tracker, Ascender and Descender
- 1 = Tracker and Ascender
- 2 = Tracker and Descender
- 3 = Tracker only */
int i;
int error_number;
int writer;
@@ -121,7 +130,7 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
char data_pattern[200];
char *d = data_pattern;
- unsigned char fcc[2] = {0}; /* Suppress clang-tidy warning clang-analyzer-core.UndefinedBinaryOperatorResult */
+ int fcc_idx; /* Index into `fccs[]` */
unsigned char local_source[30];
int zeroes = 0;
const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
@@ -150,13 +159,13 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
/* Format control code (FCC) */
switch (length) {
case 8:
- memcpy(fcc, "11", 2);
+ fcc_idx = 1; /* FCC 11 Standard Customer */
break;
case 13:
- memcpy(fcc, "59", 2);
+ fcc_idx = 2; /* FCC 59 Customer 2 */
break;
case 16:
- memcpy(fcc, "59", 2);
+ fcc_idx = 2; /* FCC 59 Customer 2 */
if ((i = z_not_sane(NEON_F, source, length))) {
return z_errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 402,
"Invalid character at position %d in input (digits only for FCC 59 length 16)",
@@ -164,10 +173,10 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
}
break;
case 18:
- memcpy(fcc, "62", 2);
+ fcc_idx = 3; /* FCC 62 Customer 3 */
break;
case 23:
- memcpy(fcc, "62", 2);
+ fcc_idx = 3; /* FCC 62 Customer 3 */
if ((i = z_not_sane(NEON_F, source, length))) {
return z_errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 406,
"Invalid character at position %d in input (digits only for FCC 62 length 23)",
@@ -175,12 +184,13 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
}
break;
}
- } else {
- switch (symbol->symbology) {
- case BARCODE_AUSREPLY: memcpy(fcc, "45", 2); break;
- case BARCODE_AUSROUTE: memcpy(fcc, "87", 2); break;
- case BARCODE_AUSREDIRECT: memcpy(fcc, "92", 2); break;
+ /* Check if DPID all zeros (Null) */
+ for (i = 0; i < 8 && source[i] == '0'; i++);
+ if (i == 8) {
+ fcc_idx = 0; /* Null */
}
+ } else {
+ fcc_idx = symbol->symbology - BARCODE_AUSREPLY + 4; /* 4 (FCC 45), 5 (FCC 87) or 6 (FCC 92) */
/* Add leading zeros as required */
zeroes = 8 - length;
@@ -188,7 +198,7 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
}
if (symbol->debug & ZINT_DEBUG_PRINT) {
- printf("AUSPOST FCC: %.2s\n", fcc);
+ printf("AUSPOST FCC: %.2s\n", fccs[fcc_idx]);
}
memcpy(local_source + zeroes, source, length);
@@ -201,12 +211,12 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
}
/* Start character */
- memcpy(d, "13", 2);
+ memcpy(d, start_stop, 2);
d += 2;
/* Encode the FCC */
for (reader = 0; reader < 2; reader++, d += 2) {
- memcpy(d, AusNTable[fcc[reader] - '0'], 2);
+ memcpy(d, AusNTable[fccs[fcc_idx][reader] - '0'], 2);
}
/* Delivery Point Identifier (DPID) */
@@ -233,7 +243,7 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
case 22:
case 37:
case 52:
- *d++ = '3';
+ *d++ = 3;
break;
default:
break;
@@ -243,22 +253,22 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
d = aus_rs_error(data_pattern, d);
/* Stop character */
- memcpy(d, "13", 2);
+ memcpy(d, start_stop, 2);
d += 2;
/* Turn the symbol into a bar pattern ready for plotting */
- writer = 0;
h = (int) (d - data_pattern);
- for (loopey = 0; loopey < h; loopey++) {
- if (data_pattern[loopey] == '1' || data_pattern[loopey] == '0') {
+ for (loopey = 0, writer = 0; loopey < h; loopey++, writer += 2) {
+ if (data_pattern[loopey] == 1 || data_pattern[loopey] == 0) {
z_set_module(symbol, 0, writer);
}
z_set_module(symbol, 1, writer);
- if (data_pattern[loopey] == '2' || data_pattern[loopey] == '0') {
+ if (data_pattern[loopey] == 2 || data_pattern[loopey] == 0) {
z_set_module(symbol, 2, writer);
}
- writer += 2;
}
+ symbol->rows = 3; /* Not stackable */
+ symbol->width = writer - 1;
if (symbol->output_options & COMPLIANT_HEIGHT) {
/* Australia Post Customer Barcoding Technical Specifications (Revised Aug 2012) Dimensions, placement and
@@ -278,10 +288,8 @@ INTERNAL int zint_auspost(struct zint_symbol *symbol, unsigned char source[], in
symbol->row_height[1] = 2.0f;
error_number = zint_daft_set_height(symbol, 0.0f, 0.0f);
}
- symbol->rows = 3; /* Not stackable */
- symbol->width = writer - 1;
- if (content_segs && z_ct_cpy_cat(symbol, fcc, 2, '\xFF' /*separator (none)*/, local_source, length)) {
+ if (content_segs && z_ct_cpy_cat(symbol, fccs[fcc_idx], 2, '\xFF' /*separator (none)*/, local_source, length)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy_cat()` only fails with OOM */
}
diff --git a/backend/bc412.c b/backend/bc412.c
index 1e3c8e36..2265c8ef 100644
--- a/backend/bc412.c
+++ b/backend/bc412.c
@@ -66,6 +66,7 @@ static const char BC412Table[35][8] = {
};
INTERNAL int zint_bc412(struct zint_symbol *symbol, unsigned char source[], int length) { /* IBM BC412 */
+ static const char stop_start[4] = { '1','1','1','2' }; /* 1st 3 stop, last 2 start */
unsigned char padded_source[20];
int posns[35];
int i, counter_odd = 0, counter_even = 0, check_sum = 0;
@@ -119,7 +120,7 @@ INTERNAL int zint_bc412(struct zint_symbol *symbol, unsigned char source[], int
posns[1] = check_sum;
/* Start character */
- memcpy(d, "12", 2);
+ memcpy(d, stop_start + 2, 2);
d += 2;
for (i = 0; i <= length; i++, d += 8) {
@@ -127,7 +128,7 @@ INTERNAL int zint_bc412(struct zint_symbol *symbol, unsigned char source[], int
}
/* Stop character */
- memcpy(d, "111", 3);
+ memcpy(d, stop_start, 3);
d += 3;
z_expand(symbol, dest, (int) (d - dest));
diff --git a/backend/channel.c b/backend/channel.c
index 0e3995e7..62560ccf 100644
--- a/backend/channel.c
+++ b/backend/channel.c
@@ -175,7 +175,8 @@ nb0: if (++B[0] <= bmax[0]) goto lb0;
/* Channel Code - According to ANSI/AIM BC12-1998 */
INTERNAL int zint_channel(struct zint_symbol *symbol, unsigned char source[], int length) {
static const int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 };
- static const unsigned char zeroes_str[] = "0000000"; /* 7 zeroes */
+ static const unsigned char zeroes_str[7] = { '0','0','0','0','0','0','0' };
+ static const char finder_pattern[9] = { '1','1','1','1','1','1','1','1','1' };
int S[8] = {0}, B[8] = {0};
int target_value;
char dest[30];
@@ -233,7 +234,7 @@ INTERNAL int zint_channel(struct zint_symbol *symbol, unsigned char source[], in
CHNCHR(channels, target_value, B, S);
- memcpy(d, "111111111", 9); /* Finder pattern */
+ memcpy(d, finder_pattern, 9); /* Finder pattern */
d += 9;
for (i = 8 - channels; i < 8; i++) {
*d++ = z_itoc(S[i]);
diff --git a/backend/codablock.c b/backend/codablock.c
index ff7fe429..43beae8f 100644
--- a/backend/codablock.c
+++ b/backend/codablock.c
@@ -535,6 +535,7 @@ static void SumASCII(uchar **ppOutPos, const int Sum, const int CharacterSet) {
/* Main function called by zint framework
*/
INTERNAL int zint_codablockf(struct zint_symbol *symbol, unsigned char source[], int length) {
+ static const char stop[7] = { '2','3','3','1','1','1','2' }; /* Stop character */
int charCur, dataLength;
int error_number;
int rows, columns, useColumns;
@@ -859,7 +860,7 @@ INTERNAL int zint_codablockf(struct zint_symbol *symbol, unsigned char source[],
for (c = 0; c < columns - 1; c++, d += 6) {
memcpy(d, zint_C128Table[pOutput[rc + c]], 6);
}
- memcpy(d, "2331112", 7); /* Stop character (106, not in `zint_C128Table[]`) */
+ memcpy(d, stop, 7); /* Stop character (106, not in `zint_C128Table[]`) */
d += 7;
z_expand(symbol, dest, (int) (d - dest));
}
diff --git a/backend/code.c b/backend/code.c
index af46fff3..46ae849b 100644
--- a/backend/code.c
+++ b/backend/code.c
@@ -1,4 +1,4 @@
-/* code.c - Handles Code 39, 39+, 93 and VIN */
+/* code.c - Handles Code 39 (incl. LOGMARS & HIBC), Extended Code 39 (39+), Code 93 and VIN */
/*
libzint - the open source barcode library
Copyright (C) 2008-2026 Robin Stuart
@@ -68,56 +68,6 @@ static const char C39Table[43 + 1][10] = {
{'1','2','1','1','2','1','2','1','1','1'} /* Start character (full 10), Stop character (first 9) */
};
-/* Encoding the full ASCII character set in Code 39 (ISO/IEC 16388:2007 Table A.2) */
-static const char EC39Ctrl[128][2] = {
- {'%','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'}
-};
-
-/* Code 93 ANSI/AIM BC5-1995 Table 3 */
-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'}
-};
-
-/* Code 93 ANSI/AIM BC5-1995 Table 2 */
-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 39 */
INTERNAL int zint_code39(struct zint_symbol *symbol, unsigned char source[], int length) {
int i;
@@ -239,6 +189,22 @@ INTERNAL int zint_code39(struct zint_symbol *symbol, unsigned char source[], int
/* Extended Code 39 - ISO/IEC 16388:2007 Annex A */
INTERNAL int zint_excode39(struct zint_symbol *symbol, unsigned char source[], int length) {
+ /* Encoding the full ASCII character set in Code 39 (ISO/IEC 16388:2007 Table A.2) */
+ static const char EC39Ctrl[128][2] = {
+ {'%','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'}
+ };
int i;
unsigned char buffer[86 * 2 + 1] = {0};
unsigned char *b = buffer;
@@ -308,11 +274,42 @@ INTERNAL int zint_excode39(struct zint_symbol *symbol, unsigned char source[], i
/* Code 93 is an advancement on Code 39 and the definition is a lot tighter */
INTERNAL int zint_code93(struct zint_symbol *symbol, unsigned char source[], int length) {
+ /* Code 93 ANSI/AIM BC5-1995 Table 2 */
+ 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 93 ANSI/AIM BC5-1995 Table 3 */
+ 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 start_stop[7] = { '1','1','1','1','4','1','1' }; /* 1st 6 start, all 7 stop */
/* SILVER includes the extra characters a, b, c and d to represent Code 93 specific
shift characters 1, 2, 3 and 4 respectively. These characters are never used by
`zint_code39()` and `excode39()` */
-
int i;
int h, weight, c, k, error_number = 0;
int values[125]; /* 123 + 2 (Checks) */
@@ -383,7 +380,7 @@ INTERNAL int zint_code93(struct zint_symbol *symbol, unsigned char source[], int
}
/* Start character */
- memcpy(d, "111141", 6);
+ memcpy(d, start_stop, 6);
d += 6;
for (i = 0; i < h; i++, d += 6) {
@@ -391,7 +388,7 @@ INTERNAL int zint_code93(struct zint_symbol *symbol, unsigned char source[], int
}
/* Stop character */
- memcpy(d, "1111411", 7);
+ memcpy(d, start_stop, 7);
d += 7;
z_expand(symbol, dest, (int) (d - dest));
diff --git a/backend/code128.c b/backend/code128.c
index 18df937c..b9229380 100644
--- a/backend/code128.c
+++ b/backend/code128.c
@@ -158,7 +158,8 @@ static int c128_cost(const unsigned char source[], const int length, const int i
const unsigned char ch = source[i];
const char *const latch_len = prior_cset == 0 ? c128_start_latch_len[start_idx] : c128_latch_len[prior_cset];
const int is_fnc1 = ch == '\x1D' && fncs[i];
- const int can_c = is_fnc1 || (z_isdigit(ch) && z_isdigit(source[i + 1])); /* Assumes source NUL-terminated */
+ const int can_c = is_fnc1 ? i != 1 || !z_isalpha(source[0]) /* Don't use C if FNC1 in 2nd position after alpha */
+ : (z_isdigit(ch) && z_isdigit(source[i + 1])); /* Assumes source NUL-terminated */
const int manual_c_fail = !can_c && manuals[i] == C128_C0; /* C requested but not doable */
int min_cost = 999999; /* Max possible cost less than 2 * 256 */
int min_mode = 0;
@@ -247,14 +248,6 @@ static int c128_set_values(const unsigned char source[], const int length, const
*p_first_cset = modes[0][0];
}
- /* Make sure FNC1 in 2nd position after single alpha does not switch modes before FNC1 */
- if (length > 1 && !fncs[0] && fncs[1] && z_isalpha(source[0])) {
- const int mode = modes[0][0];
- if (mode == (mode & 0x0F) && mode != modes[1][mode]) {
- modes[1][mode] = mode;
- }
- }
-
/* Output codewords into `values` */
for (i = 0; i < length; i++) {
const unsigned char ch = source[i];
@@ -309,6 +302,7 @@ static int c128_set_values(const unsigned char source[], const int length, const
/* Helper to write out symbol, calculating check digit */
static void c128_expand(struct zint_symbol *symbol, int values[C128_VALUES_MAX], int glyph_count) {
+ static const char stop[7] = { '2','3','3','1','1','1','2' };
char dest[640]; /* (102 + 1 (check digit)) * 6 + 7 (Stop) = 625 */
char *d = dest;
int total_sum;
@@ -329,7 +323,7 @@ static void c128_expand(struct zint_symbol *symbol, int values[C128_VALUES_MAX],
values[glyph_count++] = total_sum; /* For debug/test */
/* Stop character */
- memcpy(d, "2331112", 7);
+ memcpy(d, stop, 7);
d += 7;
values[glyph_count++] = 106; /* For debug/test */
diff --git a/backend/dxfilmedge.c b/backend/dxfilmedge.c
index 1b4de78e..ad3e2844 100644
--- a/backend/dxfilmedge.c
+++ b/backend/dxfilmedge.c
@@ -1,7 +1,7 @@
/* dxfilmedge.c - Handles DX Film Edge symbology */
/*
libzint - the open source barcode library
- Copyright (C) 2024-2025 Antoine Merino
+ Copyright (C) 2024-2026 Antoine Merino
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -54,6 +54,7 @@
static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source, const int length,
char *binary_output, int *output_length, int *has_frame_info) {
+ static const char start_stop[6] = { '1','0','1','0','1','0' }; /* All 6 start, middle 4 stop */
int i;
int parity_bit = 0;
int dx_code_1 = -1, dx_code_2 = -1, frame_number = -1;
@@ -209,7 +210,7 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source
}
/* Build the binary output */
- memcpy(binary_output, "101010", 6); /* Start pattern */
+ memcpy(binary_output, start_stop, 6); /* Start pattern */
bp = z_bin_append_posn(dx_code_1, 7, binary_output, 6);
binary_output[bp++] = '0'; /* Separator between DX part 1 and DX part 2 */
bp = z_bin_append_posn(dx_code_2, 4, binary_output, bp);
@@ -242,7 +243,7 @@ static int dx_parse_code(struct zint_symbol *symbol, const unsigned char *source
}
binary_output[bp++] = parity_bit ? '1' : '0';
- memcpy(binary_output + bp, "0101", 4); /* Stop pattern */
+ memcpy(binary_output + bp, start_stop + 1, 4); /* Stop pattern */
bp += 4;
*output_length = bp;
diff --git a/backend/gs1.c b/backend/gs1.c
index 685b378a..d77136f0 100644
--- a/backend/gs1.c
+++ b/backend/gs1.c
@@ -1671,9 +1671,14 @@ static void gs1se_gs_caret_sub(const unsigned char *src, const int length, unsig
/* Use GS1 Syntax Engine to verify */
static int gs1se_verify(struct zint_symbol *symbol, const unsigned char source[], const int length,
unsigned char reduced[], int *p_reduced_length) {
+ static const char linear_dummies[3][19] = {
+ { '[','0','1',']','1','2','3','4','5','6','7','8','9','0','1','2','3','1','|' }, /* Normal */
+ { '(','0','1',')','1','2','3','4','5','6','7','8','9','0','1','2','3','1','|' }, /* Parens */
+ { '^','0','1','1','2','3','4','5','6','7','8','9','0','1','2','3','1','|','^' }, /* Raw/caret */
+ };
int i, j;
const int primary_len = z_is_composite(symbol->symbology) ? (int) strlen(symbol->primary) : 0;
- const int gs1parens_mode = symbol->input_mode & GS1PARENS_MODE;
+ const int gs1parens_mode = !!(symbol->input_mode & GS1PARENS_MODE);
const int gs1raw_mode = !!(symbol->input_mode & GS1RAW_MODE);
const int gs1_caret = source[0] == '^';
const int is_digital_link = !primary_len && !gs1_caret && gs1_is_digital_link(source, length);
@@ -1742,7 +1747,7 @@ static int gs1se_verify(struct zint_symbol *symbol, const unsigned char source[]
} else {
/* Just use dummy "01" linear */
if (gs1_caret || gs1raw_mode) {
- memcpy(local_source_buf, "^0112345678901231|^", 18 + gs1raw_mode);
+ memcpy(local_source_buf, linear_dummies[2], 18 + gs1raw_mode);
if (gs1_caret) {
memcpy(local_source_buf + 18, source, length + 1); /* Include terminating NUL */
} else {
@@ -1750,7 +1755,7 @@ static int gs1se_verify(struct zint_symbol *symbol, const unsigned char source[]
}
local_length += 18 + gs1raw_mode;
} else {
- memcpy(local_source_buf, gs1parens_mode ? "(01)12345678901231|" : "[01]12345678901231|", 19);
+ memcpy(local_source_buf, linear_dummies[gs1parens_mode], 19);
memcpy(local_source_buf + 19, source, length + 1); /* Include terminating NUL */
local_length += 19;
}
diff --git a/backend/library.c b/backend/library.c
index c8626e8b..48feefb1 100644
--- a/backend/library.c
+++ b/backend/library.c
@@ -213,13 +213,11 @@ INTERNAL LIB_DECL_FUNC_SRC(zint_codablockf); /* Codablock */
INTERNAL LIB_DECL_FUNC_SRC(zint_nve18); /* NVE-18 */
INTERNAL LIB_DECL_FUNC_SRC(zint_japanpost); /* Japanese Post */
INTERNAL LIB_DECL_FUNC_SRC(zint_koreapost); /* Korea Post */
-INTERNAL LIB_DECL_FUNC_SRC(zint_planet); /* PLANET */
INTERNAL LIB_DECL_FUNC_SEG(zint_micropdf417); /* Micro PDF417 */
INTERNAL LIB_DECL_FUNC_SRC(zint_usps_imail); /* Intelligent Mail (aka USPS OneCode) */
INTERNAL LIB_DECL_FUNC_SRC(zint_plessey); /* Plessey Code */
INTERNAL LIB_DECL_FUNC_SRC(zint_telepen_num); /* Telepen Numeric */
INTERNAL LIB_DECL_FUNC_SRC(zint_itf14); /* ITF-14 */
-INTERNAL LIB_DECL_FUNC_SRC(zint_kix); /* TNT KIX Code */
INTERNAL LIB_DECL_FUNC_SEG(zint_aztec); /* Aztec Code */
INTERNAL LIB_DECL_FUNC_SRC(zint_daft); /* DAFT Code */
INTERNAL LIB_DECL_FUNC_SRC(zint_dpd); /* DPD Code */
@@ -531,9 +529,9 @@ static const barcode_src_func_t barcode_src_funcs[BARCODE_LAST + 1] = {
NULL, zint_auspost, zint_auspost, zint_auspost, zint_eanx, /*65-69*/
zint_rm4scc, NULL, zint_ean14, zint_vin, zint_codablockf, /*70-74*/
zint_nve18, zint_japanpost, zint_koreapost, NULL, zint_dbar_omn, /*75-79*/
- zint_dbar_omn, zint_dbar_exp, zint_planet, NULL, NULL, /*80-84*/
+ zint_dbar_omn, zint_dbar_exp, zint_postnet, NULL, NULL, /*80-84*/
zint_usps_imail, zint_plessey, zint_telepen_num, NULL, zint_itf14, /*85-89*/
- zint_kix, NULL, NULL, zint_daft, NULL, /*90-94*/
+ zint_rm4scc, NULL, NULL, zint_daft, NULL, /*90-94*/
NULL, zint_dpd, zint_microqr, NULL, NULL, /*95-99*/
NULL, NULL, NULL, NULL, NULL, /*100-104*/
NULL, NULL, NULL, NULL, NULL, /*105-109*/
@@ -1746,6 +1744,7 @@ int ZBarcode_BarcodeName(int symbol_id, char name[32]) {
"CHANNEL", "CODEONE", "GRIDMATRIX", "UPNQR", "ULTRA", /*140-144*/
"RMQR", "BC412", "DXFILMEDGE", "EAN8_CC", "EAN13_CC", /*145-149*/
};
+ static const char barcode_prefix[8] = { 'B','A','R','C','O','D','E','_' };
name[0] = '\0';
@@ -1754,7 +1753,7 @@ int ZBarcode_BarcodeName(int symbol_id, char name[32]) {
}
assert(symbol_id >= 0 && symbol_id < ARRAY_SIZE(names) && names[symbol_id][0]);
- memcpy(name, "BARCODE_", 8);
+ memcpy(name, barcode_prefix, 8);
memcpy(name + 8, names[symbol_id], strlen(names[symbol_id]) + 1); /* Include terminating NUL */
return 0;
diff --git a/backend/mailmark.c b/backend/mailmark.c
index cc91a4e3..b6cb420d 100644
--- a/backend/mailmark.c
+++ b/backend/mailmark.c
@@ -514,6 +514,7 @@ INTERNAL int zint_datamatrix(struct zint_symbol *symbol, struct zint_seg segs[],
/* https://www.royalmailtechnical.com/rmt_docs/User_Guides_2021/Mailmark_Barcode_definition_document_20210215.pdf */
INTERNAL int zint_mailmark_2d(struct zint_symbol *symbol, unsigned char source[], int length) {
static const char spaces[9] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };
+ static const char jgb_prefix[4] = { 'J','G','B',' ' };
unsigned char local_source[90 + 1];
char postcode[10];
int i;
@@ -531,11 +532,11 @@ INTERNAL int zint_mailmark_2d(struct zint_symbol *symbol, unsigned char source[]
/* Add prefix if missing */
memcpy(local_source, source, 4);
z_to_upper(local_source, 3);
- if (memcmp(local_source, "JGB ", 4) != 0) {
+ if (memcmp(local_source, jgb_prefix, 4) != 0) {
if (length > 86) {
return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 861, "Input length %d too long (maximum 86)", length);
}
- memcpy(local_source, "JGB ", 4);
+ memcpy(local_source, jgb_prefix, 4);
memcpy(local_source + 4, source, length);
length += 4;
} else {
diff --git a/backend/plessey.c b/backend/plessey.c
index 9b411ba9..8fa5f75f 100644
--- a/backend/plessey.c
+++ b/backend/plessey.c
@@ -54,10 +54,13 @@ static const char MSITable[10][8] = {
/* Not MSI/Plessey but the older Plessey standard */
INTERNAL int zint_plessey(struct zint_symbol *symbol, unsigned char source[], int length) {
+ static const char grid[9] = { 1, 1, 1, 1, 0, 1, 0, 0, 1 };
+ static const char start[8] = { '3','1','3','1','1','3','3','1' };
+ static const char stop[9] = { '3','3','1','3','1','1','3','1','3' };
+ static const char checks[3] = { '1','3','1' }; /* Case 0 1st 2, case 1 2nd 2 */
int i;
unsigned char checkptr[67 * 4 + 8] = {0};
- static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1};
char dest[570]; /* 8 + 67 * 8 + 2 * 8 + 9 + 1 = 570 */
char *d = dest;
unsigned int check_digits = 0;
@@ -74,7 +77,7 @@ INTERNAL int zint_plessey(struct zint_symbol *symbol, unsigned char source[], in
}
/* Start character */
- memcpy(d, "31311331", 8);
+ memcpy(d, start, 8);
d += 8;
/* Data area */
@@ -101,11 +104,11 @@ INTERNAL int zint_plessey(struct zint_symbol *symbol, unsigned char source[], in
for (i = 0; i < 8; i++) {
switch (checkptr[length * 4 + i]) {
case 0:
- memcpy(d, "13", 2);
+ memcpy(d, checks, 2);
d += 2;
break;
case 1:
- memcpy(d, "31", 2);
+ memcpy(d, checks + 1, 2);
d += 2;
check_digits |= (1 << i);
break;
@@ -113,7 +116,7 @@ INTERNAL int zint_plessey(struct zint_symbol *symbol, unsigned char source[], in
}
/* Stop character */
- memcpy(d, "331311313", 9);
+ memcpy(d, stop, 9);
d += 9;
z_expand(symbol, dest, (int) (d - dest));
@@ -327,6 +330,7 @@ static char *msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char
}
INTERNAL int zint_msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) {
+ static const char stop_start[3] = { '1','2','1' }; /* All 3 stop, last 2 start */
int error_number = 0;
int i;
char dest[766]; /* 2 + 92 * 8 + 3 * 8 + 3 + 1 = 766 */
@@ -354,7 +358,7 @@ INTERNAL int zint_msi_plessey(struct zint_symbol *symbol, unsigned char source[]
}
/* Start character */
- memcpy(d, "21", 2);
+ memcpy(d, stop_start + 1, 2);
d += 2;
switch (check_option) {
@@ -372,7 +376,7 @@ INTERNAL int zint_msi_plessey(struct zint_symbol *symbol, unsigned char source[]
}
/* Stop character */
- memcpy(d, "121", 3);
+ memcpy(d, stop_start, 3);
d += 3;
z_expand(symbol, dest, (int) (d - dest));
diff --git a/backend/postal.c b/backend/postal.c
index 4fd0361b..5962428b 100644
--- a/backend/postal.c
+++ b/backend/postal.c
@@ -40,54 +40,6 @@ 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][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][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][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][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][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][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][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/CEPNet codes, maintaining ratio */
static int usps_set_height(struct zint_symbol *symbol, const int no_errtxt) {
/* USPS Domestic Mail Manual (USPS DMM 300) Jan 8, 2006 (updated 2011) 708.4.2.5 POSTNET Barcode Dimensions and
@@ -133,14 +85,26 @@ static int usps_set_height(struct zint_symbol *symbol, const int no_errtxt) {
return error_number;
}
-/* Handles the POSTNET system used for Zip codes in the US */
-/* Also handles Brazilian CEPNet - more information CEPNet e Código Bidimensional Datamatrix 2D (26/05/2021) at
+/* Handles the POSTNET system for delivering mail by ZIP codes in the US */
+/* Also handles PLANET, used to tag outgoing/return mail & identify sender */
+/* Also handles Brazilian CEPNet (ZIP-like) - more info CEPNet e Código Bidimensional Datamatrix 2D (26/05/2021) at
https://www.correios.com.br/enviar/correspondencia/arquivos/nacional/
guia-tecnico-cepnet-e-2d-triagem-enderecamento-27-04-2021.pdf/view
*/
-static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[], char *d, const int length) {
+INTERNAL int zint_postnet(struct zint_symbol *symbol, unsigned char source[], int length) {
+ /* For POSTNET/CEPNet 1 is ascender and 0 is tracker, vice versa for PLANET */
+ static const char POSTNET_PLANET[10][5] = {
+ { 1,1,0,0,0 }, { 0,0,0,1,1 }, { 0,0,1,0,1 }, { 0,0,1,1,0 }, { 0,1,0,0,1 },
+ { 0,1,0,1,0 }, { 0,1,1,0,0 }, { 1,0,0,0,1 }, { 1,0,0,1,0 }, { 1,0,1,0,0 }
+ };
+ /* Suppress clang-tidy-20 garbage value false positive by initializing (see "vector.c" `vection_add_rect()`) */
+ char dest[256] = {0}; /* 5 + 38 * 5 + 5 + 5 + 1 = 206 */
+ char *d = dest;
+ unsigned int loopey, h;
+ int writer;
+ int error_number = 0, warn_number;
int i, sum, check_digit;
- int error_number = 0;
+ const int ascender = symbol->symbology != BARCODE_PLANET; /* PLANET uses 0 for ascender, 1 for tracker */
const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
if (length > 38) {
@@ -148,11 +112,19 @@ static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[],
}
if (symbol->symbology == BARCODE_CEPNET) {
+ /* 5 (area) + 3 (+location within area) */
if (length != 8) {
error_number = z_errtxtf(ZINT_WARN_NONCOMPLIANT, symbol, 780,
"Input length %d wrong (should be 8 digits)", length);
}
+ } else if (symbol->symbology == BARCODE_PLANET) {
+ /* 2 (delivery/return) + 9 or 11 (identification) */
+ if (length != 11 && length != 13) {
+ error_number = z_errtxtf(ZINT_WARN_NONCOMPLIANT, symbol, 478,
+ "Input length %d is not standard (should be 11 or 13 digits)", length);
+ }
} else {
+ /* 5 ZIP (area), 9 ZIP+4 (+location within area), 11 ZIP+6 (+delivery point barcode) */
if (length != 5 && length != 9 && length != 11) {
error_number = z_errtxtf(ZINT_WARN_NONCOMPLIANT, symbol, 479,
"Input length %d is not standard (should be 5, 9 or 11 digits)", length);
@@ -162,137 +134,53 @@ static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[],
return z_errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 481,
"Invalid character at position %d in input (digits only)", i);
}
- sum = 0;
/* Start character */
- *d++ = 'L';
+ *d++ = ascender;
+ sum = 0;
for (i = 0; i < length; i++, d += 5) {
const int val = source[i] - '0';
- memcpy(d, PNTable[val], 5);
+ memcpy(d, POSTNET_PLANET[val], 5);
sum += val;
}
check_digit = (10 - (sum % 10)) % 10;
- memcpy(d, PNTable[check_digit], 5);
+ memcpy(d, POSTNET_PLANET[check_digit], 5);
d += 5;
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit);
/* Stop character */
- memcpy(d, "L", 2); /* Include terminating NUL */
+ *d++ = ascender;
- if (content_segs && z_ct_cpy_cat(symbol, source, length, (char) z_itoc(check_digit), NULL /*cat*/, 0)) {
- return ZINT_ERROR_MEMORY; /* `z_ct_cpy_cat()` only fails with OOM */
- }
-
- return error_number;
-}
-
-/* Puts POSTNET barcodes into the pattern matrix */
-INTERNAL int zint_postnet(struct zint_symbol *symbol, unsigned char source[], int length) {
- /* Suppress clang-tidy-20 garbage value false positive by initializing (see "vector.c" `vection_add_rect()`) */
- char height_pattern[256] = {0}; /* 5 + 38 * 5 + 5 + 5 + 1 = 206 */
- unsigned int loopey, h;
- int writer;
- int error_number, warn_number;
-
- error_number = postnet_enc(symbol, source, height_pattern, length);
- if (error_number >= ZINT_ERROR) {
- return error_number;
- }
-
- writer = 0;
- h = (int) strlen(height_pattern);
- for (loopey = 0; loopey < h; loopey++) {
- if (height_pattern[loopey] == 'L') {
+ h = d - dest;
+ for (loopey = 0, writer = 0; loopey < h; loopey++, writer += 2) {
+ if (dest[loopey] == ascender) {
z_set_module(symbol, 0, writer);
}
- z_set_module(symbol, 1, writer);
- writer += 2;
+ z_set_module(symbol, 1, writer); /* Tracker */
}
warn_number = usps_set_height(symbol, error_number /*no_errtxt*/);
symbol->rows = 2;
symbol->width = writer - 1;
- return error_number ? error_number : warn_number;
-}
-
-/* Handles the PLANET system used for item tracking in the US */
-static int planet_enc(struct zint_symbol *symbol, const unsigned char source[], char *d, const int length) {
- int i, sum, check_digit;
- int error_number = 0;
- const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
-
- if (length > 38) {
- return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 482, "Input length %d too long (maximum 38)", length);
- }
- if (length != 11 && length != 13) {
- error_number = z_errtxtf(ZINT_WARN_NONCOMPLIANT, symbol, 478,
- "Input length %d is not standard (should be 11 or 13 digits)", length);
- }
- if ((i = z_not_sane(NEON_F, source, length))) {
- return z_errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 483,
- "Invalid character at position %d in input (digits only)", i);
- }
- sum = 0;
-
- /* Start character */
- *d++ = 'L';
-
- 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;
- memcpy(d, PLTable[check_digit], 5);
- d += 5;
-
- if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit);
-
- /* Stop character */
- memcpy(d, "L", 2); /* Include terminating NUL */
-
if (content_segs && z_ct_cpy_cat(symbol, source, length, (char) z_itoc(check_digit), NULL /*cat*/, 0)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy_cat()` only fails with OOM */
}
- return error_number;
-}
-
-/* Puts PLANET barcodes into the pattern matrix */
-INTERNAL int zint_planet(struct zint_symbol *symbol, unsigned char source[], int length) {
- /* Suppress clang-tidy-20 garbage value false positive by initializing (see "vector.c" `vection_add_rect()`) */
- char height_pattern[256] = {0}; /* 5 + 38 * 5 + 5 + 5 + 1 = 206 */
- unsigned int loopey, h;
- int writer;
- int error_number, warn_number;
-
- error_number = planet_enc(symbol, source, height_pattern, length);
- if (error_number >= ZINT_ERROR) {
- return error_number;
- }
-
- writer = 0;
- h = (int) strlen(height_pattern);
- for (loopey = 0; loopey < h; loopey++) {
- if (height_pattern[loopey] == 'L') {
- z_set_module(symbol, 0, writer);
- }
- z_set_module(symbol, 1, writer);
- writer += 2;
- }
- warn_number = usps_set_height(symbol, error_number /*no_errtxt*/);
- symbol->rows = 2;
- symbol->width = writer - 1;
-
return error_number ? error_number : warn_number;
}
/* Korean Postal Authority */
INTERNAL int zint_koreapost(struct zint_symbol *symbol, unsigned char source[], int length) {
+ 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" }
+ };
int total, i, check, zeroes, error_number = 0;
unsigned char local_source[8];
char dest[80];
@@ -346,6 +234,11 @@ INTERNAL int zint_koreapost(struct zint_symbol *symbol, unsigned char source[],
/* The simplest barcode symbology ever! Supported by MS Word, so here it is!
glyphs from http://en.wikipedia.org/wiki/Facing_Identification_Mark */
INTERNAL int zint_fim(struct zint_symbol *symbol, unsigned char source[], int length) {
+ static const char a[9] = { '1','1','1','5','1','5','1','1','1' };
+ static const char b[11] = { '1','3','1','1','1','3','1','1','1','3','1' };
+ static const char c[11] = { '1','1','1','3','1','3','1','3','1','1','1' };
+ static const char d[13] = { '1','1','1','1','1','3','1','3','1','1','1','1','1' };
+ static const char e[7] = { '1','3','1','7','1','3','1' };
int error_number = 0;
const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
@@ -357,19 +250,19 @@ INTERNAL int zint_fim(struct zint_symbol *symbol, unsigned char source[], int le
switch ((char) source[0]) {
case 'A':
- z_expand(symbol, "111515111", 9);
+ z_expand(symbol, a, 9);
break;
case 'B':
- z_expand(symbol, "13111311131", 11);
+ z_expand(symbol, b, 11);
break;
case 'C':
- z_expand(symbol, "11131313111", 11);
+ z_expand(symbol, c, 11);
break;
case 'D':
- z_expand(symbol, "1111131311111", 13);
+ z_expand(symbol, d, 13);
break;
case 'E':
- z_expand(symbol, "1317131", 7);
+ z_expand(symbol, e, 7);
break;
default:
return z_errtxt(ZINT_ERROR_INVALID_DATA, symbol, 487,
@@ -428,22 +321,57 @@ INTERNAL int zint_daft_set_height(struct zint_symbol *symbol, const float min_he
return error_number;
}
-/* Handles the 4 State barcodes used in the UK by Royal Mail. Returns check_character */
-static int rm4scc_enc(struct zint_symbol *symbol, const int *posns, char *d, const int length) {
+/* Helper to expand 4-states into 3 rows, where 0 = Full, 1 = Ascender, 2 = Descender, 3 Tracker (always) */
+static void post_4state(struct zint_symbol *symbol, char *dest, const int length) {
+ int loopey, writer;
+
+ for (loopey = 0, writer = 0; loopey < length; loopey++, writer += 2) {
+ if (dest[loopey] == 1 || dest[loopey] == 0) { /* Ascender/full */
+ z_set_module(symbol, 0, writer);
+ }
+ z_set_module(symbol, 1, writer); /* Tracker */
+ if (dest[loopey] == 2 || dest[loopey] == 0) { /* Descender/full */
+ z_set_module(symbol, 2, writer);
+ }
+ }
+ symbol->rows = 3;
+ symbol->width = writer - 1;
+}
+
+/* Used by Royal Mail 4-state (& KIX) - 0 = Full, 1 = Ascender, 2 = Descender, 3 = Tracker */
+static const char RM4KIX[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 }
+};
+
+/* Handles the 4-state barcodes used in the UK by Royal Mail. Returns check_character */
+static int rm4scc_enc(struct zint_symbol *symbol, const int *const posns, char *const dest, const int length,
+ int *p_dest_len) {
+ static const char CheckCharTopBottom[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 }
+ };
int i;
int top, bottom, row, column, check_digit;
+ char *d = dest;
top = 0;
bottom = 0;
/* Start character */
- *d++ = '1';
+ *d++ = 1; /* Ascender */
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];
+ memcpy(d, RM4KIX[p], 4);
+ top += CheckCharTopBottom[p][0];
+ bottom += CheckCharTopBottom[p][1];
}
/* Calculate the check digit */
@@ -456,30 +384,40 @@ static int rm4scc_enc(struct zint_symbol *symbol, const int *posns, char *d, con
column = 5;
}
check_digit = (6 * row) + column;
- memcpy(d, RoyalTable[check_digit], 4);
+ memcpy(d, RM4KIX[check_digit], 4);
d += 4;
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit);
/* Stop character */
- memcpy(d, "0", 2); /* Include terminating NUL */
+ *d++ = 0; /* Full */
+
+ *p_dest_len = d - dest;
return KRSET[check_digit];
}
-/* Puts RM4SCC into the data matrix */
+/* Royal Mail 4-State Customer Code (RM4SCC) */
+/* Also handles Dutch Post TNT KIX symbols
+ 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 zint_rm4scc(struct zint_symbol *symbol, unsigned char source[], int length) {
int i;
- char height_pattern[210];
+ char dest[210];
int posns[50];
- int loopey, h;
- int writer;
+ int h;
char check_digit;
int error_number = 0;
const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
- if (length > 50) {
- return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 488, "Input length %d too long (maximum 50)", length);
+ if (symbol->symbology == BARCODE_KIX) {
+ if (length > 18) {
+ return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 490, "Input length %d too long (maximum 18)", length);
+ }
+ } else {
+ if (length > 50) {
+ return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 488, "Input length %d too long (maximum 50)", length);
+ }
}
z_to_upper(source, length);
if ((i = z_not_sane_lookup(KRSET, 36, source, length, posns))) {
@@ -487,21 +425,20 @@ INTERNAL int zint_rm4scc(struct zint_symbol *symbol, unsigned char source[], int
"Invalid character at position %d in input (alphanumerics only)", i);
}
- check_digit = rm4scc_enc(symbol, posns, height_pattern, length);
-
- writer = 0;
- h = (int) strlen(height_pattern);
- for (loopey = 0; loopey < h; loopey++) {
- if (height_pattern[loopey] == '1' || height_pattern[loopey] == '0') {
- z_set_module(symbol, 0, writer);
+ /* Encode data */
+ if (symbol->symbology == BARCODE_KIX) {
+ char *d = dest;
+ for (i = 0; i < length; i++, d += 4) {
+ memcpy(d, RM4KIX[posns[i]], 4);
}
- z_set_module(symbol, 1, writer);
- if (height_pattern[loopey] == '2' || height_pattern[loopey] == '0') {
- z_set_module(symbol, 2, writer);
- }
- writer += 2;
+ h = (int) (d - dest);
+ check_digit = '\xFF'; /* None */
+ } else {
+ check_digit = rm4scc_enc(symbol, posns, dest, length, &h);
}
+ post_4state(symbol, dest, h);
+
if (symbol->output_options & COMPLIANT_HEIGHT) {
/* Royal Mail Know How User's Manual Appendix C: using CBC
(https://web.archive.org/web/20120120060743/
@@ -509,6 +446,7 @@ INTERNAL int zint_rm4scc(struct zint_symbol *symbol, unsigned char source[], int
Bar pitch and min/maxes same as Mailmark, so using recommendations from
Royal Mail Mailmark Barcode Definition Document (15 Sept 2015) Section 3.5.1
*/
+ /* KIX same */
const float min_height = 6.47952747f; /* (4.22 * 39) / 25.4 */
const float max_height = 10.8062992f; /* (5.84 * 47) / 25.4 */
symbol->row_height[0] = 3.16417313f; /* (1.9 * 42.3) / 25.4 */
@@ -520,8 +458,6 @@ INTERNAL int zint_rm4scc(struct zint_symbol *symbol, unsigned char source[], int
symbol->row_height[1] = 2.0f;
(void) zint_daft_set_height(symbol, 0.0f, 0.0f);
}
- symbol->rows = 3;
- symbol->width = writer - 1;
if (content_segs && z_ct_cpy_cat(symbol, source, length, check_digit, NULL /*cat*/, 0)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy_cat()` only fails with OOM */
@@ -530,67 +466,6 @@ INTERNAL int zint_rm4scc(struct zint_symbol *symbol, unsigned char source[], int
return error_number;
}
-/* Handles Dutch Post TNT KIX symbols
- 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 zint_kix(struct zint_symbol *symbol, unsigned char source[], int length) {
- char height_pattern[75];
- char *d = height_pattern;
- int posns[18];
- int loopey;
- int writer, i, h;
- int error_number = 0;
- const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
-
- if (length > 18) {
- return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 490, "Input length %d too long (maximum 18)", length);
- }
- z_to_upper(source, length);
- if ((i = z_not_sane_lookup(KRSET, 36, source, length, posns))) {
- return z_errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 491,
- "Invalid character at position %d in input (alphanumerics only)", i);
- }
-
- /* Encode data */
- for (i = 0; i < length; i++, d += 4) {
- memcpy(d, RoyalTable[posns[i]], 4);
- }
-
- writer = 0;
- h = (int) (d - height_pattern);
- for (loopey = 0; loopey < h; loopey++) {
- if (height_pattern[loopey] == '1' || height_pattern[loopey] == '0') {
- z_set_module(symbol, 0, writer);
- }
- z_set_module(symbol, 1, writer);
- if (height_pattern[loopey] == '2' || height_pattern[loopey] == '0') {
- z_set_module(symbol, 2, writer);
- }
- writer += 2;
- }
-
- if (symbol->output_options & COMPLIANT_HEIGHT) {
- /* Dimensions same as RM4SCC */
- const float min_height = 6.47952747f; /* (4.22 * 39) / 25.4 */
- const float max_height = 10.8062992f; /* (5.84 * 47) / 25.4 */
- symbol->row_height[0] = 3.16417313f; /* (1.9 * 42.3) / 25.4 */
- symbol->row_height[1] = 2.16496062f; /* (1.3 * 42.3) / 25.4 */
- /* Note using max X for minimum and min X for maximum */
- error_number = zint_daft_set_height(symbol, min_height, max_height);
- } else {
- symbol->row_height[0] = 3.0f;
- symbol->row_height[1] = 2.0f;
- (void) zint_daft_set_height(symbol, 0.0f, 0.0f);
- }
- symbol->rows = 3;
- symbol->width = writer - 1;
-
- if (content_segs && z_ct_cpy(symbol, source, length)) {
- return ZINT_ERROR_MEMORY; /* `z_ct_cpy()` only fails with OOM */
- }
-
- return error_number;
-}
/* Handles DAFT Code symbols */
INTERNAL int zint_daft(struct zint_symbol *symbol, unsigned char source[], int length) {
@@ -610,17 +485,17 @@ INTERNAL int zint_daft(struct zint_symbol *symbol, unsigned char source[], int l
"Invalid character at position %d in input (\"D\", \"A\", \"F\" and \"T\" only)", i);
}
- writer = 0;
- for (loopey = 0; loopey < length; loopey++) {
- if (posns[loopey] == 1 || posns[loopey] == 0) {
+ for (loopey = 0, writer = 0; loopey < length; loopey++, writer += 2) {
+ if (posns[loopey] == 1 || posns[loopey] == 0) { /* Ascender/full */
z_set_module(symbol, 0, writer);
}
- z_set_module(symbol, 1, writer);
- if (posns[loopey] == 2 || posns[loopey] == 0) {
+ z_set_module(symbol, 1, writer); /* Tracker */
+ if (posns[loopey] == 2 || posns[loopey] == 0) { /* Descender/full */
z_set_module(symbol, 2, writer);
}
- writer += 2;
}
+ symbol->rows = 3;
+ symbol->width = writer - 1;
/* Allow ratio of tracker to be specified in thousandths */
if (symbol->option_2 >= 50 && symbol->option_2 <= 900) {
@@ -637,8 +512,6 @@ INTERNAL int zint_daft(struct zint_symbol *symbol, unsigned char source[], int l
/* DAFT generic barcode so no dimensions/height specification */
(void) zint_daft_set_height(symbol, 0.0f, 0.0f);
- symbol->rows = 3;
- symbol->width = writer - 1;
if (content_segs && z_ct_cpy(symbol, source, length)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy()` only fails with OOM */
@@ -649,6 +522,10 @@ INTERNAL int zint_daft(struct zint_symbol *symbol, unsigned char source[], int l
/* Flattermarken - Not really a barcode symbology! */
INTERNAL int zint_flat(struct zint_symbol *symbol, unsigned char source[], int length) {
+ 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'}
+ };
int i, error_number = 0;
char dest[512]; /* 128 * 4 = 512 */
char *d = dest;
@@ -681,10 +558,17 @@ INTERNAL int zint_flat(struct zint_symbol *symbol, unsigned char source[], int l
/* Japanese Postal Code (Kasutama Barcode) */
INTERNAL int zint_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;
+ static const char JapanTable[19][3] = {
+ { 0,0,3 }, { 0,2,1 }, { 2,0,1 }, { 0,1,2 }, { 0,3,0 },
+ { 2,1,0 }, { 1,0,2 }, { 1,2,0 }, { 3,0,0 }, { 0,3,3 },
+ { 3,0,3 }, { 2,1,3 }, { 2,3,1 }, { 1,2,3 }, { 3,2,1 },
+ { 1,3,2 }, { 3,1,2 }, { 3,3,0 }, { 0,0,0 }
+ };
+ static const char start_stop[3] = { 0,2,0 }; /* 1st 2 chars start, last 2 chars stop */
+ int error_number = 0;
+ char dest[69];
+ char *d = dest;
+ int inter_posn, i, sum, check;
char check_char;
unsigned char inter[20 + 1];
const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
@@ -729,7 +613,7 @@ INTERNAL int zint_japanpost(struct zint_symbol *symbol, unsigned char source[],
"Input too long, requires too many symbol characters (maximum 20)");
}
- memcpy(d, "13", 2); /* Start */
+ memcpy(d, start_stop, 2); /* Start */
d += 2;
sum = 0;
@@ -755,25 +639,11 @@ INTERNAL int zint_japanpost(struct zint_symbol *symbol, unsigned char source[],
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check: %d, char: %c\n", check, check_char);
- memcpy(d, "31", 2); /* Stop */
+ memcpy(d, start_stop + 1, 2); /* Stop */
d += 2;
/* Resolve pattern to 4-state symbols */
- writer = 0;
- h = (int) (d - pattern);
- for (loopey = 0; loopey < h; loopey++) {
- if (pattern[loopey] == '2' || pattern[loopey] == '1') {
- z_set_module(symbol, 0, writer);
- }
- z_set_module(symbol, 1, writer);
- if (pattern[loopey] == '3' || pattern[loopey] == '1') {
- z_set_module(symbol, 2, writer);
- }
- writer += 2;
- }
-
- symbol->rows = 3;
- symbol->width = writer - 1;
+ post_4state(symbol, dest, (int) (d - dest));
if (symbol->output_options & COMPLIANT_HEIGHT) {
/* Japan Post Zip/Barcode Manual pp.11-12 https://www.post.japanpost.jp/zipcode/zipmanual/p11.html
diff --git a/backend/svg.c b/backend/svg.c
index 4a36228f..d27c6024 100644
--- a/backend/svg.c
+++ b/backend/svg.c
@@ -1,7 +1,7 @@
/* svg.c - Scalable Vector Graphics */
/*
libzint - the open source barcode library
- Copyright (C) 2009-2025 Robin Stuart
+ Copyright (C) 2009-2026 Robin Stuart
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -58,33 +58,37 @@ static void svg_pick_colour(const int colour, char colour_code[7]) {
/* Convert text to use HTML entity codes */
static void svg_make_html_friendly(const unsigned char *string, char *html_version) {
-
+ static const char gt[4] = { '&','g','t',';' };
+ static const char lt[4] = { '&','l','t',';' };
+ static const char amp[5] = { '&','a','m','p',';' };
+ static const char quot[6] = { '&','q','u','o','t',';' };
+ static const char apos[6] = { '&','a','p','o','s',';' };
/* `NOLINT` required due to disconnect between `symbol->text` and vector `string`s which are always <= */
/* NOLINTBEGIN(clang-analyzer-security.ArrayBound) clang-tidy-21 false positive */
for (; *string; string++) {
switch (*string) {
case '>':
- memcpy(html_version, ">", 4);
+ memcpy(html_version, gt, 4);
html_version += 4;
break;
case '<':
- memcpy(html_version, "<", 4);
+ memcpy(html_version, lt, 4);
html_version += 4;
break;
case '&':
- memcpy(html_version, "&", 5);
+ memcpy(html_version, amp, 5);
html_version += 5;
break;
case '"':
- memcpy(html_version, """, 6);
+ memcpy(html_version, quot, 6);
html_version += 6;
break;
case '\'':
- memcpy(html_version, "'", 6);
+ memcpy(html_version, apos, 6);
html_version += 6;
break;
diff --git a/backend/tests/test_auspost.c b/backend/tests/test_auspost.c
index af63bc85..957a3e79 100644
--- a/backend/tests/test_auspost.c
+++ b/backend/tests/test_auspost.c
@@ -1,6 +1,6 @@
/*
libzint - the open source barcode library
- Copyright (C) 2020-2025 Robin Stuart
+ Copyright (C) 2020-2026 Robin Stuart
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -148,8 +148,8 @@ static void test_hrt(const testCtx *const p_ctx) {
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/,
- -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options,
- data[i].data, -1, debug);
+ -1 /*option_1*/, -1 /*option_2*/, -1 /*option_3*/, data[i].output_options,
+ data[i].data, -1, debug);
expected_length = (int) strlen(data[i].expected);
expected_content_length = (int) strlen(data[i].expected_content);
@@ -195,25 +195,29 @@ static void test_input(const testCtx *const p_ctx) {
static const struct item data[] = {
/* 0*/ { BARCODE_AUSPOST, "12345678", 0, 3, 73, "" },
/* 1*/ { BARCODE_AUSPOST, "1234567A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 405: Invalid character at position 8 in DPID (first 8 characters) (digits only)" },
- /* 2*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
- /* 3*/ { BARCODE_AUSPOST, "12345678ABcd!", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 404: Invalid character at position 13 in input (alphanumerics, space and \"#\" only)" },
- /* 4*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
- /* 5*/ { BARCODE_AUSPOST, "1234567890123456", 0, 3, 103, "" },
- /* 6*/ { BARCODE_AUSPOST, "123456789012345A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character at position 16 in input (digits only for FCC 59 length 16)" },
- /* 7*/ { BARCODE_AUSPOST, "12345678ABCDefgh #", 0, 3, 133, "" }, /* Length 18 */
- /* 8*/ { BARCODE_AUSPOST, "12345678901234567890123", 0, 3, 133, "" },
- /* 9*/ { BARCODE_AUSPOST, "1234567890123456789012A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 406: Invalid character at position 23 in input (digits only for FCC 62 length 23)" },
- /* 10*/ { BARCODE_AUSPOST, "1234567", ZINT_ERROR_TOO_LONG, -1, -1, "Error 401: Input length 7 wrong (8, 13, 16, 18 or 23 characters required)" }, /* No leading zeroes added */
- /* 11*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "" },
- /* 12*/ { BARCODE_AUSREPLY, "1234567", 0, 3, 73, "" }, /* Leading zeroes added */
- /* 13*/ { BARCODE_AUSREPLY, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Input length 9 too long (maximum 8)" },
- /* 14*/ { BARCODE_AUSROUTE, "123456", 0, 3, 73, "" },
- /* 15*/ { BARCODE_AUSROUTE, "12345", 0, 3, 73, "" },
- /* 16*/ { BARCODE_AUSROUTE, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Input length 9 too long (maximum 8)" },
- /* 17*/ { BARCODE_AUSREDIRECT, "1234", 0, 3, 73, "" },
- /* 18*/ { BARCODE_AUSREDIRECT, "123", 0, 3, 73, "" },
- /* 19*/ { BARCODE_AUSREDIRECT, "0", 0, 3, 73, "" },
- /* 20*/ { BARCODE_AUSREDIRECT, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Input length 9 too long (maximum 8)" },
+ /* 2*/ { BARCODE_AUSPOST, "0000000A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 405: Invalid character at position 8 in DPID (first 8 characters) (digits only)" },
+ /* 3*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
+ /* 4*/ { BARCODE_AUSPOST, "12345678ABcd!", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 404: Invalid character at position 13 in input (alphanumerics, space and \"#\" only)" },
+ /* 5*/ { BARCODE_AUSPOST, "00000000ABcd!", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 404: Invalid character at position 13 in input (alphanumerics, space and \"#\" only)" },
+ /* 6*/ { BARCODE_AUSPOST, "12345678ABcd#", 0, 3, 103, "" },
+ /* 7*/ { BARCODE_AUSPOST, "1234567890123456", 0, 3, 103, "" },
+ /* 8*/ { BARCODE_AUSPOST, "123456789012345A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character at position 16 in input (digits only for FCC 59 length 16)" },
+ /* 9*/ { BARCODE_AUSPOST, "000000009012345A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 402: Invalid character at position 16 in input (digits only for FCC 59 length 16)" },
+ /* 10*/ { BARCODE_AUSPOST, "12345678ABCDefgh #", 0, 3, 133, "" }, /* Length 18 */
+ /* 11*/ { BARCODE_AUSPOST, "12345678901234567890123", 0, 3, 133, "" },
+ /* 12*/ { BARCODE_AUSPOST, "1234567890123456789012A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 406: Invalid character at position 23 in input (digits only for FCC 62 length 23)" },
+ /* 13*/ { BARCODE_AUSPOST, "0000000090123456789012A", ZINT_ERROR_INVALID_DATA, -1, -1, "Error 406: Invalid character at position 23 in input (digits only for FCC 62 length 23)" },
+ /* 14*/ { BARCODE_AUSPOST, "1234567", ZINT_ERROR_TOO_LONG, -1, -1, "Error 401: Input length 7 wrong (8, 13, 16, 18 or 23 characters required)" }, /* No leading zeroes added */
+ /* 15*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "" },
+ /* 16*/ { BARCODE_AUSREPLY, "1234567", 0, 3, 73, "" }, /* Leading zeroes added */
+ /* 17*/ { BARCODE_AUSREPLY, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Input length 9 too long (maximum 8)" },
+ /* 18*/ { BARCODE_AUSROUTE, "123456", 0, 3, 73, "" },
+ /* 19*/ { BARCODE_AUSROUTE, "12345", 0, 3, 73, "" },
+ /* 20*/ { BARCODE_AUSROUTE, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Input length 9 too long (maximum 8)" },
+ /* 21*/ { BARCODE_AUSREDIRECT, "1234", 0, 3, 73, "" },
+ /* 22*/ { BARCODE_AUSREDIRECT, "123", 0, 3, 73, "" },
+ /* 23*/ { BARCODE_AUSREDIRECT, "0", 0, 3, 73, "" },
+ /* 24*/ { BARCODE_AUSREDIRECT, "123456789", ZINT_ERROR_TOO_LONG, -1, -1, "Error 403: Input length 9 too long (maximum 8)" },
};
const int data_size = ARRAY_SIZE(data);
int i, length, ret;
@@ -277,81 +281,108 @@ static void test_encode(const testCtx *const p_ctx) {
int expected_rows;
int expected_width;
+ int bwipp_cmp;
const char *comment;
const char *expected;
};
+ /* s/\v(\/\*)[ 0-9]*(\*\/)/\=printf("%s%3d%s", submatch(1), (@z+setreg('z',@z+1)), submatch(2))/ | let @z=0: */
static const struct item data[] = {
- /* 0*/ { BARCODE_AUSPOST, "96184209", 0, 3, 73, "AusPost Tech Specs Diagram 1; verified manually against TEC-IT",
+ /* 0*/ { BARCODE_AUSPOST, "96184209", 0, 3, 73, 1, "AusPost Tech Specs Diagram 1; verified manually against TEC-IT",
"1000101010100010001010100000101010001010001000001010000010001000001000100"
"1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000100010000010101010001010000010101010001000101010001000100010000010000"
},
- /* 1*/ { BARCODE_AUSPOST, "39549554", 0, 3, 73, "AusPost Guide Figure 3, same; verified manually against TEC-IT",
+ /* 1*/ { BARCODE_AUSPOST, "39549554", 0, 3, 73, 1, "AusPost Guide Figure 3, same; verified manually against TEC-IT",
"1000101010101010001010001010001010001000101000001000101010001010000000100"
"1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000100010000010001000100000001000100010000000000010001000000000001010000"
},
- /* 2*/ { BARCODE_AUSPOST, "56439111ABA 9", 0, 3, 103, "AusPost Guide Figure 4, same; verified manually against TEC-IT",
+ /* 2*/ { BARCODE_AUSPOST, "56439111ABA 9", 0, 3, 103, 1, "AusPost Guide Figure 4, same; verified manually against TEC-IT",
"1000100000101000001010101010001010101010101010101010101010101010100000000000001010100010101010000010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001000100010101000000010001010001000100010101010100010101010100000101000000010001000101010000000000"
},
- /* 3*/ { BARCODE_AUSPOST, "3221132412345678", 0, 3, 103, "59 Custom 2 N encoding",
+ /* 3*/ { BARCODE_AUSPOST, "3221132412345678", 0, 3, 103, 1, "59 Custom 2 N encoding",
"1000100000101010100010001010101010101000101010101000101010101000001000100000101000000000001000000000100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001000100010101010101000100000101010000010001010001000000010101010001010000010001010101000100000000"
},
- /* 4*/ { BARCODE_AUSPOST, "32211324Ab #2", 0, 3, 103, "59 Custom 2 C encoding",
+ /* 4*/ { BARCODE_AUSPOST, "32211324Ab #2", 0, 3, 103, 1, "59 Custom 2 C encoding",
"1000100000101010100010001010101010101000101010101010001010100010100000101000100000000010100000100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001000100010101010101000100000101010000010101010001010100010000000100000001000101010000010000000000"
},
- /* 5*/ { BARCODE_AUSPOST, "32211324123456789012345", 0, 3, 133, "62 Custom 3 N encoding",
+ /* 5*/ { BARCODE_AUSPOST, "32211324123456789012345", 0, 3, 133, 1, "62 Custom 3 N encoding",
"1000001010001010100010001010101010101000101010101000101010101000001000100000001010101010100010101010100000100000100010101010100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010100010101010101000100000101010000010001010001000000010101010001010001010101000101000100000001000001010000010001010100010000"
},
- /* 6*/ { BARCODE_AUSPOST, "32211324aBCd#F hIz", 0, 3, 133, "62 Custom 3 C encoding",
+ /* 6*/ { BARCODE_AUSPOST, "32211324aBCd#F hIz", 0, 3, 133, 1, "62 Custom 3 C encoding",
"1000001010001010100010001010101010101000101010000010101010100010000010100010100010100010000010000000000000100010100010101010000000100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010100010101010101000100000101010000010100010100010101010001010000010001010100000100010101000000000101000001010100000000010000"
},
- /* 7*/ { BARCODE_AUSPOST, "12345678DEGHJKLMNO", 0, 3, 133, "62 Custom 3 C encoding GDSET 1st part",
+ /* 7*/ { BARCODE_AUSPOST, "12345678DEGHJKLMNO", 0, 3, 133, 1, "62 Custom 3 C encoding GDSET 1st part",
"1000001010001010100010101010100000100010000010101010101010001010001010101010101010100010101010101010100000001010000010000000000010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010101000101000100000001010101000101010001010000010101010100000101000100000101000001000000000001000001010000010001010001010000"
},
- /* 8*/ { BARCODE_AUSPOST, "23456789PQRSTUVWXY", 0, 3, 133, "62 Custom 3 C encoding GDSET 2nd part",
+ /* 8*/ { BARCODE_AUSPOST, "23456789PQRSTUVWXY", 0, 3, 133, 1, "62 Custom 3 C encoding GDSET 2nd part",
"1000001010001000101010101000001000100000001010001010001010000000101000101000100000101000101000100000001000101000101010101000101010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010101010001000000010101010001010001000101000100000101010101010100010101010001010000010001010101000000010001000001010101000000"
},
- /* 9*/ { BARCODE_AUSPOST, "34567890Zcefgijklm", 0, 3, 133, "62 Custom 3 C encoding GDSET 3rd part",
+ /* 9*/ { BARCODE_AUSPOST, "34567890Zcefgijklm", 0, 3, 133, 1, "62 Custom 3 C encoding GDSET 3rd part",
"1000001010001010101010000010001000000010101000001010001010000010100010100010001010001010000010000000100000101000100000001010001010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010100010000000101010100010100010101010100010000010000000100000000000001000000000001000000010100000101000000010101010100010000"
},
- /* 10*/ { BARCODE_AUSPOST, "12345678lnopqrstuv", 0, 3, 133, "62 Custom 3 C encoding GDSET 4th part",
+ /* 10*/ { BARCODE_AUSPOST, "12345678lnopqrstuv", 0, 3, 133, 1, "62 Custom 3 C encoding GDSET 4th part",
"1000001010001010100010101010100000100010000010000000100000000000001000001000000000000000100000100000000000001010001010101000000010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010101000101000100000001010101000101000000010000010100010001010000010001010000000100000000000100000100000001010001000100000000"
},
- /* 11*/ { BARCODE_AUSPOST, "09876543wxy# ", 0, 3, 103, "59 Custom 2 C encoding GDSET 5th part",
+ /* 11*/ { BARCODE_AUSPOST, "09876543wxy# ", 0, 3, 103, 1, "59 Custom 2 C encoding GDSET 5th part",
"1000100000101010001000000010001010001010101000001000001000000010100010100000100010000000000010100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001000101010001010101000101000100000001000001000000000001010000010100000001010001000001000100000000"
},
- /* 12*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it",
+ /* 12*/ { BARCODE_AUSPOST, "00000000", 0, 3, 73, 0, "Null (DPID all-zeros) length 8; BWIPP: not supported yet",
+ "1000101010101010101010101010101010101010101000001000001000001000101000100"
+ "1010101010101010101010101010101010101010101010101010101010101010101010101"
+ "0000101010101010101010101010101010101010101000101010100000001000001000000"
+ },
+ /* 13*/ { BARCODE_AUSPOST, "00000000ABC 9", 0, 3, 103, 0, "Null length 13; BWIPP: not supported yet",
+ "1000101010101010101010101010101010101010101010101010101010100010100000000000100000001000101000000000100"
+ "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
+ "0000101010101010101010101010101010101010101010101010100010101010100000101000101010001010001000000000000"
+ },
+ /* 14*/ { BARCODE_AUSPOST, "0000000012345678", 0, 3, 103, 0, "Null length 16; BWIPP: not supported yet",
+ "1000101010101010101010101010101010101010101010101000101010101000001000100000001000101000001010100000100"
+ "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
+ "0000101010101010101010101010101010101010101010001010001000000010101010001010001010101010101010101010000"
+ },
+ /* 15*/ { BARCODE_AUSPOST, "00000000aBCd#F hIz", 0, 3, 133, 0, "Null length 18; BWIPP: not supported yet",
+ "1000101010101010101010101010101010101010101010000010101010100010000010100010100010100010000010000000000000001010100000000000000000100"
+ "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
+ "0000101010101010101010101010101010101010101010100010100010101010001010000010001010100000100010101000000000001000001000000000000000000"
+ },
+ /* 16*/ { BARCODE_AUSPOST, "00000000123456789012345", 0, 3, 133, 0, "Null length 23; BWIPP: not supported yet",
+ "1000101010101010101010101010101010101010101010101000101010101000001000100000001010101010100010101010100000001000100000000000100010100"
+ "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
+ "0000101010101010101010101010101010101010101010001010001000000010101010001010001010101000101000100000001000101010000000101010100000000"
+ },
+ /* 17*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, 1, "Verified manually against TEC-IT",
"1000101010001010100010101010100000100010000000001000001000000000100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000000000101000101000100000001010101000101000000000100010101000101000000"
},
- /* 13*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it",
+ /* 18*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, 1, "Verified manually against TEC-IT",
"1000000000101010101010000010001000000010101000100010101010000000101000100"
"1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010000010000000101010100010100010101000100010101010001010001000000"
},
- /* 14*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it",
+ /* 19*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, 1, "Verified manually against TEC-IT",
"1000001010000010000000100010100010101010100000101010101000100010100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001010100010101010001010001000000010101000000000001010101000001010000"
@@ -376,34 +407,51 @@ static void test_encode(const testCtx *const p_ctx) {
symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
- length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
+ length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/,
+ -1 /*option_1*/, -1, -1, -1 /*output_options*/,
+ data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, TCU(data[i].data), length);
- assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
+ assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n",
+ i, ret, data[i].ret, symbol->errtxt);
if (p_ctx->generate) {
- printf(" /*%3d*/ { %s, \"%s\", %s, %d, %d, \"%s\",\n",
- i, testUtilBarcodeName(data[i].symbology), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
- testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment);
+ printf(" /*%3d*/ { %s, \"%s\", %s, %d, %d, %d, \"%s\",\n",
+ i, testUtilBarcodeName(data[i].symbology),
+ testUtilEscape(data[i].data, length, escaped, sizeof(escaped)),
+ testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment);
testUtilModulesPrint(symbol, " ", "\n");
printf(" },\n");
} else {
if (ret < ZINT_ERROR) {
int width, row;
- assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data);
- assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data);
+ assert_equal(symbol->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);
ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row);
- assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data);
+ assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n",
+ i, ret, width, row, data[i].data);
if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) {
- ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL);
- assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret);
+ if (!data[i].bwipp_cmp) {
+ if (debug & ZINT_DEBUG_TEST_PRINT) {
+ printf("i:%d %s not BWIPP compatible (%s)\n",
+ i, testUtilBarcodeName(symbol->symbology), data[i].comment);
+ }
+ } else {
+ ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf,
+ sizeof(bwipp_buf), NULL);
+ assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n",
+ i, testUtilBarcodeName(symbol->symbology), ret);
- ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected);
- assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
- i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected);
+ ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected);
+ assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n",
+ i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf,
+ data[i].expected);
+ }
}
}
}
diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c
index 2b820a50..da1f3a56 100644
--- a/backend/tests/test_code128.c
+++ b/backend/tests/test_code128.c
@@ -1752,6 +1752,7 @@ static void test_fuzz(const testCtx *const p_ctx) {
"\136\136",
162, ZINT_ERROR_TOO_LONG, "Error 341: Input too long, requires 167 symbol characters (maximum 102)", 3
}, /* fuzz_data (2nd, 2026-01-12) */
+ /* 1*/ { BARCODE_CODE128, DATA_MODE | EXTRA_ESCAPE_MODE, -1, -1, "\\^CC\\^177#", -1, 0, "", 3 },
};
const int data_size = ARRAY_SIZE(data);
int i, length, ret;
diff --git a/backend/tests/test_postal.c b/backend/tests/test_postal.c
index 66677490..66696b83 100644
--- a/backend/tests/test_postal.c
+++ b/backend/tests/test_postal.c
@@ -1,6 +1,6 @@
/*
libzint - the open source barcode library
- Copyright (C) 2019-2025 Robin Stuart
+ Copyright (C) 2019-2026 Robin Stuart
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -72,7 +72,7 @@ static void test_large(const testCtx *const p_ctx) {
/* 20*/ { BARCODE_PLANET, "1", 13, 0, 2, 143, "" },
/* 21*/ { BARCODE_PLANET, "1", 14, ZINT_WARN_NONCOMPLIANT, 2, 153, "Warning 478: Input length 14 is not standard (should be 11 or 13 digits)" },
/* 22*/ { BARCODE_PLANET, "1", 38, ZINT_WARN_NONCOMPLIANT, 2, 393, "Warning 478: Input length 38 is not standard (should be 11 or 13 digits)" },
- /* 23*/ { BARCODE_PLANET, "1", 39, ZINT_ERROR_TOO_LONG, -1, -1, "Error 482: Input length 39 too long (maximum 38)" },
+ /* 23*/ { BARCODE_PLANET, "1", 39, ZINT_ERROR_TOO_LONG, -1, -1, "Error 480: Input length 39 too long (maximum 38)" },
/* 24*/ { BARCODE_KIX, "1", 18, 0, 3, 143, "" },
/* 25*/ { BARCODE_KIX, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1, "Error 490: Input length 19 too long (maximum 18)" },
/* 26*/ { BARCODE_DAFT, "D", 576, 0, 3, 1151, "" },
@@ -352,10 +352,10 @@ static void test_input(const testCtx *const p_ctx) {
/* 34*/ { BARCODE_PLANET, -1, 0, "1234567890", ZINT_WARN_NONCOMPLIANT, 2, 113, 12, "Warning 478: Input length 10 is not standard (should be 11 or 13 digits)", 0, "BWIPP requires standard lengths" },
/* 35*/ { BARCODE_PLANET, -1, 0, "123456789012", ZINT_WARN_NONCOMPLIANT, 2, 133, 12, "Warning 478: Input length 12 is not standard (should be 11 or 13 digits)", 0, "BWIPP requires standard lengths" },
/* 36*/ { BARCODE_PLANET, -1, 0, "12345678901234", ZINT_WARN_NONCOMPLIANT, 2, 153, 12, "Warning 478: Input length 14 is not standard (should be 11 or 13 digits)", 0, "BWIPP requires standard lengths" },
- /* 37*/ { BARCODE_PLANET, -1, 0, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, -1, "Error 483: Invalid character at position 11 in input (digits only)", 1, "" },
+ /* 37*/ { BARCODE_PLANET, -1, 0, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, -1, "Error 481: Invalid character at position 11 in input (digits only)", 1, "" },
/* 38*/ { BARCODE_KIX, -1, 0, "0123456789ABCDEFGH", 0, 3, 143, 8, "", 1, "" },
/* 39*/ { BARCODE_KIX, -1, 0, "a", 0, 3, 7, 8, "", 1, "" }, /* Converts to upper */
- /* 40*/ { BARCODE_KIX, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1, "Error 491: Invalid character at position 1 in input (alphanumerics only)", 1, "" },
+ /* 40*/ { BARCODE_KIX, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1, "Error 489: Invalid character at position 1 in input (alphanumerics only)", 1, "" },
/* 41*/ { BARCODE_DAFT, -1, 0, "DAFT", 0, 3, 7, 8, "", 1, "" },
/* 42*/ { BARCODE_DAFT, -1, 0, "a", 0, 3, 1, 8, "", 1, "" }, /* Converts to upper */
/* 43*/ { BARCODE_DAFT, -1, 0, "B", ZINT_ERROR_INVALID_DATA, -1, -1, -1, "Error 493: Invalid character at position 1 in input (\"D\", \"A\", \"F\" and \"T\" only)", 1, "" },
diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c
index cf285470..aec5ffc3 100644
--- a/backend/tests/testcommon.c
+++ b/backend/tests/testcommon.c
@@ -3262,6 +3262,11 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int
bwipp_opts = bwipp_opts_buf;
}
}
+ /* Check for Null - for when supported by BWIPP */
+ for (i = 0; i < 8 && data[i] == '0'; i++);
+ if (i == 8) {
+ prefix = "00";
+ }
memmove(bwipp_data + 2, bwipp_data, data_len + 1);
memmove(bwipp_data, prefix, 2);
}
diff --git a/backend/upcean.c b/backend/upcean.c
index 292fb6b6..b0d6930f 100644
--- a/backend/upcean.c
+++ b/backend/upcean.c
@@ -1,7 +1,7 @@
/* upcean.c - Handles UPC, EAN and ISBN */
/*
libzint - the open source barcode library
- Copyright (C) 2008-2025 Robin Stuart
+ Copyright (C) 2008-2026 Robin Stuart
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -85,6 +85,8 @@ static const char EANsetB[10][4] = {
{'1','3','2','1'}, {'4','1','1','1'}, {'2','1','3','1'}, {'3','1','2','1'}, {'2','1','1','3'}
};
+static const char EANones[6] = { '1','1','1','1','1','1' }; /* Various lengths used for start/stop/separators */
+
/* Write UPC-A or EAN-8 encodation to destination `d` */
static void upca_set_dest(const unsigned char source[], const int length, char *d) {
int i, half_way;
@@ -92,13 +94,13 @@ static void upca_set_dest(const unsigned char source[], const int length, char *
half_way = length / 2;
/* Start character */
- memcpy(d, "111", 3);
+ memcpy(d, EANones, 3);
d += 3;
for (i = 0; i < length; i++, d += 4) {
if (i == half_way) {
/* Middle character - separates manufacturer no. from product no. - also inverts right hand characters */
- memcpy(d, "11111", 5);
+ memcpy(d, EANones, 5);
d += 5;
}
@@ -106,7 +108,9 @@ static void upca_set_dest(const unsigned char source[], const int length, char *
}
/* Stop character */
- memcpy(d, "111", 4); /* Include terminating NUL */
+ memcpy(d, EANones, 3);
+ d += 3;
+ *d = '\0'; /* Need to NUL-terminate */
}
/* Make a UPC-A barcode, allowing for composite if `cc_rows` set */
@@ -278,7 +282,7 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt
/* Take all this information and make the barcode pattern */
/* Start character */
- memcpy(d, "111", 3);
+ memcpy(d, EANones, 3);
d += 3;
for (i = 0; i < length; i++, d += 4) {
@@ -293,7 +297,9 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt
}
/* Stop character */
- memcpy(d, "111111", 7); /* Include terminating NUL */
+ memcpy(d, EANones, 6);
+ d += 6;
+ *d = '\0'; /* Need to NUL-terminate */
z_hrt_cat_chr_nochk(symbol, check_digit);
@@ -333,6 +339,7 @@ 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) {
+ static const char start[3] = { '1','1','2' };
const char *parity;
int i;
char *d = dest + strlen(dest);
@@ -343,7 +350,7 @@ static void ean_add_on(const unsigned char source[], const int length, char dest
}
/* Start character */
- memcpy(d, "112", 3);
+ memcpy(d, start, 3);
d += 3;
/* Calculate parity */
@@ -381,7 +388,7 @@ static void ean_add_on(const unsigned char source[], const int length, char dest
/* Glyph separator */
if (i != (length - 1)) {
- memcpy(d, "11", 2);
+ memcpy(d, EANones, 2);
d += 2;
}
}
@@ -422,13 +429,13 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in
half_way = 7;
/* Start character */
- memcpy(d, "111", 3);
+ memcpy(d, EANones, 3);
d += 3;
for (i = 1; i < symbol->text_length; i++, d += 4) {
if (i == half_way) {
/* Middle character - separates manufacturer no. from product no. - also inverts right hand characters */
- memcpy(d, "11111", 5);
+ memcpy(d, EANones, 5);
d += 5;
}
@@ -440,7 +447,9 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in
}
/* Stop character */
- memcpy(d, "111", 4); /* Include terminating NUL */
+ memcpy(d, EANones, 3);
+ d += 3;
+ *d = '\0'; /* Need to NUL-terminate */
if (symbol->output_options & COMPLIANT_HEIGHT) {
/* ISO/IEC 15420:2009 4.3.3 Bar height EAN-13 22.85mm / 0.33mm (X) ~ 69.24,
diff --git a/docs/manual.html b/docs/manual.html
index fe93be60..9996b2de 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -6086,7 +6086,8 @@ alt="zint -b AUSPOST --compliantheight -d "96184209"" />
Control Code (FCC) is added by Zint and should not be included in the
input data. Reed-Solomon error correction data is generated by Zint.
Encoding behaviour is determined by the length of the input data
-according to the formula shown in the following table.
+according to the formula shown in the following table. The first 8
+digits is the DPID.
Table 23: Australia Post Input
Formats
@@ -6103,7 +6104,7 @@ Formats
| Required Input Format |
Symbol Length |
FCC |
-Encoding Table |
+Encoding Table(s) |
@@ -6112,38 +6113,41 @@ Formats
99999999 |
37-bar |
11 |
-None |
+N |
| 13 |
99999999AAAAA |
52-bar |
59 |
-C |
+N and C |
| 16 |
9999999999999999 |
52-bar |
59 |
-N |
+N |
| 18 |
99999999AAAAAAAAAA |
67-bar |
62 |
-C |
+N and C |
| 23 |
99999999999999999999999 |
67-bar |
62 |
-N |
+N |
+The special Null FCC 00, non-machine readable and intended for
+customer use only, is used (all input lengths) if the DPID is all
+zeroes.
6.5.1.2 Reply Paid Barcode
A Reply Paid version of the Australia Post 4-State Barcode (FCC 45)
which requires an 8-digit DPID input.
diff --git a/docs/manual.pmd b/docs/manual.pmd
index 36f0f105..c209524c 100644
--- a/docs/manual.pmd
+++ b/docs/manual.pmd
@@ -4142,25 +4142,28 @@ Valid data characters are 0-9, A-Z, a-z, space and hash (#). A Format Control
Code (FCC) is added by Zint and should not be included in the input data.
Reed-Solomon error correction data is generated by Zint. Encoding behaviour is
determined by the length of the input data according to the formula shown in the
-following table.
+following table. The first 8 digits is the DPID.
-------------------------------------------------------------
Input Required Input Format Symbol FCC Encoding
-Length Length Table
+Length Length Table(s)
------ ------------------------- ------ --- --------
-8 `99999999` 37-bar 11 None
+8 `99999999` 37-bar 11 N
-13 `99999999AAAAA` 52-bar 59 C
+13 `99999999AAAAA` 52-bar 59 N and C
16 `9999999999999999` 52-bar 59 N
-18 `99999999AAAAAAAAAA` 67-bar 62 C
+18 `99999999AAAAAAAAAA` 67-bar 62 N and C
23 `99999999999999999999999` 67-bar 62 N
-------------------------------------------------------------
Table: Australia Post Input Formats {#tbl:auspost_input_formats}
+The special Null FCC 00, non-machine readable and intended for customer use
+only, is used (all input lengths) if the DPID is all zeroes.
+
#### 6.5.1.2 Reply Paid Barcode
A Reply Paid version of the Australia Post 4-State Barcode (FCC 45) which
diff --git a/docs/manual.txt b/docs/manual.txt
index 3832b4bc..c12cc136 100644
--- a/docs/manual.txt
+++ b/docs/manual.txt
@@ -3949,25 +3949,28 @@ Valid data characters are 0-9, A-Z, a-z, space and hash (#). A Format Control
Code (FCC) is added by Zint and should not be included in the input data.
Reed-Solomon error correction data is generated by Zint. Encoding behaviour is
determined by the length of the input data according to the formula shown in the
-following table.
+following table. The first 8 digits is the DPID.
---------------------------------------------------------------
Input Required Input Format Symbol FCC Encoding
- Length Length Table
+ Length Length Table(s)
--------- --------------------------- -------- ----- ----------
- 8 99999999 37-bar 11 None
+ 8 99999999 37-bar 11 N
- 13 99999999AAAAA 52-bar 59 C
+ 13 99999999AAAAA 52-bar 59 N and C
16 9999999999999999 52-bar 59 N
- 18 99999999AAAAAAAAAA 67-bar 62 C
+ 18 99999999AAAAAAAAAA 67-bar 62 N and C
23 99999999999999999999999 67-bar 62 N
---------------------------------------------------------------
Table 23: Australia Post Input Formats
+The special Null FCC 00, non-machine readable and intended for customer use
+only, is used (all input lengths) if the DPID is all zeroes.
+
6.5.1.2 Reply Paid Barcode
A Reply Paid version of the Australia Post 4-State Barcode (FCC 45) which