| @@ -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_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${PEDANTIC_CXX_FLAGS}" ) | |||
| # Dependencies #################################################################################### | |||
| Find_Package ( cpputils REQUIRED ) | |||
| # Project: cpphibernate ############################################################################### | |||
| Project ( cpphibernate VERSION 1.0.0.0 LANGUAGES CXX ) | |||
| @@ -20,6 +24,10 @@ Target_Include_Directories ( | |||
| cpphibernate | |||
| PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include | |||
| ) | |||
| Target_Link_Libraries ( | |||
| cpphibernate | |||
| cpputils | |||
| ) | |||
| If ( __COTIRE_INCLUDED ) | |||
| Cotire ( cpphibernate ) | |||
| 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; | |||
| } | |||