pull/16/merge
Philipp Hasper 8 years ago committed by GitHub
commit 5dfeb43bb4

@ -1,9 +1,9 @@
/*
/*
* QR Code generator library (C++)
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to

@ -1,9 +1,9 @@
/*
/*
* QR Code generator library (C++)
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
@ -29,29 +29,29 @@
namespace qrcodegen {
/*
/*
* An appendable sequence of bits (0's and 1's).
*/
class BitBuffer final : public std::vector<bool> {
/*---- Constructor ----*/
// Creates an empty bit buffer (length 0).
public: BitBuffer();
/*---- Methods ----*/
// Packs this buffer's bits into bytes in big endian,
// padding with '0' bit values, and returns the new vector.
public: std::vector<std::uint8_t> getBytes() const;
// Appends the given number of low bits of the given value
// to this sequence. Requires 0 <= val < 2^len.
public: void appendBits(std::uint32_t val, int len);
};
}

@ -1,9 +1,9 @@
/*
/*
* QR Code generator library (C++)
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
@ -75,7 +75,7 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
int minVersion, int maxVersion, int mask, bool boostEcl) {
if (!(1 <= minVersion && minVersion <= maxVersion && maxVersion <= 40) || mask < -1 || mask > 7)
throw "Invalid value";
// Find the minimal version number to use
int version, dataUsedBits;
for (version = minVersion; ; version++) {
@ -88,13 +88,13 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
}
if (dataUsedBits == -1)
throw "Assertion error";
// 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}) {
if (boostEcl && dataUsedBits <= getNumDataCodewords(version, newEcl) * 8)
ecl = newEcl;
}
// Create the data bit string by concatenating all segments
size_t dataCapacityBits = getNumDataCodewords(version, ecl) * 8;
BitBuffer bb;
@ -103,17 +103,17 @@ QrCode QrCode::encodeSegments(const vector<QrSegment> &segs, Ecc ecl,
bb.appendBits(seg.getNumChars(), seg.getMode().numCharCountBits(version));
bb.insert(bb.end(), seg.getData().begin(), seg.getData().end());
}
// Add terminator and pad up to a byte if applicable
bb.appendBits(0, std::min<size_t>(4, dataCapacityBits - bb.size()));
bb.appendBits(0, (8 - bb.size() % 8) % 8);
// Pad with alternate bytes until data capacity is reached
for (uint8_t padByte = 0xEC; bb.size() < dataCapacityBits; padByte ^= 0xEC ^ 0x11)
bb.appendBits(padByte, 8);
if (bb.size() % 8 != 0)
throw "Assertion error";
// Create the QR Code symbol
return QrCode(version, ecl, bb.getBytes(), mask);
}
@ -126,11 +126,11 @@ QrCode::QrCode(int ver, Ecc ecl, const vector<uint8_t> &dataCodewords, int mask)
errorCorrectionLevel(ecl),
modules(size, vector<bool>(size)), // Entirely white grid
isFunction(size, vector<bool>(size)) {
// Check arguments
if (ver < 1 || ver > 40 || mask < -1 || mask > 7)
throw "Value out of range";
// Draw function patterns, draw all codewords, do masking
drawFunctionPatterns();
const vector<uint8_t> allCodewords(appendErrorCorrection(dataCodewords));
@ -147,11 +147,11 @@ QrCode::QrCode(const QrCode &qr, int mask) :
// Handle grid fields
modules(qr.modules),
isFunction(qr.isFunction) {
// Check arguments
if (mask < -1 || mask > 7)
throw "Mask value out of range";
// Handle masking
applyMask(qr.mask); // Undo old mask
this->mask = handleConstructorMasking(mask);
@ -217,12 +217,12 @@ void QrCode::drawFunctionPatterns() {
setFunctionModule(6, i, i % 2 == 0);
setFunctionModule(i, 6, i % 2 == 0);
}
// Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules)
drawFinderPattern(3, 3);
drawFinderPattern(size - 4, 3);
drawFinderPattern(3, size - 4);
// Draw numerous alignment patterns
const vector<int> alignPatPos(getAlignmentPatternPositions(version));
int numAlign = alignPatPos.size();
@ -234,7 +234,7 @@ void QrCode::drawFunctionPatterns() {
drawAlignmentPattern(alignPatPos.at(i), alignPatPos.at(j));
}
}
// Draw configuration data
drawFormatBits(0); // Dummy mask value; overwritten later in the constructor
drawVersion();
@ -251,7 +251,7 @@ void QrCode::drawFormatBits(int mask) {
data ^= 0x5412; // uint15
if (data >> 15 != 0)
throw "Assertion error";
// Draw first copy
for (int i = 0; i <= 5; i++)
setFunctionModule(8, i, ((data >> i) & 1) != 0);
@ -260,7 +260,7 @@ void QrCode::drawFormatBits(int mask) {
setFunctionModule(7, 8, ((data >> 8) & 1) != 0);
for (int i = 9; i < 15; i++)
setFunctionModule(14 - i, 8, ((data >> i) & 1) != 0);
// Draw second copy
for (int i = 0; i <= 7; i++)
setFunctionModule(size - 1 - i, 8, ((data >> i) & 1) != 0);
@ -273,7 +273,7 @@ void QrCode::drawFormatBits(int mask) {
void QrCode::drawVersion() {
if (version < 7)
return;
// Calculate error correction code and pack bits
int rem = version; // version is uint6, in the range [7, 40]
for (int i = 0; i < 12; i++)
@ -281,7 +281,7 @@ void QrCode::drawVersion() {
long data = (long)version << 12 | rem; // uint18
if (data >> 18 != 0)
throw "Assertion error";
// Draw two copies
for (int i = 0; i < 18; i++) {
bool bit = ((data >> i) & 1) != 0;
@ -326,14 +326,14 @@ bool QrCode::module(int x, int y) const {
vector<uint8_t> QrCode::appendErrorCorrection(const vector<uint8_t> &data) const {
if (data.size() != static_cast<unsigned int>(getNumDataCodewords(version, errorCorrectionLevel)))
throw "Invalid argument";
// Calculate parameter numbers
int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[errorCorrectionLevel.getOrdinal()][version];
int blockEccLen = ECC_CODEWORDS_PER_BLOCK[errorCorrectionLevel.getOrdinal()][version];
int rawCodewords = getNumRawDataModules(version) / 8;
int numShortBlocks = numBlocks - rawCodewords % numBlocks;
int shortBlockLen = rawCodewords / numBlocks;
// Split data into blocks and append ECC to each block
vector<vector<uint8_t> > blocks;
const ReedSolomonGenerator rs(blockEccLen);
@ -346,7 +346,7 @@ vector<uint8_t> QrCode::appendErrorCorrection(const vector<uint8_t> &data) const
dat.insert(dat.end(), ecc.cbegin(), ecc.cend());
blocks.push_back(std::move(dat));
}
// Interleave (not concatenate) the bytes from every block into a single sequence
vector<uint8_t> result;
for (int i = 0; static_cast<unsigned int>(i) < blocks.at(0).size(); i++) {
@ -365,7 +365,7 @@ vector<uint8_t> QrCode::appendErrorCorrection(const vector<uint8_t> &data) const
void QrCode::drawCodewords(const vector<uint8_t> &data) {
if (data.size() != static_cast<unsigned int>(getNumRawDataModules(version) / 8))
throw "Invalid argument";
size_t i = 0; // Bit index into the data
// Do the funny zigzag scan
for (int right = size - 1; right >= 1; right -= 2) { // Index of right column in each column pair
@ -437,7 +437,7 @@ int QrCode::handleConstructorMasking(int mask) {
long QrCode::getPenaltyScore() const {
long result = 0;
// Adjacent modules in row having same color
for (int y = 0; y < size; y++) {
bool colorX;
@ -470,7 +470,7 @@ long QrCode::getPenaltyScore() const {
}
}
}
// 2*2 blocks of modules having same color
for (int y = 0; y < size - 1; y++) {
for (int x = 0; x < size - 1; x++) {
@ -481,7 +481,7 @@ long QrCode::getPenaltyScore() const {
result += PENALTY_N2;
}
}
// Finder-like pattern in rows
for (int y = 0; y < size; y++) {
for (int x = 0, bits = 0; x < size; x++) {
@ -498,7 +498,7 @@ long QrCode::getPenaltyScore() const {
result += PENALTY_N3;
}
}
// Balance of black and white modules
int black = 0;
for (const vector<bool> &row : modules) {
@ -528,7 +528,7 @@ vector<int> QrCode::getAlignmentPatternPositions(int ver) {
step = (ver * 4 + numAlign * 2 + 1) / (2 * numAlign - 2) * 2;
} else // C-C-C-Combo breaker!
step = 26;
vector<int> result;
for (int i = 0, pos = ver * 4 + 10; i < numAlign - 1; i++, pos -= step)
result.insert(result.begin(), pos);
@ -592,11 +592,11 @@ QrCode::ReedSolomonGenerator::ReedSolomonGenerator(int degree) :
coefficients() {
if (degree < 1 || degree > 255)
throw "Degree out of range";
// Start with the monomial x^0
coefficients.resize(degree);
coefficients.at(degree - 1) = 1;
// Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}),
// drop the highest term, and store the rest of the coefficients in order of descending powers.
// Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D).

@ -1,9 +1,9 @@
/*
/*
* QR Code generator library (C++)
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
@ -31,42 +31,42 @@
namespace qrcodegen {
/*
/*
* Represents an immutable square grid of black and white cells for a QR Code symbol, and
* provides static functions to create a QR Code from user-supplied textual or binary data.
* This class covers the QR Code model 2 specification, supporting all versions (sizes)
* from 1 to 40, all 4 error correction levels, and only 3 character encoding modes.
*/
class QrCode final {
/*---- Public helper enumeration ----*/
/*
/*
* Represents the error correction level used in a QR Code symbol.
*/
public: class Ecc final {
// Constants declared in ascending order of error protection.
public: const static Ecc LOW, MEDIUM, QUARTILE, HIGH;
// Fields.
private: int ordinal;
private: int formatBits;
// Constructor.
private: Ecc(int ord, int fb);
// (Public) Returns a value in the range 0 to 3 (unsigned 2-bit integer).
public: int getOrdinal() const;
// (Package-private) Returns a value in the range 0 to 3 (unsigned 2-bit integer).
public: int getFormatBits() const;
};
/*---- Public static factory functions ----*/
/*
/*
* Returns a QR Code symbol representing the specified Unicode text string at the specified error correction level.
* As a conservative upper bound, this function is guaranteed to succeed for strings that have 2953 or fewer
* UTF-8 code units (not Unicode code points) if the low error correction level is used. The smallest possible
@ -74,18 +74,18 @@ class QrCode final {
* the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeText(const char *text, Ecc ecl);
/*
/*
* Returns a QR Code symbol representing the given binary data string at the given error correction level.
* This function always encodes using the binary segment mode, not any text mode. The maximum number of
* bytes allowed is 2953. The smallest possible QR Code version is automatically chosen for the output.
* The ECC level of the result may be higher than the ecl argument if it can be done without increasing the version.
*/
public: static QrCode encodeBinary(const std::vector<std::uint8_t> &data, Ecc ecl);
/*
/*
* Returns a QR Code symbol representing the given data segments with the given encoding parameters.
* The smallest possible QR Code version within the given range is automatically chosen for the output.
* This function allows the user to create a custom sequence of segments that switches
@ -94,223 +94,223 @@ class QrCode final {
*/
public: static QrCode encodeSegments(const std::vector<QrSegment> &segs, Ecc ecl,
int minVersion=1, int maxVersion=40, int mask=-1, bool boostEcl=true); // All optional parameters
/*---- Instance fields ----*/
// Immutable scalar parameters
/* This QR Code symbol's version number, which is always between 1 and 40 (inclusive). */
private: int version;
/* The width and height of this QR Code symbol, measured in modules.
* Always equal to version &times; 4 + 17, in the range 21 to 177. */
private: int size;
/* The error correction level used in this QR Code symbol. */
private: Ecc errorCorrectionLevel;
/* The mask pattern used in this QR Code symbol, in the range 0 to 7 (i.e. unsigned 3-bit integer).
* Note that even if a constructor was called with automatic masking requested
* (mask = -1), the resulting object will still have a mask value between 0 and 7. */
private: int mask;
// Private grids of modules/pixels (conceptually immutable)
private: std::vector<std::vector<bool> > modules; // The modules of this QR Code symbol (false = white, true = black)
private: std::vector<std::vector<bool> > isFunction; // Indicates function modules that are not subjected to masking
/*---- Constructors ----*/
/*
/*
* Creates a new QR Code symbol with the given version number, error correction level, binary data array,
* and mask number. This is a cumbersome low-level constructor that should not be invoked directly by the user.
* To go one level up, see the encodeSegments() function.
*/
public: QrCode(int ver, Ecc ecl, const std::vector<std::uint8_t> &dataCodewords, int mask);
/*
/*
* Creates a new QR Code symbol based on the given existing object, but with a potentially
* different mask pattern. The version, error correction level, codewords, etc. of the newly
* created object are all identical to the argument object; only the mask may differ.
*/
public: QrCode(const QrCode &qr, int mask);
/*---- Public instance methods ----*/
public: int getVersion() const;
public: int getSize() const;
public: Ecc getErrorCorrectionLevel() const;
public: int getMask() const;
/*
/*
* Returns the color of the module (pixel) at the given coordinates, which is either
* false for white or true for black. The top left corner has the coordinates (x=0, y=0).
* If the given coordinates are out of bounds, then false (white) is returned.
*/
public: bool getModule(int x, int y) const;
/*
/*
* Based on the given number of border modules to add as padding, this returns a
* string whose contents represents an SVG XML file that depicts this QR Code symbol.
* Note that Unix newlines (\n) are always used, regardless of the platform.
*/
public: std::string toSvgString(int border) const;
/*---- Private helper methods for constructor: Drawing function modules ----*/
private: void drawFunctionPatterns();
// Draws two copies of the format bits (with its own error correction code)
// based on the given mask and this object's error correction level field.
private: void drawFormatBits(int mask);
// Draws two copies of the version bits (with its own error correction code),
// based on this object's version field (which only has an effect for 7 <= version <= 40).
private: void drawVersion();
// Draws a 9*9 finder pattern including the border separator, with the center module at (x, y).
private: void drawFinderPattern(int x, int y);
// Draws a 5*5 alignment pattern, with the center module at (x, y).
private: void drawAlignmentPattern(int x, int y);
// Sets the color of a module and marks it as a function module.
// Only used by the constructor. Coordinates must be in range.
private: void setFunctionModule(int x, int y, bool isBlack);
// Returns the color of the module at the given coordinates, which must be in range.
private: bool module(int x, int y) const;
/*---- Private helper methods for constructor: Codewords and masking ----*/
// Returns a new byte string representing the given data with the appropriate error correction
// codewords appended to it, based on this object's version and error correction level.
private: std::vector<std::uint8_t> appendErrorCorrection(const std::vector<std::uint8_t> &data) const;
// Draws the given sequence of 8-bit codewords (data and error correction) onto the entire
// data area of this QR Code symbol. Function modules need to be marked off before this is called.
private: void drawCodewords(const std::vector<std::uint8_t> &data);
// XORs the data modules in this QR Code with the given mask pattern. Due to XOR's mathematical
// properties, calling applyMask(m) twice with the same value is equivalent to no change at all.
// This means it is possible to apply a mask, undo it, and try another mask. Note that a final
// well-formed QR Code symbol needs exactly one mask applied (not zero, not two, etc.).
private: void applyMask(int mask);
// A messy helper function for the constructors. This QR Code must be in an unmasked state when this
// method is called. The given argument is the requested mask, which is -1 for auto or 0 to 7 for fixed.
// This method applies and returns the actual mask chosen, from 0 to 7.
private: int handleConstructorMasking(int mask);
// Calculates and returns the penalty score based on state of this QR Code's current modules.
// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score.
private: long getPenaltyScore() const;
/*---- Private static helper functions ----*/
// Returns a set of positions of the alignment patterns in ascending order. These positions are
// used on both the x and y axes. Each value in the resulting array is in the range [0, 177).
// This stateless pure function could be implemented as table of 40 variable-length lists of unsigned bytes.
private: static std::vector<int> getAlignmentPatternPositions(int ver);
// Returns the number of data bits that can be stored in a QR Code of the given version number, after
// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8.
// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table.
private: static int getNumRawDataModules(int ver);
// Returns the number of 8-bit data (i.e. not error correction) codewords contained in any
// QR Code of the given version number and error correction level, with remainder bits discarded.
// This stateless pure function could be implemented as a (40*4)-cell lookup table.
private: static int getNumDataCodewords(int ver, Ecc ecl);
/*---- Private tables of constants ----*/
// For use in getPenaltyScore(), when evaluating which mask is best.
private: static const int PENALTY_N1;
private: static const int PENALTY_N2;
private: static const int PENALTY_N3;
private: static const int PENALTY_N4;
private: static const std::int8_t ECC_CODEWORDS_PER_BLOCK[4][41];
private: static const std::int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41];
/*---- Private helper class ----*/
/*
/*
* Computes the Reed-Solomon error correction codewords for a sequence of data codewords
* at a given degree. Objects are immutable, and the state only depends on the degree.
* This class exists because each data block in a QR Code shares the same the divisor polynomial.
*/
private: class ReedSolomonGenerator final {
/*-- Immutable field --*/
// Coefficients of the divisor polynomial, 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}.
private: std::vector<std::uint8_t> coefficients;
/*-- Constructor --*/
/*
/*
* Creates a Reed-Solomon ECC generator for the given degree. This could be implemented
* as a lookup table over all possible parameter values, instead of as an algorithm.
*/
public: ReedSolomonGenerator(int degree);
/*-- Method --*/
/*
/*
* Computes and returns the Reed-Solomon error correction codewords for the given
* sequence of data codewords. The returned object is always a new byte array.
* This method does not alter this object's state (because it is immutable).
*/
public: std::vector<std::uint8_t> getRemainder(const std::vector<std::uint8_t> &data) const;
/*-- Static function --*/
// Returns the product of the two given field elements modulo GF(2^8/0x11D).
// All inputs are valid. This could be implemented as a 256*256 lookup table.
private: static std::uint8_t multiply(std::uint8_t x, std::uint8_t y);
};
};
}

@ -1,12 +1,12 @@
/*
/*
* QR Code generator demo (C++)
*
*
* Run this command-line program with no arguments. The program computes a bunch of demonstration
* QR Codes and prints them to the console. Also, the SVG code for one QR Code is printed as a sample.
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
@ -59,7 +59,7 @@ int main() {
static void doBasicDemo() {
const char *text = "Hello, world!"; // User-supplied text
const QrCode::Ecc errCorLvl = QrCode::Ecc::LOW; // Error correction level
// Make and print the QR Code symbol
const QrCode qr = QrCode::encodeText(text, errCorLvl);
std::cout << qr.toSvgString(4) << std::endl;
@ -72,22 +72,22 @@ static void doVarietyDemo() {
// Project Nayuki URL
const QrCode qr0 = QrCode::encodeText("https://www.nayuki.io/", QrCode::Ecc::HIGH);
printQr(QrCode(qr0, 3)); // Change mask, forcing to mask #3
// Numeric mode encoding (3.33 bits per digit)
const QrCode qr1 = QrCode::encodeText("314159265358979323846264338327950288419716939937510", QrCode::Ecc::MEDIUM);
printQr(qr1);
// Alphanumeric mode encoding (5.5 bits per character)
const QrCode qr2 = QrCode::encodeText("DOLLAR-AMOUNT:$39.87 PERCENTAGE:100.00% OPERATIONS:+-*/", QrCode::Ecc::HIGH);
printQr(qr2);
// Unicode text as UTF-8, and different masks
const QrCode qr3 = QrCode::encodeText("\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", QrCode::Ecc::QUARTILE);
printQr(QrCode(qr3, 0));
printQr(QrCode(qr3, 1));
printQr(QrCode(qr3, 5));
printQr(QrCode(qr3, 7));
// Moderately large QR Code using longer text (from Lewis Carroll's Alice in Wonderland)
const QrCode qr4 = QrCode::encodeText(
"Alice was beginning to get very tired of sitting by her sister on the bank, "
@ -110,12 +110,12 @@ static void doSegmentDemo() {
(std::string(silver0) + silver1).c_str(),
QrCode::Ecc::LOW);
printQr(qr0);
const QrCode qr1 = QrCode::encodeSegments(
{QrSegment::makeAlphanumeric(silver0), QrSegment::makeNumeric(silver1)},
QrCode::Ecc::LOW);
printQr(qr1);
// Illustration "golden"
const char *golden0 = "Golden ratio \xCF\x86 = 1.";
const char *golden1 = "6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374";
@ -124,13 +124,13 @@ static void doSegmentDemo() {
(std::string(golden0) + golden1 + golden2).c_str(),
QrCode::Ecc::LOW);
printQr(qr2);
std::vector<uint8_t> bytes(golden0, golden0 + std::strlen(golden0));
const QrCode qr3 = QrCode::encodeSegments(
{QrSegment::makeBytes(bytes), QrSegment::makeNumeric(golden1), QrSegment::makeAlphanumeric(golden2)},
QrCode::Ecc::LOW);
printQr(qr3);
// Illustration "Madoka": kanji, kana, Greek, Cyrillic, full-width Latin characters
const char *madoka = // Encoded in UTF-8
"\xE3\x80\x8C\xE9\xAD\x94\xE6\xB3\x95\xE5"
@ -144,7 +144,7 @@ static void doSegmentDemo() {
"\xBC\x9F";
const QrCode qr4 = QrCode::encodeText(madoka, QrCode::Ecc::LOW);
printQr(qr4);
const std::vector<int> kanjiChars{ // Kanji mode encoding (13 bits per character)
0x0035, 0x1002, 0x0FC0, 0x0AED, 0x0AD7,
0x015C, 0x0147, 0x0129, 0x0059, 0x01BD,

@ -1,14 +1,14 @@
/*
/*
* QR Code generator test worker (C++)
*
*
* This program reads data and encoding parameters from standard input and writes
* QR Code bitmaps to standard output. The I/O format is one integer per line.
* Run with no command line arguments. The program is intended for automated
* batch testing of end-to-end functionality of this QR Code generator library.
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
@ -47,13 +47,13 @@ static const QrCode::Ecc *(ECC_LEVELS[]) = {
int main() {
while (true) {
// Read data length or exit
int length;
std::cin >> length;
if (length == -1)
break;
// Read data bytes
bool isAscii = true;
std::vector<uint8_t> data;
@ -63,7 +63,7 @@ int main() {
data.push_back((uint8_t)b);
isAscii &= 0 < b && b < 128;
}
// Read encoding parameters
int errCorLvl, minVersion, maxVersion, mask, boostEcl;
std::cin >> errCorLvl;
@ -71,7 +71,7 @@ int main() {
std::cin >> maxVersion;
std::cin >> mask;
std::cin >> boostEcl;
// Make list of segments
std::vector<QrSegment> segs;
if (isAscii) {
@ -80,7 +80,7 @@ int main() {
segs = QrSegment::makeSegments(text.data());
} else
segs.push_back(QrSegment::makeBytes(data));
try { // Try to make QR Code symbol
const QrCode qr = QrCode::encodeSegments(segs,
*ECC_LEVELS[errCorLvl], minVersion, maxVersion, mask, boostEcl == 1);
@ -90,7 +90,7 @@ int main() {
for (int x = 0; x < qr.getSize(); x++)
std::cout << (qr.getModule(x, y) ? 1 : 0) << std::endl;
}
} catch (const char *msg) {
if (strcmp(msg, "Data too long") != 0) {
std::cerr << msg << std::endl;

@ -1,9 +1,9 @@
/*
/*
* QR Code generator library (C++)
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to

@ -1,9 +1,9 @@
/*
/*
* QR Code generator library (C++)
*
*
* Copyright (c) Project Nayuki. (MIT License)
* https://www.nayuki.io/page/qr-code-generator-library
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
@ -30,7 +30,7 @@
namespace qrcodegen {
/*
/*
* Represents a character string to be encoded in a QR Code symbol. Each segment has
* a mode, and a sequence of characters that is already encoded as a sequence of bits.
* Instances of this class are immutable.
@ -39,148 +39,148 @@ namespace qrcodegen {
* Any segment longer than this is meaningless for the purpose of generating QR Codes.
*/
class QrSegment final {
/*---- Public helper enumeration ----*/
/*
/*
* The mode field of a segment. Immutable. Provides methods to retrieve closely related values.
*/
public: class Mode final {
/*-- Constants --*/
public: static const Mode NUMERIC;
public: static const Mode ALPHANUMERIC;
public: static const Mode BYTE;
public: static const Mode KANJI;
public: static const Mode ECI;
/*-- Fields --*/
private: int modeBits;
private: int numBitsCharCount[3];
/*-- Constructor --*/
private: Mode(int mode, int cc0, int cc1, int cc2);
/*-- Methods --*/
/*
/*
* (Package-private) Returns the mode indicator bits, which is an unsigned 4-bit value (range 0 to 15).
*/
public: int getModeBits() const;
/*
/*
* (Package-private) Returns the bit width of the segment character count field for this mode object at the given version number.
*/
public: int numCharCountBits(int ver) const;
};
/*---- Public static factory functions ----*/
/*
/*
* Returns a segment representing the given binary data encoded in byte mode.
*/
public: static QrSegment makeBytes(const std::vector<std::uint8_t> &data);
/*
/*
* Returns a segment representing the given string of decimal digits encoded in numeric mode.
*/
public: static QrSegment makeNumeric(const char *digits);
/*
/*
* 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.
*/
public: static QrSegment makeAlphanumeric(const char *text);
/*
/*
* Returns a list of zero or more segments to represent the given text string.
* The result may use various segment modes and switch modes to optimize the length of the bit stream.
*/
public: static std::vector<QrSegment> makeSegments(const char *text);
/*
/*
* Returns a segment representing an Extended Channel Interpretation
* (ECI) designator with the given assignment value.
*/
public: static QrSegment makeEci(long assignVal);
/*---- Public static helper functions ----*/
/*
/*
* Tests whether the given string can be encoded as a segment in alphanumeric mode.
*/
public: static bool isAlphanumeric(const char *text);
/*
/*
* Tests whether the given string can be encoded as a segment in numeric mode.
*/
public: static bool isNumeric(const char *text);
/*---- Instance fields ----*/
/* The mode indicator for this segment. */
private: Mode mode;
/* The length of this segment's unencoded data, measured in characters. Always zero or positive. */
private: int numChars;
/* The data bits of this segment. */
private: std::vector<bool> data;
/*---- Constructor ----*/
/*
/*
* Creates a new QR Code data segment with the given parameters and data.
*/
public: QrSegment(Mode md, int numCh, const std::vector<bool> &dt);
/*
/*
* Creates a new QR Code data segment with the given parameters and data.
*/
public: QrSegment(Mode md, int numCh, std::vector<bool> &&dt);
/*---- Methods ----*/
public: Mode getMode() const;
public: int getNumChars() const;
public: const std::vector<bool> &getData() const;
// Package-private helper function.
public: static int getTotalBits(const std::vector<QrSegment> &segs, int version);
/*---- Private constant ----*/
/* The set of all legal characters in alphanumeric mode, where each character value maps to the index in the string. */
private: static const char *ALPHANUMERIC_CHARSET;
};
}

Loading…
Cancel
Save