Skip to content

Commit 06f1351

Browse files
Katze719Mqxx
andauthored
Refactor/better error codes (#18)
* 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. * 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. * 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. * 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. * Remove the Monitor struct from status_codes.h to streamline status code definitions and improve code clarity. * 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. * 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. * Update kCategoryMultiplier initialization in CategoryBase template - Changed the initialization of kCategoryMultiplier from an assignment to a uniform initialization syntax, enhancing code consistency and clarity. * 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. * 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. * 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. * Update include/cpp_core/status_code.h Co-authored-by: Mqx <62719703+Mqxx@users.noreply.github.com> * 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. * test: move status code static asserts into compile test --------- Co-authored-by: Mqx <62719703+Mqxx@users.noreply.github.com>
1 parent 62b5b39 commit 06f1351

11 files changed

Lines changed: 242 additions & 155 deletions

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ target_compile_features(cpp_core INTERFACE cxx_std_23)
4949
set(CMAKE_CXX_MODULE_STD 23)
5050
set(CMAKE_CXX_MODULE_EXTENSIONS OFF)
5151

52+
include(CTest)
53+
54+
if(BUILD_TESTING)
55+
add_library(cpp_core_status_code_compile_test OBJECT tests/status_code_compile_test.cpp)
56+
target_link_libraries(cpp_core_status_code_compile_test PRIVATE cpp_core::cpp_core)
57+
endif()
58+
5259
# Install rules --------------------------------------------------------------
5360
include(GNUInstallDirs)
5461

include/cpp_core.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414

1515
#include "cpp_core/error_callback.h"
1616
#include "cpp_core/serial.h"
17-
#include "cpp_core/status_codes.h"
17+
#include "cpp_core/status_code.h"
1818
#include "cpp_core/version.hpp"

include/cpp_core/error_handling.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include "status_codes.h"
3+
#include "status_code.h"
44

55
#include <concepts>
66
#include <string>

include/cpp_core/interface/serial_abort_read.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ extern "C"
1212
* @brief Abort a blocking read operation running in a different thread.
1313
*
1414
* The target read function returns immediately with
15-
* ::cpp_core::StatusCodes::kAbortReadError.
15+
* ::cpp_core::StatusCode::Io::kAbortReadError.
1616
*
1717
* @param handle Port handle.
1818
* @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`.
19-
* @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error.
19+
* @return 0 on success or a negative error code from ::cpp_core::StatusCode on error.
2020
*/
2121
MODULE_API auto serialAbortRead(int64_t handle, ErrorCallbackT error_callback = nullptr) -> int;
2222

include/cpp_core/interface/serial_abort_write.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ extern "C"
1212
* @brief Abort a blocking write operation running in a different thread.
1313
*
1414
* The target write function returns immediately with
15-
* ::cpp_core::StatusCodes::kAbortWriteError.
15+
* ::cpp_core::StatusCode::Io::kAbortWriteError.
1616
*
1717
* @param handle Port handle.
1818
* @param error_callback [optional] Callback to invoke on error. Defined in error_callback.h. Default is `nullptr`.
19-
* @return 0 on success or a negative error code from ::cpp_core::StatusCodes on error.
19+
* @return 0 on success or a negative error code from ::cpp_core::StatusCode on error.
2020
*/
2121
MODULE_API auto serialAbortWrite(int64_t handle, ErrorCallbackT error_callback = nullptr) -> int;
2222

include/cpp_core/result.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#pragma once
22

3-
#include "status_codes.h"
3+
#include "status_code.h"
44

55
#include <concepts>
66
#include <expected>

include/cpp_core/status_code.h

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <string_view>
5+
6+
namespace cpp_core::status_codes
7+
{
8+
9+
namespace detail
10+
{
11+
12+
using ValueType = std::int64_t;
13+
14+
inline constexpr ValueType kCategoryMultiplier{100};
15+
16+
template <typename Category, ValueType NumericValue> struct Code
17+
{
18+
static constexpr ValueType kValue = NumericValue;
19+
std::string_view kName; // NOLINT(readability-identifier-naming)
20+
21+
// NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
22+
constexpr operator ValueType() const noexcept
23+
{
24+
return kValue;
25+
}
26+
[[nodiscard]] constexpr auto value() const noexcept -> ValueType
27+
{
28+
return kValue;
29+
}
30+
[[nodiscard]] constexpr auto name() const noexcept -> std::string_view
31+
{
32+
return kName;
33+
}
34+
[[nodiscard]] constexpr auto category() const noexcept -> std::string_view
35+
{
36+
return Category::kCategoryName;
37+
}
38+
};
39+
40+
template <typename Derived> struct CategoryBase
41+
{
42+
private:
43+
constexpr CategoryBase() = default;
44+
45+
protected:
46+
template <ValueType LocalCode> static consteval auto computeValue() -> ValueType
47+
{
48+
static_assert(Derived::kCategoryCode >= 0, "Category code must not be negative");
49+
static_assert(LocalCode >= 0, "Code index must not be negative");
50+
static_assert(LocalCode < kCategoryMultiplier, "Category overflow (max 99 codes)");
51+
static_assert(Derived::kCategoryCode <=
52+
(std::numeric_limits<ValueType>::max() - kCategoryMultiplier + 1) / kCategoryMultiplier,
53+
"Category code too large, multiplication would overflow");
54+
return -((Derived::kCategoryCode * kCategoryMultiplier) + LocalCode);
55+
}
56+
57+
template <ValueType LocalCode> using Code = detail::Code<Derived, computeValue<LocalCode>()>;
58+
59+
friend Derived;
60+
};
61+
62+
} // namespace detail
63+
64+
struct StatusCode
65+
{
66+
using ValueType = detail::ValueType;
67+
static constexpr ValueType kSuccess = 0;
68+
69+
struct Configuration : detail::CategoryBase<Configuration>
70+
{
71+
static constexpr ValueType kCategoryCode = 1;
72+
static constexpr std::string_view kCategoryName{"Configuration"};
73+
74+
static constexpr Code<0> kSetBaudrateError{"SetBaudrateError"};
75+
static constexpr Code<1> kSetDataBitsError{"SetDataBitsError"};
76+
static constexpr Code<2> kSetParityError{"SetParityError"};
77+
static constexpr Code<3> kSetStopBitsError{"SetStopBitsError"};
78+
static constexpr Code<4> kSetFlowControlError{"SetFlowControlError"};
79+
static constexpr Code<5> kSetTimeoutError{"SetTimeoutError"};
80+
};
81+
82+
struct Connection : detail::CategoryBase<Connection>
83+
{
84+
static constexpr ValueType kCategoryCode = 2;
85+
static constexpr std::string_view kCategoryName{"Connection"};
86+
87+
static constexpr Code<0> kNotFoundError{"NotFoundError"};
88+
static constexpr Code<1> kInvalidHandleError{"InvalidHandleError"};
89+
static constexpr Code<2> kCloseHandleError{"CloseHandleError"};
90+
};
91+
92+
struct Io : detail::CategoryBase<Io>
93+
{
94+
static constexpr ValueType kCategoryCode = 3;
95+
static constexpr std::string_view kCategoryName{"Io"};
96+
97+
static constexpr Code<0> kReadError{"ReadError"};
98+
static constexpr Code<1> kWriteError{"WriteError"};
99+
static constexpr Code<2> kAbortReadError{"AbortReadError"};
100+
static constexpr Code<3> kAbortWriteError{"AbortWriteError"};
101+
static constexpr Code<4> kBufferError{"BufferError"};
102+
static constexpr Code<5> kClearBufferInError{"ClearBufferInError"};
103+
static constexpr Code<6> kClearBufferOutError{"ClearBufferOutError"};
104+
};
105+
106+
struct Control : detail::CategoryBase<Control>
107+
{
108+
static constexpr ValueType kCategoryCode = 4;
109+
static constexpr std::string_view kCategoryName{"Control"};
110+
111+
static constexpr Code<0> kSetDtrError{"SetDtrError"};
112+
static constexpr Code<1> kSetRtsError{"SetRtsError"};
113+
static constexpr Code<2> kGetModemStatusError{"GetModemStatusError"};
114+
static constexpr Code<3> kSendBreakError{"SendBreakError"};
115+
static constexpr Code<4> kGetStateError{"GetStateError"};
116+
static constexpr Code<5> kSetStateError{"SetStateError"};
117+
};
118+
119+
[[nodiscard]] static constexpr auto isError(ValueType code) noexcept -> bool
120+
{
121+
return code < 0;
122+
}
123+
[[nodiscard]] static constexpr auto isSuccess(ValueType code) noexcept -> bool
124+
{
125+
return code >= 0;
126+
}
127+
template <typename Category> [[nodiscard]] static constexpr auto belongsTo(ValueType code) noexcept -> bool
128+
{
129+
return code < 0 && (-code) / detail::kCategoryMultiplier == Category::kCategoryCode;
130+
}
131+
};
132+
133+
} // namespace cpp_core::status_codes
134+
135+
namespace cpp_core
136+
{
137+
using StatusCodes = ::cpp_core::status_codes::detail::ValueType;
138+
using ::cpp_core::status_codes::StatusCode;
139+
} // namespace cpp_core

include/cpp_core/status_codes.h

Lines changed: 0 additions & 31 deletions
This file was deleted.

include/cpp_core/status_codes.hpp

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)