Browse Source

feat: common code serialize

master
Dnomd343 2 years ago
parent
commit
3088a092f4
  1. 2
      src/common_code/CMakeLists.txt
  2. 57
      src/common_code/common_code.cc
  3. 5
      src/common_code/common_code.h
  4. 55
      src/common_code/serialize.cc
  5. 19
      src/main.cc

2
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)

57
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

5
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

55
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;
}

19
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;

Loading…
Cancel
Save