mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-15 11:52:08 +07:00
114
.ci/build_singles.py
Executable file
114
.ci/build_singles.py
Executable file
@@ -0,0 +1,114 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
EMPTY_MATCHER = re.compile(r'^\s*$')
|
||||
C_COMMENT_MATCHER = re.compile(r'^/\*.*\*/', re.S)
|
||||
|
||||
USER_INCLUDE_MATCHER = re.compile(r'#\s*include\s*\"(.*)\"')
|
||||
SYSTEM_INCLUDE_MATCHER = re.compile(r'#\s*include\s*<(.*)>')
|
||||
PRAGMA_ONCE_MATCHER = re.compile(r'#\s*pragma\s+once')
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
def CollectLicenseComment(headerPath):
|
||||
with open(headerPath, "r") as headerStream:
|
||||
headerContent = headerStream.read().strip()
|
||||
commentMatch = re.match(C_COMMENT_MATCHER, headerContent)
|
||||
return commentMatch.group() if commentMatch else ""
|
||||
|
||||
def CollectSystemIncludes(headerPath, parsedHeaders = set()):
|
||||
with open(headerPath, "r") as headerStream:
|
||||
headerContent = headerStream.read().strip()
|
||||
|
||||
if PRAGMA_ONCE_MATCHER.search(headerContent) and headerPath in parsedHeaders:
|
||||
return set()
|
||||
|
||||
headerIncludes = set()
|
||||
|
||||
parsedHeaders.add(headerPath)
|
||||
headerLines = headerContent.split('\n')
|
||||
|
||||
for headerLine in headerLines:
|
||||
includeMatch = USER_INCLUDE_MATCHER.findall(headerLine)
|
||||
if includeMatch:
|
||||
internalHeaderPath = os.path.abspath(os.path.join(os.path.dirname(headerPath), includeMatch[0]))
|
||||
headerIncludes = headerIncludes.union(CollectSystemIncludes(internalHeaderPath, parsedHeaders))
|
||||
includeMatch = SYSTEM_INCLUDE_MATCHER.findall(headerLine)
|
||||
if includeMatch:
|
||||
headerIncludes.add(includeMatch[0])
|
||||
|
||||
return headerIncludes
|
||||
|
||||
def ParseHeader(headerPath, parsedHeaders = set()):
|
||||
with open(headerPath, "r") as headerStream:
|
||||
headerContent = headerStream.read().strip()
|
||||
headerContent = re.sub(C_COMMENT_MATCHER, '', headerContent)
|
||||
|
||||
if PRAGMA_ONCE_MATCHER.search(headerContent) and headerPath in parsedHeaders:
|
||||
return ""
|
||||
|
||||
parsedHeaders.add(headerPath)
|
||||
headerLines = headerContent.split('\n')
|
||||
|
||||
outputContent = ""
|
||||
shouldSkipNextEmptyLines = True
|
||||
|
||||
for headerLine in headerLines:
|
||||
if EMPTY_MATCHER.match(headerLine) and shouldSkipNextEmptyLines:
|
||||
continue
|
||||
|
||||
if PRAGMA_ONCE_MATCHER.match(headerLine):
|
||||
shouldSkipNextEmptyLines = True
|
||||
continue
|
||||
|
||||
includeMatch = USER_INCLUDE_MATCHER.findall(headerLine)
|
||||
if includeMatch:
|
||||
internalHeaderPath = os.path.abspath(os.path.join(os.path.dirname(headerPath), includeMatch[0]))
|
||||
internalHeaderContent = ParseHeader(internalHeaderPath, parsedHeaders)
|
||||
|
||||
outputContent += internalHeaderContent
|
||||
shouldSkipNextEmptyLines = True
|
||||
continue
|
||||
|
||||
includeMatch = SYSTEM_INCLUDE_MATCHER.findall(headerLine)
|
||||
if includeMatch:
|
||||
shouldSkipNextEmptyLines = True
|
||||
continue
|
||||
|
||||
shouldSkipNextEmptyLines = False
|
||||
outputContent += "{}\n".format(headerLine)
|
||||
|
||||
return "{}\n".format(outputContent)
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
inputHeaderPath = os.path.abspath(sys.argv[1])
|
||||
outputHeaderPath = os.path.abspath(sys.argv[2])
|
||||
|
||||
os.makedirs(os.path.dirname(outputHeaderPath), exist_ok=True)
|
||||
|
||||
with open(outputHeaderPath, "w") as outputHeaderStream:
|
||||
licenseComment = CollectLicenseComment(inputHeaderPath)
|
||||
systemIncludes = CollectSystemIncludes(inputHeaderPath)
|
||||
|
||||
outputHeaderStream.write("{}\n".format(licenseComment))
|
||||
outputHeaderStream.write("\n")
|
||||
|
||||
for systemInclude in sorted(systemIncludes):
|
||||
outputHeaderStream.write("#include <{}>\n".format(systemInclude))
|
||||
outputHeaderStream.write("\n")
|
||||
|
||||
outputHeaderStream.write(ParseHeader(inputHeaderPath).strip())
|
||||
outputHeaderStream.write("\n")
|
||||
@@ -4,6 +4,8 @@ Checks: '-*,
|
||||
bugprone-*,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-forwarding-reference-overload,
|
||||
-bugprone-lambda-function-name,
|
||||
-bugprone-macro-parentheses,
|
||||
|
||||
clang-analyzer-*,
|
||||
|
||||
@@ -11,6 +13,7 @@ Checks: '-*,
|
||||
|
||||
cppcoreguidelines-*,
|
||||
-cppcoreguidelines-macro-usage,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
|
||||
modernize-*,
|
||||
@@ -22,7 +25,9 @@ Checks: '-*,
|
||||
|
||||
readability-*,
|
||||
-readability-identifier-length,
|
||||
-readability-named-parameter,
|
||||
-readability-redundant-access-specifiers,
|
||||
-readability-simplify-boolean-expr,
|
||||
-readability-use-anyofallof,
|
||||
'
|
||||
...
|
||||
|
||||
@@ -10,8 +10,6 @@ endif()
|
||||
project(meta.hpp)
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
||||
|
||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE headers)
|
||||
|
||||
@@ -39,5 +37,6 @@ include(EnableGCov)
|
||||
include(EnableUBSan)
|
||||
|
||||
add_subdirectory(manuals)
|
||||
add_subdirectory(singles)
|
||||
add_subdirectory(vendors)
|
||||
add_subdirectory(untests)
|
||||
|
||||
@@ -37,19 +37,19 @@ namespace meta_hpp::detail
|
||||
swap(flags_, other.flags_);
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept {
|
||||
[[nodiscard]] constexpr explicit operator bool() const noexcept {
|
||||
return !!flags_;
|
||||
}
|
||||
|
||||
constexpr underlying_type as_raw() const noexcept {
|
||||
[[nodiscard]] constexpr underlying_type as_raw() const noexcept {
|
||||
return flags_;
|
||||
}
|
||||
|
||||
constexpr enum_type as_enum() const noexcept {
|
||||
[[nodiscard]] constexpr enum_type as_enum() const noexcept {
|
||||
return static_cast<enum_type>(flags_);
|
||||
}
|
||||
|
||||
constexpr bool has(bitflags flags) const noexcept {
|
||||
[[nodiscard]] constexpr bool has(bitflags flags) const noexcept {
|
||||
return flags.flags_ == (flags_ & flags.flags_);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace meta_hpp::detail
|
||||
template < class_kind Class >
|
||||
struct class_traits : impl::class_traits_base<Class> {
|
||||
static constexpr std::size_t size{sizeof(Class)};
|
||||
static constexpr std::size_t align{alignof(Class)};
|
||||
|
||||
[[nodiscard]] static constexpr class_bitflags make_flags() noexcept {
|
||||
class_bitflags flags{};
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace meta_hpp::detail
|
||||
template < number_kind Number >
|
||||
struct number_traits {
|
||||
static constexpr std::size_t size{sizeof(Number)};
|
||||
static constexpr std::size_t align{alignof(Number)};
|
||||
|
||||
[[nodiscard]] static constexpr number_bitflags make_flags() noexcept {
|
||||
number_bitflags flags{};
|
||||
|
||||
@@ -150,6 +150,7 @@ namespace meta_hpp
|
||||
[[nodiscard]] const metadata_map& get_metadata() const noexcept;
|
||||
|
||||
[[nodiscard]] std::size_t get_size() const noexcept;
|
||||
[[nodiscard]] std::size_t get_align() const noexcept;
|
||||
|
||||
[[nodiscard]] std::size_t get_arity() const noexcept;
|
||||
[[nodiscard]] any_type get_argument_type(std::size_t position) const noexcept;
|
||||
@@ -367,6 +368,7 @@ namespace meta_hpp
|
||||
[[nodiscard]] const metadata_map& get_metadata() const noexcept;
|
||||
|
||||
[[nodiscard]] std::size_t get_size() const noexcept;
|
||||
[[nodiscard]] std::size_t get_align() const noexcept;
|
||||
private:
|
||||
detail::number_type_data* data_{};
|
||||
friend auto detail::type_access<number_type>(const number_type&);
|
||||
@@ -493,6 +495,7 @@ namespace meta_hpp::detail
|
||||
struct class_type_data final : type_data_base {
|
||||
const class_bitflags flags;
|
||||
const std::size_t size;
|
||||
const std::size_t align;
|
||||
const std::vector<any_type> argument_types;
|
||||
|
||||
class_set bases;
|
||||
@@ -579,6 +582,7 @@ namespace meta_hpp::detail
|
||||
struct number_type_data final : type_data_base {
|
||||
const number_bitflags flags;
|
||||
const std::size_t size;
|
||||
const std::size_t align;
|
||||
|
||||
template < number_kind Number >
|
||||
explicit number_type_data(type_list<Number>);
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace meta_hpp::detail
|
||||
: type_data_base{type_id{type_list<class_tag<Class>>{}}, type_kind::class_}
|
||||
, flags{class_traits<Class>::make_flags()}
|
||||
, size{class_traits<Class>::size}
|
||||
, align{class_traits<Class>::align}
|
||||
, argument_types{resolve_types(typename class_traits<Class>::argument_types{})} {}
|
||||
}
|
||||
|
||||
@@ -61,6 +62,10 @@ namespace meta_hpp
|
||||
return data_->size;
|
||||
}
|
||||
|
||||
inline std::size_t class_type::get_align() const noexcept {
|
||||
return data_->align;
|
||||
}
|
||||
|
||||
inline std::size_t class_type::get_arity() const noexcept {
|
||||
return data_->argument_types.size();
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@ namespace meta_hpp::detail
|
||||
number_type_data::number_type_data(type_list<Number>)
|
||||
: type_data_base{type_id{type_list<number_tag<Number>>{}}, type_kind::number_}
|
||||
, flags{number_traits<Number>::make_flags()}
|
||||
, size{number_traits<Number>::size} {}
|
||||
, size{number_traits<Number>::size}
|
||||
, align{number_traits<Number>::align} {}
|
||||
}
|
||||
|
||||
namespace meta_hpp
|
||||
@@ -53,4 +54,8 @@ namespace meta_hpp
|
||||
inline std::size_t number_type::get_size() const noexcept {
|
||||
return data_->size;
|
||||
}
|
||||
|
||||
inline std::size_t number_type::get_align() const noexcept {
|
||||
return data_->align;
|
||||
}
|
||||
}
|
||||
|
||||
30
singles/CMakeLists.txt
Normal file
30
singles/CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
project(meta.hpp.singles)
|
||||
|
||||
#
|
||||
# generate
|
||||
#
|
||||
|
||||
find_package(PythonInterp REQUIRED)
|
||||
|
||||
set(META_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||
set(META_SINGLES_INPUT "${META_ROOT_DIR}/headers/meta.hpp/meta_all.hpp")
|
||||
set(META_SINGLES_OUTPUT "${META_ROOT_DIR}/singles/headers/meta.hpp/meta_all.hpp")
|
||||
file(GLOB_RECURSE META_SINGLES_DEPENDS "${META_ROOT_DIR}/headers/*.hpp")
|
||||
|
||||
add_custom_command(OUTPUT "${META_SINGLES_OUTPUT}"
|
||||
COMMAND "${PYTHON_EXECUTABLE}" ".ci/build_singles.py" "${META_SINGLES_INPUT}" "${META_SINGLES_OUTPUT}"
|
||||
DEPENDS ${META_SINGLES_DEPENDS}
|
||||
WORKING_DIRECTORY "${META_ROOT_DIR}")
|
||||
|
||||
add_custom_target(${PROJECT_NAME}.generate
|
||||
DEPENDS "${META_SINGLES_OUTPUT}")
|
||||
|
||||
#
|
||||
# library
|
||||
#
|
||||
|
||||
add_library(${PROJECT_NAME} INTERFACE)
|
||||
add_dependencies(${PROJECT_NAME} ${PROJECT_NAME}.generate)
|
||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_20)
|
||||
target_include_directories(${PROJECT_NAME} INTERFACE headers)
|
||||
target_link_libraries(${PROJECT_NAME} INTERFACE Threads::Threads)
|
||||
8394
singles/headers/meta.hpp/meta_all.hpp
Normal file
8394
singles/headers/meta.hpp/meta_all.hpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,40 +4,77 @@ file(GLOB_RECURSE UNTESTS_SOURCES "*.cpp" "*.hpp")
|
||||
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${UNTESTS_SOURCES})
|
||||
|
||||
add_executable(${PROJECT_NAME} ${UNTESTS_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE meta.hpp doctest_with_main)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE meta.hpp)
|
||||
|
||||
if(${BUILD_WITH_COVERAGE})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE enable_gcov)
|
||||
endif()
|
||||
add_executable(${PROJECT_NAME}.singles ${UNTESTS_SOURCES})
|
||||
target_link_libraries(${PROJECT_NAME}.singles PRIVATE meta.hpp.singles)
|
||||
|
||||
if(${BUILD_WITH_SANITIZERS})
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE enable_asan enable_ubsan)
|
||||
endif()
|
||||
#
|
||||
# setup defines
|
||||
#
|
||||
|
||||
target_compile_options(${PROJECT_NAME}
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:
|
||||
/WX /W4>
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:GNU>:
|
||||
-Werror -Wall -Wextra -Wpedantic>
|
||||
PRIVATE
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
|
||||
-Werror -Weverything -Wconversion
|
||||
-Wno-c++98-compat
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-exit-time-destructors
|
||||
-Wno-global-constructors
|
||||
-Wno-padded
|
||||
-Wno-unknown-warning-option
|
||||
-Wno-unneeded-internal-declaration
|
||||
-Wno-unneeded-member-function
|
||||
-Wno-unused-macros
|
||||
-Wno-weak-vtables
|
||||
>)
|
||||
function(setup_defines_for_target TARGET)
|
||||
target_compile_definitions(${TARGET} PRIVATE
|
||||
DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
|
||||
DOCTEST_CONFIG_USE_STD_HEADERS)
|
||||
endfunction()
|
||||
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||
DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS
|
||||
DOCTEST_CONFIG_USE_STD_HEADERS)
|
||||
setup_defines_for_target(${PROJECT_NAME})
|
||||
setup_defines_for_target(${PROJECT_NAME}.singles)
|
||||
|
||||
#
|
||||
# setup libraries
|
||||
#
|
||||
|
||||
function(setup_libraries_for_target TARGET)
|
||||
target_link_libraries(${TARGET} PRIVATE doctest_with_main)
|
||||
|
||||
if(${BUILD_WITH_COVERAGE})
|
||||
target_link_libraries(${TARGET} PRIVATE enable_gcov)
|
||||
endif()
|
||||
|
||||
if(${BUILD_WITH_SANITIZERS})
|
||||
target_link_libraries(${TARGET} PRIVATE enable_asan enable_ubsan)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
setup_libraries_for_target(${PROJECT_NAME})
|
||||
setup_libraries_for_target(${PROJECT_NAME}.singles)
|
||||
|
||||
#
|
||||
# setup warnings
|
||||
#
|
||||
|
||||
function(setup_warnings_for_target TARGET)
|
||||
target_compile_options(${TARGET}
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:
|
||||
/WX /W4>
|
||||
PRIVATE
|
||||
$<$<CXX_COMPILER_ID:GNU>:
|
||||
-Werror -Wall -Wextra -Wpedantic>
|
||||
PRIVATE
|
||||
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>>:
|
||||
-Werror -Weverything -Wconversion
|
||||
-Wno-c++98-compat
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-exit-time-destructors
|
||||
-Wno-global-constructors
|
||||
-Wno-padded
|
||||
-Wno-unknown-warning-option
|
||||
-Wno-unneeded-internal-declaration
|
||||
-Wno-unneeded-member-function
|
||||
-Wno-unused-macros
|
||||
-Wno-weak-vtables
|
||||
>)
|
||||
endfunction()
|
||||
|
||||
setup_warnings_for_target(${PROJECT_NAME})
|
||||
setup_warnings_for_target(${PROJECT_NAME}.singles)
|
||||
|
||||
#
|
||||
# add tests
|
||||
#
|
||||
|
||||
add_test(${PROJECT_NAME} ${PROJECT_NAME})
|
||||
add_test(${PROJECT_NAME} ${PROJECT_NAME}.singles)
|
||||
|
||||
@@ -126,6 +126,13 @@ TEST_CASE("meta/meta_types/class_type") {
|
||||
CHECK(final_derived_clazz_type.get_size() == sizeof(final_derived_clazz));
|
||||
}
|
||||
|
||||
SUBCASE("get_align") {
|
||||
CHECK(base_clazz_1_type.get_align() == alignof(base_clazz_1));
|
||||
CHECK(base_clazz_2_type.get_align() == alignof(base_clazz_2));
|
||||
CHECK(derived_clazz_type.get_align() == alignof(derived_clazz));
|
||||
CHECK(final_derived_clazz_type.get_align() == alignof(final_derived_clazz));
|
||||
}
|
||||
|
||||
SUBCASE("get_arity") {
|
||||
{
|
||||
const meta::class_type type = meta::resolve_type<derived_clazz>();
|
||||
|
||||
@@ -24,6 +24,7 @@ TEST_CASE("meta/meta_types/number_type") {
|
||||
REQUIRE(type);
|
||||
|
||||
CHECK(type.get_size() == sizeof(int));
|
||||
CHECK(type.get_align() == alignof(int));
|
||||
CHECK(type.get_flags() == (
|
||||
meta::number_flags::is_signed |
|
||||
meta::number_flags::is_integral));
|
||||
@@ -34,16 +35,18 @@ TEST_CASE("meta/meta_types/number_type") {
|
||||
REQUIRE(type);
|
||||
|
||||
CHECK(type.get_size() == sizeof(float));
|
||||
CHECK(type.get_align() == alignof(float));
|
||||
CHECK(type.get_flags() == (
|
||||
meta::number_flags::is_signed |
|
||||
meta::number_flags::is_floating_point));
|
||||
}
|
||||
|
||||
SUBCASE("const unsigned") {
|
||||
const meta::number_type type = meta::resolve_type<const unsigned>();
|
||||
SUBCASE("const unsigned long long") {
|
||||
const meta::number_type type = meta::resolve_type<const unsigned long long>();
|
||||
REQUIRE(type);
|
||||
|
||||
CHECK(type.get_size() == sizeof(unsigned));
|
||||
CHECK(type.get_size() == sizeof(unsigned long long));
|
||||
CHECK(type.get_align() == alignof(unsigned long long));
|
||||
CHECK(type.get_flags() == (
|
||||
meta::number_flags::is_unsigned |
|
||||
meta::number_flags::is_integral));
|
||||
|
||||
Reference in New Issue
Block a user