diff --git a/CMakeLists.txt b/CMakeLists.txt index 1de3577..7b41174 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/cmake/Findcppmariadb.cmake b/cmake/Findcppmariadb.cmake deleted file mode 100644 index a13a828..0000000 --- a/cmake/Findcppmariadb.cmake +++ /dev/null @@ -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= - -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 ( ) \ No newline at end of file diff --git a/cmake/Findcpputils.cmake b/cmake/Findcpputils.cmake deleted file mode 100644 index 1fac201..0000000 --- a/cmake/Findcpputils.cmake +++ /dev/null @@ -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= - -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 ( ) \ No newline at end of file diff --git a/cmake/Findmariadb.cmake b/cmake/Findmariadb.cmake deleted file mode 100644 index 8f934a6..0000000 --- a/cmake/Findmariadb.cmake +++ /dev/null @@ -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 ( ) diff --git a/cmake/cpphibernate-config.cmake b/cmake/cpphibernate-config.cmake new file mode 100644 index 0000000..bb83fbc --- /dev/null +++ b/cmake/cpphibernate-config.cmake @@ -0,0 +1,10 @@ +# cpphibernate-config.cmake - package configuration file + +Message ( WARNING "Please configure the dependencies of this package!" ) +# Include ( CMakeFindDependencyMacro ) +# Find_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") diff --git a/cmake/cpphibernate-options.cmake b/cmake/cpphibernate-options.cmake new file mode 100644 index 0000000..5837376 --- /dev/null +++ b/cmake/cpphibernate-options.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 ) diff --git a/cmake/cpphibernate-var.cmake b/cmake/cpphibernate-var.cmake new file mode 100644 index 0000000..04c3853 --- /dev/null +++ b/cmake/cpphibernate-var.cmake @@ -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 ( ) diff --git a/cmake/modules b/cmake/modules index b125a1a..1a32531 160000 --- a/cmake/modules +++ b/cmake/modules @@ -1 +1 @@ -Subproject commit b125a1a176ae0aada1cd2ec90919061d202dcea9 +Subproject commit 1a32531aef2deeebd5637b1873bc4e976628801c diff --git a/cmake/options.cmake b/cmake/options.cmake deleted file mode 100644 index 3e99498..0000000 --- a/cmake/options.cmake +++ /dev/null @@ -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 ) diff --git a/cmake/options.h.in b/cmake/options.h.in deleted file mode 100644 index c9b0288..0000000 --- a/cmake/options.h.in +++ /dev/null @@ -1 +0,0 @@ -#cmakedefine CPPHIBERNATE_DEBUG \ No newline at end of file diff --git a/include/cpphibernate.h b/include/cpphibernate.h index d0bdf75..dc4dd33 100644 --- a/include/cpphibernate.h +++ b/include/cpphibernate.h @@ -1,8 +1,5 @@ #pragma once -#include -#include -#include -#include -#include -#include \ No newline at end of file +#include "cpphibernate/misc.h" +#include "cpphibernate/schema.h" +#include "cpphibernate/types.h" diff --git a/include/cpphibernate/config.h b/include/cpphibernate/config.h index 54b2205..2e65838 100644 --- a/include/cpphibernate/config.h +++ b/include/cpphibernate/config.h @@ -1,73 +1,12 @@ #pragma once +#include #include -#include -#include -#ifdef CPPHIBERNATE_DEBUG -# include -# define cpphibernate_debug_log(...) log_global_message(debug) << __VA_ARGS__ -#else -# define cpphibernate_debug_log(...) do { } while(0) -#endif - -#define cpphibernate_equality_comparable() \ - template \ - constexpr decltype(auto) operator==(T_other&&) const \ - { \ - return ::boost::hana::type<::utl::mp::decay_t> { } == \ - ::boost::hana::type<::utl::mp::decay_t> { }; \ - } \ - \ - template \ - constexpr decltype(auto) operator!=(T_other&&) const \ - { \ - return ::boost::hana::type<::utl::mp::decay_t> { } != \ - ::boost::hana::type<::utl::mp::decay_t> { }; \ - } - -#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 diff --git a/include/cpphibernate/context.h b/include/cpphibernate/context.h deleted file mode 100644 index ae0fd24..0000000 --- a/include/cpphibernate/context.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate -{ - - namespace __impl - { - - template - 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 - constexpr context_t(const schema_type& p_schema, T_args&&... args) - : base_type (p_schema, std::forward(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 - constexpr void create(T_dataset& dataset) - { this->create_impl(dataset); } - - /* read */ - - template - constexpr auto read(T_dataset& dataset, T_modifiers&&... modifiers) - -> mp::enable_if< - modifier::all_are_modifiers...>> - { - using namespace modifier; - using real_dataset_type = misc::real_dataset_t>; - schema::tables::find(_schema.tables, hana::type_c); - this->read_impl(dataset, modifier::make_list(std::forward(modifiers)...)); - } - - template - constexpr auto read(T_dataset& dataset) - -> mp::enable_if_c< - !misc::is_container>::value - && !misc::is_nullable>::value> - { - using namespace modifier; - using real_dataset_type = misc::real_dataset_t>; - auto& table = schema::tables::find(_schema.tables, hana::type_c); - 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 - constexpr auto read(T_dataset& dataset) - -> mp::enable_if_c< - misc::is_container>::value - || misc::is_nullable>::value> - { - using namespace modifier; - using real_dataset_type = misc::real_dataset_t>; - schema::tables::find(_schema.tables, hana::type_c); - this->read_impl(dataset, modifier::make_list()); - } - - /* update */ - - template - constexpr void update(T_dataset& dataset) - { this->update_impl(dataset); } - - /* destroy */ - - template - constexpr void destroy(T_dataset& dataset) - { this->destroy_impl(dataset); } - }; - - } - - /* make */ - - template - constexpr decltype(auto) make_context(T_schema&& schema, T_args&&... args) - { - using context_type = __impl::context_t; - return context_type(std::forward(schema), std::forward(args)...); - } - - template - constexpr decltype(auto) make_context_ptr(T_schema&& schema, T_args&&... args) - { - using context_type = __impl::context_t; - using pointer_type = std::unique_ptr; - return pointer_type(new context_type(std::forward(schema), std::forward(args)...)); - } - - -} -end_namespace_cpphibernate \ No newline at end of file diff --git a/include/cpphibernate/misc.h b/include/cpphibernate/misc.h index 04de4ef..0162724 100644 --- a/include/cpphibernate/misc.h +++ b/include/cpphibernate/misc.h @@ -1,8 +1,6 @@ #pragma once -#include -#include -#include -#include -#include -#include \ No newline at end of file +#include "misc/equality_compare.h" +#include "misc/print_container.h" +#include "misc/printing.h" +#include "misc/type_helper.h" diff --git a/include/cpphibernate/misc/container_helper.h b/include/cpphibernate/misc/container_helper.h deleted file mode 100644 index 0adc64d..0000000 --- a/include/cpphibernate/misc/container_helper.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -beg_namespace_cpphibernate_misc -{ - - /* container_helper */ - - template - struct container_helper; - - template - struct container_helper, void> - { - using container_type = std::vector; - using value_type = T_value; - - template - static inline value_type& emplace(container_type& container, T_xargs&&... args) - { - container.emplace_back(std::forward(args)...); - return container.back(); - } - - static inline void clear(container_type& container) - { container.clear(); } - }; - - template - struct container_helper, void> - { - using container_type = std::list; - using value_type = T_value; - - template - static inline value_type& emplace(container_type& container, T_xargs&&... args) - { - container.emplace_back(std::forward(args)...); - return container.back(); - } - - static inline void clear(container_type& container) - { container.clear(); } - }; - -} -end_namespace_cpphibernate_misc \ No newline at end of file diff --git a/include/cpphibernate/misc/equality_compare.h b/include/cpphibernate/misc/equality_compare.h new file mode 100644 index 0000000..0c19134 --- /dev/null +++ b/include/cpphibernate/misc/equality_compare.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace cpphibernate +{ + + /** + * @brief Tag all objects that are equality comparable to each other. + * + * @tparam T_group Type used for groupig different types. + */ + template + struct tag_equality_comparable; + + /** + * @brief Equality compare for all objects that has the quality compare tag + */ + template + constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs); + + /** + * @brief Equality compare for all objects that has the quality compare tag + */ + template + constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs); + +} + +#include "equality_compare.inl" diff --git a/include/cpphibernate/misc/equality_compare.inl b/include/cpphibernate/misc/equality_compare.inl new file mode 100644 index 0000000..56d24f3 --- /dev/null +++ b/include/cpphibernate/misc/equality_compare.inl @@ -0,0 +1,61 @@ +#pragma once + +#include "equality_compare.h" + +namespace cpphibernate +{ + + namespace __impl + { + + template + 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 + struct equality_compare_impl< + T_lhs, + T_rhs, + mp::enable_if_t< + mp::is_valid_v + && mp::is_valid_v + && 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> == hana::type_c>; } + + static constexpr decltype(auto) not_equal(T_lhs&&, T_rhs&&) + { return hana::type_c> != hana::type_c>; } + }; + + }; + + template + struct tag_equality_comparable + { + using equality_compare_group_type = T_group; + }; + + template + constexpr decltype(auto) operator == (T_lhs&& lhs, T_rhs&& rhs) + { + using equality_compare_type = __impl::equality_compare_impl; + return equality_compare_type::equal(std::forward(lhs), std::forward(rhs)); + } + + template + constexpr decltype(auto) operator != (T_lhs&& lhs, T_rhs&& rhs) + { + using equality_compare_type = __impl::equality_compare_impl; + return equality_compare_type::not_equal(std::forward(lhs), std::forward(rhs)); + } + +} diff --git a/include/cpphibernate/misc/general.h b/include/cpphibernate/misc/general.h deleted file mode 100644 index 037db6c..0000000 --- a/include/cpphibernate/misc/general.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -beg_namespace_cpphibernate_misc -{ - - /* make_generic_predicate */ - - template class T_builder> - struct make_generic_predicate - { - template - constexpr decltype(auto) operator()(T_args&&... args) const - { return T_builder>::apply(std::forward(args)...); } - }; - - /* get_dataset_id */ - - namespace __impl - { - struct counter_type_id - { }; - } - - template - constexpr decltype(auto) get_type_id(T_type&&) - { return utl::get_unique_id<__impl::counter_type_id, mp::decay_t>(); } - -} -end_namespace_cpphibernate_misc \ No newline at end of file diff --git a/include/cpphibernate/misc/meta.h b/include/cpphibernate/misc/meta.h deleted file mode 100644 index df78aff..0000000 --- a/include/cpphibernate/misc/meta.h +++ /dev/null @@ -1,152 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include -#include - -beg_namespace_cpphibernate_misc -{ - - namespace __impl - { - - /* is_container_impl */ - - template - struct is_container_impl - : public mp::c_false_t - { }; - - template - struct is_container_impl> - : public mp::c_true_t - { }; - - template - struct is_container_impl> - : public mp::c_true_t - { }; - - /* is_nullable_impl */ - - template - struct is_nullable_impl - : public mp::c_false_t - { }; - - template - struct is_nullable_impl> - : public mp::c_true_t - { }; - - template - struct is_nullable_impl> - : public mp::c_true_t - { }; - - template - struct is_nullable_impl> - : public mp::c_true_t - { }; - - /* is_pointer_impl */ - - template - struct is_pointer_impl - : public mp::c_false_t - { }; - - template - struct is_pointer_impl> - : public mp::c_true_t - { }; - - template - struct is_pointer_impl> - : public mp::c_true_t - { }; - - /* is_ordered_impl */ - - template - struct is_ordered_impl - : public mp::c_false_t - { }; - - template - struct is_ordered_impl> - : public mp::c_true_t - { }; - - template - struct is_ordered_impl> - : public mp::c_true_t - { }; - - /* real_dataset_impl */ - - template - struct real_dataset_impl - { using type = T; }; - - template - struct real_dataset_impl, void> - { using type = typename real_dataset_impl::type; }; - - template - struct real_dataset_impl, void> - { using type = typename real_dataset_impl::type; }; - - template - struct real_dataset_impl, void> - { using type = typename real_dataset_impl::type; }; - - template - struct real_dataset_impl, void> - { using type = typename real_dataset_impl::type; }; - - template - struct real_dataset_impl, void> - { using type = typename real_dataset_impl::type; }; - } - - /* meta */ - - template - struct is_container - : public __impl::is_container_impl - { }; - - template - struct is_nullable - : public __impl::is_nullable_impl - { }; - - template - struct is_ordered - : public __impl::is_ordered_impl - { }; - - template - struct is_pointer - : public __impl::is_pointer_impl - { }; - - template - using real_dataset_t = typename __impl::real_dataset_impl::type; - - /* hibernate_exception */ - - struct hibernate_exception - : public utl::exception - { - using utl::exception::exception; - }; - -} -end_namespace_cpphibernate_misc \ No newline at end of file diff --git a/include/cpphibernate/misc/nullable_helper.h b/include/cpphibernate/misc/nullable_helper.h deleted file mode 100644 index 5ed9ea9..0000000 --- a/include/cpphibernate/misc/nullable_helper.h +++ /dev/null @@ -1,120 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include - -beg_namespace_cpphibernate_misc -{ - - /* nullable_helper */ - - template - struct nullable_helper - { - using nullable_type = T_nullable; - using value_type = real_dataset_t; - - 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 - struct nullable_helper, void> - { - using nullable_type = utl::nullable; - 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 - struct nullable_helper, void> - { - using nullable_type = std::unique_ptr; - 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 - struct nullable_helper, void> - { - using nullable_type = std::shared_ptr; - 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 \ No newline at end of file diff --git a/include/cpphibernate/misc/print.h b/include/cpphibernate/misc/print.h deleted file mode 100644 index dcf7c06..0000000 --- a/include/cpphibernate/misc/print.h +++ /dev/null @@ -1,112 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include -#include - -namespace std -{ - - template - inline auto operator <<(basic_ostream& os, X&& x) - -> ::utl::mp::enable_if< - utl::mp::is_valid(x).print(os))>, - basic_ostream&> - { - std::forward(x).print(os); - return os; - } - -} - -beg_namespace_cpphibernate_misc -{ - - template - 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 - constexpr decltype(auto) operator()(T_container&& container, bool do_indent, T_func&& func) const - { - return container_printer - { - std::forward(container), - do_indent, - std::forward(func) - }; - } - - template - constexpr decltype(auto) operator()(T_container&& container, bool do_indent) const - { - return this->operator()( - std::forward(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 \ No newline at end of file diff --git a/include/cpphibernate/misc/print_container.h b/include/cpphibernate/misc/print_container.h new file mode 100644 index 0000000..50df3a4 --- /dev/null +++ b/include/cpphibernate/misc/print_container.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace cpphibernate +{ + + namespace __impl + { + + /** + * @brief Helper type to build print container. + */ + template + 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" diff --git a/include/cpphibernate/misc/print_container.inl b/include/cpphibernate/misc/print_container.inl new file mode 100644 index 0000000..5706dc1 --- /dev/null +++ b/include/cpphibernate/misc/print_container.inl @@ -0,0 +1,116 @@ +#pragma once + +#include + +#include "print_container.h" + +namespace cpphibernate +{ + + namespace __impl + { + + /* print_container */ + + template + 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 + struct print_container_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_print_container(...)!"); } + }; + + template + struct print_container_builder, void> + { + static constexpr decltype(auto) apply(T_container&& container, bool do_indent, T_func&& func) + { + using print_container_type = print_container; + return print_container_type { + std::forward(container), + do_indent, + std::forward(func), + }; + } + }; + + template + struct print_container_builder, void> + { + static constexpr decltype(auto) apply(T_container&& container, bool do_indent) + { + using namespace ::cppcore; + + make_print_container( + std::forward(container), + do_indent, + [do_indent](auto& os, auto& value) + { + using namespace ::cppcore; + if (do_indent) + os << indent; + os << to_string(value); + }); + } + }; + + } + +} diff --git a/include/cpphibernate/misc/printing.h b/include/cpphibernate/misc/printing.h new file mode 100644 index 0000000..ab187f4 --- /dev/null +++ b/include/cpphibernate/misc/printing.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include + +namespace std +{ + + template + inline auto operator <<(basic_ostream& os, X&& x) + -> ::cppmp::enable_if_t< + ::cppmp::is_valid_v(x).print(os))>, + basic_ostream&> + { + std::forward(x).print(os); + return os; + } + +} diff --git a/include/cpphibernate/misc/type_helper.h b/include/cpphibernate/misc/type_helper.h new file mode 100644 index 0000000..fd551e5 --- /dev/null +++ b/include/cpphibernate/misc/type_helper.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +namespace cpphibernate +{ + + /** + * @brief Evaluates to the basic dataset type (containers are removed). + */ + template + struct real_dataset; + + /** + * @brief Basic dataset type (containers are removed). + */ + template + using real_dataset_t = typename real_dataset::type; + + /** + * @brief Extract the type stored in an type definition . + */ + template + using unwrap_t = typename T::type; + + /** + * @brief Extract the decayed type in an type definition. + */ + template + using decay_unwrap_t = typename mp::decay_t::type; + +} + +#include "type_helper.inl" diff --git a/include/cpphibernate/misc/type_helper.inl b/include/cpphibernate/misc/type_helper.inl new file mode 100644 index 0000000..734ee24 --- /dev/null +++ b/include/cpphibernate/misc/type_helper.inl @@ -0,0 +1,53 @@ +#pragma once + +#include "type_helper.h" + +#include +#include +#include + +#include +#include + +namespace cpphibernate +{ + + namespace __impl + { + + /* real_dataset_impl */ + + template + struct real_dataset_impl + { using type = T; }; + + template + struct real_dataset_impl, void> + { using type = typename real_dataset_impl::type; }; + + template + struct real_dataset_impl, void> + { using type = typename real_dataset_impl::type; }; + + template + struct real_dataset_impl, void> + { using type = typename real_dataset_impl::type; }; + + template + struct real_dataset_impl, void> + { using type = typename real_dataset_impl::type; }; + + template + struct real_dataset_impl, void> + { using type = typename real_dataset_impl::type; }; + + } + + /* real_dataset */ + + template + struct real_dataset + : public __impl::real_dataset_impl + { }; + +} diff --git a/include/cpphibernate/misc/wrap.h b/include/cpphibernate/misc/wrap.h deleted file mode 100644 index f5126f2..0000000 --- a/include/cpphibernate/misc/wrap.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include - -beg_namespace_cpphibernate_misc -{ - - template - using unwrap_t = typename T::type; - - template - using decay_unwrap_t = typename mp::decay_t::type; - - namespace __impl - { - - struct wrap_t - { - template - constexpr decltype(auto) operator()(T) const noexcept - { return hana::type_c; } - }; - - struct unwrapped_t - { - template - constexpr decltype(auto) operator()(T) const noexcept - { return unwrap_t { }; } - }; - - } - - constexpr decltype(auto) wrap = __impl::wrap_t { }; - - constexpr decltype(auto) unwrap = __impl::unwrapped_t { }; - -} -end_namespace_cpphibernate_misc \ No newline at end of file diff --git a/include/cpphibernate/modifier.h b/include/cpphibernate/modifier.h deleted file mode 100644 index 36dfe11..0000000 --- a/include/cpphibernate/modifier.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include \ No newline at end of file diff --git a/include/cpphibernate/schema.h b/include/cpphibernate/schema.h index cebb0f4..638e4ca 100644 --- a/include/cpphibernate/schema.h +++ b/include/cpphibernate/schema.h @@ -1,12 +1,11 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include \ No newline at end of file +#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" diff --git a/include/cpphibernate/schema/attribute.h b/include/cpphibernate/schema/attribute.h index b0df517..bdcd27e 100644 --- a/include/cpphibernate/schema/attribute.h +++ b/include/cpphibernate/schema/attribute.h @@ -1,23 +1,31 @@ #pragma once #include +#include -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 struct attribute_t : public T_inner + , public tag_attribute + , public tag_equality_comparable { using inner_type = T_inner; using this_type = attribute_t; - - 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 + struct is_attribute; + /** + * @brief Is true if the passed type is an attribute, false otherwise. + */ template - struct is_attribute - : public mp::is_specialization_of - { }; + constexpr bool is_attribute_v = is_attribute::value; - template - struct all_are_attribures - : public mp::all_true::value...> - { }; +} } -} -end_namespace_cpphibernate_schema \ No newline at end of file +#include "attribute.inl" diff --git a/include/cpphibernate/schema/attribute.inl b/include/cpphibernate/schema/attribute.inl new file mode 100644 index 0000000..0e8376f --- /dev/null +++ b/include/cpphibernate/schema/attribute.inl @@ -0,0 +1,15 @@ +#pragma once + +#include "attribute.h" + +namespace cpphibernate { +namespace schema { + + /* is_attribute */ + + template + struct is_attribute + : public mp::is_base_of<__impl::tag_attribute, T> + { }; + +} } diff --git a/include/cpphibernate/schema/attributes.h b/include/cpphibernate/schema/attributes.h index 1dcd0c0..59d1920 100644 --- a/include/cpphibernate/schema/attributes.h +++ b/include/cpphibernate/schema/attributes.h @@ -1,73 +1,39 @@ #pragma once #include -#include #include -beg_namespace_cpphibernate_schema -{ +namespace cpphibernate { +namespace schema { namespace __impl { - /* attributes_t */ - - template - using attributes_t = hana::tuple; - - /* is_attributes_impl */ - + /** + * @brief Helper type to build attributes. + */ template - struct is_attributes_impl - : mp::c_false_t - { }; - - template - struct is_attributes_impl, mp::enable_if>> - : mp::c_true_t - { }; + struct attributes_builder; } - /* meta */ - + /** + * @brief Evaluates to true_t if the passed type is a attributes type. + */ template - struct is_attributes - : public __impl::is_attributes_impl - { }; - - /* operations */ - - namespace __impl - { + struct is_attributes; - /* attributes_make_impl */ - - template - struct attributes_make_impl - { - template - static constexpr decltype(auto) apply(T_args&&...) - { static_assert(sizeof...(T_args) == -1, "Invalid parameters for hibernate::schema::attributes::make(...)!"); } - }; - - template - struct attributes_make_impl, mp::enable_if_c< - all_are_attribures...>::value>> - { - template - static constexpr decltype(auto) apply(T_args&&...) - { return attributes_t...> { }; } - }; - - } - - namespace attributes - { + /** + * @brief Is true if the passed type is an attributes type, false otherwise. + */ + template + constexpr bool is_attributes_v = is_attributes::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 \ No newline at end of file +#include "attributes.inl" diff --git a/include/cpphibernate/schema/attributes.inl b/include/cpphibernate/schema/attributes.inl new file mode 100644 index 0000000..a333cb8 --- /dev/null +++ b/include/cpphibernate/schema/attributes.inl @@ -0,0 +1,62 @@ +#pragma once + +#include "attributes.h" + +namespace cpphibernate { +namespace schema { + + namespace __impl + { + + /* attributes_t */ + + template + using attributes_t = hana::basic_tuple; + + /* attributes_builder */ + + template + struct attributes_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_attributes(...)!"); } + }; + + template + struct attributes_builder< + mp::list, + mp::enable_if_t< + mp::is_true_v>...>>> + { + static constexpr decltype(auto) apply(T&&...) + { + using attributes_type = attributes_t...>; + return attributes_type { }; + } + }; + + /* is_attributes_impl */ + + template + struct is_attributes_impl + : mp::false_t + { }; + + template + struct is_attributes_impl< + attributes_t, + mp::enable_if_t>...>>> + : mp::true_t + { }; + + } + + /* is_attributes */ + + template + struct is_attributes + : public __impl::is_attributes_impl + { }; + +} } diff --git a/include/cpphibernate/schema/field.h b/include/cpphibernate/schema/field.h index 2e994d2..950e99d 100644 --- a/include/cpphibernate/schema/field.h +++ b/include/cpphibernate/schema/field.h @@ -1,126 +1,38 @@ #pragma once -#include #include -#include -#include -#include -#include -#include - -beg_namespace_cpphibernate_schema -{ +namespace cpphibernate { +namespace schema { namespace __impl { - /* field_t */ - - template - 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 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 (p_name)) - , getter (std::forward (p_getter)) - , setter (std::forward (p_setter)) - , attributes (std::forward(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::value_type; - using dataset_type = misc::real_dataset_t; - size_t index = 0; - os << indent << '{' - << incindent - << indent << "\"name\": \"" << name << "\"," - << indent << "\"value_type\": \"" << utl::type_helper::name() << "\"" - << indent << "\"dataset_type\": \"" << utl::type_helper::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 + struct field_builder; } - /* meta */ - + /** + * @brief Evaluates to true_t if the passed type is a field type. + */ template - struct is_field - : public mp::is_specialization_of - { }; - - template - struct all_are_fields - : public mp::all_true::value...> - { }; - - /* operations */ - - namespace __impl - { - - /* field_make_impl */ - - template - struct field_make_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::field::make(...)!"); } - }; - - template - struct field_make_impl, mp::enable_if_c< - is_getter>::value - && is_setter>::value - && is_attributes>::value>> - { - using field_type = field_t; + 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(name), std::forward(getter), std::forward(setter), std::forward(attributes)); } - }; - - } - - namespace field - { + /** + * @brief Is true if the passed type is an attributes type, false otherwise. + */ + template + constexpr bool is_field_v = is_field::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 \ No newline at end of file +#include "field.inl" diff --git a/include/cpphibernate/schema/field.inl b/include/cpphibernate/schema/field.inl new file mode 100644 index 0000000..57f072a --- /dev/null +++ b/include/cpphibernate/schema/field.inl @@ -0,0 +1,132 @@ +#pragma once + +#include +#include + +#include + +#include "field.h" + +namespace cpphibernate { +namespace schema { + + namespace __impl + { + + /* tag_field */ + + struct tag_field + { }; + + /* field_t */ + + template + struct field_t + : public tag_field + , public tag_equality_comparable + { + 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 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 (p_name)) + , getter (std::forward (p_getter)) + , setter (std::forward (p_setter)) + , attributes (std::forward(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::value_type; + using dataset_type = real_dataset_t; + + size_t index = 0; + os << indent << '{' + << incindent + << indent << "\"name\": \"" << name << "\"," + << indent << "\"value_type\": \"" << type_helper::name() << "\"" + << indent << "\"dataset_type\": \"" << type_helper::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 + struct field_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_field(...)!"); } + }; + + template + struct field_builder< + mp::list, + mp::enable_if_t< + true + // && mp::is_getter_v> + // && mp::is_setter_v> + // && is_attributes_v> + >> + { + 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; + + static constexpr decltype(auto) apply( + name_type&& name, + getter_type&& getter, + setter_type&& setter, + attributes_type&& attributes) + { + return field_type( + std::forward (name), + std::forward (getter), + std::forward (setter), + std::forward (attributes)); + } + }; + + } + + /* is_field */ + + template + struct is_field + : public mp::is_base_of<__impl::tag_field, T> + { }; + +} } diff --git a/include/cpphibernate/schema/fields.h b/include/cpphibernate/schema/fields.h index 61e06a3..a497f12 100644 --- a/include/cpphibernate/schema/fields.h +++ b/include/cpphibernate/schema/fields.h @@ -1,72 +1,39 @@ #pragma once #include -#include #include -beg_namespace_cpphibernate_schema -{ +namespace cpphibernate { +namespace schema { namespace __impl { - /* fields_t */ - - template - using fields_t = hana::tuple; - - /* is_fields_impl */ - + /** + * @brief Helper type to build fields. + */ template - struct is_fields_impl - : public mp::c_false_t - { }; - - template - struct is_fields_impl, mp::enable_if>> - : public mp::c_true_t - { }; + struct fields_builder; } - /* meta */ - + /** + * @brief Evaluates to true_t if the passed type is a fields type. + */ template - struct is_fields : - public __impl::is_fields_impl - { }; - - /* operations */ - - namespace __impl - { + struct is_fields; - /* fields_make_impl */ - - template - struct fields_make_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::fields::make(...)!"); } - }; - - template - struct fields_make_impl, mp::enable_if>> - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { return fields_t(std::forward(args)...); } - }; - - } - - namespace fields - { + /** + * @brief Is true if the passed type is an fields type, false otherwise. + */ + template + constexpr bool is_fields_v = is_fields::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 \ No newline at end of file +#include "fields.inl" diff --git a/include/cpphibernate/schema/fields.inl b/include/cpphibernate/schema/fields.inl new file mode 100644 index 0000000..386d231 --- /dev/null +++ b/include/cpphibernate/schema/fields.inl @@ -0,0 +1,63 @@ +#pragma once + +#include "fields.h" + +namespace cpphibernate { +namespace schema { + + namespace __impl + { + + /* fields_t */ + + template + using fields_t = hana::basic_tuple; + + /* fields_builder */ + + template + struct fields_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_fields(...)!"); } + }; + + template + struct fields_builder< + mp::list, + mp::enable_if_t>...>>> + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { + using fields_type = fields_t; + return fields_type(std::forward(args)...); + } + }; + + /* is_fields_impl */ + + template + struct is_fields_impl + : mp::false_t + { }; + + template + struct is_fields_impl< + fields_t, + mp::enable_if_t>...>>> + : mp::true_t + { }; + + } + + /* is_fields */ + + template + struct is_fields + : public __impl::is_fields_impl + { }; + +} } diff --git a/include/cpphibernate/schema/getter.h b/include/cpphibernate/schema/getter.h deleted file mode 100644 index d67233c..0000000 --- a/include/cpphibernate/schema/getter.h +++ /dev/null @@ -1,192 +0,0 @@ -#pragma once - -#include -#include - -beg_namespace_cpphibernate_schema -{ - - namespace __impl - { - - /* getter_t */ - - template - struct getter_t - { - using dataset_type = T_dataset; - using value_type = T_value; - }; - - /* getter_member_var_t */ - - template - struct getter_member_var_t - : public getter_t - { - using base_type = getter_t; - 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 - constexpr getter_member_var_t(X_member&& p_member) - : member(std::forward(p_member)) - { } - - cpphibernate_copyable(getter_member_var_t, delete); - cpphibernate_moveable(getter_member_var_t, default); - - template - constexpr decltype(auto) operator()(X_dataset&& data) const - { return std::forward(data).*member; } - }; - - /* getter_member_func_t */ - - template - struct getter_member_func_t - : public getter_t - { - using base_type = getter_t; - 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 - constexpr getter_member_func_t(X_member&& p_member) - : member(std::forward(p_member)) - { }; - - cpphibernate_copyable(getter_member_func_t, delete); - cpphibernate_moveable(getter_member_func_t, default); - - template - constexpr decltype(auto) operator()(X_dataset&& data) const - { return (std::forward(data).*member)(); } - }; - - /* getter_lambda_t */ - - template - struct getter_lambda_t - : public getter_t - { - using base_type = getter_t; - 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 - constexpr getter_lambda_t(X_lambda&& p_lambda) - : lambda(std::forward(p_lambda)) - { } - - cpphibernate_copyable(getter_lambda_t, delete); - cpphibernate_moveable(getter_lambda_t, default); - - template - constexpr decltype(auto) operator()(X_dataset&& data) const - { return lambda(std::forward(data)); } - }; - - /* is_getter_impl */ - - template - struct is_getter_impl - : public mp::c_false_t - { }; - - template - struct is_getter_impl, T>>> - : public mp::c_true_t - { }; - - } - - /* meta */ - - template - struct is_getter : - public __impl::is_getter_impl - { }; - - /* make */ - - template - constexpr decltype(auto) make_getter_member_var(T_value T_dataset::* member) - { - using getter_type = __impl::getter_member_var_t; - return getter_type(member); - } - - template - constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)()) - { - using getter_type = __impl::getter_member_func_t; - return getter_type(member); - } - - template - constexpr decltype(auto) make_getter_member_func(T_value (T_dataset::*member)() const) - { - using getter_type = __impl::getter_member_func_t; - return getter_type(member); - } - - template - constexpr decltype(auto) make_getter_lambda(T_lambda&& lambda, T_wrapped_dataset&&, T_wrapped_value&&) - { - using getter_type = __impl::getter_lambda_t, misc::decay_unwrap_t>; - return getter_type(std::forward(lambda)); - } - - /* operations */ - - namespace __impl - { - - /* getter_make_impl */ - - struct getter_make_impl - { - template - constexpr decltype(auto) operator()(T_value T_dataset::*member) const - { return make_getter_member_var(member); } - - template - constexpr decltype(auto) operator()(T_value (T_dataset::*member)(void)) const - { return make_getter_member_func(member); } - - template - constexpr decltype(auto) operator()(T_value (T_dataset::*member)(void) const) const - { return make_getter_member_func(member); } - - template - constexpr decltype(auto) operator()(T_func&& func, hana::type&& wrapped_dataset, hana::type&& wrapped_value) const - { return make_getter_lambda(std::forward(func), std::forward>(wrapped_dataset), std::forward>(wrapped_value)); } - - template - constexpr auto operator()(T_getter&& getter) const - -> mp::enable_if, T_getter> - { return std::forward(getter); } - }; - - } - - namespace getter - { - - constexpr decltype(auto) make = __impl::getter_make_impl { }; - - } - -} -end_namespace_cpphibernate_schema \ No newline at end of file diff --git a/include/cpphibernate/schema/macros.h b/include/cpphibernate/schema/macros.h index f3759ed..a81edad 100644 --- a/include/cpphibernate/schema/macros.h +++ b/include/cpphibernate/schema/macros.h @@ -1,32 +1,31 @@ #pragma once #include -#include #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, \ boost::hana::size_c, \ - 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, \ - ::boost::hana::type_c), \ - ::cpphibernate::schema::make_setter_lambda( \ - [](p_dataset&, p_value&&) { }, \ - ::boost::hana::type_c, \ - ::boost::hana::type_c), \ + }), \ + ::cpphibernate::mp::make_setter( \ + [](p_dataset&, p_value&&) { }), \ cpphibernate::schema::attribute::primary_key) diff --git a/include/cpphibernate/schema/schema.h b/include/cpphibernate/schema/schema.h index 158f94a..e661183 100644 --- a/include/cpphibernate/schema/schema.h +++ b/include/cpphibernate/schema/schema.h @@ -1,252 +1,38 @@ #pragma once #include -#include -#include -beg_namespace_cpphibernate_schema -{ +namespace cpphibernate { +namespace schema { namespace __impl { - /* schema_t */ - - template - 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 (p_name)) - , tables(std::forward(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 + struct schema_builder; } - /* meta */ - + /** + * @brief Evaluates to true_t if the passed type is a schema type. + */ template - struct is_schema : mp::is_specialization_of { }; - - /* schema::make */ - - namespace __impl - { - template - struct schema_make_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::make(...)!"); } - }; - - template - struct schema_make_impl, mp::enable_if_c< - is_tables>::value>> - { - static constexpr decltype(auto) apply(T_name&& name, T_tables&& tables) - { return schema_t(std::forward(name), std::forward(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); - - struct do_fold_impl - { - template - 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 - static constexpr decltype(auto) get_base_types(T_wrapped_datasets&& wrapped_datasets, T_wrapped_dataset&& wrapped_dataset) - { - return hana::filter( - std::forward(wrapped_datasets), - [&](auto type){ - return hana::and_( - is_base_of_pred(type, wrapped_dataset), - hana::not_equal(type, wrapped_dataset)); - }); - } - - template - constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const - { - using wrapped_datasets_type = mp::decay_t().tables, - schema::table::get_wrapped_dataset))>; - auto base_types = get_base_types(wrapped_datasets_type { }, std::forward(wrapped_dataset)); - return hana::eval_if( - hana::size(base_types) <= hana::size_c<0>, - [&](auto _){ return hana::type_c; }, - [&](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 - struct is_base_pred - { - using dataset_type = misc::decay_unwrap_t; - - template - constexpr decltype(auto) operator()(T_type&&) const - { - using type = misc::unwrap_t; - return hana::bool_c< - std::is_base_of::value - && !std::is_same ::value>; - } - }; - - template - 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 { }); - 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 - struct is_derived_pred - { - using dataset_type = misc::decay_unwrap_t; - - template - constexpr decltype(auto) operator()(T_type&&) const - { - return hana::bool_c< - std::is_base_of>::value>; - } - }; - - template - 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 { }); - 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 - 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 + constexpr bool is_schema_v = is_schema::value; - template - constexpr decltype(auto) operator()(T_schema&& schema, T_wrapped_dataset&& wrapped_dataset) const - { - using wrapped_datasets_type = mp::decay_t().tables, - schema::table::get_wrapped_dataset))>; - using derived_wrapped_datasets_type = mp::decay_t(), - hana::partial( - has_base, - std::declval(), - 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 \ No newline at end of file +#include "schema.inl" diff --git a/include/cpphibernate/schema/schema.inl b/include/cpphibernate/schema/schema.inl new file mode 100644 index 0000000..4293a61 --- /dev/null +++ b/include/cpphibernate/schema/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 + struct schema_t + : public tag_schema + , public tag_equality_comparable + { + 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 (p_name)) + , tables(std::forward(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 + struct schema_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_schema(...)!"); } + }; + + template + struct schema_builder< + mp::list, + mp::enable_if_t< + is_tables_v>>> + { + using name_type = T_name; + using tables_type = T_tables; + using schema_type = schema_t; + + static constexpr decltype(auto) apply( + name_type&& name, + tables_type&& tables) + { + return schema_type( + std::forward (name), + std::forward(tables)); + } + }; + + } + + /* is_schema */ + + template + struct is_schema + : public mp::is_base_of<__impl::tag_schema, T> + { }; + +} } diff --git a/include/cpphibernate/schema/setter.h b/include/cpphibernate/schema/setter.h deleted file mode 100644 index 4c2be2c..0000000 --- a/include/cpphibernate/schema/setter.h +++ /dev/null @@ -1,216 +0,0 @@ -#pragma once - -#include -#include - -beg_namespace_cpphibernate_schema -{ - - namespace __impl - { - - /* setter_t */ - - template - struct setter_t - { - using dataset_type = T_dataset; - using value_type = T_value; - }; - - /* setter_none_t */ - - struct setter_none_t - : public setter_t - { - using base_type = setter_t; - 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 - struct setter_member_var_t - : public setter_t - { - using base_type = setter_t; - 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 - constexpr setter_member_var_t(X_member&& p_member) - : member(std::forward(p_member)) - { } - - cpphibernate_copyable(setter_member_var_t, delete); - cpphibernate_moveable(setter_member_var_t, default); - - template - constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const - { return std::forward(data).*member = std::forward(value); } - }; - - /* setter_member_func_t */ - - template - struct setter_member_func_t - : public setter_t - { - using base_type = setter_t; - 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 - constexpr setter_member_func_t(X_member&& p_member) - : member(std::forward(p_member)) - { }; - - cpphibernate_copyable(setter_member_func_t, delete); - cpphibernate_moveable(setter_member_func_t, default); - - template - constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const - { return (std::forward(data).*member)(std::forward(value)); } - }; - - /* setter_lambda_t */ - - template - struct setter_lambda_t - : public setter_t - { - using base_type = setter_t; - 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 - constexpr setter_lambda_t(X_lambda&& p_lambda) - : lambda(std::forward(p_lambda)) - { } - - cpphibernate_copyable(setter_lambda_t, delete); - cpphibernate_moveable(setter_lambda_t, default); - - template - constexpr decltype(auto) operator()(X_dataset&& data, X_value&& value) const - { return lambda(std::forward(data), std::forward(value)); } - }; - - /* is_setter_impl */ - - template - struct is_setter_impl - : public mp::c_false_t - { }; - - template - struct is_setter_impl, T>>> - : public mp::c_true_t - { }; - - } - - /* meta */ - - template - struct is_setter : - public __impl::is_setter_impl - { }; - - /* make */ - - constexpr decltype(auto) make_setter_none() - { - using setter_type = __impl::setter_none_t; - return setter_type(); - } - - template - constexpr decltype(auto) make_setter_member_var(T_value T_dataset::* member) - { - using setter_type = __impl::setter_member_var_t; - return setter_type(member); - } - - template - constexpr decltype(auto) make_setter_member_func(T_return (T_dataset::*member)(T_value)) - { - using setter_type = __impl::setter_member_func_t; - return setter_type(member); - } - - template - constexpr decltype(auto) make_setter_member_func(T_return (T_dataset::*member)(T_value) const) - { - using setter_type = __impl::setter_member_func_t; - return setter_type(member); - } - - template - constexpr decltype(auto) make_setter_lambda(T_lambda&& lambda, T_wrapped_dataset&&, T_wrapped_value&&) - { - using setter_type = __impl::setter_lambda_t, misc::decay_unwrap_t>; - return setter_type(std::forward(lambda)); - } - - /* operations */ - - namespace __impl - { - - /* setter_make_impl */ - - struct setter_make_impl - { - template - constexpr decltype(auto) operator()(T_value T_dataset::*member) const - { return make_setter_member_var(member); } - - template - constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value)) const - { return make_setter_member_func(member); } - - template - constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value&)) const - { return make_setter_member_func(member); } - - template - constexpr decltype(auto) operator()(void (T_dataset::*member)(T_value&&)) const - { return make_setter_member_func(member); } - - template - constexpr decltype(auto) operator()(T_func&& func, T_wrapped_dataset&&, T_wrapped_value&&) const - { return make_setter_lambda(std::forward(func), T_wrapped_dataset { }, T_wrapped_value { }); } - - template - constexpr auto operator()(T_setter&& setter) const - -> mp::enable_if, T_setter> - { return std::forward(setter); } - }; - - } - - namespace setter - { - - constexpr decltype(auto) make = __impl::setter_make_impl { }; - - } - -} -end_namespace_cpphibernate_schema \ No newline at end of file diff --git a/include/cpphibernate/schema/table.h b/include/cpphibernate/schema/table.h index 589993c..325a1ba 100644 --- a/include/cpphibernate/schema/table.h +++ b/include/cpphibernate/schema/table.h @@ -1,190 +1,38 @@ #pragma once #include -#include -#include -#include -#include -beg_namespace_cpphibernate_schema -{ +namespace cpphibernate { +namespace schema { namespace __impl { - /* table_t */ - - template - struct table_t - { - using name_type = T_name; - using wrapped_dataset_type = mp::decay_t; - using dataset_type = misc::decay_unwrap_t; - using table_id_type = T_table_id; - using fields_type = T_fields; - using this_type = table_t; - - 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 (p_name)) - , wrapped_dataset (std::forward(p_wrapped_dataset)) - , table_id (std::forward (p_table_id)) - , fields (std::forward (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>::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 - struct is_table - : public mp::is_specialization_of - { }; - - template - struct all_are_tables - : mp::all_true::value...> - { }; - - /* operations */ - - namespace __impl - { - - /* table_make_impl */ - - template - struct table_make_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::make(...)!"); } - }; - - template - struct table_make_impl, mp::enable_if_c< - hana::is_a - && is_fields>::value>> - { - static constexpr decltype(auto) apply(T_name&& name, T_wrapped_dataset&& wrapped_dataset, T_id&& id, T_fields&& fields) - { - return table_t( - std::forward (name), - std::forward (wrapped_dataset), - std::forward (id), - std::forward (fields)); - } - }; - - /* table_get_wrapped_dataset_impl */ - - struct table_get_wrapped_dataset_impl - { - template - 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 - struct table_get_primary_key_field_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::table::get_primary_key_field(...)!"); } - }; - - template - struct table_get_primary_key_field_impl< - mp::list, - mp::enable_if_c< - is_table>::value>> - { - template - using is_primary_key_field = decltype(hana::contains( - std::declval().fields[hana::size_c].attributes, - attribute::primary_key)); - - template - struct helper; - - template - struct helper - { static_assert(N != N, "Unable to find primary key field for table!"); }; - - template - struct helper::value>> - { - static constexpr decltype(auto) apply(T_table&& table) - { return helper::apply(std::forward(table)); } - }; - - template - struct helper::value>> - { - static constexpr decltype(auto) apply(T_table&& table) - { return std::forward(table).fields[hana::size_c]; } - }; - - static constexpr decltype(auto) apply(T_table&& table) - { - using count = mp::decay_t().fields))>; - return helper<0, count::value>::apply( - std::forward(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 + 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 + constexpr bool is_table_v = is_table::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 \ No newline at end of file +#include "table.inl" diff --git a/include/cpphibernate/schema/table.inl b/include/cpphibernate/schema/table.inl new file mode 100644 index 0000000..0a8b703 --- /dev/null +++ b/include/cpphibernate/schema/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 + { + using name_type = T_name; + using wrapped_dataset_type = mp::decay_t; + using dataset_type = decay_unwrap_t; + using table_id_type = T_table_id; + using fields_type = T_fields; + using this_type = table_t; + + 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 (p_name)) + , wrapped_dataset (std::forward(p_wrapped_dataset)) + , table_id (std::forward (p_table_id)) + , fields (std::forward (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::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 + struct table_builder + { + template + 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, + mp::enable_if_t< + mp::is_valid_v>> + && is_fields_v>>> + { + 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; + + 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), + std::forward (wrapped_dataset), + std::forward (table_id), + std::forward (fields)); + } + }; + + } + + /* is_table */ + + template + struct is_table + : public mp::is_specialization_of + { }; + +} } diff --git a/include/cpphibernate/schema/tables.h b/include/cpphibernate/schema/tables.h index 184fca2..dc33dea 100644 --- a/include/cpphibernate/schema/tables.h +++ b/include/cpphibernate/schema/tables.h @@ -1,120 +1,39 @@ #pragma once #include -#include #include -beg_namespace_cpphibernate_schema -{ +namespace cpphibernate { +namespace schema { namespace __impl { - /* tables_t */ - - template - using tables_t = hana::tuple; - - /* is_tables_impl */ - + /** + * @brief Helper type to build tables. + */ template - struct is_tables_impl - : mp::c_false_t - { }; - - template - struct is_tables_impl, mp::enable_if>> - : mp::c_true_t - { }; + struct tables_builder; } - /* meta */ - + /** + * @brief Evaluates to true_t if the passed type is a tables type. + */ template - struct is_tables - : public __impl::is_tables_impl - { }; - - /* operations */ - - namespace __impl - { - - /* tables_make_impl */ - - template - struct tables_make_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::make(...)!"); } - }; - - template - struct tables_make_impl, mp::enable_if>> - { - template - static constexpr decltype(auto) apply(T_tables&&... tables) - { return tables_t(std::forward(tables)...); } - }; - - /* tables_find_impl */ + struct is_tables; - template - struct tables_find_impl - { - template - static constexpr decltype(auto) apply(T_args&&... args) - { static_assert(sizeof...(args) == -1, "Invalid parameters for hibernate::schema::tables::find(...)!"); } - }; - - template - struct tables_find_impl< - mp::list, - mp::enable_if_c< - is_tables>::value>> - { - template - struct helper; - - template - struct helper - { static_assert(N != N, "Table for given datatype does not exist!"); }; - - template - struct helper()[hana::size_c].wrapped_dataset, T_wrapped_dataset { }))::value>> - { - static constexpr decltype(auto) apply(T_tables&& tables) - { return helper::apply(std::forward(tables)); } - }; - - template - struct helper()[hana::size_c].wrapped_dataset, T_wrapped_dataset { }))::value>> - { - static constexpr decltype(auto) apply(T_tables&& tables) - { return std::forward(tables)[hana::size_c]; } - }; - - static constexpr decltype(auto) apply(T_tables&& tables, T_wrapped_dataset&&) - { - using count_type = mp::decay_t()))>; - return helper<0, count_type::value>::apply(std::forward(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 + constexpr bool is_tables_v = is_tables::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 \ No newline at end of file +#include "tables.inl" diff --git a/include/cpphibernate/schema/tables.inl b/include/cpphibernate/schema/tables.inl new file mode 100644 index 0000000..72ec401 --- /dev/null +++ b/include/cpphibernate/schema/tables.inl @@ -0,0 +1,63 @@ +#pragma once + +#include "tables.h" + +namespace cpphibernate { +namespace schema { + + namespace __impl + { + + /* tables_t */ + + template + using tables_t = hana::basic_tuple; + + /* tables_builder */ + + template + struct tables_builder + { + template + static constexpr decltype(auto) apply(T_args&&...) + { static_assert(sizeof...(T_args) == -1, "Invalid parameters for make_tables(...)!"); } + }; + + template + struct tables_builder< + mp::list, + mp::enable_if_t>...>>> + { + template + static constexpr decltype(auto) apply(T_args&&... args) + { + using tables_type = tables_t; + return tables_type(std::forward(args)...); + } + }; + + /* is_tables_impl */ + + template + struct is_tables_impl + : mp::false_t + { }; + + template + struct is_tables_impl< + tables_t, + mp::enable_if_t>...>>> + : mp::true_t + { }; + + } + + /* is_tables */ + + template + struct is_tables + : public __impl::is_tables_impl + { }; + +} } diff --git a/include/cpphibernate/types.h b/include/cpphibernate/types.h index 9f7d2d2..6841219 100644 --- a/include/cpphibernate/types.h +++ b/include/cpphibernate/types.h @@ -1,75 +1,114 @@ #pragma once #include +#include #include #include -#include - -beg_namespace_cpphibernate +namespace cpphibernate { - /* string */ - + /** + * @brief Represents a string with an fixed length. + */ template 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 { public: - inline uuid() - : std::array::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::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" diff --git a/include/cpphibernate/types.inl b/include/cpphibernate/types.inl new file mode 100644 index 0000000..7416f3c --- /dev/null +++ b/include/cpphibernate/types.inl @@ -0,0 +1,38 @@ +#pragma once + +#include + +#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::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::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"); + } + +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b39bec3..741f40d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 + $ + $ ) +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 $ ) +Set_Target_Properties ( cpphibernate-static + PROPERTIES + OUTPUT_NAME "${CPPHIBERNATE_OUTPUTNAME}" + VERSION ${CPPHIBERNATE_VERSION} ) +Target_Include_Directories ( cpphibernate-static + PUBLIC + $ + $ ) -# 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 $ ) +Set_Target_Properties ( cpphibernate-shared + PROPERTIES + OUTPUT_NAME "${CPPHIBERNATE_OUTPUTNAME}" + VERSION ${CPPHIBERNATE_VERSION} + SOVERSION ${CPPHIBERNATE_VERSION_SHORT} ) +Target_Include_Directories ( cpphibernate-shared + PUBLIC + $ + $ ) + +# 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 () diff --git a/src/cpphibernate/driver/mariadb/schema/field.cpp b/src/cpphibernate/driver/mariadb/schema/field.xcpp similarity index 100% rename from src/cpphibernate/driver/mariadb/schema/field.cpp rename to src/cpphibernate/driver/mariadb/schema/field.xcpp diff --git a/src/cpphibernate/driver/mariadb/schema/schema.cpp b/src/cpphibernate/driver/mariadb/schema/schema.xcpp similarity index 100% rename from src/cpphibernate/driver/mariadb/schema/schema.cpp rename to src/cpphibernate/driver/mariadb/schema/schema.xcpp diff --git a/src/cpphibernate/driver/mariadb/schema/table.cpp b/src/cpphibernate/driver/mariadb/schema/table.xcpp similarity index 100% rename from src/cpphibernate/driver/mariadb/schema/table.cpp rename to src/cpphibernate/driver/mariadb/schema/table.xcpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index de3903d..0074a00 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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 ( ) diff --git a/test/cpphibernate_create.cpp b/test/cpphibernate/cpphibernate_create.xcpp similarity index 100% rename from test/cpphibernate_create.cpp rename to test/cpphibernate/cpphibernate_create.xcpp diff --git a/test/cpphibernate_destroy.cpp b/test/cpphibernate/cpphibernate_destroy.xcpp similarity index 100% rename from test/cpphibernate_destroy.cpp rename to test/cpphibernate/cpphibernate_destroy.xcpp diff --git a/test/cpphibernate_init.cpp b/test/cpphibernate/cpphibernate_init.xcpp similarity index 100% rename from test/cpphibernate_init.cpp rename to test/cpphibernate/cpphibernate_init.xcpp diff --git a/test/cpphibernate_read.cpp b/test/cpphibernate/cpphibernate_read.xcpp similarity index 100% rename from test/cpphibernate_read.cpp rename to test/cpphibernate/cpphibernate_read.xcpp diff --git a/test/cpphibernate/cpphibernate_tests.cpp b/test/cpphibernate/cpphibernate_tests.cpp new file mode 100644 index 0000000..f1c3863 --- /dev/null +++ b/test/cpphibernate/cpphibernate_tests.cpp @@ -0,0 +1,20 @@ +#include + +#include + +#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; +} diff --git a/test/cpphibernate_update.cpp b/test/cpphibernate/cpphibernate_update.xcpp similarity index 100% rename from test/cpphibernate_update.cpp rename to test/cpphibernate/cpphibernate_update.xcpp diff --git a/test/mariadb_mock.h b/test/cpphibernate/mariadb_mock.h similarity index 100% rename from test/mariadb_mock.h rename to test/cpphibernate/mariadb_mock.h diff --git a/test/mariadb_mock.cpp b/test/cpphibernate/mariadb_mock.xcpp similarity index 100% rename from test/mariadb_mock.cpp rename to test/cpphibernate/mariadb_mock.xcpp diff --git a/test/test_helper.h b/test/cpphibernate/test_helper.h similarity index 100% rename from test/test_helper.h rename to test/cpphibernate/test_helper.h diff --git a/test/cpphibernate/test_schema.h b/test/cpphibernate/test_schema.h new file mode 100644 index 0000000..a61fb70 --- /dev/null +++ b/test/cpphibernate/test_schema.h @@ -0,0 +1,227 @@ +#pragma once + +#include +#include + +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 u32_nullable; + std::unique_ptr u32_ptr_u; + std::shared_ptr 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_nullable; + std::unique_ptr test2_ptr_u; + std::shared_ptr test2_ptr_s; +}; + +struct derived3 + : public derived2 +{ + ::cpphibernate::uuid derived3_id; + std::list test3_list; + std::vector 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 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 single_item; + std::vector multiple_items; +}; + +struct double_usage_wrapper +{ + int id { 0 }; + std::unique_ptr 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) + ) +);