├── .gitignore ├── CMakeLists.txt ├── cmake └── collect_sources.cmake ├── flex_lib.sln ├── include └── flex_lib │ ├── config │ ├── compiler.h │ ├── compiler_clang.h │ ├── compiler_gcc.h │ ├── compiler_msvc.h │ └── config.h │ ├── detector.h │ ├── foreach.hpp │ ├── iterator.hpp │ ├── lazy_list.h │ ├── lazy_list.inl.h │ ├── lazy_list │ ├── common.h │ ├── lazy_list_builder.h │ ├── lazy_list_factory.h │ ├── lazy_list_impl.h │ ├── lazy_list_iterator.h │ └── lazy_list_ops.h │ ├── pimpl.h │ ├── properties │ ├── abstract_property.hpp │ ├── dynamic_access.hpp │ ├── dynamic_lex_access.hpp │ ├── fwd_rw_property.hpp │ ├── index_property.hpp │ ├── index_property_fwd.hpp │ ├── index_property_impl.hpp │ ├── properties_fwd.hpp │ ├── property_accessors.hpp │ ├── property_pp.hpp │ ├── property_traits.hpp │ ├── rw_property.hpp │ └── simple_property.hpp │ ├── property.hpp │ ├── stringized_enum.h │ ├── variant.h │ └── variant │ ├── static_visitor.h │ └── variant_impl.h ├── sources ├── CMakeLists.txt └── readme.txt ├── tests ├── CMakeLists.txt ├── lazy_list │ ├── CMakeLists.txt │ ├── ReadMe.txt │ ├── lazy_list.cpp │ ├── lazy_list.vcxproj │ └── lazy_list.vcxproj.filters └── variant │ ├── CMakeLists.txt │ └── variant.cpp └── tools ├── CMakeLists.txt └── codegen ├── CMakeLists.txt ├── src ├── ast_reflector.cpp ├── ast_reflector.h ├── ast_utils.h ├── basic_generator.cpp ├── basic_generator.h ├── cpp_source_stream.cpp ├── cpp_source_stream.h ├── decls_reflection.h ├── enum2string_generator.cpp ├── enum2string_generator.h ├── generator_base.h ├── main.cpp ├── options.h ├── pimpl_generator.cpp ├── pimpl_generator.h ├── type_info.cpp ├── type_info.h └── utils.h └── test ├── CMakeLists.txt ├── enum2string ├── CMakeLists.txt ├── enum2string.cpp └── test_enums.h └── pimpl ├── CMakeLists.txt ├── pimpl_gen_test.cpp ├── test_pimpl.h └── test_pimpl_impl.h /.gitignore: -------------------------------------------------------------------------------- 1 | /*.db 2 | *.user 3 | *.user.* 4 | /flex_lib.pro 5 | /flex_lib.suo 6 | *.astdump 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 4 | 5 | include(collect_sources) 6 | 7 | set(GTEST_ROOT $ENV{GTEST_DIR} CACHE PATH "Path to GTest/GMock library root") 8 | set(BOOST_ROOT $ENV{BOOST_DIR} CACHE PATH "Path to boost library root") 9 | set(FLEXLIB_BUILD_CODEGEN OFF CACHE BOOL "Build codegenerator tools") 10 | set(FLEXLIB_CXX_STANDARD "14" CACHE STRING "C++ standard conformance for library build") 11 | 12 | if(NOT "${GTEST_ROOT}" STREQUAL "") 13 | list (APPEND CMAKE_PREFIX_PATH ${GTEST_ROOT}) 14 | set (Gtest_DIR ${GTEST_ROOT}) 15 | message(STATUS "GTest library search path: ${Gtest_DIR}") 16 | endif() 17 | 18 | 19 | if(NOT "${BOOST_ROOT}" STREQUAL "") 20 | list (APPEND CMAKE_PREFIX_PATH ${BOOST_ROOT}) 21 | set (Boost_DIR ${BOOST_ROOT}) 22 | message(STATUS "BOOST library search path: ${Boost_DIR}") 23 | endif() 24 | 25 | find_package(GTest) 26 | find_package(Boost) 27 | 28 | message (STATUS "##### COMPILER = ${CMAKE_CXX_COMPILER_ID}") 29 | message (STATUS "##### COMPILER = ${CMAKE_CXX_COMPILER_VERSION}") 30 | 31 | if (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang" OR ${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") 32 | if (${FLEXLIB_CXX_STANDARD} STREQUAL "17" OR ${FLEXLIB_CXX_STANDARD} STREQUAL "1z") 33 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") 34 | message(STATUS "FlexLib is building with C++17 enabled") 35 | else() 36 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 37 | message(STATUS "FlexLib is building with C++14 enabled") 38 | endif() 39 | endif() 40 | 41 | CollectSources(FlexLibSources FlexLibHeaders ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include) 42 | 43 | add_library(flex_lib_fake_sources EXCLUDE_FROM_ALL ${FlexLibHeaders}) 44 | set_target_properties(flex_lib_fake_sources PROPERTIES LINKER_LANGUAGE CXX) 45 | 46 | add_library(flex_lib INTERFACE) 47 | target_include_directories(flex_lib 48 | INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include 49 | ) 50 | 51 | set(FLEX_LIB_INCLUDE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include") 52 | set(FLEX_LIB_INCLUDE_DIR "flex_lib") 53 | 54 | include_directories( 55 | ${GTEST_INCLUDE_DIRS} 56 | ${Boost_INCLUDE_DIRS} 57 | ) 58 | 59 | add_subdirectory(sources) 60 | if (FLEXLIB_BUILD_CODEGEN) 61 | add_subdirectory(tools) 62 | endif() 63 | 64 | if (GTEST_INCLUDE_DIRS) 65 | add_subdirectory(tests) 66 | endif () 67 | 68 | install (DIRECTORY include/ DESTINATION include) 69 | install (DIRECTORY cmake/ DESTINATION cmake) 70 | -------------------------------------------------------------------------------- /cmake/collect_sources.cmake: -------------------------------------------------------------------------------- 1 | function (CollectSources SourcesVar HeadersVar RelativePath FromPath) 2 | if (NOT FromPath OR ${FromPath} STREQUAL "") 3 | set (FromPath ${CMAKE_CURRENT_SOURCE_DIR}) 4 | endif () 5 | 6 | file (GLOB_RECURSE Sources RELATIVE ${RelativePath} ${FromPath}/*.c ${FromPath}/*.cpp ${FromPath}/*.cxx) 7 | file (GLOB_RECURSE Headers RELATIVE ${RelativePath} ${FromPath}/*.h ${FromPath}/*.hpp ${FromPath}/*.hxx ${FromPath}/*.inc ${FromPath}/*.inl) 8 | 9 | set (${SourcesVar} ${Sources} PARENT_SCOPE) 10 | set (${HeadersVar} ${Headers} PARENT_SCOPE) 11 | endfunction () 12 | -------------------------------------------------------------------------------- /flex_lib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 11.00 3 | # Visual Studio 2010 4 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sources", "sources", "{665C1A12-9EF9-40AB-86B8-BC47009B1F03}" 5 | EndProject 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{ED2BFD7B-DBF5-44B4-8F82-42A22B89FD03}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lazy_list", "tests\lazy_list\lazy_list.vcxproj", "{A717A569-C146-4DD0-BA38-575A79343F09}" 9 | EndProject 10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "headers", "headers", "{357322CE-CF9E-4BC3-BA27-F532D549DCE1}" 11 | ProjectSection(SolutionItems) = preProject 12 | flex_lib\lazy_list.h = flex_lib\lazy_list.h 13 | flex_lib\lazy_list.inl.h = flex_lib\lazy_list.inl.h 14 | EndProjectSection 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Win32 = Debug|Win32 19 | Release|Win32 = Release|Win32 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {A717A569-C146-4DD0-BA38-575A79343F09}.Debug|Win32.ActiveCfg = Debug|Win32 23 | {A717A569-C146-4DD0-BA38-575A79343F09}.Debug|Win32.Build.0 = Debug|Win32 24 | {A717A569-C146-4DD0-BA38-575A79343F09}.Release|Win32.ActiveCfg = Release|Win32 25 | {A717A569-C146-4DD0-BA38-575A79343F09}.Release|Win32.Build.0 = Release|Win32 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | GlobalSection(NestedProjects) = preSolution 31 | {A717A569-C146-4DD0-BA38-575A79343F09} = {ED2BFD7B-DBF5-44B4-8F82-42A22B89FD03} 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /include/flex_lib/config/compiler.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_COMPILER_H__ 2 | #define FLEX_LIB_COMPILER_H__ 3 | 4 | #ifdef __clang__ 5 | #include "compiler_clang.h" 6 | #elif defined (__GNUC__) 7 | #include "compiler_gcc.h" 8 | #elif defined (_MSC_VER) 9 | #include "compiler_msvc.h" 10 | #else 11 | #pragma (warning, "Unknown compiler") 12 | #endif 13 | 14 | #endif // FLEX_LIB_COMPILER_H__ 15 | -------------------------------------------------------------------------------- /include/flex_lib/config/compiler_clang.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_COMPILER_CLANG_H__ 2 | #define FLEX_LIB_COMPILER_CLANG_H__ 3 | 4 | #if !defined(__cplusplus) || __cplusplus < 201103L 5 | #error "-std=c++11 option should be defined for compilator command line" 6 | #endif 7 | 8 | #define FL_CLANG_FULL_VERSION(v, r, p) (((v) << 24) + ((r) << 16) + (p)) 9 | #define FL_CLANG_VERSION(v, r) FL_CLANG_FULL_VERSION(v, r, 0) 10 | 11 | #define FL_COMPILER_CLANG FL_CLANG_FULL_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__) 12 | 13 | #define FL_CXX11_SUPPORT_ALIGNAS __has_feature(cxx_alignas) 14 | #define FL_CXX11_SUPPORT_AUTO __has_feature(cxx_auto_type) 15 | #define FL_CXX11_SUPPORT_CONSTEXPR __has_feature(cxx_constexpr) 16 | #define FL_CXX11_SUPPORT_DECLTYPE __has_feature(cxx_decltype) 17 | #define FL_CXX11_SUPPORT_DEFAULTFUNCTIONS __has_feature(cxx_defaulted_functions) 18 | #define FL_CXX11_SUPPORT_DELETEDFUNCTIONS __has_feature(cxx_deleted_functions) 19 | #define FL_CXX11_SUPPORT_DELEGATINGCTORS __has_feature(cxx_delegating_constructors) 20 | #define FL_CXX11_SUPPORT_EXPLICITCONVS __has_feature(cxx_explicit_conversions) 21 | #define FL_CXX11_SUPPORT_INHERITINGCTORS __has_feature(cxx_inheriting_constructors) 22 | #define FL_CXX11_SUPPORT_INITIALIZERLISTS __has_feature(cxx_generalized_initializers) 23 | #define FL_CXX11_SUPPORT_LAMBDAS __has_feature(cxx_lambdas) 24 | #define FL_CXX14_SUPPORT_POLYLAMBDAS 0 25 | #define FL_CXX14_SUPPORT_LAMBDAINITINCAPTURE 0 26 | #define FL_CXX11_SUPPORT_LOCALTYPESASTPLARGS __has_feature(cxx_local_type_template_args) 27 | #define FL_CXX11_SUPPORT_INLINENAMESPACE __has_feature(cxx_inline_namespaces) 28 | #define FL_CXX11_SUPPORT_AUTOFUNCTIONS __has_feature(cxx_trailing_return) 29 | #define FL_CXX11_SUPPORT_NULLPTR __has_feature(cxx_nullptr) 30 | #define FL_CXX11_SUPPORT_UNICODESTRINGS __has_feature(cxx_unicode_literals) 31 | #define FL_CXX11_SUPPORT_RAWSTRINGS __has_feature(cxx_raw_string_literals) 32 | #define FL_CXX11_SUPPORT_UDLITERALS __has_feature(cxx_user_literals) 33 | #define FL_CXX11_SUPPORT_RVALUEREFS __has_feature(cxx_rvalue_references) 34 | #define FL_CXX11_SUPPORT_STATICASSERT __has_feature(cxx_static_assert) 35 | #define FL_CXX11_SUPPORT_STRONGENUMS __has_feature(cxx_strong_enums) 36 | #define FL_CXX11_SUPPORT_TEMPLATEALIASES __has_feature(cxx_alias_templates) 37 | #define FL_CXX11_SUPPORT_THREADLOCALSTORAGE __has_feature(cxx_thread_local) 38 | #define FL_CXX11_SUPPORT_UNRESTRICTEDUNIONS __has_feature(cxx_unrestricted_unions) 39 | #define FL_CXX11_SUPPORT_VARIADICTEMPLATES __has_feature(cxx_variadic_templates) 40 | #define FL_CXX11_SUPPORT_RANGEBASEDFOR __has_feature(cxx_range_for) 41 | #define FL_CXX11_SUPPORT_OVERRIDESUPPORT __has_feature(cxx_override_control) 42 | #define FL_CXX11_SUPPORT_ATTRIBUTES __has_feature(cxx_attributes) 43 | #define FL_CXX11_SUPPORT_REFQUALIFIERS __has_feature(cxx_reference_qualified_functions) 44 | #define FL_CXX11_SUPPORT_NONSTATICMEMBERSINIT __has_feature(cxx_nonstatic_member_init) 45 | 46 | #if FL_COMPILER_CLANG >= FL_CLANG_VERSION(3,0) 47 | #define FL_CXX11_SUPPORT_ALIGNOF 1 48 | #define FL_CXX11_SUPPORT_EXTENDEDFRIEND 1 49 | #define FL_CXX11_SUPPORT_LONGLONG 1 50 | #define FL_CXX11_SUPPORT_NEWCHARTYPES 1 51 | #define FL_CXX11_SUPPORT_RANGLEBRACKETS 1 52 | #define FL_CXX11_SUPPORT_TYPETRAITS 1 53 | #define FL_CXX11_SUPPORT_MAGICSTATICS 1 54 | # if FL_COMPILER_CLANG >= FL_CLANG_VERSION(3,1) 55 | #define FL_CXX11_SUPPORT_ATOMIC 1 56 | #define FL_CXX11_SUPPORT_FORWARDENUMS 1 57 | #define FL_CXX11_SUPPORT_EXTENDEDSIZEOF 1 58 | # endif // FL_COMPILER_CLANG >= FL_CLANG_VERSION(3,1) 59 | #else 60 | # error "Only clang 3.0 or better is supported" 61 | #endif // FL_COMPILER_CLANG >= FL_CLANG_VERSION(3,0) 62 | 63 | 64 | 65 | #endif // FLEX_LIB_COMPILER_CLANG_H__ 66 | -------------------------------------------------------------------------------- /include/flex_lib/config/compiler_gcc.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_COMPILER_GCC_H__ 2 | #define FLEX_LIB_COMPILER_GCC_H__ 3 | 4 | #if !defined(__cplusplus) || __cplusplus < 201103L 5 | #error "-std=c++11 option should be defined for compilator command line" 6 | #endif 7 | 8 | #define FL_GCC_FULL_VERSION(v, r, p) (((v) << 24) + ((r) << 16) + (p)) 9 | #define FL_GCC_VERSION(v, r) FL_GCC_FULL_VERSION(v, r, 0) 10 | 11 | #define FL_COMPILER_GCC FL_GCC_FULL_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) 12 | 13 | #define FL_CXX14_SUPPORT_POLYLAMBDAS 0 14 | #define FL_CXX14_SUPPORT_LAMBDAINITINCAPTURE 0 15 | 16 | #if FL_COMPILER_GCC >= FL_GCC_VERSION(4, 5) 17 | #define FL_CXX11_SUPPORT_ALIGNOF 1 18 | #define FL_CXX11_SUPPORT_ATOMIC 1 19 | #define FL_CXX11_SUPPORT_AUTO 1 20 | #define FL_CXX11_SUPPORT_DECLTYPE 1 // decltype v 1.0, N2343 21 | #define FL_CXX11_SUPPORT_DEFAULTFUNCTIONS 1 22 | #define FL_CXX11_SUPPORT_DELETEDFUNCTIONS 1 23 | #define FL_CXX11_SUPPORT_EXPLICITCONVS 1 24 | #define FL_CXX11_SUPPORT_INITIALIZERLISTS 1 25 | #define FL_CXX11_SUPPORT_LAMBDAS 2 // lambdas 1.1, N2927 26 | #define FL_CXX11_SUPPORT_LOCALTYPESASTPLARGS 1 27 | #define FL_CXX11_SUPPORT_LONGLONG 1 28 | #define FL_CXX11_SUPPORT_INLINENAMESPACE 1 29 | #define FL_CXX11_SUPPORT_NEWCHARTYPES 1 30 | #define FL_CXX11_SUPPORT_AUTOFUNCTIONS 1 31 | #define FL_CXX11_SUPPORT_UNICODESTRINGS 1 32 | #define FL_CXX11_SUPPORT_RAWSTRINGS 1 33 | #define FL_CXX11_SUPPORT_RANGLEBRACKETS 1 34 | #define FL_CXX11_SUPPORT_RVALUEREFS 1 35 | #define FL_CXX11_SUPPORT_STATICASSERT 1 36 | #define FL_CXX11_SUPPORT_STRONGENUMS 1 37 | #define FL_CXX11_SUPPORT_TYPETRAITS 1 38 | #define FL_CXX11_SUPPORT_VARIADICTEMPLATES 1 39 | #define FL_CXX11_SUPPORT_EXTENDEDSIZEOF 1 40 | #define FL_CXX11_SUPPORT_MAGICSTATICS 1 41 | # if FL_COMPILER_GCC >= FL_GCC_VERSION(4, 6) 42 | #define FL_CXX11_SUPPORT_CONSTEXPR 1 43 | #define FL_CXX11_SUPPORT_FORWARDENUMS 1 44 | #define FL_CXX11_SUPPORT_NULLPTR 1 45 | #define FL_CXX11_SUPPORT_UNRESTRICTEDUNIONS 1 46 | #define FL_CXX11_SUPPORT_RANGEBASEDFOR 1 47 | # if FL_COMPILER_GCC >= FL_GCC_VERSION(4, 7) 48 | #define FL_CXX11_SUPPORT_DELEGATINGCTORS 1 49 | #define FL_CXX11_SUPPORT_EXTENDEDFRIEND 1 50 | #define FL_CXX11_SUPPORT_UDLITERALS 1 51 | #define FL_CXX11_SUPPORT_TEMPLATEALIASES 1 52 | #define FL_CXX11_SUPPORT_OVERRIDESUPPORT 1 53 | #define FL_CXX11_SUPPORT_NONSTATICMEMBERSINIT 1 54 | # if FL_COMPILER_GCC >= FL_GCC_VERSION(4, 8) 55 | #define FL_CXX11_SUPPORT_ALIGNAS 1 56 | #undef FL_CXX11_SUPPORT_DECLTYPE 57 | #define FL_CXX11_SUPPORT_DECLTYPE 2 // decltype v 1.1, N3276 58 | #define FL_CXX11_SUPPORT_INHERITINGCTORS 1 59 | #define FL_CXX11_SUPPORT_THREADLOCALSTORAGE 1 60 | #define FL_CXX11_SUPPORT_ATTRIBUTES 1 61 | # if FL_COMPILER_GCC >= FL_GCC_FULL_VERSION(4, 8, 1) 62 | #define FL_CXX11_SUPPORT_REFQUALIFIERS 1 63 | # if FL_COMPILER_GCC >= FL_GCC_VERSION(4, 9) 64 | # endif // __GNUC_MINOR__ >= 9 65 | # endif // FL_COMPILER_GCC >= FL_GCC_FULL_VERSION(4, 8, 1) 66 | # endif // FL_COMPILER_GCC >= FL_GCC_VERSION(4, 8) 67 | # endif // FL_COMPILER_GCC >= FL_GCC_VERSION(4, 7) 68 | # endif // FL_COMPILER_GCC >= FL_GCC_VERSION(4, 6) 69 | #else // FL_COMPILER_GCC >= FL_GCC_VERSION(4, 5) 70 | #error "Only gcc 4.5 or better is supported" 71 | #endif // // __GNUC__ == 4 72 | 73 | #endif // FLEX_LIB_COMPILER_GCC_H__ 74 | -------------------------------------------------------------------------------- /include/flex_lib/config/compiler_msvc.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_COMPILER_MSVC_H__ 2 | #define FLEX_LIB_COMPILER_MSVC_H__ 3 | 4 | #define FL_MSVC_FULL_VERSION(v, r, p) v * 10000000 + r * 100000 + p 5 | #define FL_MSVC_VERSION(v, r) FL_MSVC_FULL_VERSION(v, r, 0) 6 | 7 | #define FL_COMPILER_MSVC _MSC_FULL_VER 8 | 9 | #define FL_MSVS2010_VERSION FL_MSVC_FULL_VERSION(16, 0, 40219) 10 | #define FL_MSVS2012_VERSION FL_MSVC_FULL_VERSION(17, 0, 50727) 11 | #define FL_MSVS2013_VERSION FL_MSVC_FULL_VERSION(18, 0, 21005) 12 | #define FL_MSVS2015_VERSION FL_MSVC_FULL_VERSION(19, 0, 23918) 13 | #define FL_MSVC10_VERSION FL_MSVS2010_VERSION 14 | #define FL_MSVC11_VERSION FL_MSVS2012_VERSION 15 | #define FL_MSVC12_VERSION FL_MSVS2013_VERSION 16 | #define FL_MSVC13_VERSION FL_MSVS2015_VERSION 17 | 18 | #if 0 19 | #define FL_CXX11_SUPPORT_ALIGNAS 0 20 | #define FL_CXX11_SUPPORT_ALIGNOF 0 21 | #define FL_CXX11_SUPPORT_ATOMIC 0 22 | #define FL_CXX11_SUPPORT_AUTO 0 23 | #define FL_CXX11_SUPPORT_CONSTEXPR 0 24 | #define FL_CXX11_SUPPORT_DECLTYPE 0 25 | #define FL_CXX11_SUPPORT_DEFAULTFUNCTIONS 0 26 | #define FL_CXX11_SUPPORT_DELETEDFUNCTIONS 0 27 | #define FL_CXX11_SUPPORT_DELEGATINGCTORS 0 28 | #define FL_CXX11_SUPPORT_EXPLICITCONVS 0 29 | #define FL_CXX11_SUPPORT_EXTENDEDFRIEND 0 30 | #define FL_CXX11_SUPPORT_FORWARDENUMS 0 31 | #define FL_CXX11_SUPPORT_INHERITINGCTORS 0 32 | #define FL_CXX11_SUPPORT_INITIALIZERLISTS 0 33 | #define FL_CXX11_SUPPORT_LAMBDAS 0 34 | #define FL_CXX14_SUPPORT_POLYLAMBDAS 0 35 | #define FL_CXX14_SUPPORT_LAMBDAINITINCAPTURE 0 36 | #define FL_CXX11_SUPPORT_LOCALTYPESASTPLARGS 0 37 | #define FL_CXX11_SUPPORT_LONGLONG 0 38 | #define FL_CXX11_SUPPORT_INLINENAMESPACE 0 39 | #define FL_CXX11_SUPPORT_NEWCHARTYPES 0 40 | #define FL_CXX11_SUPPORT_AUTOFUNCTIONS 0 41 | #define FL_CXX11_SUPPORT_NULLPTR 0 42 | #define FL_CXX11_SUPPORT_UNICODESTRINGS 0 43 | #define FL_CXX11_SUPPORT_RAWSTRINGS 0 44 | #define FL_CXX11_SUPPORT_UDLITERALS 0 45 | #define FL_CXX11_SUPPORT_RANGLEBRACKETS 0 46 | #define FL_CXX11_SUPPORT_RVALUEREFS 0 47 | #define FL_CXX11_SUPPORT_STATICASSERT 0 48 | #define FL_CXX11_SUPPORT_STRONGENUMS 0 49 | #define FL_CXX11_SUPPORT_TEMPLATEALIASES 0 50 | #define FL_CXX11_SUPPORT_THREADLOCALSTORAGE 0 51 | #define FL_CXX11_SUPPORT_UNRESTRICTEDUNIONS 0 52 | #define FL_CXX11_SUPPORT_TYPETRAITS 0 53 | #define FL_CXX11_SUPPORT_VARIADICTEMPLATES 0 54 | #define FL_CXX11_SUPPORT_RANGEBASEDFOR 0 55 | #define FL_CXX11_SUPPORT_OVERRIDESUPPORT 0 56 | #define FL_CXX11_SUPPORT_ATTRIBUTES 0 57 | #define FL_CXX11_SUPPORT_REFQUALIFIERS 0 58 | #define FL_CXX11_SUPPORT_NONSTATICMEMBERSINIT 0 59 | #define FL_CXX11_SUPPORT_EXTENDEDSIZEOF 0 60 | #define FL_CXX11_SUPPORT_MAGICSTATICS 0 61 | #endif 62 | #define FL_CXX11_SUPPORT_ALIGNOF 0 63 | #define FL_CXX14_SUPPORT_GENERICLAMBDAS 0 64 | #define FL_CXX14_SUPPORT_LAMBDAINITINCAPTURE 0 65 | #define FL_CXX11_SUPPORT_INLINENAMESPACE 0 66 | #define FL_CXX11_SUPPORT_NEWCHARTYPES 0 67 | #define FL_CXX11_SUPPORT_UNICODESTRINGS 0 68 | #define FL_CXX11_SUPPORT_UDLITERALS 0 69 | #define FL_CXX11_SUPPORT_RVALUEREFS 0 70 | #define FL_CXX11_SUPPORT_THREADLOCALSTORAGE 0 71 | #define FL_CXX11_SUPPORT_ATTRIBUTES 0 72 | 73 | #if FL_COMPILER_MSVC >= FL_MSVS2010_VERSION 74 | #define FL_CXX11_SUPPORT_AUTO 1 75 | #define FL_CXX11_SUPPORT_DECLTYPE 1 // decltype v 1.0 76 | #define FL_CXX11_SUPPORT_EXTENDEDFRIEND 1 77 | #define FL_CXX11_SUPPORT_LAMBDAS 1 // lambdas v 1.0 78 | #define FL_CXX11_SUPPORT_LOCALTYPESASTPLARGS 1 79 | #define FL_CXX11_SUPPORT_LONGLONG 1 80 | #define FL_CXX11_SUPPORT_AUTOFUNCTIONS 1 81 | #define FL_CXX11_SUPPORT_NULLPTR 1 82 | #define FL_CXX11_SUPPORT_RANGLEBRACKETS 1 83 | #define FL_CXX11_SUPPORT_STATICASSERT 1 84 | #define FL_CXX11_SUPPORT_STRONGENUMS 1 85 | #define FL_CXX11_SUPPORT_TYPETRAITS 1 86 | # if FL_COMPILER_MSVC >= FL_MSVS2012_VERSION 87 | #define FL_CXX11_SUPPORT_ATOMIC 1 88 | #undef FL_CXX11_SUPPORT_DECLTYPE 89 | #define FL_CXX11_SUPPORT_DECLTYPE 2 // decltype v 1.1 90 | #define FL_CXX11_SUPPORT_FORWARDENUMS 1 91 | #undef FL_CXX11_SUPPORT_LAMBDAS 92 | #define FL_CXX11_SUPPORT_LAMBDAS 2 // lambdas v 1.1 93 | #define FL_CXX11_SUPPORT_RANGEBASEDFOR 1 94 | #define FL_CXX11_SUPPORT_OVERRIDESUPPORT 1 95 | # if FL_COMPILER_MSVC >= FL_MSVS2013_VERSION 96 | #define FL_CXX11_SUPPORT_DEFAULTFUNCTIONS 1 97 | #define FL_CXX11_SUPPORT_DELETEDFUNCTIONS 1 98 | #define FL_CXX11_SUPPORT_DELEGATINGCTORS 1 99 | #define FL_CXX11_SUPPORT_EXPLICITCONVS 1 100 | #define FL_CXX11_SUPPORT_INITIALIZERLISTS 1 101 | #define FL_CXX11_SUPPORT_RAWSTRINGS 1 102 | #define FL_CXX11_SUPPORT_TEMPLATEALIASES 1 103 | #define FL_CXX11_SUPPORT_VARIADICTEMPLATES 1 104 | #define FL_CXX11_SUPPORT_NONSTATICMEMBERSINIT 1 105 | # if FL_COMPILER_MSVC > FL_MSVS2013_VERSION // MSVS 2013 Nov CTP and better 106 | #define FL_CXX11_SUPPORT_ALIGNAS 1 107 | #define FL_CXX11_SUPPORT_CONSTEXPR 1 108 | #define FL_CXX11_SUPPORT_INHERITINGCTORS 1 109 | #define FL_CXX11_SUPPORT_REFQUALIFIERS 1 110 | #define FL_CXX11_SUPPORT_EXTENDEDSIZEOF 1 111 | #define FL_CXX11_SUPPORT_MAGICSTATICS 1 112 | #define FL_CXX11_SUPPORT_UNRESTRICTEDUNIONS 1 113 | # endif // FL_COMPILER_MSVC > FL_MSVS2013_VERSION 114 | # endif // FL_COMPILER_MSVC >= FL_MSVS2013_VERSION 115 | # endif // FL_COMPILER_MSVC >= FL_MSVS2012_VERSION 116 | #else // FL_COMPILER_MSVC >= FL_MSVS2010_VERSION 117 | # error "Only MSVS 2010 (MSC 16.00) or better is supported" 118 | #endif // FL_COMPILER_MSVC >= FL_MSVS2010_VERSION 119 | 120 | #endif // FLEX_LIB_COMPILER_MSVC_H__ 121 | -------------------------------------------------------------------------------- /include/flex_lib/config/config.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_CONFIG_H__ 2 | #define FLEX_LIB_CONFIG_H__ 3 | 4 | #include "compiler.h" 5 | 6 | #endif // FLEX_LIB_CONFIG_H__ 7 | -------------------------------------------------------------------------------- /include/flex_lib/detector.h: -------------------------------------------------------------------------------- 1 | #ifndef DETECTOR_H 2 | #define DETECTOR_H 3 | 4 | #include 5 | 6 | namespace flex_lib 7 | { 8 | template< class... > 9 | using void_t = void; 10 | 11 | struct nonesuch { 12 | nonesuch() = delete; 13 | ~nonesuch() = delete; 14 | nonesuch(nonesuch const&) = delete; 15 | void operator=(nonesuch const&) = delete; 16 | }; 17 | 18 | // Copy of std::experemental from library fundamentals TR2 proposal 19 | namespace detail { 20 | template class Op, class... Args> 22 | struct detector { 23 | using value_t = std::false_type; 24 | using type = Default; 25 | }; 26 | 27 | template class Op, class... Args> 28 | struct detector>, Op, Args...> { 29 | using value_t = std::true_type; 30 | using type = Op; 31 | }; 32 | 33 | } // namespace detail 34 | 35 | template class Op, class... Args> 36 | using is_detected = typename detail::detector::value_t; 37 | 38 | template class Op, class... Args> 39 | using detected_t = typename detail::detector::type; 40 | 41 | template class Op, class... Args> 42 | using detected_or = detail::detector; 43 | 44 | } // flex_lib 45 | 46 | #endif // DETECTOR_H 47 | -------------------------------------------------------------------------------- /include/flex_lib/foreach.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 26.06.2010 15:24 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20100626 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef GameWorld_xboost_foreach_hpp__ 12 | #define GameWorld_xboost_foreach_hpp__ 13 | 14 | #include "iterator.hpp" 15 | 16 | #define BOOST_FOREACH(var, cont) \ 17 | if (bool continue_loop_ = true) \ 18 | for (auto p_iterator_ = xboost::begin(cont); p_iterator_ != xboost::end(cont); ++ p_iterator_, continue_loop_ = true) \ 19 | for (var = *p_iterator_; continue_loop_; continue_loop_ = false) 20 | 21 | #define BOOST_AUTO_FOREACH(v, cont) BOOST_FOREACH(auto v, cont) 22 | 23 | #define FOREACH(v, cont) BOOST_FOREACH(v, cont) 24 | #define AUTO_FOREACH(v, cont) BOOST_AUTO_FOREACH(v, cont) 25 | 26 | #endif // GameWorld_xboost_foreach_hpp__ 27 | -------------------------------------------------------------------------------- /include/flex_lib/iterator.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 26.06.2010 15:24 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20100626 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef GameWorld_xboost_iterator_hpp__ 12 | #define GameWorld_xboost_iterator_hpp__ 13 | 14 | #include 15 | 16 | namespace xboost 17 | { 18 | template 19 | auto begin(C& cont) -> decltype(cont.begin()) {return cont.begin();} 20 | 21 | template 22 | auto end(C& cont) -> decltype(cont.end()) {return cont.end();} 23 | 24 | template 25 | auto begin(C const& cont) -> decltype(cont.begin()) {return cont.begin();} 26 | 27 | template 28 | auto end(C const& cont) -> decltype(cont.end()) {return cont.end();} 29 | 30 | template 31 | C* begin(C (&cont)[N]) {return cont;} 32 | 33 | template 34 | C* end(C (&cont)[N]) {return cont + N;} 35 | 36 | 37 | } 38 | 39 | #endif // GameWorld_xboost_iterator_hpp__ 40 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_H__ 2 | #define FLEX_LIB_LAZY_LIST_H__ 3 | 4 | #include "config/config.h" 5 | #include "lazy_list/lazy_list_impl.h" 6 | #include "lazy_list/lazy_list_iterator.h" 7 | #include "lazy_list/lazy_list_factory.h" 8 | #include "lazy_list/lazy_list_ops.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace fl = flex_lib; 18 | 19 | #endif // FLEX_LIB_LAZY_LIST_H__ 20 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list.inl.h: -------------------------------------------------------------------------------- 1 | // This is a part of lazy_list.h file. 2 | 3 | #if 0 4 | template class A> 5 | lazy_list lazy_list::tail() const 6 | { 7 | typedef NodeEvaluator node_evtor_t; 8 | NodeIniter initer; 9 | bool is_first_time = true; 10 | 11 | return this_type([is_first_time, this, initer](bool& isEOS) mutable -> node_evtor_t 12 | { 13 | if (is_first_time) 14 | { 15 | if (this->begin() == this->end()) 16 | { 17 | isEOS = true; 18 | return node_evtor_t(); 19 | } 20 | 21 | auto tb = ++ this->begin(); 22 | auto te = this->end(); 23 | initer = this->MakeRangeIniter(tb, te); 24 | is_first_time = false; 25 | } 26 | 27 | return initer(isEOS); 28 | }); 29 | } 30 | #endif 31 | 32 | 33 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list/common.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_COMMON_H 2 | #define FLEX_LIB_LAZY_LIST_COMMON_H 3 | 4 | #include 5 | 6 | #if defined(Yield) 7 | #undef Yield 8 | #endif 9 | 10 | namespace flex_lib 11 | { 12 | template 13 | struct LazyListConstructorBase 14 | { 15 | typedef LazyListConstructorBase this_type; 16 | template 17 | struct ListNode 18 | { 19 | mutable U m_nodeValue; 20 | 21 | mutable bool m_isConstructed = false; 22 | mutable bool m_isFinalNode = false; 23 | 24 | U const& Dereference() const 25 | { 26 | return m_nodeValue; 27 | } 28 | 29 | void Construct(this_type& ctor) const 30 | { 31 | if (m_isConstructed) 32 | return; 33 | 34 | m_isFinalNode = ctor.Yield(*this); 35 | m_isConstructed = true; 36 | } 37 | 38 | ListNode(bool isFinal = false) 39 | : m_isFinalNode(isFinal) 40 | { 41 | ; 42 | } 43 | }; 44 | 45 | typedef ListNode ListNodeType; 46 | typedef std::list ListType; 47 | mutable ListType m_items; 48 | 49 | LazyListConstructorBase() 50 | { 51 | m_items.emplace_back(false); 52 | } 53 | 54 | bool Yield(const ListNodeType &node) 55 | { 56 | bool isEos = false; 57 | auto val = GetNextItem(isEos); 58 | if (!isEos) 59 | { 60 | node.m_nodeValue = std::move(val); 61 | m_items.emplace_back(false); 62 | } 63 | 64 | return isEos; 65 | } 66 | 67 | private: 68 | virtual VT GetNextItem(bool &isEos) = 0; 69 | }; 70 | 71 | template 72 | class LazyListConstructor : public LazyListConstructorBase 73 | { 74 | public: 75 | LazyListConstructor(Gen &&gen) 76 | : m_gen(std::move(gen)) 77 | { 78 | ; 79 | } 80 | 81 | VT GetNextItem(bool &isEos) 82 | { 83 | return m_gen(isEos); 84 | } 85 | 86 | private: 87 | mutable Gen m_gen; 88 | }; 89 | 90 | #if 0 91 | template 92 | struct lazy_list_constructor; 93 | 94 | template 95 | using node_producer = std::function; 96 | 97 | template 98 | struct lazy_list_constructor 99 | { 100 | typedef VT value_type; 101 | typedef std::function NodeIniter; 102 | NodeIniter node_initer; 103 | 104 | template 105 | void Init(L& list) 106 | { 107 | list.InitValueList(std::move(node_initer)); 108 | } 109 | }; 110 | 111 | template 112 | struct lazy_list_constructor 113 | { 114 | typedef VT value_type; 115 | typedef node_producer NodeEvaluator; 116 | typedef std::function NodeIniter; 117 | NodeIniter node_initer; 118 | 119 | template 120 | void Init(L& list) 121 | { 122 | list.InitLazyList(std::move(node_initer)); 123 | } 124 | }; 125 | #endif 126 | } 127 | 128 | namespace fl = flex_lib; 129 | 130 | #endif // FLEX_LIB_LAZY_LIST_COMMON_H 131 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list/lazy_list_builder.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_BUILDER_H 2 | #define FLEX_LIB_LAZY_LIST_BUILDER_H 3 | 4 | #include "common.h" 5 | #include "lazy_list_impl.h" 6 | 7 | #include 8 | 9 | namespace flex_lib { 10 | namespace detail { 11 | 12 | template 13 | auto MakeLazyListBuilder(Gen &&gen); 14 | 15 | template 16 | class LazyListBuilder 17 | { 18 | public: 19 | typedef VT value_type; 20 | typedef Gen generator_type; 21 | typedef LazyListBuilder this_type; 22 | 23 | explicit LazyListBuilder(Gen &&gen) 24 | : m_gen(std::move(gen)) 25 | { 26 | ; 27 | } 28 | 29 | explicit LazyListBuilder(const Gen &gen) 30 | : m_gen(gen) 31 | { 32 | ; 33 | } 34 | 35 | LazyListBuilder(this_type &&other) 36 | : m_gen(std::move(other.m_gen)) 37 | { 38 | ; 39 | } 40 | 41 | this_type& operator = (this_type &&other) 42 | { 43 | m_gen = std::move(other.m_gen); 44 | return *this; 45 | } 46 | 47 | lazy_list done() 48 | { 49 | typedef LazyListConstructorBase ConstructorBase; 50 | typedef LazyListConstructor Constructor; 51 | auto ctor = std::make_shared(std::move(m_gen)); 52 | 53 | return lazy_list(std::static_pointer_cast(ctor)); 54 | } 55 | 56 | operator lazy_list() 57 | { 58 | return done(); 59 | } 60 | 61 | template>> 62 | operator lazy_list() 63 | { 64 | return map([](const VT &v) {return VT1(v);}).done(); 65 | } 66 | 67 | auto tail() 68 | { 69 | auto newGen = [is_first_time = true, gen = std::move(m_gen)](bool &isEos) mutable 70 | { 71 | if (is_first_time) 72 | { 73 | is_first_time = false; 74 | gen(isEos); 75 | if (isEos) 76 | return VT(); 77 | } 78 | 79 | return gen(isEos); 80 | }; 81 | 82 | return MakeLazyListBuilder(std::move(newGen)); 83 | } 84 | 85 | template 86 | auto cons(const U& val) 87 | { 88 | auto newGen = [is_first_time = true, gen = std::move(m_gen), val](bool &isEos) mutable 89 | { 90 | if (is_first_time) 91 | { 92 | is_first_time = false; 93 | return VT(val); 94 | } 95 | 96 | return gen(isEos); 97 | }; 98 | 99 | return MakeLazyListBuilder(std::move(newGen)); 100 | } 101 | 102 | template 103 | auto filter(Fn &&filter) 104 | { 105 | auto newGen = [filter = std::forward(filter), gen = std::move(m_gen)](bool &isEos) mutable 106 | { 107 | do 108 | { 109 | auto val = gen(isEos); 110 | if (!isEos && filter(val)) 111 | return val; 112 | 113 | } while (!isEos); 114 | 115 | return VT(); 116 | }; 117 | 118 | return MakeLazyListBuilder(std::move(newGen)); 119 | } 120 | 121 | template 122 | auto map(Fn &&mapper) 123 | { 124 | typedef std::decay_t MVT; 125 | 126 | auto newGen = [mapper = std::forward(mapper), gen = std::move(m_gen)](bool &isEos) mutable 127 | { 128 | auto val = gen(isEos); 129 | if (!isEos) 130 | return mapper(val); 131 | 132 | return MVT(); 133 | }; 134 | 135 | return MakeLazyListBuilder(std::move(newGen)); 136 | } 137 | 138 | template 139 | auto zip(const lazy_list &l2, Fn &&zipper) 140 | { 141 | typedef std::decay_t ZVT; 142 | 143 | auto newGen = [zipper = std::forward(zipper), b = l2.begin(), e = l2.end(), gen = std::move(m_gen)](bool &isEos) mutable 144 | { 145 | if (b != e) 146 | { 147 | auto v2 = *b ++; 148 | auto v1 = gen(isEos); 149 | if (!isEos) 150 | return zipper(v1, v2); 151 | } 152 | else 153 | isEos = true; 154 | 155 | return ZVT(); 156 | }; 157 | 158 | return MakeLazyListBuilder(std::move(newGen)); 159 | } 160 | 161 | template 162 | auto zip_self(Fn &&zipper) 163 | { 164 | typedef std::decay_t ZVT; 165 | 166 | auto newGen = [zipper = std::forward(zipper), gen = std::move(m_gen)](bool &isEos) mutable 167 | { 168 | auto v = gen(isEos); 169 | if (!isEos) 170 | return zipper(v, v); 171 | 172 | return ZVT(); 173 | }; 174 | 175 | return MakeLazyListBuilder(std::move(newGen)); 176 | } 177 | 178 | private: 179 | Gen m_gen; 180 | }; 181 | 182 | template 183 | auto MakeLazyListBuilder(Gen &&gen) 184 | { 185 | typedef std::decay_t GenType; 186 | return LazyListBuilder(std::forward(gen)); 187 | } 188 | } 189 | 190 | } 191 | 192 | #endif // FLEX_LIB_LAZY_LIST_BUILDER_H 193 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list/lazy_list_factory.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_FACTORY_H 2 | #define FLEX_LIB_LAZY_LIST_FACTORY_H 3 | 4 | #include "common.h" 5 | #include "lazy_list_builder.h" 6 | #include 7 | #include 8 | #include 9 | 10 | namespace flex_lib 11 | { 12 | template 13 | auto lazy_from(It b, It e) 14 | { 15 | typedef typename std::iterator_traits::value_type VT; 16 | auto gen = [b, e](bool &isEos) mutable 17 | { 18 | if (b == e) 19 | { 20 | isEos = true; 21 | return VT(); 22 | } 23 | 24 | return *b ++; 25 | }; 26 | 27 | return detail::MakeLazyListBuilder(std::move(gen)); 28 | } 29 | 30 | template 31 | auto lazy_from(VT (&items)[SZ]) 32 | { 33 | auto first = &items[0]; 34 | return lazy_from(first, first + SZ); 35 | } 36 | 37 | template 38 | auto lazy_from(C &cont) -> decltype(lazy_from(cont.begin(), cont.end())) 39 | { 40 | return lazy_from(cont.begin(), cont.end()); 41 | } 42 | 43 | template 44 | auto lazy_from(const C &cont) -> decltype(lazy_from(cont.begin(), cont.end())) 45 | { 46 | return lazy_from(cont.begin(), cont.end()); 47 | } 48 | 49 | template 50 | auto lazy_generate(Gen &&gen) 51 | { 52 | typedef std::decay_t VT; 53 | return detail::MakeLazyListBuilder(std::forward(gen)); 54 | } 55 | 56 | template 57 | auto lazy_sequence(size_t n, T start = 0, T step = 1) 58 | { 59 | auto gen = [start, step, n = 0, max = n](bool &isEos) mutable 60 | { 61 | if (n == max) 62 | { 63 | isEos = true; 64 | return T(); 65 | } 66 | n ++; 67 | auto cur = start; 68 | start += step; 69 | 70 | return cur; 71 | }; 72 | 73 | return detail::MakeLazyListBuilder(std::move(gen)); 74 | } 75 | } 76 | 77 | #endif // FLEX_LIB_LAZY_LIST_FACTORY_H 78 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list/lazy_list_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_IMPL_H 2 | #define FLEX_LIB_LAZY_LIST_IMPL_H 3 | 4 | #include "common.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include "../variant.h" 10 | 11 | namespace flex_lib 12 | { 13 | template 14 | class lazy_list_iterator; 15 | 16 | template class lazy_list 17 | { 18 | public: 19 | typedef LazyListConstructorBase ListConstructor; 20 | typedef std::shared_ptr ListConstructorPtr; 21 | 22 | private: 23 | typedef lazy_list this_type; 24 | 25 | public: 26 | typedef NT value_type; 27 | typedef const value_type const_value_type; 28 | typedef value_type& reference_type; 29 | typedef value_type const& const_reference_type; 30 | typedef NT* pointer_type; 31 | typedef NT const* const_pointer_type; 32 | typedef typename ListConstructor::ListNodeType node_type_t; 33 | typedef typename ListConstructor::ListType inner_list_t; 34 | typedef lazy_list_iterator const_iterator; 35 | typedef const_iterator iterator; 36 | 37 | lazy_list() 38 | { 39 | } 40 | 41 | lazy_list(ListConstructorPtr ctor) 42 | : m_constructor(ctor) 43 | { 44 | } 45 | 46 | const_iterator begin() const {return !m_constructor ? const_iterator(*this) : const_iterator(*this, m_constructor->m_items.begin());} 47 | const_iterator end() const {return const_iterator(*this);} 48 | const_iterator constructed_end() const {return !m_constructor ? const_iterator(*this) : const_iterator(*this, -- m_constructor->m_items.end());} 49 | 50 | const_iterator cbegin() const {return begin();} 51 | const_iterator cend() const {return end();} 52 | 53 | const_reference_type front() const {return *begin();} 54 | 55 | const_reference_type head() const {return front();} 56 | 57 | bool empty() const 58 | { 59 | return !m_constructor || begin() == end(); 60 | } 61 | 62 | size_t size() const 63 | { 64 | return std::distance(begin(), end()); 65 | } 66 | 67 | private: 68 | mutable ListConstructorPtr m_constructor; 69 | friend class lazy_list_iterator; 70 | 71 | }; 72 | } 73 | 74 | #endif // FLEX_LIB_LAZY_LIST_IMPL_H 75 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list/lazy_list_iterator.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_ITERATOR_H 2 | #define FLEX_LIB_LAZY_LIST_ITERATOR_H 3 | 4 | namespace flex_lib 5 | { 6 | template 7 | class lazy_list_iterator 8 | { 9 | typedef typename LL::inner_list_t::const_iterator inner_iterator; 10 | public: 11 | typedef lazy_list_iterator this_type; 12 | typedef typename LL::node_type_t node_type_t; 13 | 14 | typedef typename inner_iterator::difference_type difference_type; 15 | typedef std::forward_iterator_tag iterator_category; 16 | typedef typename LL::value_type value_type; 17 | typedef typename LL::value_type const* pointer; 18 | typedef typename LL::value_type const& reference; 19 | 20 | // TODO: Copy and default constructors 21 | 22 | lazy_list_iterator(LL const& list) : iterating_list(&list), is_end(true) {;} 23 | lazy_list_iterator(const this_type &other) = default; 24 | lazy_list_iterator(this_type &&other) 25 | : iterating_list(other.iterating_list) 26 | , current(std::move(other.current)) 27 | , is_end(other.is_end) 28 | { 29 | other.iterating_list = nullptr; 30 | other.is_end = true; 31 | } 32 | 33 | lazy_list_iterator(LL const& list, inner_iterator it) : iterating_list(&list), current(it), is_end(false) {;} 34 | 35 | reference operator*() const 36 | { 37 | current->Construct(*iterating_list->m_constructor.get()); 38 | return current->Dereference(); 39 | } 40 | 41 | pointer operator->() const 42 | { 43 | current->Construct(*iterating_list->m_constructor.get()); 44 | return ¤t->Dereference(); 45 | } 46 | 47 | this_type& operator ++() 48 | { 49 | if (current->m_isFinalNode) 50 | return *this; 51 | 52 | inner_iterator it = current ++; 53 | if (current == iterating_list->m_constructor->m_items.end() || !current->m_isConstructed) 54 | { 55 | if (current != iterating_list->m_constructor->m_items.end()) 56 | { 57 | current->Construct(*iterating_list->m_constructor.get()); 58 | } 59 | else 60 | { 61 | it->Construct(*iterating_list->m_constructor.get()); 62 | current = ++ it; 63 | } 64 | } 65 | 66 | return *this; 67 | } 68 | 69 | this_type operator ++(int) 70 | { 71 | this_type tmp(*this); 72 | ++(*this); 73 | return tmp; 74 | } 75 | 76 | bool operator == (this_type const& other) const 77 | { 78 | if (is_end) 79 | { 80 | if (other.is_end) 81 | return true; 82 | 83 | if (other.iterating_list != iterating_list) 84 | return false; 85 | 86 | if (!other.current->m_isConstructed) 87 | other.current->Construct(*iterating_list->m_constructor.get()); 88 | 89 | return other.current->m_isFinalNode; 90 | } 91 | 92 | if (!current->m_isConstructed) 93 | current->Construct(*iterating_list->m_constructor.get()); 94 | 95 | if (other.is_end) 96 | return other == *this; 97 | 98 | return current == other.current; 99 | } 100 | 101 | bool operator != (this_type const& other) const 102 | { 103 | return !(*this == other); 104 | } 105 | 106 | this_type& operator = (this_type const& other) 107 | { 108 | if (this == &other) 109 | return *this; 110 | 111 | iterating_list = other.iterating_list; 112 | current = other.current; 113 | is_end = other.is_end; 114 | return *this; 115 | } 116 | 117 | void swap(this_type& other) 118 | { 119 | std::swap(iterating_list, other.iterating_list); 120 | current.swap(other.current); 121 | std::swap(is_end, other.is_end); 122 | } 123 | 124 | private: 125 | LL const* iterating_list; 126 | inner_iterator current; 127 | bool is_end; 128 | }; 129 | 130 | 131 | } 132 | 133 | #endif // FLEX_LIB_LAZY_LIST_ITERATOR_H 134 | -------------------------------------------------------------------------------- /include/flex_lib/lazy_list/lazy_list_ops.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_LAZY_LIST_OPS_H 2 | #define FLEX_LIB_LAZY_LIST_OPS_H 3 | 4 | #include "lazy_list_impl.h" 5 | #include "lazy_list_factory.h" 6 | 7 | namespace flex_lib 8 | { 9 | 10 | template 11 | lazy_list tail(const lazy_list &ll) 12 | { 13 | return fl::lazy_from(ll).tail().done(); 14 | } 15 | 16 | template 17 | lazy_list cons(const lazy_list &ll, V &&val) 18 | { 19 | return fl::lazy_from(ll).cons(val).done(); 20 | } 21 | 22 | template 23 | auto filter(const lazy_list &ll, Fn &&val) 24 | { 25 | return fl::lazy_from(ll).filter(std::forward(val)).done(); 26 | } 27 | 28 | template 29 | auto map(const lazy_list &ll, Fn &&val) 30 | { 31 | return fl::lazy_from(ll).map(std::forward(val)).done(); 32 | } 33 | 34 | template 35 | auto zip(const lazy_list &l1, const lazy_list &l2, Fn &&val) 36 | { 37 | return fl::lazy_from(l1).zip(l2, std::forward(val)).done(); 38 | } 39 | 40 | template 41 | auto zip_self(const lazy_list &ll, Fn &&val) 42 | { 43 | return fl::lazy_from(ll).zip_self(std::forward(val)).done(); 44 | } 45 | } 46 | 47 | #endif // FLEX_LIB_LAZY_LIST_OPS_H 48 | -------------------------------------------------------------------------------- /include/flex_lib/pimpl.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_PIMPL_H 2 | #define FLEX_LIB_PIMPL_H 3 | 4 | #include "detector.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace flex_lib 10 | { 11 | template 12 | class pimpl 13 | { 14 | protected: 15 | typedef ImplType impl_t; 16 | std::unique_ptr m_impl; 17 | 18 | 19 | protected: 20 | template 21 | pimpl(Args&& ... args) 22 | : m_impl(new impl_t(std::forward(args)...)) 23 | { 24 | } 25 | 26 | ~pimpl() {;} 27 | 28 | #if 0 29 | template(args)...)), ImplType>::value, void*>> 30 | // static auto Create(Impl* impl, Args&& ... args) -> std::enable_if_t(args)...)), ImplType>::value, ImplPtr> 31 | static auto Create(Impl* impl, Args&& ... args) -> decltype(std::make_unique(impl, std::forward(args)...)) 32 | { 33 | return std::make_unique(impl, std::forward(args)...); 34 | } 35 | 36 | template(args)...)), ImplType>::value, void*>> 37 | // static auto Create(Impl*, Args&& ... args) -> std::enable_if_t(args)...)), ImplType>::value, ImplPtr> 38 | static auto Create(Impl*, Args&& ... args) -> decltype(std::make_unique(std::forward(args)...)) 39 | { 40 | return std::make_unique(std::forward(args)...); 41 | } 42 | #endif 43 | }; 44 | } 45 | 46 | #endif // FLEX_LIB_PIMPL_H 47 | -------------------------------------------------------------------------------- /include/flex_lib/properties/abstract_property.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:32 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_abstract_property_hpp__ 12 | #define Sandbox_Source_Files_property_abstract_property_hpp__ 13 | 14 | #include "properties_fwd.hpp" 15 | 16 | # define MAKE_ABST_PROP_IMPL_TYPE_SIMPLE(ClassName, BaseClassName, PI) boost::properties::detail::AbstractPropImpl 17 | # define MAKE_ABST_PROP_IMPL_TYPE_RW(ClassName, BaseClassName, PI) MAKE_ABST_PROP_IMPL_TYPE_SIMPLE(ClassName, BaseClassName, PI) 18 | # define MAKE_ABST_PROP_IMPL_TYPE_FWD_RW(ClassName, BaseClassName, PI) MAKE_ABST_PROP_IMPL_TYPE_SIMPLE(ClassName, BaseClassName, PI) 19 | 20 | # define DEFINE_PROPERTY_ABST(ClassName, PI) DEFINE_PROPERTY_GENERIC_X(ClassName, PI, DefaultPropertyBase, BOOST_PP_SEQ_ELEM(5, PI)) 21 | 22 | # define DEFINE_PROPERTY_ABST_IMPL(ClassName, PI) \ 23 | BOOST_PP_CAT(DEFINE_PROPERTY_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI))) (ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 24 | BOOST_PP_CAT(MAKE_ABST_PROP_IMPL_TYPE_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI))) (ClassName, BOOST_PP_SEQ_ELEM(5, PI), BOOST_PP_SEQ_ELEM(6, PI)) BOOST_PP_CAT(PROP_NAME(BOOST_PP_SEQ_ELEM(6, PI)),_aimpl_); 25 | 26 | # define DEFINE_PROPERTY_IMPL_AS_MEMBER_ABST(ClassName, PI) 27 | # define DEFINE_PROPERTY_IMPL_AS_MEMBER_ABST_IMPL(ClassName, PI) \ 28 | BOOST_PP_CAT(DEFINE_PROPERTY_IMPL_AS_MEMBER_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 29 | DEFINE_PROPERTY_IMPL_AS_MEMBER_ABST(ClassName, PI) 30 | 31 | # define DEFINE_PROPERTY_IMPL_AS_STATIC_ABST(ClassName, PI) 32 | # define DEFINE_PROPERTY_IMPL_AS_STATIC_ABST_IMPL(ClassName, PI) \ 33 | BOOST_PP_CAT(DEFINE_PROPERTY_IMPL_AS_STATIC_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 34 | DEFINE_PROPERTY_IMPL_AS_STATIC_ABST(ClassName, PI) 35 | 36 | # define INITIALIZE_PROPERTY_IMPL_ABST(ClassName, PI) 37 | # define INITIALIZE_PROPERTY_IMPL_ABST_IMPL(ClassName, PI) \ 38 | BOOST_PP_CAT(INITIALIZE_PROPERTY_IMPL_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 39 | host->BOOST_PP_SEQ_ELEM(5, PI)::PROP_NAME(BOOST_PP_SEQ_ELEM(6, PI)).Init(host, &host->BOOST_PP_CAT(PROP_NAME(BOOST_PP_SEQ_ELEM(6, PI)),_aimpl_)); \ 40 | host->BOOST_PP_CAT(PROP_NAME(BOOST_PP_SEQ_ELEM(6, PI)),_aimpl_).Init(&host->PROP_NAME(BOOST_PP_SEQ_ELEM(6, PI))); 41 | 42 | # define COPY_PROPERTY_IMPL_ABST(_1, _2) 43 | # define COPY_PROPERTY_IMPL_ABST_IMPL(ClassName, PI) \ 44 | BOOST_PP_CAT(COPY_PROPERTY_IMPL_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 45 | 46 | # define SERIALIZE_PROPERTY_IMPL_ABST(ClassName, PI) 47 | # define SERIALIZE_PROPERTY_IMPL_ABST_IMPL(ClassName, PI) \ 48 | BOOST_PP_CAT(SERIALIZE_PROPERTY_IMPL_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 49 | 50 | # define INVOKE_GET_PROPERTY_IMPL_ABST(ClassName, PI) INVOKE_GET_PROPERTY_IMPL_GENERIC(ClassName, PI) 51 | # define INVOKE_GET_PROPERTY_IMPL_ABST_IMPL(ClassName, PI) \ 52 | BOOST_PP_CAT(INVOKE_GET_PROPERTY_IMPL_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 53 | 54 | # define INVOKE_SET_PROPERTY_IMPL_ABST(ClassName, PI) INVOKE_SET_PROPERTY_IMPL_GENERIC(ClassName, PI) 55 | # define INVOKE_SET_PROPERTY_IMPL_ABST_IMPL(ClassName, PI) \ 56 | BOOST_PP_CAT(INVOKE_SET_PROPERTY_IMPL_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 57 | 58 | # define ENUM_PROPERTY_IMPL_ABST(ClassName, PI) ENUM_PROPERTY_IMPL_GENERIC(ClassName, PI) 59 | # define ENUM_PROPERTY_IMPL_ABST_IMPL(ClassName, PI) \ 60 | BOOST_PP_CAT(ENUM_PROPERTY_IMPL_, PROP_KIND(BOOST_PP_SEQ_ELEM(6, PI)))(ClassName, BOOST_PP_SEQ_ELEM(6, PI)) \ 61 | 62 | #define ABSTRACT_RW_PROPERTY(Type, Name) ( (ABST)((Type))(Property)(AbstractPropertyImpl)(Name)(ReadWritePropertyAccessors) ) 63 | #define ABSTRACT_RW_PROPERTY_V(Type, Name) ( (ABST)((boost::properties::by_val))(Property)(AbstractPropertyImpl)(Name)(ReadWritePropertyAccessors) ) 64 | #define ABSTRACT_RO_PROPERTY(Type, Name) ( (ABST)((Type))(Property)(AbstractPropertyImpl)(Name)(ReadPropertyAccessors) ) 65 | #define ABSTRACT_RO_PROPERTY_V(Type, Name) ( (ABST)((boost::properties::by_val))(Property)(AbstractPropertyImpl)(Name)(ReadPropertyAccessors) ) 66 | #define ABSTRACT_WO_PROPERTY(Type, Name) ( (ABST)((Type))(Property)(AbstractPropertyImpl)(Name)(WritePropertyAccessors) ) 67 | #define ABSTRACT_WO_PROPERTY_V(Type, Name) ( (ABST)((boost::properties::by_val))(Property)(AbstractPropertyImpl)(Name)(WritePropertyAccessors) ) 68 | 69 | #define IMPLEMENT_PROPERTY(BaseClass, ImplProp) ( (ABST_IMPL)((_))(PropertyImpl)(_)(_)(BaseClass)ImplProp ) 70 | #define IMPLEMENT_PROPERTY_INH(BaseClass, BaseType, ImplProp) ( (ABST_IMPL_INH)((_))(PropertyImpl)(_)(_)(BaseClass)(BaseType)ImplProp ) 71 | 72 | namespace boost 73 | { 74 | namespace properties 75 | { 76 | namespace detail 77 | { 78 | template 79 | class AbstractPropertyImpl 80 | { 81 | public: 82 | typedef PropertyTraits traits; 83 | typedef typename traits::arg_type arg_type; 84 | 85 | virtual typename traits::result_type get(H const* host) const = 0; 86 | virtual typename traits::result_type get(H* host) = 0; 87 | virtual void set(H* host, typename traits::arg_type val) = 0; 88 | }; 89 | 90 | template 91 | class AbstractPropImpl : public AbstractPropertyImpl 92 | { 93 | public: 94 | typedef typename AbstractPropertyImpl base_type; 95 | typedef typename base_type::traits::arg_type arg_type; 96 | 97 | typename base_type::traits::result_type get(BT const* host) const 98 | { 99 | return m_Prop->safe_get(); 100 | } 101 | 102 | typename base_type::traits::result_type get(BT* host) 103 | { 104 | return m_Prop->safe_get(); 105 | } 106 | 107 | void set(BT* host, typename base_type::traits::arg_type val) 108 | { 109 | m_Prop->safe_set(val); 110 | } 111 | 112 | void Init(P* prop) 113 | { 114 | m_Prop = prop; 115 | } 116 | private: 117 | P* m_Prop; 118 | }; 119 | 120 | } 121 | } 122 | } 123 | 124 | #endif // Sandbox_Source_Files_property_abstract_property_hpp__ 125 | -------------------------------------------------------------------------------- /include/flex_lib/properties/dynamic_access.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 14.01.2009 23:51 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20090114 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef properties_Boost_headers_dynamic_access_hpp__ 12 | #define properties_Boost_headers_dynamic_access_hpp__ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | namespace boost 19 | { 20 | namespace properties 21 | { 22 | class PropertyInaccessable : public std::exception 23 | { 24 | public: 25 | PropertyInaccessable(const char* name) 26 | { 27 | m_Description = std::string("Property '") + name + std::string("' is inaccessable"); 28 | } 29 | ~PropertyInaccessable() throw() {;} 30 | const char* what() const throw() {return m_Description.c_str();} 31 | private: 32 | std::string m_Description; 33 | }; 34 | 35 | class PropertyNotDefined : public std::exception 36 | { 37 | public: 38 | PropertyNotDefined(const char* name, const char* className) 39 | { 40 | m_Description = std::string("Property '") + name + std::string("' is not defined for the class '") + className + std::string("'"); 41 | } 42 | ~PropertyNotDefined() throw() {;} 43 | const char* what() const throw() {return m_Description.c_str();} 44 | private: 45 | std::string m_Description; 46 | }; 47 | 48 | namespace detail 49 | { 50 | template 51 | struct PropertyGetter 52 | { 53 | template 54 | static typename boost::enable_if_c< 55 | std::is_convertible::value && 56 | P::has_getter, R>::type 57 | Get(const char* name, P const& prop) 58 | { 59 | return prop.safe_get(); 60 | } 61 | template 62 | static typename std::enable_if< 63 | !std::is_convertible::value || 64 | !P::has_getter, R>::type 65 | Get(const char* name, P const& prop) 66 | { 67 | throw PropertyInaccessable(name); 68 | } 69 | }; 70 | 71 | template 72 | struct PropertySetter 73 | { 74 | template 75 | static typename std::enable_if< 76 | std::is_convertible::value && 77 | P::has_setter, void>::type 78 | Set(const char* name, P& prop, V val) 79 | { 80 | prop.safe_set(val); 81 | } 82 | template 83 | static typename std::enable_if< 84 | !std::is_convertible::value || 85 | !P::has_setter, void>::type 86 | Set(const char* name, P& prop, V val) 87 | { 88 | throw PropertyInaccessable(name); 89 | } 90 | }; 91 | 92 | template 93 | struct PropertyAccessorBase 94 | { 95 | template 96 | static R GetProperty(T const& obj, std::string const& name) 97 | { 98 | return obj.properties__.template invoke_get(name); 99 | } 100 | template 101 | static void SetProperty(T& obj, std::string const& name, V val) 102 | { 103 | obj.properties__.invoke_set(name, val); 104 | } 105 | }; 106 | 107 | template 108 | struct PropertyAccessorBase 109 | { 110 | template 111 | static R GetProperty(T const& obj, std::string const& name) 112 | { 113 | return obj.template get_property(name); 114 | } 115 | template 116 | static void SetProperty(T& obj, std::string const& name, V val) 117 | { 118 | obj.set_property(name, val); 119 | } 120 | }; 121 | 122 | template 123 | struct HasSpecialAccessor 124 | { 125 | struct RightType 126 | { 127 | int dummy; 128 | }; 129 | 130 | struct WrongType 131 | { 132 | int dummy[2]; 133 | }; 134 | 135 | template struct CheckFn 136 | { 137 | typedef RightType result; 138 | }; 139 | 140 | #ifdef _MSC_VER 141 | template static typename CheckFn >::result HasFn(U*); 142 | #else 143 | template static typename CheckFn::result HasFn(U*); 144 | #endif 145 | static WrongType HasFn(...); 146 | 147 | BOOST_STATIC_CONSTANT(int, value = sizeof(HasFn((T*)NULL)) == sizeof(RightType) ? 1 : 0); 148 | }; 149 | 150 | template 151 | struct PropertyAccessor : PropertyAccessorBase::value> 152 | { 153 | ; 154 | }; 155 | } 156 | 157 | template 158 | R get_property(T const& obj, std::string const& propName) 159 | { 160 | return detail::PropertyAccessor::template GetProperty(obj, propName); 161 | } 162 | 163 | template 164 | void set_property(T& obj, std::string const& propName, V val) 165 | { 166 | detail::PropertyAccessor::SetProperty(obj, propName, val); 167 | } 168 | } 169 | } 170 | 171 | #endif // properties_Boost_headers_dynamic_access_hpp__ 172 | -------------------------------------------------------------------------------- /include/flex_lib/properties/dynamic_lex_access.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 15.01.2009 12:11 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20090115 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef properties_Boost_headers_dynamic_lex_access_hpp__ 12 | #define properties_Boost_headers_dynamic_lex_access_hpp__ 13 | 14 | #include 15 | #include "dynamic_access.hpp" 16 | #include 17 | #include 18 | 19 | namespace boost 20 | { 21 | namespace properties 22 | { 23 | namespace detail 24 | { 25 | template 26 | struct IsInputStreamable 27 | { 28 | BOOST_STATIC_CONSTANT(int, value = boost::is_arithmetic::value); 29 | }; 30 | 31 | template 32 | struct IsOutputStreamable 33 | { 34 | BOOST_STATIC_CONSTANT(int, value = boost::is_arithmetic::value); 35 | }; 36 | 37 | template 38 | struct PropertyLexGetter 39 | { 40 | template 41 | static typename boost::enable_if_c< 42 | boost::is_convertible::value && 43 | P::has_getter, R>::type 44 | Get(const char* name, P const& prop) 45 | { 46 | return prop.safe_get(); 47 | } 48 | template 49 | static typename boost::enable_if_c< 50 | !boost::is_convertible::value && 51 | IsOutputStreamable::value && 52 | P::has_getter, R>::type 53 | Get(const char* name, P const& prop) 54 | { 55 | return boost::lexical_cast(prop.safe_get()); 56 | } 57 | template 58 | static typename boost::enable_if_c< 59 | (!boost::is_convertible::value && 60 | !IsOutputStreamable::value) || 61 | !P::has_getter, R>::type 62 | Get(const char* name, P const& prop) 63 | { 64 | throw PropertyInaccessable(name); 65 | } 66 | }; 67 | 68 | template<> 69 | struct PropertyGetter : PropertyLexGetter 70 | { 71 | ; 72 | }; 73 | template<> 74 | struct PropertyGetter : PropertyLexGetter 75 | { 76 | ; 77 | }; 78 | 79 | template 80 | struct PropertyLexSetter 81 | { 82 | template 83 | static typename boost::enable_if_c< 84 | boost::is_convertible::value && 85 | P::has_setter, void>::type 86 | Set(const char* name, P& prop, V val) 87 | { 88 | prop.safe_set(val); 89 | } 90 | template 91 | static typename boost::enable_if_c< 92 | !boost::is_convertible::value && 93 | IsInputStreamable::value && 94 | P::has_setter, void>::type 95 | Set(const char* name, P& prop, V val) 96 | { 97 | prop.safe_set(boost::lexical_cast(val)); 98 | } 99 | template 100 | static typename boost::enable_if_c< 101 | (!boost::is_convertible::value && 102 | !IsInputStreamable::value) || 103 | !P::has_setter, void>::type 104 | Set(const char* name, P& prop, V val) 105 | { 106 | throw PropertyInaccessable(name); 107 | } 108 | }; 109 | 110 | template<> 111 | struct PropertySetter : PropertyLexSetter 112 | { 113 | ; 114 | }; 115 | template<> 116 | struct PropertySetter : PropertyLexSetter 117 | { 118 | ; 119 | }; 120 | template<> 121 | struct PropertySetter : PropertyLexSetter 122 | { 123 | ; 124 | }; 125 | template<> 126 | struct PropertySetter : PropertyLexSetter 127 | { 128 | ; 129 | }; 130 | template<> 131 | struct PropertySetter : PropertyLexSetter 132 | { 133 | ; 134 | }; 135 | template<> 136 | struct PropertySetter : PropertyLexSetter 137 | { 138 | ; 139 | }; 140 | template<> 141 | struct PropertySetter : PropertyLexSetter 142 | { 143 | ; 144 | }; 145 | template<> 146 | struct PropertySetter : PropertyLexSetter 147 | { 148 | ; 149 | }; 150 | template<> 151 | struct PropertySetter : PropertyLexSetter 152 | { 153 | ; 154 | }; 155 | template<> 156 | struct PropertySetter : PropertyLexSetter 157 | { 158 | ; 159 | }; 160 | } 161 | } 162 | } 163 | 164 | #endif // properties_Boost_headers_dynamic_lex_access_hpp__ 165 | -------------------------------------------------------------------------------- /include/flex_lib/properties/fwd_rw_property.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:32 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_fwd_rw_property_hpp__ 12 | #define Sandbox_Source_Files_property_fwd_rw_property_hpp__ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include "properties_fwd.hpp" 19 | 20 | # define MAKE_PROPERTY_TYPE_FWDRW(ClassName, PI) MAKE_PROP_TYPE_GENERIC(ClassName, PI, DefaultPropertyBase, BOOST_PP_SEQ_ELEM(6, PI)) 21 | 22 | # define DEFINE_PROPERTY_FWDRW(ClassName, PI) DEFINE_PROPERTY_GENERIC_X(ClassName, PI, DefaultPropertyBase, BOOST_PP_SEQ_ELEM(6, PI)); 23 | 24 | # define DEFINE_PROPERTY_IMPL_AS_MEMBER_FWDRW(ClassName, PI) 25 | 26 | # define FWDRW_PROPERTY_CTR_INIT_RW(ClassName, PI) BOOST_PP_SEQ_ELEM(7, PI), BOOST_PP_SEQ_ELEM(8, PI) 27 | # define FWDRW_PROPERTY_CTR_INIT_RO(ClassName, PI) BOOST_PP_SEQ_ELEM(7, PI) 28 | 29 | # define DEFINE_PROPERTY_IMPL_AS_STATIC_FWDRW(ClassName, PI) \ 30 | static boost::properties::detail::BOOST_PP_SEQ_ELEM(3, PI) BOOST_PP_SEQ_ELEM(4, PI)(BOOST_PP_CAT(FWDRW_PROPERTY_CTR_INIT_, BOOST_PP_SEQ_ELEM(5, PI))(ClassName, PI)); 31 | 32 | # define INITIALIZE_PROPERTY_IMPL_FWDRW(ClassName, PI) \ 33 | host->BOOST_PP_SEQ_ELEM(4, PI).Init(host, &BOOST_PP_SEQ_ELEM(4, PI) ); 34 | 35 | # define COPY_PROPERTY_IMPL_FWDRW(_1, _2) 36 | 37 | 38 | # define COPY_PROPERTY_IMPL_FWDRW(_1, _2) 39 | 40 | # define SERIALIZE_PROPERTY_IMPL_FWDRW(ClassName, PI) 41 | 42 | # define INVOKE_GET_PROPERTY_IMPL_FWDRW(ClassName, PI) INVOKE_GET_PROPERTY_IMPL_GENERIC(ClassName, PI) 43 | 44 | # define INVOKE_SET_PROPERTY_IMPL_FWDRW(ClassName, PI) INVOKE_SET_PROPERTY_IMPL_GENERIC(ClassName, PI) 45 | 46 | # define ENUM_PROPERTY_IMPL_FWDRW(ClassName, PI) ENUM_PROPERTY_IMPL_GENERIC(ClassName, PI) 47 | 48 | #define FWD_RW_PROPERTY(Type, Name, Get, Set) ( (FWDRW)((Type))(Property)(FwdRWPropertyImpl)(Name)(RW)(ReadWritePropertyAccessors)(Get)(Set) ) 49 | #define MEM_FWD_RW_PROPERTY(Type, Name, MemName, Get, Set) ( (FWDRW)((Type))(Property)(FwdRWPropertyImpl)(Name)(RW)(ReadWritePropertyAccessors)\ 50 | ( (boost::bind(&Get, boost::bind(&T::MemName, _1))) )\ 51 | ( (boost::bind(&Set, boost::bind(boost::mem_ptr(&T::MemName), _1), _2)) ) ) 52 | #define FWD_RO_PROPERTY(Type, Name, Get) ( (FWDRW)((Type))(Property)(FwdROPropertyImpl)(Name)(RO)(ReadPropertyAccessors)(Get) ) 53 | #define MEM_FWD_RO_PROPERTY(Type, Name, MemName, Get) ( (FWDRW)((Type))(Property)(FwdROPropertyImpl)(Name)(RO)(ReadPropertyAccessors)\ 54 | ( (boost::bind(&Get, boost::bind(&T::MemName, _1))) ) ) 55 | #define FWD_WO_PROPERTY(Type, Name, Set) ( (FWDRW)((Type))(Property)(FwdWOPropertyImpl)(Name)(RO)(WritePropertyAccessors)(Set) ) 56 | #define MEM_FWD_WO_PROPERTY(Type, Name, MemName, Set) ( (FWDRW)((Type))(Property)(FwdWOPropertyImpl)(Name)(RO)(WritePropertyAccessors)\ 57 | ( (boost::bind(&Set, boost::bind(boost::mem_ptr(&T::MemName), _1), _2)) ) ) 58 | 59 | namespace boost 60 | { 61 | namespace properties 62 | { 63 | namespace detail 64 | { 65 | template 66 | class FwdRWPropertyImpl 67 | { 68 | public: 69 | typedef PropertyTraits traits; 70 | typedef typename traits::arg_type arg_type; 71 | typedef boost::function GetterType; 72 | typedef boost::function SetterType; 73 | 74 | FwdRWPropertyImpl(GetterType getter, SetterType setter) : m_Getter(getter), m_Setter(setter) {;} 75 | typename traits::result_type get(H const* host) const 76 | { 77 | return m_Getter(host); 78 | } 79 | void set(H* host, typename traits::arg_type val) 80 | { 81 | m_Setter(host, val); 82 | } 83 | private: 84 | GetterType m_Getter; 85 | SetterType m_Setter; 86 | }; 87 | 88 | template 89 | class FwdROPropertyImpl 90 | { 91 | public: 92 | typedef PropertyTraits traits; 93 | typedef typename traits::arg_type arg_type; 94 | typedef boost::function GetterType; 95 | 96 | FwdROPropertyImpl(GetterType getter) : m_Getter(getter) {;} 97 | typename traits::result_type get(H const* host) const 98 | { 99 | return m_Getter(host); 100 | } 101 | private: 102 | GetterType m_Getter; 103 | }; 104 | 105 | template 106 | class FwdWOPropertyImpl 107 | { 108 | public: 109 | typedef PropertyTraits traits; 110 | typedef typename traits::arg_type arg_type; 111 | typedef boost::function SetterType; 112 | 113 | FwdWOPropertyImpl(SetterType setter) : m_Setter(setter) {;} 114 | void set(H* host, typename traits::arg_type val) 115 | { 116 | m_Setter(host, val); 117 | } 118 | private: 119 | SetterType m_Setter; 120 | }; 121 | } 122 | } 123 | 124 | template 125 | class mem_ptr_impl : public std::unary_function 126 | { 127 | public: 128 | mem_ptr_impl(R T::*ptr) : m_Ptr(ptr) {;} 129 | R* operator()(T* obj) 130 | { 131 | return &(obj->*m_Ptr); 132 | } 133 | private: 134 | R T::*m_Ptr; 135 | }; 136 | 137 | template 138 | struct mem_ptr_chooser 139 | { 140 | typedef void type; 141 | }; 142 | 143 | template 144 | struct mem_ptr_chooser 145 | { 146 | typedef _mfi::dm type; 147 | }; 148 | 149 | template 150 | struct mem_ptr_chooser 151 | { 152 | typedef mem_ptr_impl type; 153 | }; 154 | 155 | template 156 | typename mem_ptr_chooser::value >::type mem_ptr(R T::*ptr) 157 | { 158 | return typename mem_ptr_chooser::value >::type(ptr); 159 | } 160 | } 161 | 162 | #endif // Sandbox_Source_Files_property_fwd_rw_property_hpp__ 163 | -------------------------------------------------------------------------------- /include/flex_lib/properties/index_property_fwd.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:32 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_index_property_fwd_hpp__ 12 | #define Sandbox_Source_Files_property_index_property_fwd_hpp__ 13 | 14 | // #include 15 | #include 16 | #include "properties_fwd.hpp" 17 | 18 | namespace boost 19 | { 20 | namespace properties 21 | { 22 | namespace detail 23 | { 24 | // template struct IndexesChain; 25 | // template struct ArgMaker; 26 | template struct ArgMaker; 27 | template class Indexer; 28 | template class IndexPropertyBase; 29 | template class IndexPropertyImpl; 30 | template class AbstractIndexPropertyImpl; 31 | template class AbstractIndexPropImpl; 32 | 33 | template 34 | struct t_arg 35 | { 36 | typedef typename std::tuple_element::type type; 37 | }; 38 | 39 | template class ACC> 40 | struct IndexPropertyInfo 41 | { 42 | typedef IndexPropertyInfo this_type; 43 | typedef IndexPropertyBase PropertyTypeBase; 44 | typedef IndexPropertyImpl PropertyImpl; 45 | typedef Property PropertyType; 46 | BOOST_STATIC_CONSTANT(int, IndexesCount = std::tuple_size::value); 47 | typedef PropertyTraits TypeTraits; 48 | typedef IDX Indexes; 49 | typedef typename ArgMaker::arg_type Args; 50 | typedef typename ArgMaker::rest_args_type RestArgs; 51 | typedef H Host; 52 | typedef T Type; 53 | }; 54 | 55 | template class ACC> 56 | struct AbstractIndexPropertyInfo 57 | { 58 | typedef AbstractIndexPropertyInfo this_type; 59 | typedef IndexPropertyBase PropertyTypeBase; 60 | typedef AbstractIndexPropertyImpl PropertyImpl; 61 | typedef Property PropertyType; 62 | BOOST_STATIC_CONSTANT(int, IndexesCount = std::tuple_size::value); 63 | typedef PropertyTraits TypeTraits; 64 | typedef IDX Indexes; 65 | typedef typename ArgMaker::arg_type Args; 66 | typedef typename ArgMaker::rest_args_type RestArgs; 67 | typedef H Host; 68 | typedef T Type; 69 | }; 70 | 71 | template<> struct ArgMaker> {}; 72 | 73 | template 74 | struct ArgMaker> 75 | { 76 | typedef std::tuple::arg_type> arg_type; 77 | typedef std::tuple<> rest_args_type; 78 | 79 | template 80 | static arg_type append_arg(U1, U2 val) 81 | { 82 | return arg_type(val); 83 | } 84 | }; 85 | 86 | template 87 | struct ArgMaker> 88 | { 89 | typedef std::tuple< 90 | typename PropertyTraits::arg_type, 91 | typename PropertyTraits::arg_type 92 | > arg_type; 93 | 94 | typedef std::tuple< 95 | typename PropertyTraits::arg_type 96 | > rest_args_type; 97 | 98 | template 99 | static arg_type append_arg(U1 a, U2 val) 100 | { 101 | return arg_type(get<0>(a), val); 102 | } 103 | }; 104 | 105 | template 106 | struct ArgMaker> 107 | { 108 | typedef std::tuple< 109 | typename PropertyTraits::arg_type, 110 | typename PropertyTraits::arg_type, 111 | typename PropertyTraits::arg_type 112 | > arg_type; 113 | 114 | typedef std::tuple< 115 | typename PropertyTraits::arg_type, 116 | typename PropertyTraits::arg_type 117 | > rest_args_type; 118 | 119 | template 120 | static arg_type append_arg(U1 a, U2 val) 121 | { 122 | return arg_type(get<0>(a), get<1>(a), val); 123 | } 124 | }; 125 | 126 | template 127 | struct ArgMaker> 128 | { 129 | typedef std::tuple< 130 | typename PropertyTraits::arg_type, 131 | typename PropertyTraits::arg_type, 132 | typename PropertyTraits::arg_type, 133 | typename PropertyTraits::arg_type 134 | > arg_type; 135 | 136 | typedef std::tuple< 137 | typename PropertyTraits::arg_type, 138 | typename PropertyTraits::arg_type, 139 | typename PropertyTraits::arg_type 140 | > rest_args_type; 141 | 142 | template 143 | static arg_type append_arg(U1 a, U2 val) 144 | { 145 | return arg_type(get<0>(a), get<1>(a), get<2>(a), val); 146 | } 147 | }; 148 | 149 | template struct TupleAppender 150 | { 151 | static void append(TUP const&, T const&) {;} 152 | }; 153 | 154 | template struct TupleAppender, T> 155 | { 156 | typedef std::tuple type; 157 | static std::tuple append(std::tuple<> const&, T const& v) 158 | { 159 | return std::make_tuple(v); 160 | } 161 | }; 162 | 163 | template struct TupleAppender, T> 164 | { 165 | typedef std::tuple type; 166 | static std::tuple append(std::tuple const& t, T const& v) 167 | { 168 | return std::make_tuple(std::get<0>(t), v); 169 | } 170 | }; 171 | 172 | template struct TupleAppender, T> 173 | { 174 | typedef std::tuple type; 175 | static std::tuple append(std::tuple const& t, T const& v) 176 | { 177 | return std::make_tuple(std::get<0>(t), std::get<1>(t), v); 178 | } 179 | }; 180 | 181 | template struct TupleAppender, T> 182 | { 183 | typedef std::tuple type; 184 | static std::tuple append(std::tuple const& t, T const& v) 185 | { 186 | return std::make_tuple(std::get<0>(t), std::get<1>(t), std::get<2>(t), v); 187 | } 188 | }; 189 | template 190 | auto append2tuple(TUP const& t, T const& v) -> decltype(TupleAppender::append(t, v)) 191 | { 192 | return TupleAppender::append(t, v); 193 | } 194 | 195 | 196 | } 197 | } 198 | } 199 | 200 | #endif // Sandbox_Source_Files_property_index_property_fwd_hpp__ 201 | -------------------------------------------------------------------------------- /include/flex_lib/properties/index_property_impl.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:32 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_index_property_impl_hpp__ 12 | #define Sandbox_Source_Files_property_index_property_impl_hpp__ 13 | 14 | #include "properties_fwd.hpp" 15 | #include "index_property_fwd.hpp" 16 | 17 | namespace boost 18 | { 19 | namespace properties 20 | { 21 | namespace detail 22 | { 23 | template class IndexPropertyImplBase {}; 24 | 25 | template 26 | class IndexPropertyImplBase 27 | { 28 | public: 29 | typedef typename ArgMaker::arg_type args; 30 | typedef typename ArgMaker::rest_args_type rest_args; 31 | typedef typename I::TypeTraits traits; 32 | typedef typename I::Host H; 33 | typedef typename traits::result_type (H::*GetterType)(typename t_arg::type) const; 34 | typedef void (H::*SetterType)(typename t_arg::type i0, typename traits::arg_type val); 35 | 36 | IndexPropertyImplBase(GetterType getter, SetterType setter) : m_Getter(getter), m_Setter(setter) {;} 37 | typename traits::result_type get(H const* host, const args& idx) const 38 | { 39 | return (host->*m_Getter)(std::get<0>(idx)); 40 | } 41 | void set(H* host, const args& idx, typename traits::arg_type val) 42 | { 43 | (host->*m_Setter)(std::get<0>(idx), val); 44 | } 45 | private: 46 | GetterType m_Getter; 47 | SetterType m_Setter; 48 | }; 49 | 50 | template 51 | class IndexPropertyImplBase 52 | { 53 | public: 54 | typedef typename ArgMaker::arg_type args; 55 | typedef typename ArgMaker::rest_args_type rest_args; 56 | typedef typename I::TypeTraits traits; 57 | typedef typename I::Host H; 58 | typedef typename traits::result_type (H::*GetterType)(typename t_arg::type, typename t_arg::type) const; 59 | typedef void (H::*SetterType)(typename t_arg::type, typename t_arg::type, typename traits::arg_type val); 60 | 61 | IndexPropertyImplBase(GetterType getter, SetterType setter) : m_Getter(getter), m_Setter(setter) {;} 62 | typename traits::result_type get(H const* host, const args& idx) const 63 | { 64 | return (host->*m_Getter)(std::get<0>(idx), std::get<1>(idx)); 65 | } 66 | void set(H* host, const args& idx, typename traits::arg_type val) 67 | { 68 | (host->*m_Setter)(std::get<0>(idx), std::get<1>(idx), val); 69 | } 70 | private: 71 | GetterType m_Getter; 72 | SetterType m_Setter; 73 | }; 74 | 75 | template 76 | class IndexPropertyImplBase 77 | { 78 | public: 79 | typedef typename ArgMaker::arg_type args; 80 | typedef typename ArgMaker::rest_args_type rest_args; 81 | typedef typename I::TypeTraits traits; 82 | typedef typename I::Host H; 83 | typedef typename traits::result_type (H::*GetterType)(typename t_arg::type, typename t_arg::type, typename t_arg::type) const; 84 | typedef void (H::*SetterType)(typename t_arg::type, typename t_arg::type, typename t_arg::type, typename traits::arg_type val); 85 | 86 | IndexPropertyImplBase(GetterType getter, SetterType setter) : m_Getter(getter), m_Setter(setter) {;} 87 | typename traits::result_type get(H const* host, const args& idx) const 88 | { 89 | return (host->*m_Getter)(std::get<0>(idx), std::get<1>(idx), std::get<2>(idx)); 90 | } 91 | void set(H* host, const args& idx, typename traits::arg_type val) 92 | { 93 | (host->*m_Setter)(std::get<0>(idx), std::get<1>(idx), std::get<2>(idx), val); 94 | } 95 | private: 96 | GetterType m_Getter; 97 | SetterType m_Setter; 98 | }; 99 | 100 | template 101 | class IndexPropertyImpl : public IndexPropertyImplBase 102 | { 103 | public: 104 | typedef IndexPropertyImplBase base_type; 105 | 106 | IndexPropertyImpl(typename base_type::GetterType g, typename base_type::SetterType s) : base_type(g, s) {;} 107 | }; 108 | 109 | template 110 | class AbstractIndexPropertyImpl 111 | { 112 | public: 113 | typedef typename I::TypeTraits traits; 114 | typedef I PropertyInfo; 115 | 116 | virtual typename traits::result_type get(const typename I::Host*, const typename I::Indexes& args) const = 0; 117 | virtual void set(const typename I::Host*, const typename I::Indexes& args, typename traits::arg_type value) = 0; 118 | }; 119 | 120 | template 121 | class AbstractIndexPropImpl : public B//public AbstractIndexPropertyImpl 122 | { 123 | public: 124 | typedef typename B::traits traits; 125 | typedef typename B::PropertyInfo I; 126 | typename traits::result_type get(const typename I::Host* h, const typename I::Indexes& args) const 127 | { 128 | return m_Prop->get(args); 129 | } 130 | void set(const typename I::Host* h, const typename I::Indexes& args, typename traits::arg_type value) 131 | { 132 | m_Prop->set(args, value); 133 | } 134 | void Init(P* prop) 135 | { 136 | m_Prop = prop; 137 | } 138 | private: 139 | P* m_Prop; 140 | }; 141 | 142 | } 143 | } 144 | } 145 | 146 | #endif // Sandbox_Source_Files_property_index_property_impl_hpp__ 147 | -------------------------------------------------------------------------------- /include/flex_lib/properties/properties_fwd.hpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flexferrum/flex_lib/322adb7acdfbc0e541292708a2bd66b305b05c52/include/flex_lib/properties/properties_fwd.hpp -------------------------------------------------------------------------------- /include/flex_lib/properties/property_accessors.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 09.05.2008 1:31 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080509 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_write_property_accessors_hpp__ 12 | #define Sandbox_Source_Files_property_write_property_accessors_hpp__ 13 | 14 | #include "property_traits.hpp" 15 | #include 16 | 17 | namespace boost 18 | { 19 | namespace properties 20 | { 21 | namespace detail 22 | { 23 | template 24 | struct EmptyBase {}; 25 | 26 | 27 | /* 28 | template 29 | class ArithmeticOperators 30 | { 31 | private: 32 | P& derived() {return *static_cast(this);} 33 | P const& derived() const {return *static_cast

(this);} 34 | public: 35 | typedef T value_type; 36 | typedef PropertyTraits traits; 37 | 38 | #define PROPERTY_BINARY_OPERATOR_COMMUTATIVE(OP ) \ 39 | template \ 40 | friend typename traits::clear_type \ 41 | operator OP( const P& lhs, T1 rhs ) \ 42 | { \ 43 | typename traits::clear_type result( lhs.get() ); \ 44 | result OP##= rhs; \ 45 | return result; \ 46 | } \ 47 | template \ 48 | friend typename traits::clear_type \ 49 | operator OP( T1 lhs, const P& rhs ) \ 50 | { \ 51 | typename traits::clear_type result( lhs ); \ 52 | result OP##= rhs.get(); \ 53 | return result; \ 54 | } \ 55 | template \ 56 | friend typename traits::clear_type \ 57 | operator OP( const P1& lhs, const P1& rhs ) \ 58 | { \ 59 | typename traits::clear_type result( lhs.get() ); \ 60 | result OP##= lhs.get(); \ 61 | return result; \ 62 | } 63 | 64 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(+) 65 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(-) 66 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(*) 67 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(/) 68 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(%) 69 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(>>) 70 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(<<) 71 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(&) 72 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(|) 73 | PROPERTY_BINARY_OPERATOR_COMMUTATIVE(^) 74 | #undef PROPERTY_BINARY_OPERATOR_COMMUTATIVE 75 | 76 | }; 77 | */ 78 | 79 | // template 80 | // class ArithmeticOperators {;}; 81 | 82 | template > 83 | class ReadPropertyAccessors : public B 84 | { 85 | private: 86 | P& derived() {return *static_cast(this);} 87 | P const& derived() const {return *static_cast

(this);} 88 | public: 89 | typedef T value_type; 90 | typedef PropertyTraits traits; 91 | BOOST_STATIC_CONSTANT(bool, has_getter = 1); 92 | BOOST_STATIC_CONSTANT(bool, has_setter = 0); 93 | 94 | typename traits::result_type safe_get() const {return derived().get();} 95 | void safe_set(typename traits::arg_type v) {;} 96 | 97 | template 98 | operator T1() const 99 | { 100 | return derived().get(); 101 | } 102 | 103 | operator typename traits::result_type() const 104 | { 105 | return derived().get(); 106 | } 107 | 108 | #if 0 109 | # define PROPERTY_LOGICALOPER_SET(OPER) \ 110 | template \ 111 | bool operator OPER (T1 other) const \ 112 | { \ 113 | return derived().get() OPER T(other); \ 114 | } \ 115 | \ 116 | bool operator OPER (typename traits::arg_type other) const \ 117 | { \ 118 | return derived().get() OPER T(other); \ 119 | } \ 120 | \ 121 | bool operator OPER (const P& other) const \ 122 | { \ 123 | return derived().get() OPER other.get(); \ 124 | } 125 | 126 | PROPERTY_LOGICALOPER_SET(==) 127 | PROPERTY_LOGICALOPER_SET(<) 128 | PROPERTY_LOGICALOPER_SET(>) 129 | # undef PROPERTY_LOGICALOPER_SET 130 | #endif 131 | 132 | bool operator !() const 133 | { 134 | return !derived().get(); 135 | } 136 | 137 | friend std::ostream& operator << (std::ostream& os, P const& prop) 138 | { 139 | os << prop.get(); 140 | return os; 141 | } 142 | }; 143 | 144 | template 145 | class SafeGetter 146 | { 147 | public: 148 | typedef PropertyTraits traits; 149 | typename traits::result_type safe_get() const {return typename traits::result_type();} 150 | }; 151 | 152 | template 153 | class SafeGetter 154 | { 155 | public: 156 | typedef PropertyTraits traits; 157 | typename traits::result_type safe_get() const {return *(typename traits::clear_type*)NULL;} 158 | }; 159 | 160 | template > 161 | class WritePropertyAccessors : public B, public SafeGetter::is_reference && !PropertyTraits::is_scalar> 162 | { 163 | private: 164 | P& derived() {return *static_cast(this);} 165 | P const& derived() const {return *static_cast

(this);} 166 | public: 167 | typedef T value_type; 168 | typedef PropertyTraits traits; 169 | BOOST_STATIC_CONSTANT(bool, has_getter = 0); 170 | BOOST_STATIC_CONSTANT(bool, has_setter = 1); 171 | void safe_set(typename traits::arg_type v) {derived().set(v);} 172 | 173 | P& operator ++() 174 | { 175 | typename traits::clear_type new_val(derived().get()); 176 | 177 | ++ new_val; 178 | derived().set(new_val); 179 | 180 | return derived(); 181 | } 182 | 183 | P& operator --() 184 | { 185 | typename traits::clear_type new_val(derived().get()); 186 | 187 | -- new_val; 188 | derived().set(new_val); 189 | 190 | return derived(); 191 | } 192 | 193 | P& operator =(typename traits::arg_type value) 194 | { 195 | derived().set(value); 196 | return derived(); 197 | } 198 | 199 | friend std::istream& operator >> (std::istream& is, P& prop) 200 | { 201 | T val; 202 | is >> val; 203 | prop.set(val); 204 | return is; 205 | } 206 | }; 207 | 208 | template > 209 | class ReadWritePropertyAccessors : public WritePropertyAccessors > 210 | { 211 | private: 212 | P& derived() {return *static_cast(this);} 213 | P const& derived() const {return *static_cast

(this);} 214 | public: 215 | typedef T value_type; 216 | typedef PropertyTraits traits; 217 | BOOST_STATIC_CONSTANT(bool, has_getter = 1); 218 | BOOST_STATIC_CONSTANT(bool, has_setter = 1); 219 | typename traits::result_type safe_get() const {return derived().get();} 220 | void safe_set(typename traits::arg_type v) {derived().set(v);} 221 | 222 | #if 1 223 | # define PROPERTY_ASSIGNOPER_SET(OPER) \ 224 | \ 225 | template \ 226 | P& operator OPER (T1 other) \ 227 | { \ 228 | typename traits::clear_type new_val(derived().get()); \ 229 | \ 230 | new_val OPER T(other); \ 231 | derived().set(new_val); \ 232 | return derived(); \ 233 | } \ 234 | \ 235 | P& operator OPER (typename traits::arg_type other) \ 236 | { \ 237 | typename traits::clear_type new_val(derived().get()); \ 238 | \ 239 | new_val OPER other; \ 240 | derived().set(new_val); \ 241 | return derived(); \ 242 | } 243 | 244 | PROPERTY_ASSIGNOPER_SET(+=); 245 | PROPERTY_ASSIGNOPER_SET(-=); 246 | PROPERTY_ASSIGNOPER_SET(*=); 247 | PROPERTY_ASSIGNOPER_SET(/=); 248 | PROPERTY_ASSIGNOPER_SET(%=); 249 | PROPERTY_ASSIGNOPER_SET(&=); 250 | PROPERTY_ASSIGNOPER_SET(|=); 251 | PROPERTY_ASSIGNOPER_SET(^=); 252 | PROPERTY_ASSIGNOPER_SET(>>=); 253 | PROPERTY_ASSIGNOPER_SET(<<=); 254 | 255 | # undef PROPERTY_ASSIGNOPER_SET 256 | #endif 257 | 258 | }; 259 | } 260 | } 261 | } 262 | 263 | #endif // Sandbox_Source_Files_property_write_property_accessors_hpp__ 264 | -------------------------------------------------------------------------------- /include/flex_lib/properties/property_pp.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:32 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_property_pp_hpp__ 12 | #define Sandbox_Source_Files_property_property_pp_hpp__ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | // #include 23 | #include "dynamic_access.hpp" 24 | 25 | #/* 26 | # * Returns kind of property 27 | # */ 28 | # define PROP_KIND(PI) BOOST_PP_SEQ_HEAD(PI) 29 | # 30 | #/* 31 | # * Returns type of property 32 | # */ 33 | # define PROP_TYPE_(TI) BOOST_PP_EXPAND(BOOST_PP_SEQ_ENUM(TI)) 34 | # define PROP_TYPE(PI) BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_ELEM(1, PI)) 35 | # define PROP_NAME(PI) BOOST_PP_SEQ_ELEM(4, PI) 36 | # 37 | # 38 | # /* Host class properties definition */ 39 | # 40 | # 41 | # define MAKE_PROP_TYPE_GENERIC(ClassName, PI, ImplType, AccessorType) \ 42 | boost::properties::BOOST_PP_SEQ_ELEM(2, PI), boost::properties::detail::AccessorType > 43 | 44 | # define DEFINE_PROPERTY_GENERIC(ClassName, PI) MAKE_PROP_TYPE_GENERIC(ClassName, PI, DefaultPropertyBase, ReadWritePropertyAccessors) PROP_NAME(PI); 45 | # define DEFINE_PROPERTY_GENERIC_X(ClassName, PI, ImplType, AccessorType) MAKE_PROP_TYPE_GENERIC(ClassName, PI, ImplType, AccessorType) PROP_NAME(PI); 46 | # 47 | #/* 48 | # * Class member property declaration macro. Declare property in the property-owner class 49 | # * scope. 50 | # * ClassName: Property-owner class name 51 | # * PI: Property info set 52 | # */ 53 | 54 | # define DEFINE_PROPERTY(_, ClassName, PI) \ 55 | BOOST_PP_CAT(DEFINE_PROPERTY_, PROP_KIND(PI))(ClassName, PI) 56 | # 57 | # 58 | # 59 | # /* Property-holder class properties definition as datamembers*/ 60 | # 61 | # 62 | # 63 | #/* 64 | # * Dispatches trivial properties initialization 65 | # * ClassName: Property-owner class name 66 | # * PI: Property info set 67 | # */ 68 | # define DEFINE_PROPERTY_IMPL_AS_MEMBER(_, ClassName, PI) \ 69 | BOOST_PP_CAT(DEFINE_PROPERTY_IMPL_AS_MEMBER_, PROP_KIND(PI))(ClassName, PI) 70 | # 71 | #/* 72 | # * Generates trivial properties initialization list 73 | # * ClassName: Property-owner class name 74 | # * S: Properties info set 75 | # */ 76 | # define PROPERTIES__DEFINE_PROPS_IMPL_AS_MEMBER(ClassName, S) \ 77 | BOOST_PP_SEQ_FOR_EACH(DEFINE_PROPERTY_IMPL_AS_MEMBER, ClassName, S) 78 | # 79 | # 80 | # 81 | # /* Property-holder class properties definition as static members*/ 82 | # 83 | # 84 | # 85 | #/* 86 | # * Dispatchs non-trivial property implementation generation 87 | # * ClassName: Property-owner class name 88 | # * PI: Property info set 89 | # */ 90 | # define DEFINE_PROPERTY_IMPL_AS_STATIC(_, ClassName, PI) \ 91 | BOOST_PP_CAT(DEFINE_PROPERTY_IMPL_AS_STATIC_, PROP_KIND(PI))(ClassName, PI) 92 | # 93 | #/* 94 | # * Generates non-trivial properties implementation list 95 | # * ClassName: Property-owner class name 96 | # * S: Properties info set 97 | # */ 98 | # define PROPERTIES__DEFINE_PROPS_AS_STATIC(ClassName, S) \ 99 | BOOST_PP_SEQ_FOR_EACH(DEFINE_PROPERTY_IMPL_AS_STATIC, ClassName, S) 100 | # 101 | # 102 | # 103 | # /* Property-holder class properties initialization*/ 104 | # 105 | # 106 | # 107 | #/* 108 | # * Dispatches property initialization code generation 109 | # * ClassName: Property-owner class name 110 | # * PI: Property info set 111 | # */ 112 | # define INITIALIZE_PROPERTY(_, ClassName, PI)\ 113 | BOOST_PP_CAT(INITIALIZE_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 114 | # 115 | #/* 116 | # * Generates properties initialization code 117 | # * ClassName: Property-owner class name 118 | # * S: Properties info set 119 | # */ 120 | # define PROPERTIES__DO_INITIALIZE(ClassName, S) \ 121 | BOOST_PP_SEQ_FOR_EACH(INITIALIZE_PROPERTY, ClassName, S) 122 | # 123 | # 124 | # 125 | # /* Property-holder class property copying */ 126 | # 127 | # 128 | # 129 | # define COPY_PROPERTY(_, ClassName, PI)\ 130 | BOOST_PP_CAT(COPY_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 131 | # define PROPERTIES__DO_COPY(ClassName, S) \ 132 | BOOST_PP_SEQ_FOR_EACH(COPY_PROPERTY, ClassName, S) 133 | # 134 | # 135 | # 136 | # /* Property-holder class property serialization */ 137 | # 138 | # 139 | # 140 | # define SERIALIZE_PROPERTY(_, ClassName, PI)\ 141 | BOOST_PP_CAT(SERIALIZE_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 142 | # define PROPERTIES__DO_SERIALIZE(ClassName, S) \ 143 | BOOST_PP_SEQ_FOR_EACH(SERIALIZE_PROPERTY, ClassName, S) 144 | # 145 | # 146 | # 147 | # /* Property-holder class property-get invoker */ 148 | # 149 | # 150 | # 151 | # define INVOKE_GET_PROPERTY_IMPL_GENERIC(ClassName, PI) \ 152 | else if (name == BOOST_PP_STRINGIZE(PROP_NAME(PI))) {return boost::properties::detail::PropertyGetter::Get(BOOST_PP_STRINGIZE(PROP_NAME(PI)), m_Host->PROP_NAME(PI));} 153 | # define INVOKE_GET_PROPERTY(_, ClassName, PI)\ 154 | BOOST_PP_CAT(INVOKE_GET_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 155 | # define PROPERTIES__DO_INVOKE_GET(ClassName, S) \ 156 | BOOST_PP_SEQ_FOR_EACH(INVOKE_GET_PROPERTY, ClassName, S) 157 | # define MAKE_BASE_INVOKE_GET_CALL(ClassName, BaseClassName) \ 158 | return boost::properties::get_property(*static_cast(m_Host), name); 159 | # define MAKE_PROPERTY_NOT_DEF_THROW(ClassName) \ 160 | throw boost::properties::PropertyNotDefined(name.c_str(), BOOST_PP_STRINGIZE(ClassName)); 161 | # 162 | # 163 | # 164 | # /* Property-holder class property-set invoker */ 165 | # 166 | # 167 | # 168 | # define INVOKE_SET_PROPERTY_IMPL_GENERIC(ClassName, PI) \ 169 | else if (name == BOOST_PP_STRINGIZE(PROP_NAME(PI))) {return boost::properties::detail::PropertySetter::Set(BOOST_PP_STRINGIZE(PROP_NAME(PI)), m_Host->PROP_NAME(PI), val);} 170 | # define INVOKE_SET_PROPERTY(_, ClassName, PI)\ 171 | BOOST_PP_CAT(INVOKE_SET_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 172 | # define PROPERTIES__DO_INVOKE_SET(ClassName, S) \ 173 | BOOST_PP_SEQ_FOR_EACH(INVOKE_SET_PROPERTY, ClassName, S) 174 | # define MAKE_BASE_INVOKE_SET_CALL(ClassName, BaseClassName) \ 175 | return boost::properties::set_property(*static_cast(m_Host), name, val); 176 | # 177 | # 178 | # 179 | # /* Property-holder class property presence checker */ 180 | # 181 | # 182 | # 183 | # define HAS_PROPERTY_PROPERTY_IMPL_GENERIC(ClassName, PI) \ 184 | else if (name == BOOST_PP_STRINGIZE(PROP_NAME(PI))) {return true;} 185 | # define HAS_PROPERTY_PROPERTY(_, ClassName, PI)\ 186 | BOOST_PP_CAT(HAS_PROPERTY_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 187 | # define PROPERTIES__DO_HAS_PROPERTY(ClassName, S) \ 188 | BOOST_PP_SEQ_FOR_EACH(HAS_PROPERTY_PROPERTY, ClassName, S) 189 | # define MAKE_BASE_HAS_PROPERTY_CALL(ClassName, BaseClassName) \ 190 | return static_cast(m_Host)->properties__.has_property(name); 191 | # 192 | # 193 | # 194 | # /* Property-holder class properties enumerator */ 195 | # 196 | # 197 | # 198 | # define ENUM_PROPERTY_IMPL_GENERIC(ClassName, PI) \ 199 | v(BOOST_PP_STRINGIZE(PROP_NAME(PI)), &T::PROP_NAME(PI)); 200 | # define ENUM_PROPERTY(_, ClassName, PI)\ 201 | BOOST_PP_CAT(ENUM_PROPERTY_IMPL_, PROP_KIND(PI))(ClassName, PI) 202 | # define PROPERTIES__DO_ENUM(ClassName, S) \ 203 | BOOST_PP_SEQ_FOR_EACH(ENUM_PROPERTY, ClassName, S) 204 | # /* 205 | # * Generates properties initialization and implementation code 206 | # * ClassName: Name of class contained properties 207 | # * S: Properties sequence 208 | # */ 209 | # define MAKE_PROPERTY_INITER(ClassName, HasBase, BaseClassName, S) \ 210 | template \ 211 | struct Properties__ \ 212 | { \ 213 | /* Simples properties definition */ \ 214 | PROPERTIES__DEFINE_PROPS_IMPL_AS_MEMBER(ClassName, S) \ 215 | \ 216 | Properties__(T* host) : m_Host(host) {init(host);} \ 217 | void init(T* host) \ 218 | { /* Non-trivial properties (such as \ 219 | * read-writer properties definition */ \ 220 | if (host == NULL) return; \ 221 | PROPERTIES__DEFINE_PROPS_AS_STATIC(ClassName, S) \ 222 | /* Properties initialization code */ \ 223 | PROPERTIES__DO_INITIALIZE(ClassName, S) \ 224 | } \ 225 | private: \ 226 | Properties__(const Properties__&) : m_Host(NULL) \ 227 | { \ 228 | BOOST_ASSERT(false); \ 229 | } \ 230 | public: \ 231 | Properties__& operator ==(const Properties__& other) \ 232 | { \ 233 | if (this == &other) return *this; \ 234 | \ 235 | copy_from(other); \ 236 | return *this; \ 237 | } \ 238 | /* Copies property values from another object */ \ 239 | void copy_from(const Properties__& other) \ 240 | { \ 241 | PROPERTIES__DO_COPY(ClassName, S); \ 242 | } \ 243 | /* Serialize property into/from archive */ \ 244 | template \ 245 | void serialize(Ar & ar, const unsigned int version = 0) \ 246 | { \ 247 | PROPERTIES__DO_SERIALIZE(ClassName, S); \ 248 | } \ 249 | /* Invokes property-get by name */ \ 250 | template \ 251 | R invoke_get(const std::string& name) const \ 252 | { \ 253 | if (false) {;} \ 254 | PROPERTIES__DO_INVOKE_GET(ClassName, S); \ 255 | BOOST_PP_IIF(HasBase, MAKE_BASE_INVOKE_GET_CALL(ClassName, BaseClassName), MAKE_PROPERTY_NOT_DEF_THROW(ClassName))\ 256 | } \ 257 | /* Invokes property-set by name */ \ 258 | template \ 259 | void invoke_set(const std::string& name, V val) \ 260 | { \ 261 | if (false) {;} \ 262 | PROPERTIES__DO_INVOKE_SET(ClassName, S); \ 263 | BOOST_PP_IIF(HasBase, MAKE_BASE_INVOKE_SET_CALL(ClassName, BaseClassName), MAKE_PROPERTY_NOT_DEF_THROW(ClassName))\ 264 | } \ 265 | /* Test property presence */ \ 266 | bool has_property(const std::string& name) \ 267 | { \ 268 | if (false) {;} \ 269 | PROPERTIES__DO_HAS_PROPERTY(ClassName, S); \ 270 | BOOST_PP_IIF(HasBase, MAKE_BASE_HAS_PROPERTY_CALL(ClassName, BaseClassName), return false;)\ 271 | } \ 272 | /* Enumerates properties */ \ 273 | template \ 274 | static void do_enum_s(const V& v) \ 275 | { \ 276 | PROPERTIES__DO_ENUM(ClassName, S); \ 277 | } \ 278 | template \ 279 | void do_enum(const V& v) \ 280 | { \ 281 | Properties__::do_enum_s(boost::bind(v, m_Host, _1, _2)); \ 282 | } \ 283 | template \ 284 | void do_enum(const V& v) const \ 285 | { \ 286 | Properties__::do_enum_s(boost::bind(v, m_Host, _1, _2));\ 287 | } \ 288 | T* m_Host; \ 289 | }; \ 290 | /* Declare properties holder class as friend for 291 | * properties owner class */ \ 292 | friend struct Properties__; \ 293 | /* Declare properties holder as data member. It helps 294 | * us to make single call (in constructor) 295 | * for all properties initialization */ \ 296 | Properties__ properties__; \ 297 | 298 | # /* 299 | # * Root macro for properties initialization code. 300 | # * ClassName: Name of class contained properties 301 | # * S: Properties sequence 302 | # */ 303 | #define PROPERTIES(ClassName, S) \ 304 | BOOST_PP_SEQ_FOR_EACH(DEFINE_PROPERTY, ClassName, S);\ 305 | MAKE_PROPERTY_INITER(ClassName, 0, BOOST_PP_EMPTY, S) 306 | 307 | #define PROPERTIES_INH(ClassName, BaseClassName, S) \ 308 | BOOST_PP_SEQ_FOR_EACH(DEFINE_PROPERTY, ClassName, S);\ 309 | MAKE_PROPERTY_INITER(ClassName, 1, BaseClassName, S) 310 | 311 | #ifdef _MSC_VER 312 | #pragma warning(disable:4355) 313 | #endif 314 | 315 | 316 | #endif // Sandbox_Source_Files_property_property_pp_hpp__ 317 | -------------------------------------------------------------------------------- /include/flex_lib/properties/property_traits.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 18:34 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_property_traits_hpp__ 12 | #define Sandbox_Source_Files_property_property_traits_hpp__ 13 | 14 | #include 15 | // #include 16 | // #include 17 | // #include 18 | // #include 19 | // #include 20 | // #include 21 | // #include 22 | // #include 23 | // #include 24 | 25 | namespace boost 26 | { 27 | namespace properties 28 | { 29 | 30 | template 31 | struct by_val 32 | { 33 | typedef T value_type; 34 | }; 35 | 36 | namespace detail 37 | { 38 | template 39 | struct PropertyTraitsBase {;}; 40 | 41 | template 42 | struct MakePtrTypeBase 43 | { 44 | typedef typename std::add_pointer::type type; 45 | }; 46 | 47 | template 48 | struct MakePtrTypeBase 49 | { 50 | typedef T type; 51 | }; 52 | 53 | template 54 | struct MakePtrType : public MakePtrTypeBase::value > 55 | { 56 | ; 57 | }; 58 | 59 | template 60 | struct PropertyTraitsBase 61 | { 62 | typedef typename std::remove_cv::type>::type clear_type; 63 | typedef clear_type arg_type; 64 | typedef clear_type result_type; 65 | typedef result_type nconst_result_type; 66 | typedef const result_type const_result_type; 67 | typedef typename MakePtrType::type ptr_type; 68 | typedef typename MakePtrType::type const_ptr_type; 69 | BOOST_STATIC_CONSTANT(bool, is_scalar = true); 70 | BOOST_STATIC_CONSTANT(bool, is_const = false); 71 | BOOST_STATIC_CONSTANT(bool, is_reference = std::is_reference::value); 72 | BOOST_STATIC_CONSTANT(bool, is_pointer = std::is_pointer::value); 73 | }; 74 | 75 | template 76 | struct NonScalarTypeTraits 77 | { 78 | typedef typename std::remove_cv::type>::type clear_type; 79 | typedef const clear_type& arg_type; 80 | typedef arg_type result_type; 81 | typedef arg_type const_result_type; 82 | typedef typename std::remove_cv::type nconst_result_type; 83 | BOOST_STATIC_CONSTANT(bool, is_const = std::is_const::type>::value); 84 | }; 85 | 86 | template 87 | struct NonScalarTypeTraits 88 | { 89 | typedef typename std::remove_cv::type>::type clear_type; 90 | typedef clear_type& arg_type; 91 | typedef T result_type; 92 | typedef clear_type const& const_result_type; 93 | typedef typename std::remove_cv::type nconst_result_type; 94 | BOOST_STATIC_CONSTANT(bool, is_const = std::is_const::type>::value); 95 | }; 96 | 97 | template 98 | struct PropertyTraitsBase : NonScalarTypeTraits::value> 99 | { 100 | typedef typename MakePtrType::type ptr_type; 101 | typedef typename MakePtrType::type>::type const_ptr_type; 102 | BOOST_STATIC_CONSTANT(bool, is_scalar = false); 103 | BOOST_STATIC_CONSTANT(bool, is_reference = std::is_reference::value); 104 | // typedef typename remove_all_extents::type result_type; 105 | BOOST_STATIC_CONSTANT(bool, is_pointer = std::is_pointer::value); 106 | }; 107 | 108 | template 109 | struct PropertyTraitsBase, false> 110 | { 111 | typedef typename std::remove_cv::type>::type clear_type; 112 | typedef clear_type arg_type; 113 | typedef clear_type result_type; 114 | typedef const clear_type const_result_type; 115 | typedef clear_type nconst_result_type; 116 | typedef typename MakePtrType::type ptr_type; 117 | typedef typename MakePtrType::type>::type const_ptr_type; 118 | BOOST_STATIC_CONSTANT(bool, is_scalar = false); 119 | BOOST_STATIC_CONSTANT(bool, is_const = false); 120 | BOOST_STATIC_CONSTANT(bool, is_reference = std::is_reference::value); 121 | BOOST_STATIC_CONSTANT(bool, is_pointer = std::is_pointer::value); 122 | }; 123 | 124 | template 125 | struct PropertyTraits : public PropertyTraitsBase::value> 126 | { 127 | ; 128 | }; 129 | } 130 | } 131 | } 132 | 133 | #endif // Sandbox_Source_Files_property_property_traits_hpp__ 134 | -------------------------------------------------------------------------------- /include/flex_lib/properties/rw_property.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:32 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_rw_property_hpp__ 12 | #define Sandbox_Source_Files_property_rw_property_hpp__ 13 | 14 | #include "properties_fwd.hpp" 15 | 16 | # define MAKE_PROPERTY_TYPE_RW(ClassName, PI) MAKE_PROP_TYPE_GENERIC(ClassName, PI, DefaultPropertyBase, BOOST_PP_SEQ_ELEM(6, PI)) 17 | 18 | # define DEFINE_PROPERTY_RW(ClassName, PI) DEFINE_PROPERTY_GENERIC_X(ClassName, PI, DefaultPropertyBase, BOOST_PP_SEQ_ELEM(6, PI)); 19 | 20 | # define DEFINE_PROPERTY_IMPL_AS_MEMBER_RW(ClassName, PI) 21 | 22 | # define RW_PROPERTY_CTR_INIT_RW(ClassName, PI) &ClassName::BOOST_PP_SEQ_ELEM(7, PI), &ClassName::BOOST_PP_SEQ_ELEM(8, PI) 23 | # define RW_PROPERTY_CTR_INIT_RO(ClassName, PI) &ClassName::BOOST_PP_SEQ_ELEM(7, PI) 24 | 25 | # define DEFINE_PROPERTY_IMPL_AS_STATIC_RW(ClassName, PI) \ 26 | static boost::properties::detail::BOOST_PP_SEQ_ELEM(3, PI) BOOST_PP_SEQ_ELEM(4, PI)(BOOST_PP_CAT(RW_PROPERTY_CTR_INIT_, BOOST_PP_SEQ_ELEM(5, PI))(ClassName, PI)); 27 | 28 | # define INITIALIZE_PROPERTY_IMPL_RW(ClassName, PI) \ 29 | host->BOOST_PP_SEQ_ELEM(4, PI).Init(host, &BOOST_PP_SEQ_ELEM(4, PI) ); 30 | 31 | # define COPY_PROPERTY_IMPL_RW(_1, _2) 32 | 33 | # define SERIALIZE_PROPERTY_IMPL_RW(ClassName, PI) 34 | 35 | # define INVOKE_GET_PROPERTY_IMPL_RW(ClassName, PI) INVOKE_GET_PROPERTY_IMPL_GENERIC(ClassName, PI) 36 | 37 | # define INVOKE_SET_PROPERTY_IMPL_RW(ClassName, PI) INVOKE_SET_PROPERTY_IMPL_GENERIC(ClassName, PI) 38 | 39 | # define HAS_PROPERTY_PROPERTY_IMPL_RW(ClassName, PI) HAS_PROPERTY_PROPERTY_IMPL_GENERIC(ClassName, PI) 40 | 41 | 42 | # define ENUM_PROPERTY_IMPL_RW(ClassName, PI) ENUM_PROPERTY_IMPL_GENERIC(ClassName, PI) 43 | 44 | #define RW_PROPERTY(Type, Name, Get, Set) ( (RW)((Type))(Property)(SetterGetterPropertyImpl)(Name)(RW)(ReadWritePropertyAccessors)(Get)(Set) ) 45 | #define RO_PROPERTY(Type, Name, Get) ( (RW)((Type))(Property)(GetterPropertyImpl)(Name)(RO)(ReadPropertyAccessors)(Get)(_) ) 46 | #define WO_PROPERTY(Type, Name, Set) ( (RW)((Type))(Property)(SetterPropertyImpl)(Name)(RO)(WritePropertyAccessors)(Set)(_) ) 47 | 48 | #define RW_PROPERTY_V(Type, Name, Get, Set) ( (RW)((boost::properties::by_val))(Property)(SetterGetterPropertyImpl)(Name)(RW)(ReadWritePropertyAccessors)(Get)(Set) ) 49 | #define RO_PROPERTY_V(Type, Name, Get) ( (RW)((boost::properties::by_val))(Property)(GetterPropertyImpl)(Name)(RO)(ReadPropertyAccessors)(Get)(_) ) 50 | #define WO_PROPERTY_V(Type, Name, Set) ( (RW)((boost::properties::by_val))(Property)(SetterPropertyImpl)(Name)(RO)(WritePropertyAccessors)(Set)(_) ) 51 | 52 | namespace boost 53 | { 54 | namespace properties 55 | { 56 | namespace detail 57 | { 58 | template 59 | struct SetterGetterTraitsImpl 60 | { 61 | typedef typename PTR::result_type result_type; 62 | typedef typename PTR::arg_type arg_type; 63 | typedef result_type (H::*GetterType)() const; 64 | typedef void (H::*SetterType)(arg_type val); 65 | typedef H* const Host; 66 | BOOST_STATIC_CONSTANT(bool, ConstGetter = true); 67 | }; 68 | 69 | template 70 | struct SetterGetterTraitsImpl 71 | { 72 | typedef typename PTR::clear_type& result_type; 73 | typedef typename PTR::clear_type& arg_type; 74 | typedef result_type (H::*GetterType)(); 75 | typedef void (H::*SetterType)(arg_type val); 76 | typedef H* Host; 77 | BOOST_STATIC_CONSTANT(bool, ConstGetter = false); 78 | }; 79 | 80 | template 81 | struct SetterGetterTraits : SetterGetterTraitsImpl 82 | { 83 | }; 84 | 85 | template 86 | class SetterGetterPropertyImpl 87 | { 88 | public: 89 | typedef PropertyTraits traits; 90 | typedef SetterGetterTraits sg_traits; 91 | typedef typename sg_traits::GetterType GetterType; 92 | typedef typename sg_traits::SetterType SetterType; 93 | typedef typename sg_traits::arg_type arg_type; 94 | 95 | SetterGetterPropertyImpl(GetterType getter, SetterType setter) : m_Getter(getter), m_Setter(setter) {;} 96 | typename sg_traits::result_type get(typename sg_traits::Host host) const 97 | { 98 | return (host->*m_Getter)(); 99 | } 100 | void set(typename sg_traits::Host host, typename sg_traits::arg_type val) 101 | { 102 | (host->*m_Setter)(val); 103 | } 104 | private: 105 | GetterType m_Getter; 106 | SetterType m_Setter; 107 | }; 108 | 109 | template 110 | class GetterPropertyImpl 111 | { 112 | public: 113 | typedef PropertyTraits traits; 114 | typedef SetterGetterTraits sg_traits; 115 | typedef typename sg_traits::GetterType GetterType; 116 | typedef typename traits::arg_type arg_type; 117 | 118 | GetterPropertyImpl(GetterType getter) : m_Getter(getter) {;} 119 | typename sg_traits::result_type get(typename sg_traits::Host host) const 120 | { 121 | return (host->*m_Getter)(); 122 | } 123 | private: 124 | GetterType m_Getter; 125 | }; 126 | 127 | template 128 | class SetterPropertyImpl 129 | { 130 | public: 131 | typedef PropertyTraits traits; 132 | typedef SetterGetterTraits sg_traits; 133 | typedef typename sg_traits::SetterType SetterType; 134 | typedef typename sg_traits::arg_type arg_type; 135 | 136 | SetterPropertyImpl(SetterType setter) : m_Setter(setter) {;} 137 | void set(typename sg_traits::Host host, typename sg_traits::arg_type val) 138 | { 139 | (host->*m_Setter)(val); 140 | } 141 | private: 142 | SetterType m_Setter; 143 | }; 144 | } 145 | } 146 | } 147 | 148 | #endif // Sandbox_Source_Files_property_rw_property_hpp__ 149 | -------------------------------------------------------------------------------- /include/flex_lib/properties/simple_property.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 04.05.2008 14:3 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080504 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_simple_property_hpp__ 12 | #define Sandbox_Source_Files_property_simple_property_hpp__ 13 | 14 | #include "properties_fwd.hpp" 15 | 16 | # define MAKE_PROPERTY_TYPE_SIMPLE(ClassName, PI) \ 17 | boost::properties::BOOST_PP_SEQ_ELEM(2, PI) > 18 | # define DEFINE_PROPERTY_SIMPLE(ClassName, PI) \ 19 | MAKE_PROPERTY_TYPE_SIMPLE(ClassName, PI) BOOST_PP_SEQ_ELEM(4, PI); 20 | 21 | 22 | # define DEFINE_PROPERTY_IMPL_AS_MEMBER_SIMPLE(ClassName, PI) 23 | # define DEFINE_PROPERTY_IMPL_AS_STATIC_SIMPLE(_1, _2) 24 | 25 | #define INIT_SIMPLE_PROPERTY_NOINIT(ClassName, PI) 26 | #define INIT_SIMPLE_PROPERTY_INIT(ClassName, PI) m_Host->BOOST_PP_SEQ_ELEM(4, PI).init_value BOOST_PP_SEQ_ELEM(6, PI); 27 | 28 | # define INITIALIZE_PROPERTY_IMPL_SIMPLE(ClassName, PI) BOOST_PP_CAT(INIT_SIMPLE_PROPERTY_, BOOST_PP_SEQ_ELEM(5, PI))(ClassName, PI) 29 | # define COPY_PROPERTY_IMPL_SIMPLE(ClassName, PI) m_Host->BOOST_PP_SEQ_ELEM(4, PI).copy_from(other.m_Host->BOOST_PP_SEQ_ELEM(4, PI) ); 30 | # define SERIALIZE_PROPERTY_IMPL_SIMPLE(ClassName, PI) ar & m_Host->BOOST_PP_SEQ_ELEM(4, PI); 31 | # define INVOKE_GET_PROPERTY_IMPL_SIMPLE(ClassName, PI) INVOKE_GET_PROPERTY_IMPL_GENERIC(ClassName, PI) 32 | # define INVOKE_SET_PROPERTY_IMPL_SIMPLE(ClassName, PI) INVOKE_SET_PROPERTY_IMPL_GENERIC(ClassName, PI) 33 | # define HAS_PROPERTY_PROPERTY_IMPL_SIMPLE(ClassName, PI) HAS_PROPERTY_PROPERTY_IMPL_GENERIC(ClassName, PI) 34 | # define ENUM_PROPERTY_IMPL_SIMPLE(ClassName, PI) ENUM_PROPERTY_IMPL_GENERIC(ClassName, PI) 35 | 36 | # define PROPERTY(Type, Name) ( (SIMPLE)((Type))(Property)(SimplePropertyImpl)(Name)(NOINIT) ) 37 | # define PROPERTY_I(Type, Name, InitVal) ( (SIMPLE)((Type))(Property)(SimplePropertyImpl)(Name)(INIT)((InitVal)) ) 38 | # define PROPERTY_CT(N, Type, Name) ( (SIMPLE)(BOOST_PP_TUPLE_TO_SEQ(N, Type))(Property)(SimplePropertyImpl)(Name)(NOINIT) ) 39 | # define PROPERTY_CT_I(N, Type, Name, InitVal) ( (SIMPLE)(BOOST_PP_TUPLE_TO_SEQ(N, Type))(Property)(SimplePropertyImpl)(Name)(INIT)(InitVal) ) 40 | 41 | namespace boost 42 | { 43 | namespace properties 44 | { 45 | template 46 | class LightWieghtProperty 47 | { 48 | public: 49 | typedef LightWieghtProperty this_type; 50 | typedef detail::PropertyTraits traits; 51 | typedef typename traits::arg_type arg_type; 52 | 53 | typename traits::const_result_type get() const 54 | { 55 | return m_Value; 56 | } 57 | typename traits::nconst_result_type get() 58 | { 59 | return m_Value; 60 | } 61 | void set(typename traits::arg_type value) 62 | { 63 | m_Value = value; 64 | } 65 | void Init(H* host, void* impl) 66 | { 67 | } 68 | void copy_from(const this_type& other) 69 | { 70 | m_Value = other.m_Value; 71 | } 72 | void init_value(typename traits::arg_type value) 73 | { 74 | m_Value = value; 75 | } 76 | private: 77 | typename traits::clear_type m_Value; 78 | }; 79 | } 80 | } 81 | 82 | #endif // Sandbox_Source_Files_property_simple_property_hpp__ 83 | -------------------------------------------------------------------------------- /include/flex_lib/property.hpp: -------------------------------------------------------------------------------- 1 | /***************************************************************************************** 2 | Created: 17.04.2008 16:30 3 | 4 | Purpose: 5 | ****************************************************************************************** 6 | History: 7 | 8 | 20080417 Flex Ferrum: 9 | ******************************************************************************************/ 10 | 11 | #ifndef Sandbox_Source_Files_property_property_hpp__ 12 | #define Sandbox_Source_Files_property_property_hpp__ 13 | 14 | #include "properties/properties_fwd.hpp" 15 | #include "properties/simple_property.hpp" 16 | #include "properties/rw_property.hpp" 17 | #include "properties/property_pp.hpp" 18 | 19 | #endif // Sandbox_Source_Files_property_property_hpp__ 20 | -------------------------------------------------------------------------------- /include/flex_lib/stringized_enum.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_STRINGIZED_ENUM_H__ 2 | #define FLEX_LIB_STRINGIZED_ENUM_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace flex_lib 10 | { 11 | 12 | class bad_enum_name : public std::logic_error 13 | { 14 | public: 15 | bad_enum_name(std::string description) : std::logic_error(std::move(description)) {} 16 | 17 | static void Throw(const char* itemName, const char* enumName) 18 | { 19 | std::ostringstream os; 20 | os << "Can't convert string \"" << itemName << "\" into value of enum '" << enumName << "'"; 21 | throw flex_lib::bad_enum_name(os.str()); 22 | } 23 | }; 24 | 25 | namespace detail 26 | { 27 | template 28 | bool String2Enum(const char* itemName, std::pair (&items)[N], EnumType& value) 29 | { 30 | auto p = std::lower_bound(begin(items), end(items), itemName, 31 | [](auto&& i, auto&& v) {return strcmp(i.first, v) < 0;}); 32 | 33 | if (p == end(items) || strcmp(p->first, itemName) != 0) 34 | return false; 35 | 36 | value = p->second; 37 | return true; 38 | } 39 | } // detail 40 | 41 | template 42 | const char* Enum2String(E e); 43 | 44 | template 45 | E String2Enum(const char* name); 46 | 47 | } // flex_lib 48 | 49 | #endif // FLEX_LIB_STRINGIZED_ENUM_H__ 50 | -------------------------------------------------------------------------------- /include/flex_lib/variant.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_VARIANT_H 2 | #define FLEX_LIB_VARIANT_H 3 | 4 | #include "variant/variant_impl.h" 5 | 6 | #endif // FLEX_LIB_VARIANT_H 7 | -------------------------------------------------------------------------------- /include/flex_lib/variant/static_visitor.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_LIB_VARIANT_STATIC_VISITOR_H 2 | #define FLEX_LIB_VARIANT_STATIC_VISITOR_H 3 | 4 | #include 5 | #include "variant_impl.h" 6 | 7 | namespace flex_lib 8 | { 9 | // visitor(*(const typename detail::VariantTypesEnumerator::FirstType::type *)nullptr)() 10 | template 11 | auto apply_visitor(Variant& v, const VFn& visitor) -> typename std::result_of::FirstType::type)>::type 12 | { 13 | typedef typename std::result_of::FirstType::type)>::type R; 14 | 15 | return v.template ApplyVisitor(visitor); 16 | } 17 | 18 | template 19 | auto apply_visitor(const Variant& v, const VFn& visitor) -> typename std::result_of::FirstType::type)>::type 20 | { 21 | typedef typename std::result_of::FirstType::type)>::type R; 22 | 23 | return v.template ApplyVisitor(visitor); 24 | } 25 | } 26 | 27 | #endif // FLEX_LIB_VARIANT_STATIC_VISITOR_H 28 | -------------------------------------------------------------------------------- /sources/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flexferrum/flex_lib/322adb7acdfbc0e541292708a2bd66b305b05c52/sources/CMakeLists.txt -------------------------------------------------------------------------------- /sources/readme.txt: -------------------------------------------------------------------------------- 1 | empty -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(${GTEST_INCLUDE_DIRS}) 2 | 3 | add_subdirectory(lazy_list) 4 | add_subdirectory(variant) 5 | -------------------------------------------------------------------------------- /tests/lazy_list/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (lazy_list_tests) 2 | 3 | include (collect_sources) 4 | 5 | CollectSources(Sources Headers ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | add_executable(${PROJECT_NAME} 8 | ${Sources} 9 | ${Headers} 10 | ) 11 | 12 | target_link_libraries(${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES} flex_lib) 13 | 14 | add_test(${PROJECT_NAME} ${PROJECT_NAME}) 15 | -------------------------------------------------------------------------------- /tests/lazy_list/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : lazy_list Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this lazy_list application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your lazy_list application. 9 | 10 | 11 | lazy_list.vcxproj 12 | This is the main project file for VC++ projects generated using an Application Wizard. 13 | It contains information about the version of Visual C++ that generated the file, and 14 | information about the platforms, configurations, and project features selected with the 15 | Application Wizard. 16 | 17 | lazy_list.vcxproj.filters 18 | This is the filters file for VC++ projects generated using an Application Wizard. 19 | It contains information about the association between the files in your project 20 | and the filters. This association is used in the IDE to show grouping of files with 21 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 22 | "Source Files" filter). 23 | 24 | lazy_list.cpp 25 | This is the main application source file. 26 | 27 | ///////////////////////////////////////////////////////////////////////////// 28 | Other standard files: 29 | 30 | StdAfx.h, StdAfx.cpp 31 | These files are used to build a precompiled header (PCH) file 32 | named lazy_list.pch and a precompiled types file named StdAfx.obj. 33 | 34 | ///////////////////////////////////////////////////////////////////////////// 35 | Other notes: 36 | 37 | AppWizard uses "TODO:" comments to indicate parts of the source code you 38 | should add to or customize. 39 | 40 | ///////////////////////////////////////////////////////////////////////////// 41 | -------------------------------------------------------------------------------- /tests/lazy_list/lazy_list.cpp: -------------------------------------------------------------------------------- 1 | // lazy_list.cpp : Defines the entry point for the console application. 2 | // 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | typedef flex_lib::lazy_list TestLazyList; 10 | 11 | template 12 | class LazyNode 13 | { 14 | public: 15 | typedef std::function generator_type; 16 | typedef LazyNode this_type; 17 | 18 | LazyNode() 19 | { 20 | ; 21 | } 22 | 23 | LazyNode(const generator_type &gen) 24 | : m_generator(gen) 25 | { 26 | ; 27 | } 28 | 29 | LazyNode(generator_type &&gen) 30 | : m_generator(std::move(gen)) 31 | { 32 | ; 33 | } 34 | 35 | T & operator *() 36 | { 37 | Dereference(); 38 | return m_val.get(); 39 | } 40 | 41 | const T & operator *() const 42 | { 43 | Dereference(); 44 | return m_val.get(); 45 | } 46 | private: 47 | void Dereference() const 48 | { 49 | if (m_val.is_initialized()) 50 | return; 51 | 52 | m_val = m_generator(); 53 | } 54 | 55 | mutable boost::optional m_val; 56 | std::function m_generator; 57 | }; 58 | 59 | TEST(LazyList, EmptyList) 60 | { 61 | TestLazyList list; 62 | 63 | EXPECT_TRUE(list.empty()); 64 | } 65 | 66 | TEST(LazyList, SequencePtrInit) 67 | { 68 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 69 | 70 | TestLazyList l1 = fl::lazy_from(std::begin(items1), std::end(items1)).done(); 71 | EXPECT_EQ(sizeof(items1) / sizeof(items1[0]), l1.size()); 72 | 73 | auto it = l1.begin(); 74 | EXPECT_EQ(items1[0], *it ++); 75 | EXPECT_EQ(items1[1], *it ++); 76 | EXPECT_EQ(items1[2], *it ++); 77 | EXPECT_EQ(items1[3], *it ++); 78 | EXPECT_EQ(items1[4], *it ++); 79 | EXPECT_EQ(items1[5], *it ++); 80 | EXPECT_TRUE(it == l1.end()); 81 | } 82 | 83 | TEST(LazyList, SequenceArrayInit) 84 | { 85 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 86 | 87 | TestLazyList l1 = fl::lazy_from(items1).done(); 88 | EXPECT_EQ(sizeof(items1) / sizeof(items1[0]), l1.size()); 89 | 90 | auto it = l1.begin(); 91 | EXPECT_EQ(items1[0], *it ++); 92 | EXPECT_EQ(items1[1], *it ++); 93 | EXPECT_EQ(items1[2], *it ++); 94 | EXPECT_EQ(items1[3], *it ++); 95 | EXPECT_EQ(items1[4], *it ++); 96 | EXPECT_EQ(items1[5], *it ++); 97 | EXPECT_TRUE(it == l1.end()); 98 | } 99 | 100 | TEST(LazyList, SequenceIteratorInit) 101 | { 102 | std::vector items1{0, 1, 2, 3, 4, 5}; 103 | 104 | TestLazyList l1 = fl::lazy_from(items1.begin(), items1.end()).done(); 105 | EXPECT_EQ(items1.size(), l1.size()); 106 | 107 | auto it = l1.begin(); 108 | EXPECT_EQ(items1[0], *it ++); 109 | EXPECT_EQ(items1[1], *it ++); 110 | EXPECT_EQ(items1[2], *it ++); 111 | EXPECT_EQ(items1[3], *it ++); 112 | EXPECT_EQ(items1[4], *it ++); 113 | EXPECT_EQ(items1[5], *it ++); 114 | EXPECT_TRUE(it == l1.end()); 115 | } 116 | 117 | TEST(LazyList, SequenceContainerInit) 118 | { 119 | std::vector items1{0, 1, 2, 3, 4, 5}; 120 | 121 | TestLazyList l1 = fl::lazy_from(items1).done(); 122 | EXPECT_EQ(items1.size(), l1.size()); 123 | 124 | auto it = l1.begin(); 125 | EXPECT_EQ(items1[0], *it ++); 126 | EXPECT_EQ(items1[1], *it ++); 127 | EXPECT_EQ(items1[2], *it ++); 128 | EXPECT_EQ(items1[3], *it ++); 129 | EXPECT_EQ(items1[4], *it ++); 130 | EXPECT_EQ(items1[5], *it ++); 131 | EXPECT_TRUE(it == l1.end()); 132 | } 133 | 134 | TEST(LazyList, FunctorInit) 135 | { 136 | uint64_t count = 0; 137 | uint64_t items1[6]; 138 | auto ftor = [&count, &items1](bool& isEnd) 139 | { 140 | if (count == 6) 141 | { 142 | isEnd = true; 143 | return 0ull; 144 | } 145 | 146 | uint64_t next_val = count ++; 147 | return items1[next_val] = next_val; 148 | }; 149 | 150 | TestLazyList l1 = fl::lazy_generate(std::move(ftor)).done(); 151 | EXPECT_EQ(6, l1.size()); 152 | 153 | auto it = l1.begin(); 154 | EXPECT_EQ(items1[0], *it ++); 155 | EXPECT_EQ(items1[1], *it ++); 156 | EXPECT_EQ(items1[2], *it ++); 157 | EXPECT_EQ(items1[3], *it ++); 158 | EXPECT_EQ(items1[4], *it ++); 159 | EXPECT_EQ(items1[5], *it ++); 160 | EXPECT_TRUE(it == l1.end()); 161 | EXPECT_EQ(6, count); 162 | } 163 | 164 | template 165 | auto MakeTestLazyList(T (&items)[N], size_t &counter) 166 | { 167 | return fl::lazy_generate( 168 | [&counter, &items](bool &isEos) -> T 169 | { 170 | if (counter == N) 171 | { 172 | isEos = true; 173 | return T(); 174 | } 175 | 176 | auto next_val = counter ++; 177 | return items[next_val] = next_val; 178 | }); 179 | } 180 | 181 | TEST(LazyList, LazyFunctorInit) 182 | { 183 | size_t count = 0; 184 | uint64_t items1[6]; 185 | 186 | auto l1(MakeTestLazyList(items1, count).done()); 187 | EXPECT_EQ(6, l1.size()); 188 | 189 | auto it = l1.begin(); 190 | EXPECT_EQ(items1[0], *it ++); 191 | EXPECT_EQ(items1[1], *it ++); 192 | EXPECT_EQ(items1[2], *it ++); 193 | EXPECT_EQ(items1[3], *it ++); 194 | EXPECT_EQ(items1[4], *it ++); 195 | EXPECT_EQ(items1[5], *it ++); 196 | EXPECT_TRUE(it == l1.end()); 197 | EXPECT_EQ(6, count); 198 | } 199 | 200 | TEST(LazyList, ValidateLazy1) 201 | { 202 | size_t count = 0; 203 | uint64_t items1[6]; 204 | 205 | auto l1(MakeTestLazyList(items1, count).done()); 206 | 207 | auto it = l1.begin(); 208 | EXPECT_EQ(0, count); 209 | EXPECT_EQ(items1[0], *it ++); 210 | EXPECT_EQ(1, count); 211 | EXPECT_EQ(items1[1], *it ++); 212 | EXPECT_EQ(2, count); 213 | EXPECT_EQ(items1[2], *it ++); 214 | EXPECT_EQ(3, count); 215 | EXPECT_EQ(items1[3], *it ++); 216 | EXPECT_EQ(4, count); 217 | EXPECT_EQ(items1[4], *it ++); 218 | EXPECT_EQ(5, count); 219 | EXPECT_EQ(items1[5], *it ++); 220 | EXPECT_TRUE(it == l1.end()); 221 | EXPECT_EQ(6, count); 222 | } 223 | 224 | TEST(LazyList, ValidateLazy2) 225 | { 226 | int count = 0; 227 | int inner_count = 0; 228 | uint64_t items1[6]; 229 | auto ftor = [&count, &items1, &inner_count](bool &isEnd) 230 | { 231 | if (count == 6) 232 | { 233 | isEnd = true; 234 | return LazyNode([] {return 0;}); 235 | } 236 | 237 | int next_val = count ++; 238 | int& ic = inner_count; 239 | items1[next_val] = next_val; 240 | return LazyNode([next_val, &ic]() -> uint64_t {++ ic; return next_val;}); 241 | }; 242 | 243 | auto l1 = fl::lazy_generate(std::move(ftor)).done(); 244 | 245 | auto it = l1.begin(); 246 | EXPECT_EQ(0, count); 247 | EXPECT_EQ(0, inner_count); 248 | EXPECT_EQ(items1[0], **it); 249 | EXPECT_EQ(1, count); 250 | EXPECT_EQ(1, inner_count); 251 | ++ it; 252 | EXPECT_EQ(1, inner_count); 253 | EXPECT_EQ(2, count); 254 | EXPECT_EQ(items1[1], **it); 255 | EXPECT_EQ(2, count); 256 | EXPECT_EQ(2, inner_count); 257 | ++ it; 258 | EXPECT_EQ(2, inner_count); 259 | EXPECT_EQ(3, count); 260 | EXPECT_EQ(items1[2], **it); 261 | EXPECT_EQ(3, count); 262 | EXPECT_EQ(3, inner_count); 263 | ++ it; 264 | EXPECT_EQ(3, inner_count); 265 | EXPECT_EQ(4, count); 266 | EXPECT_EQ(items1[3], **it); 267 | EXPECT_EQ(4, count); 268 | EXPECT_EQ(4, inner_count); 269 | ++ it; 270 | EXPECT_EQ(4, inner_count); 271 | EXPECT_EQ(5, count); 272 | EXPECT_EQ(items1[4], **it); 273 | EXPECT_EQ(5, count); 274 | EXPECT_EQ(5, inner_count); 275 | ++ it; 276 | EXPECT_EQ(5, inner_count); 277 | EXPECT_EQ(6, count); 278 | EXPECT_EQ(items1[5], **it); 279 | EXPECT_EQ(6, count); 280 | ++ it; 281 | EXPECT_TRUE(it == l1.end()); 282 | EXPECT_EQ(6, inner_count); 283 | } 284 | 285 | TEST(LazyList, Head) 286 | { 287 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 288 | 289 | auto l1(fl::lazy_from(items1).done()); 290 | 291 | EXPECT_EQ(items1[0], l1.head()); 292 | } 293 | 294 | TEST(LazyList, Tail) 295 | { 296 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 297 | 298 | auto l2(fl::lazy_from(items1).tail().done()); 299 | 300 | auto it = l2.begin(); 301 | EXPECT_EQ(items1[1], *it ++); 302 | EXPECT_EQ(items1[2], *it ++); 303 | EXPECT_EQ(items1[3], *it ++); 304 | EXPECT_EQ(items1[4], *it ++); 305 | EXPECT_EQ(items1[5], *it ++); 306 | EXPECT_TRUE(it == l2.end()); 307 | } 308 | 309 | TEST(LazyList, ValidateLazyTail) 310 | { 311 | size_t count = 0; 312 | uint64_t items1[6]; 313 | 314 | auto l2(MakeTestLazyList(items1, count).tail().done()); 315 | 316 | auto it = l2.begin(); 317 | EXPECT_EQ(0, count); 318 | EXPECT_EQ(items1[1], *it ++); 319 | EXPECT_EQ(2, count); 320 | EXPECT_EQ(items1[2], *it ++); 321 | EXPECT_EQ(3, count); 322 | EXPECT_EQ(items1[3], *it ++); 323 | EXPECT_EQ(4, count); 324 | EXPECT_EQ(items1[4], *it ++); 325 | EXPECT_EQ(5, count); 326 | EXPECT_EQ(items1[5], *it ++); 327 | EXPECT_TRUE(it == l2.end()); 328 | EXPECT_EQ(6, count); 329 | } 330 | 331 | TEST(LazyList, Cons) 332 | { 333 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 334 | 335 | auto l2(fl::lazy_from(items1).cons(10).done()); 336 | 337 | auto it = l2.begin(); 338 | EXPECT_EQ(10, *it ++); 339 | EXPECT_EQ(items1[0], *it ++); 340 | EXPECT_EQ(items1[1], *it ++); 341 | EXPECT_EQ(items1[2], *it ++); 342 | EXPECT_EQ(items1[3], *it ++); 343 | EXPECT_EQ(items1[4], *it ++); 344 | EXPECT_EQ(items1[5], *it ++); 345 | EXPECT_TRUE(it == l2.end()); 346 | } 347 | 348 | TEST(LazyList, ValidateLazyCons) 349 | { 350 | size_t count = 0; 351 | uint64_t items1[6]; 352 | 353 | auto l2(MakeTestLazyList(items1, count).cons(10).done()); 354 | 355 | auto it = l2.begin(); 356 | EXPECT_EQ(0, count); 357 | EXPECT_EQ(10, *it ++); 358 | EXPECT_EQ(0, count); 359 | EXPECT_EQ(items1[0], *it ++); 360 | EXPECT_EQ(1, count); 361 | EXPECT_EQ(items1[1], *it ++); 362 | EXPECT_EQ(2, count); 363 | EXPECT_EQ(items1[2], *it ++); 364 | EXPECT_EQ(3, count); 365 | EXPECT_EQ(items1[3], *it ++); 366 | EXPECT_EQ(4, count); 367 | EXPECT_EQ(items1[4], *it ++); 368 | EXPECT_EQ(5, count); 369 | EXPECT_EQ(items1[5], *it ++); 370 | EXPECT_TRUE(it == l2.end()); 371 | EXPECT_EQ(6, count); 372 | } 373 | 374 | TEST(LazyList, Filter) 375 | { 376 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 377 | 378 | auto l2(fl::lazy_from(items1).filter([](uint64_t val) {return (val % 2) != 0;}).done()); 379 | 380 | auto it = l2.begin(); 381 | EXPECT_EQ(items1[1], *it ++); 382 | EXPECT_EQ(items1[3], *it ++); 383 | EXPECT_EQ(items1[5], *it ++); 384 | EXPECT_TRUE(it == l2.end()); 385 | } 386 | 387 | TEST(LazyList, Map) 388 | { 389 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 390 | 391 | auto l2(fl::lazy_from(items1).map([](uint64_t val) {return std::to_string(val);}).done()); 392 | 393 | auto it = l2.begin(); 394 | EXPECT_EQ(std::string("0"), *it ++); 395 | EXPECT_EQ(std::string("1"), *it ++); 396 | EXPECT_EQ(std::string("2"), *it ++); 397 | EXPECT_EQ(std::string("3"), *it ++); 398 | EXPECT_EQ(std::string("4"), *it ++); 399 | EXPECT_EQ(std::string("5"), *it ++); 400 | EXPECT_TRUE(it == l2.end()); 401 | } 402 | 403 | TEST(LazyList, Zip) 404 | { 405 | uint64_t items1[] = {0, 1, 2, 3, 4, 5}; 406 | 407 | auto l1(fl::lazy_from(items1).done()); 408 | auto l2(fl::lazy_from(l1).zip(l1, [](uint64_t v1, uint64_t v2) {return v1 * v2;}).done()); 409 | 410 | auto it = l2.begin(); 411 | EXPECT_EQ(0, *it ++); 412 | EXPECT_EQ(1, *it ++); 413 | EXPECT_EQ(4, *it ++); 414 | EXPECT_EQ(9, *it ++); 415 | EXPECT_EQ(16, *it ++); 416 | EXPECT_EQ(25, *it ++); 417 | EXPECT_TRUE(it == l2.end()); 418 | } 419 | 420 | TEST(LazyList, ZipLazySequence) 421 | { 422 | auto l1(fl::lazy_sequence(6).done()); 423 | auto l2(fl::lazy_from(l1).zip(l1, [](uint64_t v1, uint64_t v2) {return v1 * v2;}).done()); 424 | 425 | auto it = l2.begin(); 426 | EXPECT_EQ(0, *it ++); 427 | EXPECT_EQ(1, *it ++); 428 | EXPECT_EQ(4, *it ++); 429 | EXPECT_EQ(9, *it ++); 430 | EXPECT_EQ(16, *it ++); 431 | EXPECT_EQ(25, *it ++); 432 | EXPECT_TRUE(it == l2.end()); 433 | } 434 | 435 | TEST(LazyList, ZipSelfLazySequence) 436 | { 437 | auto l2(fl::lazy_sequence(6).zip_self([](uint64_t v1, uint64_t v2) {return v1 * v2;}).done()); 438 | 439 | auto it = l2.begin(); 440 | EXPECT_EQ(0, *it ++); 441 | EXPECT_EQ(1, *it ++); 442 | EXPECT_EQ(4, *it ++); 443 | EXPECT_EQ(9, *it ++); 444 | EXPECT_EQ(16, *it ++); 445 | EXPECT_EQ(25, *it ++); 446 | EXPECT_TRUE(it == l2.end()); 447 | } 448 | int main(int argc, char* argv[]) 449 | { 450 | testing::InitGoogleTest(&argc, argv); 451 | return RUN_ALL_TESTS(); 452 | } 453 | 454 | -------------------------------------------------------------------------------- /tests/lazy_list/lazy_list.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {A717A569-C146-4DD0-BA38-575A79343F09} 15 | Win32Proj 16 | lazy_list 17 | 18 | 19 | 20 | Application 21 | true 22 | Unicode 23 | v140 24 | 25 | 26 | Application 27 | false 28 | true 29 | Unicode 30 | v140 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 55 | $(COMMONLIBS)\gtest\fused-src;$(FLEXLIBDIR)\;%(AdditionalIncludeDirectories) 56 | 57 | 58 | Console 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | 66 | 67 | MaxSpeed 68 | true 69 | true 70 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 71 | $(COMMONLIBS)\gtest\fused-src;$(FLEXLIBDIR)\;%(AdditionalIncludeDirectories) 72 | 73 | 74 | Console 75 | true 76 | true 77 | true 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /tests/lazy_list/lazy_list.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/variant/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (variant_tests) 2 | 3 | include (collect_sources) 4 | 5 | CollectSources(Sources Headers ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | add_executable(${PROJECT_NAME} 8 | ${Sources} 9 | ${Headers} 10 | ) 11 | 12 | target_link_libraries(${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES} flex_lib) 13 | 14 | add_test(${PROJECT_NAME} ${PROJECT_NAME}) 15 | -------------------------------------------------------------------------------- /tools/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(codegen) 2 | -------------------------------------------------------------------------------- /tools/codegen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (FlexLib-CodeGen VERSION 0.1 LANGUAGES CXX) 2 | 3 | set(CODEGEN_BIN_NAME "fl-codegen") 4 | set(LLVM_INSTALL_ROOT $ENV{LLVM_ROOT} CACHE PATH "Path to LLVM installation root directory") 5 | set(LLVM_SOURCES_ROOT $ENV{LLVM_ROOT} CACHE PATH "Path to LLVM sources root directory") 6 | 7 | list (APPEND CMAKE_MODULE_PATH ${LLVM_INSTALL_ROOT}/lib/cmake/llvm) 8 | list (APPEND CMAKE_MODULE_PATH ${LLVM_INSTALL_ROOT}/lib/cmake/clang) 9 | 10 | include(collect_sources) 11 | include(AddLLVM) 12 | include(ClangConfig) 13 | 14 | CollectSources(Sources Headers ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src) 15 | 16 | set (Boost_USE_STATIC_LIBS ON) 17 | find_package(Boost REQUIRED COMPONENTS iostreams) 18 | 19 | if (${CMAKE_CXX_COMPILER_ID} STREQUAL "MSVC") 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc") 21 | message(STATUS "CodeGenerator is compiled with enabled exceptions") 22 | endif() 23 | 24 | include_directories( 25 | ${CLANG_INCLUDE_DIRS} 26 | ${LLVM_INCLUDE_DIRS} 27 | ) 28 | 29 | 30 | add_llvm_executable(${CODEGEN_BIN_NAME} 31 | ${Sources} 32 | ${Headers} 33 | ) 34 | 35 | target_compile_options(${CODEGEN_BIN_NAME} 36 | PRIVATE $<$:/EHsc> 37 | ) 38 | 39 | target_link_libraries(${CODEGEN_BIN_NAME} 40 | clangAST 41 | clangBasic 42 | clangDriver 43 | clangFrontend 44 | clangRewriteFrontend 45 | clangStaticAnalyzerFrontend 46 | clangTooling 47 | ${Boost_LIBRARIES} 48 | ) 49 | 50 | add_subdirectory(test) 51 | 52 | install(TARGETS ${CODEGEN_BIN_NAME} 53 | RUNTIME DESTINATION bin 54 | LIBRARY DESTINATION lib 55 | ARCHIVE DESTINATION lib/static) 56 | -------------------------------------------------------------------------------- /tools/codegen/src/ast_reflector.cpp: -------------------------------------------------------------------------------- 1 | #include "ast_reflector.h" 2 | #include "ast_utils.h" 3 | #include "type_info.h" 4 | 5 | #include 6 | #include 7 | 8 | namespace reflection 9 | { 10 | 11 | using namespace clang; 12 | 13 | template 14 | auto FindExisting(const Cont& cont, const std::string& qualifiedName) 15 | { 16 | auto p = std::find_if(begin(cont), end(cont), 17 | [&qualifiedName](auto& item) {return item->decl->getQualifiedNameAsString() == qualifiedName;}); 18 | 19 | 20 | return p == end(cont) ? Cont::value_type() : *p; 21 | } 22 | 23 | AccessType ConvertAccessType(clang::AccessSpecifier access) 24 | { 25 | AccessType result = AccessType::Undefined; 26 | switch (access) 27 | { 28 | case clang::AS_public: 29 | result = AccessType::Public; 30 | break; 31 | case clang::AS_protected: 32 | result = AccessType::Protected; 33 | break; 34 | case clang::AS_private: 35 | result = AccessType::Private; 36 | break; 37 | case clang::AS_none: 38 | break; 39 | 40 | } 41 | 42 | return result; 43 | } 44 | 45 | EnumInfoPtr AstReflector::ReflectEnum(const clang::EnumDecl *decl, NamespacesTree* nsTree) 46 | { 47 | const DeclContext* nsContext = decl->getEnclosingNamespaceContext(); 48 | 49 | NamespaceInfoPtr ns; 50 | EnumInfoPtr enumInfo; 51 | if (nsTree != nullptr) 52 | { 53 | ns = nsTree->GetNamespace(nsContext); 54 | enumInfo = FindExisting(ns->enums, decl->getQualifiedNameAsString()); 55 | } 56 | 57 | if (enumInfo) 58 | return enumInfo; 59 | 60 | // const NamedDecl* parentDecl = FindEnclosingOpaqueDecl(decl); 61 | 62 | enumInfo = std::make_shared(); 63 | enumInfo->decl = decl; 64 | enumInfo->location = GetLocation(decl, m_astContext); 65 | 66 | SetupNamedDeclInfo(decl, enumInfo.get(), m_astContext); 67 | 68 | enumInfo->isScoped = decl->isScoped(); 69 | 70 | for (const EnumConstantDecl* itemDecl : decl->enumerators()) 71 | { 72 | EnumItemInfo item; 73 | item.itemName = itemDecl->getNameAsString(); 74 | item.itemValue = itemDecl->getInitVal().toString(10); 75 | item.location = GetLocation(itemDecl, m_astContext); 76 | enumInfo->items.push_back(std::move(item)); 77 | } 78 | 79 | if (ns) 80 | ns->enums.push_back(enumInfo); 81 | 82 | return enumInfo; 83 | } 84 | 85 | ClassInfoPtr AstReflector::ReflectClass(const CXXRecordDecl* decl, NamespacesTree* nsTree) 86 | { 87 | const DeclContext* nsContext = decl->getEnclosingNamespaceContext(); 88 | 89 | NamespaceInfoPtr ns; 90 | ClassInfoPtr classInfo; 91 | 92 | if (nsTree) 93 | { 94 | ns = nsTree->GetNamespace(nsContext); 95 | classInfo = FindExisting(ns->classes, decl->getQualifiedNameAsString()); 96 | } 97 | 98 | if (classInfo) 99 | return classInfo; 100 | 101 | classInfo = std::make_shared(); 102 | classInfo->decl = decl; 103 | 104 | SetupNamedDeclInfo(decl, classInfo.get(), m_astContext); 105 | classInfo->isAbstract = decl->isAbstract(); 106 | classInfo->isTrivial = decl->isTrivial(); 107 | classInfo->isUnion = decl->isUnion(); 108 | classInfo->location = GetLocation(decl, m_astContext); 109 | 110 | for (auto methodDecl : decl->methods()) 111 | { 112 | MethodInfoPtr methodInfo = ReflectMethod(methodDecl, nsTree); 113 | classInfo->methods.push_back(methodInfo); 114 | } 115 | 116 | for (auto& base : decl->bases()) 117 | { 118 | ; 119 | } 120 | 121 | if (ns) 122 | ns->classes.push_back(classInfo); 123 | 124 | return classInfo; 125 | } 126 | 127 | MethodInfoPtr AstReflector::ReflectMethod(const CXXMethodDecl* decl, NamespacesTree* nsTree) 128 | { 129 | MethodInfoPtr methodInfo = std::make_shared(); 130 | 131 | const DeclContext* nsContext = decl->getEnclosingNamespaceContext(); 132 | 133 | NamespaceInfoPtr ns; 134 | if (nsTree) 135 | { 136 | ns = nsTree->GetNamespace(nsContext); 137 | SetupNamedDeclInfo(decl, methodInfo.get(), m_astContext); 138 | } 139 | 140 | QualType fnQualType = decl->getType(); 141 | 142 | while (const ParenType *parenType = llvm::dyn_cast(fnQualType)) 143 | fnQualType = parenType->getInnerType(); 144 | 145 | const FunctionProtoType* fnProtoType = nullptr; 146 | if (const FunctionType *fnType = fnQualType->getAs()) 147 | { 148 | if (decl->hasWrittenPrototype()) 149 | fnProtoType = llvm::dyn_cast(fnType); 150 | } 151 | 152 | methodInfo->isCtor = llvm::dyn_cast_or_null(decl) != nullptr; 153 | methodInfo->isDtor = llvm::dyn_cast_or_null(decl) != nullptr; 154 | methodInfo->isOperator = decl->isOverloadedOperator(); 155 | methodInfo->isDeleted = decl->isDeleted(); 156 | methodInfo->isConst = decl->isConst(); 157 | methodInfo->isImplicit = decl->isImplicit(); 158 | if (fnProtoType) 159 | methodInfo->isNoExcept = isNoexceptExceptionSpec(fnProtoType->getExceptionSpecType()); 160 | // methodInfo->isNoExcept = decl->is 161 | methodInfo->isPure = decl->isPure(); 162 | methodInfo->isStatic = decl->isStatic(); 163 | methodInfo->isVirtual = decl->isVirtual(); 164 | methodInfo->accessType = ConvertAccessType(decl->getAccess()); 165 | methodInfo->fullPrototype = EntityToString(decl, m_astContext); 166 | methodInfo->decl = decl; 167 | methodInfo->returnType = TypeInfo::Create(decl->getReturnType(), m_astContext); 168 | 169 | methodInfo->declLocation = GetLocation(decl, m_astContext); 170 | auto defDecl = decl->getDefinition(); 171 | if (defDecl != nullptr) 172 | methodInfo->defLocation = GetLocation(defDecl, m_astContext); 173 | 174 | for (const clang::ParmVarDecl* param: decl->parameters()) 175 | { 176 | MethodParamInfo paramInfo; 177 | paramInfo.name = param->getNameAsString(); 178 | paramInfo.type = TypeInfo::Create(param->getType(), m_astContext); 179 | paramInfo.fullDecl = EntityToString(param, m_astContext); 180 | methodInfo->params.push_back(std::move(paramInfo)); 181 | } 182 | 183 | return methodInfo; 184 | } 185 | 186 | void AstReflector::SetupNamedDeclInfo(const NamedDecl* decl, NamedDeclInfo* info, const clang::ASTContext* astContext) 187 | { 188 | info->name = decl->getNameAsString(); 189 | 190 | auto declContext = decl->getDeclContext(); 191 | const clang::NamespaceDecl* encNs = nullptr; // = clang::NamespaceDecl::castFromDeclContext(declContext->isNamespace() ? declContext : declContext->getEnclosingNamespaceContext()); 192 | // auto encNsCtx = clang::NamespaceDecl::castToDeclContext(encNs); 193 | 194 | std::string scopeQualifier = ""; 195 | 196 | for (const DeclContext* parentCtx = declContext; parentCtx != nullptr; parentCtx = parentCtx->getParent()) 197 | { 198 | const NamedDecl* namedScope = llvm::dyn_cast_or_null(Decl::castFromDeclContext(parentCtx)); 199 | if (namedScope == nullptr) 200 | continue; 201 | 202 | if (parentCtx->isNamespace()) 203 | { 204 | encNs = clang::NamespaceDecl::castFromDeclContext(parentCtx); 205 | break; 206 | } 207 | 208 | auto scopeName = namedScope->getNameAsString(); 209 | if (scopeName.empty()) 210 | continue; 211 | 212 | if (scopeQualifier.empty()) 213 | scopeQualifier = scopeName; 214 | else 215 | scopeQualifier = scopeName + "::" + scopeQualifier; 216 | } 217 | 218 | info->scopeSpecifier = scopeQualifier; 219 | 220 | if (encNs != nullptr && !encNs->isTranslationUnit()) 221 | { 222 | clang::PrintingPolicy policy(astContext->getLangOpts()); 223 | SetupDefaultPrintingPolicy(policy); 224 | 225 | llvm::raw_string_ostream os(info->namespaceQualifier); 226 | encNs->printQualifiedName(os, policy); 227 | } 228 | 229 | boost::algorithm::replace_all(info->namespaceQualifier, "(anonymous)::", ""); 230 | boost::algorithm::replace_all(info->namespaceQualifier, "::(anonymous)", ""); 231 | boost::algorithm::replace_all(info->namespaceQualifier, "(anonymous)", ""); 232 | } 233 | 234 | 235 | } // reflection 236 | -------------------------------------------------------------------------------- /tools/codegen/src/ast_reflector.h: -------------------------------------------------------------------------------- 1 | #ifndef AST_REFLECTOR_H 2 | #define AST_REFLECTOR_H 3 | 4 | #include "decls_reflection.h" 5 | 6 | namespace reflection 7 | { 8 | 9 | class AstReflector 10 | { 11 | public: 12 | explicit AstReflector(clang::ASTContext* context) 13 | : m_astContext(context) 14 | { 15 | } 16 | 17 | EnumInfoPtr ReflectEnum(const clang::EnumDecl* decl, NamespacesTree* nsTree); 18 | ClassInfoPtr ReflectClass(const clang::CXXRecordDecl* decl, NamespacesTree* nsTree); 19 | MethodInfoPtr ReflectMethod(const clang::CXXMethodDecl* decl, NamespacesTree* nsTree); 20 | 21 | static void SetupNamedDeclInfo(const clang::NamedDecl* decl, NamedDeclInfo* info, const clang::ASTContext* astContext); 22 | 23 | private: 24 | const clang::NamedDecl* FindEnclosingOpaqueDecl(const clang::DeclContext* decl); 25 | 26 | private: 27 | clang::ASTContext* m_astContext; 28 | }; 29 | 30 | } // reflection 31 | 32 | #endif // AST_REFLECTOR_H 33 | -------------------------------------------------------------------------------- /tools/codegen/src/ast_utils.h: -------------------------------------------------------------------------------- 1 | #ifndef AST_UTILS_H 2 | #define AST_UTILS_H 3 | 4 | #include "decls_reflection.h" 5 | #include "cpp_source_stream.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace reflection 12 | { 13 | 14 | inline auto GetLocation(const clang::SourceLocation& loc, const clang::ASTContext* context) 15 | { 16 | SourceLocation result; 17 | clang::PresumedLoc ploc = context->getSourceManager().getPresumedLoc(loc, false); 18 | result.fileName = ploc.getFilename(); 19 | result.line = ploc.getLine(); 20 | result.column = ploc.getColumn(); 21 | 22 | return result; 23 | } 24 | 25 | template 26 | auto GetLocation(const Entity* decl, const clang::ASTContext* context) 27 | { 28 | return GetLocation(decl->getLocation(), context); 29 | } 30 | 31 | inline void SetupDefaultPrintingPolicy(clang::PrintingPolicy& policy) 32 | { 33 | policy.Bool = true; 34 | policy.AnonymousTagLocations = false; 35 | policy.SuppressUnwrittenScope = true; 36 | policy.Indentation = 4; 37 | policy.UseVoidForZeroParams = false; 38 | policy.SuppressInitializers = true; 39 | } 40 | 41 | template 42 | std::string EntityToString(const Entity* decl, const clang::ASTContext* context) 43 | { 44 | clang::PrintingPolicy policy(context->getLangOpts()); 45 | 46 | SetupDefaultPrintingPolicy(policy); 47 | 48 | std::string result; 49 | { 50 | llvm::raw_string_ostream os(result); 51 | 52 | decl->print(os, policy); 53 | } 54 | return result; 55 | } 56 | 57 | 58 | template 59 | void WriteNamespaceContents(codegen::CppSourceStream &hdrOs, reflection::NamespaceInfoPtr ns, Fn&& fn) 60 | { 61 | using namespace codegen; 62 | 63 | out::BracedStreamScope nsScope("namespace " + ns->name, "", 0); 64 | if (!ns->isRootNamespace) 65 | hdrOs << out::new_line << nsScope; 66 | 67 | fn(hdrOs, ns); 68 | for (auto& inner : ns->innerNamespaces) 69 | WriteNamespaceContents(hdrOs, inner, std::forward(fn)); 70 | } 71 | 72 | } // reflection 73 | 74 | #endif // AST_UTILS_H 75 | -------------------------------------------------------------------------------- /tools/codegen/src/basic_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "basic_generator.h" 2 | 3 | #include 4 | 5 | namespace codegen 6 | { 7 | BasicGenerator::BasicGenerator(const Options &opts) 8 | : m_options(opts) 9 | { 10 | 11 | } 12 | 13 | void BasicGenerator::OnCompilationStarted() 14 | { 15 | 16 | } 17 | 18 | bool BasicGenerator::Validate() 19 | { 20 | return true; 21 | } 22 | 23 | enum class FileState 24 | { 25 | Good, 26 | Bad, 27 | NoFile 28 | }; 29 | 30 | FileState OpenGeneratedFile(const std::string& fileName, std::ofstream& fileStream, std::ostream*& targetStream) 31 | { 32 | if (fileName == "stdout") 33 | { 34 | targetStream = &std::cout; 35 | return FileState::Good; 36 | } 37 | 38 | if (fileName.empty()) 39 | return FileState::NoFile; 40 | 41 | fileStream.open(fileName, std::ios_base::out | std::ios_base::trunc); 42 | if (!fileStream.good()) 43 | return FileState::Bad; 44 | 45 | targetStream = &fileStream; 46 | return FileState::Good; 47 | } 48 | 49 | bool BasicGenerator::GenerateOutput() 50 | { 51 | std::ostream* targetHeaderOs = nullptr; 52 | std::ostream* targetSourceOs = nullptr; 53 | std::ofstream outHdrFile; 54 | std::ofstream outSrcFile; 55 | 56 | auto hdrFileState = OpenGeneratedFile(m_options.outputHeaderName, outHdrFile, targetHeaderOs); 57 | if (hdrFileState == FileState::Bad) 58 | { 59 | std::cerr << "Can't open output header file for writing: " << m_options.outputHeaderName << std::endl; 60 | return false; 61 | } 62 | 63 | if (hdrFileState == FileState::Good) 64 | { 65 | CppSourceStream stream(*targetHeaderOs); 66 | 67 | WriteHeaderPreamble(stream); 68 | WriteHeaderContent(stream); 69 | WriteHeaderPostamble(stream); 70 | } 71 | 72 | return true; 73 | 74 | #if 0 75 | else 76 | { 77 | targetOs = &outFile; 78 | llvm::JamCRC crcCalc; 79 | crcCalc.update(llvm::ArrayRef(OutputFilename.getValue().data(), OutputFilename.getValue().size())); 80 | fileHash = crcCalc.getCRC(); 81 | } 82 | #endif 83 | } 84 | 85 | void BasicGenerator::WriteExtraHeaders(CppSourceStream& os) 86 | { 87 | for (auto& h : m_options.extraHeaders) 88 | { 89 | os << "#include "; 90 | bool quoted = h[0] != '<'; 91 | os << (quoted ? "\"" : "") << h << (quoted ? "\"" : "") << "\n"; 92 | } 93 | } 94 | } // codegen 95 | -------------------------------------------------------------------------------- /tools/codegen/src/basic_generator.h: -------------------------------------------------------------------------------- 1 | #ifndef BASIC_GENERATOR_H 2 | #define BASIC_GENERATOR_H 3 | 4 | #include "generator_base.h" 5 | #include "cpp_source_stream.h" 6 | 7 | namespace codegen 8 | { 9 | class BasicGenerator : public GeneratorBase 10 | { 11 | public: 12 | BasicGenerator(const Options& opts); 13 | 14 | // GeneratorBase interface 15 | void OnCompilationStarted() override; 16 | bool Validate() override; 17 | bool GenerateOutput() override; 18 | 19 | protected: 20 | const Options& m_options; 21 | 22 | virtual void WriteHeaderPreamble(CppSourceStream& hdrOs) {} 23 | virtual void WriteHeaderContent(CppSourceStream& hdrOs) {} 24 | virtual void WriteHeaderPostamble(CppSourceStream& hdrOs) {} 25 | 26 | virtual void WriteSourcePreamble(CppSourceStream& srcOs) {} 27 | virtual void WriteSourceContent(CppSourceStream& srcOs) {} 28 | virtual void WriteSourcePostamble(CppSourceStream& srcOs) {} 29 | 30 | void WriteExtraHeaders(CppSourceStream& os); 31 | }; 32 | 33 | } // codegen 34 | 35 | #endif // BASIC_GENERATOR_H 36 | -------------------------------------------------------------------------------- /tools/codegen/src/cpp_source_stream.cpp: -------------------------------------------------------------------------------- 1 | #include "cpp_source_stream.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace codegen 13 | { 14 | class StreamController : public boost::iostreams::output_filter 15 | { 16 | public: 17 | enum State 18 | { 19 | BypassChars, 20 | CollectParamName 21 | }; 22 | 23 | template 24 | bool put(Sink& dest, int c) 25 | { 26 | if (m_params.empty()) 27 | { 28 | m_prevChar = c; 29 | return boost::iostreams::put(dest, c); 30 | } 31 | 32 | if (m_currentState == BypassChars) 33 | { 34 | if (c == '$') 35 | { 36 | m_currentState = CollectParamName; 37 | m_paramName.clear(); 38 | return true; 39 | } 40 | m_prevChar = c; 41 | return boost::iostreams::put(dest, c); 42 | } 43 | else if (m_currentState == CollectParamName) 44 | { 45 | if (c == '$') 46 | { 47 | bool res = WriteParamValue(dest); 48 | m_currentState = BypassChars; 49 | return res; 50 | } 51 | m_paramName.append(1, c); 52 | } 53 | return true; 54 | } 55 | 56 | template 57 | void close(Sink&) 58 | { 59 | ; 60 | } 61 | 62 | void WriteIndent(std::ostream& os, int indentDelta) 63 | { 64 | int actualAmount = m_indentLevel + indentDelta; 65 | if (actualAmount <= 0) 66 | return; 67 | 68 | for (int n = 0; n < actualAmount; ++ n) 69 | os << " "; 70 | } 71 | 72 | void Indent(std::ostream& os, int amount) 73 | { 74 | m_indentLevel += amount; 75 | if (m_indentLevel < 0) 76 | m_indentLevel = 0; 77 | } 78 | 79 | void EnterScope(const std::string& closer, int unindent) 80 | { 81 | m_scopeClosers.push(ScopeCloser{unindent, closer}); 82 | } 83 | 84 | void ExitScope(std::ostream& os) 85 | { 86 | if (m_scopeClosers.empty()) 87 | return; 88 | 89 | auto closer = m_scopeClosers.top(); 90 | m_scopeClosers.pop(); 91 | Indent(os, closer.indentDelta); 92 | os << "\n"; 93 | WriteIndent(os, 0); 94 | os << closer.closeString; 95 | } 96 | 97 | void WriteHeaderGuard(std::ostream& os, const std::string& filePath) 98 | { 99 | std::string fileName = llvm::sys::path::filename(filePath).str(); 100 | boost::algorithm::replace_all(fileName, ".", "_"); 101 | boost::algorithm::replace_all(fileName, "-", "_"); 102 | boost::algorithm::replace_all(fileName, " ", "_"); 103 | boost::algorithm::to_upper(fileName); 104 | llvm::JamCRC crcCalc; 105 | crcCalc.update(llvm::ArrayRef(filePath.data(), filePath.size())); 106 | uint32_t fileHash = crcCalc.getCRC(); 107 | 108 | std::ostringstream str; 109 | str << "_" << fileName << "_" << fileHash; 110 | auto defineName = str.str(); 111 | 112 | os << "#ifndef " << defineName << "\n"; 113 | os << "#define " << defineName << "\n"; 114 | 115 | m_scopeClosers.push(ScopeCloser{0, "#endif // " + defineName + "\n"}); 116 | } 117 | 118 | void AddParams(const out::OutParams* params) 119 | { 120 | m_params.insert(params); 121 | } 122 | 123 | void RemoveParams(const out::OutParams* params) 124 | { 125 | m_params.erase(params); 126 | } 127 | 128 | private: 129 | template 130 | bool WriteParamValue(Sink&& sink) 131 | { 132 | std::string value; 133 | if (!FindParamValue(m_paramName, value)) 134 | value = m_paramName; 135 | 136 | std::streamsize amount = static_cast(value.size()); 137 | std::streamsize result = boost::iostreams::write(sink, value.data(), amount); 138 | return result == amount; 139 | } 140 | 141 | bool FindParamValue(const std::string& valueName, std::string& value) 142 | { 143 | for (auto& params : m_params) 144 | { 145 | auto p = params->find(valueName); 146 | if (p != params->end()) 147 | { 148 | value = p->second; 149 | return true; 150 | } 151 | } 152 | 153 | return false; 154 | } 155 | 156 | private: 157 | int m_indentLevel = 0; 158 | std::unordered_set m_params; 159 | State m_currentState = BypassChars; 160 | std::string m_paramName; 161 | char m_prevChar = 0; 162 | 163 | struct ScopeCloser 164 | { 165 | int indentDelta; 166 | std::string closeString; 167 | }; 168 | 169 | std::stack m_scopeClosers; 170 | }; 171 | 172 | CppSourceStream::CppSourceStream(std::ostream& os) 173 | { 174 | this->push(StreamController()); 175 | this->push(os); 176 | m_controller = this->component(0); 177 | } 178 | 179 | void CppSourceStream::WriteIndent(int indentDelta) 180 | { 181 | m_controller->WriteIndent(*this, indentDelta); 182 | } 183 | 184 | void CppSourceStream::Indent(int amout) 185 | { 186 | m_controller->Indent(*this, amout); 187 | } 188 | 189 | void CppSourceStream::EnterScope(const std::string &closer, int unindent) 190 | { 191 | m_controller->EnterScope(closer, unindent); 192 | } 193 | 194 | void CppSourceStream::ExitScope() 195 | { 196 | m_controller->ExitScope(*this); 197 | } 198 | 199 | void CppSourceStream::WriteHeaderGuard(const std::string &fileName) 200 | { 201 | m_controller->WriteHeaderGuard(*this, fileName); 202 | } 203 | 204 | void CppSourceStream::SetParams(const out::OutParams *params) 205 | { 206 | m_controller->AddParams(params); 207 | } 208 | 209 | void CppSourceStream::ResetParams(const out::OutParams *params) 210 | { 211 | this->flush(); 212 | m_controller->RemoveParams(params); 213 | } 214 | 215 | } // codegen 216 | -------------------------------------------------------------------------------- /tools/codegen/src/cpp_source_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef CPP_SOURCE_STREAM_H 2 | #define CPP_SOURCE_STREAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace codegen 12 | { 13 | class StreamController; 14 | 15 | namespace out 16 | { 17 | using OutParams = std::unordered_map; 18 | } 19 | 20 | class CppSourceStream : public boost::iostreams::filtering_ostream 21 | { 22 | public: 23 | CppSourceStream(std::ostream& os); 24 | 25 | void WriteIndent(int indentDelta = 0); 26 | void Indent(int amout); 27 | void EnterScope(const std::string& closer, int unindent); 28 | void ExitScope(); 29 | void WriteHeaderGuard(const std::string& fileName); 30 | void SetParams(const out::OutParams* params); 31 | void ResetParams(const out::OutParams *params); 32 | 33 | private: 34 | StreamController* m_controller; 35 | 36 | template 37 | friend auto& operator << (CppSourceStream& stream, R (*manip)(CppSourceStream& stream)) 38 | { 39 | return (*manip)(stream); 40 | } 41 | 42 | template 43 | friend auto operator << (CppSourceStream& stream, Val&& val) 44 | -> std::enable_if_t::value, CppSourceStream&> 45 | { 46 | static_cast(stream) << std::forward(val); 47 | return stream; 48 | } 49 | }; 50 | 51 | namespace out 52 | { 53 | 54 | namespace detail 55 | { 56 | template 57 | struct Manip 58 | { 59 | Fn fn; 60 | friend auto& operator << (CppSourceStream& s, const Manip& m) 61 | { 62 | return m.fn(s); 63 | } 64 | }; 65 | 66 | template 67 | auto MakeManip(Fn&& fn) 68 | { 69 | return Manip{std::forward(fn)}; 70 | } 71 | 72 | class ExpressionParams 73 | { 74 | public: 75 | ExpressionParams(const OutParams& p) 76 | : m_params(&p) 77 | { 78 | } 79 | 80 | ~ExpressionParams() 81 | { 82 | if (m_stream != nullptr) 83 | m_stream->ResetParams(m_params); 84 | } 85 | 86 | friend auto& operator << (CppSourceStream& s, const ExpressionParams& m) 87 | { 88 | m.m_stream = &s; 89 | s.SetParams(m.m_params); 90 | return s; 91 | } 92 | private: 93 | const OutParams* m_params; 94 | mutable CppSourceStream* m_stream = nullptr; 95 | 96 | }; 97 | } // detail 98 | 99 | inline CppSourceStream& new_line(CppSourceStream& s) 100 | { 101 | s << "\n"; 102 | s.WriteIndent(); 103 | return s; 104 | } 105 | 106 | inline auto new_line(int extra) 107 | { 108 | return detail::MakeManip([extra](CppSourceStream& s) -> CppSourceStream& { 109 | s << "\n"; 110 | s.WriteIndent(extra); 111 | return s; 112 | }); 113 | } 114 | 115 | inline CppSourceStream& indent(CppSourceStream& s) 116 | { 117 | s.Indent(+1); 118 | return s; 119 | } 120 | 121 | inline CppSourceStream& unindent(CppSourceStream& s) 122 | { 123 | s.Indent(-1); 124 | return s; 125 | } 126 | 127 | inline auto header_guard(const std::string& headerName) 128 | { 129 | return detail::MakeManip([headerName](CppSourceStream& s) -> CppSourceStream& { 130 | s.WriteHeaderGuard(headerName); 131 | return s; 132 | }); 133 | } 134 | 135 | inline auto scope_enter(const std::string& closer, int indent = 1) 136 | { 137 | return detail::MakeManip([closer, indent](CppSourceStream& s) -> CppSourceStream& { 138 | s.Indent(indent); 139 | s.EnterScope(closer, -indent); 140 | return s; 141 | }); 142 | } 143 | 144 | inline CppSourceStream& scope_exit(CppSourceStream& s) 145 | { 146 | s.ExitScope(); 147 | return s; 148 | } 149 | 150 | inline detail::ExpressionParams with_params(const OutParams& params) 151 | { 152 | return detail::ExpressionParams(params); 153 | } 154 | 155 | class ScopedParams 156 | { 157 | public: 158 | ScopedParams(CppSourceStream& os, OutParams* params) 159 | : m_stream(&os) 160 | , m_paramsPtr(params) 161 | { 162 | m_stream->SetParams(m_paramsPtr); 163 | } 164 | ScopedParams(CppSourceStream& os, OutParams&& params) 165 | : m_stream(&os) 166 | , m_params(std::move(params)) 167 | , m_paramsPtr(&m_params) 168 | { 169 | m_stream->SetParams(m_paramsPtr); 170 | } 171 | ScopedParams(ScopedParams&& params) 172 | : m_stream(params.m_stream) 173 | , m_params(std::move(params.m_params)) 174 | , m_paramsPtr(&m_params) 175 | { 176 | params.m_stream = nullptr; 177 | params.m_paramsPtr = nullptr; 178 | } 179 | ScopedParams(const ScopedParams&) = delete; 180 | 181 | ~ScopedParams() 182 | { 183 | if (m_stream != nullptr) 184 | m_stream->ResetParams(m_paramsPtr); 185 | } 186 | 187 | OutParams& GetParams() 188 | { 189 | return *m_paramsPtr; 190 | } 191 | 192 | auto& operator[](const std::string& key) 193 | { 194 | return (*m_paramsPtr)[key]; 195 | } 196 | 197 | private: 198 | CppSourceStream* m_stream; 199 | OutParams m_params; 200 | OutParams* m_paramsPtr; 201 | }; 202 | 203 | class StreamScope 204 | { 205 | public: 206 | StreamScope(std::string prefix, std::string suffix, int indent = 1) 207 | : m_scopePrefix(std::move(prefix)) 208 | , m_scopeSuffix(std::move(suffix)) 209 | , m_indentLevel(indent) 210 | { 211 | if (!m_scopePrefix.empty() && m_scopePrefix[0] == '\n') 212 | { 213 | m_prefixOnNewLine = true; 214 | m_scopePrefix.erase(m_scopePrefix.begin()); 215 | } 216 | 217 | if (!m_scopeSuffix.empty() && m_scopeSuffix[0] == '\n') 218 | { 219 | m_suffixOnNewLine = true; 220 | m_scopeSuffix.erase(m_scopeSuffix.begin()); 221 | } 222 | } 223 | 224 | ~StreamScope() 225 | { 226 | if (m_stream != nullptr) 227 | { 228 | m_stream->Indent(-m_indentLevel); 229 | if (m_suffixOnNewLine) 230 | (*m_stream) << new_line; 231 | 232 | (*m_stream) << m_scopeSuffix; 233 | } 234 | } 235 | 236 | private: 237 | std::string m_scopePrefix; 238 | std::string m_scopeSuffix; 239 | int m_indentLevel; 240 | mutable CppSourceStream* m_stream = nullptr; 241 | bool m_prefixOnNewLine = true; 242 | bool m_suffixOnNewLine = true; 243 | 244 | friend CppSourceStream& operator << (CppSourceStream& stream, const StreamScope& scope) 245 | { 246 | scope.m_stream = &stream; 247 | if (scope.m_prefixOnNewLine) 248 | stream << new_line; 249 | stream << scope.m_scopePrefix; 250 | stream.Indent(scope.m_indentLevel); 251 | return stream; 252 | } 253 | }; 254 | 255 | class BracedStreamScope : public StreamScope 256 | { 257 | public: 258 | BracedStreamScope(std::string bracePrefix, std::string braceSuffix, int indent = 1) 259 | : StreamScope("\n{", "\n}" + braceSuffix, indent) 260 | , m_bracePrefix(std::move(bracePrefix)) 261 | { 262 | } 263 | 264 | BracedStreamScope(std::string braceSuffix) 265 | : BracedStreamScope("", std::move(braceSuffix)) 266 | { 267 | } 268 | 269 | private: 270 | std::string m_bracePrefix; 271 | 272 | friend CppSourceStream& operator << (CppSourceStream& stream, const BracedStreamScope& scope) 273 | { 274 | stream << scope.m_bracePrefix; 275 | return stream << static_cast(scope); 276 | } 277 | }; 278 | } 279 | } // codegen 280 | #endif // CPP_SOURCE_STREAM_H 281 | -------------------------------------------------------------------------------- /tools/codegen/src/decls_reflection.h: -------------------------------------------------------------------------------- 1 | #ifndef DECLS_REFLECTION_H 2 | #define DECLS_REFLECTION_H 3 | 4 | #include "type_info.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | 13 | namespace reflection 14 | { 15 | 16 | struct ClassInfo; 17 | using ClassInfoPtr = std::shared_ptr; 18 | 19 | struct EnumInfo; 20 | using EnumInfoPtr = std::shared_ptr; 21 | 22 | struct NamespaceInfo; 23 | using NamespaceInfoPtr = std::shared_ptr; 24 | 25 | struct NamedDeclInfo 26 | { 27 | std::string name; 28 | std::string namespaceQualifier; 29 | std::string scopeSpecifier; 30 | 31 | std::string GetFullQualifiedScope(bool includeGlobalScope = true) const 32 | { 33 | std::string result; 34 | if (!namespaceQualifier.empty()) 35 | result = namespaceQualifier; 36 | 37 | const char* prefix = includeGlobalScope || !result.empty() ? "::" : ""; 38 | 39 | if (!scopeSpecifier.empty()) 40 | result += prefix + scopeSpecifier; 41 | 42 | return result; 43 | } 44 | std::string GetFullQualifiedName(bool includeGlobalScope = true) const 45 | { 46 | auto fqScope = GetFullQualifiedScope(); 47 | const char* prefix = includeGlobalScope || !fqScope.empty() ? "::" : ""; 48 | return !name.empty() ? fqScope + prefix + name : ""; 49 | } 50 | std::string GetScopedName() const 51 | { 52 | return scopeSpecifier.empty() ? name : scopeSpecifier + "::" + name; 53 | } 54 | }; 55 | 56 | struct SourceLocation 57 | { 58 | std::string fileName = ""; 59 | unsigned line = 0; 60 | unsigned column = 0; 61 | }; 62 | 63 | struct LocationInfo 64 | { 65 | SourceLocation location; 66 | }; 67 | 68 | struct MethodParamInfo 69 | { 70 | std::string name; 71 | TypeInfoPtr type; 72 | std::string fullDecl; 73 | 74 | const clang::ParmVarDecl* decl; 75 | }; 76 | 77 | enum class AccessType 78 | { 79 | Public, 80 | Protected, 81 | Private, 82 | Undefined 83 | }; 84 | 85 | struct MethodInfo : public NamedDeclInfo 86 | { 87 | SourceLocation declLocation; 88 | SourceLocation defLocation; 89 | std::vector params; 90 | std::string fullPrototype; 91 | TypeInfoPtr returnType; 92 | std::string returnTypeAsString; 93 | AccessType accessType = AccessType::Undefined; 94 | 95 | bool isConst = false; 96 | bool isVirtual = false; 97 | bool isPure = false; 98 | bool isNoExcept = false; 99 | bool isRVRef = false; 100 | bool isCtor = false; 101 | bool isDtor = false; 102 | bool isOperator = false; 103 | bool isImplicit = false; 104 | bool isDeleted = false; 105 | bool isStatic = false; 106 | 107 | const clang::CXXMethodDecl* decl; 108 | }; 109 | 110 | using MethodInfoPtr = std::shared_ptr; 111 | 112 | struct MemberInfo : public NamedDeclInfo, public LocationInfo 113 | { 114 | TypeInfo type; 115 | AccessType accessType = AccessType::Undefined; 116 | bool isStatic = false; 117 | 118 | const clang::FieldDecl* decl; 119 | }; 120 | 121 | using MemberInfoPtr = std::shared_ptr; 122 | 123 | struct ClassInfo : public NamedDeclInfo, public LocationInfo 124 | { 125 | struct BaseInfo 126 | { 127 | TypeInfo baseClass; 128 | AccessType accessType; 129 | bool isVirtual; 130 | }; 131 | 132 | struct InnerDeclInfo 133 | { 134 | using DeclType = boost::variant; 135 | 136 | DeclType innerDecl; 137 | AccessType acessType; 138 | }; 139 | 140 | std::vector baseClasses; 141 | std::vector members; 142 | std::vector methods; 143 | std::vector innerDecls; 144 | 145 | bool isTrivial = false; 146 | bool isAbstract = false; 147 | bool isUnion = false; 148 | 149 | const clang::CXXRecordDecl* decl; 150 | }; 151 | 152 | struct EnumItemInfo : public LocationInfo 153 | { 154 | std::string itemName; 155 | std::string itemValue; 156 | 157 | const clang::EnumConstantDecl* decl = nullptr; 158 | }; 159 | 160 | struct EnumInfo : public NamedDeclInfo, public LocationInfo 161 | { 162 | bool isScoped = false; 163 | std::vector items; 164 | 165 | const clang::EnumDecl* decl = nullptr; 166 | }; 167 | 168 | 169 | struct NamespaceInfo : public NamedDeclInfo 170 | { 171 | bool isRootNamespace = false; 172 | std::vector innerNamespaces; 173 | std::vector enums; 174 | std::vector classes; 175 | 176 | const clang::NamespaceDecl *decl = nullptr; 177 | }; 178 | 179 | class NamespacesTree 180 | { 181 | public: 182 | 183 | auto GetRootNamespace() const {return m_rootNamespace;} 184 | NamespaceInfoPtr GetNamespace(const clang::DeclContext* decl) 185 | { 186 | auto p = m_namespaces.find(decl); 187 | if (p != m_namespaces.end()) 188 | return p->second; 189 | 190 | if (decl->isTranslationUnit()) 191 | { 192 | NamespaceInfoPtr nsInfo = std::make_shared(); 193 | nsInfo->name = ""; 194 | nsInfo->namespaceQualifier = ""; 195 | nsInfo->scopeSpecifier = ""; 196 | nsInfo->isRootNamespace = true; 197 | m_namespaces[decl] = nsInfo; 198 | m_rootNamespace = nsInfo; 199 | return nsInfo; 200 | } 201 | 202 | const clang::NamespaceDecl* nsDecl = clang::NamespaceDecl::castFromDeclContext(decl); 203 | if (nsDecl == nullptr) 204 | return NamespaceInfoPtr(); 205 | 206 | const clang::DeclContext* parentContext = nullptr; 207 | do 208 | { 209 | parentContext = nsDecl->getParent(); 210 | } while (!parentContext->isNamespace() && !parentContext->isTranslationUnit()); 211 | 212 | auto parentNs = GetNamespace(parentContext); 213 | 214 | if (nsDecl->isAnonymousNamespace()) 215 | { 216 | m_namespaces[decl] = parentNs; 217 | return parentNs; 218 | } 219 | 220 | NamespaceInfoPtr nsInfo = std::make_shared(); 221 | nsInfo->name = nsDecl->getNameAsString(); 222 | nsInfo->namespaceQualifier = parentNs->GetFullQualifiedName(); 223 | nsInfo->scopeSpecifier = ""; 224 | nsInfo->decl = nsDecl; 225 | m_namespaces[decl] = nsInfo; 226 | parentNs->innerNamespaces.push_back(nsInfo); 227 | 228 | return nsInfo; 229 | } 230 | 231 | private: 232 | NamespaceInfoPtr m_rootNamespace; 233 | std::map m_namespaces; 234 | }; 235 | 236 | 237 | } 238 | 239 | #endif // DECLS_REFLECTION_H 240 | -------------------------------------------------------------------------------- /tools/codegen/src/enum2string_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "enum2string_generator.h" 2 | #include "options.h" 3 | #include "ast_reflector.h" 4 | #include "ast_utils.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | using namespace clang::ast_matchers; 11 | 12 | namespace codegen 13 | { 14 | namespace 15 | { 16 | DeclarationMatcher enumMatcher = 17 | enumDecl(isExpansionInMainFile()).bind("enum"); 18 | } 19 | 20 | Enum2StringGenerator::Enum2StringGenerator(const Options &opts) 21 | : BasicGenerator(opts) 22 | { 23 | 24 | } 25 | 26 | void Enum2StringGenerator::SetupMatcher(clang::ast_matchers::MatchFinder &finder, clang::ast_matchers::MatchFinder::MatchCallback *defaultCallback) 27 | { 28 | finder.addMatcher(enumMatcher, defaultCallback); 29 | } 30 | 31 | void Enum2StringGenerator::HandleMatch(const clang::ast_matchers::MatchFinder::MatchResult &matchResult) 32 | { 33 | if (const clang::EnumDecl* decl = matchResult.Nodes.getNodeAs("enum")) 34 | { 35 | reflection::AstReflector reflector(matchResult.Context); 36 | 37 | reflector.ReflectEnum(decl, &m_namespaces); 38 | } 39 | } 40 | 41 | void Enum2StringGenerator::WriteHeaderPreamble(CppSourceStream &hdrOs) 42 | { 43 | hdrOs << out::header_guard(m_options.outputHeaderName) << "\n"; 44 | 45 | // Include input files (directly, by path) 46 | for (auto fileName : m_options.inputFiles) 47 | { 48 | std::replace(fileName.begin(), fileName.end(), '\\', '/'); 49 | hdrOs << "#include \"" << fileName << "\"\n"; 50 | } 51 | 52 | WriteExtraHeaders(hdrOs); 53 | 54 | // Necessary library files 55 | hdrOs << "#include \n"; 56 | hdrOs << "#include \n"; 57 | hdrOs << "#include \n\n"; 58 | } 59 | 60 | void Enum2StringGenerator::WriteHeaderPostamble(CppSourceStream &hdrOs) 61 | { 62 | hdrOs << out::scope_exit; 63 | } 64 | 65 | namespace 66 | { 67 | out::ScopedParams MakeScopedParams(CppSourceStream &os, reflection::EnumInfoPtr enumDescr) 68 | { 69 | std::string scopeSpec = enumDescr->scopeSpecifier; 70 | std::string scopedName = scopeSpec + (scopeSpec.empty() ? "" : "::") + enumDescr->name; 71 | std::string fullQualifiedName = enumDescr->GetFullQualifiedName(false); 72 | 73 | return out::ScopedParams(os, { 74 | {"enumName", enumDescr->name}, 75 | {"enumScopedName", scopedName}, 76 | {"scopeQual", scopeSpec}, 77 | {"namespaceQual", enumDescr->namespaceQualifier}, 78 | {"enumFullQualifiedName", fullQualifiedName}, 79 | {"prefix", enumDescr->isScoped ? scopedName + "::" : scopeSpec + (scopeSpec.empty() ? "" : "::")} 80 | }); 81 | } 82 | 83 | } 84 | 85 | void Enum2StringGenerator::WriteHeaderContent(CppSourceStream &hdrOs) 86 | { 87 | std::vector enums; 88 | WriteNamespaceContents(hdrOs, m_namespaces.GetRootNamespace(), [this, &enums](CppSourceStream &os, reflection::NamespaceInfoPtr ns) { 89 | for (auto& enumInfo : ns->enums) 90 | { 91 | WriteEnumToStringConversion(os, enumInfo); 92 | WriteEnumFromStringConversion(os, enumInfo); 93 | enums.push_back(enumInfo); 94 | } 95 | }); 96 | 97 | hdrOs << "\n\n"; 98 | 99 | for (reflection::EnumInfoPtr enumInfo : enums) 100 | { 101 | auto scopedParams = MakeScopedParams(hdrOs, enumInfo); 102 | 103 | { 104 | hdrOs << out::new_line << "template<>"; 105 | out::BracedStreamScope body("inline const char* flex_lib::Enum2String($enumFullQualifiedName$ e)", "\n"); 106 | hdrOs << out::new_line << body; 107 | hdrOs << out::new_line << "return $namespaceQual$::$enumName$ToString(e);"; 108 | } 109 | { 110 | hdrOs << out::new_line << "template<>"; 111 | out::BracedStreamScope body("inline $enumFullQualifiedName$ flex_lib::String2Enum<$enumFullQualifiedName$>(const char* itemName)", "\n"); 112 | hdrOs << out::new_line << body; 113 | hdrOs << out::new_line << "return $namespaceQual$::StringTo$enumName$(itemName);"; 114 | } 115 | } 116 | { 117 | out::BracedStreamScope flNs("\nnamespace std", "\n\n", 0); 118 | hdrOs << out::new_line << flNs; 119 | 120 | for (reflection::EnumInfoPtr enumInfo : enums) 121 | { 122 | auto scopedParams = MakeScopedParams(hdrOs, enumInfo); 123 | 124 | out::BracedStreamScope body("inline std::string to_string($enumFullQualifiedName$ e)", "\n"); 125 | hdrOs << out::new_line << body; 126 | hdrOs << out::new_line << "return $namespaceQual$::$enumName$ToString(e);"; 127 | } 128 | } 129 | } 130 | 131 | // Enum item to string conversion writer 132 | void Enum2StringGenerator::WriteEnumToStringConversion(CppSourceStream &hdrOs, const reflection::EnumInfoPtr &enumDescr) 133 | { 134 | auto scopedParams = MakeScopedParams(hdrOs, enumDescr); 135 | 136 | out::BracedStreamScope fnScope("inline const char* $enumName$ToString($enumScopedName$ e)", "\n"); 137 | hdrOs << out::new_line << fnScope; 138 | { 139 | out::BracedStreamScope switchScope("switch (e)", "\n"); 140 | hdrOs << out::new_line << switchScope; 141 | out::OutParams innerParams; 142 | for (auto& i : enumDescr->items) 143 | { 144 | innerParams["itemName"] = i.itemName; 145 | hdrOs << out::with_params(innerParams) 146 | << out::new_line(-1) << "case $prefix$$itemName$:" 147 | << out::new_line << "return \"$itemName$\";"; 148 | } 149 | } 150 | hdrOs << out::new_line << "return \"Unknown Item\";"; 151 | } 152 | 153 | // String to enum conversion writer 154 | void Enum2StringGenerator::WriteEnumFromStringConversion(CppSourceStream &hdrOs, const reflection::EnumInfoPtr &enumDescr) 155 | { 156 | auto params = MakeScopedParams(hdrOs, enumDescr); 157 | 158 | out::BracedStreamScope fnScope("inline $enumScopedName$ StringTo$enumName$(const char* itemName)", "\n"); 159 | hdrOs << out::new_line << fnScope; 160 | { 161 | out::BracedStreamScope itemsScope("static std::pair items[] = ", ";\n"); 162 | hdrOs << out::new_line << itemsScope; 163 | 164 | out::OutParams& innerParams = params.GetParams(); 165 | auto items = enumDescr->items; 166 | std::sort(begin(items), end(items), [](auto& i1, auto& i2) {return i1.itemName < i2.itemName;}); 167 | for (auto& i : items) 168 | { 169 | innerParams["itemName"] = i.itemName; 170 | hdrOs << out::with_params(innerParams) << out::new_line << "{\"$itemName$\", $prefix$$itemName$},"; 171 | } 172 | } 173 | 174 | hdrOs << out::with_params(params.GetParams()) << R"( 175 | $enumScopedName$ result; 176 | if (!flex_lib::detail::String2Enum(itemName, items, result)) 177 | flex_lib::bad_enum_name::Throw(itemName, "$enumName$"); 178 | 179 | return result;)"; 180 | } 181 | } // codegen 182 | 183 | codegen::GeneratorPtr CreateEnum2StringGen(const codegen::Options& opts) 184 | { 185 | return std::make_unique(opts); 186 | } 187 | -------------------------------------------------------------------------------- /tools/codegen/src/enum2string_generator.h: -------------------------------------------------------------------------------- 1 | #ifndef ENUM2STRING_GENERATOR_H 2 | #define ENUM2STRING_GENERATOR_H 3 | 4 | #include "basic_generator.h" 5 | #include "decls_reflection.h" 6 | 7 | namespace codegen 8 | { 9 | class Enum2StringGenerator : public BasicGenerator 10 | { 11 | public: 12 | Enum2StringGenerator(const Options& opts); 13 | 14 | // GeneratorBase interface 15 | void SetupMatcher(clang::ast_matchers::MatchFinder &finder, clang::ast_matchers::MatchFinder::MatchCallback *defaultCallback) override; 16 | void HandleMatch(const clang::ast_matchers::MatchFinder::MatchResult &matchResult) override; 17 | 18 | // BasicGenerator interface 19 | protected: 20 | void WriteHeaderPreamble(CppSourceStream &hdrOs) override; 21 | void WriteHeaderContent(CppSourceStream &hdrOs) override; 22 | void WriteHeaderPostamble(CppSourceStream &hdrOs) override; 23 | 24 | private: 25 | 26 | void WriteEnumToStringConversion(CppSourceStream &hdrOs, const reflection::EnumInfoPtr& enumDescr); 27 | void WriteEnumFromStringConversion(CppSourceStream &hdrOs, const reflection::EnumInfoPtr& enumDescr); 28 | 29 | private: 30 | reflection::NamespacesTree m_namespaces; 31 | }; 32 | } // codegen 33 | 34 | #endif // ENUM2STRING_GENERATOR_H 35 | -------------------------------------------------------------------------------- /tools/codegen/src/generator_base.h: -------------------------------------------------------------------------------- 1 | #ifndef GENERATOR_BASE_H 2 | #define GENERATOR_BASE_H 3 | 4 | #include "options.h" 5 | 6 | #include 7 | 8 | namespace codegen 9 | { 10 | class GeneratorBase 11 | { 12 | public: 13 | virtual ~GeneratorBase() {} 14 | 15 | virtual void SetupMatcher(clang::ast_matchers::MatchFinder& finder, clang::ast_matchers::MatchFinder::MatchCallback* defaultCallback) = 0; 16 | virtual void OnCompilationStarted() = 0; 17 | virtual void HandleMatch(const clang::ast_matchers::MatchFinder::MatchResult& matchResult) = 0; 18 | virtual bool Validate() = 0; 19 | virtual bool GenerateOutput() = 0; 20 | }; 21 | 22 | using GeneratorPtr = std::unique_ptr; 23 | 24 | using GeneratorFactory = GeneratorPtr (*)(const Options& opts); 25 | } // codegen 26 | 27 | #endif // GENERATOR_BASE_H 28 | -------------------------------------------------------------------------------- /tools/codegen/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "options.h" 15 | #include "generator_base.h" 16 | 17 | using namespace llvm; 18 | 19 | extern codegen::GeneratorPtr CreateEnum2StringGen(const codegen::Options&); 20 | extern codegen::GeneratorPtr CreatePimplGen(const codegen::Options&); 21 | 22 | namespace 23 | { 24 | // Define code generation tool option category 25 | cl::OptionCategory CodeGenCategory("Code generator options"); 26 | 27 | // Define the generation mode 28 | cl::opt GenerationMode(cl::desc("Choose generation mode:"), 29 | cl::values( 30 | clEnumValN(codegen::GeneratorId::Enum2StringGen, "gen-enum2string" , "Enum2string conversion generation"), 31 | clEnumValN(codegen::GeneratorId::PimplGen, "gen-pimpl" , "Pimpl wrapper classes generation") 32 | ), cl::Required, cl::cat(CodeGenCategory)); 33 | 34 | // Define options for output file names 35 | // cl::opt OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename"), cl::cat(CodeGenCategory)); 36 | cl::opt OutputHeaderName("ohdr", cl::desc("Specify output header filename"), cl::value_desc("filename"), cl::cat(CodeGenCategory)); 37 | cl::opt OutputSourceName("osrc", cl::desc("Specify output source filename"), cl::value_desc("filename"), cl::cat(CodeGenCategory)); 38 | cl::opt FileToUpdateName("update", cl::desc("Specify source filename for code update"), cl::value_desc("filename"), cl::cat(CodeGenCategory)); 39 | cl::opt ShowClangErrors("show-clang-diag", cl::desc("Show clang diagnostic during file processing"), cl::value_desc("flag"), cl::init(false), cl::cat(CodeGenCategory)); 40 | cl::list ExtraHeaders("eh", cl::desc("Specify extra header files for include into generation result"), cl::value_desc("filename"), cl::ZeroOrMore, cl::cat(CodeGenCategory)); 41 | 42 | cl::opt LangStandart("std", cl::desc("Choose the standard conformance for the generation results:"), 43 | cl::values( 44 | clEnumValN(codegen::Standard::Auto, "auto" , "Automatic detection (default)"), 45 | clEnumValN(codegen::Standard::Cpp03, "c++03" , "C++ 2003 standard"), 46 | clEnumValN(codegen::Standard::Cpp11, "c++11" , "C++ 2011 standard"), 47 | clEnumValN(codegen::Standard::Cpp14, "c++14" , "C++ 2014 standard"), 48 | clEnumValN(codegen::Standard::Cpp17, "c++17" , "C++ 2017 standard") 49 | ), cl::Optional, cl::init(codegen::Standard::Auto), cl::cat(CodeGenCategory)); 50 | 51 | // Define common help message printer 52 | cl::extrahelp CommonHelp(clang::tooling::CommonOptionsParser::HelpMessage); 53 | // Define specific help message printer 54 | cl::extrahelp MoreHelp("\nCode generation tool help text..."); 55 | 56 | std::vector> GenFactories = { 57 | {codegen::GeneratorId::Enum2StringGen, CreateEnum2StringGen}, 58 | {codegen::GeneratorId::PimplGen, CreatePimplGen}, 59 | }; 60 | } 61 | 62 | namespace codegen 63 | { 64 | class MatchHandler : public clang::ast_matchers::MatchFinder::MatchCallback 65 | { 66 | public: 67 | MatchHandler(const Options& options, GeneratorBase* generator) 68 | : m_options(options) 69 | , m_generator(generator) 70 | { 71 | } 72 | 73 | void onStartOfTranslationUnit() 74 | { 75 | m_generator->OnCompilationStarted(); 76 | } 77 | 78 | void run(const clang::ast_matchers::MatchFinder::MatchResult& result) 79 | { 80 | m_generator->HandleMatch(result); 81 | } 82 | 83 | void onEndOfTranslationUnit() 84 | { 85 | if (!(m_hasErrors = !m_generator->Validate())) 86 | m_hasErrors = !m_generator->GenerateOutput(); 87 | } 88 | 89 | bool HasErrors() const {return m_hasErrors;} 90 | 91 | private: 92 | Options m_options; 93 | GeneratorBase* m_generator = nullptr; 94 | bool m_hasErrors = false; 95 | }; 96 | } // codegen 97 | 98 | int main(int argc, const char** argv) 99 | { 100 | using namespace clang::tooling; 101 | using namespace clang::ast_matchers; 102 | 103 | clang::IgnoringDiagConsumer diagConsumer; 104 | 105 | // Parse command line options and setup ClangTool 106 | CommonOptionsParser optionsParser(argc, argv, CodeGenCategory); 107 | ClangTool tool(optionsParser.getCompilations(), optionsParser.getSourcePathList()); 108 | 109 | codegen::Options options; 110 | options.generatorType = GenerationMode; 111 | options.inputFiles = optionsParser.getSourcePathList(); 112 | options.outputHeaderName = OutputHeaderName; 113 | options.outputSourceName = OutputSourceName; 114 | options.targetStandard = LangStandart; 115 | options.extraHeaders = ExtraHeaders; 116 | 117 | if (!ShowClangErrors) 118 | tool.setDiagnosticConsumer(&diagConsumer); 119 | 120 | auto genFactory = std::find_if(begin(GenFactories), end(GenFactories), [type = options.generatorType](auto& p) {return p.first == type && p.second != nullptr;}); 121 | 122 | if(genFactory == end(GenFactories)) 123 | { 124 | std::cerr << "Generator is not defined for generation mode '" << GenerationMode.ValueStr.str() << "'" << std::endl; 125 | return -1; 126 | } 127 | 128 | auto generator = genFactory->second(options); 129 | 130 | if (!generator) 131 | { 132 | std::cerr << "Failed to create generator for generation mode '" << GenerationMode.ValueStr.str() << "'" << std::endl; 133 | return -1; 134 | } 135 | 136 | codegen::MatchHandler handler(options, generator.get()); 137 | MatchFinder finder; 138 | generator->SetupMatcher(finder, &handler); 139 | 140 | 141 | // Run tool for the specified input files 142 | tool.run(newFrontendActionFactory(&finder).get()); 143 | if (handler.HasErrors()) 144 | return -1; 145 | 146 | return 0; 147 | } 148 | -------------------------------------------------------------------------------- /tools/codegen/src/options.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIONS_H 2 | #define OPTIONS_H 3 | 4 | #include 5 | #include 6 | 7 | namespace codegen 8 | { 9 | enum class Standard 10 | { 11 | Auto, 12 | Cpp03, 13 | Cpp11, 14 | Cpp14, 15 | Cpp17 16 | }; 17 | 18 | enum class GeneratorId 19 | { 20 | Unknown = -1, 21 | Enum2StringGen, 22 | PimplGen 23 | }; 24 | 25 | struct Options 26 | { 27 | GeneratorId generatorType = GeneratorId::Unknown; 28 | std::string outputHeaderName; 29 | std::string outputSourceName; 30 | std::vector inputFiles; 31 | std::vector extraHeaders; 32 | bool debugMode = false; 33 | Standard targetStandard = Standard::Auto; 34 | }; 35 | 36 | } // codegen 37 | 38 | #endif // OPTIONS_H 39 | -------------------------------------------------------------------------------- /tools/codegen/src/pimpl_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "pimpl_generator.h" 2 | #include "options.h" 3 | #include "ast_reflector.h" 4 | #include "ast_utils.h" 5 | #include "utils.h" 6 | 7 | #include 8 | 9 | #include 10 | 11 | using namespace clang::ast_matchers; 12 | 13 | namespace codegen 14 | { 15 | namespace 16 | { 17 | DeclarationMatcher pimplMatcher = cxxRecordDecl 18 | (isExpansionInMainFile(), isDerivedFrom("flex_lib::pimpl")).bind("pimpl"); 19 | } 20 | 21 | 22 | PimplGenerator::PimplGenerator(const codegen::Options &opts) 23 | : BasicGenerator(opts) 24 | { 25 | 26 | } 27 | 28 | void PimplGenerator::SetupMatcher(clang::ast_matchers::MatchFinder &finder, clang::ast_matchers::MatchFinder::MatchCallback *defaultCallback) 29 | { 30 | finder.addMatcher(pimplMatcher, defaultCallback); 31 | } 32 | 33 | void PimplGenerator::HandleMatch(const clang::ast_matchers::MatchFinder::MatchResult &matchResult) 34 | { 35 | if (const clang::CXXRecordDecl* decl = matchResult.Nodes.getNodeAs("pimpl")) 36 | { 37 | reflection::AstReflector reflector(matchResult.Context); 38 | 39 | auto ci = reflector.ReflectClass(decl, &m_namespaces); 40 | 41 | std::cout << "### Pimpl declaration found: " << ci->GetFullQualifiedName(false) << std::endl; 42 | } 43 | } 44 | 45 | bool PimplGenerator::Validate() 46 | { 47 | return true; 48 | } 49 | 50 | void PimplGenerator::WriteHeaderPreamble(CppSourceStream &hdrOs) 51 | { 52 | hdrOs << out::header_guard(m_options.outputHeaderName) << "\n"; 53 | 54 | // Include input files (directly, by path) 55 | for (auto fileName : m_options.inputFiles) 56 | { 57 | std::replace(fileName.begin(), fileName.end(), '\\', '/'); 58 | hdrOs << "#include \"" << fileName << "\"\n"; 59 | } 60 | 61 | WriteExtraHeaders(hdrOs); 62 | 63 | // Necessary library files 64 | hdrOs << "#include \n\n"; 65 | } 66 | 67 | void PimplGenerator::WriteHeaderPostamble(CppSourceStream &hdrOs) 68 | { 69 | hdrOs << out::scope_exit; 70 | } 71 | 72 | void PimplGenerator::WriteHeaderContent(CppSourceStream &hdrOs) 73 | { 74 | WriteNamespaceContents(hdrOs, m_namespaces.GetRootNamespace(), [this](CppSourceStream &os, reflection::NamespaceInfoPtr ns) { 75 | for (auto& classInfo : ns->classes) 76 | { 77 | WritePimplImplementation(os, classInfo); 78 | } 79 | }); 80 | } 81 | 82 | void PimplGenerator::WritePimplImplementation(CppSourceStream& os, reflection::ClassInfoPtr classInfo) 83 | { 84 | for (reflection::MethodInfoPtr methodInfo : classInfo->methods) 85 | { 86 | if (methodInfo->isCtor) 87 | WriteCtorImplementation(os, classInfo, methodInfo); 88 | else if (methodInfo->isDtor) 89 | { 90 | os << out::new_line; 91 | if (methodInfo->isNoExcept) 92 | os << methodInfo->GetScopedName() << "() noexcept = default;\n"; 93 | else 94 | os << methodInfo->GetScopedName() << "() = default;\n"; 95 | } 96 | else 97 | WriteMethodImplementation(os, classInfo, methodInfo); 98 | } 99 | } 100 | 101 | void PimplGenerator::WriteCtorImplementation(CppSourceStream& os, reflection::ClassInfoPtr classInfo, reflection::MethodInfoPtr methodInfo) 102 | { 103 | if (methodInfo->isImplicit) 104 | return; 105 | 106 | os << out::new_line << methodInfo->GetScopedName() << "("; 107 | WriteSeq(os, methodInfo->params, ", ", [](auto&& os, const reflection::MethodParamInfo& param) {os << param.fullDecl;}); 108 | os << ")"; 109 | if (methodInfo->isNoExcept) 110 | os << " noexcept"; 111 | os << out::new_line(+1) << ": pimpl(this"; 112 | bool isFirst = true; 113 | WriteSeq(os, methodInfo->params, ", ", [&isFirst](auto&& os, const reflection::MethodParamInfo& param) 114 | { 115 | if (isFirst) 116 | { 117 | isFirst = false; 118 | os << ", "; 119 | } 120 | reflection::TypeInfoPtr pType = param.type; 121 | 122 | if (pType->canBeMoved()) 123 | os << "std::move(" << param.name << ")"; 124 | else 125 | os << param.name; 126 | }); 127 | os << ")"; 128 | os << out::new_line << "{"; 129 | os << out::new_line << "}\n"; 130 | } 131 | 132 | void PimplGenerator::WriteMethodImplementation(CppSourceStream& os, reflection::ClassInfoPtr classInfo, reflection::MethodInfoPtr methodInfo) 133 | { 134 | if (methodInfo->isImplicit || methodInfo->isStatic) 135 | return; 136 | 137 | os << out::new_line << methodInfo->returnType->getPrintedName() << " " << methodInfo->GetScopedName() << "("; 138 | WriteSeq(os, methodInfo->params, ", ", [](auto&& os, const reflection::MethodParamInfo& param) {os << param.fullDecl;}); 139 | os << ")"; 140 | if (methodInfo->isConst) 141 | os << " const"; 142 | if (methodInfo->isNoExcept) 143 | os << " noexcept"; 144 | out::BracedStreamScope body("", "\n"); 145 | os << body; 146 | os << out::new_line; 147 | const reflection::BuiltinType* retType = methodInfo->returnType->getAsBuiltin(); 148 | if (retType == nullptr || retType->type != reflection::BuiltinType::Void) 149 | os << "return "; 150 | os << "m_impl->" << methodInfo->name << "("; 151 | WriteSeq(os, methodInfo->params, ", ", [classInfo](auto&& os, const reflection::MethodParamInfo& param) 152 | { 153 | std::string paramName = param.name; 154 | 155 | reflection::TypeInfoPtr pType = param.type; 156 | const reflection::RecordType* rType = pType->getAsRecord(); 157 | if (rType && rType->decl == classInfo->decl) 158 | paramName = "*" + param.name + (pType->getPointingLevels() != 0 ? "->" : ".") + "m_impl.get()"; 159 | 160 | if (pType->canBeMoved()) 161 | os << "std::move(" << paramName << ")"; 162 | else 163 | os << paramName; 164 | }); 165 | os << ");"; 166 | } 167 | 168 | void PimplGenerator::WriteSourcePreamble(CppSourceStream &srcOs) 169 | { 170 | 171 | } 172 | 173 | void PimplGenerator::WriteSourceContent(CppSourceStream &srcOs) 174 | { 175 | 176 | } 177 | 178 | void PimplGenerator::WriteSourcePostamble(CppSourceStream &srcOs) 179 | { 180 | 181 | } 182 | 183 | } // codegen 184 | 185 | codegen::GeneratorPtr CreatePimplGen(const codegen::Options& opts) 186 | { 187 | return std::make_unique(opts); 188 | } 189 | -------------------------------------------------------------------------------- /tools/codegen/src/pimpl_generator.h: -------------------------------------------------------------------------------- 1 | #ifndef PIMPL_GENERATOR_H 2 | #define PIMPL_GENERATOR_H 3 | 4 | #include "basic_generator.h" 5 | #include "decls_reflection.h" 6 | 7 | namespace codegen 8 | { 9 | class PimplGenerator : public BasicGenerator 10 | { 11 | public: 12 | PimplGenerator(const Options& opts); 13 | 14 | // GeneratorBase interface 15 | public: 16 | void SetupMatcher(clang::ast_matchers::MatchFinder &finder, clang::ast_matchers::MatchFinder::MatchCallback *defaultCallback) override; 17 | void HandleMatch(const clang::ast_matchers::MatchFinder::MatchResult &matchResult) override; 18 | bool Validate() override; 19 | 20 | // BasicGenerator interface 21 | protected: 22 | void WriteHeaderPreamble(CppSourceStream &hdrOs) override; 23 | void WriteHeaderContent(CppSourceStream &hdrOs) override; 24 | void WriteHeaderPostamble(CppSourceStream &hdrOs) override; 25 | void WriteSourcePreamble(CppSourceStream &srcOs) override; 26 | void WriteSourceContent(CppSourceStream &srcOs) override; 27 | void WriteSourcePostamble(CppSourceStream &srcOs) override; 28 | 29 | private: 30 | void WritePimplImplementation(CppSourceStream& os, reflection::ClassInfoPtr classInfo); 31 | void WriteCtorImplementation(CppSourceStream& os, reflection::ClassInfoPtr classInfo, reflection::MethodInfoPtr methodInfo); 32 | void WriteMethodImplementation(CppSourceStream& os, reflection::ClassInfoPtr classInfo, reflection::MethodInfoPtr methodInfo); 33 | 34 | private: 35 | reflection::NamespacesTree m_namespaces; 36 | }; 37 | } // codegen 38 | 39 | #endif // PIMPL_GENERATOR_H 40 | -------------------------------------------------------------------------------- /tools/codegen/src/type_info.h: -------------------------------------------------------------------------------- 1 | #ifndef TYPE_INFO_H 2 | #define TYPE_INFO_H 3 | 4 | #include "utils.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace reflection 12 | { 13 | class TypeInfo; 14 | using TypeInfoPtr = std::shared_ptr; 15 | 16 | struct NoType 17 | { 18 | }; 19 | 20 | struct BuiltinType 21 | { 22 | enum Types 23 | { 24 | Unspecified, 25 | Void, 26 | Bool, 27 | Char, 28 | WChar, 29 | Char16, 30 | Char32, 31 | Short, 32 | Int, 33 | Long, 34 | LongLong, 35 | Float, 36 | Double, 37 | LongDouble, 38 | Nullptr, 39 | Extended 40 | }; 41 | 42 | enum SignType 43 | { 44 | Signed, 45 | Unsigned, 46 | NoSign 47 | }; 48 | 49 | Types type = Unspecified; 50 | SignType isSigned = NoSign; 51 | int bits = 0; 52 | clang::BuiltinType::Kind kind = clang::BuiltinType::UnknownAny; 53 | const clang::BuiltinType* typeInfo = nullptr; 54 | }; 55 | 56 | struct RecordType 57 | { 58 | const clang::RecordDecl* decl = nullptr; 59 | }; 60 | 61 | struct TemplateType 62 | { 63 | enum TplArgKind 64 | { 65 | UnknownTplArg, 66 | NullTplArg, 67 | NullPtrTplArg, 68 | TemplateTplArg, 69 | TemplateExpansionTplArg, 70 | PackTplArg 71 | }; 72 | 73 | struct GenericArg 74 | { 75 | GenericArg(TplArgKind k = UnknownTplArg) 76 | : kind(k) 77 | { 78 | } 79 | 80 | TplArgKind kind; 81 | }; 82 | 83 | using TplArg = boost::variant; 84 | std::vector arguments; 85 | TypeInfoPtr aliasedType; 86 | const clang::NamedDecl* decl; 87 | 88 | auto GetTypeArg(int idx) const 89 | { 90 | const TypeInfoPtr* result = boost::get(&arguments[idx]); 91 | return result ? *result : TypeInfoPtr(); 92 | } 93 | }; 94 | 95 | struct WellKnownType : TemplateType 96 | { 97 | enum Types 98 | { 99 | StdArray, 100 | StdString, 101 | StdWstring, 102 | StdVector, 103 | StdList, 104 | StdDeque, 105 | StdMap, 106 | StdSet, 107 | StdUnorderedMap, 108 | StdUnorderedSet, 109 | StdSharedPtr, 110 | StdUniquePtr, 111 | StdOptional, 112 | BoostOptional, 113 | BoostVariant 114 | }; 115 | 116 | Types type = StdString; 117 | }; 118 | 119 | struct ArrayType 120 | { 121 | std::vector dims; 122 | TypeInfoPtr itemType; 123 | }; 124 | 125 | struct EnumType 126 | { 127 | const clang::EnumDecl* decl; 128 | }; 129 | 130 | class TypeInfo 131 | { 132 | public: 133 | using Type = boost::variant; 134 | 135 | TypeInfo(); 136 | 137 | const auto& GetType() {return m_type;} 138 | auto getAsBuiltin() const 139 | { 140 | return boost::get(&m_type); 141 | } 142 | auto getAsRecord() const 143 | { 144 | return boost::get(&m_type); 145 | } 146 | auto getAsTemplate() const 147 | { 148 | return boost::get(&m_type); 149 | } 150 | auto getAsWellKnownType() const 151 | { 152 | return boost::get(&m_type); 153 | } 154 | auto getAsArrayType() const 155 | { 156 | return boost::get(&m_type); 157 | } 158 | auto getAsEnumType() const 159 | { 160 | return boost::get(&m_type); 161 | } 162 | auto isNoType() const 163 | { 164 | return boost::get(&m_type) != nullptr; 165 | } 166 | 167 | bool getIsConst() const 168 | { 169 | return m_isConst; 170 | } 171 | bool getIsVolatile() const 172 | { 173 | return m_isVolatile; 174 | } 175 | bool getIsReference() const 176 | { 177 | return m_isReference; 178 | } 179 | bool getIsRVReference() const 180 | { 181 | return m_isRVReference; 182 | } 183 | int getPointingLevels() const 184 | { 185 | return m_pointingLevels; 186 | } 187 | std::string getDeclaredName() const 188 | { 189 | return m_declaredName; 190 | } 191 | std::string getScopedName() const 192 | { 193 | return m_scopedName; 194 | } 195 | std::string getFullQualifiedName() const 196 | { 197 | return m_fullQualifiedName; 198 | } 199 | std::string getPrintedName() const 200 | { 201 | return m_printedName; 202 | } 203 | const clang::Type* getTypeDecl() const 204 | { 205 | return m_typeDecl; 206 | } 207 | bool canBeMoved() const 208 | { 209 | struct Visitor : public boost::static_visitor 210 | { 211 | Visitor(const TypeInfo* ti) : m_type(ti) {} 212 | 213 | bool operator() (const NoType&) const {return false;} 214 | bool operator() (const BuiltinType&) const {return false;} 215 | bool operator() (const ArrayType&) const {return false;} 216 | bool operator() (const EnumType&) const {return false;} 217 | 218 | bool operator() (const RecordType&) const 219 | { 220 | if (m_type->m_isRVReference) 221 | return true; 222 | 223 | if (m_type->m_isConst) 224 | return false; 225 | 226 | if (m_type->m_pointingLevels != 0) 227 | return false; 228 | // clang::CXXRecordDecl 229 | return true; 230 | } 231 | 232 | bool operator() (const TemplateType&) const 233 | { 234 | if (m_type->m_isRVReference) 235 | return true; 236 | 237 | if (m_type->m_isConst || m_type->m_isReference) 238 | return false; 239 | 240 | if (m_type->m_pointingLevels != 0) 241 | return false; 242 | // clang::CXXRecordDecl 243 | return true; 244 | } 245 | 246 | const TypeInfo* m_type; 247 | }; 248 | 249 | return boost::apply_visitor(Visitor(this), m_type); 250 | } 251 | 252 | static TypeInfoPtr Create(const clang::QualType& qt, const clang::ASTContext* astContext); 253 | 254 | private: 255 | bool m_isConst = false; 256 | bool m_isVolatile = false; 257 | bool m_isReference = false; 258 | bool m_isRVReference = false; 259 | int m_pointingLevels = 0; 260 | std::string m_declaredName; 261 | std::string m_scopedName; 262 | std::string m_fullQualifiedName; 263 | std::string m_printedName; 264 | Type m_type; 265 | const clang::Type* m_typeDecl; 266 | 267 | friend class TypeUnwrapper; 268 | 269 | friend std::ostream& operator << (std::ostream& os, const TypeInfoPtr& tp) 270 | { 271 | os << "(" << tp->m_printedName << ")-" << tp->m_type; 272 | const char* suffix = " "; 273 | auto print = [&os, &suffix](bool flag, auto msg) 274 | { 275 | if (flag) 276 | { 277 | os << suffix << msg; 278 | suffix = ", "; 279 | } 280 | }; 281 | 282 | print(tp->m_isConst, "const"); 283 | print(tp->m_isVolatile, "volatile"); 284 | print(tp->m_isReference, "&"); 285 | print(tp->m_isRVReference, "&&"); 286 | std::string pointers; 287 | for (int n = 0; n < tp->m_pointingLevels; ++ n) 288 | pointers += "*"; 289 | print(tp->m_pointingLevels != 0, pointers); 290 | return os; 291 | } 292 | }; 293 | 294 | inline std::ostream& operator << (std::ostream& os, const NoType& tp) 295 | { 296 | os << "NOTYPE"; 297 | return os; 298 | } 299 | 300 | inline std::ostream& operator << (std::ostream& os, const BuiltinType& tp) 301 | { 302 | os << "BUILTIN[type=" << (int)tp.type << ", bits=" << tp.bits << ", isSigned=" << (int)tp.isSigned << ", kind=" << (int)tp.kind << "]"; 303 | return os; 304 | } 305 | 306 | inline std::ostream& operator << (std::ostream& os, const RecordType& tp) 307 | { 308 | os << "RECORD[" << tp.decl->getQualifiedNameAsString() << "]"; 309 | return os; 310 | } 311 | 312 | inline std::ostream& operator << (std::ostream& os, const TemplateType::GenericArg& ga) 313 | { 314 | os << "GENERIC(" << ga.kind << ")"; 315 | return os; 316 | } 317 | 318 | inline std::ostream& operator << (std::ostream& os, const TemplateType& tp) 319 | { 320 | os << "TEMPLATE[" << tp.decl->getQualifiedNameAsString() << "<"; 321 | WriteSeq(os, tp.arguments); 322 | os << ">]"; 323 | return os; 324 | } 325 | 326 | inline std::ostream& operator << (std::ostream& os, const WellKnownType& tp) 327 | { 328 | os << "WELLKNOWN[type=" << tp.type << "]"; 329 | return os; 330 | } 331 | 332 | inline std::ostream& operator << (std::ostream& os, const ArrayType& tp) 333 | { 334 | os << "ARRAY[type=" 335 | << tp.itemType 336 | << ", dims={"; 337 | WriteSeq(os, tp.dims); 338 | os << "}]"; 339 | return os; 340 | } 341 | 342 | inline std::ostream& operator << (std::ostream& os, const EnumType& tp) 343 | { 344 | os << "ENUM[" << tp.decl->getQualifiedNameAsString() << "]"; 345 | return os; 346 | } 347 | 348 | } // reflection 349 | 350 | #endif // TYPE_INFO_H 351 | -------------------------------------------------------------------------------- /tools/codegen/src/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct IntegerValue 9 | { 10 | bool isSigned = false; 11 | union 12 | { 13 | uint64_t uintValue; 14 | int64_t intValue; 15 | }; 16 | 17 | uint64_t AsUnsigned() const {return uintValue;} 18 | int64_t AsSigned() const {return intValue;} 19 | 20 | template 21 | auto GetAs() -> std::enable_if_t::value, T> 22 | { 23 | return static_cast(intValue); 24 | } 25 | 26 | template 27 | auto GetAs() -> std::enable_if_t::value, T> 28 | { 29 | return static_cast(uintValue); 30 | } 31 | }; 32 | 33 | inline IntegerValue ConvertAPSInt(llvm::APSInt intValue) 34 | { 35 | IntegerValue result; 36 | result.isSigned = intValue.isSigned(); 37 | result.intValue = intValue.getExtValue(); 38 | 39 | return result; 40 | } 41 | 42 | inline IntegerValue ConvertAPInt(llvm::APInt intValue) 43 | { 44 | IntegerValue result; 45 | result.isSigned = false; 46 | result.uintValue = intValue.getZExtValue(); 47 | 48 | return result; 49 | } 50 | 51 | template 52 | void WriteSeq(std::ostream& os, Seq&& seq, std::string delim, Fn&& ftor) 53 | { 54 | bool isFirst = true; 55 | for (auto& i : seq) 56 | { 57 | if (isFirst) 58 | isFirst = false; 59 | else 60 | os << delim; 61 | 62 | ftor(os, i); 63 | } 64 | } 65 | 66 | template 67 | void WriteSeq(std::ostream& os, Seq&& seq, std::string delim = ", ") 68 | { 69 | WriteSeq(os, std::forward(seq), std::move(delim), [](auto&& os, auto&& i) {os << i;}); 70 | } 71 | 72 | #endif // UTILS_H 73 | -------------------------------------------------------------------------------- /tools/codegen/test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(enum2string) 2 | add_subdirectory(pimpl) 3 | -------------------------------------------------------------------------------- /tools/codegen/test/enum2string/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (enum2string_codegen_tests) 2 | 3 | include (collect_sources) 4 | 5 | CollectSources(Sources Headers ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | set (CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen) 8 | 9 | file (MAKE_DIRECTORY ${CODEGEN_DIR}/generated) 10 | 11 | include_directories( 12 | ${CODEGEN_DIR} 13 | ) 14 | 15 | set (ENUM_CONV_FILE ${CODEGEN_DIR}/generated/enum_conv_gen.h) 16 | 17 | add_custom_command(OUTPUT ${ENUM_CONV_FILE} 18 | COMMAND $ -gen-enum2string -ohdr ${ENUM_CONV_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/test_enums.h -- clang-cl -std=c++14 -x c++ ${CMAKE_CXX_FLAGS} 19 | MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/test_enums.h 20 | DEPENDS ${CODEGEN_BIN_NAME} 21 | COMMENT "Generating enum2string converters for ${CMAKE_CURRENT_SOURCE_DIR}/test_enums.h" 22 | ) 23 | 24 | add_executable(${PROJECT_NAME} 25 | ${Sources} 26 | ${Headers} 27 | ${ENUM_CONV_FILE} 28 | ) 29 | 30 | target_link_libraries(${PROJECT_NAME} ${GTEST_BOTH_LIBRARIES} flex_lib) 31 | 32 | add_test(${PROJECT_NAME} ${PROJECT_NAME}) 33 | -------------------------------------------------------------------------------- /tools/codegen/test/enum2string/enum2string.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include "test_enums.h" 5 | 6 | TEST(Enum2String, ConvertToString_Successfull) 7 | { 8 | EXPECT_STREQ("Item1", Enum1ToString(Item1)); 9 | EXPECT_STREQ("Item2", Enum1ToString(Item2)); 10 | EXPECT_STREQ("Item3", Enum1ToString(Item3)); 11 | 12 | EXPECT_STREQ("Item1", Enum2ToString(Enum2::Item1)); 13 | EXPECT_STREQ("Item2", Enum2ToString(Enum2::Item2)); 14 | EXPECT_STREQ("Item3", Enum2ToString(Enum2::Item3)); 15 | } 16 | 17 | TEST(Enum2String, ConvertToString_Failed) 18 | { 19 | EXPECT_STREQ("Unknown Item", Enum1ToString(static_cast(123))); 20 | } 21 | 22 | TEST(Enum2String, ConvertFromString_Successfull) 23 | { 24 | EXPECT_EQ(Item1, StringToEnum1("Item1")); 25 | EXPECT_EQ(Item2, StringToEnum1("Item2")); 26 | EXPECT_EQ(Item3, StringToEnum1("Item3")); 27 | 28 | EXPECT_EQ(Enum2::Item1, StringToEnum2("Item1")); 29 | EXPECT_EQ(Enum2::Item2, StringToEnum2("Item2")); 30 | EXPECT_EQ(Enum2::Item3, StringToEnum2("Item3")); 31 | } 32 | 33 | TEST(Enum2String, ConvertFromString_Failed) 34 | { 35 | EXPECT_THROW(StringToEnum2("Unspecified Item"), flex_lib::bad_enum_name); 36 | } 37 | 38 | int main(int argc, char* argv[]) 39 | { 40 | testing::InitGoogleTest(&argc, argv); 41 | return RUN_ALL_TESTS(); 42 | } 43 | 44 | -------------------------------------------------------------------------------- /tools/codegen/test/enum2string/test_enums.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_ENUMS_H 2 | #define TEST_ENUMS_H 3 | 4 | enum Enum1 5 | { 6 | Item1, 7 | Item2, 8 | Item3 9 | }; 10 | 11 | enum class Enum2 12 | { 13 | Item3, 14 | Item2, 15 | Item1 16 | }; 17 | namespace 18 | { 19 | enum TestAnonEnum1 20 | { 21 | ItemAn1, 22 | ItemAn2, 23 | ItemAn3 24 | }; 25 | } 26 | 27 | namespace TestNs1 28 | { 29 | enum TestNs1Enum1 30 | { 31 | Item1, 32 | Item2, 33 | Item3 34 | }; 35 | 36 | namespace 37 | { 38 | enum TestNs1AnonEnum1 39 | { 40 | ItemAn1, 41 | ItemAn2, 42 | ItemAn3 43 | }; 44 | } 45 | 46 | inline namespace hidden 47 | { 48 | enum TestNs1HiddenEnum1 49 | { 50 | ItemInl1, 51 | ItemInl2, 52 | ItemInl3 53 | }; 54 | } 55 | 56 | struct Struct 57 | { 58 | enum TestNs1StructEnum1 59 | { 60 | Item1, 61 | Item2, 62 | Item3 63 | }; 64 | }; 65 | } // TestNs1 66 | 67 | #endif // TEST_ENUMS_H 68 | -------------------------------------------------------------------------------- /tools/codegen/test/pimpl/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project (pimpl_codegen_tests) 2 | 3 | include (collect_sources) 4 | 5 | CollectSources(Sources Headers ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) 6 | 7 | set (CODEGEN_DIR ${CMAKE_CURRENT_BINARY_DIR}/codegen) 8 | 9 | file (MAKE_DIRECTORY ${CODEGEN_DIR}/generated) 10 | 11 | include_directories( 12 | ${CODEGEN_DIR} 13 | ) 14 | 15 | set (PIMPL_GEN_FILE ${CODEGEN_DIR}/generated/pimpl_gen.cpp) 16 | 17 | add_custom_command(OUTPUT ${PIMPL_GEN_FILE} 18 | COMMAND $ -gen-pimpl -ohdr ${PIMPL_GEN_FILE} -eh ${CMAKE_CURRENT_SOURCE_DIR}/test_pimpl_impl.h ${CMAKE_CURRENT_SOURCE_DIR}/test_pimpl.h -- clang-cl -std=c++14 -x c++ ${CMAKE_CXX_FLAGS} -I ${FLEX_LIB_INCLUDE_ROOT} 19 | MAIN_DEPENDENCY ${CMAKE_CURRENT_SOURCE_DIR}/test_pimpl.h 20 | DEPENDS ${CODEGEN_BIN_NAME} 21 | COMMENT "Generating pimpl default implementation for ${CMAKE_CURRENT_SOURCE_DIR}/test_pimpl.h" 22 | ) 23 | 24 | add_executable(${PROJECT_NAME} 25 | ${Sources} 26 | ${Headers} 27 | ${PIMPL_GEN_FILE} 28 | ) 29 | 30 | target_link_libraries(${PROJECT_NAME} GTest::GTest GTest::Main flex_lib) 31 | 32 | add_test(${PROJECT_NAME} ${PROJECT_NAME}) 33 | -------------------------------------------------------------------------------- /tools/codegen/test/pimpl/pimpl_gen_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "test_pimpl.h" 5 | 6 | #include 7 | #include 8 | 9 | // #include 10 | 11 | TEST(PimplGen, StrConstructor_Successfull) 12 | { 13 | TestPimpl pimpl("1234"); 14 | 15 | EXPECT_EQ("1234", pimpl.GetString()); 16 | } 17 | 18 | TEST(PimplGen, IntConstructor_Successfull) 19 | { 20 | TestPimpl pimpl(1234); 21 | 22 | EXPECT_EQ(1234, pimpl.GetNumber()); 23 | } 24 | 25 | TEST(PimplGen, ArraySet_Successfull) 26 | { 27 | unsigned numbers[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 28 | TestPimpl pimpl(1234); 29 | 30 | pimpl.SetGeneratedValues(numbers); 31 | 32 | auto vals = pimpl.GetGeneratedValues(); 33 | auto srcBeg = numbers; 34 | auto srcEnd = numbers + 10; 35 | auto dstBeg = vals.begin(); 36 | auto dstEnd = vals.end(); 37 | 38 | auto itPair = std::mismatch(srcBeg, srcEnd, dstBeg, dstEnd); 39 | EXPECT_TRUE(itPair.first == srcEnd); 40 | EXPECT_TRUE(itPair.second == dstEnd); 41 | } 42 | 43 | TEST(PimplGen, MoveOperations_Successfull) 44 | { 45 | TestMoveable moveable; 46 | auto srcObjPtr = moveable.GetObject(); 47 | 48 | TestPimpl pimpl(std::move(moveable)); 49 | 50 | auto destObjPtr = pimpl.GetMoveablePtr(); 51 | 52 | EXPECT_EQ(*srcObjPtr, *destObjPtr); 53 | EXPECT_EQ(srcObjPtr, destObjPtr); 54 | } 55 | -------------------------------------------------------------------------------- /tools/codegen/test/pimpl/test_pimpl.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_ENUMS_H 2 | #define TEST_ENUMS_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | class TestPimplImpl; 10 | 11 | enum PimplMode 12 | { 13 | NormalMode, 14 | AbnormalMode 15 | }; 16 | 17 | class TestMoveable 18 | { 19 | public: 20 | TestMoveable(int value = 10) 21 | : m_object(new int(value)) 22 | { 23 | } 24 | 25 | const int* GetObject() const {return m_object.get();} 26 | 27 | private: 28 | std::unique_ptr m_object; 29 | }; 30 | 31 | class TestPimpl : flex_lib::pimpl 32 | { 33 | public: 34 | explicit TestPimpl(uint32_t number = 0); 35 | explicit TestPimpl(std::string number); 36 | explicit TestPimpl(TestMoveable&& obj) noexcept; 37 | ~TestPimpl() noexcept; 38 | 39 | const std::string GetString() const; 40 | const uint32_t GetNumber() const; 41 | void SetGeneratedValues(unsigned values[10]); 42 | const std::array GetGeneratedValues() const; 43 | void ResetValues(int num, std::string str); 44 | PimplMode GetCurrentMode() const; 45 | const int* GetMoveablePtr() const noexcept; 46 | 47 | bool operator == (const TestPimpl& other) const; 48 | }; 49 | 50 | #endif // TEST_ENUMS_H 51 | -------------------------------------------------------------------------------- /tools/codegen/test/pimpl/test_pimpl_impl.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_PIMPL_IMPL_H 2 | #define TEST_PIMPL_IMPL_H 3 | 4 | #include "test_pimpl.h" 5 | 6 | #include 7 | #include 8 | 9 | class TestPimpl; 10 | 11 | class TestPimplImpl 12 | { 13 | public: 14 | TestPimplImpl(TestPimpl*, uint32_t number) 15 | : m_intNumber(number) 16 | { 17 | } 18 | 19 | TestPimplImpl(TestPimpl*, std::string number) 20 | : m_strNumber(number) 21 | { 22 | } 23 | 24 | TestPimplImpl(TestPimpl*, TestMoveable&& moveable) 25 | : m_moveableObj(std::move(moveable)) 26 | { 27 | } 28 | 29 | const std::string GetString() const 30 | { 31 | return m_strNumber; 32 | } 33 | const uint32_t GetNumber() const 34 | { 35 | return m_intNumber; 36 | } 37 | void SetGeneratedValues(unsigned values[10]) 38 | { 39 | std::copy(values, values + 10, begin(m_values)); 40 | } 41 | const std::array GetGeneratedValues() const 42 | { 43 | return m_values; 44 | } 45 | void ResetValues(int num, std::string str) 46 | { 47 | m_intNumber = num; 48 | m_strNumber = str; 49 | } 50 | 51 | PimplMode GetCurrentMode() const 52 | { 53 | return m_curMode; 54 | } 55 | const int* GetMoveablePtr() const 56 | { 57 | return m_moveableObj.GetObject(); 58 | } 59 | 60 | bool operator == (const TestPimplImpl& pimpl) const 61 | { 62 | return m_intNumber == pimpl.m_intNumber; 63 | } 64 | 65 | private: 66 | uint32_t m_intNumber; 67 | std::string m_strNumber; 68 | std::array m_values; 69 | PimplMode m_curMode = AbnormalMode; 70 | TestMoveable m_moveableObj = TestMoveable(5); 71 | }; 72 | 73 | #endif // TEST_PIMPL_IMPL_H 74 | --------------------------------------------------------------------------------