diff options
Diffstat (limited to 'src/upc.c')
-rw-r--r-- | src/upc.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/upc.c b/src/upc.c new file mode 100644 index 0000000..a81979b --- /dev/null +++ b/src/upc.c @@ -0,0 +1,113 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define UPC_A_WIDTH 95 +#define UPC_A_NUMDIGITS 12 + +const char UPC_A_GUARD_PATTERN_SE[3] = { 1, 0, 1 }; +const char UPC_A_GUARD_PATTERN_M[5] = { 0, 1, 0, 1, 0 }; + +const char UPC_DIGIT[10][7] = { { 0, 0, 0, 1, 1, 0, 1 }, + { 0, 0, 1, 1, 0, 0, 1 }, + { 0, 0, 1, 0, 0, 1, 1 }, + { 0, 1, 1, 1, 1, 0, 1 }, + { 0, 1, 0, 0, 0, 1, 1 }, + { 0, 1, 1, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 1, 1, 1 }, + { 0, 1, 1, 1, 0, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 1 } }; + +static char upc_calculate_check_digit( char *digits ); +static void upc_draw_pattern( char buffer[], int *index, const char *pattern, int pattern_size ); +static void upc_draw_digits( char *buffer, int *index, char *digits, char isLeft ); + +const char* create_upc_a( char *input ) { + + // allocate 95 bytes of memory for resultant data + char *result = malloc(UPC_A_WIDTH); + // create a char array to store the GTIN-12 number + char digits[UPC_A_NUMDIGITS]; + + int index = 0; + + // copy digits from function param to local array + memcpy( digits, input, UPC_A_NUMDIGITS ); + + // set the final digit to the appropriate check digit + // digits[11] = upc_calculate_check_digit( digits ); + + // draw start guard pattern + upc_draw_pattern( result, &index, UPC_A_GUARD_PATTERN_SE, sizeof(UPC_A_GUARD_PATTERN_SE) ); + + // draw LLLLLL digits + upc_draw_digits( result, &index, digits, 1 ); + + // draw middle guard pattern + upc_draw_pattern( result, &index, UPC_A_GUARD_PATTERN_M, sizeof(UPC_A_GUARD_PATTERN_M) ); + + // draw RRRRRR digits + upc_draw_digits( result, &index, digits, 0 ); + + // draw end guard pattern + upc_draw_pattern( result, &index, UPC_A_GUARD_PATTERN_SE, sizeof(UPC_A_GUARD_PATTERN_SE) ); + + return result; +} + +char upc_a_calculate_check_digit( char *digits ) { + + char result = 0; + int M; + + // 1. Sum digits at odd-numbered positions + for( int i = 0; i < UPC_A_NUMDIGITS; ++i ) { + if( i % 2 == 0 ) { result += digits[i]; } + } + // 2. Multiply result by 3 + result *= 3; + // 3. Add digits at even-numbered positions to the result + for( int i = 0; i < UPC_A_NUMDIGITS; ++i ) { + if( i % 2 != 0 ) { result += digits[i]; } + } + // 4. Find the result mod 10 and call it "M" + M = result % 10; + // 5. If M is zero, the check digit is 0, + if( M == 0 ) { result = M; } + // otherwise the check digit is 10 - M + else { + result = 10 - M; + } + + return result; +} + +static void upc_draw_pattern( char buffer[], int *index, const char *pattern, int pattern_size ) { + + for( int i = 0; i < pattern_size; ++i ) { + buffer[*index] = pattern[i]; + ++*index; + } +} + +static void upc_draw_digits( char *buffer, int *index, char *digits, char isLeft ) { + + char temp[6][7]; + if ( isLeft ) { + for( int i = 0; i < 6; ++i ) { + memcpy(temp[i], UPC_DIGIT[digits[i]], sizeof( *UPC_DIGIT ) ); + upc_draw_pattern( buffer, index, temp[i], sizeof( *UPC_DIGIT ) ); + } + } + else { + for( int i = 0; i < 6; ++i ) { + memcpy(temp[i], UPC_DIGIT[digits[i + 6]], sizeof( *UPC_DIGIT ) ); + //invert values of RRRRRR digits + for( int j = 0; j < sizeof( *UPC_DIGIT ); ++j ) { + temp[i][j] = !temp[i][j]; + } + upc_draw_pattern( buffer, index, temp[i], sizeof( *UPC_DIGIT ) ); + } + } +} |