diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d7fab5b1..a7451af6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -166,11 +166,8 @@ jobs: - name: Generate headers run: ./b2 headers working-directory: ../boost-root - - name: Test Config - run: CXX=clang++-18 ./config/clang.sh ./config/test_has_module_support.cpp ./config/has_module_support.cpp has_module_support - working-directory: ../boost-root/libs/regex/test/module - name: Test - run: CXX=clang++-18 LIBRARIES="-licuuc -licudata -licui18n" ./test.sh ./config/clang.sh + run: CXX=clang++-18 LIBRARIES="-licuuc -licudata -licui18n" ./test_clang.sh working-directory: ../boost-root/libs/regex/test/module macos: runs-on: macos-latest diff --git a/include/boost/regex/v5/basic_regex.hpp b/include/boost/regex/v5/basic_regex.hpp index 0532e0c6..3cae3296 100644 --- a/include/boost/regex/v5/basic_regex.hpp +++ b/include/boost/regex/v5/basic_regex.hpp @@ -650,22 +650,38 @@ private: // and are designed to provide the strong exception guarantee // (in the event of a throw, the state of the object remains unchanged). // + +namespace detail +{ + template + std::shared_ptr > create_implemenation(const charT* p1, const charT* p2, F f, std::shared_ptr > ptraits) + { + std::shared_ptr > result; + if (!ptraits.get()) + { + result = std::shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation()); + } + else + { + result = std::shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation(ptraits)); + } + result->assign(p1, p2, f); + return result; + } +#ifdef BOOST_REGEX_AS_MODULE + std::shared_ptr::traits_type> > + create_implemenation(const char* p1, const char* p2, basic_regex::flag_type f, std::shared_ptr::traits_type> > ptraits); + std::shared_ptr::traits_type> > + create_implemenation(const wchar_t* p1, const wchar_t* p2, basic_regex::flag_type f, std::shared_ptr::traits_type> > ptraits); +#endif +} + template basic_regex& basic_regex::do_assign(const charT* p1, const charT* p2, flag_type f) { - std::shared_ptr > temp; - if(!m_pimpl.get()) - { - temp = std::shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation()); - } - else - { - temp = std::shared_ptr >(new BOOST_REGEX_DETAIL_NS::basic_regex_implementation(m_pimpl->m_ptraits)); - } - temp->assign(p1, p2, f); - temp.swap(m_pimpl); + m_pimpl = detail::create_implemenation(p1, p2, f, m_pimpl.get() ? m_pimpl->m_ptraits : std::shared_ptr >()); return *this; } diff --git a/include/boost/regex/v5/perl_matcher.hpp b/include/boost/regex/v5/perl_matcher.hpp index deeffa58..f4239d3f 100644 --- a/include/boost/regex/v5/perl_matcher.hpp +++ b/include/boost/regex/v5/perl_matcher.hpp @@ -558,6 +558,33 @@ private: #endif }; +template +inline bool factory_match(Matcher& m) +{ + return m.match(); +} +template +inline bool factory_find(Matcher& m) +{ + return m.find(); +} + +#ifdef BOOST_REGEX_AS_MODULE +bool factory_match(perl_matcher::allocator_type, regex::traits_type>& m); +bool factory_match(perl_matcher::allocator_type, wregex::traits_type>& m); +bool factory_match(perl_matcher::allocator_type, regex::traits_type>& m); +bool factory_match(perl_matcher::allocator_type, wregex::traits_type>& m); +bool factory_match(perl_matcher::allocator_type, regex::traits_type>& m); +bool factory_match(perl_matcher::allocator_type, wregex::traits_type>& m); + +bool factory_find(perl_matcher::allocator_type, regex::traits_type>& m); +bool factory_find(perl_matcher::allocator_type, wregex::traits_type>& m); +bool factory_find(perl_matcher::allocator_type, regex::traits_type>& m); +bool factory_find(perl_matcher::allocator_type, wregex::traits_type>& m); +bool factory_find(perl_matcher::allocator_type, regex::traits_type>& m); +bool factory_find(perl_matcher::allocator_type, wregex::traits_type>& m); +#endif + } // namespace BOOST_REGEX_DETAIL_NS #ifdef BOOST_REGEX_MSVC diff --git a/include/boost/regex/v5/regex_grep.hpp b/include/boost/regex/v5/regex_grep.hpp index 0de27cc4..3a2228ce 100644 --- a/include/boost/regex/v5/regex_grep.hpp +++ b/include/boost/regex/v5/regex_grep.hpp @@ -41,7 +41,7 @@ inline unsigned int regex_grep(Predicate foo, match_results m; BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, first); unsigned int count = 0; - while(matcher.find()) + while(BOOST_REGEX_DETAIL_NS::factory_find(matcher)) { ++count; if(0 == foo(m)) @@ -56,7 +56,7 @@ inline unsigned int regex_grep(Predicate foo, // a non-NULL one at the same position: match_results m2(m); matcher.setf(match_not_null | match_continuous); - if(matcher.find()) + if(BOOST_REGEX_DETAIL_NS::factory_find(matcher)) { ++count; if(0 == foo(m)) diff --git a/include/boost/regex/v5/regex_match.hpp b/include/boost/regex/v5/regex_match.hpp index c95c3a59..c7358ea5 100644 --- a/include/boost/regex/v5/regex_match.hpp +++ b/include/boost/regex/v5/regex_match.hpp @@ -36,7 +36,7 @@ bool regex_match(BidiIterator first, BidiIterator last, match_flag_type flags = match_default) { BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, first); - return matcher.match(); + return BOOST_REGEX_DETAIL_NS::factory_match(matcher); } BOOST_REGEX_MODULE_EXPORT template bool regex_match(iterator first, iterator last, diff --git a/include/boost/regex/v5/regex_search.hpp b/include/boost/regex/v5/regex_search.hpp index e4a8cf0a..4e42ceb0 100644 --- a/include/boost/regex/v5/regex_search.hpp +++ b/include/boost/regex/v5/regex_search.hpp @@ -42,7 +42,7 @@ bool regex_search(BidiIterator first, BidiIterator last, return false; BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags, base); - return matcher.find(); + return BOOST_REGEX_DETAIL_NS::factory_find(matcher); } // @@ -77,7 +77,7 @@ bool regex_search(BidiIterator first, BidiIterator last, match_results m; typedef typename match_results::allocator_type match_alloc_type; BOOST_REGEX_DETAIL_NS::perl_matcher matcher(first, last, m, e, flags | regex_constants::match_any, first); - return matcher.find(); + return BOOST_REGEX_DETAIL_NS::factory_find(matcher); } BOOST_REGEX_MODULE_EXPORT template diff --git a/module/regex.cxx b/module/regex.cxx index 4cf40f9f..a19c51e3 100644 --- a/module/regex.cxx +++ b/module/regex.cxx @@ -5,6 +5,23 @@ module; #define BOOST_REGEX_USE_STD_MODULE #endif +#if __has_include() + +#if !defined(BOOST_REGEX_WITH_ICU) + +#if defined(_MSC_FULL_VER) +#pragma message "ICU headers are available but building the Regex module with ICU support is turned OFF. Build with BOOST_REGEX_WITH_ICU=1 to turn it on, or BOOST_REGEX_WITH_ICU=0 to disable this message" +#else +# warning "ICU headers are available but building the Regex module with ICU support is turned OFF. Build with BOOST_REGEX_WITH_ICU=1 to turn it on, or BOOST_REGEX_WITH_ICU=0 to disable this message" +#endif + +#elif BOOST_REGEX_WITH_ICU +# define BOOST_REGEX_HAS_ICU_HEADERS +#endif + + +#endif + #if defined(_WIN32) && __has_include() #include #endif @@ -52,7 +69,7 @@ module; #include #endif -#if __has_include() +#ifdef BOOST_REGEX_HAS_ICU_HEADERS #include #include #include @@ -74,8 +91,12 @@ import std.core; #pragma warning(disable:5244) #endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Winclude-angled-in-module-purview" +#endif + #include -#if __has_include() +#ifdef BOOST_REGEX_HAS_ICU_HEADERS #include #endif diff --git a/module/regex_cfind.cpp b/module/regex_cfind.cpp new file mode 100644 index 00000000..1796d558 --- /dev/null +++ b/module/regex_cfind.cpp @@ -0,0 +1,11 @@ + +module boost.regex; + +namespace boost::re_detail_600 { + + bool factory_find(perl_matcher::allocator_type, regex::traits_type>& m) + { + return m.find(); + } + +} diff --git a/module/regex_cmatch.cpp b/module/regex_cmatch.cpp new file mode 100644 index 00000000..ae30eb8e --- /dev/null +++ b/module/regex_cmatch.cpp @@ -0,0 +1,11 @@ + +module boost.regex; + +namespace boost::re_detail_600 { + + bool factory_match(perl_matcher::allocator_type, regex::traits_type>& m) + { + return m.match(); + } + +} diff --git a/module/regex_create_char.cpp b/module/regex_create_char.cpp new file mode 100644 index 00000000..7eabb95a --- /dev/null +++ b/module/regex_create_char.cpp @@ -0,0 +1,31 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +#ifndef BOOST_REGEX_DETAIL_NS +#define BOOST_REGEX_DETAIL_NS re_detail_600 +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::detail { + + std::shared_ptr::traits_type> > + create_implemenation(const char* p1, const char* p2, basic_regex::flag_type f, std::shared_ptr::traits_type> > ptraits) + { + return create_implemenation::flag_type, basic_regex::traits_type>(p1, p2, f, ptraits); + } + +} diff --git a/module/regex_create_wchar_t.cpp b/module/regex_create_wchar_t.cpp new file mode 100644 index 00000000..0d733f0d --- /dev/null +++ b/module/regex_create_wchar_t.cpp @@ -0,0 +1,31 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +#ifndef BOOST_REGEX_DETAIL_NS +#define BOOST_REGEX_DETAIL_NS re_detail_600 +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::detail { + + std::shared_ptr::traits_type> > + create_implemenation(const wchar_t* p1, const wchar_t* p2, basic_regex::flag_type f, std::shared_ptr::traits_type> > ptraits) + { + return create_implemenation::flag_type, basic_regex::traits_type>(p1, p2, f, ptraits); + } + +} diff --git a/module/regex_nc_sfind.cpp b/module/regex_nc_sfind.cpp new file mode 100644 index 00000000..1cd193c0 --- /dev/null +++ b/module/regex_nc_sfind.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_find(perl_matcher::allocator_type, regex::traits_type>& m) + { + return m.find(); + } + +} diff --git a/module/regex_nc_smatch.cpp b/module/regex_nc_smatch.cpp new file mode 100644 index 00000000..cb76c66d --- /dev/null +++ b/module/regex_nc_smatch.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_match(perl_matcher::allocator_type, regex::traits_type>& m) + { + return m.match(); + } + +} diff --git a/module/regex_nc_wsfind.cpp b/module/regex_nc_wsfind.cpp new file mode 100644 index 00000000..cccfc678 --- /dev/null +++ b/module/regex_nc_wsfind.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_find(perl_matcher::allocator_type, wregex::traits_type>& m) + { + return m.find(); + } + +} diff --git a/module/regex_nc_wsmatch.cpp b/module/regex_nc_wsmatch.cpp new file mode 100644 index 00000000..d18339e0 --- /dev/null +++ b/module/regex_nc_wsmatch.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_match(perl_matcher::allocator_type, wregex::traits_type>& m) + { + return m.match(); + } + +} diff --git a/module/regex_sfind.cpp b/module/regex_sfind.cpp new file mode 100644 index 00000000..e0d68bf4 --- /dev/null +++ b/module/regex_sfind.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_find(perl_matcher::allocator_type, regex::traits_type>& m) + { + return m.find(); + } + +} diff --git a/module/regex_smatch.cpp b/module/regex_smatch.cpp new file mode 100644 index 00000000..2434cddb --- /dev/null +++ b/module/regex_smatch.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_match(perl_matcher::allocator_type, regex::traits_type>& m) + { + return m.match(); + } + +} diff --git a/module/regex_wcfind.cpp b/module/regex_wcfind.cpp new file mode 100644 index 00000000..0e2e9955 --- /dev/null +++ b/module/regex_wcfind.cpp @@ -0,0 +1,11 @@ + +module boost.regex; + +namespace boost::re_detail_600 { + + bool factory_find(perl_matcher::allocator_type, wregex::traits_type>& m) + { + return m.find(); + } + +} diff --git a/module/regex_wcmatch.cpp b/module/regex_wcmatch.cpp new file mode 100644 index 00000000..56003831 --- /dev/null +++ b/module/regex_wcmatch.cpp @@ -0,0 +1,11 @@ + +module boost.regex; + +namespace boost::re_detail_600 { + + bool factory_match(perl_matcher::allocator_type, wregex::traits_type>& m) + { + return m.match(); + } + +} diff --git a/module/regex_wsfind.cpp b/module/regex_wsfind.cpp new file mode 100644 index 00000000..16239941 --- /dev/null +++ b/module/regex_wsfind.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_find(perl_matcher::allocator_type, wregex::traits_type>& m) + { + return m.find(); + } + +} diff --git a/module/regex_wsmatch.cpp b/module/regex_wsmatch.cpp new file mode 100644 index 00000000..5c50ef8f --- /dev/null +++ b/module/regex_wsmatch.cpp @@ -0,0 +1,26 @@ + +#if defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523)) +#define BOOST_REGEX_USE_STD_MODULE +#endif + +#ifndef BOOST_REGEX_USE_STD_MODULE +module; + +#include + +#endif + +module boost.regex; + +#ifdef BOOST_REGEX_USE_STD_MODULE +import std; +#endif + +namespace boost::re_detail_600 { + + bool factory_match(perl_matcher::allocator_type, wregex::traits_type>& m) + { + return m.match(); + } + +} diff --git a/test/module/config/Jamfile.v2 b/test/module/config/Jamfile.v2 deleted file mode 100644 index f268160d..00000000 --- a/test/module/config/Jamfile.v2 +++ /dev/null @@ -1,17 +0,0 @@ -# copyright John Maddock 2022 -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt. - -project - : requirements - multi - msvc:on - msvc:latest - gcc:-fmodules-ts - ; - - -obj has_module_support : has_module_support.cpp : msvc:-interface ; -exe test_has_module_support : test_has_module_support.cpp has_module_support : has_module_support ; -explicit test_has_module_support ; diff --git a/test/module/config/clang.sh b/test/module/config/clang.sh deleted file mode 100755 index edf8e1b7..00000000 --- a/test/module/config/clang.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# -# Arguments are: -# -# 1) A space spearated list of source files. -# 2) A space separated list of module source files. -# 3) The name of the executable to build. -# -# Environment variables used are: -# -# CXX - the name of the clang compiler, defaults to clang++. -# CXXFLAGS - flags to pass to the build, defaults to "-std=c++20 -g". -# LINKFLAGS - flags to pass to the link stage, defaults to "". -# LIBRARIES - Additional libraries to add to the end of the link command line, defaults to "". -# - -: ${CXX:="clang++"} -: ${CXXFLAGS:="-std=c++20 -g"} - -module_usage="" - -for module_file in $2; do -module_base="${module_file%.*}" -$CXX $CXXFLAGS -x c++-module $module_file --precompile -o $module_base.pcm || exit 1 - -# grab the name of the exported module from the source: -cxx_module_name=$(grep -E "export[ ]+module[ ]+([^; ]+)" $module_file | sed -r "s/export[ ]+module[ ]+([^; ]+)[ ]*;/\1/") - -# Build the command line for module usage: -module_usage="$module_usage -fmodule-file=$cxx_module_name=$module_base.pcm $module_base.pcm" - -done - -# Build the actual executable: -$CXX $CXXFLAGS $1 $module_usage $LIBRARIES -o $3 || exit 1 diff --git a/test/module/config/has_module_support.cpp b/test/module/config/has_module_support.cpp deleted file mode 100644 index 718e533b..00000000 --- a/test/module/config/has_module_support.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * - * Copyright (c) 2022 - * John Maddock - * - * Use, modification and distribution are subject to the - * Boost Software License, Version 1.0. (See accompanying file - * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - * - */ - -module; - -#include - -export module test_support; - -export template struct pimpl -{ -private: - std::shared_ptr data; -public: - pimpl(const T& x) : data(new T(x)) {} - pimpl() = default; -}; - diff --git a/test/module/config/test_has_module_support.cpp b/test/module/config/test_has_module_support.cpp deleted file mode 100644 index 79755121..00000000 --- a/test/module/config/test_has_module_support.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * - * Copyright (c) 2022 - * John Maddock - * - * Use, modification and distribution are subject to the - * Boost Software License, Version 1.0. (See accompanying file - * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - * - */ - -import test_support; - -int main() -{ - pimpl p1, p2(3); -} diff --git a/test/module/credit_card_example.cpp b/test/module/credit_card_example.cpp index 611a8d4d..9d56f90b 100644 --- a/test/module/credit_card_example.cpp +++ b/test/module/credit_card_example.cpp @@ -16,9 +16,9 @@ * DESCRIPTION: Credit card number formatting code. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/icu_example.cpp b/test/module/icu_example.cpp deleted file mode 100644 index 6d1fc3be..00000000 --- a/test/module/icu_example.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * - * Copyright (c) 2004 - * John Maddock - * - * Use, modification and distribution are subject to the - * Boost Software License, Version 1.0. (See accompanying file - * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - * - */ - - /* - * LOCATION: see http://www.boost.org for most recent version. - * FILE mfc_example.cpp - * VERSION see - * DESCRIPTION: examples of using Boost.Regex with MFC and ATL string types. - */ - -#include - -#ifdef BOOST_HAS_ICU - -#include -#include -#include - -// -// Find out if *password* meets our password requirements, -// as defined by the regular expression *requirements*. -// -bool is_valid_password(const U_NAMESPACE_QUALIFIER UnicodeString& password, const U_NAMESPACE_QUALIFIER UnicodeString& requirements) -{ - return boost::u32regex_match(password, boost::make_u32regex(requirements)); -} - -// -// Extract filename part of a path from a UTF-8 encoded std::string and return the result -// as another std::string: -// -std::string get_filename(const std::string& path) -{ - boost::u32regex r = boost::make_u32regex("(?:\\A|.*\\\\)([^\\\\]+)"); - boost::smatch what; - if(boost::u32regex_match(path, what, r)) - { - // extract $1 as a std::string: - return what.str(1); - } - else - { - throw std::runtime_error("Invalid pathname"); - } -} - -U_NAMESPACE_QUALIFIER UnicodeString extract_greek(const U_NAMESPACE_QUALIFIER UnicodeString& text) -{ - // searches through some UTF-16 encoded text for a block encoded in Greek, - // this expression is imperfect, but the best we can do for now - searching - // for specific scripts is actually pretty hard to do right. - boost::u32regex r = boost::make_u32regex(L"[\\x{370}-\\x{3FF}](?:[^[:L*:]]|[\\x{370}-\\x{3FF}])*"); - boost::u16match what; - if(boost::u32regex_search(text, what, r)) - { - // extract $0 as a UnicodeString: - return U_NAMESPACE_QUALIFIER UnicodeString(what[0].first, what.length(0)); - } - else - { - throw std::runtime_error("No Greek found!"); - } -} - -void enumerate_currencies(const std::string& text) -{ - // enumerate and print all the currency symbols, along - // with any associated numeric values: - const char* re = - "([[:Sc:]][[:Cf:][:Cc:][:Z*:]]*)?" - "([[:Nd:]]+(?:[[:Po:]][[:Nd:]]+)?)?" - "(?(1)" - "|(?(2)" - "[[:Cf:][:Cc:][:Z*:]]*" - ")" - "[[:Sc:]]" - ")"; - boost::u32regex r = boost::make_u32regex(re); - boost::u32regex_iterator i(boost::make_u32regex_iterator(text, r)), j; - while(i != j) - { - std::cout << (*i)[0] << std::endl; - ++i; - } -} - -void enumerate_currencies2(const std::string& text) -{ - // enumerate and print all the currency symbols, along - // with any associated numeric values: - const char* re = - "([[:Sc:]][[:Cf:][:Cc:][:Z*:]]*)?" - "([[:Nd:]]+(?:[[:Po:]][[:Nd:]]+)?)?" - "(?(1)" - "|(?(2)" - "[[:Cf:][:Cc:][:Z*:]]*" - ")" - "[[:Sc:]]" - ")"; - boost::u32regex r = boost::make_u32regex(re); - boost::u32regex_token_iterator - i(boost::make_u32regex_token_iterator(text, r, 1)), j; - while(i != j) - { - std::cout << *i << std::endl; - ++i; - } -} - - -// -// Take a credit card number as a string of digits, -// and reformat it as a human readable string with "-" -// separating each group of four digit;, -// note that we're mixing a UTF-32 regex, with a UTF-16 -// string and a UTF-8 format specifier, and it still all -// just works: -// -const boost::u32regex e = boost::make_u32regex("\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z"); -const char* human_format = "$1-$2-$3-$4"; - -U_NAMESPACE_QUALIFIER UnicodeString human_readable_card_number(const U_NAMESPACE_QUALIFIER UnicodeString& s) -{ - return boost::u32regex_replace(s, e, human_format); -} - - -int main() -{ - // password checks using u32regex_match: - U_NAMESPACE_QUALIFIER UnicodeString pwd = "abcDEF---"; - U_NAMESPACE_QUALIFIER UnicodeString pwd_check = "(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}"; - bool b = is_valid_password(pwd, pwd_check); - assert(b); - pwd = "abcD-"; - b = is_valid_password(pwd, pwd_check); - assert(!b); - // filename extraction with u32regex_match: - std::string file = "abc.hpp"; - file = get_filename(file); - assert(file == "abc.hpp"); - file = "c:\\a\\b\\c\\d.h"; - file = get_filename(file); - assert(file == "d.h"); - - // Greek text extraction with u32regex_search: - const UChar t[] = { - 'S', 'o', 'm', 'e', ' ', 'w', 'h', 'e', 'r', 'e', ' ', 'i', 'n', 0x0391, 0x039D, 0x0395, 0x0398, 0x0391, 0 - }; - const UChar g[] = { - 0x0391, 0x039D, 0x0395, 0x0398, 0x0391, 0 - }; - U_NAMESPACE_QUALIFIER UnicodeString text = t; - U_NAMESPACE_QUALIFIER UnicodeString greek = extract_greek(text); - assert(greek == g); - - // extract currency symbols with associated value, use iterator interface: - std::string text2 = " $100.23 or \xC2\xA3""198.12 "; // \xC2\xA3 is the pound sign encoded in UTF-8 - enumerate_currencies(text2); - enumerate_currencies2(text2); - - U_NAMESPACE_QUALIFIER UnicodeString credit_card_number = "1234567887654321"; - credit_card_number = human_readable_card_number(credit_card_number); - assert(credit_card_number == "1234-5678-8765-4321"); - return 0; -} - -#else - -#include - -int main() -{ - std::cout << "ICU support not enabled, feature unavailable"; - return 0; -} - - -#endif - diff --git a/test/module/msvc_test.bat b/test/module/msvc_test.bat index ee984c4e..23220c25 100644 --- a/test/module/msvc_test.bat +++ b/test/module/msvc_test.bat @@ -1,8 +1,26 @@ REM Basic command line to build everything with msvc: -cl /std:c++latest /EHsc /nologo /W4 /c "%VCToolsInstallDir%\modules\std.ixx" -cl /std:c++latest /EHsc /nologo /W4 /c /interface /I ..\..\..\.. ..\..\module\regex.cxx +del *.obj +del *.exe +del *.lib + +cl /std:c++latest /EHsc /nologo /W4 /c "%VCToolsInstallDir%\modules\std.ixx" || exit 1 +cl /std:c++latest /EHsc /nologo /W4 /c /interface /I ..\..\..\.. ..\..\module\regex.cxx || exit 1 +cl /std:c++latest /EHsc /nologo /W4 /c /I ..\..\..\.. ..\..\module\*.cpp || exit 1 + +lib *.obj /OUT:regex.lib || exit 1 + +time < nul for %%f in (*.cpp) do ( - cl /std:c++latest /EHsc /nologo /W4 /I ..\..\..\.. %%f std.obj regex.obj -) \ No newline at end of file + cl /std:c++latest /EHsc /nologo /W4 /I ..\..\..\.. %%f regex.lib || exit 1 +) + +time < nul + +for %%f in (*.cpp) do ( + cl /DTEST_HEADERS /std:c++latest /EHsc /nologo /W4 /I ..\..\..\.. %%f || exit 1 +) + +time < nul + diff --git a/test/module/partial_regex_grep.cpp b/test/module/partial_regex_grep.cpp index ab1ab7c3..e4fcd8d4 100644 --- a/test/module/partial_regex_grep.cpp +++ b/test/module/partial_regex_grep.cpp @@ -16,9 +16,9 @@ * DESCRIPTION: Search example using partial matches. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/partial_regex_iterate.cpp b/test/module/partial_regex_iterate.cpp index f7af6f59..c0099d0d 100644 --- a/test/module/partial_regex_iterate.cpp +++ b/test/module/partial_regex_iterate.cpp @@ -16,9 +16,9 @@ * DESCRIPTION: Search example using partial matches. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/partial_regex_match.cpp b/test/module/partial_regex_match.cpp index f262aeb7..fa61ab97 100644 --- a/test/module/partial_regex_match.cpp +++ b/test/module/partial_regex_match.cpp @@ -19,9 +19,9 @@ //#include -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_grep_example_1.cpp b/test/module/regex_grep_example_1.cpp index d7b7bcfc..131e538a 100644 --- a/test/module/regex_grep_example_1.cpp +++ b/test/module/regex_grep_example_1.cpp @@ -16,9 +16,9 @@ * DESCRIPTION: regex_grep example 1: searches a cpp file for class definitions. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_grep_example_2.cpp b/test/module/regex_grep_example_2.cpp index e25724b1..71d30c8d 100644 --- a/test/module/regex_grep_example_2.cpp +++ b/test/module/regex_grep_example_2.cpp @@ -17,9 +17,9 @@ * using a global callback function. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_grep_example_3.cpp b/test/module/regex_grep_example_3.cpp index 4b3040ee..35698dc5 100644 --- a/test/module/regex_grep_example_3.cpp +++ b/test/module/regex_grep_example_3.cpp @@ -17,9 +17,9 @@ * using a bound member function callback. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_iterator_example.cpp b/test/module/regex_iterator_example.cpp index c061425d..6568838c 100644 --- a/test/module/regex_iterator_example.cpp +++ b/test/module/regex_iterator_example.cpp @@ -17,9 +17,9 @@ * using global data. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_match_example.cpp b/test/module/regex_match_example.cpp index 99da2252..81dc8a49 100644 --- a/test/module/regex_match_example.cpp +++ b/test/module/regex_match_example.cpp @@ -16,9 +16,9 @@ * DESCRIPTION: ftp based regex_match example. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include @@ -33,7 +33,6 @@ import std.core; import boost.regex; #endif -using namespace std; using namespace boost; regex expression("^([0-9]+)(\\-| |$)(.*)$"); @@ -52,7 +51,7 @@ int process_ftp(const char* response, std::string* msg) // what[3] contains the text message. if(msg) msg->assign(what[3].first, what[3].second); - return ::atoi(what[1].first); + return std::atoi(what[1].first); } // failure did not match if(msg) @@ -62,6 +61,7 @@ int process_ftp(const char* response, std::string* msg) int main(int argc, const char*[]) { + using namespace std; std::string in, out; do { diff --git a/test/module/regex_merge_example.cpp b/test/module/regex_merge_example.cpp index 5110b74b..056551ab 100644 --- a/test/module/regex_merge_example.cpp +++ b/test/module/regex_merge_example.cpp @@ -17,9 +17,9 @@ * converts a C++ file to syntax highlighted HTML. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_replace_example.cpp b/test/module/regex_replace_example.cpp index 03fcc464..eeb2219d 100644 --- a/test/module/regex_replace_example.cpp +++ b/test/module/regex_replace_example.cpp @@ -17,9 +17,9 @@ * converts a C++ file to syntax highlighted HTML. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_search_example.cpp b/test/module/regex_search_example.cpp index 6d644562..5f6c551a 100644 --- a/test/module/regex_search_example.cpp +++ b/test/module/regex_search_example.cpp @@ -16,9 +16,9 @@ * DESCRIPTION: regex_search example: searches a cpp file for class definitions. */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_split_example_1.cpp b/test/module/regex_split_example_1.cpp index b4935809..22057b3f 100644 --- a/test/module/regex_split_example_1.cpp +++ b/test/module/regex_split_example_1.cpp @@ -17,10 +17,10 @@ */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) -import std.core; +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) +Simport std.core; #else #include #include diff --git a/test/module/regex_split_example_2.cpp b/test/module/regex_split_example_2.cpp index e96724c0..2773a306 100644 --- a/test/module/regex_split_example_2.cpp +++ b/test/module/regex_split_example_2.cpp @@ -17,9 +17,9 @@ */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_token_iterator_eg_1.cpp b/test/module/regex_token_iterator_eg_1.cpp index 0eebca93..f40a8fbc 100644 --- a/test/module/regex_token_iterator_eg_1.cpp +++ b/test/module/regex_token_iterator_eg_1.cpp @@ -17,9 +17,9 @@ */ -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include diff --git a/test/module/regex_token_iterator_eg_2.cpp b/test/module/regex_token_iterator_eg_2.cpp index 0304cad0..af5618bc 100644 --- a/test/module/regex_token_iterator_eg_2.cpp +++ b/test/module/regex_token_iterator_eg_2.cpp @@ -16,21 +16,22 @@ * DESCRIPTION: regex_token_iterator example: spit out linked URL's. */ -#ifdef TEST_HEADERS -#include -#else -import boost.regex; -#endif - -#ifdef __cpp_lib_modules +#if (defined(__cpp_lib_modules) || (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 193933523))) && !defined(TEST_HEADERS) import std; -#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) +#elif defined(MSVC_EXPERIMENTAL_STD_MODULE) && !defined(TEST_HEADERS) import std.core; #else #include #include #include #endif + +#ifdef TEST_HEADERS +#include +#else +import boost.regex; +#endif + boost::regex e("<\\s*A\\s+[^>]*href\\s*=\\s*\"([^\"]*)\"", boost::regex::normal | boost::regex::icase); diff --git a/test/module/test.sh b/test/module/test.sh deleted file mode 100755 index 65e51aee..00000000 --- a/test/module/test.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -# -# Builds all of the tests in this folder using the supplied compiler-specific script in $1 -# - -for file in *.cpp; do - -CXXFLAGS="-std=c++20 -g -I ../../../.." $1 $file ../../module/regex.cxx "${file%.*}.exe" || exit 1 - -done diff --git a/test/module/test_clang.sh b/test/module/test_clang.sh new file mode 100644 index 00000000..ef30af8b --- /dev/null +++ b/test/module/test_clang.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +# +# Builds all of the tests in this folder using clang modules +# +: ${CXX:="clang++"} +: ${CXXFLAGS:="-std=c++20 -g -I../../../.."} + +rm *.o *.pcm *.exe + +cmd="$CXX $CXXFLAGS -x c++-module ../../module/regex.cxx --precompile -o boost.regex.pcm" +echo $cmd +$cmd || exit 1 +cmd="$CXX $CXXFLAGS boost.regex.pcm -c -o regex.o" +echo $cmd +$cmd || exit 1 +cmd="$CXX $CXXFLAGS -fprebuilt-module-path=. -c ../../module/*.cpp" +echo $cmd +$cmd || exit 1 + + +for file in *.cpp; do + +cmd="$CXX $CXXFLAGS -fprebuilt-module-path=. $file *.o -o ${file%.*}.exe" +echo $cmd +$cmd || exit 1 + +done