mirror of
https://git.code.sf.net/p/zint/code
synced 2025-05-19 17:55:10 -04:00
CODE128: reduce extended latch cut-off from 5 to 4 for better
encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
This commit is contained in:
parent
752c1fae5d
commit
5e2044ff2e
104 changed files with 8102 additions and 7755 deletions
326
backend/common.c
326
backend/common.c
|
@ -31,6 +31,7 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
|
||||
|
@ -87,7 +88,7 @@ INTERNAL int chr_cnt(const unsigned char source[], const int length, const unsig
|
|||
return count;
|
||||
}
|
||||
|
||||
/* Flag table for `is_chr()` and `is_sane()` */
|
||||
/* Flag table for `is_chr()` and `not_sane()` */
|
||||
#define IS_CLS_F (IS_CLI_F | IS_SIL_F)
|
||||
static const unsigned short flgs[256] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00-1F*/
|
||||
|
@ -126,21 +127,22 @@ INTERNAL int is_chr(const unsigned int flg, const unsigned int c) {
|
|||
return c < 0x80 && (flgs[c] & flg) != 0;
|
||||
}
|
||||
|
||||
/* Verifies that a string only uses valid characters */
|
||||
INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length) {
|
||||
/* Verifies if a string only uses valid characters, returning 1-based position in `source` if not, 0 for success */
|
||||
INTERNAL int not_sane(const unsigned int flg, const unsigned char source[], const int length) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (!(flgs[source[i]] & flg)) {
|
||||
return 0;
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Replaces huge switch statements for looking up in tables */
|
||||
/* Verifies that a string only uses valid characters, and returns `test_string` position of each in `posns` array */
|
||||
INTERNAL int is_sane_lookup(const char test_string[], const int test_length, const unsigned char source[],
|
||||
/* Verifies if a string only uses valid characters as above, but also returns `test_string` position of each in
|
||||
`posns` array */
|
||||
INTERNAL int not_sane_lookup(const char test_string[], const int test_length, const unsigned char source[],
|
||||
const int length, int *posns) {
|
||||
int i, j;
|
||||
|
||||
|
@ -153,11 +155,11 @@ INTERNAL int is_sane_lookup(const char test_string[], const int test_length, con
|
|||
}
|
||||
}
|
||||
if (posns[i] == -1) {
|
||||
return 0;
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns the position of `data` in `set_string` */
|
||||
|
@ -244,6 +246,294 @@ INTERNAL void expand(struct zint_symbol *symbol, const char data[], const int le
|
|||
}
|
||||
}
|
||||
|
||||
/* Helper for `errtxt()` & `errtxtf()` to set "err_id: " part of error message, returning length */
|
||||
static int errtxt_id_str(char *errtxt, int num) {
|
||||
int len = 0;
|
||||
if (num == -1) {
|
||||
errtxt[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
if (num < 0 || num > 9999) { /* Restrict to 4 digits */
|
||||
num = 9999;
|
||||
}
|
||||
if (num >= 1000) {
|
||||
errtxt[len++] = '0' + (num / 1000);
|
||||
num %= 1000;
|
||||
}
|
||||
errtxt[len++] = '0' + (num / 100);
|
||||
num %= 100;
|
||||
errtxt[len++] = '0' + (num / 10);
|
||||
num %= 10;
|
||||
errtxt[len++] = '0' + num;
|
||||
errtxt[len++] = ':';
|
||||
errtxt[len++] = ' ';
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Set `symbol->errtxt` to "err_id: msg", returning `error_number`. If `err_id` is -1, the "err_id: " prefix is
|
||||
omitted */
|
||||
INTERNAL int errtxt(const int error_number, struct zint_symbol *symbol, const int err_id, const char *msg) {
|
||||
const int max_len = (int) sizeof(symbol->errtxt) - 1;
|
||||
const int id_len = errtxt_id_str(symbol->errtxt, err_id);
|
||||
int msg_len = (int) strlen(msg);
|
||||
|
||||
if (id_len + msg_len > max_len) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0); /* Catch truncations */
|
||||
msg_len = max_len - id_len;
|
||||
}
|
||||
memcpy(symbol->errtxt + id_len, msg, msg_len);
|
||||
|
||||
symbol->errtxt[id_len + msg_len] = '\0';
|
||||
|
||||
return error_number;
|
||||
}
|
||||
|
||||
static int errtxtf_dpad(const char *fmt); /* Forward reference */
|
||||
|
||||
/* Helper for `errtxtf()` to parse numbered specifier "n$" (where "n" 1-9), returning `fmt` advance increment */
|
||||
static int errtxtf_num_arg(const char *fmt, int *p_arg) {
|
||||
int ret = 0;
|
||||
int arg = -2;
|
||||
if (!errtxtf_dpad(fmt) && z_isdigit(fmt[0])) {
|
||||
arg = fmt[1] == '$' ? fmt[0] - '0' - 1 : -1;
|
||||
ret = 2;
|
||||
}
|
||||
if (p_arg) {
|
||||
*p_arg = arg;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper for `errtxtf()` to parse length precision, returning `fmt` advance increment */
|
||||
static int errtxtf_slen(const char *fmt, const int arg, int *p_arg_cnt, int *p_len) {
|
||||
int ret = 0;
|
||||
int len = -1;
|
||||
if (fmt[0] == '.') {
|
||||
if (z_isdigit(fmt[1]) && fmt[1] != '0') {
|
||||
len = fmt[1] - '0';
|
||||
for (ret = 2; z_isdigit(fmt[ret]); ret++) {
|
||||
len = len * 10 + fmt[ret] - '0';
|
||||
}
|
||||
if (fmt[ret] != 's') {
|
||||
len = -1;
|
||||
}
|
||||
} else if (fmt[1] == '*' && fmt[2] == 's' && arg < 0) {
|
||||
len = 0;
|
||||
ret = 2;
|
||||
} else if (fmt[1] == '*' && z_isdigit(fmt[2]) && fmt[3] == '$' && fmt[4] == 's') {
|
||||
if (arg == -1 || arg == fmt[2] - '0') {
|
||||
len = 0;
|
||||
if (p_arg_cnt) {
|
||||
(*p_arg_cnt)++;
|
||||
}
|
||||
}
|
||||
ret = 4;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
if (p_len) {
|
||||
*p_len = len;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper for `errtxtf()` to parse zero-padded minimum field length for "%d", returning `fmt` advance increment */
|
||||
static int errtxtf_dpad(const char *fmt) {
|
||||
/* Allow one leading zero plus one or two digits only */
|
||||
if (fmt[0] == '0' && z_isdigit(fmt[1])) {
|
||||
if (fmt[1] != '0' && fmt[2] == 'd') {
|
||||
return 2;
|
||||
}
|
||||
if (z_isdigit(fmt[1]) && fmt[1] != '0' && z_isdigit(fmt[2]) && fmt[3] == 'd') {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set `symbol->errtxt` to "err_id: msg" with restricted subset of `printf()` formatting, returning `error_number`.
|
||||
If `err_id` is -1, the "err_id: " prefix is omitted. Only the following specifiers are supported: "c", "d", "f",
|
||||
"g" and "s", with no modifiers apart from "<n>$" numbering for l10n ("<n>" 1-9), in which case all specifiers must
|
||||
be numbered, "%s" with length precisions: "%.*s", "%<n+1>$.*<n>$s", "%.<p>s" and "%<n>$.<p>s", and "%d" with
|
||||
zero-padded minimum field lengths: "%0<m>d" or %<n>$0<m>d" ("<m>" 1-99) */
|
||||
INTERNAL int errtxtf(const int error_number, struct zint_symbol *symbol, const int err_id, const char *fmt, ...) {
|
||||
const int max_len = (int) sizeof(symbol->errtxt) - 1;
|
||||
int p = errtxt_id_str(symbol->errtxt, err_id);
|
||||
const char *f;
|
||||
int i;
|
||||
int arg_cnt = 0;
|
||||
int have_num_arg = 0, have_unnum_arg = 0;
|
||||
va_list ap;
|
||||
int idxs[9] = {0}; /* Argument order */
|
||||
char specs[9] = {0}; /* Format specifiers */
|
||||
const char *ss[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /* "%s" */
|
||||
int slens[9] = {0}; /* "%s" length precisions */
|
||||
int have_slens[9] = {0}; /* Bools for if "%s" has length precision */
|
||||
char dpads[9][3] = {{0}}; /* 2-digit minimum field length */
|
||||
char dfgs[9][100] = {{0}}; /* "%d", "%f" and "%g", allowing for padding up to 99 */
|
||||
int cs[9] = {0}; /* "%c" */
|
||||
|
||||
/* Get argument order and specifiers */
|
||||
for (f = fmt, i = 0; *f; f++) {
|
||||
if (*f == '%') {
|
||||
int inc, arg, len;
|
||||
if (*++f == '%') {
|
||||
continue;
|
||||
}
|
||||
if ((inc = errtxtf_num_arg(f, &arg))) {
|
||||
if (arg == -1) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0);
|
||||
return errtxt(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0,
|
||||
"Internal error: invalid numbered format specifer");
|
||||
}
|
||||
if (i >= 9) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0);
|
||||
return errtxt(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0,
|
||||
"Internal error: too many format specifiers (9 maximum)");
|
||||
}
|
||||
f += inc;
|
||||
have_num_arg = 1;
|
||||
idxs[i] = arg;
|
||||
} else {
|
||||
if (i >= 9) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0);
|
||||
return errtxt(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0,
|
||||
"Internal error: too many format specifiers (9 maximum)");
|
||||
}
|
||||
have_unnum_arg = 1;
|
||||
idxs[i] = i;
|
||||
}
|
||||
if ((inc = errtxtf_slen(f, arg, &arg_cnt, &len))) {
|
||||
if (len == -1) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0);
|
||||
return errtxt(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0, "Internal error: invalid length precision");
|
||||
}
|
||||
slens[idxs[i]] = len == 0 ? -1 : len; /* TODO: keep `slens` separate else last mentioned trumps */
|
||||
have_slens[idxs[i]] = 1;
|
||||
f += inc;
|
||||
}
|
||||
if ((inc = errtxtf_dpad(f))) {
|
||||
memcpy(dpads[idxs[i]], f + 1, inc - 1); /* TODO: keep `dpads` separate else last mentioned trumps */
|
||||
dpads[idxs[i]][inc - 1] = '\0';
|
||||
f += inc;
|
||||
}
|
||||
if (*f != 'c' && *f != 'd' && *f != 'f' && *f != 'g' && *f != 's') {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0);
|
||||
return errtxt(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0,
|
||||
"Internal error: unknown format specifier ('%c','%d','%f','%g','%s' only)");
|
||||
}
|
||||
specs[idxs[i++]] = *f;
|
||||
arg_cnt++;
|
||||
}
|
||||
}
|
||||
if (have_num_arg && have_unnum_arg) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0);
|
||||
return errtxt(ZINT_ERROR_ENCODING_PROBLEM, symbol, 0,
|
||||
"Internal error: mixed numbered and unnumbered format specifiers");
|
||||
}
|
||||
|
||||
/* Get arguments */
|
||||
va_start(ap, fmt);
|
||||
for (i = 0; i < arg_cnt; i++) {
|
||||
if (specs[i] == 'c') {
|
||||
cs[i] = va_arg(ap, int);
|
||||
} else if (specs[i] == 'd') {
|
||||
if (dpads[i][0]) {
|
||||
char dpad_fmt[30]; /* Make 30 to suppress GNU c "-Wformat-overflow=" false positive */
|
||||
sprintf(dpad_fmt, "%%0%sd", dpads[i]); /* TODO: keep `dpads` separate else last mentioned trumps */
|
||||
sprintf(dfgs[i], dpad_fmt, va_arg(ap, int));
|
||||
} else {
|
||||
sprintf(dfgs[i], "%d", va_arg(ap, int));
|
||||
}
|
||||
} else if (specs[i] == 'f' || specs[i] == 'g') {
|
||||
sprintf(dfgs[i], specs[i] == 'f' ? "%f" : "%g", va_arg(ap, double));
|
||||
} else if (specs[i] == 's') {
|
||||
if (have_slens[i] && slens[i] == -1) {
|
||||
slens[i] = va_arg(ap, int); /* TODO: keep `slens` separate else last mentioned trumps */
|
||||
}
|
||||
ss[i] = va_arg(ap, char *);
|
||||
}
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* Populate `errtxt` */
|
||||
for (f = fmt, i = 0; *f && p < max_len; f++) {
|
||||
if (*f == '%') {
|
||||
int idx;
|
||||
if (*++f == '%') {
|
||||
symbol->errtxt[p++] = '%';
|
||||
continue;
|
||||
}
|
||||
f += errtxtf_num_arg(f, NULL /*p_arg*/);
|
||||
f += errtxtf_slen(f, -1 /*arg*/, NULL /*arg_cnt*/, NULL /*p_len*/);
|
||||
f += errtxtf_dpad(f);
|
||||
idx = idxs[i];
|
||||
if (specs[idx] == 'c') {
|
||||
symbol->errtxt[p++] = cs[idx];
|
||||
} else {
|
||||
int len;
|
||||
if (specs[idx] == 's') {
|
||||
if (have_slens[idx]) {
|
||||
const char *si = ss[idx];
|
||||
for (len = 0; len < slens[idx] && si[len]; len++);
|
||||
} else {
|
||||
len = (int) strlen(ss[idx]);
|
||||
}
|
||||
} else {
|
||||
len = (int) strlen(dfgs[idx]);
|
||||
}
|
||||
if (len) {
|
||||
if (p + len > max_len) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0); /* Catch truncations */
|
||||
len = max_len - p;
|
||||
}
|
||||
memcpy(symbol->errtxt + p, specs[idx] == 's' ? ss[idx] : dfgs[idx], len);
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
symbol->errtxt[p++] = *f;
|
||||
}
|
||||
}
|
||||
if (*f) {
|
||||
if (!(symbol->debug & ZINT_DEBUG_TEST)) assert(0); /* Catch truncations */
|
||||
}
|
||||
|
||||
symbol->errtxt[p] = '\0';
|
||||
|
||||
return error_number;
|
||||
}
|
||||
|
||||
/* Helper to prepend/append to existing `symbol->errtxt` by calling `errtxtf(fmt)` with 2 arguments (copy of `errtxt`
|
||||
& `msg`) if `msg` not NULL, or 1 argument (just copy of `errtxt`) if `msg` NULL, returning `error_number` */
|
||||
INTERNAL int errtxt_adj(const int error_number, struct zint_symbol *symbol, const char *fmt, const char *msg) {
|
||||
char err_buf[sizeof(symbol->errtxt)];
|
||||
|
||||
err_buf[0] = '\0';
|
||||
|
||||
/* Suppress gcc 14 warning output may be truncated */
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 14
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-truncation"
|
||||
#endif
|
||||
|
||||
strncat(err_buf, symbol->errtxt, sizeof(symbol->errtxt) - 1);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 14
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
if (msg) {
|
||||
errtxtf(0, symbol, -1, fmt, err_buf, msg);
|
||||
} else {
|
||||
errtxtf(0, symbol, -1, fmt, err_buf);
|
||||
}
|
||||
|
||||
return error_number;
|
||||
}
|
||||
|
||||
/* Whether `symbology` can have row binding */
|
||||
INTERNAL int is_stackable(const int symbology) {
|
||||
if (symbology < BARCODE_PHARMA_TWO && symbology != BARCODE_POSTNET) {
|
||||
|
@ -489,7 +779,7 @@ INTERNAL int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char s
|
|||
symbol->text[j] = '\0';
|
||||
|
||||
if (warn_number) {
|
||||
strcpy(symbol->errtxt, "249: Human Readable Text truncated");
|
||||
errtxt(0, symbol, 249, "Human Readable Text truncated");
|
||||
}
|
||||
return warn_number;
|
||||
}
|
||||
|
@ -532,7 +822,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
|
|||
if (stripf(row_height) < stripf(min_row_height)) {
|
||||
error_number = ZINT_WARN_NONCOMPLIANT;
|
||||
if (!no_errtxt) {
|
||||
strcpy(symbol->errtxt, "247: Height not compliant with standards");
|
||||
errtxt(0, symbol, 247, "Height not compliant with standards");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +834,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
|
|||
if (stripf(symbol->height) > stripf(max_height)) {
|
||||
error_number = ZINT_WARN_NONCOMPLIANT;
|
||||
if (!no_errtxt) {
|
||||
strcpy(symbol->errtxt, "248: Height not compliant with standards");
|
||||
errtxt(0, symbol, 248, "Height not compliant with standards");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -554,12 +844,15 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
|
|||
|
||||
/* Prevent inlining of `stripf()` which can optimize away its effect */
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||
__attribute__((__noinline__))
|
||||
#define ZINT_NOINLINE __attribute__((__noinline__))
|
||||
#elif defined(_MSC_VER) && _MSC_VER >= 1310 /* MSVC 2003 (VC++ 7.1) */
|
||||
__declspec(noinline)
|
||||
#define ZINT_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define ZINT_NOINLINE
|
||||
#endif
|
||||
|
||||
/* Removes excess precision from floats - see https://stackoverflow.com/q/503436 */
|
||||
INTERNAL float stripf(const float arg) {
|
||||
INTERNAL ZINT_NOINLINE float stripf(const float arg) {
|
||||
return *((volatile const float *) &arg);
|
||||
}
|
||||
|
||||
|
@ -615,6 +908,7 @@ INTERNAL char *debug_print_escape(const unsigned char *source, const int first_l
|
|||
/* Dumps hex-formatted codewords in symbol->errtxt (for use in testing) */
|
||||
INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigned char *codewords, const int length) {
|
||||
int i, max = length, cnt_len = 0;
|
||||
assert(sizeof(symbol->errtxt) >= 100);
|
||||
if (length > 30) { /* 30*3 < errtxt 92 (100 - "Warning ") chars */
|
||||
sprintf(symbol->errtxt, "(%d) ", length); /* Place the number of codewords at the front */
|
||||
cnt_len = (int) strlen(symbol->errtxt);
|
||||
|
@ -630,6 +924,7 @@ INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigne
|
|||
INTERNAL void debug_test_codeword_dump_short(struct zint_symbol *symbol, const short *codewords, const int length) {
|
||||
int i, max = 0, cnt_len, errtxt_len;
|
||||
char temp[20];
|
||||
assert(sizeof(symbol->errtxt) >= 100);
|
||||
errtxt_len = sprintf(symbol->errtxt, "(%d) ", length); /* Place the number of codewords at the front */
|
||||
for (i = 0, cnt_len = errtxt_len; i < length; i++) {
|
||||
cnt_len += sprintf(temp, "%d ", codewords[i]);
|
||||
|
@ -648,6 +943,7 @@ INTERNAL void debug_test_codeword_dump_short(struct zint_symbol *symbol, const s
|
|||
INTERNAL void debug_test_codeword_dump_int(struct zint_symbol *symbol, const int *codewords, const int length) {
|
||||
int i, max = 0, cnt_len, errtxt_len;
|
||||
char temp[20];
|
||||
assert(sizeof(symbol->errtxt) >= 100);
|
||||
errtxt_len = sprintf(symbol->errtxt, "(%d) ", length); /* Place the number of codewords at the front */
|
||||
for (i = 0, cnt_len = errtxt_len; i < length; i++) {
|
||||
cnt_len += sprintf(temp, "%d ", codewords[i]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue