Added C functions to make numeric and alphanumeric segments, added test cases.

This commit is contained in:
Project Nayuki 2017-09-08 07:06:22 +00:00
parent d126f7b1ed
commit fb544495e7
3 changed files with 166 additions and 0 deletions

View File

@ -911,6 +911,92 @@ static void testMakeBytes(void) {
}
static void testMakeNumeric(void) {
{
struct qrcodegen_Segment seg = qrcodegen_makeNumeric("", NULL);
assert(seg.mode == qrcodegen_Mode_NUMERIC);
assert(seg.numChars == 0);
assert(seg.bitLength == 0);
numTestCases++;
}
{
uint8_t buf[1];
struct qrcodegen_Segment seg = qrcodegen_makeNumeric("9", buf);
assert(seg.numChars == 1);
assert(seg.bitLength == 4);
assert(seg.data[0] == 0x90);
numTestCases++;
}
{
uint8_t buf[1];
struct qrcodegen_Segment seg = qrcodegen_makeNumeric("81", buf);
assert(seg.numChars == 2);
assert(seg.bitLength == 7);
assert(seg.data[0] == 0xA2);
numTestCases++;
}
{
uint8_t buf[2];
struct qrcodegen_Segment seg = qrcodegen_makeNumeric("673", buf);
assert(seg.numChars == 3);
assert(seg.bitLength == 10);
assert(seg.data[0] == 0xA8);
assert(seg.data[1] == 0x40);
numTestCases++;
}
{
uint8_t buf[5];
struct qrcodegen_Segment seg = qrcodegen_makeNumeric("3141592653", buf);
assert(seg.numChars == 10);
assert(seg.bitLength == 34);
assert(seg.data[0] == 0x4E);
assert(seg.data[1] == 0x89);
assert(seg.data[2] == 0xF4);
assert(seg.data[3] == 0x24);
assert(seg.data[4] == 0xC0);
numTestCases++;
}
}
static void testMakeAlphanumeric(void) {
{
struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("", NULL);
assert(seg.mode == qrcodegen_Mode_ALPHANUMERIC);
assert(seg.numChars == 0);
assert(seg.bitLength == 0);
numTestCases++;
}
{
uint8_t buf[1];
struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("A", buf);
assert(seg.numChars == 1);
assert(seg.bitLength == 6);
assert(seg.data[0] == 0x28);
numTestCases++;
}
{
uint8_t buf[2];
struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("%:", buf);
assert(seg.numChars == 2);
assert(seg.bitLength == 11);
assert(seg.data[0] == 0xDB);
assert(seg.data[1] == 0x40);
numTestCases++;
}
{
uint8_t buf[3];
struct qrcodegen_Segment seg = qrcodegen_makeAlphanumeric("Q R", buf);
assert(seg.numChars == 3);
assert(seg.bitLength == 17);
assert(seg.data[0] == 0x96);
assert(seg.data[1] == 0xCD);
assert(seg.data[2] == 0x80);
numTestCases++;
}
}
static void testMakeEci(void) {
{
uint8_t buf[1];
@ -964,6 +1050,8 @@ int main(void) {
testCalcSegmentBufferSize();
testCalcSegmentBitLength();
testMakeBytes();
testMakeNumeric();
testMakeAlphanumeric();
testMakeEci();
printf("All %d test cases passed\n", numTestCases);
return EXIT_SUCCESS;

View File

@ -948,6 +948,70 @@ struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, u
}
struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) {
struct qrcodegen_Segment result;
size_t len = strlen(digits);
result.mode = qrcodegen_Mode_NUMERIC;
int bitLen = calcSegmentBitLength(result.mode, len);
assert(bitLen != -1);
result.numChars = (int)len;
if (bitLen > 0)
memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0]));
result.bitLength = 0;
unsigned int accumData = 0;
int accumCount = 0;
for (; *digits != '\0'; digits++) {
char c = *digits;
assert('0' <= c && c <= '9');
accumData = accumData * 10 + (c - '0');
accumCount++;
if (accumCount == 3) {
appendBitsToBuffer(accumData, 10, buf, &result.bitLength);
accumData = 0;
accumCount = 0;
}
}
if (accumCount > 0) // 1 or 2 digits remaining
appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength);
assert(result.bitLength == bitLen);
result.data = buf;
return result;
}
struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) {
struct qrcodegen_Segment result;
size_t len = strlen(text);
result.mode = qrcodegen_Mode_ALPHANUMERIC;
int bitLen = calcSegmentBitLength(result.mode, len);
assert(bitLen != -1);
result.numChars = (int)len;
if (bitLen > 0)
memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0]));
result.bitLength = 0;
unsigned int accumData = 0;
int accumCount = 0;
for (; *text != '\0'; text++) {
const char *temp = strchr(ALPHANUMERIC_CHARSET, *text);
assert(temp != NULL);
accumData = accumData * 45 + (temp - ALPHANUMERIC_CHARSET);
accumCount++;
if (accumCount == 2) {
appendBitsToBuffer(accumData, 11, buf, &result.bitLength);
accumData = 0;
accumCount = 0;
}
}
if (accumCount > 0) // 1 character remaining
appendBitsToBuffer(accumData, 6, buf, &result.bitLength);
assert(result.bitLength == bitLen);
result.data = buf;
return result;
}
struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) {
struct qrcodegen_Segment result;
result.mode = qrcodegen_Mode_ECI;

View File

@ -185,6 +185,20 @@ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars
struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]);
/*
* Returns a segment representing the given string of decimal digits encoded in numeric mode.
*/
struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]);
/*
* Returns a segment representing the given text string encoded in alphanumeric mode.
* The characters allowed are: 0 to 9, A to Z (uppercase only), space,
* dollar, percent, asterisk, plus, hyphen, period, slash, colon.
*/
struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]);
/*
* Returns a segment representing an Extended Channel Interpretation
* (ECI) designator with the given assignment value.