| @@ -0,0 +1,6 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/schema.h> | |||||
| #include <cpphibernate/types.h> | |||||
| @@ -0,0 +1,56 @@ | |||||
| #pragma once | |||||
| #include <boost/hana.hpp> | |||||
| #include <cpputils/mp/core.h> | |||||
| #define cpphibernate_equality_comparable() \ | |||||
| template<typename T_other> \ | |||||
| constexpr decltype(auto) operator==(T_other&&) const \ | |||||
| { \ | |||||
| return ::boost::hana::type<::utl::mp::decay_t<decltype(*this)>> { } == \ | |||||
| ::boost::hana::type<::utl::mp::decay_t<T_other>> { }; \ | |||||
| } \ | |||||
| \ | |||||
| template<typename T_other> \ | |||||
| constexpr decltype(auto) operator!=(T_other&&) const \ | |||||
| { \ | |||||
| return ::boost::hana::type<::utl::mp::decay_t<decltype(*this)>> { } != \ | |||||
| ::boost::hana::type<::utl::mp::decay_t<T_other>> { }; \ | |||||
| } | |||||
| #define cpphibernate_constructable(name, value) \ | |||||
| name() = value | |||||
| #define cpphibernate_copyable(name, value) \ | |||||
| name(const name&) = value; \ | |||||
| name& operator=(const name&) = value | |||||
| #define cpphibernate_moveable(name, value) \ | |||||
| name(name&&) = value; \ | |||||
| name& operator=(name&&) = value | |||||
| #define cpphibernate_define_namespace_beg(parent, name) \ | |||||
| parent { \ | |||||
| namespace name | |||||
| #define cpphibernate_define_namespace_end(parent) \ | |||||
| } \ | |||||
| parent | |||||
| #define beg_namespace_cpphibernate namespace cpphibernate | |||||
| #define end_namespace_cpphibernate | |||||
| #define beg_namespace_cpphibernate_schema cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, schema) | |||||
| #define end_namespace_cpphibernate_schema cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| #define beg_namespace_cpphibernate_misc cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, misc) | |||||
| #define end_namespace_cpphibernate_misc cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||||
| beg_namespace_cpphibernate | |||||
| { | |||||
| namespace mp = ::utl::mp; | |||||
| namespace hana = ::boost::hana; | |||||
| } | |||||
| end_namespace_cpphibernate | |||||
| @@ -0,0 +1,5 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/misc/general.h> | |||||
| #include <cpphibernate/misc/meta.h> | |||||
| #include <cpphibernate/misc/wrap.h> | |||||
| @@ -0,0 +1,19 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_misc | |||||
| { | |||||
| /* make_generic_predicate */ | |||||
| template<template<typename...> class T_builder> | |||||
| struct make_generic_predicate | |||||
| { | |||||
| template<typename... T_args> | |||||
| constexpr decltype(auto) operator()(T_args&&... args) const | |||||
| { return T_builder<mp::list<T_args...>>::apply(std::forward<T_args>(args)...); } | |||||
| }; | |||||
| } | |||||
| end_namespace_cpphibernate_misc | |||||
| @@ -0,0 +1,130 @@ | |||||
| #pragma once | |||||
| #include <list> | |||||
| #include <vector> | |||||
| #include <memory> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpputils/container/nullable.h> | |||||
| beg_namespace_cpphibernate_misc | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* is_container_impl */ | |||||
| template<typename T> | |||||
| struct is_container_impl | |||||
| : public mp::c_false_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_container_impl<std::list<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_container_impl<std::vector<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| /* is_nullable_impl */ | |||||
| template<typename T> | |||||
| struct is_nullable_impl | |||||
| : public mp::c_false_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_nullable_impl<utl::nullable<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_nullable_impl<std::unique_ptr<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_nullable_impl<std::shared_ptr<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| /* is_pointer_impl */ | |||||
| template<typename T> | |||||
| struct is_pointer_impl | |||||
| : public mp::c_false_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_pointer_impl<std::unique_ptr<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_pointer_impl<std::shared_ptr<T>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| /* real_dataset_impl */ | |||||
| template<typename T, typename = void> | |||||
| struct real_dataset_impl | |||||
| { using type = T; }; | |||||
| template<typename T> | |||||
| struct real_dataset_impl<utl::nullable<T>, void> | |||||
| { using type = typename real_dataset_impl<T>::type; }; | |||||
| template<typename T> | |||||
| struct real_dataset_impl<std::unique_ptr<T>, void> | |||||
| { using type = typename real_dataset_impl<T>::type; }; | |||||
| template<typename T> | |||||
| struct real_dataset_impl<std::shared_ptr<T>, void> | |||||
| { using type = typename real_dataset_impl<T>::type; }; | |||||
| template<typename T> | |||||
| struct real_dataset_impl<std::vector<T>, void> | |||||
| { using type = typename real_dataset_impl<T>::type; }; | |||||
| template<typename T> | |||||
| struct real_dataset_impl<std::list<T>, void> | |||||
| { using type = typename real_dataset_impl<T>::type; }; | |||||
| template<typename T_from, typename T_to, typename = void> | |||||
| struct change_dataset_type_impl | |||||
| { using type = T_to; }; | |||||
| template<template<typename...> class X, typename T_from, typename T_to> | |||||
| struct change_dataset_type_impl<X<T_from>, T_to, void> | |||||
| { using type = X<T_to>; }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_container | |||||
| : public __impl::is_container_impl<T> | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_nullable | |||||
| : public __impl::is_nullable_impl<T> | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_pointer | |||||
| : public __impl::is_pointer_impl<T> | |||||
| { }; | |||||
| template<typename T> | |||||
| using real_dataset_t = typename __impl::real_dataset_impl<T>::type; | |||||
| } | |||||
| end_namespace_cpphibernate_misc | |||||
| @@ -0,0 +1,44 @@ | |||||
| #pragma once | |||||
| #include <list> | |||||
| #include <vector> | |||||
| #include <memory> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpputils/container/nullable.h> | |||||
| beg_namespace_cpphibernate_misc | |||||
| { | |||||
| template<typename T> | |||||
| using unwrap_t = typename T::type; | |||||
| template<typename T> | |||||
| using decay_unwrap_t = typename mp::decay_t<T>::type; | |||||
| namespace __impl | |||||
| { | |||||
| struct wrap_t | |||||
| { | |||||
| template<typename T> | |||||
| constexpr decltype(auto) operator()(T) const noexcept | |||||
| { return hana::type_c<T>; } | |||||
| }; | |||||
| struct unwrapped_t | |||||
| { | |||||
| template<typename T> | |||||
| constexpr decltype(auto) operator()(T) const noexcept | |||||
| { return unwrap_t<T> { }; } | |||||
| }; | |||||
| } | |||||
| constexpr decltype(auto) wrap = __impl::wrap_t { }; | |||||
| constexpr decltype(auto) unwrap = __impl::unwrapped_t { }; | |||||
| } | |||||
| end_namespace_cpphibernate_misc | |||||
| @@ -0,0 +1,13 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/schema/attribute.h> | |||||
| #include <cpphibernate/schema/attributes.h> | |||||
| #include <cpphibernate/schema/field.h> | |||||
| #include <cpphibernate/schema/fields.h> | |||||
| #include <cpphibernate/schema/getter.h> | |||||
| #include <cpphibernate/schema/macros.h> | |||||
| #include <cpphibernate/schema/print.h> | |||||
| #include <cpphibernate/schema/schema.h> | |||||
| #include <cpphibernate/schema/setter.h> | |||||
| #include <cpphibernate/schema/table.h> | |||||
| #include <cpphibernate/schema/tables.h> | |||||
| @@ -0,0 +1,60 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* attribute_t */ | |||||
| template<typename T_inner> | |||||
| struct attribute_t | |||||
| : public T_inner | |||||
| { | |||||
| using inner_type = T_inner; | |||||
| using this_type = attribute_t<inner_type>; | |||||
| cpphibernate_equality_comparable(); | |||||
| }; | |||||
| struct hex_t { static constexpr decltype(auto) name = "hex"; }; | |||||
| struct compress_t { static constexpr decltype(auto) name = "compress"; }; | |||||
| struct primary_key_t { static constexpr decltype(auto) name = "primary_key"; }; | |||||
| } | |||||
| namespace attribute | |||||
| { | |||||
| using hex_type = __impl::attribute_t<__impl::hex_t>; | |||||
| using compress_type = __impl::attribute_t<__impl::compress_t>; | |||||
| using primary_key_type = __impl::attribute_t<__impl::primary_key_t>; | |||||
| /** value is stored as hexadecimal string, and will be converted to its binary form on read */ | |||||
| constexpr hex_type hex { }; | |||||
| /** value is stored as compressed binary, and will be uncompressed on read */ | |||||
| constexpr compress_type compress { }; | |||||
| /** this value represents a primary key (it must be stored in the dataset to be able to do the operations on the database) */ | |||||
| constexpr primary_key_type primary_key { }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_attribute | |||||
| : public mp::is_specialization_of<T, __impl::attribute_t> | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct all_are_attribures | |||||
| : public mp::all_true<is_attribute<T>::value...> | |||||
| { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,63 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/schema/attribute.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* attributes_t */ | |||||
| template<typename... T_attributes> | |||||
| using attributes_t = hana::basic_tuple<T_attributes...>; | |||||
| /* is_attributes_impl */ | |||||
| template<typename T, typename = void> | |||||
| struct is_attributes_impl | |||||
| : mp::c_false_t | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct is_attributes_impl<attributes_t<T...>, mp::enable_if<all_are_attribures<T...>>> | |||||
| : mp::c_true_t | |||||
| { }; | |||||
| /* attributes_builder */ | |||||
| template<typename T, typename = void> | |||||
| struct attributes_builder | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&...) | |||||
| { static_assert(sizeof...(T_args) == -1, "Invalid parameters for hibernate::schema::make_attributes(...)!"); } | |||||
| }; | |||||
| template<typename... T> | |||||
| struct attributes_builder<mp::list<T...>, mp::enable_if_c< | |||||
| all_are_attribures<mp::decay_t<T>...>::value>> | |||||
| { | |||||
| template<typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&...) | |||||
| { return attributes_t<mp::decay_t<T_args>...> { }; } | |||||
| }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_attributes | |||||
| : public __impl::is_attributes_impl<T> | |||||
| { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_attributes = misc::make_generic_predicate<__impl::attributes_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,115 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/misc.h> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/schema/getter.h> | |||||
| #include <cpphibernate/schema/setter.h> | |||||
| #include <cpputils/misc/indent.h> | |||||
| #include <cpputils/misc/type_helper.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* field_t */ | |||||
| template<typename T_name, typename T_getter, typename T_setter, typename T_attributes> | |||||
| struct field_t | |||||
| { | |||||
| using name_type = T_name; | |||||
| using getter_type = T_getter; | |||||
| using setter_type = T_setter; | |||||
| using attributes_type = T_attributes; | |||||
| using this_type = field_t<name_type, getter_type, setter_type, attributes_type>; | |||||
| name_type name; | |||||
| getter_type getter; | |||||
| setter_type setter; | |||||
| attributes_type attributes; | |||||
| constexpr field_t( | |||||
| T_name&& p_name, | |||||
| T_getter&& p_getter, | |||||
| T_setter&& p_setter, | |||||
| T_attributes&& p_attributes) | |||||
| : name (std::forward<T_name> (p_name)) | |||||
| , getter (std::forward<T_getter> (p_getter)) | |||||
| , setter (std::forward<T_setter> (p_setter)) | |||||
| , attributes (std::forward<T_attributes>(p_attributes)) | |||||
| { } | |||||
| cpphibernate_copyable(field_t, delete); | |||||
| cpphibernate_moveable(field_t, default); | |||||
| cpphibernate_equality_comparable(); | |||||
| inline void print(std::ostream& os) const | |||||
| { | |||||
| using namespace ::utl; | |||||
| using value_type = typename mp::decay_t<getter_type>::value_type; | |||||
| using dataset_type = misc::real_dataset_t<value_type>; | |||||
| size_t index = 0; | |||||
| os << indent << '{' | |||||
| << incindent | |||||
| << indent << "\"name\": \"" << name << "\"," | |||||
| << indent << "\"value_type\": \"" << utl::type_helper<value_type>::name() << "\"" | |||||
| << indent << "\"dataset_type\": \"" << utl::type_helper<dataset_type>::name() << "\"" | |||||
| << indent << "\"attributes\": " | |||||
| << indent << '[' | |||||
| << incindent; | |||||
| hana::for_each(attributes, [&](auto& attrib){ | |||||
| if (index++ > 0) os << ","; | |||||
| os << indent << attrib.name; | |||||
| }); | |||||
| os << decindent | |||||
| << indent << ']' | |||||
| << decindent | |||||
| << indent << '}'; | |||||
| } | |||||
| }; | |||||
| /* field_builder */ | |||||
| template<typename X, typename = void> | |||||
| struct field_builder | |||||
| { | |||||
| template <typename ...T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_field(...)!"); } | |||||
| }; | |||||
| template<typename T_name, typename T_getter, typename T_setter, typename T_attributes> | |||||
| struct field_builder<mp::list<T_name, T_getter, T_setter, T_attributes>, mp::enable_if_c< | |||||
| is_getter<mp::decay_t<T_getter>>::value | |||||
| && is_setter<mp::decay_t<T_setter>>::value | |||||
| && is_attributes<mp::decay_t<T_attributes>>::value>> | |||||
| { | |||||
| using field_type = field_t<T_name, T_getter, T_setter, T_attributes>; | |||||
| static constexpr decltype(auto) apply(T_name&& name, T_getter&& getter, T_setter&& setter, T_attributes&& attributes) | |||||
| { return field_type(std::forward<T_name>(name), std::forward<T_getter>(getter), std::forward<T_setter>(setter), std::forward<T_attributes>(attributes)); } | |||||
| }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_field | |||||
| : public mp::is_specialization_of<T, __impl::field_t> | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct all_are_fields | |||||
| : public mp::all_true<is_field<T>::value...> | |||||
| { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_field = misc::make_generic_predicate<__impl::field_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,62 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc/general.h> | |||||
| #include <cpphibernate/schema/field.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* fields_t */ | |||||
| template<typename... T_fields> | |||||
| using fields_t = hana::basic_tuple<T_fields...>; | |||||
| /* is_fields_impl */ | |||||
| template<typename T, typename = void> | |||||
| struct is_fields_impl | |||||
| : public mp::c_false_t | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct is_fields_impl<fields_t<T...>, mp::enable_if<all_are_fields<T...>>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| /* fields_builder */ | |||||
| template <typename T, typename = void> | |||||
| struct fields_builder | |||||
| { | |||||
| template <typename ...T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_fields(...)!"); } | |||||
| }; | |||||
| template<typename... T> | |||||
| struct fields_builder<mp::list<T...>, mp::enable_if<all_are_fields<T...>>> | |||||
| { | |||||
| template <typename ...T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { return fields_t<T_args...>(std::forward<T_args>(args)...); } | |||||
| }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_fields : | |||||
| public __impl::is_fields_impl<T> | |||||
| { }; | |||||
| /* constructors */ | |||||
| constexpr decltype(auto) make_fields = misc::make_generic_predicate<__impl::fields_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,206 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc/general.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* getter_t */ | |||||
| template<typename T_value> | |||||
| struct getter_t | |||||
| { | |||||
| using value_type = T_value; | |||||
| }; | |||||
| /* getter_none_t */ | |||||
| struct getter_none_t | |||||
| : public getter_t<void> | |||||
| { | |||||
| using base_type = getter_t<void>; | |||||
| using value_type = typename base_type::value_type; | |||||
| cpphibernate_constructable(getter_none_t, default); | |||||
| cpphibernate_copyable (getter_none_t, delete); | |||||
| cpphibernate_moveable (getter_none_t, default); | |||||
| }; | |||||
| /* getter_member_var_t */ | |||||
| template<typename T_dataset, typename T_value, typename T_member> | |||||
| struct getter_member_var_t | |||||
| : public getter_t<T_value> | |||||
| { | |||||
| using base_type = getter_t<T_value>; | |||||
| using value_type = typename base_type::value_type; | |||||
| using dataset_type = T_dataset; | |||||
| using member_type = T_member; | |||||
| member_type member; | |||||
| template<typename X_member> | |||||
| constexpr getter_member_var_t(X_member&& p_member) | |||||
| : member(std::forward<X_member>(p_member)) | |||||
| { } | |||||
| cpphibernate_copyable(getter_member_var_t, delete); | |||||
| cpphibernate_moveable(getter_member_var_t, default); | |||||
| template<typename X_dataset> | |||||
| constexpr decltype(auto) operator()(X_dataset&& data) const | |||||
| { return std::forward<X_dataset>(data).*member; } | |||||
| }; | |||||
| /* getter_member_func_t */ | |||||
| template<typename T_dataset, typename T_value, typename T_member> | |||||
| struct getter_member_func_t | |||||
| : public getter_t<T_value> | |||||
| { | |||||
| using base_type = getter_t<T_value>; | |||||
| using value_type = typename base_type::value_type; | |||||
| using dataset_type = T_dataset; | |||||
| using member_type = T_member; | |||||
| member_type member; | |||||
| template<typename X_member> | |||||
| constexpr getter_member_func_t(X_member&& p_member) | |||||
| : member(std::forward<X_member>(p_member)) | |||||
| { }; | |||||
| cpphibernate_copyable(getter_member_func_t, delete); | |||||
| cpphibernate_moveable(getter_member_func_t, default); | |||||
| template<typename X_dataset> | |||||
| constexpr decltype(auto) operator()(X_dataset&& data) const | |||||
| { return (std::forward<X_dataset>(data).*member)(); } | |||||
| }; | |||||
| /* getter_lambda_t */ | |||||
| template<typename T_dataset, typename T_lambda> | |||||
| struct getter_lambda_t | |||||
| : public getter_t<decltype(std::declval<T_lambda>()(std::declval<T_dataset>()))> | |||||
| { | |||||
| using base_type = getter_t<decltype(std::declval<T_lambda>()(std::declval<T_dataset>()))>; | |||||
| using value_type = typename base_type::value_type; | |||||
| using dataset_type = T_dataset; | |||||
| using lambda_type = T_lambda; | |||||
| lambda_type lambda; | |||||
| template<typename X_lambda> | |||||
| constexpr getter_lambda_t(X_lambda&& p_lambda) | |||||
| : lambda(std::forward<X_lambda>(p_lambda)) | |||||
| { } | |||||
| cpphibernate_copyable(getter_lambda_t, delete); | |||||
| cpphibernate_moveable(getter_lambda_t, default); | |||||
| template<typename X_dataset> | |||||
| constexpr decltype(auto) operator()(X_dataset&& data) const | |||||
| { return lambda(std::forward<X_dataset>(data)); } | |||||
| }; | |||||
| /* is_getter_impl */ | |||||
| template<typename T, typename = void> | |||||
| struct is_getter_impl | |||||
| : public mp::c_false_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_getter_impl<T, mp::enable_if_c< | |||||
| mp::is_base_of<getter_t<typename T::value_type>, T>::value>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_getter : | |||||
| public __impl::is_getter_impl<T> | |||||
| { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_getter_none() | |||||
| { return __impl::getter_none_t(); } | |||||
| template<typename T_dataset, typename T_value> | |||||
| constexpr decltype(auto) make_getter_member_var(T_value T_dataset::* member) | |||||
| { return __impl::getter_member_var_t<T_dataset, T_value, T_value T_dataset::*>(member); } | |||||
| template<typename T_dataset, typename T_value> | |||||
| constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)()) | |||||
| { return __impl::getter_member_func_t<T_dataset, T_value, T_value (T_dataset::*)()>(member); } | |||||
| template<typename T_dataset, typename T_value> | |||||
| constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)() const) | |||||
| { return __impl::getter_member_func_t<const T_dataset, T_value, T_value (T_dataset::*)() const>(member); } | |||||
| template<typename T_dataset, typename T_lambda> | |||||
| constexpr decltype(auto) make_getter_lambda(T_lambda&& lambda, boost::hana::basic_type<T_dataset>) | |||||
| { return __impl::getter_lambda_t<T_dataset, T_lambda>(std::forward<T_lambda>(lambda)); } | |||||
| namespace __impl | |||||
| { | |||||
| /* getter_buildser */ | |||||
| template<typename X, typename = void> | |||||
| struct getter_builder | |||||
| { | |||||
| template<typename... Args> | |||||
| static constexpr decltype(auto) apply(Args&&...) | |||||
| { return make_getter_none(); } | |||||
| }; | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct getter_builder<mp::list<T_value T_dataset::*>, void> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_value T_dataset::*member) | |||||
| { return make_getter_member_var(member); } | |||||
| }; | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct getter_builder<mp::list<T_value (T_dataset::*)(void)>, void> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void)) | |||||
| { return make_getter_member_func(member); } | |||||
| }; | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct getter_builder<mp::list<T_value (T_dataset::*)(void) const>, void> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void) const) | |||||
| { return make_getter_member_func(member); } | |||||
| }; | |||||
| template<typename T_func, typename T_dataset_type, typename T_value_type> | |||||
| struct getter_builder<mp::list<T_func, T_dataset_type, T_value_type>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, mp::decay_t<T_dataset_type>> | |||||
| && hana::is_a<hana::type_tag, mp::decay_t<T_value_type>>>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_func&& func, T_dataset_type&& dataset_type, T_value_type&& value_type) | |||||
| { return make_getter_lambda(std::forward<T_func>(func), std::forward<T_dataset_type>(dataset_type), std::forward<T_value_type>(value_type)); } | |||||
| }; | |||||
| } | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_getter = misc::make_generic_predicate<__impl::getter_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,43 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/types.h> | |||||
| #define cpphibernate_make_string(str) \ | |||||
| #str | |||||
| #define cpphibernate_make_schema(name, ...) \ | |||||
| cpphibernate::schema::make_schema( \ | |||||
| cpphibernate_make_string(name), \ | |||||
| cpphibernate::schema::make_tables(__VA_ARGS__)) | |||||
| #define cpphibernate_make_table_name(name, type, id, ...) \ | |||||
| cpphibernate::schema::make_table( \ | |||||
| cpphibernate_make_string(name), \ | |||||
| boost::hana::type_c<type>, \ | |||||
| boost::hana::size_c<id>, \ | |||||
| cpphibernate::schema::make_fields(__VA_ARGS__)) | |||||
| #define cpphibernate_make_table(name, id, ...) \ | |||||
| cpphibernate_make_table_name(name, name, id, __VA_ARGS__) | |||||
| #define cpphibernate_make_field_custom(name, getter, setter, ...) \ | |||||
| cpphibernate::schema::make_field( \ | |||||
| cpphibernate_make_string(name), \ | |||||
| cpphibernate::schema::make_getter(getter), \ | |||||
| cpphibernate::schema::make_setter(setter), \ | |||||
| cpphibernate::schema::make_attributes(__VA_ARGS__)) | |||||
| #define cpphibernate_make_field_name(name, member_ptr, ...) \ | |||||
| cpphibernate_make_field_custom( \ | |||||
| name, member_ptr, member_ptr, __VA_ARGS__) | |||||
| #define cpphibernate_make_field(type, member, ...) \ | |||||
| cpphibernate_make_field_name( \ | |||||
| member, &type::member, __VA_ARGS__) | |||||
| #define cpphibernate_make_id(member_ptr) \ | |||||
| cpphibernate_make_field_name( \ | |||||
| null, \ | |||||
| member_ptr, \ | |||||
| cpphibernate::schema::attribute::primary_key) | |||||
| @@ -0,0 +1,18 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| namespace std | |||||
| { | |||||
| template<typename T_char, typename T_traits, typename X> | |||||
| inline auto operator <<(basic_ostream<T_char, T_traits>& os, X&& x) | |||||
| -> ::utl::mp::enable_if< | |||||
| utl::mp::is_valid<decltype(std::forward<X>(x).print(os))>, | |||||
| basic_ostream<T_char, T_traits>&> | |||||
| { | |||||
| std::forward<X>(x).print(os); | |||||
| return os; | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,85 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc/general.h> | |||||
| #include <cpphibernate/schema/tables.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* schema_t */ | |||||
| template<typename T_name, typename T_tables> | |||||
| struct schema_t | |||||
| { | |||||
| using name_type = T_name; | |||||
| using tables_type = T_tables; | |||||
| name_type name; | |||||
| tables_type tables; | |||||
| constexpr schema_t( | |||||
| T_name&& p_name, | |||||
| T_tables&& p_tables) | |||||
| : name (std::forward<T_name> (p_name)) | |||||
| , tables(std::forward<T_tables>(p_tables)) | |||||
| { } | |||||
| cpphibernate_copyable(schema_t, delete); | |||||
| cpphibernate_moveable(schema_t, default); | |||||
| inline void print(std::ostream& os) const | |||||
| { | |||||
| using namespace ::utl; | |||||
| size_t index = 0; | |||||
| os << indent << '{' | |||||
| << incindent | |||||
| << indent << "\"name\": \"" << name << "\"," | |||||
| << indent << "\"tables\": " | |||||
| << indent << '[' | |||||
| << incindent; | |||||
| hana::for_each(tables, [&](auto& table){ | |||||
| if (index++ > 0) os << ","; | |||||
| table.print(os); | |||||
| }); | |||||
| os << decindent | |||||
| << indent << ']' | |||||
| << decindent | |||||
| << indent << '}'; | |||||
| } | |||||
| }; | |||||
| /* schema_builder */ | |||||
| template <typename X, typename = void> | |||||
| struct schema_builder | |||||
| { | |||||
| template <typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_schema(...)!"); } | |||||
| }; | |||||
| template<typename T_name, typename T_tables> | |||||
| struct schema_builder<mp::list<T_name, T_tables>, mp::enable_if_c< | |||||
| is_tables<mp::clean_type<T_tables>>::value>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_name&& name, T_tables&& tables) | |||||
| { return schema_t<T_name, T_tables>(std::forward<T_name>(name), std::forward<T_tables>(tables)); } | |||||
| }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_schema : mp::is_specialization_of<T, __impl::schema_t> { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_schema = misc::make_generic_predicate<__impl::schema_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,206 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc/general.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* setter_t */ | |||||
| template<typename T_value> | |||||
| struct setter_t | |||||
| { | |||||
| using value_type = T_value; | |||||
| }; | |||||
| /* setter_none_t */ | |||||
| struct setter_none_t | |||||
| : public setter_t<void> | |||||
| { | |||||
| using base_type = setter_t<void>; | |||||
| using value_type = typename base_type::value_type; | |||||
| cpphibernate_constructable(setter_none_t, default); | |||||
| cpphibernate_copyable (setter_none_t, delete); | |||||
| cpphibernate_moveable (setter_none_t, default); | |||||
| }; | |||||
| /* setter_member_var_t */ | |||||
| template<typename T_dataset, typename T_value, typename T_member> | |||||
| struct setter_member_var_t | |||||
| : public setter_t<T_value> | |||||
| { | |||||
| using base_type = setter_t<T_value>; | |||||
| using value_type = typename base_type::value_type; | |||||
| using dataset_type = T_dataset; | |||||
| using member_type = T_member; | |||||
| member_type member; | |||||
| template<typename X_member> | |||||
| constexpr setter_member_var_t(X_member&& p_member) | |||||
| : member(std::forward<X_member>(p_member)) | |||||
| { } | |||||
| cpphibernate_copyable(setter_member_var_t, delete); | |||||
| cpphibernate_moveable(setter_member_var_t, default); | |||||
| template<typename X_dataset, typename X_value> | |||||
| constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const | |||||
| { return std::forward<X_dataset>(data).*member = std::forward<X_value>(value); } | |||||
| }; | |||||
| /* setter_member_func_t */ | |||||
| template<typename T_dataset, typename T_value, typename T_member> | |||||
| struct setter_member_func_t | |||||
| : public setter_t<T_value> | |||||
| { | |||||
| using base_type = setter_t<T_value>; | |||||
| using value_type = typename base_type::value_type; | |||||
| using dataset_type = T_dataset; | |||||
| using member_type = T_member; | |||||
| member_type member; | |||||
| template<typename X_member> | |||||
| constexpr setter_member_func_t(X_member&& p_member) | |||||
| : member(std::forward<X_member>(p_member)) | |||||
| { }; | |||||
| cpphibernate_copyable(setter_member_func_t, delete); | |||||
| cpphibernate_moveable(setter_member_func_t, default); | |||||
| template<typename X_dataset, typename X_value> | |||||
| constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const | |||||
| { return (std::forward<X_dataset>(data).*member)(std::forward<X_value>(value)); } | |||||
| }; | |||||
| /* setter_lambda_t */ | |||||
| template<typename T_dataset, typename T_value, typename T_lambda> | |||||
| struct setter_lambda_t | |||||
| : public setter_t<T_value> | |||||
| { | |||||
| using base_type = setter_t<T_value>; | |||||
| using value_type = typename base_type::value_type; | |||||
| using dataset_type = T_dataset; | |||||
| using lambda_type = T_lambda; | |||||
| lambda_type lambda; | |||||
| template<typename X_lambda> | |||||
| constexpr setter_lambda_t(X_lambda&& p_lambda) | |||||
| : lambda(std::forward<X_lambda>(p_lambda)) | |||||
| { } | |||||
| cpphibernate_copyable(setter_lambda_t, delete); | |||||
| cpphibernate_moveable(setter_lambda_t, default); | |||||
| template<typename X_dataset, typename X_value> | |||||
| constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const | |||||
| { return lambda(std::forward<X_dataset>(data), std::forward<X_value>(value)); } | |||||
| }; | |||||
| /* is_setter_impl */ | |||||
| template<typename T, typename = void> | |||||
| struct is_setter_impl | |||||
| : public mp::c_false_t | |||||
| { }; | |||||
| template<typename T> | |||||
| struct is_setter_impl<T, mp::enable_if_c< | |||||
| mp::is_base_of<setter_t<typename T::value_type>, T>::value>> | |||||
| : public mp::c_true_t | |||||
| { }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_setter : | |||||
| public __impl::is_setter_impl<T> | |||||
| { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_setter_none() | |||||
| { return __impl::setter_none_t(); } | |||||
| template<typename T_dataset, typename T_value> | |||||
| constexpr decltype(auto) make_setter_member_var(T_value T_dataset::* member) | |||||
| { return __impl::setter_member_var_t<T_dataset, T_value, T_value T_dataset::*>(member); } | |||||
| template<typename T_dataset, typename T_value, typename T_return> | |||||
| constexpr decltype(auto) make_setter_member_func(T_return (T_dataset::*member)(T_value)) | |||||
| { return __impl::setter_member_func_t<T_dataset, T_value, T_return (T_dataset::*)(T_value)>(member); } | |||||
| template<typename T_dataset, typename T_value, typename T_return> | |||||
| constexpr decltype(auto) make_setter_member_func(T_return (T_dataset::*member)(T_value) const) | |||||
| { return __impl::setter_member_func_t<const T_dataset, T_value, T_return (T_dataset::*)(T_value) const>(member); } | |||||
| template<typename T_dataset, typename T_value, typename T_lambda> | |||||
| constexpr decltype(auto) make_setter_lambda(T_lambda&& lambda, boost::hana::basic_type<T_dataset>, boost::hana::basic_type<T_value>) | |||||
| { return __impl::setter_lambda_t<T_dataset, T_value, T_lambda>(std::forward<T_lambda>(lambda)); } | |||||
| namespace __impl | |||||
| { | |||||
| /* setter_buildser */ | |||||
| template<typename X, typename = void> | |||||
| struct setter_builder | |||||
| { | |||||
| template<typename... Args> | |||||
| static constexpr decltype(auto) apply(Args&&...) | |||||
| { return make_setter_none(); } | |||||
| }; | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct setter_builder<mp::list<T_value T_dataset::*>, void> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_value T_dataset::*member) | |||||
| { return make_setter_member_var(member); } | |||||
| }; | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct setter_builder<mp::list<T_value (T_dataset::*)(void)>, void> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void)) | |||||
| { return make_setter_member_func(member); } | |||||
| }; | |||||
| template<typename T_dataset, typename T_value> | |||||
| struct setter_builder<mp::list<T_value (T_dataset::*)(void) const>, void> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_value (T_dataset::*member)(void) const) | |||||
| { return make_setter_member_func(member); } | |||||
| }; | |||||
| template<typename T_func, typename T_dataset_type, typename T_value_type> | |||||
| struct setter_builder<mp::list<T_func, T_dataset_type, T_value_type>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, mp::clean_type<T_dataset_type>> | |||||
| && hana::is_a<hana::type_tag, mp::clean_type<T_value_type>>>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_func&& func, T_dataset_type&& dataset_type, T_value_type&& value_type) | |||||
| { return make_setter_lambda(std::forward<T_func>(func), std::forward<T_dataset_type>(dataset_type), std::forward<T_value_type>(value_type)); } | |||||
| }; | |||||
| } | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_setter = misc::make_generic_predicate<__impl::setter_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,109 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc/wrap.h> | |||||
| #include <cpphibernate/misc/general.h> | |||||
| #include <cpphibernate/schema/fields.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* table_t */ | |||||
| template<typename T_name, typename T_dataset_wrapped, typename T_table_id, typename T_fields> | |||||
| struct table_t | |||||
| { | |||||
| using name_type = T_name; | |||||
| using dataset_wrapped_type = mp::decay_t<T_dataset_wrapped>; | |||||
| using table_id_type = T_table_id; | |||||
| using fields_type = T_fields; | |||||
| using this_type = table_t<name_type, dataset_wrapped_type, table_id_type, fields_type>; | |||||
| name_type name; | |||||
| dataset_wrapped_type dataset_wrapped; | |||||
| table_id_type table_id; | |||||
| fields_type fields; | |||||
| constexpr table_t( | |||||
| T_name p_name, | |||||
| T_dataset_wrapped p_dataset_wrapped, | |||||
| T_table_id p_table_id, | |||||
| T_fields p_fields) | |||||
| : name (std::forward<T_name> (p_name)) | |||||
| , dataset_wrapped (std::forward<T_dataset_wrapped>(p_dataset_wrapped)) | |||||
| , table_id (std::forward<T_table_id> (p_table_id)) | |||||
| , fields (std::forward<T_fields> (p_fields)) | |||||
| { } | |||||
| cpphibernate_copyable(table_t, delete); | |||||
| cpphibernate_moveable(table_t, default); | |||||
| cpphibernate_equality_comparable(); | |||||
| inline void print(std::ostream& os) const | |||||
| { | |||||
| using namespace ::utl; | |||||
| size_t index = 0; | |||||
| os << indent << '{' | |||||
| << incindent | |||||
| << indent << "\"name\": \"" << name << "\"," | |||||
| << indent << "\"dataset_wrapped\": \"" << utl::type_helper<misc::decay_unwrap_t<dataset_wrapped_type>>::name() << "\"" | |||||
| << indent << "\"table_id\": \"" << hana::value(table_id) << "\"" | |||||
| << indent << "\"fields\": " | |||||
| << indent << '[' | |||||
| << incindent; | |||||
| hana::for_each(fields, [&](auto& field){ | |||||
| if (index++ > 0) os << ","; | |||||
| field.print(os); | |||||
| }); | |||||
| os << decindent | |||||
| << indent << ']' | |||||
| << decindent | |||||
| << indent << '}'; | |||||
| } | |||||
| }; | |||||
| /* table_builder */ | |||||
| template <typename X, typename = void> | |||||
| struct table_builder | |||||
| { | |||||
| template <typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_table(...)!"); } | |||||
| }; | |||||
| template<typename T_name, typename T_dataset_wrapped, typename T_id, typename T_fields> | |||||
| struct table_builder<mp::list<T_name, T_dataset_wrapped, T_id, T_fields>, mp::enable_if_c< | |||||
| hana::is_a<hana::type_tag, T_dataset_wrapped> | |||||
| && is_fields<mp::decay_t<T_fields>>::value>> | |||||
| { | |||||
| static constexpr decltype(auto) apply(T_name&& name, T_dataset_wrapped&& dataset_wrapped, T_id&& id, T_fields&& fields) | |||||
| { | |||||
| return table_t<T_name, T_dataset_wrapped, T_id, T_fields>( | |||||
| std::forward<T_name> (name), | |||||
| std::forward<T_dataset_wrapped> (dataset_wrapped), | |||||
| std::forward<T_id> (id), | |||||
| std::forward<T_fields> (fields)); | |||||
| } | |||||
| }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_table : mp::is_specialization_of<T, __impl::table_t> { }; | |||||
| template<typename... T> | |||||
| struct all_are_tables : mp::all_true<is_table<T>::value...> { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_table = misc::make_generic_predicate<__impl::table_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,62 @@ | |||||
| #pragma once | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpphibernate/misc/general.h> | |||||
| #include <cpphibernate/schema/table.h> | |||||
| beg_namespace_cpphibernate_schema | |||||
| { | |||||
| namespace __impl | |||||
| { | |||||
| /* tables_t */ | |||||
| template<typename... T_table> | |||||
| using tables_t = hana::tuple<T_table...>; | |||||
| /* is_tables_impl */ | |||||
| template<typename T, typename = void> | |||||
| struct is_tables_impl | |||||
| : mp::c_false_t | |||||
| { }; | |||||
| template<typename... T> | |||||
| struct is_tables_impl<tables_t<T...>, mp::enable_if<all_are_tables<T...>>> | |||||
| : mp::c_true_t | |||||
| { }; | |||||
| /* tables_builder */ | |||||
| template <typename X, typename = void> | |||||
| struct tables_builder | |||||
| { | |||||
| template <typename... T_args> | |||||
| static constexpr decltype(auto) apply(T_args&&... args) | |||||
| { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make_tables(...)!"); } | |||||
| }; | |||||
| template<typename... T> | |||||
| struct tables_builder<mp::list<T...>, mp::enable_if<all_are_tables<T...>>> | |||||
| { | |||||
| template <typename ...T_tables> | |||||
| static constexpr decltype(auto) apply(T_tables&&... tables) | |||||
| { return tables_t<T_tables...>(std::forward<T_tables>(tables)...); } | |||||
| }; | |||||
| } | |||||
| /* meta */ | |||||
| template<typename T> | |||||
| struct is_tables | |||||
| : public __impl::is_tables_impl<T> | |||||
| { }; | |||||
| /* make */ | |||||
| constexpr decltype(auto) make_tables = misc::make_generic_predicate<__impl::tables_builder> { }; | |||||
| } | |||||
| end_namespace_cpphibernate_schema | |||||
| @@ -0,0 +1,51 @@ | |||||
| #pragma once | |||||
| #include <string> | |||||
| #include <iostream> | |||||
| #include <cpphibernate/config.h> | |||||
| #include <cpputils/misc/exception.h> | |||||
| beg_namespace_cpphibernate | |||||
| { | |||||
| /* string */ | |||||
| template<size_t N> | |||||
| struct string | |||||
| : public std::string | |||||
| { | |||||
| static constexpr decltype(auto) max_size = N; | |||||
| using std::string::string; | |||||
| using std::string::operator=; | |||||
| }; | |||||
| /* uuid */ | |||||
| struct uuid | |||||
| : public std::array<uint8_t, 16> | |||||
| { | |||||
| public: | |||||
| inline uuid() | |||||
| : std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }) | |||||
| { } | |||||
| inline uuid(const std::string& str) | |||||
| : std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }) | |||||
| { | |||||
| if (!from_string(str, *this)) | |||||
| throw utl::argument_exception("str", "invalid uuid"); | |||||
| } | |||||
| cpphibernate_copyable(uuid, default); | |||||
| cpphibernate_moveable(uuid, default); | |||||
| void to_string(std::ostream& os) const; | |||||
| public: | |||||
| static bool from_string(const std::string& str, uuid& val); | |||||
| }; | |||||
| } | |||||
| end_namespace_cpphibernate | |||||
| @@ -11,6 +11,10 @@ Set ( CMAKE_CXX_STANDARD 17 ) | |||||
| Set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PEDANTIC_C_FLAGS}" ) | Set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${PEDANTIC_C_FLAGS}" ) | ||||
| Set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX_FLAGS}" ) | Set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX_FLAGS}" ) | ||||
| # Dependencies #################################################################################### | |||||
| Find_Package ( cpputils REQUIRED ) | |||||
| # Project: cpphibernate ############################################################################### | # Project: cpphibernate ############################################################################### | ||||
| Project ( cpphibernate VERSION 1.0.0.0 LANGUAGES CXX ) | Project ( cpphibernate VERSION 1.0.0.0 LANGUAGES CXX ) | ||||
| @@ -20,6 +24,10 @@ Target_Include_Directories ( | |||||
| cpphibernate | cpphibernate | ||||
| PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include | PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include | ||||
| ) | ) | ||||
| Target_Link_Libraries ( | |||||
| cpphibernate | |||||
| cpputils | |||||
| ) | |||||
| If ( __COTIRE_INCLUDED ) | If ( __COTIRE_INCLUDED ) | ||||
| Cotire ( cpphibernate ) | Cotire ( cpphibernate ) | ||||
| EndIf ( ) | EndIf ( ) | ||||
| @@ -0,0 +1,54 @@ | |||||
| #include <iomanip> | |||||
| #include <cpphibernate/types.h> | |||||
| using namespace ::cpphibernate;; | |||||
| void uuid::to_string(std::ostream& os) const | |||||
| { | |||||
| os << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 0] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 1] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 2] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 3] | |||||
| << '-' | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 4] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 5] | |||||
| << '-' | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 6] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 7] | |||||
| << '-' | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 8] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[ 9] | |||||
| << '-' | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[10] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[11] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[12] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[13] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[14] | |||||
| << std::setw(2) << std::setfill('0') << std::hex << (int)(*this)[15]; | |||||
| } | |||||
| bool uuid::from_string(const std::string& str, uuid& val) | |||||
| { | |||||
| const char* c = str.data(); | |||||
| const char* e = c + str.size(); | |||||
| size_t i = 0; | |||||
| val.fill(0); | |||||
| while(i < 32 && c < e) | |||||
| { | |||||
| if (*c >= '0' && *c <= '9') | |||||
| val[i >> 1] |= ((*c - '0') << (4 * (1 - (i & 1)))); | |||||
| else if (*c >= 'a' && *c <= 'f') | |||||
| val[i >> 1] |= ((*c - 'a' + 10) << (4 * (1 - (i & 1)))); | |||||
| else if (*c >= 'A' && *c <= 'F') | |||||
| val[i >> 1] |= ((*c - 'A' + 10) << (4 * (1 - (i & 1)))); | |||||
| else if (*c != '-') | |||||
| return false; | |||||
| if (*c != '-') | |||||
| ++i; | |||||
| ++c; | |||||
| } | |||||
| if (i != 32 || c != e) | |||||
| return false; | |||||
| return true; | |||||
| } | |||||
| @@ -0,0 +1,128 @@ | |||||
| #include <gtest/gtest.h> | |||||
| #include <cpphibernate.h> | |||||
| using namespace ::cpphibernate; | |||||
| struct test1 | |||||
| { | |||||
| uuid id; | |||||
| std::string str_data; | |||||
| string<64> str64_data; | |||||
| }; | |||||
| struct test2 | |||||
| { | |||||
| uuid id; | |||||
| uint8_t u8_data; | |||||
| int8_t i8_data; | |||||
| uint16_t u16_data; | |||||
| int16_t i16_data; | |||||
| }; | |||||
| struct test3 | |||||
| { | |||||
| uuid id; | |||||
| uint32_t u32_data; | |||||
| int32_t i32_data; | |||||
| uint64_t u64_data; | |||||
| int64_t i64_data; | |||||
| }; | |||||
| struct base | |||||
| { | |||||
| uuid id; | |||||
| std::string name; | |||||
| }; | |||||
| struct derived1 | |||||
| : public base | |||||
| { | |||||
| uuid derived1_id; | |||||
| test1 test1_data; | |||||
| }; | |||||
| struct derived2 | |||||
| : public base | |||||
| { | |||||
| uuid derived2_id; | |||||
| utl::nullable<test2> test2_nullable; | |||||
| std::unique_ptr<test2> test2_ptr_u; | |||||
| std::shared_ptr<test2> test2_ptr_s; | |||||
| }; | |||||
| struct derived3 | |||||
| : public derived1 | |||||
| { | |||||
| uuid derived3_id; | |||||
| std::list<test3> test3_list; | |||||
| std::vector<test3> test3_vector; | |||||
| }; | |||||
| constexpr decltype(auto) test_schema = cpphibernate_make_schema( | |||||
| test, | |||||
| cpphibernate_make_table_name( | |||||
| tbl_test1, | |||||
| test1, | |||||
| 1, | |||||
| cpphibernate_make_id (&test1::id), | |||||
| cpphibernate_make_field (test1, str_data), | |||||
| cpphibernate_make_field (test1, str64_data) | |||||
| ), | |||||
| cpphibernate_make_table_name( | |||||
| tbl_test2, | |||||
| test2, | |||||
| 2, | |||||
| cpphibernate_make_id (&test2::id), | |||||
| cpphibernate_make_field (test2, u8_data), | |||||
| cpphibernate_make_field (test2, i8_data), | |||||
| cpphibernate_make_field (test2, u16_data), | |||||
| cpphibernate_make_field (test2, i16_data) | |||||
| ), | |||||
| cpphibernate_make_table_name( | |||||
| tbl_test3, | |||||
| test3, | |||||
| 3, | |||||
| cpphibernate_make_id (&test3::id), | |||||
| cpphibernate_make_field (test3, u32_data), | |||||
| cpphibernate_make_field (test3, i32_data), | |||||
| cpphibernate_make_field (test3, u64_data), | |||||
| cpphibernate_make_field (test3, i64_data) | |||||
| ), | |||||
| cpphibernate_make_table_name( | |||||
| tbl_base, | |||||
| base, | |||||
| 10, | |||||
| cpphibernate_make_id (&base::id), | |||||
| cpphibernate_make_field (base, name) | |||||
| ), | |||||
| cpphibernate_make_table_name( | |||||
| tbl_derived1, | |||||
| derived1, | |||||
| 11, | |||||
| cpphibernate_make_id (&derived1::derived1_id), | |||||
| cpphibernate_make_field (derived1, test1_data) | |||||
| ), | |||||
| cpphibernate_make_table_name( | |||||
| tbl_derived2, | |||||
| derived2, | |||||
| 12, | |||||
| cpphibernate_make_id (&derived2::derived2_id), | |||||
| cpphibernate_make_field (derived2, test2_nullable), | |||||
| cpphibernate_make_field (derived2, test2_ptr_u), | |||||
| cpphibernate_make_field (derived2, test2_ptr_s) | |||||
| ), | |||||
| cpphibernate_make_table_name( | |||||
| tbl_derived3, | |||||
| derived3, | |||||
| 13, | |||||
| cpphibernate_make_id (&derived3::derived3_id), | |||||
| cpphibernate_make_field (derived3, test3_list), | |||||
| cpphibernate_make_field (derived3, test3_vector) | |||||
| ) | |||||
| ); | |||||
| TEST(CppHibernateTests, fuuu) | |||||
| { | |||||
| std::cout << test_schema << std::endl; | |||||
| } | |||||