From 677ce8eedc473d132ca15fef0e92d8d7dcfe1003 Mon Sep 17 00:00:00 2001 From: Jim Evins Date: Mon, 27 Dec 2010 15:47:56 -0500 Subject: [PATCH] Some cleanup of built-in barcode code. - Validate data rather than filtering it into something canonical - Reconcile style and design patterns between all built-in backends --- libglbarcode/lgl-barcode-code39.c | 233 ++++++++++++++++++----------- libglbarcode/lgl-barcode-onecode.c | 204 ++++++++++++------------- libglbarcode/lgl-barcode-postnet.c | 91 +++++------ 3 files changed, 292 insertions(+), 236 deletions(-) diff --git a/libglbarcode/lgl-barcode-code39.c b/libglbarcode/lgl-barcode-code39.c index 723d90f2..31e7f2af 100644 --- a/libglbarcode/lgl-barcode-code39.c +++ b/libglbarcode/lgl-barcode-code39.c @@ -49,62 +49,60 @@ /* Private types. */ /*========================================================*/ -typedef struct { - gchar c; - gchar *sym; -} Code39Symbol; - /*===========================================*/ /* Private globals */ /*===========================================*/ -static Code39Symbol symbols[] = { - /* BsBsBsBsB */ - { '0', "NnNwWnWnN" }, - { '1', "WnNwNnNnW" }, - { '2', "NnWwNnNnW" }, - { '3', "WnWwNnNnN" }, - { '4', "NnNwWnNnW" }, - { '5', "WnNwWnNnN" }, - { '6', "NnWwWnNnN" }, - { '7', "NnNwNnWnW" }, - { '8', "WnNwNnWnN" }, - { '9', "NnWwNnWnN" }, - { 'A', "WnNnNwNnW" }, - { 'B', "NnWnNwNnW" }, - { 'C', "WnWnNwNnN" }, - { 'D', "NnNnWwNnW" }, - { 'E', "WnNnWwNnN" }, - { 'F', "NnWnWwNnN" }, - { 'G', "NnNnNwWnW" }, - { 'H', "WnNnNwWnN" }, - { 'I', "NnWnNwWnN" }, - { 'J', "NnNnWwWnN" }, - { 'K', "WnNnNnNwW" }, - { 'L', "NnWnNnNwW" }, - { 'M', "WnWnNnNwN" }, - { 'N', "NnNnWnNwW" }, - { 'O', "WnNnWnNwN" }, - { 'P', "NnWnWnNwN" }, - { 'Q', "NnNnNnWwW" }, - { 'R', "WnNnNnWwN" }, - { 'S', "NnWnNnWwN" }, - { 'T', "NnNnWnWwN" }, - { 'U', "WwNnNnNnW" }, - { 'V', "NwWnNnNnW" }, - { 'W', "WwWnNnNnN" }, - { 'X', "NwNnWnNnW" }, - { 'Y', "WwNnWnNnN" }, - { 'Z', "NwWnWnNnN" }, - { '-', "NwNnNnWnW" }, - { '.', "WwNnNnWnN" }, - { ' ', "NwWnNnWnN" }, - { '$', "NwNwNwNnN" }, - { '/', "NwNwNnNwN" }, - { '+', "NwNnNwNwN" }, - { '%', "NnNwNwNwN" }, - { 0, NULL } +/* Code 39 alphabet. Position indicates value. */ +static gchar *alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; + +/* Code 39 symbols. Position must match position in alphabet. */ +static gchar* symbols[43] = { + /* BsBsBsBsB */ + /* 0 */ "NnNwWnWnN", + /* 1 */ "WnNwNnNnW", + /* 2 */ "NnWwNnNnW", + /* 3 */ "WnWwNnNnN", + /* 4 */ "NnNwWnNnW", + /* 5 */ "WnNwWnNnN", + /* 6 */ "NnWwWnNnN", + /* 7 */ "NnNwNnWnW", + /* 8 */ "WnNwNnWnN", + /* 9 */ "NnWwNnWnN", + /* A */ "WnNnNwNnW", + /* B */ "NnWnNwNnW", + /* C */ "WnWnNwNnN", + /* D */ "NnNnWwNnW", + /* E */ "WnNnWwNnN", + /* F */ "NnWnWwNnN", + /* G */ "NnNnNwWnW", + /* H */ "WnNnNwWnN", + /* I */ "NnWnNwWnN", + /* J */ "NnNnWwWnN", + /* K */ "WnNnNnNwW", + /* L */ "NnWnNnNwW", + /* M */ "WnWnNnNwN", + /* N */ "NnNnWnNwW", + /* O */ "WnNnWnNwN", + /* P */ "NnWnWnNwN", + /* Q */ "NnNnNnWwW", + /* R */ "WnNnNnWwN", + /* S */ "NnWnNnWwN", + /* T */ "NnNnWnWwN", + /* U */ "WwNnNnNnW", + /* V */ "NwWnNnNnW", + /* W */ "WwWnNnNnN", + /* X */ "NwNnWnNnW", + /* Y */ "WwNnWnNnN", + /* Z */ "NwWnWnNnN", + /* - */ "NwNnNnWnW", + /* . */ "WwNnNnWnN", + /* */ "NwWnNnWnN", + /* $ */ "NwNwNwNnN", + /* / */ "NwNwNnNwN", + /* + */ "NwNnNwNwN", + /* % */ "NnNwNwNwN", }; static gchar *frame_symbol = "NwNnWnWnN"; @@ -150,20 +148,23 @@ static gchar *ascii_map[128] = /* Local function prototypes */ /*===========================================*/ -static gchar *code39_encode (const gchar *data, - gboolean checksum_flag); +static gboolean code39_is_data_valid (const gchar *data); +static gboolean code39_ext_is_data_valid (const gchar *data); -static lglBarcode *code39_vectorize (const gchar *code, - gdouble w, - gdouble h, - gboolean text_flag, - gboolean checksum_flag, - const gchar *data, - const gchar *string); +static gchar *code39_encode (const gchar *data, + gboolean checksum_flag); + +static lglBarcode *code39_vectorize (const gchar *code, + gdouble w, + gdouble h, + gboolean text_flag, + gboolean checksum_flag, + const gchar *data, + const gchar *string); /****************************************************************************/ -/* Generate list of lines that form the barcode for the given digits. */ +/* Generate new Code 39 barcode structure from data. */ /****************************************************************************/ lglBarcode * lgl_barcode_code39_new (lglBarcodeType type, @@ -186,37 +187,39 @@ lgl_barcode_code39_new (lglBarcodeType type, } - /* Canonicalize data. */ - if ( data[0] == '\0' ) + /* Validate data. */ + if (type == LGL_BARCODE_TYPE_CODE39) { - return NULL; + if ( !code39_is_data_valid (data) ) + { + return NULL; + } + canon_data = g_ascii_strup (data, -1); + display_data = g_strdup (canon_data); } - if (type == LGL_BARCODE_TYPE_CODE39_EXT) + else { GString *canon_data_str; - GString *display_data_str; + + if ( !code39_ext_is_data_valid (data) ) + { + return NULL; + } canon_data_str = g_string_new (""); - display_data_str = g_string_new (""); for ( p = (gchar *)data; *p != '\0'; p++ ) { - canon_data_str = g_string_append (canon_data_str, ascii_map[(*p) & 0x7F]); - display_data_str = g_string_append_c (display_data_str, (*p) & 0x7F); + canon_data_str = g_string_append (canon_data_str, ascii_map[(int)*p]); } - canon_data = g_string_free (canon_data_str, FALSE); - display_data = g_string_free (display_data_str, FALSE); - } - else - { - canon_data = g_ascii_strup (data, -1); - g_strcanon (canon_data, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", ' '); - display_data = g_strdup (canon_data); + + display_data = g_strdup (data); } /* First get code string */ code = code39_encode (canon_data, checksum_flag); - if (code == NULL) { + if (code == NULL) + { g_free (canon_data); g_free (display_data); return NULL; @@ -233,6 +236,59 @@ lgl_barcode_code39_new (lglBarcodeType type, } +/*--------------------------------------------------------------------------*/ +/* PRIVATE. Validate data for Code 39. */ +/*--------------------------------------------------------------------------*/ +static gboolean +code39_is_data_valid (const gchar *data) +{ + gchar *p; + gchar c; + + if (!data || (*data == '\0')) + { + return FALSE; + } + + for ( p = (gchar *)data; *p != 0; p++ ) + { + c = g_ascii_toupper (*p); + + if ( strchr(alphabet, c) == NULL ) + { + return FALSE; + } + } + + return TRUE; +} + + +/*--------------------------------------------------------------------------*/ +/* PRIVATE. Validate data for Extended Code 39. */ +/*--------------------------------------------------------------------------*/ +static gboolean +code39_ext_is_data_valid (const gchar *data) +{ + gchar *p; + + if (!data || (*data == '\0')) + { + return FALSE; + } + + for ( p = (gchar *)data; *p != 0; p++ ) + { + if ( (*p < 0) || (*p > 0x7f) ) + { + return FALSE; + } + } + + return TRUE; +} + + /*--------------------------------------------------------------------------*/ /* PRIVATE. Generate string of symbols, representing barcode. */ /*--------------------------------------------------------------------------*/ @@ -241,7 +297,7 @@ code39_encode (const gchar *data, gboolean checksum_flag) { gchar *p, c; - gint i, sum; + gint c_value, sum; GString *code; @@ -252,22 +308,17 @@ code39_encode (const gchar *data, sum = 0; for ( p=(gchar *)data; *p != 0; p++ ) { - c = toupper( *p ); - for ( i = 0; symbols[i].c != 0; i++ ) - { - if ( c == symbols[i].c ) - { - sum += i; - code = g_string_append (code, symbols[i].sym); - break; - } - } + c = g_ascii_toupper( *p ); + c_value = strchr(alphabet, c) - alphabet; + code = g_string_append (code, symbols[c_value]); code = g_string_append (code, "i"); + + sum += c_value; } if ( checksum_flag ) { - code = g_string_append (code, symbols[sum % 43].sym); + code = g_string_append (code, symbols[sum % 43]); code = g_string_append (code, "i"); } @@ -279,7 +330,7 @@ code39_encode (const gchar *data, /*--------------------------------------------------------------------------*/ -/* Generate list of rectangles that form the barcode for the given digits. */ +/* PRIVATE. Vectorize encoded barcode. */ /*--------------------------------------------------------------------------*/ static lglBarcode * code39_vectorize (const gchar *code, diff --git a/libglbarcode/lgl-barcode-onecode.c b/libglbarcode/lgl-barcode-onecode.c index 8f4308ac..ab744f60 100644 --- a/libglbarcode/lgl-barcode-onecode.c +++ b/libglbarcode/lgl-barcode-onecode.c @@ -293,34 +293,32 @@ static guint character_table[] = { }; - - /*===========================================*/ /* Local function prototypes */ /*===========================================*/ -static gboolean is_string_valid (const gchar *data); - -static gchar *onecode_encode (const gchar *data); - -static void int104_mult_uint (Int104 *x, - guint y); -static void int104_add_uint (Int104 *x, - guint y); -static void int104_add_uint64 (Int104 *x, - guint64 y); -static guint int104_div_uint (Int104 *x, - guint y); +static gboolean onecode_is_data_valid (const gchar *data); + +static gchar *onecode_encode (const gchar *data); + +static lglBarcode *onecode_vectorize (const gchar *code); + +static void int104_mult_uint (Int104 *x, + guint y); +static void int104_add_uint (Int104 *x, + guint y); +static void int104_add_uint64 (Int104 *x, + guint64 y); +static guint int104_div_uint (Int104 *x, + guint y); #ifdef DEBUG -static void int104_print (Int104 *x); +static void int104_print (Int104 *x); #endif static unsigned short USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr ); -static lglBarcode *onecode_vectorize (const gchar *code); - /****************************************************************************/ -/* Generate list of lines that form the barcode for the given digits. */ +/* Generate new One Code barcode structure from data. */ /****************************************************************************/ lglBarcode * lgl_barcode_onecode_new (lglBarcodeType type, @@ -339,7 +337,14 @@ lgl_barcode_onecode_new (lglBarcodeType type, return NULL; } - /* First get code string */ + + /* Validate data */ + if ( !onecode_is_data_valid (data) ) + { + return NULL; + } + + /* Now get code string */ code = onecode_encode (data); if (code == NULL) { return NULL; @@ -354,6 +359,46 @@ lgl_barcode_onecode_new (lglBarcodeType type, } +/*--------------------------------------------------------------------------*/ +/* Validate if string is of proper length & contains only valid characters. */ +/*--------------------------------------------------------------------------*/ +static gboolean +onecode_is_data_valid (const gchar *data) +{ + gchar *p; + gint str_length; + + if (!data) + { + return FALSE; + } + + str_length = strlen (data); + if ( (str_length != 20) && + (str_length != 25) && + (str_length != 29) && + (str_length != 31) ) + { + return FALSE; + } + + for ( p = (gchar *)data; *p != 0; p++ ) + { + if (!g_ascii_isdigit (*p)) + { + return FALSE; + } + } + + if (data[1] > '4') + { + return FALSE; /* Invalid Barcode Identifier. */ + } + + return TRUE; +} + + /*--------------------------------------------------------------------------*/ /* PRIVATE. Generate string of symbols, representing barcode. */ /*--------------------------------------------------------------------------*/ @@ -368,12 +413,6 @@ onecode_encode (const gchar *data) gint d, a; GString *code; - if ( !is_string_valid (data) ) - { - return NULL; - } - - /*-----------------------------------------------------------*/ /* Step 1 -- Conversion of Data Fields into Binary Data */ /*-----------------------------------------------------------*/ @@ -479,41 +518,54 @@ onecode_encode (const gchar *data) /*--------------------------------------------------------------------------*/ -/* Validate if string is of proper length & contains only valid characters. */ +/* Vectorize encoded data. */ /*--------------------------------------------------------------------------*/ -static gboolean -is_string_valid (const gchar *data) +static lglBarcode * +onecode_vectorize (const gchar *code) { - gchar *p; - gint str_length; - - if (!data) { - return FALSE; - } + lglBarcode *bc; + gchar *p; + gdouble x, y, length, width; - str_length = strlen (data); - if ( (str_length != 20) && - (str_length != 25) && - (str_length != 29) && - (str_length != 31) ) - { - return FALSE; - } + bc = lgl_barcode_new (); - for ( p = (gchar *)data; *p != 0; p++ ) + /* Now traverse the code string and create a list of lines */ + x = ONECODE_HORIZ_MARGIN; + for (p = (gchar *)code; *p != 0; p++) { - if (!g_ascii_isdigit (*p)) + y = ONECODE_VERT_MARGIN; + switch ( *p ) { - return FALSE; + case 'T': + y += ONECODE_TRACKER_OFFSET; + length = ONECODE_TRACKER_HEIGHT; + break; + case 'D': + y += ONECODE_DESCENDER_OFFSET; + length = ONECODE_DESCENDER_HEIGHT; + break; + case 'A': + y += ONECODE_ASCENDER_OFFSET; + length = ONECODE_ASCENDER_HEIGHT; + break; + case 'F': + y += ONECODE_FULL_OFFSET; + length = ONECODE_FULL_HEIGHT; + break; + default: + break; } - } + width = ONECODE_BAR_WIDTH; - if (data[1] > '4') - { - return FALSE; /* Invalid Barcode Identifier. */ + lgl_barcode_add_box (bc, x, y, width, length); + + x += ONECODE_BAR_PITCH; } - return TRUE; + bc->width = x + ONECODE_HORIZ_MARGIN; + bc->height = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN; + + return bc; } @@ -683,58 +735,6 @@ USPS_MSB_Math_CRC11GenerateFrameCheckSequence( unsigned char *ByteArrayPtr ) } -/*--------------------------------------------------------------------------*/ -/* Vectorize encoded data. */ -/*--------------------------------------------------------------------------*/ -static lglBarcode * -onecode_vectorize (const gchar *code) -{ - lglBarcode *bc; - gchar *p; - gdouble x, y, length, width; - - bc = lgl_barcode_new (); - - /* Now traverse the code string and create a list of lines */ - x = ONECODE_HORIZ_MARGIN; - for (p = (gchar *)code; *p != 0; p++) - { - y = ONECODE_VERT_MARGIN; - switch ( *p ) - { - case 'T': - y += ONECODE_TRACKER_OFFSET; - length = ONECODE_TRACKER_HEIGHT; - break; - case 'D': - y += ONECODE_DESCENDER_OFFSET; - length = ONECODE_DESCENDER_HEIGHT; - break; - case 'A': - y += ONECODE_ASCENDER_OFFSET; - length = ONECODE_ASCENDER_HEIGHT; - break; - case 'F': - y += ONECODE_FULL_OFFSET; - length = ONECODE_FULL_HEIGHT; - break; - default: - break; - } - width = ONECODE_BAR_WIDTH; - - lgl_barcode_add_box (bc, x, y, width, length); - - x += ONECODE_BAR_PITCH; - } - - bc->width = x + ONECODE_HORIZ_MARGIN; - bc->height = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN; - - return bc; -} - - /* diff --git a/libglbarcode/lgl-barcode-postnet.c b/libglbarcode/lgl-barcode-postnet.c index 6de6900f..63084837 100644 --- a/libglbarcode/lgl-barcode-postnet.c +++ b/libglbarcode/lgl-barcode-postnet.c @@ -67,17 +67,16 @@ static gchar *frame_symbol = "1"; /*===========================================*/ /* Local function prototypes */ /*===========================================*/ -static gchar *postnet_encode (const gchar *digits); +static gint postnet_validate_data (const gchar *data); -static gboolean is_length_valid (const gchar *digits, - gint n); +static gchar *postnet_encode (const gchar *digits); -static lglBarcode *postnet_vectorize (const gchar *code); +static lglBarcode *postnet_vectorize (const gchar *code); /****************************************************************************/ -/* Generate list of lines that form the barcode for the given digits. */ +/* Generate new Postnet barcode structure from data. */ /****************************************************************************/ lglBarcode * lgl_barcode_postnet_new (lglBarcodeType type, @@ -87,45 +86,47 @@ lgl_barcode_postnet_new (lglBarcodeType type, gdouble h, const gchar *data) { + gint n_digits; gchar *code; lglBarcode *bc; - /* Validate code length for all subtypes. */ + /* Validate data and length for all subtypes. */ + n_digits = postnet_validate_data (data); switch (type) { case LGL_BARCODE_TYPE_POSTNET: - if (!is_length_valid (data, 5) && - !is_length_valid (data, 9) && - !is_length_valid (data, 11)) + if ( (n_digits != 5) && + (n_digits != 9) && + (n_digits != 11) ) { return NULL; } break; case LGL_BARCODE_TYPE_POSTNET_5: - if (!is_length_valid (data, 5)) + if ( n_digits != 5 ) { return NULL; } break; case LGL_BARCODE_TYPE_POSTNET_9: - if (!is_length_valid (data, 9)) + if ( n_digits != 9 ) { return NULL; } break; case LGL_BARCODE_TYPE_POSTNET_11: - if (!is_length_valid (data, 11)) + if ( n_digits != 11 ) { return NULL; } break; case LGL_BARCODE_TYPE_CEPNET: - if (!is_length_valid (data, 8)) + if ( n_digits != 8 ) { return NULL; } @@ -153,6 +154,37 @@ lgl_barcode_postnet_new (lglBarcodeType type, } +/*--------------------------------------------------------------------------*/ +/* PRIVATE. Validate data, returning number of digits if valid. */ +/*--------------------------------------------------------------------------*/ +static gint +postnet_validate_data (const gchar *data) +{ + gchar *p; + gint i; + + if (!data) + { + return 0; + } + + for ( p = (gchar *)data, i=0; *p != 0; p++ ) + { + if (g_ascii_isdigit (*p)) + { + i++; + } + else if ( (*p != '-') && (*p != ' ') ) + { + /* Only allow digits, dashes, and spaces. */ + return 0; + } + } + + return i; +} + + /*--------------------------------------------------------------------------*/ /* PRIVATE. Generate string of symbols, representing barcode. */ /*--------------------------------------------------------------------------*/ @@ -168,11 +200,11 @@ postnet_encode (const gchar *data) code = g_string_new (frame_symbol); sum = 0; - for (p = (gchar *)data, len = 0; (*p != 0) && (len < 11); p++) + for ( p = (gchar *)data, len = 0; (*p != 0) && (len < 11); p++ ) { if (g_ascii_isdigit (*p)) { - /* Only translate valid characters (0-9) */ + /* Only translate the digits (0-9) */ d = (*p) - '0'; sum += d; code = g_string_append (code, symbols[d]); @@ -191,33 +223,6 @@ postnet_encode (const gchar *data) } -/*--------------------------------------------------------------------------*/ -/* PRIVATE. Validate specific length of string (for subtypes). */ -/*--------------------------------------------------------------------------*/ -static gboolean -is_length_valid (const gchar *data, - gint n) -{ - gchar *p; - gint i; - - if (!data) - { - return FALSE; - } - - for (p = (gchar *)data, i=0; *p != 0; p++) - { - if (g_ascii_isdigit (*p)) - { - i++; - } - } - - return (i == n); -} - - /*--------------------------------------------------------------------------*/ /* PRIVATE. Vectorize encoded barcode. */ /*--------------------------------------------------------------------------*/ @@ -232,7 +237,7 @@ postnet_vectorize (const gchar *code) /* Now traverse the code string and create a list of lines */ x = POSTNET_HORIZ_MARGIN; - for (p = (gchar *)code; *p != 0; p++) + for ( p = (gchar *)code; *p != 0; p++ ) { y = POSTNET_VERT_MARGIN; switch (*p) -- 2.39.5