From 562df68c926ad30d54d05983671c56d64266beba Mon Sep 17 00:00:00 2001 From: dm1sh Date: Sun, 26 Dec 2021 07:58:44 +0300 Subject: [PATCH] Switched from string to vector of unsigned chars as input --- Demo/main.cpp | 2 +- QRCodeLibrary/Encoder.cpp | 2 +- QRCodeLibrary/Encoder.hpp | 14 +++++++------- QRCodeLibrary/Method.cpp | 2 +- QRCodeLibrary/Method.hpp | 4 ++-- QRCodeLibrary/QRCode.cpp | 2 +- QRCodeLibrary/QRCode.hpp | 6 ++++-- QRCodeLibrary/utils.hpp | 15 ++++++++++++++- README.MD | 12 +++++++----- tests/Encoder_test.cpp | 9 ++++----- tests/Method_test.cpp | 6 +++--- tests/QRCode_test.cpp | 10 ++-------- 12 files changed, 47 insertions(+), 37 deletions(-) diff --git a/Demo/main.cpp b/Demo/main.cpp index 3b45949..f26cdf6 100644 --- a/Demo/main.cpp +++ b/Demo/main.cpp @@ -64,7 +64,7 @@ int main() { input = cp1251_to_utf8(input.c_str()); #endif - QRCode qr(input); + QRCode qr(input, CorrectionLevel::H); const auto& res = qr.to_vector(); diff --git a/QRCodeLibrary/Encoder.cpp b/QRCodeLibrary/Encoder.cpp index 4f5fd08..a3dc2a0 100644 --- a/QRCodeLibrary/Encoder.cpp +++ b/QRCodeLibrary/Encoder.cpp @@ -91,7 +91,7 @@ void Encoder::encode_alphabetic(const string& input, BitArray& out, unsigned off } } -void Encoder::encode_byte(const string& input, BitArray& out, unsigned offset) +void Encoder::encode_byte(const byte_list& input, BitArray& out, unsigned offset) { for (unsigned i = 0; i < input.size(); i++) out.set(offset + i * 8, input[i], 8); diff --git a/QRCodeLibrary/Encoder.hpp b/QRCodeLibrary/Encoder.hpp index 6e07737..aa12a6e 100644 --- a/QRCodeLibrary/Encoder.hpp +++ b/QRCodeLibrary/Encoder.hpp @@ -13,7 +13,7 @@ using namespace std; class Encoder { public: - Encoder(const string& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1) : input{ input_ }, corr_lvl{ corr_lvl_ }, method{ method_ }, version{ version_ } {}; + Encoder(const byte_list& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1) : input{ input_ }, corr_lvl{ corr_lvl_ }, method{ method_ }, version{ version_ } {}; BitArray& encode(); @@ -27,10 +27,10 @@ public: constexpr void encode_input(unsigned offset) { switch (method) { case QRCodeMethod::Numeric: - encode_numeric(input, e, offset); + encode_numeric(bytes_to_str(input), e, offset); break; case QRCodeMethod::Alphabetic: - encode_alphabetic(input, e, offset); + encode_alphabetic(bytes_to_str(input), e, offset); break; case QRCodeMethod::Byte: encode_byte(input, e, offset); @@ -40,7 +40,7 @@ public: static void encode_numeric(const string& input, BitArray& out, unsigned offset); static void encode_alphabetic(const string& input, BitArray& out, unsigned offset); - static void encode_byte(const string& input, BitArray& out, unsigned offset); + static void encode_byte(const byte_list& input, BitArray& out, unsigned offset); static void pad_data(BitArray& arr, unsigned bits_written); @@ -50,7 +50,7 @@ public: private: static constexpr unsigned char encode_char(char ch); - const string input; + const byte_list input; CorrectionLevel corr_lvl; const QRCodeMethod method; char version; @@ -86,8 +86,8 @@ constexpr unsigned Encoder::calculate_encoded_input_size(unsigned input_size, QR } template -constexpr unsigned upper_index(const array arr, T val) { - unsigned count = to_U(arr.size()), s = 0, e = 0, step = 0; +constexpr unsigned upper_index(const array& arr, T val) { + unsigned count = N, s = 0, e = 0, step = 0; while (count > 0) { step = count / 2; diff --git a/QRCodeLibrary/Method.cpp b/QRCodeLibrary/Method.cpp index 0d3524b..390fc2f 100644 --- a/QRCodeLibrary/Method.cpp +++ b/QRCodeLibrary/Method.cpp @@ -3,7 +3,7 @@ #include "Method.hpp" #include "Tables.hpp" -QRCodeMethod Method::determite_method(string& input) +QRCodeMethod Method::determite_method(byte_list& input) { QRCodeMethod type = QRCodeMethod::Numeric; diff --git a/QRCodeLibrary/Method.hpp b/QRCodeLibrary/Method.hpp index 0838b5f..e4503e3 100644 --- a/QRCodeLibrary/Method.hpp +++ b/QRCodeLibrary/Method.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include "utils.hpp" using namespace std; @@ -20,7 +20,7 @@ enum class CorrectionLevel { class Method { public: - static QRCodeMethod determite_method(string& input); + static QRCodeMethod determite_method(byte_list& input); static constexpr bool is_num(char ch) { return ch >= '0' && ch <= '9'; }; }; diff --git a/QRCodeLibrary/QRCode.cpp b/QRCodeLibrary/QRCode.cpp index 2fc3b8d..17b51f0 100644 --- a/QRCodeLibrary/QRCode.cpp +++ b/QRCodeLibrary/QRCode.cpp @@ -5,7 +5,7 @@ #include "DataBlocks.hpp" #include "Tables.hpp" -QRCode::QRCode(string& input_, CorrectionLevel corr_lvl_, QRCodeMethod method_, char version_, unsigned char mask_n) : +QRCode::QRCode(const byte_list& input_, CorrectionLevel corr_lvl_, QRCodeMethod method_, char version_, unsigned char mask_n) : input{ input_ }, corr_lvl{ corr_lvl_ }, method{ method_ }, version{ version_ }, matrix(0) { if (method == QRCodeMethod::Dynamic) { diff --git a/QRCodeLibrary/QRCode.hpp b/QRCodeLibrary/QRCode.hpp index 637ec8c..5be5373 100644 --- a/QRCodeLibrary/QRCode.hpp +++ b/QRCodeLibrary/QRCode.hpp @@ -4,20 +4,22 @@ #include "Method.hpp" #include "QRMatrix.hpp" +#include "utils.hpp" using namespace std; class QRCode { public: - QRCode(string& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1, unsigned char mask_n = 0); + QRCode(const byte_list& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1, unsigned char mask_n = 0); + QRCode(const string& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1, unsigned char mask_n = 0) : QRCode(str_to_bytes(input_), corr_lvl_, method_, version_, mask_n) {}; string to_string() const { return matrix.to_string(); }; string to_ascii(char black = '#', char white = ' ', char empty = 'E') const { return matrix.to_ascii(black, white, empty); } vector> to_vector() const { return matrix.to_vector(); }; protected: - string input; + byte_list input; CorrectionLevel corr_lvl; QRCodeMethod method; char version; diff --git a/QRCodeLibrary/utils.hpp b/QRCodeLibrary/utils.hpp index 9f47c8d..77a5d60 100644 --- a/QRCodeLibrary/utils.hpp +++ b/QRCodeLibrary/utils.hpp @@ -1,10 +1,23 @@ #pragma once +#include #include #include +#include +#include -constexpr unsigned to_U(size_t val) { +constexpr static unsigned to_U(size_t val) { if (val > (std::numeric_limits::max)()) throw std::runtime_error("Too big number to convert it to unsigned int" + std::to_string(val)); return static_cast(val); } + +using byte_list = std::vector; + +static byte_list str_to_bytes(const std::string& inp) { + return byte_list(inp.begin(), inp.end()); +} + +static std::string bytes_to_str(const byte_list& inp) { + return std::string(inp.begin(), inp.end()); +} \ No newline at end of file diff --git a/README.MD b/README.MD index b6e7c6f..2209fd2 100644 --- a/README.MD +++ b/README.MD @@ -7,20 +7,24 @@ ## Description -A C++ library for QRCode generation. It provides `QRCode` class with constructor, accepting input string and other QR code properties (see constructor definition below). After class construction you can access QR code content as new-line separated string of zeros and ones (useful for latter processing in other languages), multiline ASCII string for immidiate console output, or 2D vector of `Trit`s. It is an internal enum with three possible values: black, white or empty. +A C++ library for QRCode generation. It provides `QRCode` class with constructor, accepting input bytes as vector of unsigned chars or string and other QR code properties (see constructor definition below). After class construction you can access QR code content as new-line separated string of zeros and ones (useful for latter processing in other languages), multiline ASCII string for immidiate console output, or 2D vector of `Trit`s. It is an internal enum with three possible values: black, white or empty. ## Library interface ```c++ +using byte_list = vector; // shorthand for + class QRCode { public: - QRCode( string& input_, // input string for qr-code encoding + QRCode( const byte_list& input_, // input bytes for qr-code encoding CorrectionLevel corr_lvl_ = CorrectionLevel::M, // correction level of qr-code (see below for possible values) QRCodeMethod method_ = QRCodeMethod::Dynamic, // input encoding method (see below for possible values) char version_ = -1, // manual version, starting from 0 (0 - 39 versions). If not set, calculated dynamically unsigned char mask_n = 0 // index of mask to use (see below for different masks options) ); + // same as before except for input as std::string + QRCode(const string& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1, unsigned char mask_n = 0) string to_string() const; // presents qr-code as multiline string of zeros and ones string to_ascii(char black = '#', char white = ' ', char empty = 'E') const; // presents qr-code as multiline string of specified characters @@ -92,9 +96,7 @@ Creating qrcode from string "HELLO WORLD" with quarter correction level, in alph // ... -std::string input("HELLO WORLD"); - -QRCode qr(input, CorrectionLevel::Q, QRCodeMethod::Alphabetic, 1, 3); +QRCode qr("HELLO WORLD", CorrectionLevel::Q, QRCodeMethod::Alphabetic, 1, 3); std::cout << qr.to_ascii('#', ' ', 'E') << std::endl; ``` diff --git a/tests/Encoder_test.cpp b/tests/Encoder_test.cpp index f4918d1..b48ae3c 100644 --- a/tests/Encoder_test.cpp +++ b/tests/Encoder_test.cpp @@ -3,7 +3,6 @@ #define private public #include "../QRCodeLibrary/Encoder.hpp" -#include "../QRCodeLibrary/utils.hpp" /* upper_index function */ @@ -89,7 +88,7 @@ TEST(EncoderTests, EncodesAlphabetic) { TEST(EncoderTests, EncodesBytes) { BitArray tmp(to_U(string("0000110100001001010011010000101111001101000010111000110100011000001011010001100000001101000010111000110100001011100100100000110100001010100011010000101110001101000110001000110100001011101011010000101111101101000010110010").size())); - Encoder::encode_byte(u8"Дмитрий Шишков", tmp, 4); + Encoder::encode_byte(str_to_bytes(u8"Дмитрий Шишков"), tmp, 4); EXPECT_EQ(std::string(tmp), "0000110100001001010011010000101111001101000010111000110100011000001011010001100000001101000010111000110100001011100100100000110100001010100011010000101110001101000110001000110100001011101011010000101111101101000010110010"); } @@ -106,15 +105,15 @@ TEST(EncoderTests, PadsData) { } TEST(EncoderTests, EncodesInput) { - Encoder e1("8675309", CorrectionLevel::Q, QRCodeMethod::Numeric); + Encoder e1(str_to_bytes("8675309"), CorrectionLevel::Q, QRCodeMethod::Numeric); e1.encode(); EXPECT_EQ(std::string(e1.get_data()), "00010000000111110110001110000100101001001110110000010001111011000001000111101100000100011110110000010001"); - Encoder e2("HELLO WORLD", CorrectionLevel::M, QRCodeMethod::Alphabetic); + Encoder e2(str_to_bytes("HELLO WORLD"), CorrectionLevel::M, QRCodeMethod::Alphabetic); e2.encode(); EXPECT_EQ(std::string(e2.get_data()), "00100000010110110000101101111000110100010111001011011100010011010100001101000000111011000001000111101100000100011110110000010001"); - Encoder e3(u8"Дмитрий Шишков", CorrectionLevel::Q, QRCodeMethod::Byte); + Encoder e3(str_to_bytes(u8"Дмитрий Шишков"), CorrectionLevel::Q, QRCodeMethod::Byte); e3.encode(); EXPECT_EQ(std::string(e3.get_data()), "01000001101111010000100101001101000010111100110100001011100011010001100000101101000110000000110100001011100011010000101110010010000011010000101010001101000010111000110100011000100011010000101110101101000010111110110100001011001000001110110000010001111011000001000111101100"); } \ No newline at end of file diff --git a/tests/Method_test.cpp b/tests/Method_test.cpp index 5dc435b..eb3597c 100644 --- a/tests/Method_test.cpp +++ b/tests/Method_test.cpp @@ -10,9 +10,9 @@ TEST(MethodTests, DetermitesStringMethod) { string a2("ABC"); string a3("ghfjghfj gfjhgd"); - EXPECT_EQ(Method::determite_method(a1), QRCodeMethod::Numeric); - EXPECT_EQ(Method::determite_method(a2), QRCodeMethod::Alphabetic); - EXPECT_EQ(Method::determite_method(a3), QRCodeMethod::Byte); + EXPECT_EQ(Method::determite_method(str_to_bytes(a1)), QRCodeMethod::Numeric); + EXPECT_EQ(Method::determite_method(str_to_bytes(a2)), QRCodeMethod::Alphabetic); + EXPECT_EQ(Method::determite_method(str_to_bytes(a3)), QRCodeMethod::Byte); } TEST(MethodTests, ChecksNumber) { diff --git a/tests/QRCode_test.cpp b/tests/QRCode_test.cpp index 8653dd8..d87b748 100644 --- a/tests/QRCode_test.cpp +++ b/tests/QRCode_test.cpp @@ -5,16 +5,10 @@ #include "../QRCodeLibrary/QRCode.hpp" -class QRCodeConstructorMock : public QRCode { -public: - template - QRCodeConstructorMock(Parameters ...params) {}; -}; TEST(QRCodeTests, ConstructsClass) { - string inp("TESTTESTTESTTESTTESTTEST"); - QRCode qr(inp); + QRCode qr("TESTTESTTESTTESTTESTTEST"); - EXPECT_EQ(qr.input, "TESTTESTTESTTESTTESTTEST"); + EXPECT_EQ(qr.input, str_to_bytes("TESTTESTTESTTESTTESTTEST")); EXPECT_EQ(qr.corr_lvl, CorrectionLevel::M); EXPECT_EQ(qr.method, QRCodeMethod::Alphabetic); EXPECT_EQ(qr.version, 1);