From d126f7b1ed39015a4796b287dc96a8217ab11dd5 Mon Sep 17 00:00:00 2001 From: Project Nayuki Date: Fri, 8 Sep 2017 06:43:25 +0000 Subject: [PATCH] Added C functions to make byte and ECI segments, added test cases. --- c/qrcodegen-test.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++ c/qrcodegen.c | 37 ++++++++++++++++++++++++++ c/qrcodegen.h | 13 ++++++++++ 3 files changed, 115 insertions(+) diff --git a/c/qrcodegen-test.c b/c/qrcodegen-test.c index b03f477..1e8a8e3 100644 --- a/c/qrcodegen-test.c +++ b/c/qrcodegen-test.c @@ -880,6 +880,69 @@ static void testCalcSegmentBitLength(void) { } +static void testMakeBytes(void) { + { + struct qrcodegen_Segment seg = qrcodegen_makeBytes(NULL, 0, NULL); + assert(seg.mode == qrcodegen_Mode_BYTE); + assert(seg.numChars == 0); + assert(seg.bitLength == 0); + numTestCases++; + } + { + const uint8_t data[] = {0x00}; + uint8_t buf[1]; + struct qrcodegen_Segment seg = qrcodegen_makeBytes(data, 1, buf); + assert(seg.numChars == 1); + assert(seg.bitLength == 8); + assert(seg.data[0] == 0x00); + numTestCases++; + } + { + const uint8_t data[] = {0xEF, 0xBB, 0xBF}; + uint8_t buf[3]; + struct qrcodegen_Segment seg = qrcodegen_makeBytes(data, 3, buf); + assert(seg.numChars == 3); + assert(seg.bitLength == 24); + assert(seg.data[0] == 0xEF); + assert(seg.data[1] == 0xBB); + assert(seg.data[2] == 0xBF); + numTestCases++; + } +} + + +static void testMakeEci(void) { + { + uint8_t buf[1]; + struct qrcodegen_Segment seg = qrcodegen_makeEci(127, buf); + assert(seg.mode == qrcodegen_Mode_ECI); + assert(seg.numChars == 0); + assert(seg.bitLength == 8); + assert(seg.data[0] == 0x7F); + numTestCases++; + } + { + uint8_t buf[2]; + struct qrcodegen_Segment seg = qrcodegen_makeEci(10345, buf); + assert(seg.numChars == 0); + assert(seg.bitLength == 16); + assert(seg.data[0] == 0xA8); + assert(seg.data[1] == 0x69); + numTestCases++; + } + { + uint8_t buf[3]; + struct qrcodegen_Segment seg = qrcodegen_makeEci(999999, buf); + assert(seg.numChars == 0); + assert(seg.bitLength == 24); + assert(seg.data[0] == 0xCF); + assert(seg.data[1] == 0x42); + assert(seg.data[2] == 0x3F); + numTestCases++; + } +} + + /*---- Main runner ----*/ int main(void) { @@ -900,6 +963,8 @@ int main(void) { testIsNumeric(); testCalcSegmentBufferSize(); testCalcSegmentBitLength(); + testMakeBytes(); + testMakeEci(); printf("All %d test cases passed\n", numTestCases); return EXIT_SUCCESS; } diff --git a/c/qrcodegen.c b/c/qrcodegen.c index ca17038..b8b7523 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -933,3 +933,40 @@ testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) { overflow: return -1; } + + +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) { + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_BYTE; + result.bitLength = calcSegmentBitLength(result.mode, len); + assert(result.bitLength != -1); + result.numChars = (int)len; + if (len > 0) + memcpy(buf, data, len * sizeof(buf[0])); + result.data = buf; + return result; +} + + +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) { + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_ECI; + result.numChars = 0; + result.bitLength = 0; + if (0 <= assignVal && assignVal < (1 << 7)) { + memset(buf, 0, 1 * sizeof(buf[0])); + appendBitsToBuffer(assignVal, 8, buf, &result.bitLength); + } else if ((1 << 7) <= assignVal && assignVal < (1 << 14)) { + memset(buf, 0, 2 * sizeof(buf[0])); + appendBitsToBuffer(2, 2, buf, &result.bitLength); + appendBitsToBuffer(assignVal, 14, buf, &result.bitLength); + } else if ((1 << 14) <= assignVal && assignVal < 1000000L) { + memset(buf, 0, 3 * sizeof(buf[0])); + appendBitsToBuffer(6, 3, buf, &result.bitLength); + appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength); + appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength); + } else + assert(false); + result.data = buf; + return result; +} diff --git a/c/qrcodegen.h b/c/qrcodegen.h index 6d25862..0fbbe92 100644 --- a/c/qrcodegen.h +++ b/c/qrcodegen.h @@ -179,6 +179,19 @@ bool qrcodegen_isNumeric(const char *text); size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); +/* + * Returns a segment representing the given binary data encoded in byte mode. + */ +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); + + +/* + * Returns a segment representing an Extended Channel Interpretation + * (ECI) designator with the given assignment value. + */ +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); + + /*---- Functions to extract raw data from QR Codes ----*/