Updated C++ code to use standard exception classes instead of bare C strings.

pull/39/merge
Project Nayuki 6 years ago
parent 31b092da2d
commit 4ca232b949

@ -21,6 +21,7 @@
* Software. * Software.
*/ */
#include <stdexcept>
#include "BitBuffer.hpp" #include "BitBuffer.hpp"
@ -40,7 +41,7 @@ std::vector<std::uint8_t> BitBuffer::getBytes() const {
void BitBuffer::appendBits(std::uint32_t val, int len) { void BitBuffer::appendBits(std::uint32_t val, int len) {
if (len < 0 || len > 31 || val >> len != 0) if (len < 0 || len > 31 || val >> len != 0)
throw "Value out of range"; throw std::domain_error("Value out of range");
for (int i = len - 1; i >= 0; i--) // Append bit by bit for (int i = len - 1; i >= 0; i--) // Append bit by bit
this->push_back(((val >> i) & 1) != 0); this->push_back(((val >> i) & 1) != 0);
} }

@ -26,6 +26,7 @@
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include <stdexcept>
#include <utility> #include <utility>
#include "BitBuffer.hpp" #include "BitBuffer.hpp"
#include "QrCode.hpp" #include "QrCode.hpp"
@ -44,7 +45,7 @@ int QrCode::getFormatBits(Ecc ecl) {
case Ecc::MEDIUM : return 0; case Ecc::MEDIUM : return 0;
case Ecc::QUARTILE: return 3; case Ecc::QUARTILE: return 3;
case Ecc::HIGH : return 2; case Ecc::HIGH : return 2;
default: throw "Assertion error"; default: throw std::logic_error("Assertion error");
} }
} }
@ -64,7 +65,7 @@ QrCode QrCode::encodeBinary(const vector<uint8_t> &data, Ecc ecl) {
QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl, QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
int minVersion, int maxVersion, int mask, bool boostEcl) { int minVersion, int maxVersion, int mask, bool boostEcl) {
if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7) if (!(MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= MAX_VERSION) || mask < -1 || mask > 7)
throw "Invalid value"; throw std::invalid_argument("Invalid value");
// Find the minimal version number to use // Find the minimal version number to use
int version, dataUsedBits; int version, dataUsedBits;
@ -74,10 +75,10 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
break; // This version number is found to be suitable break; // This version number is found to be suitable
if (version >= maxVersion) // All versions in the range could not fit the given data if (version >= maxVersion) // All versions in the range could not fit the given data
throw "Data too long"; throw std::length_error("Data too long");
} }
if (dataUsedBits == -1) if (dataUsedBits == -1)
throw "Assertion error"; throw std::logic_error("Assertion error");
// Increase the error correction level while the data still fits in the current version number // Increase the error correction level while the data still fits in the current version number
for (Ecc newEcl : vector<Ecc>{Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) { for (Ecc newEcl : vector<Ecc>{Ecc::MEDIUM, Ecc::QUARTILE, Ecc::HIGH}) {
@ -102,7 +103,7 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11) for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8); bb.appendBits(padByte, 8);
if (bb.size() % 8 != 0) if (bb.size() % 8 != 0)
throw "Assertion error"; throw std::logic_error("Assertion error");
// Create the QR Code symbol // Create the QR Code symbol
return QrCode(version, ecl, bb.getBytes(), mask); return QrCode(version, ecl, bb.getBytes(), mask);
@ -119,7 +120,7 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int mask)
// Check arguments // Check arguments
if (ver < MIN_VERSION || ver > MAX_VERSION || mask < -1 || mask > 7) if (ver < MIN_VERSION || ver > MAX_VERSION || mask < -1 || mask > 7)
throw "Value out of range"; throw std::domain_error("Value out of range");
// Draw function patterns, draw all codewords, do masking // Draw function patterns, draw all codewords, do masking
drawFunctionPatterns(); drawFunctionPatterns();
@ -156,9 +157,9 @@ bool QrCode::getModule(int x, int y) const {
std::string QrCode::toSvgString(int border) const { std::string QrCode::toSvgString(int border) const {
if (border < 0) if (border < 0)
throw "Border must be non-negative"; throw std::domain_error("Border must be non-negative");
if (border > INT_MAX / 2 || border * 2 > INT_MAX - size) if (border > INT_MAX / 2 || border * 2 > INT_MAX - size)
throw "Border too large"; throw std::overflow_error("Border too large");
std::ostringstream sb; std::ostringstream sb;
sb << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; sb << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
@ -224,7 +225,7 @@ void QrCode::drawFormatBits(int mask) {
data = data << 10 | rem; data = data << 10 | rem;
data ^= 0x5412; // uint15 data ^= 0x5412; // uint15
if (data >> 15 != 0) if (data >> 15 != 0)
throw "Assertion error"; throw std::logic_error("Assertion error");
// Draw first copy // Draw first copy
for (int i = 0; i <= 5; i++) for (int i = 0; i <= 5; i++)
@ -254,7 +255,7 @@ void QrCode::drawVersion() {
rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); rem = (rem << 1) ^ ((rem >> 11) * 0x1F25);
long data = (long)version << 12 | rem; // uint18 long data = (long)version << 12 | rem; // uint18
if (data >> 18 != 0) if (data >> 18 != 0)
throw "Assertion error"; throw std::logic_error("Assertion error");
// Draw two copies // Draw two copies
for (int i = 0; i < 18; i++) { for (int i = 0; i < 18; i++) {
@ -299,7 +300,7 @@ bool QrCode::module(int x, int y) const {
vector<uint8_t> QrCode::appendErrorCorrection(const vector<uint8_t> &data) const { vector<uint8_t> QrCode::appendErrorCorrection(const vector<uint8_t> &data) const {
if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel))) if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel)))
throw "Invalid argument"; throw std::invalid_argument("Invalid argument");
// Calculate parameter numbers // Calculate parameter numbers
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version]; int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(errorCorrectionLevel)][version];
@ -331,14 +332,14 @@ vector<uint8_t> QrCode::appendErrorCorrection(const vector<uint8_t> &data) const
} }
} }
if (result.size() != static_cast<unsigned int>(rawCodewords)) if (result.size() != static_cast<unsigned int>(rawCodewords))
throw "Assertion error"; throw std::logic_error("Assertion error");
return result; return result;
} }
void QrCode::drawCodewords(const vector<uint8_t> &data) { void QrCode::drawCodewords(const vector<uint8_t> &data) {
if (data.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8)) if (data.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8))
throw "Invalid argument"; throw std::invalid_argument("Invalid argument");
size_t i = 0; // Bit index into the data size_t i = 0; // Bit index into the data
// Do the funny zigzag scan // Do the funny zigzag scan
@ -360,13 +361,13 @@ void QrCode::drawCodewords(const vector<uint8_t> &data) {
} }
} }
if (static_cast<unsigned int>(i) != data.size() * 8) if (static_cast<unsigned int>(i) != data.size() * 8)
throw "Assertion error"; throw std::logic_error("Assertion error");
} }
void QrCode::applyMask(int mask) { void QrCode::applyMask(int mask) {
if (mask < 0 || mask > 7) if (mask < 0 || mask > 7)
throw "Mask value out of range"; throw std::domain_error("Mask value out of range");
for (int y = 0; y < size; y++) { for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) { for (int x = 0; x < size; x++) {
bool invert; bool invert;
@ -379,7 +380,7 @@ void QrCode::applyMask(int mask) {
case 5: invert = x * y % 2 + x * y % 3 == 0; break; case 5: invert = x * y % 2 + x * y % 3 == 0; break;
case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break;
case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break;
default: throw "Assertion error"; default: throw std::logic_error("Assertion error");
} }
modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x)); modules.at(y).at(x) = modules.at(y).at(x) ^ (invert & !isFunction.at(y).at(x));
} }
@ -402,7 +403,7 @@ int QrCode::handleConstructorMasking(int mask) {
} }
} }
if (mask < 0 || mask > 7) if (mask < 0 || mask > 7)
throw "Assertion error"; throw std::logic_error("Assertion error");
drawFormatBits(mask); // Overwrite old format bits drawFormatBits(mask); // Overwrite old format bits
applyMask(mask); // Apply the final choice of mask applyMask(mask); // Apply the final choice of mask
return mask; // The caller shall assign this value to the final-declared field return mask; // The caller shall assign this value to the final-declared field
@ -491,7 +492,7 @@ long QrCode::getPenaltyScore() const {
vector<int> QrCode::getAlignmentPatternPositions(int ver) { vector<int> QrCode::getAlignmentPatternPositions(int ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (ver < MIN_VERSION || ver > MAX_VERSION)
throw "Version number out of range"; throw std::domain_error("Version number out of range");
else if (ver == 1) else if (ver == 1)
return vector<int>(); return vector<int>();
else { else {
@ -514,7 +515,7 @@ vector<int> QrCode::getAlignmentPatternPositions(int ver) {
int QrCode::getNumRawDataModules(int ver) { int QrCode::getNumRawDataModules(int ver) {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (ver < MIN_VERSION || ver > MAX_VERSION)
throw "Version number out of range"; throw std::domain_error("Version number out of range");
int result = (16 * ver + 128) * ver + 64; int result = (16 * ver + 128) * ver + 64;
if (ver >= 2) { if (ver >= 2) {
int numAlign = ver / 7 + 2; int numAlign = ver / 7 + 2;
@ -528,7 +529,7 @@ int QrCode::getNumRawDataModules(int ver) {
int QrCode::getNumDataCodewords(int ver, Ecc ecl) { int QrCode::getNumDataCodewords(int ver, Ecc ecl) {
if (ver < MIN_VERSION || ver > MAX_VERSION) if (ver < MIN_VERSION || ver > MAX_VERSION)
throw "Version number out of range"; throw std::domain_error("Version number out of range");
return getNumRawDataModules(ver) / 8 return getNumRawDataModules(ver) / 8
- ECC_CODEWORDS_PER_BLOCK[static_cast<int>(ecl)][ver] - ECC_CODEWORDS_PER_BLOCK[static_cast<int>(ecl)][ver]
* NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(ecl)][ver]; * NUM_ERROR_CORRECTION_BLOCKS[static_cast<int>(ecl)][ver];
@ -570,7 +571,7 @@ const int8_t QrCode::NUM_ERROR_CORRECTION_BLOCKS[4][41] = {
QrCode::ReedSolomonGenerator::ReedSolomonGenerator(int degree) : QrCode::ReedSolomonGenerator::ReedSolomonGenerator(int degree) :
coefficients() { coefficients() {
if (degree < 1 || degree > 255) if (degree < 1 || degree > 255)
throw "Degree out of range"; throw std::domain_error("Degree out of range");
// Start with the monomial x^0 // Start with the monomial x^0
coefficients.resize(degree); coefficients.resize(degree);
@ -614,7 +615,7 @@ uint8_t QrCode::ReedSolomonGenerator::multiply(uint8_t x, uint8_t y) {
z ^= ((y >> i) & 1) * x; z ^= ((y >> i) & 1) * x;
} }
if (z >> 8 != 0) if (z >> 8 != 0)
throw "Assertion error"; throw std::logic_error("Assertion error");
return static_cast<uint8_t>(z); return static_cast<uint8_t>(z);
} }

@ -23,6 +23,7 @@
#include <climits> #include <climits>
#include <cstring> #include <cstring>
#include <stdexcept>
#include <utility> #include <utility>
#include "QrSegment.hpp" #include "QrSegment.hpp"
@ -49,7 +50,7 @@ int QrSegment::Mode::numCharCountBits(int ver) const {
if ( 1 <= ver && ver <= 9) return numBitsCharCount[0]; if ( 1 <= ver && ver <= 9) return numBitsCharCount[0];
else if (10 <= ver && ver <= 26) return numBitsCharCount[1]; else if (10 <= ver && ver <= 26) return numBitsCharCount[1];
else if (27 <= ver && ver <= 40) return numBitsCharCount[2]; else if (27 <= ver && ver <= 40) return numBitsCharCount[2];
else throw "Version number out of range"; else throw std::domain_error("Version number out of range");
} }
@ -63,7 +64,7 @@ const QrSegment::Mode QrSegment::Mode::ECI (0x7, 0, 0, 0);
QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) { QrSegment QrSegment::makeBytes(const vector<uint8_t> &data) {
if (data.size() > INT_MAX) if (data.size() > INT_MAX)
throw "Data too long"; throw std::length_error("Data too long");
BitBuffer bb; BitBuffer bb;
for (uint8_t b : data) for (uint8_t b : data)
bb.appendBits(b, 8); bb.appendBits(b, 8);
@ -79,7 +80,7 @@ QrSegment QrSegment::makeNumeric(const char *digits) {
for (; *digits != '\0'; digits++, charCount++) { for (; *digits != '\0'; digits++, charCount++) {
char c = *digits; char c = *digits;
if (c < '0' || c > '9') if (c < '0' || c > '9')
throw "String contains non-numeric characters"; throw std::domain_error("String contains non-numeric characters");
accumData = accumData * 10 + (c - '0'); accumData = accumData * 10 + (c - '0');
accumCount++; accumCount++;
if (accumCount == 3) { if (accumCount == 3) {
@ -102,7 +103,7 @@ QrSegment QrSegment::makeAlphanumeric(const char *text) {
for (; *text != '\0'; text++, charCount++) { for (; *text != '\0'; text++, charCount++) {
const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text); const char *temp = std::strchr(ALPHANUMERIC_CHARSET, *text);
if (temp == nullptr) if (temp == nullptr)
throw "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 + (temp - ALPHANUMERIC_CHARSET);
accumCount++; accumCount++;
if (accumCount == 2) { if (accumCount == 2) {
@ -146,7 +147,7 @@ QrSegment QrSegment::makeEci(long assignVal) {
bb.appendBits(6, 3); bb.appendBits(6, 3);
bb.appendBits(assignVal, 21); bb.appendBits(assignVal, 21);
} else } else
throw "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));
} }
@ -156,7 +157,7 @@ QrSegment::QrSegment(Mode md, int numCh, const std::vector<bool> &dt) :
numChars(numCh), numChars(numCh),
data(dt) { data(dt) {
if (numCh < 0) if (numCh < 0)
throw "Invalid value"; throw std::domain_error("Invalid value");
} }
@ -165,13 +166,13 @@ QrSegment::QrSegment(Mode md, int numCh, std::vector<bool> &&dt) :
numChars(numCh), numChars(numCh),
data(std::move(dt)) { data(std::move(dt)) {
if (numCh < 0) if (numCh < 0)
throw "Invalid value"; throw std::domain_error("Invalid value");
} }
int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) { int QrSegment::getTotalBits(const vector<QrSegment> &segs, int version) {
if (version < 1 || version > 40) if (version < 1 || version > 40)
throw "Version number out of range"; throw std::domain_error("Version number out of range");
int result = 0; int result = 0;
for (const QrSegment &seg : segs) { for (const QrSegment &seg : segs) {
int ccbits = seg.mode.numCharCountBits(version); int ccbits = seg.mode.numCharCountBits(version);

Loading…
Cancel
Save