mirror of
https://github.com/getml/sqlgen.git
synced 2025-12-31 06:30:18 -06:00
Changed to the Parser pattern, just like reflect-cpp
This commit is contained in:
@@ -6,58 +6,14 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "../Result.hpp"
|
||||
#include "../parsing/has_reflection_method.hpp"
|
||||
#include "../parsing/is_nullable.hpp"
|
||||
#include "../parsing/Parser.hpp"
|
||||
|
||||
namespace sqlgen::internal {
|
||||
|
||||
template <class T>
|
||||
Result<T> from_str(const std::optional<std::string>& _str) {
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
|
||||
if constexpr (parsing::has_reflection_method<Type>) {
|
||||
return from_str<typename Type::ReflectionType>(_str).transform(
|
||||
[](auto&& _v) { return Type(std::move(_v)); });
|
||||
|
||||
} else if constexpr (parsing::is_nullable_v<Type>) {
|
||||
if (!_str) {
|
||||
return Type();
|
||||
}
|
||||
|
||||
if constexpr (parsing::is_ptr<Type>::value) {
|
||||
return from_str<typename Type::element_type>(_str).transform(
|
||||
[](auto&& _v) { return Type(std::move(_v)); });
|
||||
|
||||
} else {
|
||||
return from_str<typename Type::value_type>(_str).transform(
|
||||
[](auto&& _v) { return Type(std::move(_v)); });
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!_str) {
|
||||
return error("Encountered NULL value.");
|
||||
}
|
||||
|
||||
if constexpr (std::is_same_v<Type, std::string>) {
|
||||
return *_str;
|
||||
|
||||
} else {
|
||||
try {
|
||||
if constexpr (std::is_floating_point_v<Type>) {
|
||||
return static_cast<Type>(std::stod(*_str));
|
||||
} else if constexpr (std::is_integral_v<Type>) {
|
||||
return static_cast<type>(std::stoll(*_str));
|
||||
} else if (std::is_same_v<Type, bool>) {
|
||||
return std::stoi(*_str) != 0;
|
||||
} else {
|
||||
static_assert(rfl::always_false<Type>, "Unsupported type");
|
||||
}
|
||||
|
||||
} catch (std::exception& e) {
|
||||
return error(e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Parser<Type>::read(_str);
|
||||
}
|
||||
|
||||
} // namespace sqlgen::internal
|
||||
|
||||
@@ -5,30 +5,14 @@
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../parsing/has_reflection_method.hpp"
|
||||
#include "../parsing/is_nullable.hpp"
|
||||
#include "../parsing/Parser.hpp"
|
||||
|
||||
namespace sqlgen::internal {
|
||||
|
||||
template <class T>
|
||||
std::optional<std::string> to_str(const T& _val) {
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
if constexpr (parsing::is_nullable_v<Type>) {
|
||||
if (!_val) {
|
||||
return std::nullopt;
|
||||
} else {
|
||||
return to_str(*_val);
|
||||
}
|
||||
|
||||
} else if constexpr (parsing::has_reflection_method<Type>) {
|
||||
return to_str(_val.reflection());
|
||||
|
||||
} else if constexpr (std::is_same_v<Type, std::string>) {
|
||||
return _val;
|
||||
|
||||
} else {
|
||||
return std::to_string(_val);
|
||||
}
|
||||
return parsing::Parser<Type>::write(_val);
|
||||
}
|
||||
|
||||
} // namespace sqlgen::internal
|
||||
|
||||
12
include/sqlgen/parsing/Parser.hpp
Normal file
12
include/sqlgen/parsing/Parser.hpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_HPP_
|
||||
|
||||
#include "Parser_base.hpp"
|
||||
#include "Parser_default.hpp"
|
||||
#include "Parser_optional.hpp"
|
||||
#include "Parser_primary_key.hpp"
|
||||
#include "Parser_shared_ptr.hpp"
|
||||
#include "Parser_string.hpp"
|
||||
#include "Parser_unique_ptr.hpp"
|
||||
|
||||
#endif
|
||||
11
include/sqlgen/parsing/Parser_base.hpp
Normal file
11
include/sqlgen/parsing/Parser_base.hpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_BASE_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_BASE_HPP_
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
struct Parser;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
119
include/sqlgen/parsing/Parser_default.hpp
Normal file
119
include/sqlgen/parsing/Parser_default.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_DEFAULT_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_DEFAULT_HPP_
|
||||
|
||||
#include <rfl.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../Result.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "../dynamic/types.hpp"
|
||||
#include "Parser_base.hpp"
|
||||
#include "has_reflection_method.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
struct Parser {
|
||||
using Type = std::remove_cvref_t<T>;
|
||||
|
||||
static Result<T> read(const std::optional<std::string>& _str) noexcept {
|
||||
if constexpr (has_reflection_method<Type>) {
|
||||
return Parser<std::remove_cvref_t<typename Type::ReflectionType>>::read(
|
||||
_str)
|
||||
.transform([](auto&& _t) { return Type(std::move(_t)); });
|
||||
|
||||
} else {
|
||||
if (!_str) {
|
||||
return error("NULL value encounted: Numeric value cannot be NULL.");
|
||||
}
|
||||
|
||||
try {
|
||||
if constexpr (std::is_floating_point_v<Type>) {
|
||||
return static_cast<Type>(std::stod(*_str));
|
||||
} else if constexpr (std::is_integral_v<Type>) {
|
||||
return static_cast<Type>(std::stoll(*_str));
|
||||
} else if (std::is_same_v<Type, bool>) {
|
||||
return std::stoi(*_str) != 0;
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<Type>, "Unsupported type");
|
||||
}
|
||||
|
||||
} catch (std::exception& e) {
|
||||
return error(e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<std::string> write(const T& _t) noexcept {
|
||||
if constexpr (has_reflection_method<Type>) {
|
||||
return Parser<std::remove_cvref_t<typename Type::ReflectionType>>::write(
|
||||
_t.reflection());
|
||||
} else {
|
||||
return std::to_string(_t);
|
||||
}
|
||||
}
|
||||
|
||||
static dynamic::Type to_type() noexcept {
|
||||
if constexpr (has_reflection_method<Type>) {
|
||||
return Parser<
|
||||
std::remove_cvref_t<typename Type::ReflectionType>>::to_type();
|
||||
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
return dynamic::types::Boolean{};
|
||||
|
||||
} else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::Int8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::Int16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Int32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Int64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported signed integer.");
|
||||
}
|
||||
|
||||
} else if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::UInt8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::UInt16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::UInt32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::UInt64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported unsigned integer.");
|
||||
}
|
||||
|
||||
} else if constexpr (std::is_floating_point_v<T>) {
|
||||
if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Float32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Float64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>,
|
||||
"Unsupported floating point value.");
|
||||
}
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported type.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
45
include/sqlgen/parsing/Parser_optional.hpp
Normal file
45
include/sqlgen/parsing/Parser_optional.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_OPTIONAL_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_OPTIONAL_HPP_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../Result.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "Parser_base.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
struct Parser<std::optional<T>> {
|
||||
static Result<std::optional<T>> read(
|
||||
const std::optional<std::string>& _str) noexcept {
|
||||
if (!_str) {
|
||||
return std::optional<T>();
|
||||
}
|
||||
return Parser<std::remove_cvref_t<T>>::read(_str).transform(
|
||||
[](auto&& _t) -> std::optional<T> {
|
||||
return std::make_optional<T>(std::move(_t));
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<std::string> write(const std::optional<T>& _o) noexcept {
|
||||
if (!_o) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return Parser<std::remove_cvref_t<T>>::write(*_o);
|
||||
}
|
||||
|
||||
static dynamic::Type to_type() noexcept {
|
||||
return Parser<std::remove_cvref_t<T>>::to_type().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.nullable = true;
|
||||
return _t;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
39
include/sqlgen/parsing/Parser_primary_key.hpp
Normal file
39
include/sqlgen/parsing/Parser_primary_key.hpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_PRIMARY_KEY_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_PRIMARY_KEY_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../PrimaryKey.hpp"
|
||||
#include "../Result.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "Parser_base.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
struct Parser<PrimaryKey<T>> {
|
||||
static Result<PrimaryKey<T>> read(
|
||||
const std::optional<std::string>& _str) noexcept {
|
||||
return Parser<std::remove_cvref_t<T>>::read(_str).transform(
|
||||
[](auto&& _t) -> PrimaryKey<T> {
|
||||
return PrimaryKey<T>(std::move(_t));
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<std::string> write(const PrimaryKey<T>& _p) noexcept {
|
||||
return Parser<std::remove_cvref_t<T>>::write(_p.value());
|
||||
}
|
||||
|
||||
static dynamic::Type to_type() noexcept {
|
||||
return Parser<std::remove_cvref_t<T>>::to_type().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.primary = true;
|
||||
return _t;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
46
include/sqlgen/parsing/Parser_shared_ptr.hpp
Normal file
46
include/sqlgen/parsing/Parser_shared_ptr.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_SHARED_PTR_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_SHARED_PTR_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../Result.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "Parser_base.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
struct Parser<std::shared_ptr<T>> {
|
||||
static Result<std::shared_ptr<T>> read(
|
||||
const std::optional<std::string>& _str) noexcept {
|
||||
if (!_str) {
|
||||
return std::shared_ptr<T>();
|
||||
}
|
||||
return Parser<std::remove_cvref_t<T>>::read(_str).transform(
|
||||
[](auto&& _t) -> std::shared_ptr<T> {
|
||||
return std::make_shared<T>(std::move(_t));
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<std::string> write(
|
||||
const std::shared_ptr<T>& _ptr) noexcept {
|
||||
if (!_ptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return Parser<std::remove_cvref_t<T>>::write(*_ptr);
|
||||
}
|
||||
|
||||
static dynamic::Type to_type() noexcept {
|
||||
return Parser<std::remove_cvref_t<T>>::to_type().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.nullable = true;
|
||||
return _t;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
33
include/sqlgen/parsing/Parser_string.hpp
Normal file
33
include/sqlgen/parsing/Parser_string.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_STRING_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_STRING_HPP_
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../Result.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "../dynamic/types.hpp"
|
||||
#include "Parser_base.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <>
|
||||
struct Parser<std::string> {
|
||||
static Result<std::string> read(
|
||||
const std::optional<std::string>& _str) noexcept {
|
||||
if (!_str) {
|
||||
return error("NULL value encounted: String value cannot be NULL.");
|
||||
}
|
||||
return *_str;
|
||||
}
|
||||
|
||||
static std::optional<std::string> write(const std::string& _str) noexcept {
|
||||
return _str;
|
||||
}
|
||||
|
||||
static dynamic::Type to_type() noexcept { return dynamic::types::Text{}; }
|
||||
};
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
46
include/sqlgen/parsing/Parser_unique_ptr.hpp
Normal file
46
include/sqlgen/parsing/Parser_unique_ptr.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef SQLGEN_PARSING_PARSER_UNIQUE_PTR_HPP_
|
||||
#define SQLGEN_PARSING_PARSER_UNIQUE_PTR_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../Result.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "Parser_base.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
struct Parser<std::unique_ptr<T>> {
|
||||
static Result<std::unique_ptr<T>> read(
|
||||
const std::optional<std::string>& _str) noexcept {
|
||||
if (!_str) {
|
||||
return std::unique_ptr<T>();
|
||||
}
|
||||
return Parser<std::remove_cvref_t<T>>::read(_str).transform(
|
||||
[](auto&& _t) -> std::unique_ptr<T> {
|
||||
return std::make_unique<T>(std::move(_t));
|
||||
});
|
||||
}
|
||||
|
||||
static std::optional<std::string> write(
|
||||
const std::unique_ptr<T>& _ptr) noexcept {
|
||||
if (!_ptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return Parser<std::remove_cvref_t<T>>::write(*_ptr);
|
||||
}
|
||||
|
||||
static dynamic::Type to_type() noexcept {
|
||||
return Parser<std::remove_cvref_t<T>>::to_type().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.nullable = true;
|
||||
return _t;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "../dynamic/Column.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "../dynamic/types.hpp"
|
||||
#include "Parser.hpp"
|
||||
#include "has_reflection_method.hpp"
|
||||
#include "is_nullable.hpp"
|
||||
#include "is_primary_key.hpp"
|
||||
@@ -22,76 +23,7 @@ std::string to_colname() {
|
||||
template <class Type>
|
||||
dynamic::Type to_type() {
|
||||
using T = std::remove_cvref_t<Type>;
|
||||
if constexpr (is_primary_key_v<T>) {
|
||||
return to_type<typename T::ReflectionType>().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.primary = true;
|
||||
return _t;
|
||||
});
|
||||
|
||||
} else if constexpr (is_nullable_v<T>) {
|
||||
const auto set_nullable = [](auto _t) -> dynamic::Type {
|
||||
_t.properties.nullable = true;
|
||||
return _t;
|
||||
};
|
||||
if constexpr (is_ptr<T>::value) {
|
||||
return to_type<typename T::element_type>().visit(set_nullable);
|
||||
} else {
|
||||
return to_type<typename T::value_type>().visit(set_nullable);
|
||||
}
|
||||
|
||||
} else if constexpr (has_reflection_method<T>) {
|
||||
return to_type<typename Type::ReflectionType>();
|
||||
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
return dynamic::types::Boolean{};
|
||||
|
||||
} else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::Int8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::Int16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Int32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Int64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported signed integer.");
|
||||
}
|
||||
} else if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::UInt8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::UInt16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::UInt32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::UInt64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported unsigned integer.");
|
||||
}
|
||||
} else if constexpr (std::is_floating_point_v<T>) {
|
||||
if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Float32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Float64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>,
|
||||
"Unsupported floating point value.");
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
return dynamic::types::Text{};
|
||||
}
|
||||
return Parser<T>::to_type();
|
||||
}
|
||||
|
||||
template <class FieldType>
|
||||
|
||||
Reference in New Issue
Block a user