diff --git a/DEPENDENCIES b/DEPENDENCIES index 425adb78d..30df177fd 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,5 +1,5 @@ vendorpull https://github.com/sourcemeta/vendorpull 1dcbac42809cf87cb5b045106b863e17ad84ba02 -core https://github.com/sourcemeta/core 31404273bf927fc26457a1052b27b56519c0329c +core https://github.com/sourcemeta/core 8018e9d85ef6fc0fd9ccd11c2ae438789214b00a jsonschema-test-suite https://github.com/json-schema-org/JSON-Schema-Test-Suite c7257e92580678a086f0b9243a1903ed88bd27f7 jsonschema-2020-12 https://github.com/json-schema-org/json-schema-spec 769daad75a9553562333a8937a187741cb708c72 jsonschema-2019-09 https://github.com/json-schema-org/json-schema-spec 41014ea723120ce70b314d72f863c6929d9f3cfd diff --git a/vendor/core/CMakeLists.txt b/vendor/core/CMakeLists.txt index 8afa68c62..6c8c05bce 100644 --- a/vendor/core/CMakeLists.txt +++ b/vendor/core/CMakeLists.txt @@ -10,6 +10,7 @@ option(SOURCEMETA_CORE_LANG_PARALLEL "Build the Sourcemeta Core language paralle option(SOURCEMETA_CORE_LANG_NUMERIC "Build the Sourcemeta Core language numeric library" ON) option(SOURCEMETA_CORE_LANG_ERROR "Build the Sourcemeta Core language error library" ON) option(SOURCEMETA_CORE_LANG_OPTIONS "Build the Sourcemeta Core Options library" ON) +option(SOURCEMETA_CORE_LANG_TEXT "Build the Sourcemeta Core language text library" ON) option(SOURCEMETA_CORE_UNICODE "Build the Sourcemeta Core Unicode library" ON) option(SOURCEMETA_CORE_PUNYCODE "Build the Sourcemeta Core Punycode library" ON) option(SOURCEMETA_CORE_TIME "Build the Sourcemeta Core time library" ON) @@ -93,6 +94,10 @@ if(SOURCEMETA_CORE_LANG_OPTIONS) add_subdirectory(src/lang/options) endif() +if(SOURCEMETA_CORE_LANG_TEXT) + add_subdirectory(src/lang/text) +endif() + if(SOURCEMETA_CORE_UNICODE) add_subdirectory(src/core/unicode) endif() @@ -231,6 +236,10 @@ if(SOURCEMETA_CORE_TESTS) add_subdirectory(test/options) endif() + if(SOURCEMETA_CORE_LANG_TEXT) + add_subdirectory(test/text) + endif() + if(SOURCEMETA_CORE_UNICODE) add_subdirectory(test/unicode) endif() diff --git a/vendor/core/cmake/common/compiler/options.cmake b/vendor/core/cmake/common/compiler/options.cmake index 37754283d..d43bb2d91 100644 --- a/vendor/core/cmake/common/compiler/options.cmake +++ b/vendor/core/cmake/common/compiler/options.cmake @@ -1,3 +1,13 @@ +# Applies the shared compiler defaults to at . +# +# Flag categories handled here: +# - Diagnostics (-W...): always on, every config +# - Language semantics (-fwrapv, -fstrict-aliasing, -fno-rtti on GCC): always on +# - Optimization-related (loop unrolling, vectorization, fast-math relaxations): +# gated to non-Debug configs because they have no effect at -O0 but still +# cost Clang/GCC pipeline time +# +# Do not add optimization-only flags here without a generator-expression gate function(sourcemeta_add_default_options visibility target) if(SOURCEMETA_COMPILER_MSVC) # See https://learn.microsoft.com/en-us/cpp/build/reference/compiler-options-listed-by-category @@ -40,22 +50,28 @@ function(sourcemeta_add_default_options visibility target) $<$,$>:-Wnon-virtual-dtor> $<$,$>:-Woverloaded-virtual> $<$,$>:-Winvalid-offsetof> - -funroll-loops + # Semantics, not optimization: keep on for every config -fstrict-aliasing - -ftree-vectorize - - # To improve how much GCC/Clang will vectorize + # Assume that signed arithmetic overflow of addition, subtraction and + # multiplication wraps around using twos-complement representation + # See https://users.cs.utah.edu/~regehr/papers/overflow12.pdf + # See https://www.postgresql.org/message-id/1689.1134422394@sss.pgh.pa.us + -fwrapv + # Fast-math relaxations relax IEEE conformance (errno after math.h, + # signed-zero handling, reassociation), so they affect observable + # behavior and must apply to every config to keep Debug and Release + # semantics aligned -fno-math-errno -fno-trapping-math -fno-signed-zeros -freciprocal-math -fassociative-math - # Assume that signed arithmetic overflow of addition, subtraction and - # multiplication wraps around using twos-complement representation - # See https://users.cs.utah.edu/~regehr/papers/overflow12.pdf - # See https://www.postgresql.org/message-id/1689.1134422394@sss.pgh.pa.us - -fwrapv) + # Optimization-only: emitted only when not building Debug. At -O0 these + # run analyses that never reach codegen, costing build time for no + # behavioral effect + $<$>:-funroll-loops> + $<$>:-ftree-vectorize>) endif() if(SOURCEMETA_COMPILER_LLVM) @@ -81,9 +97,9 @@ function(sourcemeta_add_default_options visibility target) -Wrange-loop-analysis # Enable loop vectorization for performance reasons - -fvectorize + $<$>:-fvectorize> # Enable vectorization of straight-line code for performance - -fslp-vectorize) + $<$>:-fslp-vectorize>) elseif(SOURCEMETA_COMPILER_GCC) target_compile_options("${target}" ${visibility} # Newer versions of GCC (i.e. 14) seem to print a lot of false-positives here diff --git a/vendor/core/cmake/common/targets/googletest.cmake b/vendor/core/cmake/common/targets/googletest.cmake index 176d2872b..39cb9f22f 100644 --- a/vendor/core/cmake/common/targets/googletest.cmake +++ b/vendor/core/cmake/common/targets/googletest.cmake @@ -18,6 +18,14 @@ function(sourcemeta_googletest) target_link_libraries("${TARGET_NAME}" PRIVATE GTest::gtest GTest::gmock GTest::gtest_main) + + # Test executables are not shipped, so LTO buys nothing and significantly + # slows the link step (GCC's LTRANS phase serializes per executable) + if(SOURCEMETA_COMPILER_LLVM OR SOURCEMETA_COMPILER_GCC) + target_compile_options("${TARGET_NAME}" PRIVATE -fno-lto) + target_link_options("${TARGET_NAME}" PRIVATE -fno-lto) + endif() + add_test(NAME "${SOURCEMETA_GOOGLETEST_PROJECT}.${SOURCEMETA_GOOGLETEST_NAME}" COMMAND "${TARGET_NAME}" --gtest_brief=1) endfunction() diff --git a/vendor/core/config.cmake.in b/vendor/core/config.cmake.in index 4f73aa20f..18a7effdb 100644 --- a/vendor/core/config.cmake.in +++ b/vendor/core/config.cmake.in @@ -30,6 +30,7 @@ if(NOT SOURCEMETA_CORE_COMPONENTS) list(APPEND SOURCEMETA_CORE_COMPONENTS markdown) list(APPEND SOURCEMETA_CORE_COMPONENTS error) list(APPEND SOURCEMETA_CORE_COMPONENTS options) + list(APPEND SOURCEMETA_CORE_COMPONENTS text) endif() include(CMakeFindDependencyMacro) @@ -136,6 +137,8 @@ foreach(component ${SOURCEMETA_CORE_COMPONENTS}) include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_error.cmake") elseif(component STREQUAL "options") include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_options.cmake") + elseif(component STREQUAL "text") + include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_text.cmake") else() message(FATAL_ERROR "Unknown Sourcemeta Core component: ${component}") endif() diff --git a/vendor/core/src/lang/text/CMakeLists.txt b/vendor/core/src/lang/text/CMakeLists.txt new file mode 100644 index 000000000..3b8602d58 --- /dev/null +++ b/vendor/core/src/lang/text/CMakeLists.txt @@ -0,0 +1,6 @@ +sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME text + SOURCES text.cc) + +if(SOURCEMETA_CORE_INSTALL) + sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME text) +endif() diff --git a/vendor/core/src/lang/text/include/sourcemeta/core/text.h b/vendor/core/src/lang/text/include/sourcemeta/core/text.h new file mode 100644 index 000000000..c9851754c --- /dev/null +++ b/vendor/core/src/lang/text/include/sourcemeta/core/text.h @@ -0,0 +1,39 @@ +#ifndef SOURCEMETA_CORE_TEXT_H_ +#define SOURCEMETA_CORE_TEXT_H_ + +#ifndef SOURCEMETA_CORE_TEXT_EXPORT +#include +#endif + +#include // std::string + +/// @defgroup text Text +/// @brief A collection of general-purpose text manipulation utilities +/// +/// This functionality is included as follows: +/// +/// ```cpp +/// #include +/// ``` + +namespace sourcemeta::core { + +/// @ingroup text +/// +/// Convert a string to Title Case in place. For example: +/// +/// ```cpp +/// #include +/// #include +/// #include +/// +/// std::string value{"hello_world"}; +/// sourcemeta::core::to_title_case(value); +/// assert(value == "Hello World"); +/// ``` +SOURCEMETA_CORE_TEXT_EXPORT +auto to_title_case(std::string &value) -> void; + +} // namespace sourcemeta::core + +#endif diff --git a/vendor/core/src/lang/text/text.cc b/vendor/core/src/lang/text/text.cc new file mode 100644 index 000000000..3c3b4ae5e --- /dev/null +++ b/vendor/core/src/lang/text/text.cc @@ -0,0 +1,37 @@ +#include + +#include // std::isalpha, std::toupper +#include // std::size_t + +namespace sourcemeta::core { + +auto to_title_case(std::string &value) -> void { + std::size_t write{0}; + bool capitalize_next{true}; + bool pending_separator{false}; + for (const char character : value) { + if (character == '_' || character == '-') { + if (write > 0) { + pending_separator = true; + } + } else { + if (pending_separator) { + value[write++] = ' '; + pending_separator = false; + capitalize_next = true; + } + if (capitalize_next) { + value[write++] = static_cast( + std::toupper(static_cast(character))); + if (std::isalpha(static_cast(character))) { + capitalize_next = false; + } + } else { + value[write++] = character; + } + } + } + value.resize(write); +} + +} // namespace sourcemeta::core