summaryrefslogtreecommitdiff
path: root/src/upc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/upc.c')
-rw-r--r--src/upc.c113
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 ) );
+ }
+ }
+}