From 1d5a14164a2392c2e52db52ad1e49dfdc711ddbe Mon Sep 17 00:00:00 2001 From: John Maddock Date: Mon, 7 Jun 2004 12:50:39 +0000 Subject: [PATCH] Fixed most of the compiler specific issues in the last commit. [SVN r23041] --- build/Jamfile | 3 + example/jgrep/main.cpp | 20 +- example/timer/regex_timer.cpp | 1 - include/boost/regex/concepts.hpp | 6 +- include/boost/regex/config.hpp | 7 +- include/boost/regex/v4/basic_regex.hpp | 2 +- include/boost/regex/v4/c_regex_traits.hpp | 2 +- include/boost/regex/v4/cpp_regex_traits.hpp | 6 + include/boost/regex/v4/instances.hpp | 2 +- include/boost/regex/v4/regex.hpp | 6 +- include/boost/regex/v4/regex_format.hpp | 8 +- include/boost/regex/v4/regex_fwd.hpp | 22 +- include/boost/regex/v4/regex_match.hpp | 64 ++++ include/boost/regex/v4/regex_traits.hpp | 18 +- include/boost/regex/v4/regex_workaround.hpp | 1 - include/boost/regex/v4/w32_regex_traits.hpp | 14 + src/c_regex_traits.cpp | 198 ++++++++++++ src/w32_regex_traits.cpp | 334 ++++++++++++++++++++ src/wc_regex_traits.cpp | 216 +++++++++++++ test/Jamfile | 2 - test/captures/Jamfile | 3 + test/concepts/concept_check.cpp | 17 +- test/regress/test.hpp | 6 + 23 files changed, 903 insertions(+), 55 deletions(-) create mode 100644 src/c_regex_traits.cpp create mode 100644 src/w32_regex_traits.cpp create mode 100644 src/wc_regex_traits.cpp diff --git a/build/Jamfile b/build/Jamfile index 2317b62a..09d24a66 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -38,6 +38,7 @@ template msvc-stlport-tricky ; SOURCES = + c_regex_traits.cpp cpp_regex_traits.cpp cregex.cpp fileiter.cpp @@ -48,6 +49,8 @@ SOURCES = regex_raw_buffer.cpp regex_traits_defaults.cpp static_mutex.cpp + w32_regex_traits.cpp + wc_regex_traits.cpp wide_posix_api.cpp winstances.cpp ; diff --git a/example/jgrep/main.cpp b/example/jgrep/main.cpp index b5d11f42..c625f494 100644 --- a/example/jgrep/main.cpp +++ b/example/jgrep/main.cpp @@ -18,15 +18,8 @@ #include #include #include -#ifdef JM_OLD_IOSTREAM -#include -#else #include -using std::cout; -using std::cin; -using std::cerr; -using std::endl; -#endif +using namespace std; #ifdef __BORLANDC__ # pragma hrdstop #endif @@ -38,12 +31,13 @@ using std::endl; #endif #include "jgrep.h" #ifndef BOOST_REGEX_NO_FILEITER - -#ifndef JM_ALGO_INCLUDED -// HP and SGI STL's use instead -// this will have been pulled in by -// for std::distance #include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strcpy; using ::strcat; + using ::sprintf; +} #endif re_type e; diff --git a/example/timer/regex_timer.cpp b/example/timer/regex_timer.cpp index 6280f5c2..af1f01b5 100644 --- a/example/timer/regex_timer.cpp +++ b/example/timer/regex_timer.cpp @@ -39,7 +39,6 @@ using std::getline; #if defined(_WIN32) && defined(BOOST_REGEX_USE_WIN32_LOCALE) #include -#pragma comment(lib, "user32.lib") #endif #if (defined(_MSC_VER) && (_MSC_VER <= 1300)) || defined(__sgi) diff --git a/include/boost/regex/concepts.hpp b/include/boost/regex/concepts.hpp index 8773c1de..de3e5c9f 100644 --- a/include/boost/regex/concepts.hpp +++ b/include/boost/regex/concepts.hpp @@ -528,7 +528,7 @@ struct BaseRegexConcept BidiIterator m_in; global_regex_namespace::regex_constants::match_flag_type m_mft; global_regex_namespace::match_results m_pmatch; -private: + BaseRegexConcept(); BaseRegexConcept(const BaseRegexConcept&); BaseRegexConcept& operator=(const BaseRegexConcept&); @@ -727,7 +727,7 @@ struct RegexConcept BidiIterator m_in; global_regex_namespace::regex_constants::match_flag_type m_mft; global_regex_namespace::match_results m_smatch; -private: + RegexConcept(); RegexConcept(const RegexConcept&); RegexConcept& operator=(const RegexConcept&); @@ -818,7 +818,7 @@ struct BoostRegexConcept const value_type m_char; match_results_type m_results; const match_results_type m_cresults; -private: + BoostRegexConcept(); BoostRegexConcept(const BoostRegexConcept&); BoostRegexConcept& operator=(const BoostRegexConcept&); diff --git a/include/boost/regex/config.hpp b/include/boost/regex/config.hpp index 9cc86202..3a8a75eb 100644 --- a/include/boost/regex/config.hpp +++ b/include/boost/regex/config.hpp @@ -115,7 +115,6 @@ #if defined(__GNUC__) && (defined(_WIN32) || defined(__CYGWIN__)) // gcc on win32 has problems if you include // (sporadically generates bad code). -# define BOOST_REGEX_USE_C_LOCALE # define BOOST_REGEX_NO_W32 #endif #if defined(__COMO__) && !defined(BOOST_REGEX_NO_W32) && !defined(_MSC_EXTENSIONS) @@ -214,7 +213,11 @@ namespace boost{ typedef wchar_t regex_wchar_type; } #if defined(_WIN32) && !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) && !defined(BOOST_REGEX_NO_W32) # define BOOST_REGEX_USE_WIN32_LOCALE #endif -// otherwise use C locale: +// otherwise use C++ locale if supported: +#if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) && !defined(BOOST_NO_STD_LOCALE) +# define BOOST_REGEX_USE_CPP_LOCALE +#endif +// otherwise use C+ locale: #if !defined(BOOST_REGEX_USE_WIN32_LOCALE) && !defined(BOOST_REGEX_USE_C_LOCALE) && !defined(BOOST_REGEX_USE_CPP_LOCALE) # define BOOST_REGEX_USE_C_LOCALE #endif diff --git a/include/boost/regex/v4/basic_regex.hpp b/include/boost/regex/v4/basic_regex.hpp index 1696266b..5260f870 100644 --- a/include/boost/regex/v4/basic_regex.hpp +++ b/include/boost/regex/v4/basic_regex.hpp @@ -502,7 +502,7 @@ basic_regex& basic_regex::assign(const charT* p1, { temp = shared_ptr >(new re_detail::basic_regex_implementation()); } - else if(!m_pimpl.unique()) + else { temp = shared_ptr >(new re_detail::basic_regex_implementation(m_pimpl->m_ptraits)); } diff --git a/include/boost/regex/v4/c_regex_traits.hpp b/include/boost/regex/v4/c_regex_traits.hpp index f15c8084..72004404 100644 --- a/include/boost/regex/v4/c_regex_traits.hpp +++ b/include/boost/regex/v4/c_regex_traits.hpp @@ -64,7 +64,7 @@ struct BOOST_REGEX_DECL c_regex_traits } char translate_nocase(char c) const { - return (std::tolower)(c); + return static_cast((std::tolower)(static_cast(c))); } static string_type BOOST_REGEX_CALL transform(const char* p1, const char* p2); diff --git a/include/boost/regex/v4/cpp_regex_traits.hpp b/include/boost/regex/v4/cpp_regex_traits.hpp index 8447af86..5b71eadd 100644 --- a/include/boost/regex/v4/cpp_regex_traits.hpp +++ b/include/boost/regex/v4/cpp_regex_traits.hpp @@ -19,6 +19,10 @@ #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED #define BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +#include + +#ifndef BOOST_NO_STD_LOCALE + #ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED #include #endif @@ -801,3 +805,5 @@ static_mutex& cpp_regex_traits::get_mutex_inst() #endif #endif + +#endif diff --git a/include/boost/regex/v4/instances.hpp b/include/boost/regex/v4/instances.hpp index 182f2207..762e39be 100644 --- a/include/boost/regex/v4/instances.hpp +++ b/include/boost/regex/v4/instances.hpp @@ -57,7 +57,7 @@ template class BOOST_REGEX_DECL basic_regex< BOOST_REGEX_CHAR_T >; # include BOOST_ABI_SUFFIX #endif -#elif defined(BOOST_MSVC) || defined(__GNUC__) +#elif defined(BOOST_MSVC) # ifndef BOOST_REGEX_INSTANTIATE # define template extern template diff --git a/include/boost/regex/v4/regex.hpp b/include/boost/regex/v4/regex.hpp index 2559a4f1..dc39f9a6 100644 --- a/include/boost/regex/v4/regex.hpp +++ b/include/boost/regex/v4/regex.hpp @@ -89,18 +89,18 @@ #ifdef BOOST_REGEX_NARROW_INSTANTIATE # define BOOST_REGEX_INSTANTIATE #endif -//#include +#include #undef BOOST_REGEX_CHAR_T #ifdef BOOST_REGEX_INSTANTIATE # undef BOOST_REGEX_INSTANTIATE #endif #ifndef BOOST_NO_WREGEX -#define BOOST_REGEX_CHAR_T boost::regex_wchar_type +#define BOOST_REGEX_CHAR_T wchar_t #ifdef BOOST_REGEX_WIDE_INSTANTIATE # define BOOST_REGEX_INSTANTIATE #endif -//#include +#include #undef BOOST_REGEX_CHAR_T #ifdef BOOST_REGEX_INSTANTIATE # undef BOOST_REGEX_INSTANTIATE diff --git a/include/boost/regex/v4/regex_format.hpp b/include/boost/regex/v4/regex_format.hpp index 13fe740c..cccc5029 100644 --- a/include/boost/regex/v4/regex_format.hpp +++ b/include/boost/regex/v4/regex_format.hpp @@ -31,7 +31,7 @@ namespace boost{ // // Forward declaration: // -template ) > + template >::allocator_type > class match_results; namespace re_detail{ @@ -483,9 +483,9 @@ public: } }; -template +template OutputIterator regex_format_imp(OutputIterator out, - const match_results& m, + const match_results& m, const charT* p1, const charT* p2, match_flag_type flags, const traits& t @@ -493,7 +493,7 @@ OutputIterator regex_format_imp(OutputIterator out, { re_detail::basic_regex_formatter< OutputIterator, - match_results, + match_results, traits > f(out, m, t); return f.format(p1, p2, flags); } diff --git a/include/boost/regex/v4/regex_fwd.hpp b/include/boost/regex/v4/regex_fwd.hpp index db16eba5..704104ed 100644 --- a/include/boost/regex/v4/regex_fwd.hpp +++ b/include/boost/regex/v4/regex_fwd.hpp @@ -21,7 +21,7 @@ #define BOOST_REGEX_FWD_HPP_INCLUDED #ifndef BOOST_REGEX_CONFIG_HPP -#include +#include #endif // @@ -34,21 +34,25 @@ # endif #else -// -// If there isn't good enough wide character support then there will -// be no wide character regular expressions: -// -#if (defined(BOOST_NO_CWCHAR) || defined(BOOST_NO_CWCTYPE) || defined(BOOST_NO_STD_WSTRING)) && !defined(BOOST_NO_WREGEX) -# define BOOST_NO_WREGEX -#endif - namespace boost{ template class cpp_regex_traits; +template +struct c_regex_traits; +template +class w32_regex_traits; +#ifdef BOOST_REGEX_USE_WIN32_LOCALE +template > +struct regex_traits; +#elif defined(BOOST_REGEX_USE_CPP_LOCALE) template > struct regex_traits; +#else +template > +struct regex_traits; +#endif template > class basic_regex; diff --git a/include/boost/regex/v4/regex_match.hpp b/include/boost/regex/v4/regex_match.hpp index bc52750d..4e3123f2 100644 --- a/include/boost/regex/v4/regex_match.hpp +++ b/include/boost/regex/v4/regex_match.hpp @@ -135,6 +135,22 @@ inline bool regex_match(const char* str, match_results m; return regex_match(str, str + regex::traits_type::length(str), m, e, flags); } +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const char* str, + cmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const char* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + regex::traits_type::length(str), m, e, flags); +} +#endif #ifndef BOOST_NO_WREGEX inline bool regex_match(const wchar_t* str, wcmatch& m, @@ -178,6 +194,22 @@ inline bool regex_match(const wchar_t* str, match_results m; return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); } +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const wchar_t* str, + wcmatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +inline bool regex_match(const wchar_t* str, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); +} +#endif #endif inline bool regex_match(const std::string& s, smatch& m, @@ -221,6 +253,22 @@ inline bool regex_match(const std::string& s, match_results m; return regex_match(s.begin(), s.end(), m, e, flags); } +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const std::string& s, + smatch& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results m; + return regex_match(s.begin(), s.end(), m, e, flags); +} +#endif #if !defined(BOOST_NO_WREGEX) inline bool regex_match(const std::basic_string& s, match_results::const_iterator>& m, @@ -264,6 +312,22 @@ inline bool regex_match(const std::basic_string& s, match_results::const_iterator> m; return regex_match(s.begin(), s.end(), m, e, flags); } +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +inline bool regex_match(const std::basic_string& s, + match_results::const_iterator>& m, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + return regex_match(s.begin(), s.end(), m, e, flags); +} +inline bool regex_match(const std::basic_string& s, + const basic_regex >& e, + match_flag_type flags = match_default) +{ + match_results::const_iterator> m; + return regex_match(s.begin(), s.end(), m, e, flags); +} +#endif #endif #endif diff --git a/include/boost/regex/v4/regex_traits.hpp b/include/boost/regex/v4/regex_traits.hpp index d7325836..866076e1 100644 --- a/include/boost/regex/v4/regex_traits.hpp +++ b/include/boost/regex/v4/regex_traits.hpp @@ -31,14 +31,20 @@ #ifndef BOOST_REGEX_ERROR_TYPE_HPP #include #endif -#ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED -#include +#ifndef BOOST_NO_STD_LOCALE +# ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED +# include +# endif #endif -#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED -#include +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x560) +# ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +# include +# endif #endif -#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED -#include +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +# ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +# include +# endif #endif #ifndef BOOST_REGEX_FWD_HPP_INCLUDED #include diff --git a/include/boost/regex/v4/regex_workaround.hpp b/include/boost/regex/v4/regex_workaround.hpp index 41be928c..22564519 100644 --- a/include/boost/regex/v4/regex_workaround.hpp +++ b/include/boost/regex/v4/regex_workaround.hpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/include/boost/regex/v4/w32_regex_traits.hpp b/include/boost/regex/v4/w32_regex_traits.hpp index 6f692eca..19667e07 100644 --- a/include/boost/regex/v4/w32_regex_traits.hpp +++ b/include/boost/regex/v4/w32_regex_traits.hpp @@ -59,20 +59,34 @@ typedef ::boost::shared_ptr cat_type; // placeholder for dll HANDLE. // BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale(); BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char, lcid_type); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type); +#endif BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type); +#endif BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name); BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type id, int i, const std::string& def); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type id, int i, const std::wstring& def); +#endif BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const char* p1, const char* p2); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const wchar_t* p1, const wchar_t* p2); +#endif BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type); +#endif BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type); +#endif BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c); +#ifndef BOOST_NO_WREGEX BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c); +#endif // // class w32_regex_traits_base: // acts as a container for locale and the facets we are using. diff --git a/src/c_regex_traits.cpp b/src/c_regex_traits.cpp new file mode 100644 index 00000000..697dc17c --- /dev/null +++ b/src/c_regex_traits.cpp @@ -0,0 +1,198 @@ +/* + * + * Copyright (c) 2004 + * Dr 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: c_regex_traits.cpp + * VERSION: see + * DESCRIPTION: Implements out of line c_regex_traits members + */ + + +#define BOOST_REGEX_SOURCE + +#include +#include + +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x560) + +#include +#include +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strxfrm; using ::isspace; + using ::ispunct; using ::isalpha; + using ::isalnum; using ::iscntrl; + using ::isprint; using ::isupper; + using ::islower; using ::isdigit; + using ::isxdigit; using ::strtol; +} +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost{ + +c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform(const char* p1, const char* p2) +{ + std::size_t s = 10; + std::string result(s, ' '); + std::size_t r; + std::string src(p1, p2); + while(s < (r = std::strxfrm(&*result.begin(), src.c_str(), result.size()))) + { + result.append(r - s + 3, ' '); + } + result.erase(r); + return result; +} + +c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform_primary(const char* p1, const char* p2) +{ + static char s_delim; + static const int s_collate_type = ::boost::re_detail::find_sort_syntax(static_cast*>(0), &s_delim); + std::string result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(s_collate_type) + { + case ::boost::re_detail::sort_C: + case ::boost::re_detail::sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + for(std::string::size_type i = 0; i < result.size(); ++i) + result[i] = (std::tolower)(static_cast(result[i])); + result = transform(&*result.begin(), &*result.end()); + break; + } + case ::boost::re_detail::sort_fixed: + { + // get a regular sort key, and then truncate it: + result = transform(p1, p2); + result.erase(s_delim); + break; + } + case ::boost::re_detail::sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result = transform(p1, p2); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == s_delim) + break; + } + result.erase(i); + break; + } + return result; +} + +enum +{ + char_class_space=1<<0, + char_class_print=1<<1, + char_class_cntrl=1<<2, + char_class_upper=1<<3, + char_class_lower=1<<4, + char_class_alpha=1<<5, + char_class_digit=1<<6, + char_class_punct=1<<7, + char_class_xdigit=1<<8, + char_class_alnum=char_class_alpha|char_class_digit, + char_class_graph=char_class_alnum|char_class_punct, + char_class_blank=1<<9, + char_class_word=1<<10, + char_class_unicode=1<<11 +}; + +c_regex_traits::char_class_type BOOST_REGEX_CALL c_regex_traits::lookup_classname(const char* p1, const char* p2) +{ + static const char_class_type masks[] = + { + 0, + char_class_alnum, + char_class_alpha, + char_class_blank, + char_class_cntrl, + char_class_digit, + char_class_digit, + char_class_graph, + char_class_lower, + char_class_lower, + char_class_print, + char_class_punct, + char_class_space, + char_class_space, + char_class_upper, + char_class_unicode, + char_class_upper, + char_class_alnum | char_class_word, + char_class_alnum | char_class_word, + char_class_xdigit, + }; + + int id = ::boost::re_detail::get_default_class_id(p1, p2); + if(id < 0) + { + std::string s(p1, p2); + for(std::string::size_type i = 0; i < s.size(); ++i) + s[i] = (std::tolower)(static_cast(s[i])); + id = ::boost::re_detail::get_default_class_id(&*s.begin(), &*s.end()); + } + BOOST_ASSERT(id+1 < sizeof(masks) / sizeof(masks[0])); + return masks[id+1]; +} + +bool BOOST_REGEX_CALL c_regex_traits::isctype(char c, char_class_type mask) +{ + return + ((mask & char_class_space) && (std::isspace)(static_cast(c))) + || ((mask & char_class_print) && (std::isprint)(static_cast(c))) + || ((mask & char_class_cntrl) && (std::iscntrl)(static_cast(c))) + || ((mask & char_class_upper) && (std::isupper)(static_cast(c))) + || ((mask & char_class_lower) && (std::islower)(static_cast(c))) + || ((mask & char_class_alpha) && (std::isalpha)(static_cast(c))) + || ((mask & char_class_digit) && (std::isdigit)(static_cast(c))) + || ((mask & char_class_punct) && (std::ispunct)(static_cast(c))) + || ((mask & char_class_xdigit) && (std::isxdigit)(static_cast(c))) + || ((mask & char_class_blank) && (std::isspace)(static_cast(c)) && !::boost::re_detail::is_separator(c)) + || ((mask & char_class_word) && (c == '_')); +} + +c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::lookup_collatename(const char* p1, const char* p2) +{ + std::string s(p1, p2); + return ::boost::re_detail::lookup_default_collate_name(s); +} + +int BOOST_REGEX_CALL c_regex_traits::value(char c, int radix) +{ + char b[2] = { c, '\0', }; + char* ep; + int result = std::strtol(b, &ep, radix); + if(ep == b) + return -1; + return result; +} + +} +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif diff --git a/src/w32_regex_traits.cpp b/src/w32_regex_traits.cpp new file mode 100644 index 00000000..120ee806 --- /dev/null +++ b/src/w32_regex_traits.cpp @@ -0,0 +1,334 @@ +/* + * + * Copyright (c) 2004 + * Dr 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 w32_regex_traits.cpp + * VERSION see + * DESCRIPTION: Implements w32_regex_traits (and associated helper classes). + */ + +#define BOOST_REGEX_SOURCE +#include + +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) +#include + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NOGDI +#include + +#ifdef _MSC_VER +#pragma comment(lib, "user32.lib") +#endif + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::memset; +} +#endif + +namespace boost{ namespace re_detail{ + +void w32_regex_traits_char_layer::init() +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + std::memset(m_char_map, 0, sizeof(m_char_map)); + cat_type cat; + std::string cat_name(w32_regex_traits::get_catalog_name()); + if(cat_name.size()) + { + cat = ::boost::re_detail::w32_cat_open(cat_name); + if(!cat) + { + std::string m("Unable to open message catalog: "); + std::runtime_error err(m + cat_name); + boost::throw_exception(err); + } + } + // + // if we have a valid catalog then load our messages: + // + if(cat) + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + string_type mss = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i, get_default_syntax(i)); + for(string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[static_cast(mss[j])] = i; + } + } + } + else + { + for(regex_constants::syntax_type i = 1; i < regex_constants::syntax_max; ++i) + { + const char* ptr = get_default_syntax(i); + while(ptr && *ptr) + { + m_char_map[static_cast(*ptr)] = i; + ++ptr; + } + } + } + // + // finish off by calculating our escape types: + // + unsigned char i = 'A'; + do + { + if(m_char_map[i] == 0) + { + if(::boost::re_detail::w32_is(this->m_locale, 0x0002u, (char)i)) + m_char_map[i] = regex_constants::escape_type_class; + else if(::boost::re_detail::w32_is(this->m_locale, 0x0001u, (char)i)) + m_char_map[i] = regex_constants::escape_type_not_class; + } + }while(0xFF != i++); +} + +BOOST_REGEX_DECL lcid_type BOOST_REGEX_CALL w32_get_default_locale() +{ + return ::GetUserDefaultLCID(); +} + +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(char c, lcid_type id) +{ + WORD mask; + if(::GetStringTypeExA(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER)) + return true; + return false; +} + +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t c, lcid_type id) +{ + WORD mask; + if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_LOWER)) + return true; + return false; +} + +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char c, lcid_type id) +{ + WORD mask; + if(::GetStringTypeExA(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER)) + return true; + return false; +} + +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t c, lcid_type id) +{ + WORD mask; + if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & C1_UPPER)) + return true; + return false; +} + +void free_module(void* mod) +{ + ::FreeLibrary(static_cast(mod)); +} + +BOOST_REGEX_DECL cat_type BOOST_REGEX_CALL w32_cat_open(const std::string& name) +{ + cat_type result(::LoadLibrary(name.c_str()), &free_module); + return result; +} + +BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type id, int i, const std::string& def) +{ + char buf[256]; + if(0 == ::LoadStringA( + static_cast(cat.get()), + i, + buf, + 256 + )) + { + return def; + } + return buf; +} + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type id, int i, const std::wstring& def) +{ + wchar_t buf[256]; + if(0 == ::LoadStringW( + static_cast(cat.get()), + i, + buf, + 256 + )) + { + return def; + } + return buf; +} +#endif +BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const char* p1, const char* p2) +{ + int bytes = ::LCMapStringA( + id, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + p2 - p1, // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if(!bytes) + return std::string(p1, p2); + std::string result(++bytes, '\0'); + bytes = ::LCMapStringA( + id, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + p2 - p1, // number of characters in source string + &*result.begin(), // destination buffer + bytes // size of destination buffer + ); + if(bytes > result.size()) + return std::string(p1, p2); + while(result.size() && result[result.size()-1] == '\0') + { + result.erase(result.size()-1); + } + return result; +} + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const wchar_t* p1, const wchar_t* p2) +{ + int bytes = ::LCMapStringW( + id, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + p2 - p1, // number of characters in source string + 0, // destination buffer + 0 // size of destination buffer + ); + if(!bytes) + return std::wstring(p1, p2); + std::string result(++bytes, '\0'); + bytes = ::LCMapStringW( + id, // locale identifier + LCMAP_SORTKEY, // mapping transformation type + p1, // source string + p2 - p1, // number of characters in source string + reinterpret_cast(&*result.begin()), // destination buffer *of bytes* + bytes // size of destination buffer + ); + if(bytes > result.size()) + return std::wstring(p1, p2); + while(result.size() && result[result.size()-1] == L'\0') + { + result.erase(result.size()-1); + } + std::wstring r2; + for(std::string::size_type i = 0; i < result.size(); ++i) + r2.append(1, static_cast(static_cast(result[i]))); + return r2; +} +#endif +BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type id) +{ + char result[2]; + int b = ::LCMapStringA( + id, // locale identifier + LCMAP_LOWERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if(b == 0) + return c; + return result[0]; +} + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type id) +{ + wchar_t result[2]; + int b = ::LCMapStringW( + id, // locale identifier + LCMAP_LOWERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if(b == 0) + return c; + return result[0]; +} +#endif +BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type id) +{ + char result[2]; + int b = ::LCMapStringA( + id, // locale identifier + LCMAP_UPPERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if(b == 0) + return c; + return result[0]; +} + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type id) +{ + wchar_t result[2]; + int b = ::LCMapStringW( + id, // locale identifier + LCMAP_UPPERCASE, // mapping transformation type + &c, // source string + 1, // number of characters in source string + result, // destination buffer + 1); // size of destination buffer + if(b == 0) + return c; + return result[0]; +} +#endif +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type id, boost::uint32_t m, char c) +{ + WORD mask; + if(::GetStringTypeExA(id, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; + if((m & w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + return false; +} + +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type id, boost::uint32_t m, wchar_t c) +{ + WORD mask; + if(::GetStringTypeExW(id, CT_CTYPE1, &c, 1, &mask) && (mask & m & w32_regex_traits_implementation::mask_base)) + return true; + if((m & w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + if((m & w32_regex_traits_implementation::mask_unicode) && (c > 0xff)) + return true; + return false; +} +#endif + +} // re_detail +} // boost + +#endif + diff --git a/src/wc_regex_traits.cpp b/src/wc_regex_traits.cpp new file mode 100644 index 00000000..a4230a04 --- /dev/null +++ b/src/wc_regex_traits.cpp @@ -0,0 +1,216 @@ +/* + * + * Copyright (c) 2004 + * Dr 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: wc_regex_traits.cpp + * VERSION: see + * DESCRIPTION: Implements out of line members for c_regex_traits + */ + + +#define BOOST_REGEX_SOURCE + +#include +#include + +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x560) + +#include +#ifndef BOOST_NO_WREGEX +#include +#include + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::wcstol; +} +#endif + +namespace boost{ + +c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform(const wchar_t* p1, const wchar_t* p2) const +{ + std::size_t r; + std::size_t s = 10; + std::wstring src(p1, p2); + std::wstring result(s, L' '); + while(s < (r = std::wcsxfrm(&*result.begin(), src.c_str(), result.size()))) + { + result.append(r - s + 3, L' '); + } + result.erase(r); + return result; +} + +c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::transform_primary(const wchar_t* p1, const wchar_t* p2) const +{ + static wchar_t s_delim; + static const int s_collate_type = ::boost::re_detail::find_sort_syntax(this, &s_delim); + std::wstring result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(s_collate_type) + { + case ::boost::re_detail::sort_C: + case ::boost::re_detail::sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + for(std::wstring::size_type i = 0; i < result.size(); ++i) + result[i] = (std::towlower)(result[i]); + result = this->transform(&*result.begin(), &*result.end()); + break; + } + case ::boost::re_detail::sort_fixed: + { + // get a regular sort key, and then truncate it: + result = this->transform(&*result.begin(), &*result.end()); + result.erase(s_delim); + break; + } + case ::boost::re_detail::sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result = this->transform(&*result.begin(), &*result.end()); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == s_delim) + break; + } + result.erase(i); + break; + } + return result; +} + +enum +{ + char_class_space=1<<0, + char_class_print=1<<1, + char_class_cntrl=1<<2, + char_class_upper=1<<3, + char_class_lower=1<<4, + char_class_alpha=1<<5, + char_class_digit=1<<6, + char_class_punct=1<<7, + char_class_xdigit=1<<8, + char_class_alnum=char_class_alpha|char_class_digit, + char_class_graph=char_class_alnum|char_class_punct, + char_class_blank=1<<9, + char_class_word=1<<10, + char_class_unicode=1<<11 +}; + +c_regex_traits::char_class_type BOOST_REGEX_CALL c_regex_traits::lookup_classname(const wchar_t* p1, const wchar_t* p2) const +{ + static const char_class_type masks[] = + { + 0, + char_class_alnum, + char_class_alpha, + char_class_blank, + char_class_cntrl, + char_class_digit, + char_class_digit, + char_class_graph, + char_class_lower, + char_class_lower, + char_class_print, + char_class_punct, + char_class_space, + char_class_space, + char_class_upper, + char_class_unicode, + char_class_upper, + char_class_alnum | char_class_word, + char_class_alnum | char_class_word, + char_class_xdigit, + }; + + int id = ::boost::re_detail::get_default_class_id(p1, p2); + if(id < 0) + { + std::wstring s(p1, p2); + for(std::wstring::size_type i = 0; i < s.size(); ++i) + s[i] = (std::towlower)(s[i]); + id = ::boost::re_detail::get_default_class_id(&*s.begin(), &*s.end()); + } + BOOST_ASSERT(id+1 < sizeof(masks) / sizeof(masks[0])); + return masks[id+1]; +} + +bool BOOST_REGEX_CALL c_regex_traits::isctype(wchar_t c, char_class_type mask) const +{ + return + ((mask & char_class_space) && (std::iswspace)(c)) + || ((mask & char_class_print) && (std::iswprint)(c)) + || ((mask & char_class_cntrl) && (std::iswcntrl)(c)) + || ((mask & char_class_upper) && (std::iswupper)(c)) + || ((mask & char_class_lower) && (std::iswlower)(c)) + || ((mask & char_class_alpha) && (std::iswalpha)(c)) + || ((mask & char_class_digit) && (std::iswdigit)(c)) + || ((mask & char_class_punct) && (std::iswpunct)(c)) + || ((mask & char_class_xdigit) && (std::iswxdigit)(c)) + || ((mask & char_class_blank) && (std::iswspace)(c) && !::boost::re_detail::is_separator(c)) + || ((mask & char_class_word) && (c == '_')) + || ((mask & char_class_unicode) && (c & ~static_cast(0xff))); +} + +c_regex_traits::string_type BOOST_REGEX_CALL c_regex_traits::lookup_collatename(const wchar_t* p1, const wchar_t* p2) const +{ +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + std::string name(p1, p2); +#else + std::string name; + const charT* p0 = p1; + while(p0 != p2) + name.append(1, char(*p0++)); +#endif + name = ::boost::re_detail::lookup_default_collate_name(name); +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + if(name.size()) + return string_type(name.begin(), name.end()); +#else + if(name.size()) + { + string_type result; + typedef std::string::const_iterator iter; + iter b = name.begin(); + iter e = name.end(); + while(b != e) + result.append(1, charT(*b++)); + return result; + } +#endif + if(p2 - p1 == 1) + return string_type(1, *p1); + return string_type(); +} + +int BOOST_REGEX_CALL c_regex_traits::value(wchar_t c, int radix) const +{ + wchar_t b[2] = { c, '\0', }; + wchar_t* ep; + int result = std::wcstol(b, &ep, radix); + if(ep == b) + return -1; + return result; +} + +} + +#endif // BOOST_NO_WREGEX + +#endif // __BORLANDC__ + diff --git a/test/Jamfile b/test/Jamfile index a78af05b..5432cc1c 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -115,8 +115,6 @@ test-suite regex [ compile concepts/concept_check.cpp ] - [ compile concepts/wide_concept_check.cpp - ] [ run # sources diff --git a/test/captures/Jamfile b/test/captures/Jamfile index 465ede3f..4817028d 100644 --- a/test/captures/Jamfile +++ b/test/captures/Jamfile @@ -3,6 +3,7 @@ subproject libs/regex/test/captures ; EX_SOURCES = + c_regex_traits.cpp cpp_regex_traits.cpp cregex.cpp fileiter.cpp @@ -13,6 +14,8 @@ EX_SOURCES = regex_raw_buffer.cpp regex_traits_defaults.cpp static_mutex.cpp + w32_regex_traits.cpp + wc_regex_traits.cpp wide_posix_api.cpp winstances.cpp ; diff --git a/test/concepts/concept_check.cpp b/test/concepts/concept_check.cpp index e90ceafb..59d0f1ff 100644 --- a/test/concepts/concept_check.cpp +++ b/test/concepts/concept_check.cpp @@ -17,9 +17,10 @@ #pragma option -w-8019 -w-8004 -w-8008 #endif #include -#include #include - +#if !BOOST_WORKAROUND(_MSC_VER, < 1310) && !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__GNUC__, < 3) +#include +#endif boost::re_detail::digraph get_next_set_literal(); @@ -33,6 +34,7 @@ int main() boost::regex_traits > >(); +#ifndef BOOST_NO_STD_LOCALE boost::function_requires< boost::BoostRegexConcept< boost::basic_regex > @@ -45,6 +47,8 @@ int main() > >(); #endif +#endif +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x560) boost::function_requires< boost::BoostRegexConcept< boost::basic_regex > @@ -57,11 +61,8 @@ int main() > >(); #endif - boost::function_requires< - boost::RegexTraitsConcept< - boost::regex_traits - > - >(); +#endif +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) boost::function_requires< boost::BoostRegexConcept< boost::basic_regex > @@ -74,7 +75,7 @@ int main() > >(); #endif - +#endif // // now test the regex_traits concepts: // diff --git a/test/regress/test.hpp b/test/regress/test.hpp index 055e7f4d..af62f6ce 100644 --- a/test/regress/test.hpp +++ b/test/regress/test.hpp @@ -15,12 +15,18 @@ template void test(const charT& c, const tagT& tag) { +#ifndef BOOST_NO_STD_LOCALE boost::basic_regex > e1; test(e1, tag); +#endif +#if !BOOST_WORKAROUND(__BORLANDC__, < 0x560) boost::basic_regex > e2; test(e2, tag); +#endif +#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) boost::basic_regex > e3; test(e3, tag); +#endif // test old depecated code: test_deprecated(c, tag); }