diff --git a/c/qrcodegen-demo.c b/c/qrcodegen-demo.c index 3af9b72..2227e23 100644 --- a/c/qrcodegen-demo.c +++ b/c/qrcodegen-demo.c @@ -53,9 +53,9 @@ static void doBasicDemo() { // Make and print the QR Code symbol uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - int version = qrcodegen_encodeText(text, tempBuffer, qrcode, errCorLvl, + bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode, errCorLvl, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true); - if (version != 0) + if (ok) printQr(qrcode); } @@ -65,27 +65,27 @@ static void doVarietyDemo() { { // Project Nayuki URL uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - int version = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode, + bool ok = qrcodegen_encodeText("https://www.nayuki.io/", tempBuffer, qrcode, qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_3, true); - if (version != 0) + if (ok) printQr(qrcode); } { // Numeric mode encoding (3.33 bits per digit) uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - int version = qrcodegen_encodeText("314159265358979323846264338327950288419716939937510", tempBuffer, qrcode, + bool ok = qrcodegen_encodeText("314159265358979323846264338327950288419716939937510", tempBuffer, qrcode, qrcodegen_Ecc_MEDIUM, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true); - if (version != 0) + if (ok) printQr(qrcode); } { // Alphanumeric mode encoding (5.5 bits per character) uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - int version = qrcodegen_encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", tempBuffer, qrcode, + bool ok = qrcodegen_encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", tempBuffer, qrcode, qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true); - if (version != 0) + if (ok) printQr(qrcode); } @@ -93,26 +93,26 @@ static void doVarietyDemo() { const char *text = "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1wa\xE3\x80\x81\xE4\xB8\x96\xE7\x95\x8C\xEF\xBC\x81\x20\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4"; uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - int version; + bool ok; - version = qrcodegen_encodeText(text, tempBuffer, qrcode, + ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_0, true); - if (version != 0) + if (ok) printQr(qrcode); - version = qrcodegen_encodeText(text, tempBuffer, qrcode, + ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_1, true); - if (version != 0) + if (ok) printQr(qrcode); - version = qrcodegen_encodeText(text, tempBuffer, qrcode, + ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_5, true); - if (version != 0) + if (ok) printQr(qrcode); - version = qrcodegen_encodeText(text, tempBuffer, qrcode, + ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_QUARTILE, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_7, true); - if (version != 0) + if (ok) printQr(qrcode); } @@ -127,9 +127,9 @@ static void doVarietyDemo() { "a White Rabbit with pink eyes ran close by her."; uint8_t qrcode[qrcodegen_BUFFER_LEN_MAX]; uint8_t tempBuffer[qrcodegen_BUFFER_LEN_MAX]; - int version = qrcodegen_encodeText(text, tempBuffer, qrcode, + bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_HIGH, qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true); - if (version != 0) + if (ok) printQr(qrcode); } } diff --git a/c/qrcodegen-worker.c b/c/qrcodegen-worker.c index e18a426..43d50c0 100644 --- a/c/qrcodegen-worker.c +++ b/c/qrcodegen-worker.c @@ -74,31 +74,31 @@ int main(void) { } // Try to make QR Code symbol - int version; + bool ok; if (isAscii) { char *text = malloc((length + 1) * sizeof(char)); for (int i = 0; i < length; i++) text[i] = (char)data[i]; text[length] = '\0'; - version = qrcodegen_encodeText(text, tempBuffer, qrcode, (enum qrcodegen_Ecc)errCorLvl, + ok = qrcodegen_encodeText(text, tempBuffer, qrcode, (enum qrcodegen_Ecc)errCorLvl, minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1); free(text); } else if (length <= bufferLen) { for (int i = 0; i < length; i++) tempBuffer[i] = data[i]; - version = qrcodegen_encodeBinary(tempBuffer, (size_t)length, qrcode, (enum qrcodegen_Ecc)errCorLvl, + ok = qrcodegen_encodeBinary(tempBuffer, (size_t)length, qrcode, (enum qrcodegen_Ecc)errCorLvl, minVersion, maxVersion, (enum qrcodegen_Mask)mask, boostEcl == 1); } else - version = 0; + ok = false; free(data); free(tempBuffer); // Print grid of modules - if (version == 0) + if (!ok) printf("-1\n"); else { - printf("%d\n", version); int size = qrcodegen_getSize(qrcode); + printf("%d\n", (size - 17) / 4); for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) printf("%d\n", qrcodegen_getModule(qrcode, x, y) ? 1 : 0); diff --git a/c/qrcodegen.c b/c/qrcodegen.c index 01fb9b0..33fb7d9 100644 --- a/c/qrcodegen.c +++ b/c/qrcodegen.c @@ -108,7 +108,7 @@ static const int PENALTY_N4 = 10; /*---- High-level QR Code encoding functions ----*/ // Public function - see documentation comment in header file. -int qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); @@ -118,11 +118,11 @@ int qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[ int textBits; int textLen = getTextProperties(text, &isNumeric, &isAlphanumeric, &textBits); if (textLen < 0) - return 0; + goto fail; if (!isAlphanumeric) { // Fully handle in binary mode if (textLen > qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion)) - return 0; + goto fail; for (int i = 0; i < textLen; i++) tempBuffer[i] = (uint8_t)text[i]; return qrcodegen_encodeBinary(tempBuffer, (size_t)textLen, qrcode, ecl, minVersion, maxVersion, mask, boostEcl); @@ -131,7 +131,7 @@ int qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[ int version = fitVersionToData(minVersion, maxVersion, ecl, textLen, (int)textBits, (isNumeric ? 10 : 9), (isNumeric ? 12 : 11), (isNumeric ? 14 : 13)); if (version == 0) - return 0; + goto fail; memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); int bitLen = 0; @@ -175,23 +175,27 @@ int qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[ // Make QR Code encodeQrCodeTail(qrcode, bitLen, tempBuffer, version, ecl, mask, boostEcl); - return version; + return true; + +fail: + qrcode[0] = 0; // An invalid size value for safety + return false; } // Public function - see documentation comment in header file. -int qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) { assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); // Check length and find version if (dataLen > INT16_MAX / 8) - return 0; + goto fail; // Now dataLen * 8 <= 32767 <= INT_MAX int version = fitVersionToData(minVersion, maxVersion, ecl, (int)dataLen, (int)dataLen * 8, 8, 16, 16); if (version == 0) - return 0; + goto fail; // Make bit sequence and QR Code memset(qrcode, 0, qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); @@ -201,7 +205,11 @@ int qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode for (size_t i = 0; i < dataLen; i++) appendBitsToBuffer(dataAndTemp[i], 8, qrcode, &bitLen); encodeQrCodeTail(qrcode, bitLen, dataAndTemp, version, ecl, mask, boostEcl); - return version; + return true; + +fail: + qrcode[0] = 0; // An invalid size value for safety + return false; } diff --git a/c/qrcodegen.h b/c/qrcodegen.h index 9b75047..7d925ad 100644 --- a/c/qrcodegen.h +++ b/c/qrcodegen.h @@ -77,24 +77,24 @@ enum qrcodegen_Mask { /*---- Top-level QR Code functions ----*/ /* - * Encodes the given text data to a QR Code symbol, returning the actual version number used. + * Encodes the given text data to a QR Code symbol, returning whether encoding succeeded. * If the data is too long to fit in any version in the given range at the given ECC level, - * then 0 is returned. Both dataAndTemp and qrcode each must have length at least + * then false is returned. Both dataAndTemp and qrcode each must have length at least * qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). The text must be encoded in UTF-8. * The resulting QR Code may use numeric, alphanumeric, or byte mode to encode the text. */ -int qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); /* - * Encodes the given binary data to a QR Code symbol, returning the actual version number used. + * Encodes the given binary data to a QR Code symbol, returning whether encoding succeeded. * If the data is too long to fit in any version in the given range at the given ECC level, - * then 0 is returned. dataAndTemp[0 : dataLen] represents the input data, and the function + * then false is returned. dataAndTemp[0 : dataLen] represents the input data, and the function * may overwrite the array's contents as a temporary work area. Both dataAndTemp and qrcode * must have length at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). */ -int qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl);