@@ -1,15 +1,57 @@ | |||
# Initialize CMake ################################################################################ | |||
CMake_Minimum_Required ( VERSION 3.5.1 FATAL_ERROR ) | |||
Include ( CTest ) | |||
If ( NOT CMAKE_BUILD_TYPE ) | |||
Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE ) | |||
EndIf ( NOT CMAKE_BUILD_TYPE ) | |||
Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/" | |||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/" ) | |||
# Projects ######################################################################################## | |||
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src ) | |||
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test ) | |||
CMake_Minimum_Required ( VERSION 3.12.0 FATAL_ERROR ) | |||
# Set CMAKE_BUILD_TYPE | |||
If ( NOT CMAKE_BUILD_TYPE ) | |||
Set ( CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build!" FORCE ) | |||
EndIf ( NOT CMAKE_BUILD_TYPE ) | |||
Set_Property ( CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo MinSizeRel ) | |||
# Set CMAKE_MODULE_PATH | |||
If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||
Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||
EndIf ( ) | |||
If ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmake/" ) | |||
Set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} | |||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules" ) | |||
EndIf ( ) | |||
# Project ######################################################################################### | |||
Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpphibernate-var.cmake ) | |||
Include ( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpphibernate-options.cmake ) | |||
Project ( cpphibernate | |||
DESCRIPTION "A simple library" | |||
VERSION "${CPPHIBERNATE_VERSION}" ) | |||
Include ( CTest ) | |||
Include ( GNUInstallDirs ) | |||
# Subdirectories | |||
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/src ) | |||
Add_SubDirectory ( ${CMAKE_CURRENT_SOURCE_DIR}/test ) | |||
# Install | |||
Include ( CMakePackageConfigHelpers ) | |||
Write_Basic_Package_Version_File ( "${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config-version.cmake" | |||
VERSION ${CPPHIBERNATE_VERSION} | |||
COMPATIBILITY AnyNewerVersion ) | |||
Configure_File ( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cpphibernate-config.cmake" | |||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config.cmake" | |||
@ONLY ) | |||
Set ( ConfigPackageLocation "${CPPHIBERNATE_INSTALL_DIR_SHARE}/cmake" ) | |||
Install ( EXPORT | |||
cpphibernate | |||
NAMESPACE | |||
cpphibernate:: | |||
DESTINATION | |||
${ConfigPackageLocation} ) | |||
Install ( FILES | |||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config.cmake" | |||
"${CMAKE_CURRENT_BINARY_DIR}/cmake/cpphibernate-config-version.cmake" | |||
DESTINATION | |||
${ConfigPackageLocation} | |||
COMPONENT | |||
Devel ) |
@@ -1,46 +0,0 @@ | |||
Include ( ExternalProject ) | |||
Include ( FindPackageHandleStandardArgs ) | |||
Set ( CPPMARIADB_PATH ${CMAKE_BINARY_DIR}/extern/cppmariadb ) | |||
If ( NOT TARGET cppmariadb_extern ) | |||
ExternalProject_Add ( cppmariadb_extern | |||
PREFIX ${CPPMARIADB_PATH} | |||
TMP_DIR ${CPPMARIADB_PATH}/tmp | |||
STAMP_DIR ${CPPMARIADB_PATH}/stamp | |||
SOURCE_DIR ${CPPMARIADB_PATH}/src | |||
BINARY_DIR ${CPPMARIADB_PATH}/build | |||
INSTALL_DIR ${CPPMARIADB_PATH}/install | |||
GIT_REPOSITORY "https://git.bergmann89.de/cpp/cppmariadb.git" | |||
GIT_TAG "master" | |||
TEST_COMMAND make test | |||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> | |||
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} | |||
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} | |||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} | |||
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}) | |||
EndIf ( ) | |||
Set ( CPPMARIADB_LIBRARY ${CPPMARIADB_PATH}/install/lib/libcppmariadb.so ) | |||
Set ( CPPMARIADB_INCLUDE_DIR ${CPPMARIADB_PATH}/install/include ) | |||
Set ( CPPMARIADB_LIBRARIES ${CPPMARIADB_LIBRARY} ) | |||
Set ( CPPMARIADB_INCLUDE_DIRS ${CPPMARIADB_INCLUDE_DIR} ) | |||
File ( MAKE_DIRECTORY ${CPPMARIADB_INCLUDE_DIR} ) | |||
Find_Package_Handle_Standard_Args ( cppmariadb DEFAULT_MSG | |||
CPPMARIADB_LIBRARY | |||
CPPMARIADB_INCLUDE_DIR ) | |||
If ( NOT TARGET cppmariadb ) | |||
Add_Library ( cppmariadb SHARED IMPORTED ) | |||
Add_Dependencies ( cppmariadb cppmariadb_extern ) | |||
Set_Property ( TARGET cppmariadb | |||
PROPERTY IMPORTED_LOCATION ${CPPMARIADB_LIBRARY} ) | |||
Set_Property ( TARGET cppmariadb | |||
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CPPMARIADB_INCLUDE_DIRS} ) | |||
Install ( FILES ${CPPMARIADB_LIBRARY} DESTINATION lib ) | |||
If ( CPPHIBERNATE_INSTALL_DEV_FILES ) | |||
Install ( DIRECTORY ${CPPMARIADB_INCLUDE_DIR}/ DESTINATION include ) | |||
EndIf ( ) | |||
EndIf ( ) |
@@ -1,46 +0,0 @@ | |||
Include ( ExternalProject ) | |||
Include ( FindPackageHandleStandardArgs ) | |||
Set ( CPPUTILS_PATH ${CMAKE_BINARY_DIR}/extern/cpputils ) | |||
If ( NOT TARGET cpputils_extern ) | |||
ExternalProject_Add ( cpputils_extern | |||
PREFIX ${CPPUTILS_PATH} | |||
TMP_DIR ${CPPUTILS_PATH}/tmp | |||
STAMP_DIR ${CPPUTILS_PATH}/stamp | |||
SOURCE_DIR ${CPPUTILS_PATH}/src | |||
BINARY_DIR ${CPPUTILS_PATH}/build | |||
INSTALL_DIR ${CPPUTILS_PATH}/install | |||
GIT_REPOSITORY "https://git.bergmann89.de/cpp/cpputils.git" | |||
GIT_TAG "master" | |||
TEST_COMMAND make test | |||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> | |||
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} | |||
-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} | |||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} | |||
-DCMAKE_MODULE_PATH=${CMAKE_MODULE_PATH}) | |||
EndIf ( ) | |||
Set ( CPPUTILS_LIBRARY ${CPPUTILS_PATH}/install/lib/libcpputils.so ) | |||
Set ( CPPUTILS_INCLUDE_DIR ${CPPUTILS_PATH}/install/include ) | |||
Set ( CPPUTILS_LIBRARIES ${CPPUTILS_LIBRARY} ) | |||
Set ( CPPUTILS_INCLUDE_DIRS ${CPPUTILS_INCLUDE_DIR} ) | |||
File ( MAKE_DIRECTORY ${CPPUTILS_INCLUDE_DIR} ) | |||
Find_Package_Handle_Standard_Args ( cpputils DEFAULT_MSG | |||
CPPUTILS_LIBRARY | |||
CPPUTILS_INCLUDE_DIR ) | |||
If ( NOT TARGET cpputils ) | |||
Add_Library ( cpputils SHARED IMPORTED ) | |||
Add_Dependencies ( cpputils cpputils_extern ) | |||
Set_Property ( TARGET cpputils | |||
PROPERTY IMPORTED_LOCATION ${CPPUTILS_LIBRARY} ) | |||
Set_Property ( TARGET cpputils | |||
PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CPPUTILS_INCLUDE_DIRS} ) | |||
Install ( FILES ${CPPUTILS_LIBRARY} DESTINATION lib ) | |||
If ( CPPHIBERNATE_INSTALL_DEV_FILES ) | |||
Install ( DIRECTORY ${CPPUTILS_INCLUDE_DIR}/ DESTINATION include ) | |||
EndIf ( ) | |||
EndIf ( ) |
@@ -1,34 +0,0 @@ | |||
Find_Library ( MARIADB_LIBRARY | |||
NAMES mariadb mysql | |||
PATH_SUFFIXES mariadb ) | |||
Find_File ( MARIADB_INCLUDE_DIR | |||
NAMES mysql.h | |||
PATH_SUFFIXES mariadb ) | |||
Get_Filename_Component ( MARIADB_INCLUDE_DIR | |||
${MARIADB_INCLUDE_DIR} | |||
DIRECTORY ) | |||
Include ( FindPackageHandleStandardArgs ) | |||
Find_Package_Handle_Standard_Args ( mariadb DEFAULT_MSG | |||
MARIADB_LIBRARY | |||
MARIADB_INCLUDE_DIR ) | |||
Mark_As_Advanced ( MARIADB_LIBRARY | |||
MARIADB_LIBRARIES ) | |||
If ( MARIADB_FOUND ) | |||
Set ( MARIADB_LIBRARIES ${MARIADB_LIBRARY} ) | |||
Set ( MARIADB_INCLUDE_DIRS ${MARIADB_INCLUDE_DIR} ) | |||
If ( NOT TARGET mariadb ) | |||
Add_Library ( mariadb UNKNOWN IMPORTED ) | |||
Set_Property ( TARGET mariadb | |||
PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${MARIADB_INCLUDE_DIRS}" ) | |||
Set_Property ( TARGET mariadb | |||
APPEND | |||
PROPERTY IMPORTED_LOCATION "${MARIADB_LIBRARY}") | |||
EndIf ( ) | |||
EndIf ( ) |
@@ -0,0 +1,10 @@ | |||
# cpphibernate-config.cmake - package configuration file | |||
Message ( WARNING "Please configure the dependencies of this package!" ) | |||
# Include ( CMakeFindDependencyMacro ) | |||
# Find_Dependency ( <dependency> ) | |||
Include ( FindPackageHandleStandardArgs ) | |||
Set ( ${CMAKE_FIND_PACKAGE_NAME}_CONFIG ${CMAKE_CURRENT_LIST_FILE} ) | |||
Find_Package_Handle_Standard_Args ( cpphibernate CONFIG_MODE ) | |||
Include ( "${CMAKE_CURRENT_LIST_DIR}/cpphibernate.cmake") |
@@ -0,0 +1,15 @@ | |||
Option ( CPPHIBERNATE_INSTALL_HEADER | |||
"Install headers of cpphibernate." | |||
ON ) | |||
Option ( CPPHIBERNATE_INSTALL_STATIC | |||
"Install static library of cpphibernate." | |||
ON ) | |||
Option ( CPPHIBERNATE_INSTALL_SHARED | |||
"Install shared library of cpphibernate." | |||
ON ) | |||
Option ( CPPHIBERNATE_INSTALL_DEBUG | |||
"Install the stripped debug informations of cpphibernate." | |||
OFF ) | |||
Option ( CPPHIBERNATE_NO_STRIP | |||
"Do not strip debug symbols from binary." | |||
OFF ) |
@@ -0,0 +1,31 @@ | |||
# Version | |||
Set ( CPPHIBERNATE_VERSION_MAJOR 1 ) | |||
Set ( CPPHIBERNATE_VERSION_MINOR 0 ) | |||
Set ( CPPHIBERNATE_VERSION_PATCH 0 ) | |||
Set ( CPPHIBERNATE_VERSION_BUILD 0 ) | |||
Set ( CPPHIBERNATE_VERSION_SHORT "${CPPHIBERNATE_VERSION_MAJOR}.${CPPHIBERNATE_VERSION_MINOR}" ) | |||
Set ( CPPHIBERNATE_VERSION "${CPPHIBERNATE_VERSION_SHORT}.${CPPHIBERNATE_VERSION_PATCH}.${CPPHIBERNATE_VERSION_BUILD}" ) | |||
Set ( CPPHIBERNATE_NAME "cpphibernate-${CPPHIBERNATE_VERSION_SHORT}" ) | |||
Set ( CPPHIBERNATE_OUTPUTNAME "cpphibernate" ) | |||
# Install directories | |||
Set ( CPPHIBERNATE_INSTALL_DIR_INCLUDE "include/${CPPHIBERNATE_NAME}" ) | |||
Set ( CPPHIBERNATE_INSTALL_DIR_LIB "lib" ) | |||
Set ( CPPHIBERNATE_INSTALL_DIR_SHARE "share/${CPPHIBERNATE_NAME}" ) | |||
# C Standard | |||
Set ( CMAKE_C_STANDARD 11 ) | |||
Set ( CMAKE_CXX_STANDARD 17 ) | |||
Set ( CMAKE_C_STANDARD_REQUIRED ON ) | |||
Set ( CMAKE_CXX_STANDARD_REQUIRED ON ) | |||
# Git Version | |||
Include ( git_helper OPTIONAL RESULT_VARIABLE HAS_GIT_HELPER ) | |||
If ( HAS_GIT_HELPER ) | |||
GitGetVersion ( ${CMAKE_CURRENT_LIST_DIR}/.. | |||
CPPHIBERNATE_VERSION_MAJOR | |||
CPPHIBERNATE_VERSION_MINOR | |||
CPPHIBERNATE_VERSION_PATCH | |||
CPPHIBERNATE_VERSION_BUILD | |||
CPPHIBERNATE_VERSION_HASH ) | |||
EndIf ( ) |
@@ -1 +1 @@ | |||
Subproject commit b125a1a176ae0aada1cd2ec90919061d202dcea9 | |||
Subproject commit 1a32531aef2deeebd5637b1873bc4e976628801c |
@@ -1,9 +0,0 @@ | |||
Option ( CPPHIBERNATE_BUILD_SHARED | |||
"Build cpphibernate shared library" | |||
ON ) | |||
Option ( CPPHIBERNATE_INSTALL_DEV_FILES | |||
"Install development files of cpphibernate" | |||
ON ) | |||
Option ( CPPHIBERNATE_DEBUG | |||
"Enable debug output" | |||
OFF ) |
@@ -1 +0,0 @@ | |||
#cmakedefine CPPHIBERNATE_DEBUG |
@@ -1,8 +1,5 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/context.h> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/modifier.h> | |||
#include <cpphibernate/schema.h> | |||
#include <cpphibernate/types.h> | |||
#include "cpphibernate/misc.h" | |||
#include "cpphibernate/schema.h" | |||
#include "cpphibernate/types.h" |
@@ -1,73 +1,12 @@ | |||
#pragma once | |||
#include <cppmp.h> | |||
#include <boost/hana.hpp> | |||
#include <cpputils/mp/core.h> | |||
#include <cpphibernate/options.h> | |||
#ifdef CPPHIBERNATE_DEBUG | |||
# include <cpputils/logging/global.h> | |||
# define cpphibernate_debug_log(...) log_global_message(debug) << __VA_ARGS__ | |||
#else | |||
# define cpphibernate_debug_log(...) do { } while(0) | |||
#endif | |||
#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) | |||
#define beg_namespace_cpphibernate_modifier cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, modifier) | |||
#define end_namespace_cpphibernate_modifier cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||
#define beg_namespace_cpphibernate_driver cpphibernate_define_namespace_beg(beg_namespace_cpphibernate, driver) | |||
#define end_namespace_cpphibernate_driver cpphibernate_define_namespace_end(end_namespace_cpphibernate) | |||
#define beg_namespace_cpphibernate_driver_mariadb cpphibernate_define_namespace_beg(beg_namespace_cpphibernate_driver, mariadb_impl) | |||
#define end_namespace_cpphibernate_driver_mariadb cpphibernate_define_namespace_end(end_namespace_cpphibernate_driver) | |||
beg_namespace_cpphibernate | |||
namespace cpphibernate | |||
{ | |||
namespace mp = ::utl::mp; | |||
namespace mp = ::cppmp; | |||
namespace hana = ::boost::hana; | |||
} | |||
end_namespace_cpphibernate |
@@ -1,123 +0,0 @@ | |||
#pragma once | |||
#include <memory> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/schema/table.h> | |||
#include <cpphibernate/schema/tables.h> | |||
#include <cpphibernate/modifier/where.h> | |||
#include <cpphibernate/modifier/modifiers.h> | |||
beg_namespace_cpphibernate | |||
{ | |||
namespace __impl | |||
{ | |||
template<typename T_driver, typename T_schema> | |||
struct context_t | |||
: public T_driver | |||
{ | |||
public: | |||
using base_type = T_driver; | |||
using driver_type = T_driver; | |||
using schema_type = T_schema; | |||
private: | |||
const schema_type& _schema; | |||
public: | |||
template<typename... T_args> | |||
constexpr context_t(const schema_type& p_schema, T_args&&... args) | |||
: base_type (p_schema, std::forward<T_args>(args)...) | |||
, _schema (p_schema) | |||
{ } | |||
cpphibernate_copyable(context_t, delete); | |||
cpphibernate_moveable(context_t, default); | |||
/* init */ | |||
inline void init(bool recreate) | |||
{ this->init_impl(recreate); } | |||
/* create */ | |||
template<typename T_dataset> | |||
constexpr void create(T_dataset& dataset) | |||
{ this->create_impl(dataset); } | |||
/* read */ | |||
template<typename T_dataset, typename... T_modifiers> | |||
constexpr auto read(T_dataset& dataset, T_modifiers&&... modifiers) | |||
-> mp::enable_if< | |||
modifier::all_are_modifiers<mp::decay_t<T_modifiers>...>> | |||
{ | |||
using namespace modifier; | |||
using real_dataset_type = misc::real_dataset_t<mp::decay_t<T_dataset>>; | |||
schema::tables::find(_schema.tables, hana::type_c<real_dataset_type>); | |||
this->read_impl(dataset, modifier::make_list(std::forward<T_modifiers>(modifiers)...)); | |||
} | |||
template<typename T_dataset> | |||
constexpr auto read(T_dataset& dataset) | |||
-> mp::enable_if_c< | |||
!misc::is_container<mp::decay_t<T_dataset>>::value | |||
&& !misc::is_nullable<mp::decay_t<T_dataset>>::value> | |||
{ | |||
using namespace modifier; | |||
using real_dataset_type = misc::real_dataset_t<mp::decay_t<T_dataset>>; | |||
auto& table = schema::tables::find(_schema.tables, hana::type_c<real_dataset_type>); | |||
auto& primary_key = schema::table::get_primary_key_field(table); | |||
this->read_impl(dataset, modifier::make_list(where(equal(primary_key, primary_key.getter(dataset))))); | |||
} | |||
template<typename T_dataset> | |||
constexpr auto read(T_dataset& dataset) | |||
-> mp::enable_if_c< | |||
misc::is_container<mp::decay_t<T_dataset>>::value | |||
|| misc::is_nullable<mp::decay_t<T_dataset>>::value> | |||
{ | |||
using namespace modifier; | |||
using real_dataset_type = misc::real_dataset_t<mp::decay_t<T_dataset>>; | |||
schema::tables::find(_schema.tables, hana::type_c<real_dataset_type>); | |||
this->read_impl(dataset, modifier::make_list()); | |||
} | |||
/* update */ | |||
template<typename T_dataset> | |||
constexpr void update(T_dataset& dataset) | |||
{ this->update_impl(dataset); } | |||
/* destroy */ | |||
template<typename T_dataset> | |||
constexpr void destroy(T_dataset& dataset) | |||
{ this->destroy_impl(dataset); } | |||
}; | |||
} | |||
/* make */ | |||
template<typename T_driver, typename T_schema, typename... T_args> | |||
constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args) | |||
{ | |||
using context_type = __impl::context_t<T_driver, T_schema>; | |||
return context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...); | |||
} | |||
template<typename T_driver, typename T_schema, typename... T_args> | |||
constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args) | |||
{ | |||
using context_type = __impl::context_t<T_driver, T_schema>; | |||
using pointer_type = std::unique_ptr<context_type>; | |||
return pointer_type(new context_type(std::forward<T_schema>(schema), std::forward<T_args>(args)...)); | |||
} | |||
} | |||
end_namespace_cpphibernate |
@@ -1,8 +1,6 @@ | |||
#pragma once | |||
#include <cpphibernate/misc/container_helper.h> | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/misc/meta.h> | |||
#include <cpphibernate/misc/nullable_helper.h> | |||
#include <cpphibernate/misc/print.h> | |||
#include <cpphibernate/misc/wrap.h> | |||
#include "misc/equality_compare.h" | |||
#include "misc/print_container.h" | |||
#include "misc/printing.h" | |||
#include "misc/type_helper.h" |
@@ -1,52 +0,0 @@ | |||
#pragma once | |||
#include <set> | |||
#include <list> | |||
#include <vector> | |||
#include <cpphibernate/config.h> | |||
beg_namespace_cpphibernate_misc | |||
{ | |||
/* container_helper */ | |||
template<typename T_container, typename = void> | |||
struct container_helper; | |||
template<typename T_value, typename... T_args> | |||
struct container_helper<std::vector<T_value, T_args...>, void> | |||
{ | |||
using container_type = std::vector<T_value, T_args...>; | |||
using value_type = T_value; | |||
template<typename... T_xargs> | |||
static inline value_type& emplace(container_type& container, T_xargs&&... args) | |||
{ | |||
container.emplace_back(std::forward<T_xargs>(args)...); | |||
return container.back(); | |||
} | |||
static inline void clear(container_type& container) | |||
{ container.clear(); } | |||
}; | |||
template<typename T_value, typename... T_args> | |||
struct container_helper<std::list<T_value, T_args...>, void> | |||
{ | |||
using container_type = std::list<T_value, T_args...>; | |||
using value_type = T_value; | |||
template<typename... T_xargs> | |||
static inline value_type& emplace(container_type& container, T_xargs&&... args) | |||
{ | |||
container.emplace_back(std::forward<T_xargs>(args)...); | |||
return container.back(); | |||
} | |||
static inline void clear(container_type& container) | |||
{ container.clear(); } | |||
}; | |||
} | |||
end_namespace_cpphibernate_misc |
@@ -0,0 +1,30 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
namespace cpphibernate | |||
{ | |||
/** | |||
* @brief Tag all objects that are equality comparable to each other. | |||
* | |||
* @tparam T_group Type used for groupig different types. | |||
*/ | |||
template<typename T_group> | |||
struct tag_equality_comparable; | |||
/** | |||
* @brief Equality compare for all objects that has the quality compare tag | |||
*/ | |||
template<typename T_lhs, typename T_rhs> | |||
constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs); | |||
/** | |||
* @brief Equality compare for all objects that has the quality compare tag | |||
*/ | |||
template<typename T_lhs, typename T_rhs> | |||
constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs); | |||
} | |||
#include "equality_compare.inl" |
@@ -0,0 +1,61 @@ | |||
#pragma once | |||
#include "equality_compare.h" | |||
namespace cpphibernate | |||
{ | |||
namespace __impl | |||
{ | |||
template<typename T_lhs, typename T_rhs, typename = void> | |||
struct equality_compare_impl | |||
{ | |||
static constexpr decltype(auto) equal(T_lhs&&, T_rhs&&) | |||
{ static_assert(sizeof(T_lhs) == -1, "Unable to equality compare these two types."); } | |||
static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&) | |||
{ static_assert(sizeof(T_lhs) == -1, "Unable to equality compare these two types."); } | |||
}; | |||
template<typename T_lhs, typename T_rhs> | |||
struct equality_compare_impl< | |||
T_lhs, | |||
T_rhs, | |||
mp::enable_if_t< | |||
mp::is_valid_v<typename T_lhs::equality_compare_group_type> | |||
&& mp::is_valid_v<typename T_rhs::equality_compare_group_type> | |||
&& mp::is_same_v< | |||
typename T_lhs::equality_compare_group_type, | |||
typename T_rhs::equality_compare_group_type>>> | |||
{ | |||
static constexpr decltype(auto) equal(T_lhs&&, T_rhs&&) | |||
{ return hana::type_c<mp::decay_t<T_lhs>> == hana::type_c<mp::decay_t<T_rhs>>; } | |||
static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&) | |||
{ return hana::type_c<mp::decay_t<T_lhs>> != hana::type_c<mp::decay_t<T_rhs>>; } | |||
}; | |||
}; | |||
template<typename T_group> | |||
struct tag_equality_comparable | |||
{ | |||
using equality_compare_group_type = T_group; | |||
}; | |||
template<typename T_lhs, typename T_rhs> | |||
constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs) | |||
{ | |||
using equality_compare_type = __impl::equality_compare_impl<T_lhs, T_rhs>; | |||
return equality_compare_type::equal(std::forward<T_lhs>(lhs), std::forward<T_rhs>(rhs)); | |||
} | |||
template<typename T_lhs, typename T_rhs> | |||
constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs) | |||
{ | |||
using equality_compare_type = __impl::equality_compare_impl<T_lhs, T_rhs>; | |||
return equality_compare_type::not_equal(std::forward<T_lhs>(lhs), std::forward<T_rhs>(rhs)); | |||
} | |||
} |
@@ -1,32 +0,0 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpputils/misc/type_helper.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)...); } | |||
}; | |||
/* get_dataset_id */ | |||
namespace __impl | |||
{ | |||
struct counter_type_id | |||
{ }; | |||
} | |||
template<typename T_type> | |||
constexpr decltype(auto) get_type_id(T_type&&) | |||
{ return utl::get_unique_id<__impl::counter_type_id, mp::decay_t<T_type>>(); } | |||
} | |||
end_namespace_cpphibernate_misc |
@@ -1,152 +0,0 @@ | |||
#pragma once | |||
#include <list> | |||
#include <vector> | |||
#include <memory> | |||
#include <cpphibernate/config.h> | |||
#include <cpputils/misc/exception.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, typename... T_args> | |||
struct is_container_impl<std::list<T, T_args...>> | |||
: public mp::c_true_t | |||
{ }; | |||
template<typename T, typename... T_args> | |||
struct is_container_impl<std::vector<T, T_args...>> | |||
: 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 | |||
{ }; | |||
/* is_ordered_impl */ | |||
template<typename T> | |||
struct is_ordered_impl | |||
: public mp::c_false_t | |||
{ }; | |||
template<typename T, typename... T_args> | |||
struct is_ordered_impl<std::list<T, T_args...>> | |||
: public mp::c_true_t | |||
{ }; | |||
template<typename T, typename... T_args> | |||
struct is_ordered_impl<std::vector<T, T_args...>> | |||
: 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, typename... T_args> | |||
struct real_dataset_impl<std::unique_ptr<T, T_args...>, 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, typename... T_args> | |||
struct real_dataset_impl<std::list<T, T_args...>, void> | |||
{ using type = typename real_dataset_impl<T>::type; }; | |||
template<typename T, typename... T_args> | |||
struct real_dataset_impl<std::vector<T, T_args...>, void> | |||
{ using type = typename real_dataset_impl<T>::type; }; | |||
} | |||
/* 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_ordered | |||
: public __impl::is_ordered_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; | |||
/* hibernate_exception */ | |||
struct hibernate_exception | |||
: public utl::exception | |||
{ | |||
using utl::exception::exception; | |||
}; | |||
} | |||
end_namespace_cpphibernate_misc |
@@ -1,120 +0,0 @@ | |||
#pragma once | |||
#include <memory> | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/meta.h> | |||
#include <cpputils/container/nullable.h> | |||
beg_namespace_cpphibernate_misc | |||
{ | |||
/* nullable_helper */ | |||
template<typename T_nullable, typename = void> | |||
struct nullable_helper | |||
{ | |||
using nullable_type = T_nullable; | |||
using value_type = real_dataset_t<nullable_type>; | |||
static value_type* get (const nullable_type&) = delete; | |||
static value_type& set (nullable_type&, const value_type&) = delete; | |||
static void clear (nullable_type&) = delete; | |||
}; | |||
/* nullable_helper - utl::nullable */ | |||
template<typename T_value> | |||
struct nullable_helper<utl::nullable<T_value>, void> | |||
{ | |||
using nullable_type = utl::nullable<T_value>; | |||
using value_type = T_value; | |||
static inline value_type* get(nullable_type& x) | |||
{ return x.has_value() ? &x.value() : nullptr; } | |||
static inline const value_type* get(const nullable_type& x) | |||
{ return x.has_value() ? &x.value() : nullptr; } | |||
static inline value_type& set(nullable_type& x, const value_type* value) | |||
{ return *(x = *value); } | |||
static inline value_type& set(nullable_type& x, const value_type& value) | |||
{ return *(x = value); } | |||
static inline value_type& set(nullable_type& x, value_type&& value) | |||
{ return *(x = std::move(value)); } | |||
static void clear(nullable_type& x) | |||
{ x.reset(); } | |||
}; | |||
/* nullable_helper - std::unique_ptr */ | |||
template<typename T_value> | |||
struct nullable_helper<std::unique_ptr<T_value>, void> | |||
{ | |||
using nullable_type = std::unique_ptr<T_value>; | |||
using value_type = T_value; | |||
static inline value_type* get(const nullable_type& x) | |||
{ return x.get(); } | |||
static inline value_type& set(nullable_type& x, value_type* value) | |||
{ | |||
x.reset(value); | |||
return *x; | |||
} | |||
static inline value_type& set(nullable_type& x, const value_type& value) | |||
{ | |||
x.reset(new value_type(value)); | |||
return *x; | |||
} | |||
static inline value_type& set(nullable_type& x, value_type&& value) | |||
{ | |||
x.reset(new value_type(std::move(value))); | |||
return *x; | |||
} | |||
static void clear(nullable_type& x) | |||
{ return x.reset(); } | |||
}; | |||
/* nullable_helper - std::shared_ptr */ | |||
template<typename T_value> | |||
struct nullable_helper<std::shared_ptr<T_value>, void> | |||
{ | |||
using nullable_type = std::shared_ptr<T_value>; | |||
using value_type = T_value; | |||
static inline value_type* get(const nullable_type& x) | |||
{ return x.get(); } | |||
static inline value_type& set(nullable_type& x, value_type* value) | |||
{ | |||
x.reset(value); | |||
return *x; | |||
} | |||
static inline value_type& set(nullable_type& x, const value_type& value) | |||
{ | |||
x.reset(new value_type(value)); | |||
return *x; | |||
} | |||
static inline value_type& set(nullable_type& x, value_type&& value) | |||
{ | |||
x.reset(new value_type(std::move(value))); | |||
return *x; | |||
} | |||
static void clear(nullable_type& x) | |||
{ return x.reset(); } | |||
}; | |||
} | |||
end_namespace_cpphibernate_misc |
@@ -1,112 +0,0 @@ | |||
#pragma once | |||
#include <list> | |||
#include <vector> | |||
#include <memory> | |||
#include <iostream> | |||
#include <cpphibernate/config.h> | |||
#include <cpputils/misc/indent.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; | |||
} | |||
} | |||
beg_namespace_cpphibernate_misc | |||
{ | |||
template<typename T_container, typename T_func> | |||
struct container_printer | |||
{ | |||
T_container container; | |||
bool do_indent; | |||
T_func func; | |||
inline void print(std::ostream& os) const | |||
{ | |||
using namespace ::utl; | |||
auto beg = std::begin(container); | |||
auto end = std::end (container); | |||
if (beg != end) | |||
{ | |||
if (do_indent) | |||
{ | |||
os << indent << "[" | |||
<< incindent; | |||
} | |||
else | |||
{ | |||
os << "["; | |||
} | |||
size_t index = 0; | |||
for (auto it = beg; it != end; ++it) | |||
{ | |||
if (index++) | |||
os << ","; | |||
if (!do_indent) | |||
os << " "; | |||
func(os, *it); | |||
} | |||
if (do_indent) | |||
{ | |||
os << decindent | |||
<< indent << "]"; | |||
} | |||
else | |||
{ | |||
os << " ]"; | |||
} | |||
} | |||
else | |||
{ | |||
os << "[ ]"; | |||
} | |||
} | |||
}; | |||
struct print_container_builder | |||
{ | |||
template<typename T_container, typename T_func> | |||
constexpr decltype(auto) operator()(T_container&& container, bool do_indent, T_func&& func) const | |||
{ | |||
return container_printer<T_container, T_func> | |||
{ | |||
std::forward<T_container>(container), | |||
do_indent, | |||
std::forward<T_func>(func) | |||
}; | |||
} | |||
template<typename T_container> | |||
constexpr decltype(auto) operator()(T_container&& container, bool do_indent) const | |||
{ | |||
return this->operator()( | |||
std::forward<T_container>(container), | |||
do_indent, | |||
[do_indent](auto& os, auto& value) | |||
{ | |||
using namespace ::utl; | |||
if (do_indent) | |||
os << indent; | |||
os << utl::to_string(value); | |||
}); | |||
} | |||
}; | |||
constexpr decltype(auto) print_container = print_container_builder { }; | |||
} | |||
end_namespace_cpphibernate_misc |
@@ -0,0 +1,26 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
namespace cpphibernate | |||
{ | |||
namespace __impl | |||
{ | |||
/** | |||
* @brief Helper type to build print container. | |||
*/ | |||
template<typename X, typename = void> | |||
struct print_container_builder; | |||
} | |||
/** | |||
* @brief Predicate to create print container from the passed attributes. | |||
*/ | |||
constexpr decltype(auto) make_print_container = mp::generic_predicate<__impl::print_container_builder> { }; | |||
} | |||
#include "print_container.inl" |
@@ -0,0 +1,116 @@ | |||
#pragma once | |||
#include <cppcore/misc/indent.h> | |||
#include "print_container.h" | |||
namespace cpphibernate | |||
{ | |||
namespace __impl | |||
{ | |||
/* print_container */ | |||
template<typename T_container, typename T_func> | |||
struct print_container | |||
{ | |||
using container_type = T_container; | |||
using func_type = T_func; | |||
container_type container; | |||
bool do_indent; | |||
func_type func; | |||
inline void print(std::ostream& os) const | |||
{ | |||
using namespace ::cppcore; | |||
auto beg = std::begin(container); | |||
auto end = std::end (container); | |||
if (beg != end) | |||
{ | |||
if (do_indent) | |||
{ | |||
os << indent << "[" | |||
<< incindent; | |||
} | |||
else | |||
{ | |||
os << "["; | |||
} | |||
size_t index = 0; | |||
for (auto it = beg; it != end; ++it) | |||
{ | |||
if (index++) | |||
os << ","; | |||
if (!do_indent) | |||
os << " "; | |||
func(os, *it); | |||
} | |||
if (do_indent) | |||
{ | |||
os << decindent | |||
<< indent << "]"; | |||
} | |||
else | |||
{ | |||
os << " ]"; | |||
} | |||
} | |||
else | |||
{ | |||
os << "[ ]"; | |||
} | |||
} | |||
}; | |||
/* print_container_builder */ | |||
template<typename X, typename> | |||
struct print_container_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_print_container(...)!"); } | |||
}; | |||
template<typename T_container, typename T_func> | |||
struct print_container_builder<mp::list<T_container, bool, T_func>, void> | |||
{ | |||
static constexpr decltype(auto) apply(T_container&& container, bool do_indent, T_func&& func) | |||
{ | |||
using print_container_type = print_container<T_container, T_func>; | |||
return print_container_type { | |||
std::forward<T_container>(container), | |||
do_indent, | |||
std::forward<T_func>(func), | |||
}; | |||
} | |||
}; | |||
template<typename T_container> | |||
struct print_container_builder<mp::list<T_container, bool>, void> | |||
{ | |||
static constexpr decltype(auto) apply(T_container&& container, bool do_indent) | |||
{ | |||
using namespace ::cppcore; | |||
make_print_container( | |||
std::forward<T_container>(container), | |||
do_indent, | |||
[do_indent](auto& os, auto& value) | |||
{ | |||
using namespace ::cppcore; | |||
if (do_indent) | |||
os << indent; | |||
os << to_string(value); | |||
}); | |||
} | |||
}; | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
#pragma once | |||
#include <iostream> | |||
#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) | |||
-> ::cppmp::enable_if_t< | |||
::cppmp::is_valid_v<decltype(std::forward<X>(x).print(os))>, | |||
basic_ostream<T_char, T_traits>&> | |||
{ | |||
std::forward<X>(x).print(os); | |||
return os; | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
namespace cpphibernate | |||
{ | |||
/** | |||
* @brief Evaluates to the basic dataset type (containers are removed). | |||
*/ | |||
template<typename T> | |||
struct real_dataset; | |||
/** | |||
* @brief Basic dataset type (containers are removed). | |||
*/ | |||
template<typename T> | |||
using real_dataset_t = typename real_dataset<T>::type; | |||
/** | |||
* @brief Extract the type stored in an type definition . | |||
*/ | |||
template<typename T> | |||
using unwrap_t = typename T::type; | |||
/** | |||
* @brief Extract the decayed type in an type definition. | |||
*/ | |||
template<typename T> | |||
using decay_unwrap_t = typename mp::decay_t<T>::type; | |||
} | |||
#include "type_helper.inl" |
@@ -0,0 +1,53 @@ | |||
#pragma once | |||
#include "type_helper.h" | |||
#include <list> | |||
#include <vector> | |||
#include <memory> | |||
#include <cppcore/misc/nullable.h> | |||
#include <cpphibernate/config.h> | |||
namespace cpphibernate | |||
{ | |||
namespace __impl | |||
{ | |||
/* real_dataset_impl */ | |||
template<typename T, typename = void> | |||
struct real_dataset_impl | |||
{ using type = T; }; | |||
template<typename T> | |||
struct real_dataset_impl<cppcore::nullable<T>, void> | |||
{ using type = typename real_dataset_impl<T>::type; }; | |||
template<typename T, typename... T_args> | |||
struct real_dataset_impl<std::unique_ptr<T, T_args...>, 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, typename... T_args> | |||
struct real_dataset_impl<std::list<T, T_args...>, void> | |||
{ using type = typename real_dataset_impl<T>::type; }; | |||
template<typename T, typename... T_args> | |||
struct real_dataset_impl<std::vector<T, T_args...>, void> | |||
{ using type = typename real_dataset_impl<T>::type; }; | |||
} | |||
/* real_dataset */ | |||
template<typename T> | |||
struct real_dataset | |||
: public __impl::real_dataset_impl<T> | |||
{ }; | |||
} |
@@ -1,44 +0,0 @@ | |||
#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 |
@@ -1,8 +0,0 @@ | |||
#pragma once | |||
#include <cpphibernate/modifier/limit.h> | |||
#include <cpphibernate/modifier/modifier.h> | |||
#include <cpphibernate/modifier/modifiers.h> | |||
#include <cpphibernate/modifier/offset.h> | |||
#include <cpphibernate/modifier/order_by.h> | |||
#include <cpphibernate/modifier/where.h> |
@@ -1,12 +1,11 @@ | |||
#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/schema.h> | |||
#include <cpphibernate/schema/setter.h> | |||
#include <cpphibernate/schema/table.h> | |||
#include <cpphibernate/schema/tables.h> | |||
#include "schema/macros.h" | |||
#include "schema/attribute.h" | |||
#include "schema/attributes.h" | |||
#include "schema/field.h" | |||
#include "schema/fields.h" | |||
#include "schema/table.h" | |||
#include "schema/tables.h" | |||
#include "schema/schema.h" |
@@ -1,23 +1,31 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/equality_compare.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* attribute_t */ | |||
/** | |||
* @brief Tag class to mark attribute types. | |||
*/ | |||
struct tag_attribute | |||
{ }; | |||
/** | |||
* @brief Attribute implementation. | |||
*/ | |||
template<typename T_inner> | |||
struct attribute_t | |||
: public T_inner | |||
, public tag_attribute | |||
, public tag_equality_comparable<tag_attribute> | |||
{ | |||
using inner_type = T_inner; | |||
using this_type = attribute_t<inner_type>; | |||
cpphibernate_equality_comparable(); | |||
}; | |||
struct hex_t { static constexpr decltype(auto) name = "hex"; }; | |||
@@ -29,32 +37,39 @@ beg_namespace_cpphibernate_schema | |||
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>; | |||
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 { }; | |||
/** | |||
* @brief Attribute to indicate that the value is stored as hexadecimal string. | |||
*/ | |||
constexpr hex_type hex { }; | |||
/** value is stored as compressed binary, and will be uncompressed on read */ | |||
constexpr compress_type compress { }; | |||
/** | |||
* @brief Attribute to indicate that the value is stored compressed. | |||
*/ | |||
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 { }; | |||
/** | |||
* @brief Attribute to indicate that the value is the primary key field. | |||
*/ | |||
constexpr primary_key_type primary_key { }; | |||
} | |||
/* meta */ | |||
/** | |||
* @brief Evaluates to true_t if the passed type is an attribute type. | |||
*/ | |||
template<typename T> | |||
struct is_attribute; | |||
/** | |||
* @brief Is true if the passed type is an attribute, false otherwise. | |||
*/ | |||
template<typename T> | |||
struct is_attribute | |||
: public mp::is_specialization_of<T, __impl::attribute_t> | |||
{ }; | |||
constexpr bool is_attribute_v = is_attribute<T>::value; | |||
template<typename... T> | |||
struct all_are_attribures | |||
: public mp::all_true<is_attribute<T>::value...> | |||
{ }; | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "attribute.inl" |
@@ -0,0 +1,15 @@ | |||
#pragma once | |||
#include "attribute.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
/* is_attribute */ | |||
template<typename T> | |||
struct is_attribute | |||
: public mp::is_base_of<__impl::tag_attribute, T> | |||
{ }; | |||
} } |
@@ -1,73 +1,39 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/schema/attribute.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* attributes_t */ | |||
template<typename... T_attributes> | |||
using attributes_t = hana::tuple<T_attributes...>; | |||
/* is_attributes_impl */ | |||
/** | |||
* @brief Helper type to build attributes. | |||
*/ | |||
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 | |||
{ }; | |||
struct attributes_builder; | |||
} | |||
/* meta */ | |||
/** | |||
* @brief Evaluates to true_t if the passed type is a attributes type. | |||
*/ | |||
template<typename T> | |||
struct is_attributes | |||
: public __impl::is_attributes_impl<T> | |||
{ }; | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
struct is_attributes; | |||
/* attributes_make_impl */ | |||
template<typename T, typename = void> | |||
struct attributes_make_impl | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for hibernate::schema::attributes::make(...)!"); } | |||
}; | |||
template<typename... T> | |||
struct attributes_make_impl<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>...> { }; } | |||
}; | |||
} | |||
namespace attributes | |||
{ | |||
/** | |||
* @brief Is true if the passed type is an attributes type, false otherwise. | |||
*/ | |||
template<typename T> | |||
constexpr bool is_attributes_v = is_attributes<T>::value; | |||
constexpr decltype(auto) make = misc::make_generic_predicate<__impl::attributes_make_impl> { }; | |||
/** | |||
* @brief Predicate to create an attributes object from the passed attributes. | |||
*/ | |||
constexpr decltype(auto) make_attributes = mp::generic_predicate<__impl::attributes_builder> { }; | |||
} | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "attributes.inl" |
@@ -0,0 +1,62 @@ | |||
#pragma once | |||
#include "attributes.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* attributes_t */ | |||
template<typename... T_attributes> | |||
using attributes_t = hana::basic_tuple<T_attributes...>; | |||
/* attributes_builder */ | |||
template<typename T, typename> | |||
struct attributes_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_attributes(...)!"); } | |||
}; | |||
template<typename... T> | |||
struct attributes_builder< | |||
mp::list<T...>, | |||
mp::enable_if_t< | |||
mp::is_true_v<is_attribute_v<mp::decay_t<T>>...>>> | |||
{ | |||
static constexpr decltype(auto) apply(T&&...) | |||
{ | |||
using attributes_type = attributes_t<mp::decay_t<T>...>; | |||
return attributes_type { }; | |||
} | |||
}; | |||
/* is_attributes_impl */ | |||
template<typename T, typename = void> | |||
struct is_attributes_impl | |||
: mp::false_t | |||
{ }; | |||
template<typename... T> | |||
struct is_attributes_impl< | |||
attributes_t<T...>, | |||
mp::enable_if_t<mp::is_true_v<is_attribute_v<mp::decay_t<T>>...>>> | |||
: mp::true_t | |||
{ }; | |||
} | |||
/* is_attributes */ | |||
template<typename T> | |||
struct is_attributes | |||
: public __impl::is_attributes_impl<T> | |||
{ }; | |||
} } |
@@ -1,126 +1,38 @@ | |||
#pragma once | |||
#include <cpphibernate/misc.h> | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/schema/getter.h> | |||
#include <cpphibernate/schema/setter.h> | |||
#include <cpphibernate/schema/attributes.h> | |||
#include <cpputils/misc/indent.h> | |||
#include <cpputils/misc/type_helper.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace 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 << '}'; | |||
} | |||
}; | |||
/** | |||
* @brief Helper type to build field objects. | |||
*/ | |||
template<typename X, typename = void> | |||
struct field_builder; | |||
} | |||
/* meta */ | |||
/** | |||
* @brief Evaluates to true_t if the passed type is a field type. | |||
*/ | |||
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...> | |||
{ }; | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* field_make_impl */ | |||
template<typename X, typename = void> | |||
struct field_make_impl | |||
{ | |||
template <typename ...T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::field::make(...)!"); } | |||
}; | |||
template<typename T_name, typename T_getter, typename T_setter, typename T_attributes> | |||
struct field_make_impl<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>; | |||
struct is_field; | |||
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)); } | |||
}; | |||
} | |||
namespace field | |||
{ | |||
/** | |||
* @brief Is true if the passed type is an attributes type, false otherwise. | |||
*/ | |||
template<typename T> | |||
constexpr bool is_field_v = is_field<T>::value; | |||
constexpr decltype(auto) make = misc::make_generic_predicate<__impl::field_make_impl> { }; | |||
/** | |||
* @brief Predicate to create an field object from the passed attributes. | |||
*/ | |||
constexpr decltype(auto) make_field = mp::generic_predicate<__impl::field_builder> { }; | |||
} | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "field.inl" |
@@ -0,0 +1,132 @@ | |||
#pragma once | |||
#include <cppcore/misc/indent.h> | |||
#include <cppcore/misc/type_helper.h> | |||
#include <cpphibernate/misc/type_helper.h> | |||
#include "field.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* tag_field */ | |||
struct tag_field | |||
{ }; | |||
/* field_t */ | |||
template<typename T_name, typename T_getter, typename T_setter, typename T_attributes> | |||
struct field_t | |||
: public tag_field | |||
, public tag_equality_comparable<tag_field> | |||
{ | |||
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)) | |||
{ } | |||
constexpr field_t(field_t&&) = default; | |||
constexpr field_t(const field_t&) = delete; | |||
constexpr field_t& operator = (field_t&&) = default; | |||
constexpr field_t& operator = (const field_t&) = delete; | |||
inline void print(std::ostream& os) const | |||
{ | |||
using namespace ::cppcore; | |||
using value_type = typename mp::decay_t<getter_type>::value_type; | |||
using dataset_type = real_dataset_t<value_type>; | |||
size_t index = 0; | |||
os << indent << '{' | |||
<< incindent | |||
<< indent << "\"name\": \"" << name << "\"," | |||
<< indent << "\"value_type\": \"" << type_helper<value_type>::name() << "\"" | |||
<< indent << "\"dataset_type\": \"" << 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> | |||
struct field_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for 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_t< | |||
true | |||
// && mp::is_getter_v<mp::decay_t<T_getter>> | |||
// && mp::is_setter_v<mp::decay_t<T_setter>> | |||
// && is_attributes_v<mp::decay_t<T_attributes>> | |||
>> | |||
{ | |||
using name_type = T_name; | |||
using getter_type = T_getter; | |||
using setter_type = T_setter; | |||
using attributes_type = T_attributes; | |||
using field_type = field_t<name_type, getter_type, setter_type, attributes_type>; | |||
static constexpr decltype(auto) apply( | |||
name_type&& name, | |||
getter_type&& getter, | |||
setter_type&& setter, | |||
attributes_type&& attributes) | |||
{ | |||
return field_type( | |||
std::forward<name_type> (name), | |||
std::forward<getter_type> (getter), | |||
std::forward<setter_type> (setter), | |||
std::forward<attributes_type> (attributes)); | |||
} | |||
}; | |||
} | |||
/* is_field */ | |||
template<typename T> | |||
struct is_field | |||
: public mp::is_base_of<__impl::tag_field, T> | |||
{ }; | |||
} } |
@@ -1,72 +1,39 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/schema/field.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* fields_t */ | |||
template<typename... T_fields> | |||
using fields_t = hana::tuple<T_fields...>; | |||
/* is_fields_impl */ | |||
/** | |||
* @brief Helper type to build fields. | |||
*/ | |||
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 | |||
{ }; | |||
struct fields_builder; | |||
} | |||
/* meta */ | |||
/** | |||
* @brief Evaluates to true_t if the passed type is a fields type. | |||
*/ | |||
template<typename T> | |||
struct is_fields : | |||
public __impl::is_fields_impl<T> | |||
{ }; | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
struct is_fields; | |||
/* fields_make_impl */ | |||
template <typename T, typename = void> | |||
struct fields_make_impl | |||
{ | |||
template <typename ...T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::fields::make(...)!"); } | |||
}; | |||
template<typename... T> | |||
struct fields_make_impl<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)...); } | |||
}; | |||
} | |||
namespace fields | |||
{ | |||
/** | |||
* @brief Is true if the passed type is an fields type, false otherwise. | |||
*/ | |||
template<typename T> | |||
constexpr bool is_fields_v = is_fields<T>::value; | |||
constexpr decltype(auto) make = misc::make_generic_predicate<__impl::fields_make_impl> { }; | |||
/** | |||
* @brief Predicate to create an fields object from the passed fields. | |||
*/ | |||
constexpr decltype(auto) make_fields = mp::generic_predicate<__impl::fields_builder> { }; | |||
} | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "fields.inl" |
@@ -0,0 +1,63 @@ | |||
#pragma once | |||
#include "fields.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* fields_t */ | |||
template<typename... T_fields> | |||
using fields_t = hana::basic_tuple<T_fields...>; | |||
/* fields_builder */ | |||
template<typename T, typename> | |||
struct fields_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_fields(...)!"); } | |||
}; | |||
template<typename... T> | |||
struct fields_builder< | |||
mp::list<T...>, | |||
mp::enable_if_t<mp::is_true_v< | |||
is_field_v<mp::decay_t<T>>...>>> | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ | |||
using fields_type = fields_t<T_args...>; | |||
return fields_type(std::forward<T_args>(args)...); | |||
} | |||
}; | |||
/* is_fields_impl */ | |||
template<typename T, typename = void> | |||
struct is_fields_impl | |||
: mp::false_t | |||
{ }; | |||
template<typename... T> | |||
struct is_fields_impl< | |||
fields_t<T...>, | |||
mp::enable_if_t<mp::is_true_v<is_field_v<mp::decay_t<T>>...>>> | |||
: mp::true_t | |||
{ }; | |||
} | |||
/* is_fields */ | |||
template<typename T> | |||
struct is_fields | |||
: public __impl::is_fields_impl<T> | |||
{ }; | |||
} } |
@@ -1,192 +0,0 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/general.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace __impl | |||
{ | |||
/* getter_t */ | |||
template<typename T_dataset, typename T_value> | |||
struct getter_t | |||
{ | |||
using dataset_type = T_dataset; | |||
using value_type = T_value; | |||
}; | |||
/* getter_member_var_t */ | |||
template<typename T_dataset, typename T_value, typename T_member> | |||
struct getter_member_var_t | |||
: public getter_t<T_dataset, T_value> | |||
{ | |||
using base_type = getter_t<T_dataset, T_value>; | |||
using dataset_type = typename base_type::dataset_type; | |||
using value_type = typename base_type::value_type; | |||
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_dataset, T_value> | |||
{ | |||
using base_type = getter_t<T_dataset, T_value>; | |||
using dataset_type = typename base_type::dataset_type; | |||
using value_type = typename base_type::value_type; | |||
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_lambda, typename T_dataset, typename T_value> | |||
struct getter_lambda_t | |||
: public getter_t<T_dataset, T_value> | |||
{ | |||
using base_type = getter_t<T_dataset, T_value>; | |||
using dataset_type = typename base_type::dataset_type; | |||
using value_type = typename base_type::value_type; | |||
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< | |||
mp::is_base_of<getter_t<typename T::dataset_type, typename T::value_type>, T>>> | |||
: public mp::c_true_t | |||
{ }; | |||
} | |||
/* meta */ | |||
template<typename T> | |||
struct is_getter : | |||
public __impl::is_getter_impl<T> | |||
{ }; | |||
/* make */ | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) make_getter_member_var(T_value T_dataset::* member) | |||
{ | |||
using getter_type = __impl::getter_member_var_t<T_dataset, T_value, T_value T_dataset::*>; | |||
return getter_type(member); | |||
} | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)()) | |||
{ | |||
using getter_type = __impl::getter_member_func_t<T_dataset, T_value, T_value (T_dataset::*)()>; | |||
return getter_type(member); | |||
} | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)() const) | |||
{ | |||
using getter_type = __impl::getter_member_func_t<const T_dataset, T_value, T_value (T_dataset::*)() const>; | |||
return getter_type(member); | |||
} | |||
template<typename T_lambda, typename T_wrapped_dataset, typename T_wrapped_value> | |||
constexpr decltype(auto) make_getter_lambda(T_lambda&& lambda, T_wrapped_dataset&&, T_wrapped_value&&) | |||
{ | |||
using getter_type = __impl::getter_lambda_t<T_lambda, misc::decay_unwrap_t<T_wrapped_dataset>, misc::decay_unwrap_t<T_wrapped_value>>; | |||
return getter_type(std::forward<T_lambda>(lambda)); | |||
} | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* getter_make_impl */ | |||
struct getter_make_impl | |||
{ | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(T_value T_dataset::*member) const | |||
{ return make_getter_member_var(member); } | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(T_value (T_dataset::*member)(void)) const | |||
{ return make_getter_member_func(member); } | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(T_value (T_dataset::*member)(void) const) const | |||
{ return make_getter_member_func(member); } | |||
template<typename T_func, typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(T_func&& func, hana::type<T_dataset>&& wrapped_dataset, hana::type<T_value>&& wrapped_value) const | |||
{ return make_getter_lambda(std::forward<T_func>(func), std::forward<hana::type<T_dataset>>(wrapped_dataset), std::forward<hana::type<T_value>>(wrapped_value)); } | |||
template<typename T_getter> | |||
constexpr auto operator()(T_getter&& getter) const | |||
-> mp::enable_if<is_getter<T_getter>, T_getter> | |||
{ return std::forward<T_getter>(getter); } | |||
}; | |||
} | |||
namespace getter | |||
{ | |||
constexpr decltype(auto) make = __impl::getter_make_impl { }; | |||
} | |||
} | |||
end_namespace_cpphibernate_schema |
@@ -1,32 +1,31 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/types.h> | |||
#define cpphibernate_make_string(str) \ | |||
#str | |||
#define cpphibernate_make_schema(p_name, ...) \ | |||
cpphibernate::schema::make( \ | |||
cpphibernate::schema::make_schema( \ | |||
cpphibernate_make_string(p_name), \ | |||
cpphibernate::schema::tables::make(__VA_ARGS__)) | |||
cpphibernate::schema::make_tables(__VA_ARGS__)) | |||
#define cpphibernate_make_table_name(p_name, p_type, p_id, ...) \ | |||
cpphibernate::schema::table::make( \ | |||
cpphibernate::schema::make_table( \ | |||
cpphibernate_make_string(p_name), \ | |||
boost::hana::type_c<p_type>, \ | |||
boost::hana::size_c<p_id>, \ | |||
cpphibernate::schema::fields::make(__VA_ARGS__)) | |||
cpphibernate::schema::make_fields(__VA_ARGS__)) | |||
#define cpphibernate_make_table(p_name, p_id, ...) \ | |||
cpphibernate_make_table_name(p_name, p_name, p_id, __VA_ARGS__) | |||
#define cpphibernate_make_field_custom(p_name, p_getter, p_setter, ...) \ | |||
cpphibernate::schema::field::make( \ | |||
cpphibernate::schema::make_field( \ | |||
cpphibernate_make_string(p_name), \ | |||
cpphibernate::schema::getter::make(p_getter), \ | |||
cpphibernate::schema::setter::make(p_setter), \ | |||
cpphibernate::schema::attributes::make(__VA_ARGS__)) | |||
cpphibernate::mp::make_getter(p_getter), \ | |||
cpphibernate::mp::make_setter(p_setter), \ | |||
cpphibernate::schema::make_attributes(__VA_ARGS__)) | |||
#define cpphibernate_make_field_name(p_name, p_member_ptr, ...) \ | |||
cpphibernate_make_field_custom( \ | |||
@@ -45,14 +44,10 @@ | |||
#define cpphibernate_make_temp_id(p_dataset, p_value) \ | |||
cpphibernate_make_field_custom( \ | |||
id, \ | |||
::cpphibernate::schema::make_getter_lambda( \ | |||
::cpphibernate::mp::make_getter( \ | |||
[](p_dataset&) { \ | |||
return p_value { }; \ | |||
}, \ | |||
::boost::hana::type_c<p_dataset>, \ | |||
::boost::hana::type_c<p_value>), \ | |||
::cpphibernate::schema::make_setter_lambda( \ | |||
[](p_dataset&, p_value&&) { }, \ | |||
::boost::hana::type_c<p_dataset>, \ | |||
::boost::hana::type_c<p_value>), \ | |||
}), \ | |||
::cpphibernate::mp::make_setter( \ | |||
[](p_dataset&, p_value&&) { }), \ | |||
cpphibernate::schema::attribute::primary_key) |
@@ -1,252 +1,38 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/schema/tables.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace 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 << '}'; | |||
} | |||
}; | |||
/** | |||
* @brief Helper type to build schema objects. | |||
*/ | |||
template<typename X, typename = void> | |||
struct schema_builder; | |||
} | |||
/* meta */ | |||
/** | |||
* @brief Evaluates to true_t if the passed type is a schema type. | |||
*/ | |||
template<typename T> | |||
struct is_schema : mp::is_specialization_of<T, __impl::schema_t> { }; | |||
/* schema::make */ | |||
namespace __impl | |||
{ | |||
template <typename X, typename = void> | |||
struct schema_make_impl | |||
{ | |||
template <typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make(...)!"); } | |||
}; | |||
template<typename T_name, typename T_tables> | |||
struct schema_make_impl<mp::list<T_name, T_tables>, mp::enable_if_c< | |||
is_tables<mp::decay_t<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)); } | |||
}; | |||
} | |||
constexpr decltype(auto) make = misc::make_generic_predicate<__impl::schema_make_impl> { }; | |||
/* schema::get_base_type */ | |||
namespace __impl | |||
{ | |||
struct schema_get_base_type_impl | |||
{ | |||
static constexpr decltype(auto) is_base_of_pred = hana::integral(hana::metafunction<mp::is_base_of>); | |||
struct do_fold_impl | |||
{ | |||
template<typename T_type_1, typename T_type_2> | |||
constexpr decltype(auto) operator()(T_type_1&& type_1, T_type_2&& type_2) const | |||
{ | |||
auto check = hana::or_(is_base_of_pred(type_1, type_2), is_base_of_pred(type_2, type_1)); | |||
static_assert(decltype(check)::value, "A dataset must not have more than one base class!"); | |||
return hana::if_(is_base_of_pred(type_1, type_2), type_2, type_1); | |||
} | |||
}; | |||
static constexpr decltype(auto) do_fold = do_fold_impl { }; | |||
template<typename T_wrapped_datasets, typename T_wrapped_dataset> | |||
static constexpr decltype(auto) get_base_types(T_wrapped_datasets&& wrapped_datasets, T_wrapped_dataset&& wrapped_dataset) | |||
{ | |||
return hana::filter( | |||
std::forward<T_wrapped_datasets>(wrapped_datasets), | |||
[&](auto type){ | |||
return hana::and_( | |||
is_base_of_pred(type, wrapped_dataset), | |||
hana::not_equal(type, wrapped_dataset)); | |||
}); | |||
} | |||
template<typename T_schema, typename T_wrapped_dataset> | |||
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const | |||
{ | |||
using wrapped_datasets_type = mp::decay_t<decltype( | |||
hana::transform( | |||
std::declval<T_schema>().tables, | |||
schema::table::get_wrapped_dataset))>; | |||
auto base_types = get_base_types(wrapped_datasets_type { }, std::forward<T_wrapped_dataset>(wrapped_dataset)); | |||
return hana::eval_if( | |||
hana::size(base_types) <= hana::size_c<0>, | |||
[&](auto _){ return hana::type_c<void>; }, | |||
[&](auto _){ return hana::fold(_(base_types), do_fold); }); | |||
} | |||
}; | |||
} | |||
constexpr decltype(auto) get_base_type = __impl::schema_get_base_type_impl { }; | |||
struct is_schema; | |||
/* schema::get_root_base_type */ | |||
namespace __impl | |||
{ | |||
struct schema_get_root_base_type_impl | |||
{ | |||
template<typename T_wrapped_dataset> | |||
struct is_base_pred | |||
{ | |||
using dataset_type = misc::decay_unwrap_t<T_wrapped_dataset>; | |||
template<typename T_type> | |||
constexpr decltype(auto) operator()(T_type&&) const | |||
{ | |||
using type = misc::unwrap_t<T_type>; | |||
return hana::bool_c< | |||
std::is_base_of<type, dataset_type>::value | |||
&& !std::is_same <type, dataset_type>::value>; | |||
} | |||
}; | |||
template<typename T_schema, typename T_wrapped_dataset> | |||
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const | |||
{ | |||
auto all_types = hana::transform( | |||
schema.tables, | |||
table::get_wrapped_dataset); | |||
auto base_type = hana::find_if( | |||
all_types, | |||
is_base_pred<T_wrapped_dataset> { }); | |||
return hana::eval_if( | |||
base_type != hana::nothing, | |||
[&](auto _){ | |||
return schema_get_root_base_type_impl { }(schema, _(base_type).value()); | |||
}, | |||
[&]{ | |||
return wrapped_dataset; | |||
}); | |||
} | |||
}; | |||
} | |||
constexpr decltype(auto) get_root_base_type = __impl::schema_get_root_base_type_impl { }; | |||
/* schema::get_all_derived_types */ | |||
namespace __impl | |||
{ | |||
struct schema_get_all_derived_types_impl | |||
{ | |||
template<typename T_wrapped_dataset> | |||
struct is_derived_pred | |||
{ | |||
using dataset_type = misc::decay_unwrap_t<T_wrapped_dataset>; | |||
template<typename T_type> | |||
constexpr decltype(auto) operator()(T_type&&) const | |||
{ | |||
return hana::bool_c< | |||
std::is_base_of<dataset_type, misc::decay_unwrap_t<T_type>>::value>; | |||
} | |||
}; | |||
template<typename T_schema, typename T_wrapped_dataset> | |||
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&&) const | |||
{ | |||
auto all_types = hana::transform( | |||
schema.tables, | |||
table::get_wrapped_dataset); | |||
auto derived_types = hana::filter( | |||
all_types, | |||
is_derived_pred<T_wrapped_dataset> { }); | |||
return derived_types; | |||
} | |||
}; | |||
} | |||
constexpr decltype(auto) get_all_derived_types = __impl::schema_get_all_derived_types_impl { }; | |||
/* schema::get_derived_types */ | |||
namespace __impl | |||
{ | |||
struct schema_get_derived_types_impl | |||
{ | |||
struct has_base_impl | |||
{ | |||
template<typename T_schema, typename T_base_type, typename T_type> | |||
constexpr decltype(auto) operator()(T_schema&& schema, T_base_type& base_type, T_type&& type) const | |||
{ return get_base_type(schema, type) == base_type; } | |||
}; | |||
static constexpr decltype(auto) has_base = has_base_impl { }; | |||
/** | |||
* @brief Is true if the passed type is an attributes type, false otherwise. | |||
*/ | |||
template<typename T> | |||
constexpr bool is_schema_v = is_schema<T>::value; | |||
template<typename T_schema, typename T_wrapped_dataset> | |||
constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const | |||
{ | |||
using wrapped_datasets_type = mp::decay_t<decltype( | |||
hana::transform( | |||
std::declval<T_schema>().tables, | |||
schema::table::get_wrapped_dataset))>; | |||
using derived_wrapped_datasets_type = mp::decay_t<decltype( | |||
hana::filter( | |||
std::declval<wrapped_datasets_type>(), | |||
hana::partial( | |||
has_base, | |||
std::declval<T_schema>(), | |||
wrapped_dataset)))>; | |||
return derived_wrapped_datasets_type { }; | |||
} | |||
}; | |||
} | |||
/** | |||
* @brief Predicate to create an schema object from the passed attributes. | |||
*/ | |||
constexpr decltype(auto) make_schema = mp::generic_predicate<__impl::schema_builder> { }; | |||
constexpr decltype(auto) get_derived_types = __impl::schema_get_derived_types_impl { }; | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "schema.inl" |
@@ -0,0 +1,102 @@ | |||
#pragma once | |||
#include "schema.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* tag_schema */ | |||
struct tag_schema | |||
{ }; | |||
/* schema_t */ | |||
template<typename T_name, typename T_tables> | |||
struct schema_t | |||
: public tag_schema | |||
, public tag_equality_comparable<tag_schema> | |||
{ | |||
using name_type = T_name; | |||
using tables_type = T_tables; | |||
name_type name; | |||
tables_type tables; | |||
constexpr schema_t( | |||
name_type&& p_name, | |||
tables_type&& p_tables) | |||
: name (std::forward<name_type> (p_name)) | |||
, tables(std::forward<tables_type>(p_tables)) | |||
{ } | |||
constexpr schema_t(schema_t&&) = default; | |||
constexpr schema_t(const schema_t&) = delete; | |||
constexpr schema_t& operator = (schema_t&&) = default; | |||
constexpr schema_t& operator = (const schema_t&) = delete; | |||
inline void print(std::ostream& os) const | |||
{ | |||
using namespace ::cppcore; | |||
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> | |||
struct schema_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_schema(...)!"); } | |||
}; | |||
template<typename T_name, typename T_tables> | |||
struct schema_builder< | |||
mp::list<T_name, T_tables>, | |||
mp::enable_if_t< | |||
is_tables_v<mp::decay_t<T_tables>>>> | |||
{ | |||
using name_type = T_name; | |||
using tables_type = T_tables; | |||
using schema_type = schema_t<name_type, tables_type>; | |||
static constexpr decltype(auto) apply( | |||
name_type&& name, | |||
tables_type&& tables) | |||
{ | |||
return schema_type( | |||
std::forward<name_type> (name), | |||
std::forward<tables_type>(tables)); | |||
} | |||
}; | |||
} | |||
/* is_schema */ | |||
template<typename T> | |||
struct is_schema | |||
: public mp::is_base_of<__impl::tag_schema, T> | |||
{ }; | |||
} } |
@@ -1,216 +0,0 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/general.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace __impl | |||
{ | |||
/* setter_t */ | |||
template<typename T_dataset, typename T_value> | |||
struct setter_t | |||
{ | |||
using dataset_type = T_dataset; | |||
using value_type = T_value; | |||
}; | |||
/* setter_none_t */ | |||
struct setter_none_t | |||
: public setter_t<void, void> | |||
{ | |||
using base_type = setter_t<void, void>; | |||
using dataset_type = typename base_type::dataset_type; | |||
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_dataset, T_value> | |||
{ | |||
using base_type = setter_t<T_dataset, T_value>; | |||
using value_type = typename base_type::value_type; | |||
using dataset_type = typename base_type::dataset_type; | |||
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_dataset, T_value> | |||
{ | |||
using base_type = setter_t<T_dataset, T_value>; | |||
using value_type = typename base_type::value_type; | |||
using dataset_type = typename base_type::dataset_type; | |||
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_lambda, typename T_dataset, typename T_value> | |||
struct setter_lambda_t | |||
: public setter_t<T_dataset, T_value> | |||
{ | |||
using base_type = setter_t<T_dataset, T_value>; | |||
using value_type = typename base_type::value_type; | |||
using dataset_type = typename base_type::dataset_type; | |||
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< | |||
mp::is_base_of<setter_t<typename T::dataset_type, typename T::value_type>, T>>> | |||
: 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() | |||
{ | |||
using setter_type = __impl::setter_none_t; | |||
return setter_type(); | |||
} | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) make_setter_member_var(T_value T_dataset::* member) | |||
{ | |||
using setter_type = __impl::setter_member_var_t<T_dataset, T_value, T_value T_dataset::*>; | |||
return setter_type(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)) | |||
{ | |||
using setter_type = __impl::setter_member_func_t<T_dataset, T_value, T_return (T_dataset::*)(T_value)>; | |||
return setter_type(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) | |||
{ | |||
using setter_type = __impl::setter_member_func_t<const T_dataset, T_value, T_return (T_dataset::*)(T_value) const>; | |||
return setter_type(member); | |||
} | |||
template<typename T_lambda, typename T_wrapped_dataset, typename T_wrapped_value> | |||
constexpr decltype(auto) make_setter_lambda(T_lambda&& lambda, T_wrapped_dataset&&, T_wrapped_value&&) | |||
{ | |||
using setter_type = __impl::setter_lambda_t<T_lambda, misc::decay_unwrap_t<T_wrapped_dataset>, misc::decay_unwrap_t<T_wrapped_value>>; | |||
return setter_type(std::forward<T_lambda>(lambda)); | |||
} | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* setter_make_impl */ | |||
struct setter_make_impl | |||
{ | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(T_value T_dataset::*member) const | |||
{ return make_setter_member_var(member); } | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value)) const | |||
{ return make_setter_member_func(member); } | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value&)) const | |||
{ return make_setter_member_func(member); } | |||
template<typename T_dataset, typename T_value> | |||
constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value&&)) const | |||
{ return make_setter_member_func(member); } | |||
template<typename T_func, typename T_wrapped_dataset, typename T_wrapped_value> | |||
constexpr decltype(auto) operator()(T_func&& func, T_wrapped_dataset&&, T_wrapped_value&&) const | |||
{ return make_setter_lambda(std::forward<T_func>(func), T_wrapped_dataset { }, T_wrapped_value { }); } | |||
template<typename T_setter> | |||
constexpr auto operator()(T_setter&& setter) const | |||
-> mp::enable_if<is_setter<T_setter>, T_setter> | |||
{ return std::forward<T_setter>(setter); } | |||
}; | |||
} | |||
namespace setter | |||
{ | |||
constexpr decltype(auto) make = __impl::setter_make_impl { }; | |||
} | |||
} | |||
end_namespace_cpphibernate_schema |
@@ -1,190 +1,38 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/wrap.h> | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/schema/fields.h> | |||
#include <cpphibernate/schema/attribute.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* table_t */ | |||
template<typename T_name, typename T_wrapped_dataset, typename T_table_id, typename T_fields> | |||
struct table_t | |||
{ | |||
using name_type = T_name; | |||
using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>; | |||
using dataset_type = misc::decay_unwrap_t<wrapped_dataset_type>; | |||
using table_id_type = T_table_id; | |||
using fields_type = T_fields; | |||
using this_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>; | |||
name_type name; | |||
wrapped_dataset_type wrapped_dataset; | |||
table_id_type table_id; | |||
fields_type fields; | |||
constexpr table_t( | |||
T_name p_name, | |||
T_wrapped_dataset p_wrapped_dataset, | |||
T_table_id p_table_id, | |||
T_fields p_fields) | |||
: name (std::forward<T_name> (p_name)) | |||
, wrapped_dataset (std::forward<T_wrapped_dataset>(p_wrapped_dataset)) | |||
, 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 << "\"wrapped_dataset\": \"" << utl::type_helper<misc::decay_unwrap_t<wrapped_dataset_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 << '}'; | |||
} | |||
}; | |||
} | |||
/* meta */ | |||
template<typename T> | |||
struct is_table | |||
: public mp::is_specialization_of<T, __impl::table_t> | |||
{ }; | |||
template<typename... T> | |||
struct all_are_tables | |||
: mp::all_true<is_table<T>::value...> | |||
{ }; | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* table_make_impl */ | |||
template <typename X, typename = void> | |||
struct table_make_impl | |||
{ | |||
template <typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::make(...)!"); } | |||
}; | |||
template<typename T_name, typename T_wrapped_dataset, typename T_id, typename T_fields> | |||
struct table_make_impl<mp::list<T_name, T_wrapped_dataset, T_id, T_fields>, mp::enable_if_c< | |||
hana::is_a<hana::type_tag, T_wrapped_dataset> | |||
&& is_fields<mp::decay_t<T_fields>>::value>> | |||
{ | |||
static constexpr decltype(auto) apply(T_name&& name, T_wrapped_dataset&& wrapped_dataset, T_id&& id, T_fields&& fields) | |||
{ | |||
return table_t<T_name, T_wrapped_dataset, T_id, T_fields>( | |||
std::forward<T_name> (name), | |||
std::forward<T_wrapped_dataset> (wrapped_dataset), | |||
std::forward<T_id> (id), | |||
std::forward<T_fields> (fields)); | |||
} | |||
}; | |||
/* table_get_wrapped_dataset_impl */ | |||
struct table_get_wrapped_dataset_impl | |||
{ | |||
template<typename T_table> | |||
constexpr decltype(auto) operator()(T_table&& table) const | |||
{ return table.wrapped_dataset; } | |||
}; | |||
/* table_get_primary_key_field_impl */ | |||
/** | |||
* @brief Helper type to build table objects. | |||
*/ | |||
template<typename X, typename = void> | |||
struct table_get_primary_key_field_impl | |||
{ | |||
template <typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::get_primary_key_field(...)!"); } | |||
}; | |||
template<typename T_table> | |||
struct table_get_primary_key_field_impl< | |||
mp::list<T_table>, | |||
mp::enable_if_c< | |||
is_table<mp::decay_t<T_table>>::value>> | |||
{ | |||
template<size_t I> | |||
using is_primary_key_field = decltype(hana::contains( | |||
std::declval<T_table>().fields[hana::size_c<I>].attributes, | |||
attribute::primary_key)); | |||
template<size_t I, size_t N, typename = void> | |||
struct helper; | |||
template<size_t N> | |||
struct helper<N, N, void> | |||
{ static_assert(N != N, "Unable to find primary key field for table!"); }; | |||
template<size_t I, size_t N> | |||
struct helper<I, N, mp::enable_if_c< | |||
!is_primary_key_field<I>::value>> | |||
{ | |||
static constexpr decltype(auto) apply(T_table&& table) | |||
{ return helper<I+1, N>::apply(std::forward<T_table>(table)); } | |||
}; | |||
template<size_t I, size_t N> | |||
struct helper<I, N, mp::enable_if_c< | |||
is_primary_key_field<I>::value>> | |||
{ | |||
static constexpr decltype(auto) apply(T_table&& table) | |||
{ return std::forward<T_table>(table).fields[hana::size_c<I>]; } | |||
}; | |||
static constexpr decltype(auto) apply(T_table&& table) | |||
{ | |||
using count = mp::decay_t<decltype(hana::size(std::declval<T_table>().fields))>; | |||
return helper<0, count::value>::apply( | |||
std::forward<T_table>(table)); | |||
} | |||
}; | |||
struct table_builder; | |||
} | |||
namespace table | |||
{ | |||
constexpr decltype(auto) make = misc::make_generic_predicate<__impl::table_make_impl> { }; | |||
/** | |||
* @brief Evaluates to true_t if the passed type is a table type. | |||
*/ | |||
template<typename T> | |||
struct is_table; | |||
constexpr decltype(auto) get_wrapped_dataset = __impl::table_get_wrapped_dataset_impl { }; | |||
/** | |||
* @brief Is true if the passed type is an attributes type, false otherwise. | |||
*/ | |||
template<typename T> | |||
constexpr bool is_table_v = is_table<T>::value; | |||
constexpr decltype(auto) get_primary_key_field = misc::make_generic_predicate<__impl::table_get_primary_key_field_impl> { }; | |||
/** | |||
* @brief Predicate to create an table object from the passed attributes. | |||
*/ | |||
constexpr decltype(auto) make_table = mp::generic_predicate<__impl::table_builder> { }; | |||
} | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "table.inl" |
@@ -0,0 +1,129 @@ | |||
#pragma once | |||
#include "table.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* tag_table */ | |||
struct tag_table | |||
{ }; | |||
/* table_t */ | |||
template< | |||
typename T_name, | |||
typename T_wrapped_dataset, | |||
typename T_table_id, | |||
typename T_fields> | |||
struct table_t | |||
: public tag_table | |||
, public tag_equality_comparable<tag_table> | |||
{ | |||
using name_type = T_name; | |||
using wrapped_dataset_type = mp::decay_t<T_wrapped_dataset>; | |||
using dataset_type = decay_unwrap_t<wrapped_dataset_type>; | |||
using table_id_type = T_table_id; | |||
using fields_type = T_fields; | |||
using this_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>; | |||
name_type name; | |||
wrapped_dataset_type wrapped_dataset; | |||
table_id_type table_id; | |||
fields_type fields; | |||
constexpr table_t( | |||
name_type p_name, | |||
wrapped_dataset_type p_wrapped_dataset, | |||
table_id_type p_table_id, | |||
fields_type p_fields) | |||
: name (std::forward<name_type> (p_name)) | |||
, wrapped_dataset (std::forward<wrapped_dataset_type>(p_wrapped_dataset)) | |||
, table_id (std::forward<table_id_type> (p_table_id)) | |||
, fields (std::forward<fields_type> (p_fields)) | |||
{ } | |||
constexpr table_t(table_t&&) = default; | |||
constexpr table_t(const table_t&) = delete; | |||
constexpr table_t& operator = (table_t&&) = default; | |||
constexpr table_t& operator = (const table_t&) = delete; | |||
inline void print(std::ostream& os) const | |||
{ | |||
using namespace ::cppcore; | |||
size_t index = 0; | |||
os << indent << '{' | |||
<< incindent | |||
<< indent << "\"name\": \"" << name << "\"," | |||
<< indent << "\"wrapped_dataset\": \"" << type_helper<dataset_type>::name() << "\"" | |||
<< indent << "\"table_id\": \"" << hana::value(table_id) << "\"" | |||
<< indent << "\"fields\": " | |||
<< indent << '[' | |||
<< incindent; | |||
hana::for_each(fields, [&](auto& table){ | |||
if (index++ > 0) os << ","; | |||
table.print(os); | |||
}); | |||
os << decindent | |||
<< indent << ']' | |||
<< decindent | |||
<< indent << '}'; | |||
} | |||
}; | |||
/* table_builder */ | |||
template<typename X, typename> | |||
struct table_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_table(...)!"); } | |||
}; | |||
template< | |||
typename T_name, | |||
typename T_wrapped_dataset, | |||
typename T_table_id, | |||
typename T_fields> | |||
struct table_builder< | |||
mp::list<T_name, T_wrapped_dataset, T_table_id, T_fields>, | |||
mp::enable_if_t< | |||
mp::is_valid_v<unwrap_t<mp::decay_t<T_wrapped_dataset>>> | |||
&& is_fields_v<mp::decay_t<T_fields>>>> | |||
{ | |||
using name_type = T_name; | |||
using wrapped_dataset_type = T_wrapped_dataset; | |||
using table_id_type = T_table_id; | |||
using fields_type = T_fields; | |||
using table_type = table_t<name_type, wrapped_dataset_type, table_id_type, fields_type>; | |||
static constexpr decltype(auto) apply( | |||
name_type&& name, | |||
wrapped_dataset_type&& wrapped_dataset, | |||
table_id_type&& table_id, | |||
fields_type&& fields) | |||
{ | |||
return table_type( | |||
std::forward<name_type> (name), | |||
std::forward<wrapped_dataset_type> (wrapped_dataset), | |||
std::forward<table_id_type> (table_id), | |||
std::forward<fields_type> (fields)); | |||
} | |||
}; | |||
} | |||
/* is_table */ | |||
template<typename T> | |||
struct is_table | |||
: public mp::is_specialization_of<T, __impl::table_t> | |||
{ }; | |||
} } |
@@ -1,120 +1,39 @@ | |||
#pragma once | |||
#include <cpphibernate/config.h> | |||
#include <cpphibernate/misc/general.h> | |||
#include <cpphibernate/schema/table.h> | |||
beg_namespace_cpphibernate_schema | |||
{ | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* tables_t */ | |||
template<typename... T_table> | |||
using tables_t = hana::tuple<T_table...>; | |||
/* is_tables_impl */ | |||
/** | |||
* @brief Helper type to build tables. | |||
*/ | |||
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 | |||
{ }; | |||
struct tables_builder; | |||
} | |||
/* meta */ | |||
/** | |||
* @brief Evaluates to true_t if the passed type is a tables type. | |||
*/ | |||
template<typename T> | |||
struct is_tables | |||
: public __impl::is_tables_impl<T> | |||
{ }; | |||
/* operations */ | |||
namespace __impl | |||
{ | |||
/* tables_make_impl */ | |||
template <typename X, typename = void> | |||
struct tables_make_impl | |||
{ | |||
template <typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::make(...)!"); } | |||
}; | |||
template<typename... T> | |||
struct tables_make_impl<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)...); } | |||
}; | |||
/* tables_find_impl */ | |||
struct is_tables; | |||
template<typename X, typename = void> | |||
struct tables_find_impl | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::find(...)!"); } | |||
}; | |||
template<typename T_tables, typename T_wrapped_dataset> | |||
struct tables_find_impl< | |||
mp::list<T_tables, T_wrapped_dataset>, | |||
mp::enable_if_c< | |||
is_tables<mp::decay_t<T_tables>>::value>> | |||
{ | |||
template<size_t I, size_t N, typename = void> | |||
struct helper; | |||
template<size_t N> | |||
struct helper<N, N, void> | |||
{ static_assert(N != N, "Table for given datatype does not exist!"); }; | |||
template<size_t I, size_t N> | |||
struct helper<I, N, mp::enable_if_c< | |||
decltype(hana::not_equal(std::declval<T_tables>()[hana::size_c<I>].wrapped_dataset, T_wrapped_dataset { }))::value>> | |||
{ | |||
static constexpr decltype(auto) apply(T_tables&& tables) | |||
{ return helper<I+1, N>::apply(std::forward<T_tables>(tables)); } | |||
}; | |||
template<size_t I, size_t N> | |||
struct helper<I, N, mp::enable_if_c< | |||
decltype(hana::equal(std::declval<T_tables>()[hana::size_c<I>].wrapped_dataset, T_wrapped_dataset { }))::value>> | |||
{ | |||
static constexpr decltype(auto) apply(T_tables&& tables) | |||
{ return std::forward<T_tables>(tables)[hana::size_c<I>]; } | |||
}; | |||
static constexpr decltype(auto) apply(T_tables&& tables, T_wrapped_dataset&&) | |||
{ | |||
using count_type = mp::decay_t<decltype(hana::size(std::declval<T_tables>()))>; | |||
return helper<0, count_type::value>::apply(std::forward<T_tables>(tables)); | |||
} | |||
}; | |||
} | |||
namespace tables | |||
{ | |||
constexpr decltype(auto) make = misc::make_generic_predicate<__impl::tables_make_impl> { }; | |||
/** | |||
* @brief Is true if the passed type is an tables type, false otherwise. | |||
*/ | |||
template<typename T> | |||
constexpr bool is_tables_v = is_tables<T>::value; | |||
constexpr decltype(auto) find = misc::make_generic_predicate<__impl::tables_find_impl> { }; | |||
/** | |||
* @brief Predicate to create an tables object from the passed tables. | |||
*/ | |||
constexpr decltype(auto) make_tables = mp::generic_predicate<__impl::tables_builder> { }; | |||
} | |||
} } | |||
} | |||
end_namespace_cpphibernate_schema | |||
#include "tables.inl" |
@@ -0,0 +1,63 @@ | |||
#pragma once | |||
#include "tables.h" | |||
namespace cpphibernate { | |||
namespace schema { | |||
namespace __impl | |||
{ | |||
/* tables_t */ | |||
template<typename... T_tables> | |||
using tables_t = hana::basic_tuple<T_tables...>; | |||
/* tables_builder */ | |||
template<typename T, typename> | |||
struct tables_builder | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&...) | |||
{ static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_tables(...)!"); } | |||
}; | |||
template<typename... T> | |||
struct tables_builder< | |||
mp::list<T...>, | |||
mp::enable_if_t<mp::is_true_v< | |||
is_table_v<mp::decay_t<T>>...>>> | |||
{ | |||
template<typename... T_args> | |||
static constexpr decltype(auto) apply(T_args&&... args) | |||
{ | |||
using tables_type = tables_t<T_args...>; | |||
return tables_type(std::forward<T_args>(args)...); | |||
} | |||
}; | |||
/* is_tables_impl */ | |||
template<typename T, typename = void> | |||
struct is_tables_impl | |||
: mp::false_t | |||
{ }; | |||
template<typename... T> | |||
struct is_tables_impl< | |||
tables_t<T...>, | |||
mp::enable_if_t<mp::is_true_v<is_table_v<mp::decay_t<T>>...>>> | |||
: mp::true_t | |||
{ }; | |||
} | |||
/* is_tables */ | |||
template<typename T> | |||
struct is_tables | |||
: public __impl::is_tables_impl<T> | |||
{ }; | |||
} } |
@@ -1,75 +1,114 @@ | |||
#pragma once | |||
#include <string> | |||
#include <cstddef> | |||
#include <iostream> | |||
#include <cpphibernate/config.h> | |||
#include <cpputils/misc/exception.h> | |||
beg_namespace_cpphibernate | |||
namespace cpphibernate | |||
{ | |||
/* string */ | |||
/** | |||
* @brief Represents a string with an fixed length. | |||
*/ | |||
template<size_t N> | |||
struct string | |||
: public std::string | |||
{ | |||
static constexpr decltype(auto) max_size = N; | |||
using std::string::string; | |||
using std::string::operator=; | |||
}; | |||
/* timestamp */ | |||
/** | |||
* @brief Timestamp class. | |||
*/ | |||
struct timestamp | |||
{ | |||
uint64_t value; | |||
/** | |||
* @brief Default constructor. | |||
*/ | |||
inline timestamp() = default; | |||
inline timestamp(uint64_t v) | |||
: value(v) | |||
{ } | |||
/** | |||
* @brief Value constructor. | |||
*/ | |||
inline timestamp(uint64_t v); | |||
inline timestamp& operator=(const uint64_t& v) | |||
{ | |||
value = v; | |||
return *this; | |||
} | |||
/** | |||
* @brief Value assignment constructor. | |||
*/ | |||
inline timestamp& operator=(const uint64_t& v); | |||
inline operator uint64_t() const | |||
{ return value; } | |||
/** | |||
* @brief Impicit type conversion to base type. | |||
*/ | |||
inline operator uint64_t() const; | |||
}; | |||
/* uuid */ | |||
/** | |||
* @brief A typical UUID implementation. | |||
*/ | |||
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); | |||
/** | |||
* @brief Default constructor. | |||
*/ | |||
inline uuid(); | |||
/** | |||
* @brief Construtor to create a UUID from a string. | |||
* | |||
* @param[in] str String to create UUID from. | |||
*/ | |||
inline uuid(const std::string& str); | |||
/** | |||
* @brief Move constructor. | |||
*/ | |||
inline uuid(uuid&&) = default; | |||
/** | |||
* @brief Copy constructor. | |||
*/ | |||
inline uuid(const uuid&) = default; | |||
/** | |||
* @brief Write the UUID to passed stream. | |||
* | |||
* @param[in] os Stream to write UUID to. | |||
*/ | |||
void to_string(std::ostream& os) const; | |||
/** | |||
* @brief Write the UUID to passed stream. | |||
* | |||
* @param[in] os Stream to write UUID to. | |||
* | |||
* @return Stream passed as parameter. | |||
*/ | |||
std::ostream& operator<<(std::ostream& os) const; | |||
public: | |||
/** | |||
* @brief Create an UUID object from an string. | |||
* | |||
* @param[in] str String to create UUID from. | |||
* @param[in] val Parameter to store converted object in | |||
* | |||
* @retval true If the convertion was successful. | |||
* @retval false If the string could not be converted. | |||
*/ | |||
static bool from_string(const std::string& str, uuid& val); | |||
}; | |||
} | |||
end_namespace_cpphibernate | |||
#include "types.inl" |
@@ -0,0 +1,38 @@ | |||
#pragma once | |||
#include <cppcore/misc/exception.h> | |||
#include "types.h" | |||
namespace cpphibernate | |||
{ | |||
/* timestamp */ | |||
timestamp::timestamp(uint64_t v) | |||
: value(v) | |||
{ } | |||
timestamp& timestamp::operator=(const uint64_t& v) | |||
{ | |||
value = v; | |||
return *this; | |||
} | |||
timestamp::operator uint64_t() const | |||
{ return value; } | |||
/* uuid */ | |||
uuid::uuid() | |||
: std::array<uint8_t, 16>::array({ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }) | |||
{ } | |||
uuid::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 ::cppcore::argument_exception("str", "invalid uuid"); | |||
} | |||
} |
@@ -1,53 +1,105 @@ | |||
# Initialize ###################################################################################### | |||
Include ( cotire OPTIONAL ) | |||
Include ( pedantic OPTIONAL ) | |||
Include ( strip_symbols OPTIONAL ) | |||
Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||
Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||
Include ( strip_symbols OPTIONAL RESULT_VARIABLE HAS_STRIP_SYMBOLS ) | |||
Include ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/options.cmake ) | |||
Find_Package ( Hana REQUIRED ) | |||
Find_Package ( cppmp REQUIRED ) | |||
Find_Package ( cppcore REQUIRED ) | |||
Set ( BUILD_SHARED_LIBS ${CPPHIBERNATE_BUILD_SHARED} ) | |||
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}" ) | |||
# Object Library ################################################################################## | |||
# Dependencies #################################################################################### | |||
Set ( CMAKE_POSITION_INDEPENDENT_CODE ON ) | |||
Set ( CPPHIBERNATE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include ) | |||
File ( GLOB_RECURSE CPPHIBERNATE_HEADER_FILES ${CPPHIBERNATE_INCLUDE_DIR}/*.h ) | |||
File ( GLOB_RECURSE CPPHIBERNATE_INLINE_FILES ${CPPHIBERNATE_INCLUDE_DIR}/*.inl ) | |||
File ( GLOB_RECURSE CPPHIBERNATE_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||
Add_Library ( cpphibernate-objects | |||
OBJECT | |||
${CPPHIBERNATE_HEADER_FILES} | |||
${CPPHIBERNATE_INLINE_FILES} | |||
${CPPHIBERNATE_SOURCE_FILES} ) | |||
Target_Include_Directories ( cpphibernate-objects | |||
PUBLIC | |||
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}> | |||
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> ) | |||
Target_Link_Libraries ( cpphibernate-objects | |||
PUBLIC | |||
hana | |||
cppmp::cppmp | |||
cppcore::cppcore ) | |||
Find_Package ( cpputils REQUIRED ) | |||
Find_Package ( cppmariadb REQUIRED ) | |||
# Static Library ################################################################################## | |||
# Project: cpphibernate ############################################################################### | |||
Add_Library ( cpphibernate-static STATIC $<TARGET_OBJECTS:cpphibernate-objects> ) | |||
Set_Target_Properties ( cpphibernate-static | |||
PROPERTIES | |||
OUTPUT_NAME "${CPPHIBERNATE_OUTPUTNAME}" | |||
VERSION ${CPPHIBERNATE_VERSION} ) | |||
Target_Include_Directories ( cpphibernate-static | |||
PUBLIC | |||
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}> | |||
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> ) | |||
# Build | |||
Project ( cpphibernate VERSION 1.0.0.0 LANGUAGES CXX ) | |||
Set ( CPPHIBERNATE_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../include ) | |||
Set ( CPPHIBERNATE_GENERATE_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated ) | |||
File ( GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||
Add_Library ( cpphibernate ${SOURCE_FILES} ) | |||
Configure_File ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/options.h.in | |||
${CPPHIBERNATE_GENERATE_DIR}/cpphibernate/options.h ) | |||
Target_Include_Directories ( cpphibernate | |||
PUBLIC ${CPPHIBERNATE_INCLUDE_DIR} | |||
${CPPHIBERNATE_GENERATE_DIR} ) | |||
Target_Link_Libraries ( cpphibernate | |||
cpputils | |||
cppmariadb ) | |||
# Install | |||
If ( BUILD_SHARED_LIBS OR CPPHIBERNATE_INSTALL_DEV_FILES ) | |||
Install ( TARGETS cpphibernate DESTINATION lib ) | |||
# Shared Library ################################################################################## | |||
Add_Library ( cpphibernate-shared SHARED $<TARGET_OBJECTS:cpphibernate-objects> ) | |||
Set_Target_Properties ( cpphibernate-shared | |||
PROPERTIES | |||
OUTPUT_NAME "${CPPHIBERNATE_OUTPUTNAME}" | |||
VERSION ${CPPHIBERNATE_VERSION} | |||
SOVERSION ${CPPHIBERNATE_VERSION_SHORT} ) | |||
Target_Include_Directories ( cpphibernate-shared | |||
PUBLIC | |||
$<BUILD_INTERFACE:${CPPHIBERNATE_INCLUDE_DIR}> | |||
$<INSTALL_INTERFACE:${CPPHIBERNATE_INSTALL_DIR_INCLUDE}> ) | |||
# Optimization #################################################################################### | |||
# pedantic | |||
If ( HAS_PEDANTIC ) | |||
Pedantic_Apply_Flags_Target ( cpphibernate-objects ALL ) | |||
Pedantic_Apply_Flags_Target ( cpphibernate-static ALL ) | |||
Pedantic_Apply_Flags_Target ( cpphibernate-shared ALL ) | |||
EndIf ( ) | |||
# cotire | |||
If ( HAS_COTIRE ) | |||
Cotire ( cpphibernate-objects ) | |||
Cotire ( cpphibernate-static ) | |||
Cotire ( cpphibernate-shared ) | |||
EndIf ( ) | |||
# Install ######################################################################################### | |||
# Header | |||
If ( CPPHIBERNATE_INSTALL_HEADER ) | |||
Install ( FILES ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate.h | |||
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_INCLUDE} ) | |||
Install ( DIRECTORY ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate | |||
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_INCLUDE} ) | |||
EndIf ( ) | |||
# Static | |||
If ( CPPHIBERNATE_INSTALL_STATIC ) | |||
Install ( TARGETS cpphibernate-static | |||
EXPORT cpphibernate | |||
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_LIB} ) | |||
EndIf ( ) | |||
If ( CPPHIBERNATE_INSTALL_DEV_FILES ) | |||
Install ( FILES ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate.h DESTINATION include ) | |||
Install ( DIRECTORY ${CPPHIBERNATE_INCLUDE_DIR}/cpphibernate DESTINATION include ) | |||
Install ( DIRECTORY ${CPPHIBERNATE_GENERATE_DIR}/cpphibernate DESTINATION include ) | |||
# Shared | |||
If ( CPPHIBERNATE_INSTALL_SHARED ) | |||
Install ( TARGETS cpphibernate-shared | |||
EXPORT cpphibernate | |||
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_LIB} ) | |||
EndIf ( ) | |||
# Optimize | |||
If ( __COTIRE_INCLUDED ) | |||
Cotire ( cpphibernate ) | |||
# Debug | |||
If ( HAS_STRIP_SYMBOLS AND NOT CPPHIBERNATE_NO_STRIP ) | |||
Strip_Symbols ( cpphibernate-shared CPPHIBERNATE_DBG_FILE ) | |||
If ( CPPHIBERNATE_INSTALL_DEBUG ) | |||
Install ( FILES ${CPPHIBERNATE_DBG_FILE} | |||
DESTINATION ${CPPHIBERNATE_INSTALL_DIR_LIB} ) | |||
EndIf ( ) | |||
EndIf ( ) | |||
If ( __STRIP_SYMBOLS_INCLUDED AND BUILD_SHARED_LIBS ) | |||
Strip_Symbols ( cpphibernate DBG_FILE ) | |||
EndIf () |
@@ -1,31 +1,43 @@ | |||
# Initialize ###################################################################################### | |||
Include ( cotire OPTIONAL ) | |||
Include ( pedantic OPTIONAL ) | |||
Include ( cmake_tests OPTIONAL ) | |||
Include ( ${CMAKE_CURRENT_SOURCE_DIR}/../cmake/options.cmake ) | |||
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}" ) | |||
# Project: test_cpphibernate ########################################################################## | |||
Project ( test_cpphibernate ) | |||
File ( GLOB_RECURSE SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||
List ( FILTER SOURCE_FILES EXCLUDE REGEX "/_[A-Za-z0-9_-]*\.cpp$" ) | |||
Add_Executable ( test_cpphibernate EXCLUDE_FROM_ALL ${SOURCE_FILES} ) | |||
Target_Link_Libraries ( test_cpphibernate | |||
cpphibernate | |||
gmock_main | |||
gmock | |||
gtest | |||
pthread ) | |||
If ( __COTIRE_INCLUDED ) | |||
Cotire ( test_cpphibernate ) | |||
Include ( cotire OPTIONAL RESULT_VARIABLE HAS_COTIRE ) | |||
Include ( pedantic OPTIONAL RESULT_VARIABLE HAS_PEDANTIC ) | |||
Include ( cmake_tests OPTIONAL RESULT_VARIABLE HAS_CMAKE_TESTS ) | |||
# Test ############################################################################################ | |||
Find_Package ( GTest ) | |||
If ( NOT "${GTest_FOUND}" ) | |||
Return ( ) | |||
EndIf ( ) | |||
If ( __CMAKE_TESTS_INCLUDED ) | |||
Add_CMake_Test ( NAME cpphibernate | |||
TARGET test_cpphibernate ) | |||
File ( GLOB_RECURSE CPPHIBERNATE_TEST_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.h ) | |||
File ( GLOB_RECURSE CPPHIBERNATE_TEST_INLINE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.inl ) | |||
File ( GLOB_RECURSE CPPHIBERNATE_TEST_SOURCE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp ) | |||
Add_Executable ( cpphibernate-test | |||
EXCLUDE_FROM_ALL | |||
${CPPHIBERNATE_TEST_HEADER_FILES} | |||
${CPPHIBERNATE_TEST_INLINE_FILES} | |||
${CPPHIBERNATE_TEST_SOURCE_FILES} ) | |||
Target_Link_Libraries ( cpphibernate-test | |||
PUBLIC | |||
cpphibernate-objects | |||
GTest::Main ) | |||
# pedantic | |||
If ( HAS_PEDANTIC ) | |||
Pedantic_Apply_Flags_Target ( cpphibernate-test ALL ) | |||
EndIf ( ) | |||
# optimization | |||
If ( HAS_COTIRE ) | |||
Cotire ( cpphibernate-test ) | |||
EndIf ( ) | |||
# test | |||
If ( HAS_CMAKE_TESTS ) | |||
Add_CMake_Test ( NAME cpphibernate TARGET cpphibernate-test ) | |||
Else ( ) | |||
Add_Test ( NAME cpphibernate COMMAND cpphibernate-test ) | |||
EndIf ( ) |
@@ -0,0 +1,20 @@ | |||
#include <gtest/gtest.h> | |||
#include <cpphibernate.h> | |||
#include "test_schema.h" | |||
constexpr decltype(auto) x = ::cpphibernate::mp::make_getter( | |||
[](std::string&) { | |||
return int { }; | |||
}); | |||
using namespace ::testing; | |||
using namespace ::cpphibernate; | |||
using namespace ::cpphibernate::schema; | |||
TEST(cpphibernate, getHelloWorld) | |||
{ | |||
(void)x; | |||
// std::cout << test_schema << std::endl; | |||
} |
@@ -0,0 +1,227 @@ | |||
#pragma once | |||
#include <cpphibernate.h> | |||
#include <cppcore/conversion/enum.h> | |||
enum class test_enum | |||
{ | |||
test0, | |||
test1, | |||
test2, | |||
test3, | |||
first = test0, | |||
last = test3, | |||
}; | |||
cppcore_define_enum_value_traits( | |||
test_enum, | |||
{ test_enum::test0, "test0" }, | |||
{ test_enum::test1, "test1" }, | |||
{ test_enum::test2, "test2" }, | |||
{ test_enum::test3, "test3" } | |||
); | |||
struct test1 | |||
{ | |||
::cpphibernate::uuid id; | |||
std::string str_data; | |||
::cpphibernate::string<64> str64_data; | |||
cppcore::nullable<uint32_t> u32_nullable; | |||
std::unique_ptr<uint32_t> u32_ptr_u; | |||
std::shared_ptr<uint32_t> u32_ptr_s; | |||
}; | |||
struct test2 | |||
{ | |||
::cpphibernate::uuid id; | |||
uint8_t u8_data; | |||
int8_t i8_data; | |||
uint16_t u16_data; | |||
int16_t i16_data; | |||
}; | |||
struct test3 | |||
{ | |||
::cpphibernate::uuid id; | |||
uint32_t u32_data; | |||
int32_t i32_data; | |||
uint64_t u64_data; | |||
int64_t i64_data; | |||
}; | |||
struct base | |||
{ | |||
::cpphibernate::uuid id; | |||
std::string name; | |||
virtual ~base() = default; | |||
}; | |||
struct derived1 | |||
: public base | |||
{ | |||
::cpphibernate::uuid derived1_id; | |||
test1 test1_data; | |||
test_enum enum_data; | |||
}; | |||
struct derived2 | |||
: public base | |||
{ | |||
::cpphibernate::uuid derived2_id; | |||
cppcore::nullable<test2> test2_nullable; | |||
std::unique_ptr<test2> test2_ptr_u; | |||
std::shared_ptr<test2> test2_ptr_s; | |||
}; | |||
struct derived3 | |||
: public derived2 | |||
{ | |||
::cpphibernate::uuid derived3_id; | |||
std::list<test3> test3_list; | |||
std::vector<test3> test3_vector; | |||
}; | |||
struct dummy_id | |||
{ | |||
int data; | |||
inline dummy_id(int p_data = 0) | |||
: data(p_data) | |||
{ } | |||
}; | |||
struct dummy_owner | |||
{ | |||
::cpphibernate::uuid id; | |||
std::vector<dummy_id> dummies; | |||
}; | |||
struct double_usage_item | |||
{ | |||
unsigned int id { 0 }; | |||
int data { 0 }; | |||
double_usage_item(int p_data = 0) | |||
: data(p_data) | |||
{ } | |||
}; | |||
struct double_usage | |||
{ | |||
int id { 0 }; | |||
std::unique_ptr<double_usage_item> single_item; | |||
std::vector<double_usage_item> multiple_items; | |||
}; | |||
struct double_usage_wrapper | |||
{ | |||
int id { 0 }; | |||
std::unique_ptr<double_usage> double_usage; | |||
}; | |||
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_field (test1, u32_nullable), | |||
cpphibernate_make_field (test1, u32_ptr_u), | |||
cpphibernate_make_field (test1, u32_ptr_s) | |||
), | |||
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_field (derived1, enum_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) | |||
), | |||
cpphibernate_make_table_name( | |||
tbl_dummy_id, | |||
dummy_id, | |||
14, | |||
cpphibernate_make_temp_id (dummy_id, ::cpphibernate::uuid), | |||
cpphibernate_make_field (dummy_id, data) | |||
), | |||
cpphibernate_make_table_name( | |||
tbl_dummy_owner, | |||
dummy_owner, | |||
15, | |||
cpphibernate_make_id (&dummy_owner::id), | |||
cpphibernate_make_field (dummy_owner, dummies) | |||
), | |||
cpphibernate_make_table_name( | |||
tbl_double_usage_item, | |||
double_usage_item, | |||
16, | |||
cpphibernate_make_id (&double_usage_item::id), | |||
cpphibernate_make_field (double_usage_item, data) | |||
), | |||
cpphibernate_make_table_name( | |||
tbl_double_usage, | |||
double_usage, | |||
17, | |||
cpphibernate_make_id (&double_usage::id), | |||
cpphibernate_make_field (double_usage, single_item), | |||
cpphibernate_make_field (double_usage, multiple_items) | |||
), | |||
cpphibernate_make_table_name( | |||
tbl_double_usage_wrapper, | |||
double_usage_wrapper, | |||
18, | |||
cpphibernate_make_id (&double_usage_wrapper::id), | |||
cpphibernate_make_field (double_usage_wrapper, double_usage) | |||
) | |||
); |