diff --git a/src/core_ffi/CMakeLists.txt b/src/core_ffi/CMakeLists.txt index ba48a6c..d84dda1 100644 --- a/src/core_ffi/CMakeLists.txt +++ b/src/core_ffi/CMakeLists.txt @@ -13,13 +13,14 @@ endif() if (KLSK_PYTHON_FFI) pybind11_add_module(klotski_py py_ffi/binder.cc - py_ffi/codec/short_code.cc - py_ffi/codec/common_codec.cc - py_ffi/py_cases.cc - py_ffi/py_group_union.cc - py_ffi/py_group.cc + py_ffi/wrapper/short_code.cc + py_ffi/wrapper/common_codec.cc + py_ffi/wrapper/py_cases.cc + py_ffi/wrapper/py_group_union.cc + py_ffi/wrapper/py_group.cc ) target_include_directories(klotski_py PRIVATE py_ffi/include) + target_include_directories(klotski_py PRIVATE py_ffi) target_link_libraries(klotski_py PRIVATE klotski::core) set_target_properties(klotski_py PROPERTIES OUTPUT_NAME klotski) endif() diff --git a/src/core_ffi/py_ffi/binder.cc b/src/core_ffi/py_ffi/binder.cc index 306a776..836753b 100644 --- a/src/core_ffi/py_ffi/binder.cc +++ b/src/core_ffi/py_ffi/binder.cc @@ -3,7 +3,8 @@ #include #include "py_exps.h" -#include "py_codec.h" +#include "py_common_code.h" +#include "py_short_code.h" #include "py_cases.h" #include "py_group.h" @@ -38,10 +39,12 @@ void bind_common_code(const py::module_ &m) { .def(py::self < uint64_t()).def(py::self <= uint64_t()) .def(py::self > uint64_t()).def(py::self >= uint64_t()) - .def_property_readonly("str", &PyCommonCode::string) +// .def_property_readonly("str", &PyCommonCode::string) .def_property_readonly("value", &PyCommonCode::value) .def_property_readonly("short_code", &PyCommonCode::short_code) + .def("to_string", &PyCommonCode::string, py::arg("shorten") = false) + .def_static("check", static_cast(&PyCommonCode::check)) .def_static("check", static_cast(&PyCommonCode::check)); } diff --git a/src/core_ffi/py_ffi/include/py_cases.h b/src/core_ffi/py_ffi/include/py_cases.h index fb53bd3..2a4e7c1 100644 --- a/src/core_ffi/py_ffi/include/py_cases.h +++ b/src/core_ffi/py_ffi/include/py_cases.h @@ -8,7 +8,7 @@ #include "ranges/ranges.h" -#include "py_codec.h" +#include "py_common_code.h" namespace klotski::ffi { diff --git a/src/core_ffi/py_ffi/include/py_codec.h b/src/core_ffi/py_ffi/include/py_codec.h deleted file mode 100644 index 278087c..0000000 --- a/src/core_ffi/py_ffi/include/py_codec.h +++ /dev/null @@ -1,135 +0,0 @@ -#pragma once - -#include "short_code/short_code.h" -#include "common_code/common_code.h" - -namespace klotski::ffi { - -using codec::ShortCode; -using codec::CommonCode; - -class PyCommonCode; - -// ----------------------------------------------------------------------------------------- // - -class PyShortCode { -public: - explicit PyShortCode(uint32_t code); - explicit PyShortCode(PyCommonCode code); - explicit PyShortCode(std::string_view code); - - /// Get original value. - [[nodiscard]] uint32_t value() const; - - /// Convert ShortCode to CommonCode. - [[nodiscard]] PyCommonCode common_code() const; - - /// Verify ShortCode in u32 form. - static bool check(uint32_t code); - - /// Verify ShortCode in string form. - static bool check(std::string_view code); - - /// Build conversion index for ShortCode. - static void speed_up(bool fast_mode); - - /// Wrapper of `__str__` method in Python. - static std::string str(PyShortCode code); - - /// Wrapper of `__repr__` method in Python. - static std::string repr(PyShortCode code); - -private: - ShortCode code_; -}; - -// ----------------------------------------------------------------------------------------- // - -constexpr auto operator==(const PyShortCode &lhs, const uint32_t rhs) { - return lhs.value() == rhs; -} - -constexpr auto operator<=>(const PyShortCode &lhs, const uint32_t rhs) { - return lhs.value() <=> rhs; -} - -constexpr auto operator==(const PyShortCode &lhs, const PyShortCode &rhs) { - return lhs.value() == rhs.value(); -} - -constexpr auto operator<=>(const PyShortCode &lhs, const PyShortCode &rhs) { - return lhs.value() <=> rhs.value(); -} - -// ----------------------------------------------------------------------------------------- // - -class PyCommonCode { -public: - explicit PyCommonCode(uint64_t code); - explicit PyCommonCode(PyShortCode code); - explicit PyCommonCode(std::string_view code); - - /// Get original value. - [[nodiscard]] uint64_t value() const; - - /// Convert as shorten string form. - [[nodiscard]] std::string string() const; - - /// Convert CommonCode to ShortCode. - [[nodiscard]] PyShortCode short_code() const; - - /// Verify CommonCode in u64 form. - static bool check(uint64_t code); - - /// Verify CommonCode in string form. - static bool check(std::string_view code); - - /// Wrapper of `__str__` method in Python. - static std::string str(PyCommonCode code); - - /// Wrapper of `__repr__` method in Python. - static std::string repr(PyCommonCode code); - -private: - CommonCode code_; -}; - -// ----------------------------------------------------------------------------------------- // - -constexpr auto operator==(const PyCommonCode &lhs, const uint64_t rhs) { - return lhs.value() == rhs; -} - -constexpr auto operator<=>(const PyCommonCode &lhs, const uint64_t rhs) { - return lhs.value() <=> rhs; -} - -constexpr auto operator==(const PyCommonCode &lhs, const PyCommonCode &rhs) { - return lhs.value() == rhs.value(); -} - -constexpr auto operator<=>(const PyCommonCode &lhs, const PyCommonCode &rhs) { - return lhs.value() <=> rhs.value(); -} - -// ----------------------------------------------------------------------------------------- // - -} // namespace klotski::ffi - -// ----------------------------------------------------------------------------------------- // - -template<> -struct std::hash { - size_t operator()(const klotski::ffi::PyShortCode &short_code) const noexcept { - return std::hash()(short_code.value()); - } -}; - -template<> -struct std::hash { - size_t operator()(const klotski::ffi::PyCommonCode &common_code) const noexcept { - return std::hash()(common_code.value()); - } -}; - -// ----------------------------------------------------------------------------------------- // diff --git a/src/core_ffi/py_ffi/include/py_common_code.h b/src/core_ffi/py_ffi/include/py_common_code.h new file mode 100644 index 0000000..57226d7 --- /dev/null +++ b/src/core_ffi/py_ffi/include/py_common_code.h @@ -0,0 +1,97 @@ +/// Klotski Engine Python FFI by Dnomd343 @2024 + +#pragma once + +#include "py_short_code.h" +#include "common_code/common_code.h" + +namespace klotski::ffi { + +using codec::CommonCode; + +class PyShortCode; + +class PyCommonCode { +public: + PyCommonCode() = delete; + + // ------------------------------------------------------------------------------------- // + + /// Construct from origin u64 value. + explicit PyCommonCode(uint64_t code); + + /// Construct from origin string form. + explicit PyCommonCode(std::string_view code); + + /// Construct from PyShortCode object. + explicit PyCommonCode(PyShortCode code) noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Verify CommonCode in u64 form. + static bool check(uint64_t code) noexcept; + + /// Verify CommonCode in string form. + static bool check(std::string_view code) noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Get original value. + [[nodiscard]] uint64_t value() const noexcept; + + /// Convert CommonCode as ShortCode. + [[nodiscard]] PyShortCode short_code() const noexcept; + + /// Convert CommonCode as string form. + [[nodiscard]] std::string string(bool shorten) const noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Wrapper of `__str__` method in Python. + static std::string str(PyCommonCode code) noexcept; + + /// Wrapper of `__repr__` method in Python. + static std::string repr(PyCommonCode code) noexcept; + + // ------------------------------------------------------------------------------------- // + +private: + CommonCode code_; +}; + +// ----------------------------------------------------------------------------------------- // + +constexpr auto operator==(const PyCommonCode &lhs, const uint64_t rhs) { + return lhs.value() == rhs; +} + +constexpr auto operator<=>(const PyCommonCode &lhs, const uint64_t rhs) { + return lhs.value() <=> rhs; +} + +constexpr auto operator==(const PyCommonCode &lhs, const PyCommonCode &rhs) { + return lhs.value() == rhs.value(); +} + +constexpr auto operator<=>(const PyCommonCode &lhs, const PyCommonCode &rhs) { + return lhs.value() <=> rhs.value(); +} + +// ----------------------------------------------------------------------------------------- // + +} // namespace klotski::ffi + +// ----------------------------------------------------------------------------------------- // + +namespace std { + +template<> +struct std::hash { + size_t operator()(const klotski::ffi::PyCommonCode &common_code) const noexcept { + return std::hash{}(common_code.value()); + } +}; + +} // namespace std + +// ----------------------------------------------------------------------------------------- // diff --git a/src/core_ffi/py_ffi/include/py_exception.h b/src/core_ffi/py_ffi/include/py_exception.h new file mode 100644 index 0000000..92d2c05 --- /dev/null +++ b/src/core_ffi/py_ffi/include/py_exception.h @@ -0,0 +1,24 @@ +/// Klotski Engine Python FFI by Dnomd343 @2024 + +#pragma once + +#include +#include + +namespace klotski::ffi { + +class PyExc_CodecError final : std::exception { +public: + explicit PyExc_CodecError(const std::string_view &msg) : msg_(msg) {} + + ~PyExc_CodecError() override = default; + + [[nodiscard]] const char* what() const noexcept override { + return msg_.c_str(); + } + +private: + std::string msg_; +}; + +} // namespace klotski::ffi diff --git a/src/core_ffi/py_ffi/include/py_group.h b/src/core_ffi/py_ffi/include/py_group.h index 6c78767..455f2a6 100644 --- a/src/core_ffi/py_ffi/include/py_group.h +++ b/src/core_ffi/py_ffi/include/py_group.h @@ -9,7 +9,7 @@ #include "py_cases.h" -#include "py_codec.h" +#include "py_common_code.h" namespace klotski::ffi { diff --git a/src/core_ffi/py_ffi/include/py_short_code.h b/src/core_ffi/py_ffi/include/py_short_code.h new file mode 100644 index 0000000..fa157e1 --- /dev/null +++ b/src/core_ffi/py_ffi/include/py_short_code.h @@ -0,0 +1,99 @@ +/// Klotski Engine Python FFI by Dnomd343 @2024 + +#pragma once + +#include "py_common_code.h" +#include "short_code/short_code.h" + +namespace klotski::ffi { + +using codec::ShortCode; + +class PyCommonCode; + +class PyShortCode { +public: + PyShortCode() = delete; + + // ------------------------------------------------------------------------------------- // + + /// Construct from origin u32 value. + explicit PyShortCode(uint32_t code); + + /// Construct from origin string form. + explicit PyShortCode(std::string_view code); + + /// Construct from PyCommonCode object. + explicit PyShortCode(PyCommonCode code) noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Verify ShortCode in u32 form. + static bool check(uint32_t code) noexcept; + + /// Verify ShortCode in string form. + static bool check(std::string_view code) noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Get original value. + [[nodiscard]] uint32_t value() const noexcept; + + /// Convert ShortCode as CommonCode. + [[nodiscard]] PyCommonCode common_code() const noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Wrapper of `__str__` method in Python. + static std::string str(PyShortCode code) noexcept; + + /// Wrapper of `__repr__` method in Python. + static std::string repr(PyShortCode code) noexcept; + + // ------------------------------------------------------------------------------------- // + + /// Build conversion index for ShortCode. + static void speed_up(bool fast_mode) { // TODO: move to `SpeedUp` + ShortCode::speed_up(fast_mode); + } + +private: + ShortCode code_; +}; + +// ----------------------------------------------------------------------------------------- // + +constexpr auto operator==(const PyShortCode &lhs, const uint32_t rhs) { + return lhs.value() == rhs; +} + +constexpr auto operator<=>(const PyShortCode &lhs, const uint32_t rhs) { + return lhs.value() <=> rhs; +} + +constexpr auto operator==(const PyShortCode &lhs, const PyShortCode &rhs) { + return lhs.value() == rhs.value(); +} + +constexpr auto operator<=>(const PyShortCode &lhs, const PyShortCode &rhs) { + return lhs.value() <=> rhs.value(); +} + +// ----------------------------------------------------------------------------------------- // + +} // namespace klotski::ffi + +// ----------------------------------------------------------------------------------------- // + +namespace std { + +template<> +struct std::hash { + size_t operator()(const klotski::ffi::PyShortCode &short_code) const noexcept { + return std::hash{}(short_code.value()); + } +}; + +} + +// ----------------------------------------------------------------------------------------- // diff --git a/src/core_ffi/py_ffi/codec/common_codec.cc b/src/core_ffi/py_ffi/wrapper/common_codec.cc similarity index 60% rename from src/core_ffi/py_ffi/codec/common_codec.cc rename to src/core_ffi/py_ffi/wrapper/common_codec.cc index d474fe0..3207e77 100644 --- a/src/core_ffi/py_ffi/codec/common_codec.cc +++ b/src/core_ffi/py_ffi/wrapper/common_codec.cc @@ -1,53 +1,47 @@ #include -#include "py_exps.h" -#include "py_codec.h" +#include "include/py_exception.h" +#include "include/py_common_code.h" -using klotski::ffi::PyCodecExp; - -using klotski::ffi::PyShortCode; -using klotski::ffi::PyCommonCode; - -using klotski::codec::ShortCode; -using klotski::codec::CommonCode; +using namespace klotski::ffi; // ----------------------------------------------------------------------------------------- // -uint64_t PyCommonCode::value() const { +uint64_t PyCommonCode::value() const noexcept { return code_.unwrap(); } -std::string PyCommonCode::string() const { - return code_.to_string(true); +std::string PyCommonCode::string(bool shorten) const noexcept { + return code_.to_string(shorten); } -PyShortCode PyCommonCode::short_code() const { +PyShortCode PyCommonCode::short_code() const noexcept { return std::bit_cast(code_.to_short_code()); } // ----------------------------------------------------------------------------------------- // -bool PyCommonCode::check(const uint64_t code) { +bool PyCommonCode::check(const uint64_t code) noexcept { return CommonCode::check(code); } -bool PyCommonCode::check(const std::string_view code) { +bool PyCommonCode::check(const std::string_view code) noexcept { return CommonCode::from_string(code).has_value(); } // ----------------------------------------------------------------------------------------- // -std::string PyCommonCode::str(const PyCommonCode code) { +std::string PyCommonCode::str(const PyCommonCode code) noexcept { return code.code_.to_string(); } -std::string PyCommonCode::repr(const PyCommonCode code) { +std::string PyCommonCode::repr(const PyCommonCode code) noexcept { return std::format("", str(code)); } // ----------------------------------------------------------------------------------------- // -static CommonCode convert(const PyShortCode code) { +static CommonCode convert(const PyShortCode code) noexcept { return std::bit_cast(code).to_common_code(); } @@ -55,20 +49,18 @@ static CommonCode convert(const uint64_t code) { if (CommonCode::check(code)) { return CommonCode::unsafe_create(code); } - throw PyCodecExp(std::format("invalid common code -> {}", code)); + throw PyExc_CodecError(std::format("invalid common code -> {}", code)); } static CommonCode convert(const std::string_view code) { if (const auto str = CommonCode::from_string(code)) { return str.value(); } - throw PyCodecExp(std::format("invalid common code -> `{}`", code)); + throw PyExc_CodecError(std::format("invalid common code -> `{}`", code)); } PyCommonCode::PyCommonCode(const uint64_t code) : code_(convert(code)) {} - -PyCommonCode::PyCommonCode(const PyShortCode code) : code_(convert(code)) {} - PyCommonCode::PyCommonCode(const std::string_view code) : code_(convert(code)) {} +PyCommonCode::PyCommonCode(const PyShortCode code) noexcept : code_(convert(code)) {} // ----------------------------------------------------------------------------------------- // diff --git a/src/core_ffi/py_ffi/py_cases.cc b/src/core_ffi/py_ffi/wrapper/py_cases.cc similarity index 100% rename from src/core_ffi/py_ffi/py_cases.cc rename to src/core_ffi/py_ffi/wrapper/py_cases.cc diff --git a/src/core_ffi/py_ffi/py_group.cc b/src/core_ffi/py_ffi/wrapper/py_group.cc similarity index 100% rename from src/core_ffi/py_ffi/py_group.cc rename to src/core_ffi/py_ffi/wrapper/py_group.cc diff --git a/src/core_ffi/py_ffi/py_group_union.cc b/src/core_ffi/py_ffi/wrapper/py_group_union.cc similarity index 100% rename from src/core_ffi/py_ffi/py_group_union.cc rename to src/core_ffi/py_ffi/wrapper/py_group_union.cc diff --git a/src/core_ffi/py_ffi/codec/short_code.cc b/src/core_ffi/py_ffi/wrapper/short_code.cc similarity index 60% rename from src/core_ffi/py_ffi/codec/short_code.cc rename to src/core_ffi/py_ffi/wrapper/short_code.cc index 6bb6f49..f95d540 100644 --- a/src/core_ffi/py_ffi/codec/short_code.cc +++ b/src/core_ffi/py_ffi/wrapper/short_code.cc @@ -1,53 +1,43 @@ #include -#include "py_exps.h" -#include "py_codec.h" +#include "include/py_exception.h" +#include "include/py_short_code.h" -using klotski::ffi::PyCodecExp; - -using klotski::ffi::PyShortCode; -using klotski::ffi::PyCommonCode; - -using klotski::codec::ShortCode; -using klotski::codec::CommonCode; +using namespace klotski::ffi; // ----------------------------------------------------------------------------------------- // -uint32_t PyShortCode::value() const { +uint32_t PyShortCode::value() const noexcept { return code_.unwrap(); } -PyCommonCode PyShortCode::common_code() const { +PyCommonCode PyShortCode::common_code() const noexcept { return std::bit_cast(code_.to_common_code()); } // ----------------------------------------------------------------------------------------- // -bool PyShortCode::check(const uint32_t code) { +bool PyShortCode::check(const uint32_t code) noexcept { return ShortCode::check(code); } -bool PyShortCode::check(const std::string_view code) { +bool PyShortCode::check(const std::string_view code) noexcept { return ShortCode::from_string(code).has_value(); } -void PyShortCode::speed_up(const bool fast_mode) { - ShortCode::speed_up(fast_mode); -} - // ----------------------------------------------------------------------------------------- // -std::string PyShortCode::str(const PyShortCode code) { +std::string PyShortCode::str(const PyShortCode code) noexcept { return code.code_.to_string(); } -std::string PyShortCode::repr(const PyShortCode code) { +std::string PyShortCode::repr(const PyShortCode code) noexcept { return std::format("", code.value(), str(code)); } // ----------------------------------------------------------------------------------------- // -static ShortCode convert(const PyCommonCode code) { +static ShortCode convert(const PyCommonCode code) noexcept { return std::bit_cast(code).to_short_code(); } @@ -55,20 +45,18 @@ static ShortCode convert(const uint32_t code) { if (ShortCode::check(code)) { return ShortCode::unsafe_create(code); } - throw PyCodecExp(std::format("invalid short code -> {}", code)); + throw PyExc_CodecError(std::format("invalid short code -> {}", code)); } static ShortCode convert(const std::string_view code) { if (const auto str = ShortCode::from_string(code)) { return str.value(); } - throw PyCodecExp(std::format("invalid short code -> `{}`", code)); + throw PyExc_CodecError(std::format("invalid short code -> `{}`", code)); } PyShortCode::PyShortCode(const uint32_t code) : code_(convert(code)) {} - -PyShortCode::PyShortCode(const PyCommonCode code) : code_(convert(code)) {} - PyShortCode::PyShortCode(const std::string_view code) : code_(convert(code)) {} +PyShortCode::PyShortCode(const PyCommonCode code) noexcept : code_(convert(code)) {} // ----------------------------------------------------------------------------------------- //