Sync from fork #2

Open
CommanderRedYT wants to merge 5 commits from CommanderRedYT/main into main
6 changed files with 66 additions and 27 deletions

View File

@ -23,18 +23,12 @@ set(sources
src/strutils.cpp
)
set(dependencies
fmt
)
idf_component_register(
INCLUDE_DIRS
src
SRCS
${headers}
${sources}
REQUIRES
${dependencies}
)
target_compile_options(${COMPONENT_TARGET}

View File

@ -33,6 +33,11 @@ struct ArrayView
m_begin{begin}, m_end{begin + size}
{}
template<std::size_t N>
constexpr explicit ArrayView(value_type (&array)[N]) noexcept :
m_begin{array}, m_end{array + N}
{}
constexpr ArrayView(const ArrayView &other) noexcept :
m_begin{other.m_begin}, m_end{other.m_end}
{}

View File

@ -2,14 +2,12 @@
// system includes
#include <cstdio>
// 3rdparty lib includes
#include <fmt/core.h>
#include <format>
namespace cpputils {
std::string toString(ColorHelper color)
{
return fmt::format("#{:02X}{:02X}{:02X}", color.r, color.g, color.b);
return std::format("#{:02X}{:02X}{:02X}", color.r, color.g, color.b);
}
std::expected<ColorHelper, std::string> parseColor(std::string_view str)
@ -21,13 +19,14 @@ std::expected<ColorHelper, std::string> parseColor(std::string_view str)
if (ColorHelper helper; std::sscanf(str.data(), "#%1hhx%1hhx%1hhx", &helper.r, &helper.g, &helper.b) == 3)
{
helper.r <<= 4;
helper.g <<= 4;
helper.b <<= 4;
// #F00 -> #FF0000
helper.r *= 0x11;
helper.g *= 0x11;
helper.b *= 0x11;
return helper;
}
return std::unexpected(fmt::format("invalid color {}", str));
return std::unexpected(std::format("invalid color {}", str));
}
} // namespace cpputils

View File

@ -3,9 +3,7 @@
// system includes
#include <string>
#include <expected>
// 3rdparty lib includes
#include <fmt/core.h>
#include <format>
// local includes
#include "cppmacros.h"
@ -13,6 +11,14 @@
// These macros make it possible to define a typesafe enum with parse and
// toString methods
namespace typesafeenum {
template<typename T>
struct iterateEnum;
template<typename T>
struct parseEnum;
}
#define DECLARE_TYPESAFE_ENUM_HELPER1(name, ...) name __VA_ARGS__ ,
#define DECLARE_TYPESAFE_ENUM_HELPER2(name, ...) case TheEnum::name: return #name;
#define DECLARE_TYPESAFE_ENUM_HELPER3(name, ...) else if (str == CPP_STRINGIFY(name)) return TheEnum::name;
@ -30,14 +36,14 @@
using TheEnum = Name; \
Values(DECLARE_TYPESAFE_ENUM_HELPER2) \
} \
return fmt::format("Unknown " #Name "({})", int(value)); \
return std::format("Unknown " #Name "({})", int(value)); \
} \
inline std::expected<Name, std::string> parse##Name(std::string_view str) \
{ \
using TheEnum = Name; \
if (false) {} \
Values(DECLARE_TYPESAFE_ENUM_HELPER3) \
return std::unexpected(fmt::format("invalid " #Name " ({})", str)); \
return std::unexpected(std::format("invalid " #Name " ({})", str)); \
} \
template<typename T> \
void iterate##Name(T &&cb) \
@ -45,3 +51,25 @@
using TheEnum = Name; \
Values(DECLARE_TYPESAFE_ENUM_HELPER4) \
}
#define DECLARE_GLOBAL_TYPESAFE_ENUM(Name, Derivation, Values) \
DECLARE_TYPESAFE_ENUM(Name, Derivation, Values) \
namespace typesafeenum { \
template<> \
struct iterateEnum<Name> { \
template<typename T> \
static void iterate(T&&cb) \
{ \
return iterate##Name(std::forward<T>(cb)); \
} \
}; \
template<> \
struct parseEnum<Name> { \
static std::expected<Name, std::string> parse(std::string_view str) \
{ \
return parse##Name(str); \
} \
}; \
}
using namespace typesafeenum;

View File

@ -3,12 +3,10 @@
// system includes
#include <cstdint>
#include <cstdio>
#include <expected>
#include <format>
#include <inttypes.h>
#include <string>
#include <expected>
// 3rdparty lib includes
#include <fmt/format.h>
namespace cpputils {
template<typename T> std::expected<T, std::string> fromString(std::string_view str) = delete;
@ -94,4 +92,20 @@ template<> inline std::expected<uint64_t, std::string> fromString<uint64_t>(std:
return std::unexpected(fmt::format("invalid uint64_t {}", str));
return val;
}
template<> inline std::expected<float, std::string> fromString<float>(std::string_view str)
{
float val;
if (std::sscanf(str.data(), "%f", &val) != 1)
return std::unexpected(fmt::format("invalid float {}", str));
return val;
}
template<> inline std::expected<double, std::string> fromString<double>(std::string_view str)
{
double val;
if (std::sscanf(str.data(), "%lf", &val) != 1)
return std::unexpected(fmt::format("invalid double {}", str));
return val;
}
} // namespace cpputils

View File

@ -2,10 +2,9 @@
// system includes
#include <cctype>
#include <format>
#include <assert.h>
// 3rdparty lib includes
#include <fmt/core.h>
namespace cpputils {
namespace {
@ -56,7 +55,7 @@ std::expected<std::basic_string<unsigned char>, std::string> fromHexString(std::
case 'A'...'F': nibbles.nibble0 = c - 'A' + 10; break;
case 'a'...'f': nibbles.nibble0 = c - 'a' + 10; break;
default:
return std::unexpected(fmt::format("invalid character {} at pos {}", c, std::distance(std::begin(hex), iter)));
return std::unexpected(std::format("invalid character {} at pos {}", c, std::distance(std::begin(hex), iter)));
}
iter++;
@ -67,7 +66,7 @@ std::expected<std::basic_string<unsigned char>, std::string> fromHexString(std::
case 'A'...'F': nibbles.nibble1 = c - 'A' + 10; break;
case 'a'...'f': nibbles.nibble1 = c - 'a' + 10; break;
default:
return std::unexpected(fmt::format("invalid character {} at pos {}", c, std::distance(std::begin(hex), iter)));
return std::unexpected(std::format("invalid character {} at pos {}", c, std::distance(std::begin(hex), iter)));
}
iter++;