Browse Source

feat: try rust style

master
Dnomd343 2 years ago
parent
commit
321460c445
  1. 125
      src/common_code/common_code.cc
  2. 21
      src/common_code/common_code.h
  3. 19
      src/main.cc

125
src/common_code/common_code.cc

@ -8,22 +8,89 @@ inline uint8_t last_zero_num(uint32_t bin) { // get last zero number
return __builtin_popcount(bin >> 1);
}
std::string CommonCode::to_string(uint64_t common_code, bool shorten) {
if (!CommonCode::check(common_code)) {
throw std::invalid_argument("invalid common code");
//std::string CommonCode::to_string_(uint64_t common_code, bool shorten) {
// if (!CommonCode::check(common_code)) {
// throw std::invalid_argument("invalid common code");
// }
// char result[10]; // max length 9-bits
// sprintf(result, "%09lX", common_code);
// if (shorten) { // remove `0` after common code
// if (common_code == 0x000000000) {
// return "0"; // special case
// }
// result[9 - last_zero_num(common_code) / 4] = '\0'; // truncate string
// }
// return result;
//}
//uint64_t CommonCode::from_string_(const std::string &common_code) {
// if (common_code.length() > 9 || common_code.length() == 0) {
// throw std::invalid_argument("common code format error");
// }
// 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");
// }
// }
// // TODO: should we ensure that common code is valid?
// return result << (9 - common_code.length()) * 4; // low-bits fill with zero
//}
bool CommonCode::check(uint64_t common_code) { // check whether common code is valid
uint32_t head = common_code >> 32;
if (head >= 16 || (head & 0b11) == 0b11) { // check 2x2 block address
return false; // invalid common code
}
uint32_t fill_num = 0, space_num = 0;
auto range = Common::range_reverse((uint32_t)common_code); // get common code range
for (int i = 0; i < 32; i += 2) { // traverse range
switch ((range >> i) & 0b11) {
case 0b00: // space block
++space_num;
case 0b11: // 1x1 block
++fill_num;
break;
case 0b01: // 1x2 block
case 0b10: // 2x1 block
fill_num += 2;
}
if (fill_num >= 16) { // all block filled
break;
}
}
if (space_num < 2) {
return false; // at least 2 space
}
return Common::check_case(head, range); // check by head and range
}
std::string CommonCode::to_string(bool shorten) const {
char result[10]; // max length 9-bits
sprintf(result, "%09lX", common_code);
sprintf(result, "%09lX", code);
if (shorten) { // remove `0` after common code
if (common_code == 0x000000000) {
if (code == 0x000000000) {
return "0"; // special case
}
result[9 - last_zero_num(common_code) / 4] = '\0'; // truncate string
result[9 - last_zero_num(code) / 4] = '\0'; // truncate string
}
return result;
// return CommonCode::to_string_(code, shorten);
}
uint64_t CommonCode::from_string(const std::string &common_code) {
CommonCode CommonCode::from_string(const std::string &common_code) {
if (common_code.length() > 9 || common_code.length() == 0) {
throw std::invalid_argument("common code format error");
}
@ -40,35 +107,27 @@ uint64_t CommonCode::from_string(const std::string &common_code) {
throw std::invalid_argument("common code format error");
}
}
return CommonCode(result << (9 - common_code.length()) * 4); // low-bits fill with zero
// TODO: should we ensure that common code is valid?
return result << (9 - common_code.length()) * 4; // low-bits fill with zero
// return result << (9 - common_code.length()) * 4; // low-bits fill with zero
// return CommonCode(CommonCode::from_string_(common_code));
}
bool CommonCode::check(uint64_t common_code) { // check whether common code is valid
uint32_t head = common_code >> 32;
if (head >= 16 || (head & 0b11) == 0b11) { // check 2x2 block address
return false; // invalid common code
}
CommonCode::CommonCode(uint64_t common_code) {
uint32_t fill_num = 0, space_num = 0;
auto range = Common::range_reverse((uint32_t)common_code); // get common code range
for (int i = 0; i < 32; i += 2) { // traverse range
switch ((range >> i) & 0b11) {
case 0b00: // space block
++space_num;
case 0b11: // 1x1 block
++fill_num;
break;
case 0b01: // 1x2 block
case 0b10: // 2x1 block
fill_num += 2;
}
if (fill_num >= 16) { // all block filled
break;
}
}
if (space_num < 2) {
return false; // at least 2 space
if (!CommonCode::check(common_code)) {
throw std::invalid_argument("invalid common code");
}
return Common::check_case(head, range); // check by head and range
code = common_code;
}
uint64_t CommonCode::unwrap() const {
return code;
}

21
src/common_code/common_code.h

@ -5,7 +5,24 @@
class CommonCode {
public:
explicit CommonCode(uint64_t common_code);
uint64_t unwrap() const;
std::string to_string(bool shorten = false) const;
static CommonCode from_string(const std::string &common_code);
private:
uint64_t code;
static bool check(uint64_t common_code);
static uint64_t from_string(const std::string &common_code);
static std::string to_string(uint64_t common_code, bool shorten = false);
// static uint64_t from_string(const std::string &common_code);
// static std::string to_string(uint64_t common_code, bool shorten = false);
};

19
src/main.cc

@ -45,13 +45,20 @@ int main() {
// std::cout << AllCases::get_basic_ranges() << std::endl;
std::cout << CommonCode::check(0x123456789) << std::endl;
std::cout << CommonCode::check(0x4FEA13400) << std::endl;
// std::cout << CommonCode::check(0x123456789) << std::endl;
// std::cout << CommonCode::check(0x4FEA13400) << std::endl;
//
// // TODO: should we return a CommonCode object like String::new(...) in rust?
// printf("%09lX\n", CommonCode::from_string("1A9bF0c0"));
// std::cout << CommonCode::to_string(0x1A9BF0C00) << std::endl;
// std::cout << CommonCode::to_string(0x1A9BF0C00, true) << std::endl;
auto c = CommonCode::from_string("1A9bF0c0");
std::cout << c.to_string(true) << std::endl;
std::cout << c.to_string() << std::endl;
printf("%09lX\n", c.unwrap());
// TODO: should we return a CommonCode object like String::new(...) in rust?
printf("%09lX\n", CommonCode::from_string("1A9bF0c0"));
std::cout << CommonCode::to_string(0x1A9BF0C00) << std::endl;
std::cout << CommonCode::to_string(0x1A9BF0C00, true) << std::endl;
std::cout << CommonCode(0x1A9BF0C00).to_string() << std::endl;
return 0;
}

Loading…
Cancel
Save