|
|
@ -714,48 +714,28 @@ size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars
|
|
|
|
// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned.
|
|
|
|
// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned.
|
|
|
|
// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
|
|
|
|
// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact.
|
|
|
|
testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) {
|
|
|
|
testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) {
|
|
|
|
const int LIMIT = INT16_MAX; // Can be configured as high as INT_MAX
|
|
|
|
// All calculations are designed to avoid overflow on all platforms
|
|
|
|
if (numChars > (unsigned int)LIMIT)
|
|
|
|
if (numChars > (unsigned int)INT16_MAX)
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
int n = (int)numChars;
|
|
|
|
long result = (long)numChars;
|
|
|
|
|
|
|
|
if (mode == qrcodegen_Mode_NUMERIC)
|
|
|
|
int result;
|
|
|
|
result = (result * 10 + 2) / 3; // ceil(10/3 * n)
|
|
|
|
if (mode == qrcodegen_Mode_NUMERIC) {
|
|
|
|
else if (mode == qrcodegen_Mode_ALPHANUMERIC)
|
|
|
|
// n * 3 + ceil(n / 3)
|
|
|
|
result = (result * 11 + 1) / 2; // ceil(11/2 * n)
|
|
|
|
if (n > LIMIT / 3)
|
|
|
|
else if (mode == qrcodegen_Mode_BYTE)
|
|
|
|
goto overflow;
|
|
|
|
result *= 8;
|
|
|
|
result = n * 3;
|
|
|
|
else if (mode == qrcodegen_Mode_KANJI)
|
|
|
|
int temp = n / 3 + (n % 3 > 0 ? 1 : 0);
|
|
|
|
result *= 13;
|
|
|
|
if (temp > LIMIT - result)
|
|
|
|
else if (mode == qrcodegen_Mode_ECI && numChars == 0)
|
|
|
|
goto overflow;
|
|
|
|
|
|
|
|
result += temp;
|
|
|
|
|
|
|
|
} else if (mode == qrcodegen_Mode_ALPHANUMERIC) {
|
|
|
|
|
|
|
|
// n * 5 + ceil(n / 2)
|
|
|
|
|
|
|
|
if (n > LIMIT / 5)
|
|
|
|
|
|
|
|
goto overflow;
|
|
|
|
|
|
|
|
result = n * 5;
|
|
|
|
|
|
|
|
int temp = n / 2 + n % 2;
|
|
|
|
|
|
|
|
if (temp > LIMIT - result)
|
|
|
|
|
|
|
|
goto overflow;
|
|
|
|
|
|
|
|
result += temp;
|
|
|
|
|
|
|
|
} else if (mode == qrcodegen_Mode_BYTE) {
|
|
|
|
|
|
|
|
if (n > LIMIT / 8)
|
|
|
|
|
|
|
|
goto overflow;
|
|
|
|
|
|
|
|
result = n * 8;
|
|
|
|
|
|
|
|
} else if (mode == qrcodegen_Mode_KANJI) {
|
|
|
|
|
|
|
|
if (n > LIMIT / 13)
|
|
|
|
|
|
|
|
goto overflow;
|
|
|
|
|
|
|
|
result = n * 13;
|
|
|
|
|
|
|
|
} else if (mode == qrcodegen_Mode_ECI && numChars == 0)
|
|
|
|
|
|
|
|
result = 3 * 8;
|
|
|
|
result = 3 * 8;
|
|
|
|
else {
|
|
|
|
else { // Invalid argument
|
|
|
|
assert(false);
|
|
|
|
assert(false);
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(0 <= result && result <= LIMIT);
|
|
|
|
assert(result >= 0);
|
|
|
|
return result;
|
|
|
|
if (result > (unsigned int)INT16_MAX)
|
|
|
|
overflow:
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return (int)result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|