Browse Source

refactor: project structure of short code

legacy
Dnomd343 8 months ago
parent
commit
24961cc32c
  1. 6
      src/core/CMakeLists.txt
  2. 56
      src/core/short_code/inline_impl.h
  3. 22
      src/core/short_code/internal/convert.cc
  4. 12
      src/core/short_code/internal/offset/basic.h
  5. 10
      src/core/short_code/internal/offset/range_prefix.h
  6. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x0.inc
  7. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x1.inc
  8. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x2.inc
  9. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x4.inc
  10. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x5.inc
  11. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x6.inc
  12. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x8.inc
  13. 0
      src/core/short_code/internal/offset/range_prefix/offset_0x9.inc
  14. 0
      src/core/short_code/internal/offset/range_prefix/offset_0xA.inc
  15. 0
      src/core/short_code/internal/offset/range_prefix/offset_0xC.inc
  16. 0
      src/core/short_code/internal/offset/range_prefix/offset_0xD.inc
  17. 0
      src/core/short_code/internal/offset/range_prefix/offset_0xE.inc
  18. 26
      src/core/short_code/internal/serialize.cc
  19. 11
      src/core/short_code/internal/serialize_chars.h
  20. 120
      src/core/short_code/internal/short_code.inl
  21. 24
      src/core/short_code/short_code.cc
  22. 121
      src/core/short_code/short_code.h
  23. 71
      src/core/short_code/sundry.cc

6
src/core/CMakeLists.txt

@ -16,10 +16,8 @@ set(KLOTSKI_CORE_SRC
raw_code/internal/sundry.cc raw_code/internal/sundry.cc
raw_code/internal/mirror.cc raw_code/internal/mirror.cc
short_code/convert.cc short_code/internal/convert.cc
short_code/serialize.cc short_code/internal/serialize.cc
short_code/short_code.cc
short_code/sundry.cc
) )
add_library(klotski_core STATIC ${KLOTSKI_CORE_SRC}) add_library(klotski_core STATIC ${KLOTSKI_CORE_SRC})

56
src/core/short_code/inline_impl.h

@ -1,56 +0,0 @@
#pragma once
namespace klotski {
namespace codec {
/// Get the original 32-bit code.
inline uint32_t ShortCode::unwrap() const noexcept {
return code_;
}
/// Implicit conversion to 32-bit code.
inline ShortCode::operator uint32_t() const noexcept {
return code_;
}
/// Equality comparison between ShortCode and numbers.
inline bool operator==(ShortCode s1, uint32_t s2) noexcept {
return s1.unwrap() == s2;
}
/// ShortCode equal comparison implement.
inline bool operator==(ShortCode s1, ShortCode s2) noexcept {
return s1.unwrap() == s2.unwrap();
}
/// ShortCode less than comparison implement.
inline bool operator<(ShortCode s1, ShortCode s2) noexcept {
return s1.unwrap() < s2.unwrap();
}
/// ShortCode greater than comparison implement.
inline bool operator>(ShortCode s1, ShortCode s2) noexcept {
return s1.unwrap() > s2.unwrap();
}
/// ShortCode create without any check.
inline ShortCode ShortCode::unsafe_create(uint32_t short_code) noexcept {
return *reinterpret_cast<ShortCode*>(&short_code); // init directly
}
/// ShortCode create with valid check.
inline std::optional<ShortCode> ShortCode::create(uint32_t short_code) noexcept {
if (!ShortCode::check(short_code)) {
return std::nullopt; // invalid short code
}
return ShortCode::unsafe_create(short_code);
}
/// Output string encoding of ShortCode.
inline std::ostream& operator<<(std::ostream &out, ShortCode self) {
out << ShortCode::string_encode(self.code_);
return out;
}
} // namespace codec
} // namespace klotski

22
src/core/short_code/convert.cc → src/core/short_code/internal/convert.cc

@ -1,18 +1,17 @@
#include <algorithm> #include <algorithm>
#include "short_code.h"
#include "offset/basic.h" #include "offset/basic.h"
#include "offset/range_prefix.h" #include "offset/range_prefix.h"
#include "short_code/short_code.h"
using klotski::cases::AllCases; using klotski::cases::AllCases;
using klotski::codec::ShortCode;
using klotski::cases::BasicRanges; using klotski::cases::BasicRanges;
using klotski::codec::offset::ALL_CASES_OFFSET; using klotski::codec::offset::ALL_CASES_OFFSET;
using klotski::codec::offset::BASIC_RANGES_OFFSET; using klotski::codec::offset::BASIC_RANGES_OFFSET;
using klotski::codec::offset::RANGE_PREFIX_OFFSET; using klotski::codec::offset::RANGE_PREFIX_OFFSET;
namespace klotski {
namespace codec {
/// FIXME: temporarily used to implement tidy conversion /// FIXME: temporarily used to implement tidy conversion
static uint32_t check_range(uint32_t head, uint32_t range) noexcept { static uint32_t check_range(uint32_t head, uint32_t range) noexcept {
/// M_1x1 | M_1x2 | M_2x1 | M_2x2 /// M_1x1 | M_1x2 | M_2x1 | M_2x2
@ -52,23 +51,20 @@ static uint32_t check_range(uint32_t head, uint32_t range) noexcept {
return 0; // pass check return 0; // pass check
} }
/// Convert CommonCode to ShortCode based on AllCases data. uint32_t ShortCode::fast_encode(uint64_t common_code) {
uint32_t ShortCode::fast_encode(uint64_t common_code) noexcept {
auto head = common_code >> 32; auto head = common_code >> 32;
auto &ranges = AllCases::instance().fetch()[head]; // match available ranges auto &ranges = AllCases::instance().fetch()[head]; // match available ranges
auto target = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code); auto target = std::lower_bound(ranges.begin(), ranges.end(), (uint32_t)common_code);
return ALL_CASES_OFFSET[head] + (target - ranges.begin()); return ALL_CASES_OFFSET[head] + (target - ranges.begin());
} }
/// Convert ShortCode to CommonCode based on AllCases data. uint64_t ShortCode::fast_decode(uint32_t short_code) {
uint64_t ShortCode::fast_decode(uint32_t short_code) noexcept {
auto offset = std::upper_bound(ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code) - 1; auto offset = std::upper_bound(ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code) - 1;
uint64_t head = offset - ALL_CASES_OFFSET; uint64_t head = offset - ALL_CASES_OFFSET;
return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset]; return (head << 32) | AllCases::instance().fetch()[head][short_code - *offset];
} }
/// Convert CommonCode to ShortCode based on BasicRanges data. uint32_t ShortCode::tiny_encode(uint64_t common_code) {
uint32_t ShortCode::tiny_encode(uint64_t common_code) noexcept {
uint32_t head = common_code >> 32; uint32_t head = common_code >> 32;
uint32_t prefix = (common_code >> 20) & 0xFFF; uint32_t prefix = (common_code >> 20) & 0xFFF;
@ -93,8 +89,7 @@ uint32_t ShortCode::tiny_encode(uint64_t common_code) noexcept {
return ALL_CASES_OFFSET[head] + RANGE_PREFIX_OFFSET[head][prefix] + offset; return ALL_CASES_OFFSET[head] + RANGE_PREFIX_OFFSET[head][prefix] + offset;
} }
/// NOTE: ensure that input short code is valid! uint64_t ShortCode::tiny_decode(uint32_t short_code) { // short code --> common code
uint64_t ShortCode::tiny_decode(uint32_t short_code) noexcept { // short code --> common code
auto offset = std::upper_bound(ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code) - 1; auto offset = std::upper_bound(ALL_CASES_OFFSET, ALL_CASES_OFFSET + 16, short_code) - 1;
auto head = offset - ALL_CASES_OFFSET; // head index auto head = offset - ALL_CASES_OFFSET; // head index
short_code -= *offset; short_code -= *offset;
@ -118,6 +113,3 @@ uint64_t ShortCode::tiny_decode(uint32_t short_code) noexcept { // short code --
} }
return (uint64_t)head << 32 | range_reverse(basic_ranges[index]); return (uint64_t)head << 32 | range_reverse(basic_ranges[index]);
} }
} // namespace codec
} // namespace klotski

12
src/core/short_code/offset/basic.h → src/core/short_code/internal/offset/basic.h

@ -2,16 +2,14 @@
#include <cstdint> #include <cstdint>
namespace klotski { namespace klotski::codec::offset {
namespace codec {
namespace offset {
/// This is the head index, the offset [0, 29334498) in all cases is obtained /// This is the head index, the offset [0, 29334498) in all cases is obtained
/// according to the `head` (0 ~ 15). In other words, the short code range can /// according to the `head` (0 ~ 15). In other words, the short code range can
/// be obtained according to the position of the 2x2 block. /// be obtained according to the position of the 2x2 block.
// TODO: using std::array // TODO: using std::array
const uint32_t ALL_CASES_OFFSET[16] = { constexpr uint32_t ALL_CASES_OFFSET[16] {
0, 2942906, 5203298, 8146204, 0, 2942906, 5203298, 8146204,
8146204, 10468254, 12345199, 14667249, 8146204, 10468254, 12345199, 14667249,
14667249, 16989299, 18866244, 21188294, 14667249, 16989299, 18866244, 21188294,
@ -23,7 +21,7 @@ const uint32_t ALL_CASES_OFFSET[16] = {
/// 32-bit `range`. /// 32-bit `range`.
// TODO: using std::array // TODO: using std::array
const uint32_t BASIC_RANGES_OFFSET[4096] = { constexpr uint32_t BASIC_RANGES_OFFSET[4096] {
0, 18272, 24960, 31648, 49920, 56608, 59056, 61504, 0, 18272, 24960, 31648, 49920, 56608, 59056, 61504,
68192, 74880, 77328, 79776, 86464, 104736, 111424, 118112, 68192, 74880, 77328, 79776, 86464, 104736, 111424, 118112,
136384, 143072, 145520, 147968, 154656, 157104, 158000, 158896, 136384, 143072, 145520, 147968, 154656, 157104, 158000, 158896,
@ -538,6 +536,4 @@ const uint32_t BASIC_RANGES_OFFSET[4096] = {
7253514, 7259861, 7261646, 7263431, 7268677, 7286266, 7291512, 7296758, 7253514, 7259861, 7261646, 7263431, 7268677, 7286266, 7291512, 7296758,
}; };
} // namespace offset } // namespace klotski::codec::offset
} // namespace codec
} // namespace klotski

10
src/core/short_code/offset/range_prefix.h → src/core/short_code/internal/offset/range_prefix.h

@ -7,12 +7,10 @@
#include <cstdint> #include <cstdint>
namespace klotski { namespace klotski::codec::offset {
namespace codec {
namespace offset {
// TODO: using std::array // TODO: using std::array
const uint32_t RANGE_PREFIX_OFFSET[16][4096] = {{ constexpr uint32_t RANGE_PREFIX_OFFSET[16][4096] = {{
#include "range_prefix/offset_0x0.inc" #include "range_prefix/offset_0x0.inc"
}, { }, {
#include "range_prefix/offset_0x1.inc" #include "range_prefix/offset_0x1.inc"
@ -46,6 +44,4 @@ const uint32_t RANGE_PREFIX_OFFSET[16][4096] = {{
/// --------------- 0xF --------------- /// --------------- 0xF ---------------
}}; }};
} // namespace offset } // namespace klotski::codec::offset
} // namespace codec
} // namespace klotski

0
src/core/short_code/offset/range_prefix/offset_0x0.inc → src/core/short_code/internal/offset/range_prefix/offset_0x0.inc

0
src/core/short_code/offset/range_prefix/offset_0x1.inc → src/core/short_code/internal/offset/range_prefix/offset_0x1.inc

0
src/core/short_code/offset/range_prefix/offset_0x2.inc → src/core/short_code/internal/offset/range_prefix/offset_0x2.inc

0
src/core/short_code/offset/range_prefix/offset_0x4.inc → src/core/short_code/internal/offset/range_prefix/offset_0x4.inc

0
src/core/short_code/offset/range_prefix/offset_0x5.inc → src/core/short_code/internal/offset/range_prefix/offset_0x5.inc

0
src/core/short_code/offset/range_prefix/offset_0x6.inc → src/core/short_code/internal/offset/range_prefix/offset_0x6.inc

0
src/core/short_code/offset/range_prefix/offset_0x8.inc → src/core/short_code/internal/offset/range_prefix/offset_0x8.inc

0
src/core/short_code/offset/range_prefix/offset_0x9.inc → src/core/short_code/internal/offset/range_prefix/offset_0x9.inc

0
src/core/short_code/offset/range_prefix/offset_0xA.inc → src/core/short_code/internal/offset/range_prefix/offset_0xA.inc

0
src/core/short_code/offset/range_prefix/offset_0xC.inc → src/core/short_code/internal/offset/range_prefix/offset_0xC.inc

0
src/core/short_code/offset/range_prefix/offset_0xD.inc → src/core/short_code/internal/offset/range_prefix/offset_0xD.inc

0
src/core/short_code/offset/range_prefix/offset_0xE.inc → src/core/short_code/internal/offset/range_prefix/offset_0xE.inc

26
src/core/short_code/serialize.cc → src/core/short_code/internal/serialize.cc

@ -1,26 +1,25 @@
#include "short_code.h"
#include "serialize_chars.h" #include "serialize_chars.h"
#include "short_code/short_code.h"
namespace klotski { using klotski::codec::ShortCode;
namespace codec {
std::string ShortCode::string_encode(uint32_t short_code) noexcept { // encode as 5-bits string std::string ShortCode::string_encode(uint32_t short_code) {
char result[6]; // short code length 5 char result[6];
result[5] = '\0'; // string ending flag result[5] = '\0'; // string ending flag
for (int n = 0; n < 5; ++n) { for (int n = 0; n < 5; ++n) {
result[4 - n] = SHORT_CODE_TABLE[short_code & 0b11111]; // aka _ % 32 result[4 - n] = SHORT_CODE_TABLE[short_code & 0b11111];
short_code >>= 5; // aka _ / 32 short_code >>= 5;
} }
return result; return result;
} }
std::optional<uint32_t> ShortCode::string_decode(const std::string &short_code) noexcept { // 5-bits string decode std::optional<uint32_t> ShortCode::string_decode(const std::string &short_code) {
if (short_code.length() != 5) { // check string length if (short_code.length() != 5) {
return std::nullopt; return std::nullopt; // invalid string length
} }
uint64_t result = 0; uint64_t result = 0;
for (auto bit : short_code) { for (auto bit : short_code) {
result <<= 5; // aka _ * 32 result <<= 5;
if (bit >= 'a' && bit <= 'z') { if (bit >= 'a' && bit <= 'z') {
bit -= 32; // convert to uppercase bit -= 32; // convert to uppercase
} }
@ -32,11 +31,8 @@ std::optional<uint32_t> ShortCode::string_decode(const std::string &short_code)
return std::nullopt; return std::nullopt;
} }
} }
if (!ShortCode::check(result)) { // check converted short code if (!check(result)) { // check converted short code
return std::nullopt; return std::nullopt;
} }
return result; // apply convert result return result; // apply convert result
} }
} // namespace codec
} // namespace klotski

11
src/core/short_code/serialize_chars.h → src/core/short_code/internal/serialize_chars.h

@ -17,10 +17,9 @@
#include <cstdint> #include <cstdint>
namespace klotski { namespace klotski::codec {
namespace codec {
const int8_t SHORT_CODE_TABLE[32] = { constexpr int8_t SHORT_CODE_TABLE[32] {
'1', '2', '3', '4', '5', '6', '7', '8', '9', // skip `0` '1', '2', '3', '4', '5', '6', '7', '8', '9', // skip `0`
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // skip `I` 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // skip `I`
'J', 'K', // skip `L` 'J', 'K', // skip `L`
@ -28,8 +27,7 @@ const int8_t SHORT_CODE_TABLE[32] = {
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
}; };
/// `1`(49) ~ `Z`(90) constexpr int8_t SHORT_CODE_TABLE_REV[42] {
const int8_t SHORT_CODE_TABLE_REV[42] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, // `1`(49) ~ `9`(57) 0, 1, 2, 3, 4, 5, 6, 7, 8, // `1`(49) ~ `9`(57)
-1, -1, -1, -1, -1, -1, -1, // `:`(58) ~ `@`(64) -1, -1, -1, -1, -1, -1, -1, // `:`(58) ~ `@`(64)
9, 10, 11, 12, 13, 14, 15, 16, -1, 17, // `A`(65) ~ `J`(74) 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, // `A`(65) ~ `J`(74)
@ -37,5 +35,4 @@ const int8_t SHORT_CODE_TABLE_REV[42] = {
26, 27, 28, 29, 30, 31, // `U`(85) ~ `Z`(90) 26, 27, 28, 29, 30, 31, // `U`(85) ~ `Z`(90)
}; };
} // namespace codec } // namespace klotski::codec
} // namespace klotski

120
src/core/short_code/internal/short_code.inl

@ -0,0 +1,120 @@
#pragma once
#include <bit>
#include "common_code/common_code.h"
namespace klotski::codec {
// ------------------------------------------------------------------------------------- //
inline ShortCode::ShortCode(const CommonCode common_code) {
// TODO: test the affect of CPU branch prediction.
if (cases::AllCases::instance().is_available()) {
code_ = fast_encode(common_code.unwrap());
} else {
code_ = tiny_encode(common_code.unwrap());
}
}
inline ShortCode ShortCode::unsafe_create(const uint32_t short_code) {
return std::bit_cast<ShortCode>(short_code); // init directly
}
inline std::optional<ShortCode> ShortCode::create(const uint32_t short_code) {
if (!check(short_code)) {
return std::nullopt; // invalid short code
}
return unsafe_create(short_code);
}
// ------------------------------------------------------------------------------------- //
inline ShortCode::operator uint32_t() const {
return code_;
}
inline bool ShortCode::check(const uint32_t short_code) {
return short_code < SHORT_CODE_LIMIT; // [0, SHORT_CODE_LIMIT)
}
inline void ShortCode::speed_up(const bool fast_mode) {
if (fast_mode) {
cases::AllCases::instance().build();
} else {
cases::BasicRanges::instance().build();
}
}
#ifndef KLSK_NDEBUG
inline std::ostream& operator<<(std::ostream &out, const ShortCode self) {
out << ShortCode::string_encode(self.code_);
return out;
}
#endif
// ----------------------------------------------------------------------------------------- //
inline uint32_t ShortCode::unwrap() const {
return code_;
}
inline std::string ShortCode::to_string() const {
return string_encode(code_);
}
inline CommonCode ShortCode::to_common_code() const {
// TODO: test the affect of CPU branch prediction.
if (cases::AllCases::instance().is_available()) {
return CommonCode::unsafe_create(fast_decode(code_));
}
return CommonCode::unsafe_create(tiny_decode(code_));
}
// ----------------------------------------------------------------------------------------- //
inline std::optional<ShortCode> ShortCode::from_string(const std::string &short_code) {
return string_decode(short_code).transform(unsafe_create);
}
// ----------------------------------------------------------------------------------------- //
inline ShortCode ShortCode::from_common_code(const CommonCode common_code) {
return common_code.to_short_code();
}
inline std::optional<ShortCode> ShortCode::from_common_code(const uint64_t common_code) {
const auto convert = [](const CommonCode code) {
return code.to_short_code();
};
return CommonCode::create(common_code).transform(convert);
}
inline std::optional<ShortCode> ShortCode::from_common_code(const std::string &common_code) {
const auto convert = [](const CommonCode code) {
return code.to_short_code();
};
return CommonCode::from_string(common_code).transform(convert);
}
// ------------------------------------------------------------------------------------- //
constexpr auto operator==(const ShortCode &lhs, const uint32_t rhs) {
return lhs.code_ == rhs;
}
constexpr auto operator<=>(const ShortCode &lhs, const uint32_t rhs) {
return lhs.code_ <=> rhs;
}
constexpr auto operator==(const ShortCode &lhs, const ShortCode &rhs) {
return lhs.code_ == rhs.code_;
}
constexpr auto operator<=>(const ShortCode &lhs, const ShortCode &rhs) {
return lhs.code_ <=> rhs.code_;
}
// ----------------------------------------------------------------------------------------- //
} // namespace klotski::codec

24
src/core/short_code/short_code.cc

@ -1,24 +0,0 @@
#include "all_cases.h"
#include "short_code.h"
using klotski::cases::AllCases;
using klotski::cases::BasicRanges;
namespace klotski {
namespace codec {
/// Check the validity of the original ShortCode.
bool ShortCode::check(uint32_t short_code) noexcept {
return short_code < SHORT_CODE_LIMIT; // 0 ~ (SHORT_CODE_LIMIT - 1)
}
void ShortCode::speed_up(bool fast_mode) noexcept {
if (fast_mode) {
AllCases::instance().build();
} else {
BasicRanges::instance().build();
}
}
} // namespace codec
} // namespace klotski

121
src/core/short_code/short_code.h

@ -1,4 +1,4 @@
#pragma once /// Klotski Engine by Dnomd343 @2024
/// ShortCode is a high-compression encoding scheme based on CommonCode. Since /// ShortCode is a high-compression encoding scheme based on CommonCode. Since
/// there are a total of 29334498 valid klotski cases, arrange then from small /// there are a total of 29334498 valid klotski cases, arrange then from small
@ -66,58 +66,119 @@
/// => "AXCZN" /// /// => "AXCZN" ///
/// -------------------------------------------------------------------------------------------- /// /// -------------------------------------------------------------------------------------------- ///
#pragma once
#include <string> #include <string>
#include <cstdint> #include <cstdint>
#include <ostream> #include <ostream>
#include <optional> #include <optional>
#include "all_cases.h"
namespace klotski { #include "all_cases/all_cases.h"
namespace codec {
namespace klotski::codec {
constexpr uint32_t SHORT_CODE_LIMIT = cases::ALL_CASES_NUM_; constexpr uint32_t SHORT_CODE_LIMIT = cases::ALL_CASES_NUM_;
class CommonCode; class CommonCode;
class ShortCode { class ShortCode {
public: public:
explicit operator uint32_t() const noexcept; // ------------------------------------------------------------------------------------- //
static bool check(uint32_t short_code) noexcept;
static void speed_up(bool fast_mode = false) noexcept; ShortCode() = delete;
/// Construct ShortCode from CommonCode.
explicit ShortCode(CommonCode common_code);
/// Create ShortCode without any check.
static ShortCode unsafe_create(uint32_t short_code);
/// Create ShortCode with validity check.
static std::optional<ShortCode> create(uint32_t short_code);
// ------------------------------------------------------------------------------------- //
/// Explicit conversion to u32 code.
explicit operator uint32_t() const;
/// Check the validity of the original ShortCode.
static bool check(uint32_t short_code);
/// Build the conversion index for ShortCode.
static void speed_up(bool fast_mode = false);
#ifndef KLSK_NDEBUG
/// Output string encoding of ShortCode only for debug.
friend std::ostream& operator<<(std::ostream &out, ShortCode self); friend std::ostream& operator<<(std::ostream &out, ShortCode self);
#endif
[[nodiscard]] uint32_t unwrap() const noexcept; // ------------------------------------------------------------------------------------- //
[[nodiscard]] std::string to_string() const noexcept;
[[nodiscard]] CommonCode to_common_code() const noexcept;
public: /// Get the original u32 code.
ShortCode() = delete; [[nodiscard]] uint32_t unwrap() const;
explicit ShortCode(CommonCode common_code) noexcept;
/// Convert ShortCode to string form.
[[nodiscard]] std::string to_string() const;
/// Convert ShortCode to CommonCode.
[[nodiscard]] CommonCode to_common_code() const;
// ------------------------------------------------------------------------------------- //
/// Create ShortCode from string form.
static std::optional<ShortCode> from_string(const std::string &short_code);
// ------------------------------------------------------------------------------------- //
/// Create ShortCode from CommonCode.
static ShortCode from_common_code(CommonCode common_code);
/// Create ShortCode from CommonCode in u64.
static std::optional<ShortCode> from_common_code(uint64_t common_code);
static ShortCode unsafe_create(uint32_t short_code) noexcept; /// Create ShortCode from CommonCode in string form.
static std::optional<ShortCode> create(uint32_t short_code) noexcept; static std::optional<ShortCode> from_common_code(const std::string &common_code);
static std::optional<ShortCode> from_string(std::string &&short_code) noexcept; // ------------------------------------------------------------------------------------- //
static std::optional<ShortCode> from_string(const std::string &short_code) noexcept;
static ShortCode from_common_code(CommonCode common_code) noexcept; /// Compare ShortCode with u32 value.
static std::optional<ShortCode> from_common_code(uint64_t common_code) noexcept; friend constexpr auto operator==(const ShortCode &lhs, uint32_t rhs);
static std::optional<ShortCode> from_common_code(std::string &&common_code) noexcept; friend constexpr auto operator<=>(const ShortCode &lhs, uint32_t rhs);
static std::optional<ShortCode> from_common_code(const std::string &common_code) noexcept;
/// Compare the original values of two ShortCodes.
friend constexpr auto operator==(const ShortCode &lhs, const ShortCode &rhs);
friend constexpr auto operator<=>(const ShortCode &lhs, const ShortCode &rhs);
// ------------------------------------------------------------------------------------- //
private: private:
uint32_t code_; uint32_t code_;
static uint64_t fast_decode(uint32_t short_code) noexcept; // ------------------------------------------------------------------------------------- //
static uint32_t fast_encode(uint64_t common_code) noexcept;
/// Convert ShortCode to CommonCode based on AllCases data.
static uint64_t fast_decode(uint32_t short_code);
/// Convert CommonCode to ShortCode based on AllCases data.
static uint32_t fast_encode(uint64_t common_code);
/// Convert ShortCode to CommonCode based on BasicRanges data.
static uint64_t tiny_decode(uint32_t short_code);
/// Convert CommonCode to ShortCode based on BasicRanges data.
static uint32_t tiny_encode(uint64_t common_code);
// ------------------------------------------------------------------------------------- //
/// Serialize ShortCode into 5-bit length string.
static std::string string_encode(uint32_t short_code);
static uint64_t tiny_decode(uint32_t short_code) noexcept; /// Deserialize ShortCode from string and return nullopt on error.
static uint32_t tiny_encode(uint64_t common_code) noexcept; static std::optional<uint32_t> string_decode(const std::string &short_code);
static std::string string_encode(uint32_t short_code) noexcept; // ------------------------------------------------------------------------------------- //
static std::optional<uint32_t> string_decode(const std::string &short_code) noexcept;
}; };
} // namespace codec } // namespace klotski::codec
} // namespace klotski
#include "inline_impl.h" #include "internal/short_code.inl"

71
src/core/short_code/sundry.cc

@ -1,71 +0,0 @@
#include "short_code.h"
#include "common_code.h"
using klotski::cases::AllCases;
namespace klotski {
namespace codec {
// ----------------------------------------------------------------------------------------- //
ShortCode::ShortCode(CommonCode common_code) noexcept {
if (AllCases::instance().is_available()) {
code_ = fast_encode(common_code.unwrap());
} else {
code_ = tiny_encode(common_code.unwrap());
}
}
// ----------------------------------------------------------------------------------------- //
std::string ShortCode::to_string() const noexcept {
return string_encode(code_);
}
CommonCode ShortCode::to_common_code() const noexcept {
if (AllCases::instance().is_available()) {
return CommonCode::unsafe_create(fast_decode(code_));
}
return CommonCode::unsafe_create(tiny_decode(code_));
}
// ----------------------------------------------------------------------------------------- //
std::optional<ShortCode> ShortCode::from_string(std::string &&short_code) noexcept {
return ShortCode::from_string(short_code);
}
std::optional<ShortCode> ShortCode::from_string(const std::string &short_code) noexcept {
return ShortCode::string_decode(short_code).transform([](auto code) {
return ShortCode::unsafe_create(code);
});
}
// ----------------------------------------------------------------------------------------- //
ShortCode ShortCode::from_common_code(CommonCode common_code) noexcept {
return common_code.to_short_code();
}
std::optional<ShortCode> ShortCode::from_common_code(uint64_t common_code) noexcept {
return CommonCode::create(common_code).transform([](auto common_code) {
return common_code.to_short_code();
});
}
std::optional<ShortCode> ShortCode::from_common_code(std::string &&common_code) noexcept {
return CommonCode::from_string(std::move(common_code)).transform([](auto common_code) {
return common_code.to_short_code();
});
}
std::optional<ShortCode> ShortCode::from_common_code(const std::string &common_code) noexcept {
return CommonCode::from_string(common_code).transform([](auto common_code) {
return common_code.to_short_code();
});
}
// ----------------------------------------------------------------------------------------- //
} // namespace codec
} // namespace klotski
Loading…
Cancel
Save