Skip to content

Commit

Permalink
Did some code improvements, added comments for incomprehensible lines
Browse files Browse the repository at this point in the history
  • Loading branch information
dm1sh committed Dec 29, 2021
1 parent 7b38336 commit 1ceffb7
Show file tree
Hide file tree
Showing 14 changed files with 90 additions and 116 deletions.
23 changes: 14 additions & 9 deletions Demo/main.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#include <iostream>
#include <locale>

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#include <Windows.h>
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
#define IS_WINDOWS
#endif

#ifdef IS_WINDOWS
#include <IS_WINDOWSows.h>
#endif

#include "../QRCodeLibrary/QRCode.hpp"

using namespace std;

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#ifdef IS_WINDOWS
std::string cp1251_to_utf8(const char* str)
{
std::string res;
Expand Down Expand Up @@ -49,18 +53,19 @@ string str_of(unsigned k, const string& input) {
#endif

int main() {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#ifdef IS_WINDOWS
SetConsoleCP(1251);
#endif

string input, buff;
string input;
string buff;

while (getline(cin, buff)) {
input += buff + '\n';
}
input.pop_back();

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#ifdef IS_WINDOWS
input = cp1251_to_utf8(input.c_str());
#endif

Expand All @@ -70,7 +75,7 @@ int main() {

#define SQUARE_WIDTH 2

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#ifdef IS_WINDOWS
const string long_sep = string((res.size() + 8) * SQUARE_WIDTH, 219),
short_sep = string(4 * SQUARE_WIDTH, 219),
black = string(SQUARE_WIDTH, ' '),
Expand Down Expand Up @@ -106,7 +111,7 @@ int main() {
for (int i = 0; i < 4; i++)
cout << long_sep << endl;

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__)
#ifdef IS_WINDOWS
system("pause");
#endif
}
}
29 changes: 14 additions & 15 deletions QRCodeLibrary/BitArray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ bool BitArray::get(unsigned index) const
{
if (index >= size) throw std::out_of_range("No such element in array");

return (v[index / 8] >> (8 - 1 - index % 8)) & 1;
return (v[index / 8] >> (8 - index % 8 - 1)) & 1;
}

BitArray::operator std::string() const
{
std::stringstream res;

for (unsigned i = 0; i < size; i++)
res << static_cast<int>((*this).get(i));
res << static_cast<int>(get(i));

return res.str();
}
Expand All @@ -25,32 +25,31 @@ void BitArray::set(unsigned index, bool val)
{
if (index >= size) throw std::out_of_range("No such element in array");

if (val)
v[index / 8] |= 1 << (8 - 1 - index % 8);
if (val == 1)
v[index / 8] |= 1 << (8 - index % 8 - 1);
else
v[index / 8] &= ~(1 << (8 - 1 - index % 8));
v[index / 8] &= ~(1 << (8 - index % 8 - 1));
}

unsigned BitArray::set(unsigned index, int32_t val, unsigned size)
{
if (index >= this->size) throw std::out_of_range("No such element in array");

unsigned shift = index % 8, written = 0;
unsigned shift = index % 8;
unsigned written = 0;

if (size > this->size - index) throw std::out_of_range("Number of bits to write from this index is more than BitArray capability");

index /= 8;
for (int i = index / 8; written < size; i++) {
int input_shift = size - (8 - shift) - written; // right shift for written data
int right_rem = input_shift < 0 ? -input_shift : 0; // how many bits should I take from right side of original byte

while (written < size) {
int input_shift = size - (8 - shift) - written;
int right_rem = input_shift < 0 ? -input_shift : 0;

v[index] = ((v[index] >> (8 - shift)) << (8 - shift)) |
(unsigned char)(((1 << (8 - shift)) - 1) & ((input_shift >= 0) ? (val >> input_shift) : (val << -input_shift))) |
(v[index] & ((1 << right_rem) - 1));
v[i] = (v[i] & (-1 << (8 - shift))) |
(((1 << (8 - shift)) - 1) &
((input_shift >= 0) ? (val >> input_shift) : (val << -input_shift))) |
(v[i] & ((1 << right_rem) - 1));

written += 8 - shift;
index++;
shift = 0;
}

Expand Down
9 changes: 5 additions & 4 deletions QRCodeLibrary/BitArray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

using namespace std;

constexpr unsigned ceil_div(unsigned a, unsigned b) {
constexpr static unsigned ceil_div(unsigned a, unsigned b) {
if (b == 0) throw runtime_error("Dividion by zero not possible");
return a / b + (a % b > 0);
}
Expand All @@ -17,15 +17,16 @@ class BitArray
{
public:
BitArray(unsigned size_ = 0) : size{ size_ }, v(ceil_div(size_, 8), 0) {};
BitArray(const vector<unsigned char>& input) : size(to_U(input.size()) * 8), v{ input } {};
BitArray(const byte_list& input) : size(to_U(input.size()) * 8), v{ input } {};

operator std::string() const;

unsigned size;
vector<unsigned char> v;
unsigned size; // array size in bits
byte_list v;

bool get(unsigned index) const;
void set(unsigned index, bool val);
// sets least size bits of val starting from index
unsigned set(unsigned index, int32_t val, unsigned size);

void resize(unsigned new_size);
Expand Down
29 changes: 13 additions & 16 deletions QRCodeLibrary/DataBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,19 @@
#include "Tables.hpp"
#include "utils.hpp"

vector<unsigned char>& DataBlocks::compose_joined_data_and_EC_blocks()
DataBlocks::DataBlocks(const byte_list& e_data_, CorrectionLevel corr_lvl_, char version_) : e_data{ e_data_ }, corr_lvl{ corr_lvl_ }, version{ version_ }
{
vector<pair<unsigned, unsigned>>data_block_sizes;

divide_to_blocks(data_block_sizes, to_U(e_data.size()), Tables::data_blocks_number.at(corr_lvl).at(version));

unsigned EC_bytes_number = Tables::correction_bytes_num.at(corr_lvl).at(version);
vector<vector<unsigned char>> EC_blocks(data_block_sizes.size(), vector<unsigned char>());
vector<byte_list> EC_blocks(data_block_sizes.size(), byte_list());

for (unsigned i = 0; i < data_block_sizes.size(); i++)
compose_EC_bytes(EC_blocks[i], e_data.cbegin() + data_block_sizes[i].second, EC_bytes_number, data_block_sizes[i].first);

join_data_and_EC_blocks(data, e_data, data_block_sizes, EC_blocks, EC_bytes_number);

return data;
}

void DataBlocks::divide_to_blocks(vector<pair<unsigned, unsigned>>& db_sizes, unsigned data_size, unsigned db_number)
Expand All @@ -33,14 +32,16 @@ void DataBlocks::divide_to_blocks(vector<pair<unsigned, unsigned>>& db_sizes, un
}
}

void DataBlocks::compose_EC_bytes(vector<unsigned char>& res, const vector<unsigned char>::const_iterator& src, unsigned corr_bytes_num, unsigned db_size)
void DataBlocks::compose_EC_bytes(byte_list& res, const byte_list::const_iterator& src, unsigned corr_bytes_num, unsigned db_size)
{
res.reserve(max(db_size, corr_bytes_num));
res.insert(res.end(), src, src + db_size);
res.resize(res.capacity(), 0);

auto gen_poly = Tables::reed_solomon_generative_polynomial.at(corr_bytes_num);

for (unsigned j = 0; j < db_size; j++) {
unsigned char A = res[0];
unsigned char A = res[0];
res.erase(res.begin());
res.push_back(0);

Expand All @@ -50,7 +51,7 @@ void DataBlocks::compose_EC_bytes(vector<unsigned char>& res, const vector<unsig
unsigned char B = Tables::reverse_galois_field.at(A);

for (unsigned k = 0; k < corr_bytes_num; k++) {
unsigned char C = (Tables::reed_solomon_generative_polynomial.at(corr_bytes_num).at(k) + B) % 255;
unsigned char C = (gen_poly.at(k) + B) % 255;
res[k] ^= Tables::galois_field[C];
}
}
Expand All @@ -60,20 +61,16 @@ unsigned get_db_byte_index(unsigned block_index, unsigned byte_index, const vect
return db_sizes[block_index].second + byte_index;
}

void DataBlocks::join_data_and_EC_blocks(vector<unsigned char>& res, const vector<unsigned char>& e_data, const vector<pair<unsigned, unsigned>>& db_sizes, const vector<vector<unsigned char>>& ec_codes, unsigned ec_bytes_number)
void DataBlocks::join_data_and_EC_blocks(byte_list& res, const byte_list& e_data, const vector<pair<unsigned, unsigned>>& db_sizes, const vector<byte_list>& ec_codes, unsigned ec_bytes_number)
{
if (ec_codes.size())
res.reserve(e_data.size() + ec_codes.at(0).size() * ec_codes.size());
else
res.reserve(e_data.size());
res.reserve(e_data.size() + ec_codes.at(0).size() * ec_codes.size());

for (unsigned i = 0; i < db_sizes[db_sizes.size() - 1].first; i++)
for (unsigned j = 0; j < db_sizes.size(); j++)
if (i < db_sizes[j].first)
res.push_back(e_data[get_db_byte_index(j, i, db_sizes)]);

if (ec_codes.size())
for (unsigned i = 0; i < ec_bytes_number; i++)
for (unsigned j = 0; j < ec_codes.size(); j++)
res.push_back(ec_codes[j][i]);
for (unsigned i = 0; i < ec_bytes_number; i++)
for (unsigned j = 0; j < ec_codes.size(); j++)
res.push_back(ec_codes[j][i]);
}
12 changes: 6 additions & 6 deletions QRCodeLibrary/DataBlocks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ using namespace std;
class DataBlocks
{
public:
DataBlocks(const vector<unsigned char>& e_data_, CorrectionLevel corr_lvl_, char version_) : e_data{ e_data_ }, corr_lvl{ corr_lvl_ }, version{ version_ } {};
DataBlocks(const byte_list& e_data_, CorrectionLevel corr_lvl_, char version_);

vector<unsigned char>& compose_joined_data_and_EC_blocks();
byte_list& get_joined_data_and_EC_blocks() { return data; };

static void divide_to_blocks(vector<pair<unsigned, unsigned>>& db_sizes, unsigned data_size, unsigned db_number);
static void compose_EC_bytes(vector<unsigned char>& res, const vector<unsigned char>::const_iterator& src, unsigned corr_bytes_num, unsigned db_size);
static void join_data_and_EC_blocks(vector<unsigned char>&res, const vector<unsigned char>& e_data, const vector<pair<unsigned, unsigned>>& db_sizes, const vector<vector<unsigned char>>& ec_codes, unsigned ec_bytes_number);
static void compose_EC_bytes(byte_list& res, const byte_list::const_iterator& src, unsigned corr_bytes_num, unsigned db_size);
static void join_data_and_EC_blocks(byte_list&res, const byte_list& e_data, const vector<pair<unsigned, unsigned>>& db_sizes, const vector<byte_list>& ec_codes, unsigned ec_bytes_number);

private:
const vector<unsigned char>& e_data;
const byte_list& e_data;
CorrectionLevel corr_lvl;
char version;

vector<unsigned char> data;
byte_list data;
};

17 changes: 9 additions & 8 deletions QRCodeLibrary/Encoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#include <stdexcept>

BitArray& Encoder::encode()
Encoder::Encoder(const byte_list& input_, CorrectionLevel corr_lvl_, QRCodeMethod method_, char version_): input{ input_ }, corr_lvl{ corr_lvl_ }, method{ method_ }, version{ version_ }
{
unsigned encoded_bit_num = calculate_encoded_input_size(to_U(input.size()), method);
unsigned metadata_bit_num = calculate_metadata_size(method, ((version < 0) ? 0 : version));
Expand All @@ -27,8 +27,6 @@ BitArray& Encoder::encode()
encode_input(metadata_bit_num);

pad_data(e, metadata_bit_num + encoded_bit_num);

return e;
}

char Encoder::determite_version(unsigned size, CorrectionLevel corr_lvl)
Expand Down Expand Up @@ -65,17 +63,20 @@ void Encoder::write_metadata(unsigned input_size, unsigned input_bits_amount_siz

void Encoder::encode_numeric(const string& input, BitArray& out, unsigned offset)
{
int bin;
for (unsigned i = 0; i < input.size() / 3; i++) {
int bin = stoi(input.substr(i * 3, 3));
bin = stoi(input.substr(i * 3, 3));
out.set(offset + i * 10, bin, 10);
}

if (input.size() % 3 == 2) {
int bin = stoi(input.substr(input.size() - 2, 2));
bin = stoi(input.substr(input.size() - 2, 2));
out.set(offset + to_U(input.size()) / 3 * 10, bin, 7);
}
else if (input.size() % 3 == 1)
out.set(offset + to_U(input.size()) / 3 * 10, input[input.size() - 1] - '0', 4);
else if (input.size() % 3 == 1) {
bin = input[input.size() - 1] - '0';
out.set(offset + to_U(input.size()) / 3 * 10, bin, 4);
}
}

void Encoder::encode_alphabetic(const string& input, BitArray& out, unsigned offset)
Expand Down Expand Up @@ -118,7 +119,7 @@ void Encoder::pad_data(BitArray& arr, unsigned bits_written)
arr.v[i] = ((i - encoded_bytes) % 2 == 0) ? 0b11101100 : 0b00010001;
}

BitArray Encoder::get_data() const
BitArray& Encoder::get_data()
{
if (e.size == 0) throw std::runtime_error("Data is not calculated yet");

Expand Down
6 changes: 2 additions & 4 deletions QRCodeLibrary/Encoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ using namespace std;
class Encoder
{
public:
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();
Encoder(const byte_list& input_, CorrectionLevel corr_lvl_ = CorrectionLevel::M, QRCodeMethod method_ = QRCodeMethod::Dynamic, char version_ = -1);

static char determite_version(unsigned size, CorrectionLevel corr_lvl);

Expand Down Expand Up @@ -45,7 +43,7 @@ class Encoder
static void pad_data(BitArray& arr, unsigned bits_written);

constexpr char get_version() const { return version; };
BitArray get_data() const;
BitArray& get_data();

private:
static constexpr unsigned char encode_char(char ch);
Expand Down
8 changes: 2 additions & 6 deletions QRCodeLibrary/QRCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,15 @@ QRCode::QRCode(const byte_list& input_, CorrectionLevel corr_lvl_, QRCodeMethod
else
method = QRCodeMethod::Byte;
}

Encoder encoder(input, corr_lvl, method, version);
const BitArray& encoded_data = encoder.encode();
const BitArray& encoded_data = encoder.get_data();
version = encoder.get_version();

DataBlocks data_blocks(encoded_data.v, corr_lvl, version);
const BitArray final_message(data_blocks.compose_joined_data_and_EC_blocks());
const BitArray final_message(data_blocks.get_joined_data_and_EC_blocks());

matrix.set_version(version);

matrix.draw_patterns();

matrix.place_metadata(corr_lvl, mask_n);

matrix.place_data(final_message, mask_n);
}
Loading

0 comments on commit 1ceffb7

Please sign in to comment.