Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/cpp_core/interface/serial_abort_read.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions include/cpp_core/interface/serial_abort_write.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
165 changes: 165 additions & 0 deletions include/cpp_core/status_code.h
Comment thread
Katze719 marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#pragma once

#include <cstdint>
#include <string_view>

namespace cpp_core::status_codes
{

namespace detail
{

using ValueType = std::int64_t;

inline constexpr ValueType kCategoryMultiplier{100};

template <typename Category, ValueType NumericValue> 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
{
return kValue;
}
[[nodiscard]] constexpr auto value() const noexcept -> ValueType
{
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 <typename Derived> struct CategoryBase
{
private:
constexpr CategoryBase() = default;

protected:
template <ValueType LocalCode> static consteval auto computeValue() -> ValueType
{
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 <ValueType LocalCode> using Code = detail::Code<Derived, computeValue<LocalCode>()>;

friend Derived;
};

} // namespace detail

struct StatusCode
{
using ValueType = detail::ValueType;
static constexpr ValueType kSuccess = 0;

struct Configuration : detail::CategoryBase<Configuration>
{
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<Connection>
{
static constexpr ValueType kCategoryCode = 2;
static constexpr std::string_view kCategoryName{"Connection"};

static constexpr Code<0> kNotFoundError{"NotFoundError"};
static constexpr Code<1> kInvalidHandleError{"InvalidHandleError"};
static constexpr Code<2> kCloseHandleError{"CloseHandleError"};
};

struct Io : detail::CategoryBase<Io>
{
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<Control>
{
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(ValueType code) noexcept -> bool
{
return code >= 0;
}
template <typename Category> [[nodiscard]] static constexpr auto belongsTo(ValueType code) noexcept -> bool
{
return code < 0 && (-code) / detail::kCategoryMultiplier == Category::kCategoryCode;
}
};

} // namespace cpp_core::status_codes

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));

Comment thread
Katze719 marked this conversation as resolved.
Outdated
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);
Comment thread
Mqxx marked this conversation as resolved.
Outdated
31 changes: 0 additions & 31 deletions include/cpp_core/status_codes.h

This file was deleted.

108 changes: 0 additions & 108 deletions include/cpp_core/status_codes.hpp

This file was deleted.

21 changes: 13 additions & 8 deletions include/cpp_core/validation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ constexpr auto validateHandle(int64_t handle, Callback &&error_callback) -> Ret
{
if (handle <= 0 || handle > std::numeric_limits<int>::max())
{
return failMsg<Ret>(std::forward<Callback>(error_callback), StatusCodes::kInvalidHandleError, "Invalid handle");
return failMsg<Ret>(std::forward<Callback>(error_callback),
static_cast<StatusCodes>(StatusCode::Connection::kInvalidHandleError), "Invalid handle");
}
return static_cast<Ret>(StatusCodes::kSuccess);
return static_cast<Ret>(StatusCode::kSuccess);
}

/**
Expand All @@ -33,20 +34,23 @@ constexpr auto validateOpenParams(void *port, int baudrate, int data_bits, Callb
{
if (port == nullptr)
{
return failMsg<Ret>(std::forward<Callback>(error_callback), StatusCodes::kNotFoundError,
return failMsg<Ret>(std::forward<Callback>(error_callback),
static_cast<StatusCodes>(StatusCode::Connection::kNotFoundError),
"Port parameter is nullptr");
}
if (baudrate < 300)
{
return failMsg<Ret>(std::forward<Callback>(error_callback), StatusCodes::kSetStateError,
return failMsg<Ret>(std::forward<Callback>(error_callback),
static_cast<StatusCodes>(StatusCode::Control::kSetStateError),
"Invalid baudrate: must be >= 300");
}
if (data_bits < 5 || data_bits > 8)
{
return failMsg<Ret>(std::forward<Callback>(error_callback), StatusCodes::kSetStateError,
return failMsg<Ret>(std::forward<Callback>(error_callback),
static_cast<StatusCodes>(StatusCode::Control::kSetStateError),
"Invalid data bits: must be 5-8");
}
return static_cast<Ret>(StatusCodes::kSuccess);
return static_cast<Ret>(StatusCode::kSuccess);
}

// Validate buffer + size for read/write calls.
Expand All @@ -55,10 +59,11 @@ constexpr auto validateBuffer(const void *buffer, int buffer_size, Callback &&er
{
if (buffer == nullptr || buffer_size <= 0)
{
return failMsg<Ret>(std::forward<Callback>(error_callback), StatusCodes::kBufferError,
return failMsg<Ret>(std::forward<Callback>(error_callback),
static_cast<StatusCodes>(StatusCode::Io::kBufferError),
"Invalid buffer or buffer_size");
}
return static_cast<Ret>(StatusCodes::kSuccess);
return static_cast<Ret>(StatusCode::kSuccess);
}

// Clamp timeout to non-negative.
Expand Down