#pragma once #include "../errors.h" #include #include #include namespace sqlite::utility { template struct VariantFirstNullable { using type = void; }; template struct VariantFirstNullable { using type = typename VariantFirstNullable::type; }; #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT template struct VariantFirstNullable, Options...> { using type = std::optional; }; #endif template struct VariantFirstNullable, Options...> { using type = std::unique_ptr; }; template struct VariantFirstNullable { using type = std::nullptr_t; }; template inline void variant_select_null(Callback&&callback) { if constexpr(std::is_same_v::type, void>) { throw errors::mismatch("NULL is unsupported by this variant.", "", SQLITE_MISMATCH); } else { std::forward(callback)(typename VariantFirstNullable::type()); } } template struct VariantFirstIntegerable { using type = void; }; template struct VariantFirstIntegerable { using type = typename VariantFirstIntegerable::type; }; #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT template struct VariantFirstIntegerable, Options...> { using type = std::conditional_t::type, T>, std::optional, typename VariantFirstIntegerable::type>; }; #endif template struct VariantFirstIntegerable::type, T>>, std::unique_ptr, Options...> { using type = std::conditional_t::type, T>, std::unique_ptr, typename VariantFirstIntegerable::type>; }; template struct VariantFirstIntegerable { using type = int; }; template struct VariantFirstIntegerable { using type = sqlite_int64; }; template inline auto variant_select_integer(Callback&&callback) { if constexpr(std::is_same_v::type, void>) { throw errors::mismatch("Integer is unsupported by this variant.", "", SQLITE_MISMATCH); } else { std::forward(callback)(typename VariantFirstIntegerable::type()); } } template struct VariantFirstFloatable { using type = void; }; template struct VariantFirstFloatable { using type = typename VariantFirstFloatable::type; }; #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT template struct VariantFirstFloatable, Options...> { using type = std::conditional_t::type, T>, std::optional, typename VariantFirstFloatable::type>; }; #endif template struct VariantFirstFloatable, Options...> { using type = std::conditional_t::type, T>, std::unique_ptr, typename VariantFirstFloatable::type>; }; template struct VariantFirstFloatable { using type = float; }; template struct VariantFirstFloatable { using type = double; }; template inline auto variant_select_float(Callback&&callback) { if constexpr(std::is_same_v::type, void>) { throw errors::mismatch("Real is unsupported by this variant.", "", SQLITE_MISMATCH); } else { std::forward(callback)(typename VariantFirstFloatable::type()); } } template struct VariantFirstTextable { using type = void; }; template struct VariantFirstTextable { using type = typename VariantFirstTextable::type; }; #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT template struct VariantFirstTextable, Options...> { using type = std::conditional_t::type, T>, std::optional, typename VariantFirstTextable::type>; }; #endif template struct VariantFirstTextable, Options...> { using type = std::conditional_t::type, T>, std::unique_ptr, typename VariantFirstTextable::type>; }; template struct VariantFirstTextable { using type = std::string; }; template struct VariantFirstTextable { using type = std::u16string; }; template inline void variant_select_text(Callback&&callback) { if constexpr(std::is_same_v::type, void>) { throw errors::mismatch("Text is unsupported by this variant.", "", SQLITE_MISMATCH); } else { std::forward(callback)(typename VariantFirstTextable::type()); } } template struct VariantFirstBlobable { using type = void; }; template struct VariantFirstBlobable { using type = typename VariantFirstBlobable::type; }; #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT template struct VariantFirstBlobable, Options...> { using type = std::conditional_t::type, T>, std::optional, typename VariantFirstBlobable::type>; }; #endif template struct VariantFirstBlobable, Options...> { using type = std::conditional_t::type, T>, std::unique_ptr, typename VariantFirstBlobable::type>; }; template struct VariantFirstBlobable>, std::vector, Options...> { using type = std::vector; }; template inline auto variant_select_blob(Callback&&callback) { if constexpr(std::is_same_v::type, void>) { throw errors::mismatch("Blob is unsupported by this variant.", "", SQLITE_MISMATCH); } else { std::forward(callback)(typename VariantFirstBlobable::type()); } } template inline auto variant_select(int type) { return [type](auto &&callback) { using Callback = decltype(callback); switch(type) { case SQLITE_NULL: variant_select_null(std::forward(callback)); break; case SQLITE_INTEGER: variant_select_integer(std::forward(callback)); break; case SQLITE_FLOAT: variant_select_float(std::forward(callback)); break; case SQLITE_TEXT: variant_select_text(std::forward(callback)); break; case SQLITE_BLOB: variant_select_blob(std::forward(callback)); break; default:; /* assert(false); */ } }; } }