added expected and fmt for cleaner code/interfaces

This commit is contained in:
2021-08-01 21:41:53 +02:00
parent 89bff1a8dc
commit e38a5ef264
6 changed files with 88 additions and 77 deletions

View File

@@ -1,15 +1,16 @@
#pragma once
// system includes
#include <optional>
#include <string>
// 3rdparty lib includes
#include <tl/expected.hpp>
#include <fmt/core.h>
// local includes
#include "cppmacros.h"
#define CPPTYPESAFEENUM_SHOULD_INLINE
// These two macros make it possible to define a typesafe enum with parse and
// These macros make it possible to define a typesafe enum with parse and
// toString methods
#define DECLARE_TYPESAFE_ENUM_HELPER1(name) name,
@@ -17,7 +18,6 @@
#define DECLARE_TYPESAFE_ENUM_HELPER3(name) else if (str == CPP_STRINGIFY(name)) return TheEnum::name;
#define DECLARE_TYPESAFE_ENUM_HELPER4(name) cb(TheEnum::name, CPP_STRINGIFY(name));
#ifdef CPPTYPESAFEENUM_SHOULD_INLINE
#define DECLARE_TYPESAFE_ENUM(Name, Derivation, Values) \
enum class Name Derivation \
{ \
@@ -30,14 +30,14 @@
using TheEnum = Name; \
Values(DECLARE_TYPESAFE_ENUM_HELPER2) \
} \
return std::string{"Unknown " #Name "("} + std::to_string(int(value)) + ')'; \
return fmt::format("Unknown " #Name "({})", int(value)); \
} \
inline std::optional<Name> parse##Name(std::string_view str) \
inline tl::expected<Name, std::string> parse##Name(std::string_view str) \
{ \
using TheEnum = Name; \
if (false) {} \
Values(DECLARE_TYPESAFE_ENUM_HELPER3) \
return std::nullopt; \
return tl::make_unexpected(fmt::format("invalid " #Name " ({})", str)); \
} \
template<typename T> \
void iterate##Name(T &&cb) \
@@ -47,36 +47,3 @@
}
#define IMPLEMENT_TYPESAFE_ENUM(Name, Derivation, Values)
#else
#define DECLARE_TYPESAFE_ENUM(Name, Derivation, Values) \
enum class Name Derivation \
{ \
Values(DECLARE_TYPESAFE_ENUM_HELPER1) \
}; \
std::string toString(Name value); \
std::optional<Name> parse##Name(std::string_view str); \
template<typename T> \
void iterate##Name(T &&cb) \
{ \
using TheEnum = Name; \
Values(DECLARE_TYPESAFE_ENUM_HELPER4) \
}
#define IMPLEMENT_TYPESAFE_ENUM(Name, Derivation, Values) \
ExportPrefix std::string toString(Name value) \
{ \
switch (value) \
{ \
using TheEnum = Name; \
Values(DECLARE_TYPESAFE_ENUM_HELPER2) \
} \
return std::string{"Unknown " #Name "("} + std::to_string(int(value)) + ')'; \
} \
ExportPrefix std::optional<Name> parse##Name(std::string_view str) \
{ \
using TheEnum = Name; \
if (false) {} \
Values(DECLARE_TYPESAFE_ENUM_HELPER3) \
return std::nullopt; \
}
#endif

View File

@@ -2,74 +2,78 @@
// system includes
#include <cstdint>
#include <optional>
#include <cstdio>
#include <inttypes.h>
#include <string>
// 3rdparty lib includes
#include <tl/expected.hpp>
#include <fmt/format.h>
namespace cpputils {
template<typename T> constexpr std::optional<T> fromString(std::string_view str) = delete;
template<typename T> constexpr tl::expected<T, std::string> fromString(std::string_view str) = delete;
template<> constexpr inline std::optional<int8_t> fromString<int8_t>(std::string_view str)
template<> constexpr inline tl::expected<int8_t, std::string> fromString<int8_t>(std::string_view str)
{
int8_t val{};
if (std::sscanf(str.data(), "%" SCNi8, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNi8, &val) != 1)
return tl::make_unexpected(fmt::format("invalid int8_t {}", str));
return val;
}
template<> constexpr inline std::optional<uint8_t> fromString<uint8_t>(std::string_view str)
template<> constexpr inline tl::expected<uint8_t, std::string> fromString<uint8_t>(std::string_view str)
{
uint8_t val{};
if (std::sscanf(str.data(), "%" SCNu8, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNu8, &val) != 1)
return tl::make_unexpected(fmt::format("invalid uint8_t {}", str));
return val;
}
template<> constexpr inline std::optional<int16_t> fromString<int16_t>(std::string_view str)
template<> constexpr inline tl::expected<int16_t, std::string> fromString<int16_t>(std::string_view str)
{
int16_t val{};
if (std::sscanf(str.data(), "%" SCNi16, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNi16, &val) != 1)
return tl::make_unexpected(fmt::format("invalid int16_t {}", str));
return val;
}
template<> constexpr inline std::optional<uint16_t> fromString<uint16_t>(std::string_view str)
template<> constexpr inline tl::expected<uint16_t, std::string> fromString<uint16_t>(std::string_view str)
{
uint16_t val{};
if (std::sscanf(str.data(), "%" SCNu16, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNu16, &val) != 1)
return tl::make_unexpected(fmt::format("invalid uint16_t {}", str));
return val;
}
template<> constexpr inline std::optional<int32_t> fromString<int32_t>(std::string_view str)
template<> constexpr inline tl::expected<int32_t, std::string> fromString<int32_t>(std::string_view str)
{
int32_t val{};
if (std::sscanf(str.data(), "%" SCNi32, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNi32, &val) != 1)
return tl::make_unexpected(fmt::format("invalid int32_t {}", str));
return val;
}
template<> constexpr inline std::optional<uint32_t> fromString<uint32_t>(std::string_view str)
template<> constexpr inline tl::expected<uint32_t, std::string> fromString<uint32_t>(std::string_view str)
{
uint32_t val{};
if (std::sscanf(str.data(), "%" SCNu32, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNu32, &val) != 1)
return tl::make_unexpected(fmt::format("invalid uint32_t {}", str));
return val;
}
template<> constexpr inline std::optional<int64_t> fromString<int64_t>(std::string_view str)
template<> constexpr inline tl::expected<int64_t, std::string> fromString<int64_t>(std::string_view str)
{
int64_t val{};
if (std::sscanf(str.data(), "%" SCNi64, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNi64, &val) != 1)
return tl::make_unexpected(fmt::format("invalid int64_t {}", str));
return val;
}
template<> constexpr inline std::optional<uint64_t> fromString<uint64_t>(std::string_view str)
template<> constexpr inline tl::expected<uint64_t, std::string> fromString<uint64_t>(std::string_view str)
{
uint64_t val{};
if (std::sscanf(str.data(), "%" SCNu64, &val) == 1)
return val;
return std::nullopt;
if (std::sscanf(str.data(), "%" SCNu64, &val) != 1)
return tl::make_unexpected(fmt::format("invalid uint64_t {}", str));
return val;
}
} // namespace cpputils