#ifndef MYGRATE_DBTYPES_H #define MYGRATE_DBTYPES_H #include "bitset.h" #include #include #include #include #include struct timespec; namespace MyGrate { template struct printer; template<> struct printer { constexpr static const char * const fmt {"%g"}; }; template<> struct printer { constexpr static const char * const fmt {"%g"}; }; template<> struct printer { constexpr static const char * const fmt {"%hhd"}; }; template<> struct printer { constexpr static const char * const fmt {"%hhu"}; }; template<> struct printer { constexpr static const char * const fmt {"%hd"}; }; template<> struct printer { constexpr static const char * const fmt {"%hu"}; }; template<> struct printer { constexpr static const char * const fmt {"%d"}; }; template<> struct printer { constexpr static const char * const fmt {"%u"}; }; template<> struct printer { constexpr static const char * const fmt {"%ld"}; }; template<> struct printer { constexpr static const char * const fmt {"%lu"}; }; struct Date { inline Date() { } inline Date(uint16_t y, uint8_t m, uint8_t d) : year {y}, month {m}, day {d} { } explicit inline Date(const tm & tm) : Date(boost::numeric_cast(tm.tm_year + 1900), boost::numeric_cast(tm.tm_mon + 1), boost::numeric_cast(tm.tm_mday)) { } bool operator<=>(const Date &) const = default; uint16_t year; uint8_t month; uint8_t day; }; struct Time { inline Time() { } inline Time(uint8_t h, uint8_t m, uint8_t s) : hour {h}, minute {m}, second {s} { } explicit inline Time(const tm & tm) : Time(boost::numeric_cast(tm.tm_hour), boost::numeric_cast(tm.tm_min), boost::numeric_cast(tm.tm_sec)) { } bool operator<=>(const Time &) const = default; uint8_t hour; uint8_t minute; uint8_t second; }; struct DateTime : public Date, public Time { inline DateTime() { } inline DateTime(const Date & d, const Time & t) : Date {d}, Time {t} { } inline DateTime(uint16_t y, uint8_t m, uint8_t d, uint8_t H, uint8_t M, uint8_t S) : DateTime {{y, m, d}, {H, M, S}} { } explicit inline DateTime(const tm & tm) : Date {tm}, Time {tm} { } bool operator<=>(const DateTime &) const = default; }; using Blob = std::span; using DbValueV = std::variant; namespace detail { template concept HasToString = requires { std::to_string(I {}); }; template struct is_false { static constexpr bool value {false}; }; template typename ConceptT> struct SafeExtract { R operator()(const R & i) const { return i; } template R operator()(const I & i) const { if constexpr (ConceptT::value) { return boost::numeric_cast(i); } else { throw std::logic_error("Unreasonable conversion requested"); } } }; struct ToString { std::string operator()(const std::string_view & i) const { return std::string {i}; } std::string operator()(const HasToString auto & i) const { return std::to_string(i); } template std::string operator()(const I &) const { throw std::logic_error("Unreasonable to_string requested"); } }; } class DbValue : public DbValueV { public: using DbValueV::DbValueV; using DbValueV::operator=; template inline auto visit(V && v) const { return std::visit(std::forward(v), static_cast(*this)); } template inline const auto & get() const { return std::get(static_cast(*this)); } template operator R() const { if constexpr (std::is_integral_v) { return visit(detail::SafeExtract {}); } else if constexpr (std::is_floating_point_v) { return visit(detail::SafeExtract {}); } else if constexpr (std::is_same_v) { return get(); } else if constexpr (std::is_same_v) { return visit(detail::ToString {}); } else { static_assert(detail::is_false::value, "Cannot extract one of these"); } } }; } namespace std { std::ostream & operator<<(std::ostream & strm, const MyGrate::DbValueV & v); } #endif