From 3088a092f453ffbe1e1d109aad65bbea04621fa1 Mon Sep 17 00:00:00 2001 From: Dnomd343 Date: Tue, 17 Jan 2023 01:28:26 +0800 Subject: [PATCH] feat: common code serialize --- src/common_code/CMakeLists.txt | 2 +- src/common_code/common_code.cc | 57 ++-------------------------------- src/common_code/common_code.h | 5 +-- src/common_code/serialize.cc | 55 ++++++++++++++++++++++++++++++++ src/main.cc | 19 +++++++----- 5 files changed, 70 insertions(+), 68 deletions(-) create mode 100644 src/common_code/serialize.cc diff --git a/src/common_code/CMakeLists.txt b/src/common_code/CMakeLists.txt index 077dcde..702aa81 100644 --- a/src/common_code/CMakeLists.txt +++ b/src/common_code/CMakeLists.txt @@ -1,4 +1,4 @@ cmake_minimum_required(VERSION 3.0) -add_library(common_code common_code.cc) +add_library(common_code serialize.cc common_code.cc) target_link_libraries(common_code utils raw_code) diff --git a/src/common_code/common_code.cc b/src/common_code/common_code.cc index f9d84f8..f83d43b 100644 --- a/src/common_code/common_code.cc +++ b/src/common_code/common_code.cc @@ -2,21 +2,6 @@ #include "common.h" #include "common_code.h" -inline uint32_t binary_count(uint32_t bin) { // get number of non-zero bits - bin -= (bin >> 1) & 0x55555555; - bin = (bin & 0x33333333) + ((bin >> 2) & 0x33333333); - bin = ((bin >> 4) + bin) & 0x0F0F0F0F; - bin += bin >> 8; - bin += bin >> 16; - return bin & 0b111111; -} - -/// NOTE: bin should not be zero -inline uint32_t last_zero_num(uint32_t bin) { // get last zero number - bin ^= (bin - 1); - return __builtin_popcount(bin >> 1); -} - uint64_t CommonCode::unwrap() const { // get raw uint64_t code return code; } @@ -42,52 +27,14 @@ CommonCode::CommonCode(uint64_t common_code) { code = common_code; } -CommonCode::CommonCode(const RawCode &raw_code) { // init from raw code +CommonCode::CommonCode(const RawCode &raw_code) { // load from raw code code = raw_code.to_common_code().code; } -CommonCode::CommonCode(const ShortCode &short_code) { // init from short code +CommonCode::CommonCode(const ShortCode &short_code) { // load from short code code = short_code.to_common_code().code; } -CommonCode::CommonCode(const std::string &common_code_str) { - if (common_code_str.length() > 9 || common_code_str.length() == 0) { // check string length - throw std::invalid_argument("common code format error"); - } - - uint64_t common_code = 0; - for (auto const &bit : common_code_str) { - common_code <<= 4; - if (bit >= '0' && bit <= '9') { // 0 ~ 9 - common_code |= (bit - 48); - } else if (bit >= 'A' && bit <= 'Z') { // A ~ Z - common_code |= (bit - 55); - } else if (bit >= 'a' && bit <= 'z') { // a ~ z - common_code |= (bit - 87); - } else { - throw std::invalid_argument("common code format error"); // unknown characters - } - } - common_code <<= (9 - common_code_str.length()) * 4; // low-bits fill with zero - - if (!CommonCode::check(common_code)) { // check converted common code - throw std::invalid_argument("invalid common code"); - } - code = common_code; -} - -std::string CommonCode::to_string(bool shorten) const { // convert uint64_t code to string - char result[10]; // max length 9-bits - sprintf(result, "%09lX", code); - if (shorten) { // remove `0` after common code - if (code == 0x000000000) { - return "0"; // special case -> only one `0` - } - result[9 - last_zero_num(code) / 4] = '\0'; // truncate string - } - return result; // char* -> std::string -} - bool CommonCode::check(uint64_t common_code) { // whether common code is valid /// M_1x1 M_1x2 M_2x1 M_2x2 /// 1 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 diff --git a/src/common_code/common_code.h b/src/common_code/common_code.h index ebb9679..87b2881 100644 --- a/src/common_code/common_code.h +++ b/src/common_code/common_code.h @@ -21,16 +21,13 @@ public: explicit CommonCode(uint64_t common_code); explicit CommonCode(const RawCode &raw_code); explicit CommonCode(const ShortCode &short_code); - explicit CommonCode(const std::string &common_code_str); + explicit CommonCode(const std::string &common_code); // TODO: std::cout << CommonCode(...) // TODO: CommonCode::create(...) / CommonCode::from_string(...) // TODO: CommonCode::from_short_code(...) / CommonCode::from_raw_code(...) - // TODO: single check function for CommonCode - // TODO: single `.cc` file for serialize - private: uint64_t code; CommonCode() = default; // unsafe initialize diff --git a/src/common_code/serialize.cc b/src/common_code/serialize.cc new file mode 100644 index 0000000..e6a146c --- /dev/null +++ b/src/common_code/serialize.cc @@ -0,0 +1,55 @@ +#include "common_code.h" + +inline uint8_t binary_count(uint32_t bin) { // get number of non-zero bits + bin -= (bin >> 1) & 0x55555555; + bin = (bin & 0x33333333) + ((bin >> 2) & 0x33333333); + bin = ((bin >> 4) + bin) & 0x0F0F0F0F; + bin += bin >> 8; + bin += bin >> 16; + return bin & 0b111111; +} + +/// NOTE: input should not be zero +inline uint32_t last_zero_num(uint32_t bin) { // get last zero number + bin ^= (bin - 1); + return binary_count(bin >> 1); +} + +std::string CommonCode::to_string(bool shorten) const { // convert uint64_t code to string + char result[10]; // max length 9-bits + sprintf(result, "%09lX", code); + if (shorten) { // remove `0` after common code + if (code == 0x000000000) { + return "0"; // special case -> only one `0` + } + result[9 - last_zero_num(code) / 4] = '\0'; // truncate string + } + return result; // char* -> std::string +} + +CommonCode::CommonCode(const std::string &common_code) { // convert from 1 ~ 9 bits string + /// check string length + if (common_code.length() > 9 || common_code.empty()) { // check string length + throw std::invalid_argument("common code format error"); + } + /// check every characters + uint64_t result = 0; + for (auto const &bit : common_code) { + result <<= 4; + if (bit >= '0' && bit <= '9') { // 0 ~ 9 + result |= (bit - 48); + } else if (bit >= 'A' && bit <= 'Z') { // A ~ Z + result |= (bit - 55); + } else if (bit >= 'a' && bit <= 'z') { // a ~ z + result |= (bit - 87); + } else { + throw std::invalid_argument("common code format error"); // unknown characters + } + } + result <<= (9 - common_code.length()) * 4; // low-bits fill with zero + /// check whether common code is valid + if (!CommonCode::check(result)) { // check converted common code + throw std::invalid_argument("invalid common code"); + } + code = result; +} diff --git a/src/main.cc b/src/main.cc index d9dd5a9..b197170 100644 --- a/src/main.cc +++ b/src/main.cc @@ -336,26 +336,29 @@ int main() { // std::cout << sizeof(ShortCode) << std::endl; // int sum = 0; - for (uint64_t common_code = 0; common_code < 0x1000000000; ++common_code) { - if (CommonCode::check(common_code)) { - printf("%09lX\n", common_code); +// for (uint64_t common_code = 0; common_code < 0x1000000000; ++common_code) { +// if (CommonCode::check(common_code)) { +// printf("%09lX\n", common_code); // ++sum; - } +// } - if (common_code % 0x10000000 == 0) { - std::cerr << common_code / 0x10000000 << std::endl; - } +// if (common_code % 0x10000000 == 0) { +// std::cerr << common_code / 0x10000000 << std::endl; +// } // if (CommonCode::check(common_code) != CommonCode::check_demo(common_code)) { // printf("%09lX\n", common_code); // } - } +// } // std::cout << "sum = " << sum << std::endl; // std::cout << CommonCode::check_demo(0x4FEA13400) << std::endl; // std::cout << CommonCode::check_demo(0x0000011CE) << std::endl; // std::cout << CommonCode::check_demo(0x02ED67000) << std::endl; + std::cout << CommonCode("1a9bf0C0").to_string() << std::endl; + std::cout << CommonCode(0x4FEA13400).to_string() << std::endl; + // std::cerr << (clock() - start_time) * 1000 / CLOCKS_PER_SEC << "ms" << std::endl; std::cerr << (clock() - start_time) * 1000000 / CLOCKS_PER_SEC << "us" << std::endl; // std::cout << "complete benchmark" << std::endl;