From 6636731577378bb8bda73d333c7c425577650f2a Mon Sep 17 00:00:00 2001 From: lyrathorpe Date: Mon, 6 Jul 2026 17:41:43 +0100 Subject: [PATCH] feat(inventory): add upc.c (Phase 1: scan + UPC validation) --- code/inventory/upc.c | 54 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 code/inventory/upc.c diff --git a/code/inventory/upc.c b/code/inventory/upc.c new file mode 100644 index 0000000..fb922e5 --- /dev/null +++ b/code/inventory/upc.c @@ -0,0 +1,54 @@ +/* + * upc.c - UPC-A validation. + * + * A UPC-A barcode is 12 digits. The last digit is a mod-10 checksum over the + * first 11: digits in odd positions (1,3,5,7,9,11) are weighted x3 and digits + * in even positions (2,4,6,8,10) x1; the check digit is whatever makes the + * weighted total a multiple of 10. + */ +#include "upc.h" + +static int allDigits(const char *s, int n) +{ + int i; + for (i = 0; i < n; i++) { + if (s[i] < '0' || s[i] > '9') + return 0; + } + return 1; +} + +int upcCheckDigit(const char *s) +{ + int i, sum = 0; + + if (!allDigits(s, 11)) + return -1; + + for (i = 0; i < 11; i++) { + int d = s[i] - '0'; + if ((i % 2) == 0) /* 0-based even index = 1st,3rd,... digit: weight 3 */ + sum += 3 * d; + else + sum += d; + } + return (10 - (sum % 10)) % 10; +} + +int upcIsValid(const char *s) +{ + int n = 0; + int check; + + while (s[n] != '\0') + n++; + if (n != UPC_A_LEN) + return 0; + if (!allDigits(s, UPC_A_LEN)) + return 0; + + check = upcCheckDigit(s); + if (check < 0) + return 0; + return (s[11] - '0') == check; +}