pull/65/head
Project Nayuki 5 years ago
commit f9c8183f64

@ -224,7 +224,7 @@ static void doSegmentDemo(void) {
uint8_t *segBuf = calloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_KANJI, len), sizeof(uint8_t)); uint8_t *segBuf = calloc(qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_KANJI, len), sizeof(uint8_t));
struct qrcodegen_Segment seg; struct qrcodegen_Segment seg;
seg.mode = qrcodegen_Mode_KANJI; seg.mode = qrcodegen_Mode_KANJI;
seg.numChars = len; seg.numChars = (int)len;
seg.bitLength = 0; seg.bitLength = 0;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
for (int j = 12; j >= 0; j--, seg.bitLength++) for (int j = 12; j >= 0; j--, seg.bitLength++)

@ -107,21 +107,21 @@ static void testAppendBitsToBuffer(void) {
// Ported from the Java version of the code. // Ported from the Java version of the code.
static uint8_t *addEccAndInterleaveReference(const uint8_t *data, int version, enum qrcodegen_Ecc ecl) { static uint8_t *addEccAndInterleaveReference(const uint8_t *data, int version, enum qrcodegen_Ecc ecl) {
// Calculate parameter numbers // Calculate parameter numbers
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; size_t numBlocks = (size_t)NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version];
int blockEccLen = ECC_CODEWORDS_PER_BLOCK[(int)ecl][version]; size_t blockEccLen = (size_t)ECC_CODEWORDS_PER_BLOCK[(int)ecl][version];
int rawCodewords = getNumRawDataModules(version) / 8; size_t rawCodewords = (size_t)getNumRawDataModules(version) / 8;
int numShortBlocks = numBlocks - rawCodewords % numBlocks; size_t numShortBlocks = numBlocks - rawCodewords % numBlocks;
int shortBlockLen = rawCodewords / numBlocks; size_t shortBlockLen = rawCodewords / numBlocks;
// Split data into blocks and append ECC to each block // Split data into blocks and append ECC to each block
uint8_t **blocks = malloc(numBlocks * sizeof(uint8_t*)); uint8_t **blocks = malloc(numBlocks * sizeof(uint8_t*));
uint8_t *generator = malloc(blockEccLen * sizeof(uint8_t)); uint8_t *generator = malloc(blockEccLen * sizeof(uint8_t));
reedSolomonComputeDivisor(blockEccLen, generator); reedSolomonComputeDivisor((int)blockEccLen, generator);
for (int i = 0, k = 0; i < numBlocks; i++) { for (size_t i = 0, k = 0; i < numBlocks; i++) {
uint8_t *block = malloc((shortBlockLen + 1) * sizeof(uint8_t)); uint8_t *block = malloc((shortBlockLen + 1) * sizeof(uint8_t));
int datLen = shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1); size_t datLen = shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1);
memcpy(block, &data[k], datLen * sizeof(uint8_t)); memcpy(block, &data[k], datLen * sizeof(uint8_t));
reedSolomonComputeRemainder(&data[k], datLen, generator, blockEccLen, &block[shortBlockLen + 1 - blockEccLen]); reedSolomonComputeRemainder(&data[k], (int)datLen, generator, (int)blockEccLen, &block[shortBlockLen + 1 - blockEccLen]);
k += datLen; k += datLen;
blocks[i] = block; blocks[i] = block;
} }
@ -129,8 +129,8 @@ static uint8_t *addEccAndInterleaveReference(const uint8_t *data, int version, e
// Interleave (not concatenate) the bytes from every block into a single sequence // Interleave (not concatenate) the bytes from every block into a single sequence
uint8_t *result = malloc(rawCodewords * sizeof(uint8_t)); uint8_t *result = malloc(rawCodewords * sizeof(uint8_t));
for (int i = 0, k = 0; i < shortBlockLen + 1; i++) { for (size_t i = 0, k = 0; i < shortBlockLen + 1; i++) {
for (int j = 0; j < numBlocks; j++) { for (size_t j = 0; j < numBlocks; j++) {
// Skip the padding byte in short blocks // Skip the padding byte in short blocks
if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) { if (i != shortBlockLen - blockEccLen || j >= numShortBlocks) {
result[k] = blocks[j][i]; result[k] = blocks[j][i];
@ -138,7 +138,7 @@ static uint8_t *addEccAndInterleaveReference(const uint8_t *data, int version, e
} }
} }
} }
for (int i = 0; i < numBlocks; i++) for (size_t i = 0; i < numBlocks; i++)
free(blocks[i]); free(blocks[i]);
free(blocks); free(blocks);
return result; return result;
@ -148,13 +148,13 @@ static uint8_t *addEccAndInterleaveReference(const uint8_t *data, int version, e
static void testAddEccAndInterleave(void) { static void testAddEccAndInterleave(void) {
for (int version = 1; version <= 40; version++) { for (int version = 1; version <= 40; version++) {
for (int ecl = 0; ecl < 4; ecl++) { for (int ecl = 0; ecl < 4; ecl++) {
int dataLen = getNumDataCodewords(version, (enum qrcodegen_Ecc)ecl); size_t dataLen = (size_t)getNumDataCodewords(version, (enum qrcodegen_Ecc)ecl);
uint8_t *pureData = malloc(dataLen * sizeof(uint8_t)); uint8_t *pureData = malloc(dataLen * sizeof(uint8_t));
for (int i = 0; i < dataLen; i++) for (size_t i = 0; i < dataLen; i++)
pureData[i] = rand() % 256; pureData[i] = (uint8_t)(rand() % 256);
uint8_t *expectOutput = addEccAndInterleaveReference(pureData, version, (enum qrcodegen_Ecc)ecl); uint8_t *expectOutput = addEccAndInterleaveReference(pureData, version, (enum qrcodegen_Ecc)ecl);
int dataAndEccLen = getNumRawDataModules(version) / 8; size_t dataAndEccLen = (size_t)getNumRawDataModules(version) / 8;
uint8_t *paddedData = malloc(dataAndEccLen * sizeof(uint8_t)); uint8_t *paddedData = malloc(dataAndEccLen * sizeof(uint8_t));
memcpy(paddedData, pureData, dataLen * sizeof(uint8_t)); memcpy(paddedData, pureData, dataLen * sizeof(uint8_t));
uint8_t *actualOutput = malloc(dataAndEccLen * sizeof(uint8_t)); uint8_t *actualOutput = malloc(dataAndEccLen * sizeof(uint8_t));
@ -362,7 +362,7 @@ static void testReedSolomonMultiply(void) {
static void testInitializeFunctionModulesEtc(void) { static void testInitializeFunctionModulesEtc(void) {
for (int ver = 1; ver <= 40; ver++) { for (int ver = 1; ver <= 40; ver++) {
uint8_t *qrcode = malloc(qrcodegen_BUFFER_LEN_FOR_VERSION(ver) * sizeof(uint8_t)); uint8_t *qrcode = malloc((size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(ver) * sizeof(uint8_t));
assert(qrcode != NULL); assert(qrcode != NULL);
initializeFunctionModules(ver, qrcode); initializeFunctionModules(ver, qrcode);
@ -694,8 +694,12 @@ static void testCalcSegmentBufferSize(void) {
static void testCalcSegmentBitLength(void) { static void testCalcSegmentBitLength(void) {
struct TestCase {
size_t numChars;
int result;
};
{ {
const int cases[][2] = { const struct TestCase CASES[] = {
{0, 0}, {0, 0},
{1, 4}, {1, 4},
{2, 7}, {2, 7},
@ -713,17 +717,18 @@ static void testCalcSegmentBitLength(void) {
{9832, -1}, {9832, -1},
{12000, -1}, {12000, -1},
{28453, -1}, {28453, -1},
{INT_MAX / 3, -1}, {SIZE_MAX / 6, -1},
{INT_MAX / 2, -1}, {SIZE_MAX / 3, -1},
{INT_MAX / 1, -1}, {SIZE_MAX / 2, -1},
{SIZE_MAX / 1, -1},
}; };
for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) { for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
assert(calcSegmentBitLength(qrcodegen_Mode_NUMERIC, cases[i][0]) == cases[i][1]); assert(calcSegmentBitLength(qrcodegen_Mode_NUMERIC, CASES[i].numChars) == CASES[i].result);
numTestCases++; numTestCases++;
} }
} }
{ {
const int cases[][2] = { const struct TestCase CASES[] = {
{0, 0}, {0, 0},
{1, 6}, {1, 6},
{2, 11}, {2, 11},
@ -741,19 +746,18 @@ static void testCalcSegmentBitLength(void) {
{5959, -1}, {5959, -1},
{12000, -1}, {12000, -1},
{28453, -1}, {28453, -1},
{INT_MAX / 5, -1}, {SIZE_MAX / 10, -1},
{INT_MAX / 4, -1}, {SIZE_MAX / 5, -1},
{INT_MAX / 3, -1}, {SIZE_MAX / 2, -1},
{INT_MAX / 2, -1}, {SIZE_MAX / 1, -1},
{INT_MAX / 1, -1},
}; };
for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) { for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
assert(calcSegmentBitLength(qrcodegen_Mode_ALPHANUMERIC, cases[i][0]) == cases[i][1]); assert(calcSegmentBitLength(qrcodegen_Mode_ALPHANUMERIC, CASES[i].numChars) == CASES[i].result);
numTestCases++; numTestCases++;
} }
} }
{ {
const int cases[][2] = { const struct TestCase CASES[] = {
{0, 0}, {0, 0},
{1, 8}, {1, 8},
{2, 16}, {2, 16},
@ -767,22 +771,19 @@ static void testCalcSegmentBitLength(void) {
{5957, -1}, {5957, -1},
{12000, -1}, {12000, -1},
{28453, -1}, {28453, -1},
{INT_MAX / 8 + 1, -1}, {SIZE_MAX / 15, -1},
{INT_MAX / 7, -1}, {SIZE_MAX / 12, -1},
{INT_MAX / 6, -1}, {SIZE_MAX / 7, -1},
{INT_MAX / 5, -1}, {SIZE_MAX / 3, -1},
{INT_MAX / 4, -1}, {SIZE_MAX / 1, -1},
{INT_MAX / 3, -1},
{INT_MAX / 2, -1},
{INT_MAX / 1, -1},
}; };
for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) { for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
assert(calcSegmentBitLength(qrcodegen_Mode_BYTE, cases[i][0]) == cases[i][1]); assert(calcSegmentBitLength(qrcodegen_Mode_BYTE, CASES[i].numChars) == CASES[i].result);
numTestCases++; numTestCases++;
} }
} }
{ {
const int cases[][2] = { const struct TestCase CASES[] = {
{0, 0}, {0, 0},
{1, 13}, {1, 13},
{2, 26}, {2, 26},
@ -796,16 +797,15 @@ static void testCalcSegmentBitLength(void) {
{2522, -1}, {2522, -1},
{12000, -1}, {12000, -1},
{28453, -1}, {28453, -1},
{INT_MAX / 13 + 1, -1}, {SIZE_MAX / 25, -1},
{INT_MAX / 12, -1}, {SIZE_MAX / 20, -1},
{INT_MAX / 9, -1}, {SIZE_MAX / 11, -1},
{INT_MAX / 4, -1}, {SIZE_MAX / 4, -1},
{INT_MAX / 3, -1}, {SIZE_MAX / 2, -1},
{INT_MAX / 2, -1}, {SIZE_MAX / 1, -1},
{INT_MAX / 1, -1},
}; };
for (size_t i = 0; i < ARRAY_LENGTH(cases); i++) { for (size_t i = 0; i < ARRAY_LENGTH(CASES); i++) {
assert(calcSegmentBitLength(qrcodegen_Mode_KANJI, cases[i][0]) == cases[i][1]); assert(calcSegmentBitLength(qrcodegen_Mode_KANJI, CASES[i].numChars) == CASES[i].result);
numTestCases++; numTestCases++;
} }
} }
@ -1049,7 +1049,7 @@ static void testGetTotalBits(void) {
/*---- Main runner ----*/ /*---- Main runner ----*/
int main(void) { int main(void) {
srand(time(NULL)); srand((unsigned int)time(NULL));
testAppendBitsToBuffer(); testAppendBitsToBuffer();
testAddEccAndInterleave(); testAddEccAndInterleave();
testGetNumDataCodewords(); testGetNumDataCodewords();

@ -39,11 +39,15 @@ int main(void) {
while (true) { while (true) {
// Read data length or exit // Read data length or exit
int length; size_t length;
if (scanf("%d", &length) != 1) {
return EXIT_FAILURE; int temp;
if (length == -1) if (scanf("%d", &temp) != 1)
break; return EXIT_FAILURE;
if (temp == -1)
break;
length = (size_t)temp;
}
// Read data bytes // Read data bytes
bool isAscii = true; bool isAscii = true;
@ -52,10 +56,10 @@ int main(void) {
perror("malloc"); perror("malloc");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
for (int i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
int b; int b;
if (scanf("%d", &b) != 1) if (scanf("%d", &b) != 1)
return EXIT_FAILURE; return EXIT_FAILURE;
data[i] = (uint8_t)b; data[i] = (uint8_t)b;
isAscii &= 0 < b && b < 128; isAscii &= 0 < b && b < 128;
} }
@ -66,7 +70,7 @@ int main(void) {
return EXIT_FAILURE; return EXIT_FAILURE;
// Allocate memory for QR Code // Allocate memory for QR Code
int bufferLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); size_t bufferLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion);
uint8_t *qrcode = malloc(bufferLen * sizeof(uint8_t)); uint8_t *qrcode = malloc(bufferLen * sizeof(uint8_t));
uint8_t *tempBuffer = malloc(bufferLen * sizeof(uint8_t)); uint8_t *tempBuffer = malloc(bufferLen * sizeof(uint8_t));
if (qrcode == NULL || tempBuffer == NULL) { if (qrcode == NULL || tempBuffer == NULL) {
@ -82,7 +86,7 @@ int main(void) {
perror("malloc"); perror("malloc");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
for (int i = 0; i < length; i++) for (size_t i = 0; i < length; i++)
text[i] = (char)data[i]; text[i] = (char)data[i];
text[length] = '\0'; text[length] = '\0';
ok = qrcodegen_encodeText(text, tempBuffer, qrcode, (enum qrcodegen_Ecc)errCorLvl, ok = qrcodegen_encodeText(text, tempBuffer, qrcode, (enum qrcodegen_Ecc)errCorLvl,
@ -90,7 +94,7 @@ int main(void) {
free(text); free(text);
} else if (length <= bufferLen) { } else if (length <= bufferLen) {
memcpy(tempBuffer, data, length * sizeof(data[0])); memcpy(tempBuffer, data, length * sizeof(data[0]));
ok = qrcodegen_encodeBinary(tempBuffer, (size_t)length, qrcode, (enum qrcodegen_Ecc)errCorLvl, ok = qrcodegen_encodeBinary(tempBuffer, length, qrcode, (enum qrcodegen_Ecc)errCorLvl,
minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1); minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1);
} else } else
ok = false; ok = false;

@ -132,7 +132,7 @@ bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode
size_t textLen = strlen(text); size_t textLen = strlen(text);
if (textLen == 0) if (textLen == 0)
return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode);
size_t bufLen = qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); size_t bufLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion);
struct qrcodegen_Segment seg; struct qrcodegen_Segment seg;
if (qrcodegen_isNumeric(text)) { if (qrcodegen_isNumeric(text)) {
@ -228,14 +228,16 @@ bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], siz
} }
// Concatenate all segments to create the data bit string // Concatenate all segments to create the data bit string
memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); memset(qrcode, 0, (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0]));
int bitLen = 0; int bitLen = 0;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
const struct qrcodegen_Segment *seg = &segs[i]; const struct qrcodegen_Segment *seg = &segs[i];
appendBitsToBuffer((int)seg->mode, 4, qrcode, &bitLen); appendBitsToBuffer((unsigned int)seg->mode, 4, qrcode, &bitLen);
appendBitsToBuffer(seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); appendBitsToBuffer((unsigned int)seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen);
for (int j = 0; j < seg->bitLength; j++) for (int j = 0; j < seg->bitLength; j++) {
appendBitsToBuffer((seg->data[j >> 3] >> (7 - (j & 7))) & 1, 1, qrcode, &bitLen); int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1;
appendBitsToBuffer((unsigned int)bit, 1, qrcode, &bitLen);
}
} }
assert(bitLen == dataUsedBits); assert(bitLen == dataUsedBits);
@ -356,7 +358,7 @@ testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) {
assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX);
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
memset(result, 0, degree * sizeof(result[0])); memset(result, 0, (size_t)degree * sizeof(result[0]));
result[degree - 1] = 1; // Start off with the monomial x^0 result[degree - 1] = 1; // Start off with the monomial x^0
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
@ -381,10 +383,10 @@ testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) {
testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen,
const uint8_t generator[], int degree, uint8_t result[]) { const uint8_t generator[], int degree, uint8_t result[]) {
assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX);
memset(result, 0, degree * sizeof(result[0])); memset(result, 0, (size_t)degree * sizeof(result[0]));
for (int i = 0; i < dataLen; i++) { // Polynomial division for (int i = 0; i < dataLen; i++) { // Polynomial division
uint8_t factor = data[i] ^ result[0]; uint8_t factor = data[i] ^ result[0];
memmove(&result[0], &result[1], (degree - 1) * sizeof(result[0])); memmove(&result[0], &result[1], (size_t)(degree - 1) * sizeof(result[0]));
result[degree - 1] = 0; result[degree - 1] = 0;
for (int j = 0; j < degree; j++) for (int j = 0; j < degree; j++)
result[j] ^= reedSolomonMultiply(generator[j], factor); result[j] ^= reedSolomonMultiply(generator[j], factor);
@ -400,7 +402,7 @@ testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) {
// Russian peasant multiplication // Russian peasant multiplication
uint8_t z = 0; uint8_t z = 0;
for (int i = 7; i >= 0; i--) { for (int i = 7; i >= 0; i--) {
z = (z << 1) ^ ((z >> 7) * 0x11D); z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D));
z ^= ((y >> i) & 1) * x; z ^= ((y >> i) & 1) * x;
} }
return z; return z;
@ -415,7 +417,7 @@ testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) {
testable void initializeFunctionModules(int version, uint8_t qrcode[]) { testable void initializeFunctionModules(int version, uint8_t qrcode[]) {
// Initialize QR Code // Initialize QR Code
int qrsize = version * 4 + 17; int qrsize = version * 4 + 17;
memset(qrcode, 0, ((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); memset(qrcode, 0, (size_t)((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0]));
qrcode[0] = (uint8_t)qrsize; qrcode[0] = (uint8_t)qrsize;
// Fill horizontal and vertical timing patterns // Fill horizontal and vertical timing patterns
@ -551,7 +553,7 @@ testable int getAlignmentPatternPositions(int version, uint8_t result[7]) {
int step = (version == 32) ? 26 : int step = (version == 32) ? 26 :
(version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2; (version*4 + numAlign*2 + 1) / (numAlign*2 - 2) * 2;
for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step)
result[i] = pos; result[i] = (uint8_t)pos;
result[0] = 6; result[0] = 6;
return numAlign; return numAlign;
} }
@ -962,16 +964,16 @@ struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) {
assert(false); assert(false);
else if (assignVal < (1 << 7)) { else if (assignVal < (1 << 7)) {
memset(buf, 0, 1 * sizeof(buf[0])); memset(buf, 0, 1 * sizeof(buf[0]));
appendBitsToBuffer(assignVal, 8, buf, &result.bitLength); appendBitsToBuffer((unsigned int)assignVal, 8, buf, &result.bitLength);
} else if (assignVal < (1 << 14)) { } else if (assignVal < (1 << 14)) {
memset(buf, 0, 2 * sizeof(buf[0])); memset(buf, 0, 2 * sizeof(buf[0]));
appendBitsToBuffer(2, 2, buf, &result.bitLength); appendBitsToBuffer(2, 2, buf, &result.bitLength);
appendBitsToBuffer(assignVal, 14, buf, &result.bitLength); appendBitsToBuffer((unsigned int)assignVal, 14, buf, &result.bitLength);
} else if (assignVal < 1000000L) { } else if (assignVal < 1000000L) {
memset(buf, 0, 3 * sizeof(buf[0])); memset(buf, 0, 3 * sizeof(buf[0]));
appendBitsToBuffer(6, 3, buf, &result.bitLength); appendBitsToBuffer(6, 3, buf, &result.bitLength);
appendBitsToBuffer(assignVal >> 10, 11, buf, &result.bitLength); appendBitsToBuffer((unsigned int)(assignVal >> 10), 11, buf, &result.bitLength);
appendBitsToBuffer(assignVal & 0x3FF, 10, buf, &result.bitLength); appendBitsToBuffer((unsigned int)(assignVal & 0x3FF), 10, buf, &result.bitLength);
} else } else
assert(false); assert(false);
result.data = buf; result.data = buf;

@ -96,19 +96,19 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
// Concatenate all segments to create the data bit string // Concatenate all segments to create the data bit string
BitBuffer bb; BitBuffer bb;
for (const QrSegment &seg : segs) { for (const QrSegment &seg : segs) {
bb.appendBits(seg.getMode().getModeBits(), 4); bb.appendBits(static_cast<uint32_t>(seg.getMode().getModeBits()), 4);
bb.appendBits(seg.getNumChars(), seg.getMode().numCharCountBits(version)); bb.appendBits(static_cast<uint32_t>(seg.getNumChars()), seg.getMode().numCharCountBits(version));
bb.insert(bb.end(), seg.getData().begin(), seg.getData().end()); bb.insert(bb.end(), seg.getData().begin(), seg.getData().end());
} }
if (bb.size() != static_cast<unsigned int>(dataUsedBits)) if (bb.size() != static_cast<unsigned int>(dataUsedBits))
throw std::logic_error("Assertion error"); throw std::logic_error("Assertion error");
// Add terminator and pad up to a byte if applicable // Add terminator and pad up to a byte if applicable
size_t dataCapacityBits = getNumDataCodewords(version, ecl) * 8; size_t dataCapacityBits = static_cast<size_t>(getNumDataCodewords(version, ecl)) * 8;
if (bb.size() > dataCapacityBits) if (bb.size() > dataCapacityBits)
throw std::logic_error("Assertion error"); throw std::logic_error("Assertion error");
bb.appendBits(0, std::min<size_t>(4, dataCapacityBits - bb.size())); bb.appendBits(0, std::min(4, static_cast<int>(dataCapacityBits - bb.size())));
bb.appendBits(0, (8 - bb.size() % 8) % 8); bb.appendBits(0, (8 - static_cast<int>(bb.size() % 8)) % 8);
if (bb.size() % 8 != 0) if (bb.size() % 8 != 0)
throw std::logic_error("Assertion error"); throw std::logic_error("Assertion error");
@ -135,8 +135,9 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int mask)
if (mask < -1 || mask > 7) if (mask < -1 || mask > 7)
throw std::domain_error("Mask value out of range"); throw std::domain_error("Mask value out of range");
size = ver * 4 + 17; size = ver * 4 + 17;
modules = vector<vector<bool> >(size, vector<bool>(size)); // Initially all white size_t sz = static_cast<size_t>(size);
isFunction = vector<vector<bool> >(size, vector<bool>(size)); modules = vector<vector<bool> >(sz, vector<bool>(sz)); // Initially all white
isFunction = vector<vector<bool> >(sz, vector<bool>(sz));
// Compute ECC, draw modules // Compute ECC, draw modules
drawFunctionPatterns(); drawFunctionPatterns();
@ -235,9 +236,9 @@ void QrCode::drawFunctionPatterns() {
// Draw numerous alignment patterns // Draw numerous alignment patterns
const vector<int> alignPatPos = getAlignmentPatternPositions(); const vector<int> alignPatPos = getAlignmentPatternPositions();
int numAlign = alignPatPos.size(); size_t numAlign = alignPatPos.size();
for (int i = 0; i < numAlign; i++) { for (size_t i = 0; i < numAlign; i++) {
for (int j = 0; j < numAlign; j++) { for (size_t j = 0; j < numAlign; j++) {
// Don't draw on the three finder corners // Don't draw on the three finder corners
if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)))
drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j)); drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j));
@ -322,13 +323,15 @@ void QrCode::drawAlignmentPattern(int x, int y) {
void QrCode::setFunctionModule(int x, int y, bool isBlack) { void QrCode::setFunctionModule(int x, int y, bool isBlack) {
modules.at(y).at(x) = isBlack; size_t ux = static_cast<size_t>(x);
isFunction.at(y).at(x) = true; size_t uy = static_cast<size_t>(y);
modules .at(uy).at(ux) = isBlack;
isFunction.at(uy).at(ux) = true;
} }
bool QrCode::module(int x, int y) const { bool QrCode::module(int x, int y) const {
return modules.at(y).at(x); return modules.at(static_cast<size_t>(y)).at(static_cast<size_t>(x));
} }
@ -348,7 +351,7 @@ vector<uint8_t> QrCode::addEccAndInterleave(const vector<uint8_t> &data) const {
const vector<uint8_t> rsDiv = reedSolomonComputeDivisor(blockEccLen); const vector<uint8_t> rsDiv = reedSolomonComputeDivisor(blockEccLen);
for (int i = 0, k = 0; i < numBlocks; i++) { for (int i = 0, k = 0; i < numBlocks; i++) {
vector<uint8_t> dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1))); vector<uint8_t> dat(data.cbegin() + k, data.cbegin() + (k + shortBlockLen - blockEccLen + (i < numShortBlocks ? 0 : 1)));
k += dat.size(); k += static_cast<int>(dat.size());
const vector<uint8_t> ecc = reedSolomonComputeRemainder(dat, rsDiv); const vector<uint8_t> ecc = reedSolomonComputeRemainder(dat, rsDiv);
if (i < numShortBlocks) if (i < numShortBlocks)
dat.push_back(0); dat.push_back(0);
@ -382,9 +385,9 @@ void QrCode::drawCodewords(const vector<uint8_t> &data) {
right = 5; right = 5;
for (int vert = 0; vert < size; vert++) { // Vertical counter for (int vert = 0; vert < size; vert++) { // Vertical counter
for (int j = 0; j < 2; j++) { for (int j = 0; j < 2; j++) {
int x = right - j; // Actual x coordinate size_t x = static_cast<size_t>(right - j); // Actual x coordinate
bool upward = ((right + 1) & 2) == 0; bool upward = ((right + 1) & 2) == 0;
int y = upward ? size - 1 - vert : vert; // Actual y coordinate size_t y = static_cast<size_t>(upward ? size - 1 - vert : vert); // Actual y coordinate
if (!isFunction.at(y).at(x) && i < data.size() * 8) { if (!isFunction.at(y).at(x) && i < data.size() * 8) {
modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7)); modules.at(y).at(x) = getBit(data.at(i >> 3), 7 - static_cast<int>(i & 7));
i++; i++;
@ -402,8 +405,9 @@ void QrCode::drawCodewords(const vector<uint8_t> &data) {
void QrCode::applyMask(int mask) { void QrCode::applyMask(int mask) {
if (mask < 0 || mask > 7) if (mask < 0 || mask > 7)
throw std::domain_error("Mask value out of range"); throw std::domain_error("Mask value out of range");
for (int y = 0; y < size; y++) { size_t sz = static_cast<size_t>(size);
for (int x = 0; x < size; x++) { for (size_t y = 0; y < sz; y++) {
for (size_t x = 0; x < sz; x++) {
bool invert; bool invert;
switch (mask) { switch (mask) {
case 0: invert = (x + y) % 2 == 0; break; case 0: invert = (x + y) % 2 == 0; break;
@ -543,8 +547,8 @@ vector<uint8_t> QrCode::reedSolomonComputeDivisor(int degree) {
throw std::domain_error("Degree out of range"); throw std::domain_error("Degree out of range");
// Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1.
// For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}.
vector<uint8_t> result(degree); vector<uint8_t> result(static_cast<size_t>(degree));
result.at(degree - 1) = 1; // Start off with the monomial x^0 result.at(result.size() - 1) = 1; // Start off with the monomial x^0
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
// and drop the highest monomial term which is always 1x^degree. // and drop the highest monomial term which is always 1x^degree.

@ -153,9 +153,9 @@ static void doSegmentDemo() {
}; };
qrcodegen::BitBuffer bb; qrcodegen::BitBuffer bb;
for (int c : kanjiChars) for (int c : kanjiChars)
bb.appendBits(c, 13); bb.appendBits(static_cast<std::uint32_t>(c), 13);
const QrCode qr5 = QrCode::encodeSegments( const QrCode qr5 = QrCode::encodeSegments(
{QrSegment(QrSegment::Mode::KANJI, kanjiChars.size(), bb)}, {QrSegment(QrSegment::Mode::KANJI, static_cast<int>(kanjiChars.size()), bb)},
QrCode::Ecc::LOW); QrCode::Ecc::LOW);
printQr(qr5); printQr(qr5);
} }

@ -26,6 +26,7 @@
* Software. * Software.
*/ */
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -83,7 +84,7 @@ int main() {
try { // Try to make QR Code symbol try { // Try to make QR Code symbol
const QrCode qr = QrCode::encodeSegments(segs, const QrCode qr = QrCode::encodeSegments(segs,
ECC_LEVELS.at(errCorLvl), minVersion, maxVersion, mask, boostEcl == 1); ECC_LEVELS.at(static_cast<std::size_t>(errCorLvl)), minVersion, maxVersion, mask, boostEcl == 1);
// Print grid of modules // Print grid of modules
std::cout << qr.getVersion() << std::endl; std::cout << qr.getVersion() << std::endl;
for (int y = 0; y < qr.getSize(); y++) { for (int y = 0; y < qr.getSize(); y++) {

@ -81,13 +81,13 @@ QrSegment QrSegment::makeNumeric(const char *digits) {
accumData = accumData * 10 + (c - '0'); accumData = accumData * 10 + (c - '0');
accumCount++; accumCount++;
if (accumCount == 3) { if (accumCount == 3) {
bb.appendBits(accumData, 10); bb.appendBits(static_cast<uint32_t>(accumData), 10);
accumData = 0; accumData = 0;
accumCount = 0; accumCount = 0;
} }
} }
if (accumCount > 0) // 1 or 2 digits remaining if (accumCount > 0) // 1 or 2 digits remaining
bb.appendBits(accumData, accumCount * 3 + 1); bb.appendBits(static_cast<uint32_t>(accumData), accumCount * 3 + 1);
return QrSegment(Mode::NUMERIC, charCount, std::move(bb)); return QrSegment(Mode::NUMERIC, charCount, std::move(bb));
} }
@ -101,16 +101,16 @@ QrSegment QrSegment::makeAlphanumeric(const char *text) {
const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text); const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text);
if (temp == nullptr) if (temp == nullptr)
throw std::domain_error("String contains unencodable characters in alphanumeric mode"); throw std::domain_error("String contains unencodable characters in alphanumeric mode");
accumData = accumData * 45 + (temp - ALPHANUMERIC_CHARSET); accumData = accumData * 45 + static_cast<int>(temp - ALPHANUMERIC_CHARSET);
accumCount++; accumCount++;
if (accumCount == 2) { if (accumCount == 2) {
bb.appendBits(accumData, 11); bb.appendBits(static_cast<uint32_t>(accumData), 11);
accumData = 0; accumData = 0;
accumCount = 0; accumCount = 0;
} }
} }
if (accumCount > 0) // 1 character remaining if (accumCount > 0) // 1 character remaining
bb.appendBits(accumData, 6); bb.appendBits(static_cast<uint32_t>(accumData), 6);
return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb)); return QrSegment(Mode::ALPHANUMERIC, charCount, std::move(bb));
} }
@ -138,13 +138,13 @@ QrSegment QrSegment::makeEci(long assignVal) {
if (assignVal < 0) if (assignVal < 0)
throw std::domain_error("ECI assignment value out of range"); throw std::domain_error("ECI assignment value out of range");
else if (assignVal < (1 << 7)) else if (assignVal < (1 << 7))
bb.appendBits(assignVal, 8); bb.appendBits(static_cast<uint32_t>(assignVal), 8);
else if (assignVal < (1 << 14)) { else if (assignVal < (1 << 14)) {
bb.appendBits(2, 2); bb.appendBits(2, 2);
bb.appendBits(assignVal, 14); bb.appendBits(static_cast<uint32_t>(assignVal), 14);
} else if (assignVal < 1000000L) { } else if (assignVal < 1000000L) {
bb.appendBits(6, 3); bb.appendBits(6, 3);
bb.appendBits(assignVal, 21); bb.appendBits(static_cast<uint32_t>(assignVal), 21);
} else } else
throw std::domain_error("ECI assignment value out of range"); throw std::domain_error("ECI assignment value out of range");
return QrSegment(Mode::ECI, 0, std::move(bb)); return QrSegment(Mode::ECI, 0, std::move(bb));

@ -26,9 +26,9 @@
namespace qrcodegen { namespace qrcodegen {
type bit = number; type bit = number;
type byte = number; type byte = number;
type int = number; type int = number;
/*---- QR Code symbol class ----*/ /*---- QR Code symbol class ----*/

Loading…
Cancel
Save