From 916ad16dfa5e61f79b8c16a6e5bb6a288f3f1015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asbj=C3=B8rn=20Sloth=20T=C3=B8nnesen?= Date: Mon, 12 Jan 2026 19:04:08 +0000 Subject: Improve error code formatting For text output, allocate exactly the right buffer size. For JSON output, return error codes as an array, not just a concatinated text string. --- src/ql.c | 135 ++++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 41 deletions(-) (limited to 'src/ql.c') diff --git a/src/ql.c b/src/ql.c index 3a94c03..02ac3cb 100644 --- a/src/ql.c +++ b/src/ql.c @@ -12,6 +12,7 @@ #include #include #include +#include #define QL_XMIT_SIZE 4096 #define QL_BUF_SIZE (QL_XMIT_SIZE * 2) @@ -315,52 +316,105 @@ const char *ql_decode_mode(const ql_status_t *status) return "no-auto-cut"; } -const char *ql_decode_errors(const ql_status_t *status) -{ - typedef struct { - uint16_t bit; - const char *str; - } strmap_t; +typedef struct { + uint16_t bit; + const char *str; +} strmap_t; #define ERR1(x) (x << 0) #define ERR2(x) (x << 8) - const strmap_t strmap[] = { - {ERR1(QL_ERR_1_NO_MEDIA), "no-media "}, - {ERR1(QL_ERR_1_END_OF_MEDIA), "end-of-media "}, - {ERR1(QL_ERR_1_CUTTER_JAM), "cutter-jam "}, - {ERR1(QL_ERR_1_PRINTER_IN_USE), "printer-in-use "}, - {ERR1(QL_ERR_1_PRINTER_TURNED_OFF), "printer-turned-off "}, - {ERR1(QL_ERR_1_HIGH_VOLTAGE_ADAPTER), "high-voltage-adapter "}, - {ERR1(QL_ERR_1_FAN_MOTOR_ERROR), "fan-motor-error "}, - - {ERR2(QL_ERR_2_REPLACE_MEDIA), "replace-media "}, - {ERR2(QL_ERR_2_EXPANSION_BUFFER_FULL), "expansion-buffer-full "}, - {ERR2(QL_ERR_2_COMMUNICATION_ERROR), "communication-error "}, - {ERR2(QL_ERR_2_COMMUNICATION_BUFFER_FULL), "communication-buffer-full "}, - {ERR2(QL_ERR_2_COVER_OPEN), "cover-open "}, - {ERR2(QL_ERR_2_CANCEL_KEY), "cancel-key-pressed "}, - {ERR2(QL_ERR_2_MEDIA_CANNOT_BE_FED), "media-cannot-be-fed "}, - {ERR2(QL_ERR_2_SYSTEM_ERROR), "system-error "} - }; +static const strmap_t strmap[] = { + {ERR1(QL_ERR_1_NO_MEDIA), "no-media"}, + {ERR1(QL_ERR_1_END_OF_MEDIA), "end-of-media"}, + {ERR1(QL_ERR_1_CUTTER_JAM), "cutter-jam"}, + {ERR1(QL_ERR_1_PRINTER_IN_USE), "printer-in-use"}, + {ERR1(QL_ERR_1_PRINTER_TURNED_OFF), "printer-turned-off"}, + {ERR1(QL_ERR_1_HIGH_VOLTAGE_ADAPTER), "high-voltage-adapter"}, + {ERR1(QL_ERR_1_FAN_MOTOR_ERROR), "fan-motor-error"}, + + {ERR2(QL_ERR_2_REPLACE_MEDIA), "replace-media"}, + {ERR2(QL_ERR_2_EXPANSION_BUFFER_FULL), "expansion-buffer-full"}, + {ERR2(QL_ERR_2_COMMUNICATION_ERROR), "communication-error"}, + {ERR2(QL_ERR_2_COMMUNICATION_BUFFER_FULL), "communication-buffer-full"}, + {ERR2(QL_ERR_2_COVER_OPEN), "cover-open"}, + {ERR2(QL_ERR_2_CANCEL_KEY), "cancel-key-pressed"}, + {ERR2(QL_ERR_2_MEDIA_CANNOT_BE_FED), "media-cannot-be-fed"}, + {ERR2(QL_ERR_2_SYSTEM_ERROR), "system-error"} +}; + +const char *ql_decode_errors_human(const ql_status_t *status) +{ + static char *buf = NULL; + unsigned int i; + uint16_t errs; + size_t len; + + errs = ERR1(status->err_info_1) | ERR2(status->err_info_2); + if (!errs) + return "none"; - static char *buf = 0; - if (!buf) { - int len = 0; - for (unsigned i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) - len += strlen(strmap[i].str); - buf = malloc(len + 1); - if (!buf) - return ""; + len = 0; + for (i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) + if (errs & strmap[i].bit) + len += strlen(strmap[i].str) + 1; /* space or terminating NULL byte */ + if (!len) + return "unknown-error"; + + buf = malloc(len); + if (!buf) + return ""; + + buf[0] = '\0'; + for (i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) { + if (errs & strmap[i].bit) { + if (buf[0]) + strcat(buf, " "); + strcat(buf, strmap[i].str); + } } + assert(strlen(buf) == len - 1); + return buf; +} + +const char *ql_decode_errors_json(const ql_status_t *status) +{ + static char *buf = NULL; + unsigned int i; + uint16_t errs; + size_t len; - uint16_t errs = ERR1(status->err_info_1) | ERR2(status->err_info_2); - buf[0] = 0; - for (unsigned i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) { + errs = ERR1(status->err_info_1) | ERR2(status->err_info_2); + if (!errs) + return "null"; + + len = 2; /* [] */ + for (i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) if (errs & strmap[i].bit) + len += strlen(strmap[i].str) + 3; /* quotes + comma or terminating NULL byte */ + if (!len) + return "\"unknown-error\""; + + buf = malloc(len); + if (!buf) + return "\"\""; + + buf[0] = '['; + buf[1] = '\0'; + for (i = 0; i < (sizeof(strmap) / sizeof(strmap[0])); ++i) { + if (errs & strmap[i].bit) { + if (buf[1]) + strcat(buf, ","); + strcat(buf, "\""); strcat(buf, strmap[i].str); + strcat(buf, "\""); + } } - return (buf[0] == 0) ? "none" : buf; + strcat(buf, "]"); + assert(strlen(buf) == len - 1); + return buf; } +#undef ERR1 +#undef ERR2 const char *ql_decode_media_type(const ql_status_t *status) { @@ -391,7 +445,7 @@ static void ql_decode_print_status_human(FILE *f, const ql_status_t *status, uns if (flags & QL_DECODE_MODE) fprintf(f, fmt_s, "Mode", ql_decode_mode(status)); if (flags & QL_DECODE_ERROR) - fprintf(f, fmt_s, "Errors", ql_decode_errors(status)); + fprintf(f, fmt_s, "Errors", ql_decode_errors_human(status)); if (flags & QL_DECODE_MEDIA) { fprintf(f, fmt_s, "Media type", ql_decode_media_type(status)); fprintf(f, fmt_u, "Media width (mm)", status->media_width_mm); @@ -408,6 +462,7 @@ static void ql_decode_print_status_json(FILE *f, const ql_print_json_t *json_ctx const char *fmt_s = "\t\"%s\": \"%s\",\n"; const char *fmt_u = "\t\"%s\": %u,\n"; + const char *fmt_d = "\t\"%s\": %s,\n"; bool status_ok = true; fprintf(f, "{\n"); fprintf(f, fmt_s, "printer", ql_json_escape(json_ctx->printer)); @@ -416,11 +471,9 @@ static void ql_decode_print_status_json(FILE *f, const ql_print_json_t *json_ctx if (flags & QL_DECODE_MODE) fprintf(f, fmt_s, "mode", ql_decode_mode(status)); if (flags & QL_DECODE_ERROR) { - const char *errors = ql_decode_errors(status); - - if (strcmp(errors, "none") != 0) + if (status->err_info_1 || status->err_info_2) status_ok = false; - fprintf(f, fmt_s, "errors", ql_decode_errors(status)); + fprintf(f, fmt_d, "errors", ql_decode_errors_json(status)); } if (flags & QL_DECODE_MEDIA) { fprintf(f, fmt_s, "media_type", ql_decode_media_type(status)); -- cgit v1.2.1