From edd214cb361ca3cdfcd8ac24062df2059abb53bf Mon Sep 17 00:00:00 2001 From: Katze719 Date: Tue, 17 Mar 2026 22:10:42 +0100 Subject: [PATCH 01/13] Refactor status codes and remove deprecated header - Introduced a new structure for status codes in status_codes.h, categorizing errors into Configuration, Connection, Io, Control, and Monitor. - Removed the obsolete status_codes.hpp file, consolidating functionality into status_codes.h. - Updated validation functions in validation.hpp to utilize the new status code structure for improved error handling. - Adjusted documentation in serial_abort_read.h and serial_abort_write.h to reflect changes in status code usage. --- .../cpp_core/interface/serial_abort_read.h | 4 +- .../cpp_core/interface/serial_abort_write.h | 4 +- include/cpp_core/status_codes.h | 90 +++++++++++---- include/cpp_core/status_codes.hpp | 108 ------------------ include/cpp_core/validation.hpp | 21 ++-- 5 files changed, 83 insertions(+), 144 deletions(-) delete mode 100644 include/cpp_core/status_codes.hpp diff --git a/include/cpp_core/interface/serial_abort_read.h b/include/cpp_core/interface/serial_abort_read.h index 8db85bb..6ac8008 100644 --- a/include/cpp_core/interface/serial_abort_read.h +++ b/include/cpp_core/interface/serial_abort_read.h @@ -12,11 +12,11 @@ extern "C" * @brief Abort a blocking read operation running in a different thread. * * The target read function returns immediately with - * ::cpp_core::StatusCodes::kAbortReadError. + * ::cpp_core::StatusCode::Io::kAbortReadError. * * @param handle Port handle. * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. - * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + * @return 0 on success or a negative error code from ::cpp_core::StatusCode on error. */ MODULE_API auto serialAbortRead(int64_t handle, ErrorCallbackT error_callback = nullptr) -> int; diff --git a/include/cpp_core/interface/serial_abort_write.h b/include/cpp_core/interface/serial_abort_write.h index 46fd50f..d579d94 100644 --- a/include/cpp_core/interface/serial_abort_write.h +++ b/include/cpp_core/interface/serial_abort_write.h @@ -12,11 +12,11 @@ extern "C" * @brief Abort a blocking write operation running in a different thread. * * The target write function returns immediately with - * ::cpp_core::StatusCodes::kAbortWriteError. + * ::cpp_core::StatusCode::Io::kAbortWriteError. * * @param handle Port handle. * @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`. - * @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error. + * @return 0 on success or a negative error code from ::cpp_core::StatusCode on error. */ MODULE_API auto serialAbortWrite(int64_t handle, ErrorCallbackT error_callback = nullptr) -> int; diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_codes.h index 4da48ce..b234a29 100644 --- a/include/cpp_core/status_codes.h +++ b/include/cpp_core/status_codes.h @@ -1,31 +1,73 @@ #pragma once +#include +#include +#include + namespace cpp_core { -enum class StatusCodes + +using ValueType = std::int32_t; + +template struct CategoryBase { - kSuccess = 0, - kCloseHandleError = -1, - kInvalidHandleError = -2, - kReadError = -3, - kWriteError = -4, - kGetStateError = -5, - kSetStateError = -6, - kSetTimeoutError = -7, - kBufferError = -8, - kNotFoundError = -9, - kClearBufferInError = -10, - kClearBufferOutError = -11, - kAbortReadError = -12, - kAbortWriteError = -13, - kSetDtrError = -14, - kSetRtsError = -15, - kGetModemStatusError = -16, - kSendBreakError = -17, - kSetFlowControlError = -18, - kSetBaudrateError = -19, - kSetDataBitsError = -20, - kSetParityError = -22, - kSetStopBitsError = -23, + private: + constexpr CategoryBase() = default; + + public: + static constexpr auto make(ValueType detail) -> ValueType + { + return -((Category * 100) + detail); + } }; + +struct StatusCode +{ + static constexpr ValueType kSuccess = 0; + + struct Configuration : CategoryBase<1> + { + static constexpr ValueType kSetBaudrateError = make(0); + static constexpr ValueType kSetDataBitsError = make(1); + static constexpr ValueType kSetParityError = make(2); + static constexpr ValueType kSetStopBitsError = make(3); + static constexpr ValueType kSetFlowControlError = make(4); + static constexpr ValueType kSetTimeoutError = make(5); + }; + + struct Connection : CategoryBase<2> + { + static constexpr ValueType kNotFoundError = make(0); + static constexpr ValueType kInvalidHandleError = make(1); + static constexpr ValueType kCloseHandleError = make(2); + }; + + struct Io : CategoryBase<3> + { + static constexpr ValueType kReadError = make(0); + static constexpr ValueType kWriteError = make(1); + static constexpr ValueType kAbortReadError = make(2); + static constexpr ValueType kAbortWriteError = make(3); + static constexpr ValueType kBufferError = make(4); + static constexpr ValueType kClearBufferInError = make(5); + static constexpr ValueType kClearBufferOutError = make(6); + }; + + struct Control : CategoryBase<4> + { + static constexpr ValueType kSetDtrError = make(0); + static constexpr ValueType kSetRtsError = make(1); + static constexpr ValueType kGetModemStatusError = make(2); + static constexpr ValueType kSendBreakError = make(3); + static constexpr ValueType kGetStateError = make(4); + static constexpr ValueType kSetStateError = make(5); + }; + + struct Monitor : CategoryBase<5> + { + static constexpr ValueType kMonitorError = make(0); + }; +}; + +using StatusCodes = ValueType; } // namespace cpp_core diff --git a/include/cpp_core/status_codes.hpp b/include/cpp_core/status_codes.hpp deleted file mode 100644 index 3573de2..0000000 --- a/include/cpp_core/status_codes.hpp +++ /dev/null @@ -1,108 +0,0 @@ -#pragma once - -#include "status_codes.h" - -#include -#include - -namespace cpp_core -{ - -// constexpr toString -[[nodiscard]] constexpr auto toString(StatusCodes code) noexcept -> std::string_view -{ - switch (code) - { - case StatusCodes::kSuccess: - return "Success"; - case StatusCodes::kCloseHandleError: - return "CloseHandleError"; - case StatusCodes::kInvalidHandleError: - return "InvalidHandleError"; - case StatusCodes::kReadError: - return "ReadError"; - case StatusCodes::kWriteError: - return "WriteError"; - case StatusCodes::kGetStateError: - return "GetStateError"; - case StatusCodes::kSetStateError: - return "SetStateError"; - case StatusCodes::kSetTimeoutError: - return "SetTimeoutError"; - case StatusCodes::kBufferError: - return "BufferError"; - case StatusCodes::kNotFoundError: - return "NotFoundError"; - case StatusCodes::kClearBufferInError: - return "ClearBufferInError"; - case StatusCodes::kClearBufferOutError: - return "ClearBufferOutError"; - case StatusCodes::kAbortReadError: - return "AbortReadError"; - case StatusCodes::kAbortWriteError: - return "AbortWriteError"; - case StatusCodes::kSetDtrError: - return "SetDtrError"; - case StatusCodes::kSetRtsError: - return "SetRtsError"; - case StatusCodes::kGetModemStatusError: - return "GetModemStatusError"; - case StatusCodes::kSendBreakError: - return "SendBreakError"; - case StatusCodes::kSetFlowControlError: - return "SetFlowControlError"; - case StatusCodes::kSetBaudrateError: - return "SetBaudrateError"; - case StatusCodes::kSetDataBitsError: - return "SetDataBitsError"; - case StatusCodes::kSetParityError: - return "SetParityError"; - case StatusCodes::kSetStopBitsError: - return "SetStopBitsError"; - } - return "Unknown"; -} - -[[nodiscard]] constexpr auto isError(StatusCodes code) noexcept -> bool -{ - return static_cast(code) < 0; -} - -[[nodiscard]] constexpr auto isSuccess(StatusCodes code) noexcept -> bool -{ - return code == StatusCodes::kSuccess; -} - -/** - * Convert a raw int (as returned by C API functions) back to a StatusCodes. - * Returns kSuccess for any non-negative value. - */ -[[nodiscard]] constexpr auto fromInt(int value) noexcept -> StatusCodes -{ - if (value >= 0) - { - return StatusCodes::kSuccess; - } - return static_cast(value); -} - -} // namespace cpp_core - -// std::format support -/** - * Enables: std::format("Port open failed: {}", StatusCodes::kNotFoundError) - * => "Port open failed: NotFoundError (-9)" - */ -template <> struct std::formatter : std::formatter -{ - auto format(cpp_core::StatusCodes code, auto &ctx) const - { - auto name = cpp_core::toString(code); - auto val = static_cast(code); - if (val == 0) - { - return std::formatter::format(name, ctx); - } - return std::format_to(ctx.out(), "{} ({})", name, val); - } -}; diff --git a/include/cpp_core/validation.hpp b/include/cpp_core/validation.hpp index f910d00..8abcdd1 100644 --- a/include/cpp_core/validation.hpp +++ b/include/cpp_core/validation.hpp @@ -19,9 +19,10 @@ constexpr auto validateHandle(int64_t handle, Callback &&error_callback) -> Ret { if (handle <= 0 || handle > std::numeric_limits::max()) { - return failMsg(std::forward(error_callback), StatusCodes::kInvalidHandleError, "Invalid handle"); + return failMsg(std::forward(error_callback), + static_cast(StatusCode::Connection::kInvalidHandleError), "Invalid handle"); } - return static_cast(StatusCodes::kSuccess); + return static_cast(StatusCode::kSuccess); } /** @@ -33,20 +34,23 @@ constexpr auto validateOpenParams(void *port, int baudrate, int data_bits, Callb { if (port == nullptr) { - return failMsg(std::forward(error_callback), StatusCodes::kNotFoundError, + return failMsg(std::forward(error_callback), + static_cast(StatusCode::Connection::kNotFoundError), "Port parameter is nullptr"); } if (baudrate < 300) { - return failMsg(std::forward(error_callback), StatusCodes::kSetStateError, + return failMsg(std::forward(error_callback), + static_cast(StatusCode::Control::kSetStateError), "Invalid baudrate: must be >= 300"); } if (data_bits < 5 || data_bits > 8) { - return failMsg(std::forward(error_callback), StatusCodes::kSetStateError, + return failMsg(std::forward(error_callback), + static_cast(StatusCode::Control::kSetStateError), "Invalid data bits: must be 5-8"); } - return static_cast(StatusCodes::kSuccess); + return static_cast(StatusCode::kSuccess); } // Validate buffer + size for read/write calls. @@ -55,10 +59,11 @@ constexpr auto validateBuffer(const void *buffer, int buffer_size, Callback &&er { if (buffer == nullptr || buffer_size <= 0) { - return failMsg(std::forward(error_callback), StatusCodes::kBufferError, + return failMsg(std::forward(error_callback), + static_cast(StatusCode::Io::kBufferError), "Invalid buffer or buffer_size"); } - return static_cast(StatusCodes::kSuccess); + return static_cast(StatusCode::kSuccess); } // Clamp timeout to non-negative. From 1616b1c00e5a4f78248e2e548dd8d689f62a7ab4 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Tue, 17 Mar 2026 22:22:46 +0100 Subject: [PATCH 02/13] Refactor status code definitions in status_codes.h - Changed ValueType from std::int32_t to std::int64_t for improved range. - Replaced the make function with a GenCode template structure for generating error codes, enhancing clarity and maintainability. - Updated error codes in Configuration, Connection, Io, Control, and Monitor categories to utilize the new GenCode structure. --- include/cpp_core/status_codes.h | 61 ++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_codes.h index b234a29..fd86b11 100644 --- a/include/cpp_core/status_codes.h +++ b/include/cpp_core/status_codes.h @@ -7,18 +7,23 @@ namespace cpp_core { -using ValueType = std::int32_t; +using ValueType = std::int64_t; template struct CategoryBase { private: constexpr CategoryBase() = default; - public: - static constexpr auto make(ValueType detail) -> ValueType + protected: + static constexpr ValueType kCategoryMultiplier = 100; + + template struct GenCode { - return -((Category * 100) + detail); - } + static constexpr ValueType kValue = -((Category * kCategoryMultiplier) + Code); + }; + + public: + static constexpr auto kCategoryCode = Category; }; struct StatusCode @@ -27,45 +32,45 @@ struct StatusCode struct Configuration : CategoryBase<1> { - static constexpr ValueType kSetBaudrateError = make(0); - static constexpr ValueType kSetDataBitsError = make(1); - static constexpr ValueType kSetParityError = make(2); - static constexpr ValueType kSetStopBitsError = make(3); - static constexpr ValueType kSetFlowControlError = make(4); - static constexpr ValueType kSetTimeoutError = make(5); + static constexpr ValueType kSetBaudrateError = GenCode<0>::kValue; + static constexpr ValueType kSetDataBitsError = GenCode<1>::kValue; + static constexpr ValueType kSetParityError = GenCode<2>::kValue; + static constexpr ValueType kSetStopBitsError = GenCode<3>::kValue; + static constexpr ValueType kSetFlowControlError = GenCode<4>::kValue; + static constexpr ValueType kSetTimeoutError = GenCode<5>::kValue; }; struct Connection : CategoryBase<2> { - static constexpr ValueType kNotFoundError = make(0); - static constexpr ValueType kInvalidHandleError = make(1); - static constexpr ValueType kCloseHandleError = make(2); + static constexpr ValueType kNotFoundError = GenCode<0>::kValue; + static constexpr ValueType kInvalidHandleError = GenCode<1>::kValue; + static constexpr ValueType kCloseHandleError = GenCode<2>::kValue; }; struct Io : CategoryBase<3> { - static constexpr ValueType kReadError = make(0); - static constexpr ValueType kWriteError = make(1); - static constexpr ValueType kAbortReadError = make(2); - static constexpr ValueType kAbortWriteError = make(3); - static constexpr ValueType kBufferError = make(4); - static constexpr ValueType kClearBufferInError = make(5); - static constexpr ValueType kClearBufferOutError = make(6); + static constexpr ValueType kReadError = GenCode<0>::kValue; + static constexpr ValueType kWriteError = GenCode<1>::kValue; + static constexpr ValueType kAbortReadError = GenCode<2>::kValue; + static constexpr ValueType kAbortWriteError = GenCode<3>::kValue; + static constexpr ValueType kBufferError = GenCode<4>::kValue; + static constexpr ValueType kClearBufferInError = GenCode<5>::kValue; + static constexpr ValueType kClearBufferOutError = GenCode<6>::kValue; }; struct Control : CategoryBase<4> { - static constexpr ValueType kSetDtrError = make(0); - static constexpr ValueType kSetRtsError = make(1); - static constexpr ValueType kGetModemStatusError = make(2); - static constexpr ValueType kSendBreakError = make(3); - static constexpr ValueType kGetStateError = make(4); - static constexpr ValueType kSetStateError = make(5); + static constexpr ValueType kSetDtrError = GenCode<0>::kValue; + static constexpr ValueType kSetRtsError = GenCode<1>::kValue; + static constexpr ValueType kGetModemStatusError = GenCode<2>::kValue; + static constexpr ValueType kSendBreakError = GenCode<3>::kValue; + static constexpr ValueType kGetStateError = GenCode<4>::kValue; + static constexpr ValueType kSetStateError = GenCode<5>::kValue; }; struct Monitor : CategoryBase<5> { - static constexpr ValueType kMonitorError = make(0); + static constexpr ValueType kMonitorError = GenCode<0>::kValue; }; }; From f9aef382e22be7603d8f1b42914b74dd8acd71e8 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Tue, 17 Mar 2026 22:31:44 +0100 Subject: [PATCH 03/13] Enhance status code structure in status_codes.h - Added an explicit conversion operator to the GenCode template for improved usability. - Updated status code definitions in Configuration, Connection, Io, Control, and Monitor categories to utilize the GenCode structure directly, enhancing clarity and maintainability. --- include/cpp_core/status_codes.h | 50 ++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_codes.h index fd86b11..329cfe0 100644 --- a/include/cpp_core/status_codes.h +++ b/include/cpp_core/status_codes.h @@ -20,6 +20,10 @@ template struct CategoryBase template struct GenCode { static constexpr ValueType kValue = -((Category * kCategoryMultiplier) + Code); + constexpr explicit operator ValueType() const noexcept + { + return kValue; + } }; public: @@ -32,45 +36,45 @@ struct StatusCode struct Configuration : CategoryBase<1> { - static constexpr ValueType kSetBaudrateError = GenCode<0>::kValue; - static constexpr ValueType kSetDataBitsError = GenCode<1>::kValue; - static constexpr ValueType kSetParityError = GenCode<2>::kValue; - static constexpr ValueType kSetStopBitsError = GenCode<3>::kValue; - static constexpr ValueType kSetFlowControlError = GenCode<4>::kValue; - static constexpr ValueType kSetTimeoutError = GenCode<5>::kValue; + static constexpr GenCode<0> kSetBaudrateError; + static constexpr GenCode<1> kSetDataBitsError; + static constexpr GenCode<2> kSetParityError; + static constexpr GenCode<3> kSetStopBitsError; + static constexpr GenCode<4> kSetFlowControlError; + static constexpr GenCode<5> kSetTimeoutError; }; struct Connection : CategoryBase<2> { - static constexpr ValueType kNotFoundError = GenCode<0>::kValue; - static constexpr ValueType kInvalidHandleError = GenCode<1>::kValue; - static constexpr ValueType kCloseHandleError = GenCode<2>::kValue; + static constexpr GenCode<0> kNotFoundError; + static constexpr GenCode<1> kInvalidHandleError; + static constexpr GenCode<2> kCloseHandleError; }; struct Io : CategoryBase<3> { - static constexpr ValueType kReadError = GenCode<0>::kValue; - static constexpr ValueType kWriteError = GenCode<1>::kValue; - static constexpr ValueType kAbortReadError = GenCode<2>::kValue; - static constexpr ValueType kAbortWriteError = GenCode<3>::kValue; - static constexpr ValueType kBufferError = GenCode<4>::kValue; - static constexpr ValueType kClearBufferInError = GenCode<5>::kValue; - static constexpr ValueType kClearBufferOutError = GenCode<6>::kValue; + static constexpr GenCode<0> kReadError; + static constexpr GenCode<1> kWriteError; + static constexpr GenCode<2> kAbortReadError; + static constexpr GenCode<3> kAbortWriteError; + static constexpr GenCode<4> kBufferError; + static constexpr GenCode<5> kClearBufferInError; + static constexpr GenCode<6> kClearBufferOutError; }; struct Control : CategoryBase<4> { - static constexpr ValueType kSetDtrError = GenCode<0>::kValue; - static constexpr ValueType kSetRtsError = GenCode<1>::kValue; - static constexpr ValueType kGetModemStatusError = GenCode<2>::kValue; - static constexpr ValueType kSendBreakError = GenCode<3>::kValue; - static constexpr ValueType kGetStateError = GenCode<4>::kValue; - static constexpr ValueType kSetStateError = GenCode<5>::kValue; + static constexpr GenCode<0> kSetDtrError; + static constexpr GenCode<1> kSetRtsError; + static constexpr GenCode<2> kGetModemStatusError; + static constexpr GenCode<3> kSendBreakError; + static constexpr GenCode<4> kGetStateError; + static constexpr GenCode<5> kSetStateError; }; struct Monitor : CategoryBase<5> { - static constexpr ValueType kMonitorError = GenCode<0>::kValue; + static constexpr GenCode<0> kMonitorError; }; }; From be05f7bae8abbe96a55c218f5643636f2b1231a2 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Tue, 17 Mar 2026 22:35:14 +0100 Subject: [PATCH 04/13] Refactor status code organization in status_codes.h - Moved status code definitions into a new cpp_core::status_codes namespace for better modularity. - Introduced a detail namespace to encapsulate internal structures, enhancing code clarity. - Updated references to ValueType and CategoryBase to reflect the new namespace structure, improving maintainability. --- include/cpp_core/status_codes.h | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_codes.h index 329cfe0..bb13f87 100644 --- a/include/cpp_core/status_codes.h +++ b/include/cpp_core/status_codes.h @@ -4,9 +4,11 @@ #include #include -namespace cpp_core +namespace cpp_core::status_codes { +namespace detail +{ using ValueType = std::int64_t; template struct CategoryBase @@ -29,12 +31,13 @@ template struct CategoryBase public: static constexpr auto kCategoryCode = Category; }; +} // namespace detail struct StatusCode { - static constexpr ValueType kSuccess = 0; + static constexpr detail::ValueType kSuccess = 0; - struct Configuration : CategoryBase<1> + struct Configuration : detail::CategoryBase<1> { static constexpr GenCode<0> kSetBaudrateError; static constexpr GenCode<1> kSetDataBitsError; @@ -44,14 +47,14 @@ struct StatusCode static constexpr GenCode<5> kSetTimeoutError; }; - struct Connection : CategoryBase<2> + struct Connection : detail::CategoryBase<2> { static constexpr GenCode<0> kNotFoundError; static constexpr GenCode<1> kInvalidHandleError; static constexpr GenCode<2> kCloseHandleError; }; - struct Io : CategoryBase<3> + struct Io : detail::CategoryBase<3> { static constexpr GenCode<0> kReadError; static constexpr GenCode<1> kWriteError; @@ -62,7 +65,7 @@ struct StatusCode static constexpr GenCode<6> kClearBufferOutError; }; - struct Control : CategoryBase<4> + struct Control : detail::CategoryBase<4> { static constexpr GenCode<0> kSetDtrError; static constexpr GenCode<1> kSetRtsError; @@ -72,11 +75,16 @@ struct StatusCode static constexpr GenCode<5> kSetStateError; }; - struct Monitor : CategoryBase<5> + struct Monitor : detail::CategoryBase<5> { static constexpr GenCode<0> kMonitorError; }; }; -using StatusCodes = ValueType; +} // namespace cpp_core::status_codes + +namespace cpp_core +{ +using StatusCodes = ::cpp_core::status_codes::detail::ValueType; +using StatusCode = ::cpp_core::status_codes::StatusCode; } // namespace cpp_core From 6ea7683fe34325ee05845fd64bc84b248c0b7d18 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Wed, 18 Mar 2026 19:46:50 +0100 Subject: [PATCH 05/13] Remove the Monitor struct from status_codes.h to streamline status code definitions and improve code clarity. --- include/cpp_core/status_codes.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_codes.h index bb13f87..6f37a18 100644 --- a/include/cpp_core/status_codes.h +++ b/include/cpp_core/status_codes.h @@ -74,11 +74,6 @@ struct StatusCode static constexpr GenCode<4> kGetStateError; static constexpr GenCode<5> kSetStateError; }; - - struct Monitor : detail::CategoryBase<5> - { - static constexpr GenCode<0> kMonitorError; - }; }; } // namespace cpp_core::status_codes From f4bf82452cf85a47c5149c919331a555a34add6c Mon Sep 17 00:00:00 2001 From: Katze719 Date: Wed, 18 Mar 2026 19:47:29 +0100 Subject: [PATCH 06/13] Add status code definitions in a new header file - Introduced a new header file status_code.h to define a structured approach for status codes within the cpp_core::status_codes namespace. - Implemented a CategoryBase template for generating error codes, enhancing clarity and maintainability. - Organized status codes into categories: Configuration, Connection, Io, and Control, each with specific error codes for improved usability. --- include/cpp_core/{status_codes.h => status_code.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename include/cpp_core/{status_codes.h => status_code.h} (100%) diff --git a/include/cpp_core/status_codes.h b/include/cpp_core/status_code.h similarity index 100% rename from include/cpp_core/status_codes.h rename to include/cpp_core/status_code.h From b83325319839bf0e738125e6d6d343c88ed3bc78 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Wed, 18 Mar 2026 19:52:05 +0100 Subject: [PATCH 07/13] Refactor CategoryBase template in status_code.h - Changed the CategoryBase template to accept a derived type instead of a category value, enhancing type safety and clarity. - Updated the Configuration, Connection, Io, and Control structs to define their category codes directly, improving maintainability and readability of status code definitions. --- include/cpp_core/status_code.h | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index 6f37a18..a1553f4 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -11,7 +11,7 @@ namespace detail { using ValueType = std::int64_t; -template struct CategoryBase +template struct CategoryBase { private: constexpr CategoryBase() = default; @@ -21,15 +21,13 @@ template struct CategoryBase template struct GenCode { - static constexpr ValueType kValue = -((Category * kCategoryMultiplier) + Code); + static constexpr ValueType kValue = -((Derived::kCategoryCode * kCategoryMultiplier) + Code); constexpr explicit operator ValueType() const noexcept { return kValue; } }; - - public: - static constexpr auto kCategoryCode = Category; + friend Derived; }; } // namespace detail @@ -37,8 +35,10 @@ struct StatusCode { static constexpr detail::ValueType kSuccess = 0; - struct Configuration : detail::CategoryBase<1> + struct Configuration : detail::CategoryBase { + static constexpr auto kCategoryCode{1}; + static constexpr GenCode<0> kSetBaudrateError; static constexpr GenCode<1> kSetDataBitsError; static constexpr GenCode<2> kSetParityError; @@ -47,15 +47,19 @@ struct StatusCode static constexpr GenCode<5> kSetTimeoutError; }; - struct Connection : detail::CategoryBase<2> + struct Connection : detail::CategoryBase { + static constexpr auto kCategoryCode{2}; + static constexpr GenCode<0> kNotFoundError; static constexpr GenCode<1> kInvalidHandleError; static constexpr GenCode<2> kCloseHandleError; }; - struct Io : detail::CategoryBase<3> + struct Io : detail::CategoryBase { + static constexpr auto kCategoryCode{3}; + static constexpr GenCode<0> kReadError; static constexpr GenCode<1> kWriteError; static constexpr GenCode<2> kAbortReadError; @@ -65,8 +69,10 @@ struct StatusCode static constexpr GenCode<6> kClearBufferOutError; }; - struct Control : detail::CategoryBase<4> + struct Control : detail::CategoryBase { + static constexpr auto kCategoryCode{4}; + static constexpr GenCode<0> kSetDtrError; static constexpr GenCode<1> kSetRtsError; static constexpr GenCode<2> kGetModemStatusError; From 8b235bab638d6f43212668cfe75f46e735de68e6 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Wed, 18 Mar 2026 19:56:13 +0100 Subject: [PATCH 08/13] Update kCategoryMultiplier initialization in CategoryBase template - Changed the initialization of kCategoryMultiplier from an assignment to a uniform initialization syntax, enhancing code consistency and clarity. --- include/cpp_core/status_code.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index a1553f4..7163428 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -16,8 +16,7 @@ template struct CategoryBase private: constexpr CategoryBase() = default; - protected: - static constexpr ValueType kCategoryMultiplier = 100; + static constexpr ValueType kCategoryMultiplier{100}; template struct GenCode { From 176158d190f934b63b37ecf78c7d52b12f5ebb5f Mon Sep 17 00:00:00 2001 From: Katze719 Date: Wed, 18 Mar 2026 20:11:31 +0100 Subject: [PATCH 09/13] Add new status code generation macros and enhance error handling - Introduced CPP_CORE_STATUS_CATEGORY and CPP_CORE_CODE macros for streamlined status code definitions, improving maintainability and readability. - Added isError and isSuccess functions for better error handling. - Updated the CategoryBase template to support compile-time code generation, enhancing type safety and clarity in status code management. --- include/cpp_core/status_code.h | 173 +++++++++++++++++++++++---------- 1 file changed, 119 insertions(+), 54 deletions(-) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index 7163428..c569cd4 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -2,6 +2,7 @@ #include #include +#include #include namespace cpp_core::status_codes @@ -9,82 +10,146 @@ namespace cpp_core::status_codes namespace detail { + using ValueType = std::int64_t; +inline constexpr ValueType kCategoryMultiplier{100}; + +template struct Code +{ + static constexpr ValueType kValue = NumericValue; + + // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) + constexpr operator ValueType() const noexcept + { + return kValue; + } + [[nodiscard]] constexpr auto value() const noexcept -> ValueType + { + return kValue; + } +}; + template struct CategoryBase { private: constexpr CategoryBase() = default; - static constexpr ValueType kCategoryMultiplier{100}; - - template struct GenCode + protected: + template static consteval auto computeValue() -> ValueType { - static constexpr ValueType kValue = -((Derived::kCategoryCode * kCategoryMultiplier) + Code); - constexpr explicit operator ValueType() const noexcept - { - return kValue; - } - }; + static_assert(LocalCode >= 0, "Code index must not be negative"); + static_assert(LocalCode < kCategoryMultiplier, "Category overflow (max 99 codes)"); + return -((Derived::kCategoryCode * kCategoryMultiplier) + LocalCode); + } + + template using GenCode = Code()>; + friend Derived; }; -} // namespace detail -struct StatusCode +[[nodiscard]] constexpr auto isError(ValueType code) noexcept -> bool { - static constexpr detail::ValueType kSuccess = 0; + return code < 0; +} +[[nodiscard]] constexpr auto isSuccess(ValueType code) noexcept -> bool +{ + return code >= 0; +} - struct Configuration : detail::CategoryBase - { - static constexpr auto kCategoryCode{1}; +template [[nodiscard]] constexpr auto belongsTo(ValueType code) noexcept -> bool +{ + return code < 0 && (-code) / kCategoryMultiplier == Category::kCategoryCode; +} - static constexpr GenCode<0> kSetBaudrateError; - static constexpr GenCode<1> kSetDataBitsError; - static constexpr GenCode<2> kSetParityError; - static constexpr GenCode<3> kSetStopBitsError; - static constexpr GenCode<4> kSetFlowControlError; - static constexpr GenCode<5> kSetTimeoutError; - }; +} // namespace detail - struct Connection : detail::CategoryBase - { - static constexpr auto kCategoryCode{2}; +// Helper Macro +// +// CPP_CORE_STATUS_CATEGORY(Name, Id) opens a category struct +// CPP_CORE_CODE(name) declares an auto-numbered code +// CPP_CORE_STATUS_CATEGORY_END() closes the category +// +// Each code carries: +// .value() / compile-time numeric value +// .name() / "kSomethingError" +// .category() / "CategoryName" +// and converts implicitly to ValueType (no static_cast needed). + +// NOLINTBEGIN(cppcoreguidelines-macro-usage) + +#define CPP_CORE_STATUS_CATEGORY(Name, CategoryId) \ + struct Name : ::cpp_core::status_codes::detail::CategoryBase \ + { \ + static constexpr ::cpp_core::status_codes::detail::ValueType kCategoryCode = CategoryId; \ + static constexpr std::string_view kCategoryName{#Name}; \ + \ + private: \ + static constexpr int kCounterBase_ = __COUNTER__; \ + \ + public: + +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define CPP_CORE_CODE(code_name) \ + static constexpr struct code_name##_t \ + : GenCode<__COUNTER__ - kCounterBase_ - 1>{[[nodiscard]] constexpr auto name() const noexcept \ + -> std::string_view{return #code_name; \ + } \ + [[nodiscard]] constexpr auto category() const noexcept -> std::string_view \ + { \ + return kCategoryName; \ + } \ + } \ + (code_name) \ + { \ + } + +#define CPP_CORE_STATUS_CATEGORY_END() } + +// NOLINTEND(cppcoreguidelines-macro-usage) - static constexpr GenCode<0> kNotFoundError; - static constexpr GenCode<1> kInvalidHandleError; - static constexpr GenCode<2> kCloseHandleError; - }; +struct StatusCode +{ + static constexpr detail::ValueType kSuccess = 0; - struct Io : detail::CategoryBase - { - static constexpr auto kCategoryCode{3}; - - static constexpr GenCode<0> kReadError; - static constexpr GenCode<1> kWriteError; - static constexpr GenCode<2> kAbortReadError; - static constexpr GenCode<3> kAbortWriteError; - static constexpr GenCode<4> kBufferError; - static constexpr GenCode<5> kClearBufferInError; - static constexpr GenCode<6> kClearBufferOutError; - }; - - struct Control : detail::CategoryBase - { - static constexpr auto kCategoryCode{4}; - - static constexpr GenCode<0> kSetDtrError; - static constexpr GenCode<1> kSetRtsError; - static constexpr GenCode<2> kGetModemStatusError; - static constexpr GenCode<3> kSendBreakError; - static constexpr GenCode<4> kGetStateError; - static constexpr GenCode<5> kSetStateError; - }; + CPP_CORE_STATUS_CATEGORY(Configuration, 1); + CPP_CORE_CODE(kSetBaudrateError); + CPP_CORE_CODE(kSetDataBitsError); + CPP_CORE_CODE(kSetParityError); + CPP_CORE_CODE(kSetStopBitsError); + CPP_CORE_CODE(kSetFlowControlError); + CPP_CORE_CODE(kSetTimeoutError); + CPP_CORE_STATUS_CATEGORY_END(); + + CPP_CORE_STATUS_CATEGORY(Connection, 2); + CPP_CORE_CODE(kNotFoundError); + CPP_CORE_CODE(kInvalidHandleError); + CPP_CORE_CODE(kCloseHandleError); + CPP_CORE_STATUS_CATEGORY_END(); + + CPP_CORE_STATUS_CATEGORY(Io, 3); + CPP_CORE_CODE(kReadError); + CPP_CORE_CODE(kWriteError); + CPP_CORE_CODE(kAbortReadError); + CPP_CORE_CODE(kAbortWriteError); + CPP_CORE_CODE(kBufferError); + CPP_CORE_CODE(kClearBufferInError); + CPP_CORE_CODE(kClearBufferOutError); + CPP_CORE_STATUS_CATEGORY_END(); + + CPP_CORE_STATUS_CATEGORY(Control, 4); + CPP_CORE_CODE(kSetDtrError); + CPP_CORE_CODE(kSetRtsError); + CPP_CORE_CODE(kGetModemStatusError); + CPP_CORE_CODE(kSendBreakError); + CPP_CORE_CODE(kGetStateError); + CPP_CORE_CODE(kSetStateError); + CPP_CORE_STATUS_CATEGORY_END(); }; } // namespace cpp_core::status_codes namespace cpp_core { -using StatusCodes = ::cpp_core::status_codes::detail::ValueType; using StatusCode = ::cpp_core::status_codes::StatusCode; } // namespace cpp_core From 2b63c694046982396d34e7bcf839f430100bd97c Mon Sep 17 00:00:00 2001 From: Katze719 Date: Wed, 18 Mar 2026 20:26:23 +0100 Subject: [PATCH 10/13] Refactor error handling functions in StatusCode - Moved isError, isSuccess, and belongsTo functions into the StatusCode struct for better encapsulation and organization. - Updated function signatures to use detail::ValueType for consistency with the new structure. - Removed redundant definitions from the detail namespace, enhancing code clarity and maintainability. --- include/cpp_core/status_code.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index c569cd4..05d821d 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -48,20 +48,6 @@ template struct CategoryBase friend Derived; }; -[[nodiscard]] constexpr auto isError(ValueType code) noexcept -> bool -{ - return code < 0; -} -[[nodiscard]] constexpr auto isSuccess(ValueType code) noexcept -> bool -{ - return code >= 0; -} - -template [[nodiscard]] constexpr auto belongsTo(ValueType code) noexcept -> bool -{ - return code < 0 && (-code) / kCategoryMultiplier == Category::kCategoryCode; -} - } // namespace detail // Helper Macro @@ -145,11 +131,24 @@ struct StatusCode CPP_CORE_CODE(kGetStateError); CPP_CORE_CODE(kSetStateError); CPP_CORE_STATUS_CATEGORY_END(); + + [[nodiscard]] static constexpr auto isError(detail::ValueType code) noexcept -> bool + { + return code < 0; + } + [[nodiscard]] static constexpr auto isSuccess(detail::ValueType code) noexcept -> bool + { + return code >= 0; + } + template [[nodiscard]] static constexpr auto belongsTo(detail::ValueType code) noexcept -> bool + { + return code < 0 && (-code) / detail::kCategoryMultiplier == Category::kCategoryCode; + } }; } // namespace cpp_core::status_codes namespace cpp_core { -using StatusCode = ::cpp_core::status_codes::StatusCode; +using ::cpp_core::status_codes::StatusCode; } // namespace cpp_core From a5ce350bb53525daa3890cee66eb376ac260b7f9 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Thu, 19 Mar 2026 16:37:10 +0100 Subject: [PATCH 11/13] Enhance status code structure in status_code.h - Refactored the Code template to accept a Category type, improving type safety and clarity. - Introduced new member functions for retrieving the name and category of status codes. - Replaced macro-based status code definitions with structured definitions for Configuration, Connection, and Io categories, enhancing maintainability and readability. --- include/cpp_core/status_code.h | 183 +++++++++++++++++---------------- 1 file changed, 97 insertions(+), 86 deletions(-) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index 05d821d..69fa4d8 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -1,9 +1,7 @@ #pragma once -#include #include #include -#include namespace cpp_core::status_codes { @@ -15,9 +13,10 @@ using ValueType = std::int64_t; inline constexpr ValueType kCategoryMultiplier{100}; -template struct Code +template struct Code { static constexpr ValueType kValue = NumericValue; + std::string_view kName; // NOLINT(readability-identifier-naming) // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions) constexpr operator ValueType() const noexcept @@ -28,6 +27,14 @@ template struct Code { return kValue; } + [[nodiscard]] constexpr auto name() const noexcept -> std::string_view + { + return kName; + } + [[nodiscard]] constexpr auto category() const noexcept -> std::string_view + { + return Category::kCategoryName; + } }; template struct CategoryBase @@ -43,104 +50,77 @@ template struct CategoryBase return -((Derived::kCategoryCode * kCategoryMultiplier) + LocalCode); } - template using GenCode = Code()>; + template using Code = detail::Code()>; friend Derived; }; } // namespace detail -// Helper Macro -// -// CPP_CORE_STATUS_CATEGORY(Name, Id) opens a category struct -// CPP_CORE_CODE(name) declares an auto-numbered code -// CPP_CORE_STATUS_CATEGORY_END() closes the category -// -// Each code carries: -// .value() / compile-time numeric value -// .name() / "kSomethingError" -// .category() / "CategoryName" -// and converts implicitly to ValueType (no static_cast needed). - -// NOLINTBEGIN(cppcoreguidelines-macro-usage) - -#define CPP_CORE_STATUS_CATEGORY(Name, CategoryId) \ - struct Name : ::cpp_core::status_codes::detail::CategoryBase \ - { \ - static constexpr ::cpp_core::status_codes::detail::ValueType kCategoryCode = CategoryId; \ - static constexpr std::string_view kCategoryName{#Name}; \ - \ - private: \ - static constexpr int kCounterBase_ = __COUNTER__; \ - \ - public: - -// NOLINTNEXTLINE(bugprone-macro-parentheses) -#define CPP_CORE_CODE(code_name) \ - static constexpr struct code_name##_t \ - : GenCode<__COUNTER__ - kCounterBase_ - 1>{[[nodiscard]] constexpr auto name() const noexcept \ - -> std::string_view{return #code_name; \ - } \ - [[nodiscard]] constexpr auto category() const noexcept -> std::string_view \ - { \ - return kCategoryName; \ - } \ - } \ - (code_name) \ - { \ - } +struct StatusCode +{ + using ValueType = detail::ValueType; + static constexpr ValueType kSuccess = 0; -#define CPP_CORE_STATUS_CATEGORY_END() } + struct Configuration : detail::CategoryBase + { + static constexpr ValueType kCategoryCode = 1; + static constexpr std::string_view kCategoryName{"Configuration"}; + + static constexpr Code<0> kSetBaudrateError{"SetBaudrateError"}; + static constexpr Code<1> kSetDataBitsError{"SetDataBitsError"}; + static constexpr Code<2> kSetParityError{"SetParityError"}; + static constexpr Code<3> kSetStopBitsError{"SetStopBitsError"}; + static constexpr Code<4> kSetFlowControlError{"SetFlowControlError"}; + static constexpr Code<5> kSetTimeoutError{"SetTimeoutError"}; + }; + + struct Connection : detail::CategoryBase + { + static constexpr ValueType kCategoryCode = 2; + static constexpr std::string_view kCategoryName{"Connection"}; -// NOLINTEND(cppcoreguidelines-macro-usage) + static constexpr Code<0> kNotFoundError{"NotFoundError"}; + static constexpr Code<1> kInvalidHandleError{"InvalidHandleError"}; + static constexpr Code<2> kCloseHandleError{"CloseHandleError"}; + }; -struct StatusCode -{ - static constexpr detail::ValueType kSuccess = 0; - - CPP_CORE_STATUS_CATEGORY(Configuration, 1); - CPP_CORE_CODE(kSetBaudrateError); - CPP_CORE_CODE(kSetDataBitsError); - CPP_CORE_CODE(kSetParityError); - CPP_CORE_CODE(kSetStopBitsError); - CPP_CORE_CODE(kSetFlowControlError); - CPP_CORE_CODE(kSetTimeoutError); - CPP_CORE_STATUS_CATEGORY_END(); - - CPP_CORE_STATUS_CATEGORY(Connection, 2); - CPP_CORE_CODE(kNotFoundError); - CPP_CORE_CODE(kInvalidHandleError); - CPP_CORE_CODE(kCloseHandleError); - CPP_CORE_STATUS_CATEGORY_END(); - - CPP_CORE_STATUS_CATEGORY(Io, 3); - CPP_CORE_CODE(kReadError); - CPP_CORE_CODE(kWriteError); - CPP_CORE_CODE(kAbortReadError); - CPP_CORE_CODE(kAbortWriteError); - CPP_CORE_CODE(kBufferError); - CPP_CORE_CODE(kClearBufferInError); - CPP_CORE_CODE(kClearBufferOutError); - CPP_CORE_STATUS_CATEGORY_END(); - - CPP_CORE_STATUS_CATEGORY(Control, 4); - CPP_CORE_CODE(kSetDtrError); - CPP_CORE_CODE(kSetRtsError); - CPP_CORE_CODE(kGetModemStatusError); - CPP_CORE_CODE(kSendBreakError); - CPP_CORE_CODE(kGetStateError); - CPP_CORE_CODE(kSetStateError); - CPP_CORE_STATUS_CATEGORY_END(); - - [[nodiscard]] static constexpr auto isError(detail::ValueType code) noexcept -> bool + struct Io : detail::CategoryBase + { + static constexpr ValueType kCategoryCode = 3; + static constexpr std::string_view kCategoryName{"Io"}; + + static constexpr Code<0> kReadError{"ReadError"}; + static constexpr Code<1> kWriteError{"WriteError"}; + static constexpr Code<2> kAbortReadError{"AbortReadError"}; + static constexpr Code<3> kAbortWriteError{"AbortWriteError"}; + static constexpr Code<4> kBufferError{"BufferError"}; + static constexpr Code<5> kClearBufferInError{"ClearBufferInError"}; + static constexpr Code<6> kClearBufferOutError{"ClearBufferOutError"}; + }; + + struct Control : detail::CategoryBase + { + static constexpr ValueType kCategoryCode = 4; + static constexpr std::string_view kCategoryName{"Control"}; + + static constexpr Code<0> kSetDtrError{"SetDtrError"}; + static constexpr Code<1> kSetRtsError{"SetRtsError"}; + static constexpr Code<2> kGetModemStatusError{"GetModemStatusError"}; + static constexpr Code<3> kSendBreakError{"SendBreakError"}; + static constexpr Code<4> kGetStateError{"GetStateError"}; + static constexpr Code<5> kSetStateError{"SetStateError"}; + }; + + [[nodiscard]] static constexpr auto isError(ValueType code) noexcept -> bool { return code < 0; } - [[nodiscard]] static constexpr auto isSuccess(detail::ValueType code) noexcept -> bool + [[nodiscard]] static constexpr auto isSuccess(ValueType code) noexcept -> bool { return code >= 0; } - template [[nodiscard]] static constexpr auto belongsTo(detail::ValueType code) noexcept -> bool + template [[nodiscard]] static constexpr auto belongsTo(ValueType code) noexcept -> bool { return code < 0 && (-code) / detail::kCategoryMultiplier == Category::kCategoryCode; } @@ -152,3 +132,34 @@ namespace cpp_core { using ::cpp_core::status_codes::StatusCode; } // namespace cpp_core + +// Test cases +static_assert(cpp_core::StatusCode::kSuccess == 0); +static_assert(cpp_core::StatusCode::isSuccess(cpp_core::StatusCode::kSuccess)); +static_assert(!cpp_core::StatusCode::isError(cpp_core::StatusCode::kSuccess)); + +static_assert(cpp_core::StatusCode::Configuration::kSetBaudrateError == -100); +static_assert(cpp_core::StatusCode::Configuration::kSetDataBitsError == -101); +static_assert(cpp_core::StatusCode::Configuration::kSetParityError == -102); +static_assert(cpp_core::StatusCode::Configuration::kSetStopBitsError == -103); +static_assert(cpp_core::StatusCode::Configuration::kSetFlowControlError == -104); +static_assert(cpp_core::StatusCode::Configuration::kSetTimeoutError == -105); + +static_assert(cpp_core::StatusCode::Connection::kNotFoundError == -200); +static_assert(cpp_core::StatusCode::Connection::kInvalidHandleError == -201); +static_assert(cpp_core::StatusCode::Connection::kCloseHandleError == -202); + +static_assert(cpp_core::StatusCode::Io::kReadError == -300); +static_assert(cpp_core::StatusCode::Io::kWriteError == -301); +static_assert(cpp_core::StatusCode::Io::kAbortReadError == -302); +static_assert(cpp_core::StatusCode::Io::kAbortWriteError == -303); +static_assert(cpp_core::StatusCode::Io::kBufferError == -304); +static_assert(cpp_core::StatusCode::Io::kClearBufferInError == -305); +static_assert(cpp_core::StatusCode::Io::kClearBufferOutError == -306); + +static_assert(cpp_core::StatusCode::Control::kSetDtrError == -400); +static_assert(cpp_core::StatusCode::Control::kSetRtsError == -401); +static_assert(cpp_core::StatusCode::Control::kGetModemStatusError == -402); +static_assert(cpp_core::StatusCode::Control::kSendBreakError == -403); +static_assert(cpp_core::StatusCode::Control::kGetStateError == -404); +static_assert(cpp_core::StatusCode::Control::kSetStateError == -405); From 9375730068b3a43a3c60c3c716fd85a921de3359 Mon Sep 17 00:00:00 2001 From: Katze719 <38188106+Katze719@users.noreply.github.com> Date: Fri, 20 Mar 2026 07:34:26 +0100 Subject: [PATCH 12/13] Update include/cpp_core/status_code.h Co-authored-by: Mqx <62719703+Mqxx@users.noreply.github.com> --- include/cpp_core/status_code.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index 69fa4d8..023ac2c 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -138,6 +138,8 @@ static_assert(cpp_core::StatusCode::kSuccess == 0); static_assert(cpp_core::StatusCode::isSuccess(cpp_core::StatusCode::kSuccess)); static_assert(!cpp_core::StatusCode::isError(cpp_core::StatusCode::kSuccess)); +static_assert(cpp_core::StatusCode::isError(cpp_core::StatusCode::Configuration::kSetBaudrateError)); + static_assert(cpp_core::StatusCode::Configuration::kSetBaudrateError == -100); static_assert(cpp_core::StatusCode::Configuration::kSetDataBitsError == -101); static_assert(cpp_core::StatusCode::Configuration::kSetParityError == -102); From ba2838b4d80e39c073de4ccbda9772ac5b345403 Mon Sep 17 00:00:00 2001 From: Katze719 Date: Fri, 20 Mar 2026 21:30:32 +0100 Subject: [PATCH 13/13] Enhance CategoryBase template in status_code.h - Added static assertions to enforce constraints on category and local codes, improving safety against negative values and overflow. - Introduced a new test category, FakeCategory, to validate the computation of status codes, ensuring correct behavior across edge cases and preventing overflow. - Updated test cases to cover various scenarios, enhancing the robustness of the status code generation logic. --- include/cpp_core/status_code.h | 76 ++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/include/cpp_core/status_code.h b/include/cpp_core/status_code.h index 023ac2c..4f652a2 100644 --- a/include/cpp_core/status_code.h +++ b/include/cpp_core/status_code.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include namespace cpp_core::status_codes @@ -45,8 +46,12 @@ template struct CategoryBase protected: template static consteval auto computeValue() -> ValueType { + static_assert(Derived::kCategoryCode >= 0, "Category code must not be negative"); static_assert(LocalCode >= 0, "Code index must not be negative"); static_assert(LocalCode < kCategoryMultiplier, "Category overflow (max 99 codes)"); + static_assert(Derived::kCategoryCode <= + (std::numeric_limits::max() - kCategoryMultiplier + 1) / kCategoryMultiplier, + "Category code too large, multiplication would overflow"); return -((Derived::kCategoryCode * kCategoryMultiplier) + LocalCode); } @@ -133,35 +138,42 @@ namespace cpp_core using ::cpp_core::status_codes::StatusCode; } // namespace cpp_core -// Test cases -static_assert(cpp_core::StatusCode::kSuccess == 0); -static_assert(cpp_core::StatusCode::isSuccess(cpp_core::StatusCode::kSuccess)); -static_assert(!cpp_core::StatusCode::isError(cpp_core::StatusCode::kSuccess)); - -static_assert(cpp_core::StatusCode::isError(cpp_core::StatusCode::Configuration::kSetBaudrateError)); - -static_assert(cpp_core::StatusCode::Configuration::kSetBaudrateError == -100); -static_assert(cpp_core::StatusCode::Configuration::kSetDataBitsError == -101); -static_assert(cpp_core::StatusCode::Configuration::kSetParityError == -102); -static_assert(cpp_core::StatusCode::Configuration::kSetStopBitsError == -103); -static_assert(cpp_core::StatusCode::Configuration::kSetFlowControlError == -104); -static_assert(cpp_core::StatusCode::Configuration::kSetTimeoutError == -105); - -static_assert(cpp_core::StatusCode::Connection::kNotFoundError == -200); -static_assert(cpp_core::StatusCode::Connection::kInvalidHandleError == -201); -static_assert(cpp_core::StatusCode::Connection::kCloseHandleError == -202); - -static_assert(cpp_core::StatusCode::Io::kReadError == -300); -static_assert(cpp_core::StatusCode::Io::kWriteError == -301); -static_assert(cpp_core::StatusCode::Io::kAbortReadError == -302); -static_assert(cpp_core::StatusCode::Io::kAbortWriteError == -303); -static_assert(cpp_core::StatusCode::Io::kBufferError == -304); -static_assert(cpp_core::StatusCode::Io::kClearBufferInError == -305); -static_assert(cpp_core::StatusCode::Io::kClearBufferOutError == -306); - -static_assert(cpp_core::StatusCode::Control::kSetDtrError == -400); -static_assert(cpp_core::StatusCode::Control::kSetRtsError == -401); -static_assert(cpp_core::StatusCode::Control::kGetModemStatusError == -402); -static_assert(cpp_core::StatusCode::Control::kSendBreakError == -403); -static_assert(cpp_core::StatusCode::Control::kGetStateError == -404); -static_assert(cpp_core::StatusCode::Control::kSetStateError == -405); +namespace cpp_core::status_codes::detail::tests +{ + +template struct FakeCategory : CategoryBase> +{ + static constexpr ValueType kCategoryCode = CatCode; + + template static consteval auto call() -> ValueType + { + return CategoryBase::template computeValue(); + } +}; + +// Formula: result == -(kCategoryCode * 100 + LocalCode) +static_assert(FakeCategory<1>::call<0>() == -100); +static_assert(FakeCategory<1>::call<42>() == -142); +static_assert(FakeCategory<3>::call<7>() == -307); + +// Edge: kCategoryCode == 0 -> call<0>() produces 0 (not negative) +static_assert(FakeCategory<0>::call<0>() == 0); +static_assert(FakeCategory<0>::call<1>() == -1); + +// Edge: LocalCode == 99 (max before overflow guard) +static_assert(FakeCategory<2>::call<99>() == -299); + +// Consecutive codes differ by exactly -1 +static_assert(FakeCategory<1>::call<1>() - FakeCategory<1>::call<0>() == -1); + +// Adjacent category ranges don't overlap (last of cat N > first of cat N+1) +static_assert(FakeCategory<1>::call<99>() > FakeCategory<2>::call<0>()); + +// Overflow: largest safe category still produces correct results +inline constexpr ValueType kMaxSafeCat = + (std::numeric_limits::max() - kCategoryMultiplier + 1) / kCategoryMultiplier; +static_assert(kMaxSafeCat > 1'000'000); +static_assert(FakeCategory::call<0>() == -(kMaxSafeCat * kCategoryMultiplier)); +static_assert(FakeCategory::call<99>() > std::numeric_limits::min()); + +} // namespace cpp_core::status_codes::detail::tests