From f2649d8a64984a15187eb7981895a61ffa7cfc03 Mon Sep 17 00:00:00 2001 From: lightyear15 Date: Tue, 11 Apr 2023 20:46:43 +0200 Subject: [PATCH 1/5] adding cmake to the project also adding a github workflow task that compiles, runs tests and installs the produced artifacts --- .github/workflows/ci.yml | 10 ++++ CMakeLists.txt | 97 +++++++++++++++++++++++++++++++++++++ cmake/bc-ur-config.cmake.in | 6 +++ src/xoshiro256.cpp | 1 + 4 files changed, 114 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 cmake/bc-ur-config.cmake.in diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec268c4..09c5754 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,3 +23,13 @@ jobs: - run: export CC="clang-10" && export CXX="clang++-10" && ./configure && make check - run: sudo make install - run: export CC="clang-10" && export CXX="clang++-10" && make distcheck && make distclean + + build-Linux-cmake: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v2 + - run: sudo apt-get install -y cmake || exit 1 + - run: cmake -B build -S . -DENABLE_TESTS:BOOL=TRUE + - run: cmake --build build + - run: ctest --test-dir build || exit 1 + - run: cmake --install build --prefix install-dir diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3056add --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,97 @@ +cmake_minimum_required(VERSION 3.15) +project(bc-ur + VERSION 0.3.0 + DESCRIPTION "UR reference library in C++" + LANGUAGES C CXX +) + +option(ENABLE_TESTS "Build bc-ur tests" FALSE) + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) + +add_library(bc-ur) + +set(public_headers + src/bc-ur.hpp + src/bytewords.hpp + src/cbor-lite.hpp + src/fountain-decoder.hpp + src/fountain-encoder.hpp + src/fountain-utils.hpp + src/random-sampler.hpp + src/ur.hpp + src/ur-decoder.hpp + src/ur-encoder.hpp + src/utils.hpp + src/xoshiro256.hpp +) +set(sources + src/bytewords.cpp + src/crc32.c + src/crc32.h + src/fountain-decoder.cpp + src/fountain-encoder.cpp + src/fountain-utils.cpp + src/Makefile.in + src/memzero.c + src/memzero.h + src/random-sampler.cpp + src/sha2.c + src/sha2.h + src/ur.cpp + src/ur-decoder.cpp + src/ur-encoder.cpp + src/utils.cpp + src/xoshiro256.cpp +) + +target_sources(bc-ur PRIVATE ${public_headers} ${sources}) +target_include_directories(bc-ur + PUBLIC + "$" + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src" +) +set_target_properties(bc-ur PROPERTIES + PUBLIC_HEADER "${public_headers}" + VERSION ${PROJECT_VERSION} +) + +if(ENABLE_TESTS) + enable_testing() + add_executable(bc-ur-test test/test.cpp test/test-utils.cpp) + target_include_directories(bc-ur-test PRIVATE test) + target_link_libraries(bc-ur-test bc-ur) + add_test(bc-ur-test ./bc-ur-test) +endif() + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) +configure_package_config_file(cmake/bc-ur-config.cmake.in bc-ur-config.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/bc-ur +) +write_basic_package_version_file( + ${CMAKE_CURRENT_BINARY_DIR}/bc-ur-config-version.cmake + COMPATIBILITY SameMajorVersion +) +install(TARGETS bc-ur + EXPORT "bc-ur-export" + ARCHIVE + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/bc-ur +) +install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/bc-ur-config.cmake + ${CMAKE_CURRENT_BINARY_DIR}/bc-ur-config-version.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/bc-ur +) +install(EXPORT "bc-ur-export" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/bc-ur + NAMESPACE ${PROJECT_NAME}:: + FILE bc-ur-targets.cmake +) + diff --git a/cmake/bc-ur-config.cmake.in b/cmake/bc-ur-config.cmake.in new file mode 100644 index 0000000..eab0b07 --- /dev/null +++ b/cmake/bc-ur-config.cmake.in @@ -0,0 +1,6 @@ +@PACKAGE_INIT@ + +set_and_check(BC-UR_LIB_DIR "@PACKAGE_LIB_INSTALL_DIR@") +include("${BCUR_LIB_DIR}/cmake/bc-urTargets.cmake") +set(bc-ur_COMPONENT_FOUND TRUE) +check_required_components(bc-ur) diff --git a/src/xoshiro256.cpp b/src/xoshiro256.cpp index 7e87833..2f40b8b 100644 --- a/src/xoshiro256.cpp +++ b/src/xoshiro256.cpp @@ -7,6 +7,7 @@ #include "xoshiro256.hpp" #include +#include /* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) From ae5fff1f2cdea1ec0bf50b1282d861a3bfd0d3a2 Mon Sep 17 00:00:00 2001 From: lightyear15 Date: Tue, 11 Apr 2023 20:50:20 +0200 Subject: [PATCH 2/5] removing const qualifier from returned types it practically does not enforce any sort of const-correctness while polluting the code. --- src/bytewords.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/bytewords.cpp b/src/bytewords.cpp index 34e9d4e..8e256c4 100644 --- a/src/bytewords.cpp +++ b/src/bytewords.cpp @@ -69,12 +69,12 @@ uint8_t decode_word(const string& word, size_t word_len) { return value; } -static const string get_word(uint8_t index) { - auto p = &bytewords[index * 4]; - return string(p, p + 4); +static string get_word(uint8_t index) { + const auto *p = &bytewords[index * 4]; + return {p, p + 4}; } -static const string get_minimal_word(uint8_t index) { +static string get_minimal_word(uint8_t index) { string word; word.reserve(2); auto p = &bytewords[index * 4]; @@ -83,7 +83,7 @@ static const string get_minimal_word(uint8_t index) { return word; } -static const string encode(const ByteVector& buf, const string& separator) { +static string encode(const ByteVector& buf, const string& separator) { auto len = buf.size(); StringVector words; words.reserve(len); @@ -94,19 +94,19 @@ static const string encode(const ByteVector& buf, const string& separator) { return join(words, separator); } -static const ByteVector add_crc(const ByteVector& buf) { +static ByteVector add_crc(const ByteVector& buf) { auto crc_buf = crc32_bytes(buf); auto result = buf; append(result, crc_buf); return result; } -static const string encode_with_separator(const ByteVector& buf, const string& separator) { +static string encode_with_separator(const ByteVector& buf, const string& separator) { auto crc_buf = add_crc(buf); return encode(crc_buf, separator); } -static const string encode_minimal(const ByteVector& buf) { +static string encode_minimal(const ByteVector& buf) { string result; auto crc_buf = add_crc(buf); auto len = crc_buf.size(); @@ -117,7 +117,7 @@ static const string encode_minimal(const ByteVector& buf) { return result; } -static const ByteVector _decode(const string& s, char separator, size_t word_len) { +static ByteVector _decode(const string& s, char separator, size_t word_len) { StringVector words; if(word_len == 4) { words = split(s, separator); From 2679a268f65e70ae6e08dd144fd4168be25092b0 Mon Sep 17 00:00:00 2001 From: lightyear15 Date: Tue, 11 Apr 2023 21:26:20 +0200 Subject: [PATCH 3/5] removing final from main classes even though syntatically correct, it does make little sense on classes that reprensent front-end APIs of this library for different reasons. On one side, as these classes have no virtual methods and no protected member variables, they and their internal machineries are already shielded against weird uses. Secondly, preventing this library's users to use these classes as base class does not put library authors under any further future obligation of not deprecating old code, or changing APIs. --- src/ur-decoder.hpp | 2 +- src/ur-encoder.hpp | 2 +- src/ur.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ur-decoder.hpp b/src/ur-decoder.hpp index 132fa77..3b7f418 100644 --- a/src/ur-decoder.hpp +++ b/src/ur-decoder.hpp @@ -18,7 +18,7 @@ namespace ur { -class URDecoder final { +class URDecoder { public: typedef std::optional > Result; diff --git a/src/ur-encoder.hpp b/src/ur-encoder.hpp index 5b2dec4..db1291c 100644 --- a/src/ur-encoder.hpp +++ b/src/ur-encoder.hpp @@ -15,7 +15,7 @@ namespace ur { -class UREncoder final { +class UREncoder { public: // Encode a single-part UR. static std::string encode(const UR& ur); diff --git a/src/ur.hpp b/src/ur.hpp index c26943c..6cf2fbf 100644 --- a/src/ur.hpp +++ b/src/ur.hpp @@ -14,7 +14,7 @@ namespace ur { -class UR final { +class UR { private: std::string type_; ByteVector cbor_; From 07e5f99e3db1e4922e3131022773b479d05c62ef Mon Sep 17 00:00:00 2001 From: lightyear15 Date: Tue, 11 Apr 2023 21:36:23 +0200 Subject: [PATCH 4/5] general improvements to code replacing C-style arrays with std::array adding const-qualified autos removing return types replacing typedefs with usings replacing NULL with nullptr --- src/bytewords.cpp | 12 +++++------- src/fountain-encoder.cpp | 2 +- src/utils.cpp | 29 +++++++++++++++-------------- src/utils.hpp | 4 ++-- src/xoshiro256.cpp | 6 +++--- src/xoshiro256.hpp | 4 ++-- 6 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/bytewords.cpp b/src/bytewords.cpp index 8e256c4..365065f 100644 --- a/src/bytewords.cpp +++ b/src/bytewords.cpp @@ -21,13 +21,13 @@ uint8_t decode_word(const string& word, size_t word_len) { throw runtime_error("Invalid Bytewords."); } - static int16_t* array = NULL; + static int16_t* array = nullptr; const size_t dim = 26; // Since the first and last letters of each Byteword are unique, // we can use them as indexes into a two-dimensional lookup table. // This table is generated lazily. - if(array == NULL) { + if(array == nullptr) { const size_t array_len = dim * dim; array = (int16_t*)malloc(array_len * sizeof(int16_t)); for(size_t i = 0; i < array_len; i++) { @@ -77,7 +77,7 @@ static string get_word(uint8_t index) { static string get_minimal_word(uint8_t index) { string word; word.reserve(2); - auto p = &bytewords[index * 4]; + const auto *p = &bytewords[index * 4]; word.push_back(*p); word.push_back(*(p + 3)); return word; @@ -148,9 +148,8 @@ string Bytewords::encode(style style, const ByteVector& bytes) { return encode_with_separator(bytes, "-"); case minimal: return encode_minimal(bytes); - default: - assert(false); } + assert(false); } ByteVector Bytewords::decode(style style, const string& string) { @@ -161,9 +160,8 @@ ByteVector Bytewords::decode(style style, const string& string) { return _decode(string, '-', 4); case minimal: return _decode(string, 0, 2); - default: - assert(false); } + assert(false); } } diff --git a/src/fountain-encoder.cpp b/src/fountain-encoder.cpp index f7f6cf9..5f08bf1 100644 --- a/src/fountain-encoder.cpp +++ b/src/fountain-encoder.cpp @@ -6,7 +6,7 @@ // #include "fountain-encoder.hpp" -#include +#include #include #include #include diff --git a/src/utils.cpp b/src/utils.cpp index 1f1c0e3..a10108c 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -14,6 +14,7 @@ extern "C" { } +#include #include #include #include @@ -24,28 +25,28 @@ using namespace std; namespace ur { ByteVector sha256(const ByteVector &buf) { - uint8_t digest[SHA256_DIGEST_LENGTH]; - sha256_Raw(&buf[0], buf.size(), digest); - return ByteVector(digest, digest + SHA256_DIGEST_LENGTH); + array digest; + sha256_Raw(buf.data(), buf.size(), digest.data()); + return {digest.begin(), digest.end()}; } ByteVector crc32_bytes(const ByteVector &buf) { - uint32_t checksum = ur_crc32n(&buf[0], buf.size()); - auto cbegin = (uint8_t*)&checksum; - auto cend = cbegin + sizeof(uint32_t); - return ByteVector(cbegin, cend); + uint32_t checksum = ur_crc32n(buf.data(), buf.size()); + auto *cbegin = (uint8_t*)&checksum; + auto *cend = cbegin + sizeof(uint32_t); + return {cbegin, cend}; } uint32_t crc32_int(const ByteVector &buf) { - return ur_crc32(&buf[0], buf.size()); + return ur_crc32(buf.data(), buf.size()); } ByteVector string_to_bytes(const string& s) { - return ByteVector(s.begin(), s.end()); + return {s.begin(), s.end()}; } string data_to_hex(const ByteVector& in) { - auto hex = "0123456789abcdef"; + const string hex = "0123456789abcdef"; string result; for(auto c: in) { result.append(1, hex[(c >> 4) & 0xF]); @@ -81,7 +82,7 @@ uint32_t bytes_to_int(const ByteVector& in) { string join(const StringVector &strings, const string &separator) { ostringstream result; bool first = true; - for(auto s: strings) { + for(const auto& s: strings) { if(!first) { result << separator; } @@ -104,7 +105,7 @@ StringVector split(const string& s, char separator) { } } - if(buf != "") { + if(!buf.empty()) { result.push_back(buf); } @@ -125,12 +126,12 @@ string take_first(const string &s, size_t count) { auto first = s.begin(); auto c = min(s.size(), count); auto last = first + c; - return string(first, last); + return {first, last}; } string drop_first(const string& s, size_t count) { if(count >= s.length()) { return ""; } - return string(s.begin() + count, s.end()); + return {s.begin() + count, s.end()}; } void xor_into(ByteVector& target, const ByteVector& source) { diff --git a/src/utils.hpp b/src/utils.hpp index 2e45e5c..fdf859d 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -17,8 +17,8 @@ namespace ur { -typedef std::vector ByteVector; -typedef std::vector StringVector; +using ByteVector = std::vector; +using StringVector = std::vector; ByteVector sha256(const ByteVector &buf); ByteVector crc32_bytes(const ByteVector &buf); diff --git a/src/xoshiro256.cpp b/src/xoshiro256.cpp index 2f40b8b..8fc471c 100644 --- a/src/xoshiro256.cpp +++ b/src/xoshiro256.cpp @@ -130,7 +130,7 @@ void Xoshiro256::jump() { uint64_t s3 = 0; for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++) for(int b = 0; b < 64; b++) { - if (JUMP[i] & UINT64_C(1) << b) { + if ((JUMP[i] & UINT64_C(1) << b) != 0u) { s0 ^= s[0]; s1 ^= s[1]; s2 ^= s[2]; @@ -151,13 +151,13 @@ void Xoshiro256::jump() { subsequences for parallel distributed computations. */ void Xoshiro256::long_jump() { - static const uint64_t LONG_JUMP[] = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 }; + static const std::array LONG_JUMP = { 0x76e15d3efefdcbbf, 0xc5004e441c522fb3, 0x77710069854ee241, 0x39109bb02acbe635 }; uint64_t s0 = 0; uint64_t s1 = 0; uint64_t s2 = 0; uint64_t s3 = 0; - for(int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++) + for(int i = 0; i < LONG_JUMP.size(); i++) for(int b = 0; b < 64; b++) { if (LONG_JUMP[i] & UINT64_C(1) << b) { s0 ^= s[0]; diff --git a/src/xoshiro256.hpp b/src/xoshiro256.hpp index 2654cbc..573a4c8 100644 --- a/src/xoshiro256.hpp +++ b/src/xoshiro256.hpp @@ -8,7 +8,7 @@ #ifndef XOSHIRO256_HPP #define XOSHIRO256_HPP -#include +#include #include #include #include "utils.hpp" @@ -34,7 +34,7 @@ class Xoshiro256 { void long_jump(); private: - uint64_t s[4]; + std::array s; void set_s(const std::array& a); void hash_then_set_s(const ByteVector& bytes); From e38c515debb9a032eb6d6d05bea9142073552b51 Mon Sep 17 00:00:00 2001 From: lightyear15 Date: Tue, 11 Apr 2023 21:40:48 +0200 Subject: [PATCH 5/5] in UR::UR constructor use std::move simply more efficient --- src/ur.cpp | 4 ++-- src/ur.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ur.cpp b/src/ur.cpp index 2227340..230d123 100644 --- a/src/ur.cpp +++ b/src/ur.cpp @@ -13,8 +13,8 @@ using namespace std; namespace ur { -UR::UR(const std::string &type, const ByteVector &cbor) - : type_(type), cbor_(cbor) +UR::UR(std::string type, ByteVector cbor) + : type_(std::move(type)), cbor_(std::move(cbor)) { if (!is_ur_type(type)) { throw invalid_type(); diff --git a/src/ur.hpp b/src/ur.hpp index 6cf2fbf..6a40f40 100644 --- a/src/ur.hpp +++ b/src/ur.hpp @@ -24,7 +24,7 @@ class UR { const std::string& type() const { return type_; } const ByteVector& cbor() const { return cbor_; } - UR(const std::string& type, const ByteVector& cbor); + UR(std::string type, ByteVector cbor); }; bool operator==(const UR& lhs, const UR& rhs);