From bdb4c091f1bb4dd234dc66f7bf55b93f73610ab5 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sat, 22 May 2004 11:04:22 +0000 Subject: [PATCH] Rewritten regex formatting code, refactored headers to reduce dependencies. [SVN r22891] --- example/timer/regex_timer.cpp | 6 + include/boost/regex/config.hpp | 190 +--- include/boost/regex/pattern_except.hpp | 19 + .../boost/regex/v4/basic_regex_creator.hpp | 6 +- include/boost/regex/v4/basic_regex_parser.hpp | 14 +- include/boost/regex/v4/cpp_regex_traits.hpp | 8 + include/boost/regex/v4/cregex.hpp | 6 + include/boost/regex/v4/match_results.hpp | 29 +- .../boost/regex/v4/perl_matcher_common.hpp | 9 +- .../regex/v4/perl_matcher_non_recursive.hpp | 14 +- .../boost/regex/v4/perl_matcher_recursive.hpp | 14 +- include/boost/regex/v4/protected_call.hpp | 65 ++ include/boost/regex/v4/regex.hpp | 54 +- include/boost/regex/v4/regex_format.hpp | 903 ++++++++++-------- include/boost/regex/v4/regex_iterator.hpp | 10 +- include/boost/regex/v4/regex_kmp.hpp | 2 +- include/boost/regex/v4/regex_raw_buffer.hpp | 2 + include/boost/regex/v4/regex_replace.hpp | 34 +- .../boost/regex/v4/regex_token_iterator.hpp | 16 +- include/boost/regex/v4/regex_traits.hpp | 11 +- include/boost/regex/v4/regex_workaround.hpp | 114 +++ include/boost/regex/v4/states.hpp | 2 +- include/boost/regex/v4/sub_match.hpp | 6 +- src/cregex.cpp | 8 +- src/fileiter.cpp | 20 +- src/posix_api.cpp | 12 +- src/regex.cpp | 30 + src/regex_raw_buffer.cpp | 10 + src/regex_traits_defaults.cpp | 39 +- src/wide_posix_api.cpp | 14 +- test/Jamfile | 2 + test/regress/basic_tests.cpp | 17 +- test/regress/test_deprecated.cpp | 5 + 33 files changed, 1001 insertions(+), 690 deletions(-) create mode 100644 include/boost/regex/v4/protected_call.hpp create mode 100644 include/boost/regex/v4/regex_workaround.hpp diff --git a/example/timer/regex_timer.cpp b/example/timer/regex_timer.cpp index 67484858..6280f5c2 100644 --- a/example/timer/regex_timer.cpp +++ b/example/timer/regex_timer.cpp @@ -33,9 +33,15 @@ using std::getline; #include #include +#include #include #include +#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) // maybe no Koenig lookup, use using declaration instead: using namespace boost; diff --git a/include/boost/regex/config.hpp b/include/boost/regex/config.hpp index bcea0fb2..9cc86202 100644 --- a/include/boost/regex/config.hpp +++ b/include/boost/regex/config.hpp @@ -40,30 +40,8 @@ # include BOOST_REGEX_USER_CONFIG -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include # include -# include -# include -# include -# include -# include -# include -# include -# include -# ifndef BOOST_NO_STD_LOCALE -# include -# endif + #else // // C build, @@ -122,27 +100,6 @@ #if defined(BOOST_DISABLE_WIN32) && !defined(BOOST_REGEX_NO_W32) # define BOOST_REGEX_NO_W32 #endif -#if defined(_WIN32) && !defined(BOOST_REGEX_NO_W32) -# include -#endif - -// some versions of gcc can't merge template instances: -#if defined(__CYGWIN__) -# define BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE -#endif - -// fix problems with bool as a macro, -// this probably doesn't affect any current compilers: -#if defined(bool) || defined(true) || defined(false) -# define BOOST_REGEX_NO_BOOL -#endif - -// We don't make our templates external if the compiler -// can't handle it: -#if (defined(BOOST_NO_MEMBER_FUNCTION_SPECIALIZATIONS) || defined(__HP_aCC) || defined(__MWERKS__) || defined(__COMO__) || defined(BOOST_INTEL))\ - && !defined(BOOST_MSVC) && !defined(__BORLANDC__) -# define BOOST_REGEX_NO_EXTERNAL_TEMPLATES -#endif // disable our own file-iterators and mapfiles if we can't // support them: @@ -150,44 +107,12 @@ # define BOOST_REGEX_NO_FILEITER #endif -#ifdef __cplusplus -#ifndef MB_CUR_MAX -// yuk! -// better make a conservative guess! -#define MB_CUR_MAX 10 -#endif - -namespace boost{ namespace re_detail{ -#ifdef BOOST_NO_STD_DISTANCE -template -std::ptrdiff_t distance(const T& x, const T& y) -{ return y - x; } -#else -using std::distance; -#endif -}} - - -#ifdef BOOST_REGEX_NO_BOOL -# define BOOST_REGEX_MAKE_BOOL(x) static_cast((x) ? true : false) -#else -# ifdef BOOST_MSVC - // warning suppression with VC6: -# pragma warning(disable: 4800) -# pragma warning(disable: 4786) -# endif -# define BOOST_REGEX_MAKE_BOOL(x) static_cast(x) -#endif -#endif // __cplusplus - // backwards compatibitity: #if defined(BOOST_RE_NO_LIB) # define BOOST_REGEX_NO_LIB #endif #if defined(__GNUC__) && (defined(_WIN32) || defined(__CYGWIN__)) -// gcc on win32 has problems merging switch statements in templates: -# define BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE // gcc on win32 has problems if you include // (sporadically generates bad code). # define BOOST_REGEX_USE_C_LOCALE @@ -357,32 +282,6 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page(); #endif -/***************************************************************************** - * - * Error handling: - * - ****************************************************************************/ - -#if defined(__cplusplus) - -namespace boost{ -namespace re_detail{ - -BOOST_REGEX_DECL void BOOST_REGEX_CALL raise_runtime_error(const std::runtime_error& ex); - -template -void raise_error(const traits& t, unsigned code) -{ - (void)t; // warning suppression - std::runtime_error e(t.error_string(code)); - ::boost::re_detail::raise_runtime_error(e); -} - -} -} - -#endif - /***************************************************************************** * * Algorithm selection and configuration: @@ -419,93 +318,6 @@ void raise_error(const traits& t, unsigned code) #endif -/***************************************************************************** - * - * Fix broken compilers that wrongly #define some symbols: - * - ****************************************************************************/ - -#ifdef __cplusplus - -// the following may be defined as macros; this is -// incompatable with std::something syntax, we have -// no choice but to undef them? - -#ifdef sprintf -#undef sprintf -#endif -#ifdef swprintf -#undef swprintf -#endif -#endif - -/***************************************************************************** - * - * Fix broken broken namespace support: - * - ****************************************************************************/ - -#if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus) - -namespace std{ - using ::ptrdiff_t; - using ::size_t; - using ::sprintf; - using ::abs; - using ::setlocale; -# ifndef BOOST_NO_WREGEX -# ifndef BOOST_NO_SWPRINTF - using ::swprintf; -# endif - using ::wcstombs; - using ::mbstowcs; -# if !defined(BOOST_NO_STD_LOCALE) && !defined (__STL_NO_NATIVE_MBSTATE_T) && !defined(_STLP_NO_NATIVE_MBSTATE_T) - using ::mbstate_t; -# endif -# endif // BOOST_NO_WREGEX - using ::fseek; - using ::fread; - using ::ftell; - using ::fopen; - using ::fclose; - using ::FILE; -#ifdef BOOST_NO_EXCEPTIONS - using ::fprintf; - using ::abort; -#endif -} - -#endif - -/***************************************************************************** - * - * helper functions pointer_construct/pointer_destroy: - * - ****************************************************************************/ - -#ifdef __cplusplus -namespace boost{ namespace re_detail{ - -#ifdef BOOST_MSVC -#pragma warning (push) -#pragma warning (disable : 4100) -#endif - -template -inline void pointer_destroy(T* p) -{ p->~T(); (void)p; } - -#ifdef BOOST_MSVC -#pragma warning (pop) -#endif - -template -inline void pointer_construct(T* p, const T& t) -{ new (p) T(t); } - -}} // namespaces -#endif - /***************************************************************************** * * helper memory allocation functions: diff --git a/include/boost/regex/pattern_except.hpp b/include/boost/regex/pattern_except.hpp index c689c194..ae183e1d 100644 --- a/include/boost/regex/pattern_except.hpp +++ b/include/boost/regex/pattern_except.hpp @@ -23,6 +23,10 @@ #include #endif +#include +#include +#include + namespace boost{ #ifdef BOOST_HAS_ABI_HEADERS @@ -58,6 +62,21 @@ private: std::ptrdiff_t m_position; }; +namespace re_detail{ + +BOOST_REGEX_DECL void BOOST_REGEX_CALL raise_runtime_error(const std::runtime_error& ex); + +template +void raise_error(const traits& t, unsigned code) +{ + (void)t; // warning suppression + std::runtime_error e(t.error_string(code)); + ::boost::re_detail::raise_runtime_error(e); +} + +} + + #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX #endif diff --git a/include/boost/regex/v4/basic_regex_creator.hpp b/include/boost/regex/v4/basic_regex_creator.hpp index bf9c9561..2b30592a 100644 --- a/include/boost/regex/v4/basic_regex_creator.hpp +++ b/include/boost/regex/v4/basic_regex_creator.hpp @@ -337,9 +337,9 @@ re_syntax_base* basic_regex_creator::append_set( // // fill in the basics: // - result->csingles = static_cast(std::distance(char_set.singles_begin(), char_set.singles_end())); - result->cranges = static_cast(std::distance(char_set.ranges_begin(), char_set.ranges_end())) / 2; - result->cequivalents = static_cast(std::distance(char_set.equivalents_begin(), char_set.equivalents_end())); + result->csingles = static_cast(::boost::re_detail::distance(char_set.singles_begin(), char_set.singles_end())); + result->cranges = static_cast(::boost::re_detail::distance(char_set.ranges_begin(), char_set.ranges_end())) / 2; + result->cequivalents = static_cast(::boost::re_detail::distance(char_set.equivalents_begin(), char_set.equivalents_end())); result->cclasses = char_set.classes(); if(flags() & regbase::icase) { diff --git a/include/boost/regex/v4/basic_regex_parser.hpp b/include/boost/regex/v4/basic_regex_parser.hpp index 522ac428..b592ae96 100644 --- a/include/boost/regex/v4/basic_regex_parser.hpp +++ b/include/boost/regex/v4/basic_regex_parser.hpp @@ -110,7 +110,7 @@ void basic_regex_parser::parse(const charT* p1, const charT* p2, // if we haven't gobbled up all the characters then we must // have had an unexpected ')' : if(!result) - fail(regex_constants::error_paren, std::distance(m_base, m_position)); + fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_position)); // fill in our sub-expression count: this->m_pdata->m_mark_count = 1 + m_mark_count; this->finalize(p1, p2); @@ -320,7 +320,7 @@ bool basic_regex_parser::parse_open_paren() // we either have a ')' or we have run out of characters prematurely: // if(m_position == m_end) - this->fail(regex_constants::error_paren, std::distance(m_base, m_end)); + this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end)); BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark); ++m_position; // @@ -511,7 +511,7 @@ bool basic_regex_parser::parse_repeat(std::size_t low, std::size_ } if(0 == this->m_last_state) { - fail(regex_constants::error_badrepeat, std::distance(m_base, m_position)); + fail(regex_constants::error_badrepeat, ::boost::re_detail::distance(m_base, m_position)); } if(this->m_last_state->type == syntax_element_endmark) { @@ -1039,13 +1039,15 @@ charT basic_regex_parser::unescape_character() fail(regex_constants::error_escape, m_position - m_base); return result; } + /* if((*m_position < charT('@')) || (*m_position > charT(125)) ) { fail(regex_constants::error_escape, m_position - m_base); return result; } - result = static_cast(*m_position - charT('@')); + */ + result = static_cast(*m_position % 32); break; case regex_constants::escape_type_hex: ++m_position; @@ -1090,7 +1092,7 @@ charT basic_regex_parser::unescape_character() { // an octal escape sequence, the first character must be a zero // followed by up to 3 octal digits: - std::ptrdiff_t len = (std::min)(std::distance(m_position, m_end), static_cast(4)); + std::ptrdiff_t len = (std::min)(::boost::re_detail::distance(m_position, m_end), static_cast(4)); int val = this->m_traits.toi(m_position, m_position + len, 8); if(val < 0) fail(regex_constants::error_escape, m_position - m_base); @@ -1353,7 +1355,7 @@ bool basic_regex_parser::parse_perl_extension() // we either have a ')' or we have run out of characters prematurely: // if(m_position == m_end) - this->fail(regex_constants::error_paren, std::distance(m_base, m_end)); + this->fail(regex_constants::error_paren, ::boost::re_detail::distance(m_base, m_end)); BOOST_ASSERT(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_close_mark); ++m_position; // diff --git a/include/boost/regex/v4/cpp_regex_traits.hpp b/include/boost/regex/v4/cpp_regex_traits.hpp index 8ba46de8..d1c1dec7 100644 --- a/include/boost/regex/v4/cpp_regex_traits.hpp +++ b/include/boost/regex/v4/cpp_regex_traits.hpp @@ -651,6 +651,14 @@ public: { return icase ? m_pimpl->m_pctype->tolower(c) : c; } + charT tolower(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } + charT toupper(charT c) const + { + return m_pimpl->m_pctype->toupper(c); + } string_type transform(const charT* p1, const charT* p2) const { return m_pimpl->m_pcollate->transform(p1, p2); diff --git a/include/boost/regex/v4/cregex.hpp b/include/boost/regex/v4/cregex.hpp index 07bfeb06..6f420bcc 100644 --- a/include/boost/regex/v4/cregex.hpp +++ b/include/boost/regex/v4/cregex.hpp @@ -26,6 +26,12 @@ #include #include +#ifdef __cplusplus +#include +#else +#include +#endif + #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif diff --git a/include/boost/regex/v4/match_results.hpp b/include/boost/regex/v4/match_results.hpp index 421e1cb5..0de349ac 100644 --- a/include/boost/regex/v4/match_results.hpp +++ b/include/boost/regex/v4/match_results.hpp @@ -92,7 +92,7 @@ public: const sub_match& s = m_subs[sub]; if(s.matched) { - return boost::re_detail::distance((BidiIterator)(m_base), (BidiIterator)(s.first)); + return ::boost::re_detail::distance((BidiIterator)(m_base), (BidiIterator)(s.first)); } } return ~static_cast(0); @@ -151,6 +151,25 @@ public: { return regex_format(*this, fmt, flags); } + // format with locale: + template + OutputIterator format(OutputIterator out, + const string_type& fmt, + match_flag_type flags, + const RegexT& re) const + { + return ::boost::re_detail::regex_format_imp(out, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits()); + } + template + string_type format(const string_type& fmt, + match_flag_type flags, + const RegexT& re) const + { + string_type result; + re_detail::string_out_iterator i(result); + ::boost::re_detail::regex_format_imp(i, *this, fmt.data(), fmt.data() + fmt.size(), flags, re.get_traits()); + return result; + } allocator_type get_allocator() const { @@ -278,13 +297,13 @@ void BOOST_REGEX_CALL match_results::maybe_assign(const { // // leftmost takes priority over longest: - base1 = boost::re_detail::distance(base, p1->first); - base2 = boost::re_detail::distance(base, p2->first); + base1 = ::boost::re_detail::distance(base, p1->first); + base2 = ::boost::re_detail::distance(base, p2->first); if(base1 < base2) return; if(base2 < base1) break; - len1 = boost::re_detail::distance((BidiIterator)p1->first, (BidiIterator)p1->second); - len2 = boost::re_detail::distance((BidiIterator)p2->first, (BidiIterator)p2->second); + len1 = ::boost::re_detail::distance((BidiIterator)p1->first, (BidiIterator)p1->second); + len2 = ::boost::re_detail::distance((BidiIterator)p2->first, (BidiIterator)p2->second); if((len1 != len2) || ((p1->matched == false) && (p2->matched == true))) break; if((p1->matched == true) && (p2->matched == false)) diff --git a/include/boost/regex/v4/perl_matcher_common.hpp b/include/boost/regex/v4/perl_matcher_common.hpp index 80129a00..ad7790f3 100644 --- a/include/boost/regex/v4/perl_matcher_common.hpp +++ b/include/boost/regex/v4/perl_matcher_common.hpp @@ -101,6 +101,7 @@ template bool perl_matcher::protected_call( protected_proc_type proc) { + /* __try{ return (this->*proc)(); }__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) @@ -111,6 +112,12 @@ bool perl_matcher::protected_call( raise_error(traits_inst, regex_constants::error_size); // and we never really get here at all: return false; + */ + ::boost::re_detail::concrete_protected_call + > + obj(this, proc); + return obj.execute(); + } #endif @@ -664,7 +671,7 @@ bool perl_matcher::match_restart_continue() template bool perl_matcher::match_backstep() { - std::ptrdiff_t maxlen = std::distance(search_base, position); + std::ptrdiff_t maxlen = ::boost::re_detail::distance(search_base, position); if(maxlen < static_cast(pstate)->index) return false; std::advance(position, -static_cast(pstate)->index); diff --git a/include/boost/regex/v4/perl_matcher_non_recursive.hpp b/include/boost/regex/v4/perl_matcher_non_recursive.hpp index 61e5fe91..8bb9dc92 100644 --- a/include/boost/regex/v4/perl_matcher_non_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_non_recursive.hpp @@ -582,7 +582,7 @@ bool perl_matcher::match_dot_repeat_fast() return match_dot_repeat_slow(); const re_repeat* rep = static_cast(pstate); - unsigned count = (std::min)(static_cast(re_detail::distance(position, last)), static_cast(rep->greedy ? rep->max : rep->min)); + unsigned count = static_cast((std::min)(static_cast(::boost::re_detail::distance(position, last)), static_cast(rep->greedy ? rep->max : rep->min))); if(rep->min > count) return false; // not enough text left to match std::advance(position, count); @@ -629,13 +629,13 @@ bool perl_matcher::match_char_repeat() if(::boost::is_random_access_iterator::value) { BidiIterator end = position; - std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); + std::advance(end, (std::min)((unsigned)::boost::re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && (traits_inst.translate(*position, icase) == what)) { ++position; } - count = (unsigned)re_detail::distance(origin, position); + count = (unsigned)::boost::re_detail::distance(origin, position); } else { @@ -696,13 +696,13 @@ bool perl_matcher::match_set_repeat() if(::boost::is_random_access_iterator::value) { BidiIterator end = position; - std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); + std::advance(end, (std::min)((unsigned)::boost::re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && map[static_cast(traits_inst.translate(*position, icase))]) { ++position; } - count = (unsigned)re_detail::distance(origin, position); + count = (unsigned)::boost::re_detail::distance(origin, position); } else { @@ -764,13 +764,13 @@ bool perl_matcher::match_long_set_repeat() if(::boost::is_random_access_iterator::value) { BidiIterator end = position; - std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); + std::advance(end, (std::min)((unsigned)::boost::re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) { ++position; } - count = (unsigned)re_detail::distance(origin, position); + count = (unsigned)::boost::re_detail::distance(origin, position); } else { diff --git a/include/boost/regex/v4/perl_matcher_recursive.hpp b/include/boost/regex/v4/perl_matcher_recursive.hpp index 3b389f9d..84a79189 100644 --- a/include/boost/regex/v4/perl_matcher_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_recursive.hpp @@ -436,7 +436,7 @@ bool perl_matcher::match_dot_repeat_fast() // start by working out how much we can skip: // const re_repeat* rep = static_cast(pstate); - unsigned count = (std::min)(static_cast(re_detail::distance(position, last)), (rep->greedy ? rep->max : rep->min)); + unsigned count = (std::min)(static_cast(::boost::re_detail::distance(position, last)), (rep->greedy ? rep->max : rep->min)); if(rep->min > count) return false; // not enough text left to match std::advance(position, count); @@ -494,13 +494,13 @@ bool perl_matcher::match_char_repeat() if(::boost::is_random_access_iterator::value) { BidiIterator end = position; - std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); + std::advance(end, (std::min)((unsigned)::boost::re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && (traits_inst.translate(*position, icase) == what)) { ++position; } - count = (unsigned)re_detail::distance(origin, position); + count = (unsigned)::boost::re_detail::distance(origin, position); } else { @@ -582,13 +582,13 @@ bool perl_matcher::match_set_repeat() if(::boost::is_random_access_iterator::value) { BidiIterator end = position; - std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); + std::advance(end, (std::min)((unsigned)::boost::re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && map[static_cast(traits_inst.translate(*position, icase))]) { ++position; } - count = (unsigned)re_detail::distance(origin, position); + count = (unsigned)::boost::re_detail::distance(origin, position); } else { @@ -671,13 +671,13 @@ bool perl_matcher::match_long_set_repeat() if(::boost::is_random_access_iterator::value) { BidiIterator end = position; - std::advance(end, (std::min)((unsigned)re_detail::distance(position, last), desired)); + std::advance(end, (std::min)((unsigned)::boost::re_detail::distance(position, last), desired)); BidiIterator origin(position); while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase))) { ++position; } - count = (unsigned)re_detail::distance(origin, position); + count = (unsigned)::boost::re_detail::distance(origin, position); } else { diff --git a/include/boost/regex/v4/protected_call.hpp b/include/boost/regex/v4/protected_call.hpp new file mode 100644 index 00000000..baa4ee9b --- /dev/null +++ b/include/boost/regex/v4/protected_call.hpp @@ -0,0 +1,65 @@ +/* + * + * 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 basic_regex_creator.cpp + * VERSION see + * DESCRIPTION: Declares template class basic_regex_creator which fills in + * the data members of a regex_data object. + */ + +#ifndef BOOST_REGEX_V4_PROTECTED_CALL_HPP +#define BOOST_REGEX_V4_PROTECTED_CALL_HPP + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost{ +namespace re_detail{ + +class BOOST_REGEX_DECL abstract_protected_call +{ +public: + bool BOOST_REGEX_CALL execute()const; +private: + virtual bool call()const = 0; +}; + +template +class concrete_protected_call + : public abstract_protected_call +{ +public: + typedef bool (T::*proc_type)(); + concrete_protected_call(T* o, proc_type p) + : obj(o), proc(p) {} +private: + virtual bool call()const; + T* obj; + proc_type proc; +}; + +template +bool concrete_protected_call::call()const +{ + return (obj->*proc)(); +} + +} +} // namespace boost + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif diff --git a/include/boost/regex/v4/regex.hpp b/include/boost/regex/v4/regex.hpp index 3f19fed3..2559a4f1 100644 --- a/include/boost/regex/v4/regex.hpp +++ b/include/boost/regex/v4/regex.hpp @@ -21,39 +21,35 @@ #ifndef BOOST_RE_REGEX_HPP_INCLUDED #define BOOST_RE_REGEX_HPP_INCLUDED -#ifndef BOOST_RE_CREGEX_HPP -#include -#endif - #ifdef __cplusplus // what follows is all C++ don't include in C builds!! -#ifdef BOOST_REGEX_DEBUG -# include -#endif - -#include -#include #ifndef BOOST_REGEX_CONFIG_HPP #include #endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include +#endif + #ifndef BOOST_REGEX_FWD_HPP #include #endif -#ifndef BOOST_REGEX_RAW_BUFFER_HPP -#include -#endif -#ifndef BOOST_REGEX_KMP_HPP -#include -#endif -#ifndef BOOST_RE_PAT_EXCEPT_HPP -#include -#endif #ifndef BOOST_REGEX_TRAITS_HPP #include #endif -#include +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#include +#endif +#ifndef BOOST_REGEX_V4_MATCH_FLAGS +#include +#endif +#ifndef BOOST_REGEX_RAW_BUFFER_HPP +#include +#endif +#ifndef BOOST_RE_PAT_EXCEPT_HPP +#include +#endif #ifndef BOOST_REGEX_V4_CHAR_REGEX_TRAITS_HPP #include @@ -67,9 +63,6 @@ #ifndef BOOST_REGEX_V4_ITERATOR_TRAITS_HPP #include #endif -#ifndef BOOST_REGEX_V4_ITERATOR_TRAITS_HPP -#include -#endif #ifndef BOOST_REGEX_V4_BASIC_REGEX_HPP #include #endif @@ -131,6 +124,9 @@ typedef match_results wsmatch; #endif } // namespace boost +#ifndef BOOST_REGEX_V4_PROTECTED_CALL_HPP +#include +#endif #ifndef BOOST_REGEX_MATCHER_HPP #include #endif @@ -140,6 +136,12 @@ typedef match_results wsmatch; #ifndef BOOST_REGEX_V4_REGEX_SEARCH_HPP #include #endif +#ifndef BOOST_REGEX_ITERATOR_HPP +#include +#endif +#ifndef BOOST_REGEX_TOKEN_ITERATOR_HPP +#include +#endif #ifndef BOOST_REGEX_V4_REGEX_GREP_HPP #include #endif @@ -152,12 +154,6 @@ typedef match_results wsmatch; #ifndef BOOST_REGEX_SPLIT_HPP #include #endif -#ifndef BOOST_REGEX_ITERATOR_HPP -#include -#endif -#ifndef BOOST_REGEX_TOKEN_ITERATOR_HPP -#include -#endif #endif // __cplusplus diff --git a/include/boost/regex/v4/regex_format.hpp b/include/boost/regex/v4/regex_format.hpp index 8db2fd26..dc2d14f3 100644 --- a/include/boost/regex/v4/regex_format.hpp +++ b/include/boost/regex/v4/regex_format.hpp @@ -36,400 +36,509 @@ class match_results; namespace re_detail{ -template -O BOOST_REGEX_CALL re_copy_out(O out, I first, I last) +// +// helper functions: +// +template +std::ptrdiff_t global_length(const charT* p) { - while(first != last) + std::ptrdiff_t n = 0; + while(*p) { - *out = *first; - ++out; - ++first; + ++p; + ++n; } - return out; + return n; +} +inline std::ptrdiff_t global_length(const char* p) +{ + return (std::strlen)(p); +} +#ifndef BOOST_NO_WREGEX +inline std::ptrdiff_t global_length(const wchar_t* p) +{ + return (std::wcslen)(p); +} +#endif +template +inline charT global_lower(charT c) +{ + return c; +} +template +inline charT global_upper(charT c) +{ + return c; +} +BOOST_REGEX_DECL char BOOST_REGEX_CALL global_lower(char c); +BOOST_REGEX_DECL char BOOST_REGEX_CALL global_upper(char c); +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_lower(wchar_t c); +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_upper(wchar_t c); +#endif +template +int global_value(charT c) +{ + static const charT zero = '0'; + static const charT nine = '9'; + static const charT a = 'a'; + static const charT f = 'f'; + static const charT A = 'A'; + static const charT F = 'F'; + + if((c >= zero) && (c <= nine)) + return c - zero; + if((c >= a) && (c <= f)) + return 10 + (c - a); + if((c >= A) && (c <= F)) + return 10 + (c - A); + return -1; +} +template +int global_toi(const charT*& p1, const charT* p2, int radix) +{ + int next_value = global_value(*p1); + if((p1 == p2) || (next_value < 0) || (next_value >= radix)) + return -1; + int result = 0; + while(p1 != p2) + { + next_value = global_value(*p1); + if((next_value < 0) || (next_value >= radix)) + break; + result *= radix; + result += next_value; + ++p1; + } + return result; } -template -void BOOST_REGEX_CALL re_skip_format(const charT*& fmt, const traits_type& traits_inst) -{ - // dwa 9/13/00 - suppress incorrect unused parameter warning for MSVC - (void)traits_inst; - - typedef typename traits_type::size_type traits_size_type; - typedef typename traits_type::string_type traits_string_type; - - unsigned int parens = 0; - unsigned int c; - while(*fmt) - { - c = traits_inst.syntax_type(*fmt); - if((c == regex_constants::syntax_colon) && (parens == 0)) - { - ++fmt; - return; - } - else if(c == regex_constants::syntax_close_mark) - { - if(parens == 0) - { - ++fmt; - return; - } - --parens; - } - else if(c == regex_constants::syntax_open_mark) - ++parens; - else if(c == regex_constants::syntax_escape) - { - ++fmt; - if(*fmt == 0) - return; - } - ++fmt; - } -} - -#ifdef BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN // -// ugly hack for buggy output iterators - -template -inline void oi_assign(T* p, T v) +// struct trivial_format_traits: +// defines minimum localisation support for formatting +// in the case that the actual regex traits is unavailable. +// +template +struct trivial_format_traits { - ::boost::re_detail::pointer_destroy(p); - pointer_construct(p, v); + typedef charT char_type; + + static std::ptrdiff_t length(const charT* p) + { + return global_length(p); + } + static charT tolower(charT c) + { + return ::boost::re_detail::global_lower(c); + } + static charT toupper(charT c) + { + return ::boost::re_detail::global_upper(c); + } + static int toi(const charT*& p1, const charT* p2, int radix) + { + return global_toi(p1, p2, radix); + } +}; + +template +class basic_regex_formatter +{ +public: + typedef typename traits::char_type char_type; + basic_regex_formatter(OutputIterator o, const Results& r, const traits& t) + : m_traits(t), m_results(r), m_out(o), m_state(output_copy) {} + OutputIterator format(const char_type* p1, const char_type* p2, match_flag_type f); + OutputIterator format(const char_type* p1, match_flag_type f) + { + return format(p1, p1 + m_traits.length(p1), f); + } +private: + typedef typename Results::value_type sub_match_type; + enum output_state + { + output_copy, + output_next_lower, + output_next_upper, + output_lower, + output_upper, + output_none + }; + + void put(char_type c); + void put(const sub_match_type& sub); + void format_all(); + void format_perl(); + void format_escape(); + void format_conditional(); + void format_until_scope_end(); + + const traits& m_traits; // the traits class for localised formatting operations + const Results& m_results; // the match_results being used. + OutputIterator m_out; // where to send output. + const char_type* m_position; // format string, current position + const char_type* m_end; // format string end + match_flag_type m_flags; // format flags to use + output_state m_state; // what to do with the next character +}; + +template +OutputIterator basic_regex_formatter::format(const char_type* p1, const char_type* p2, match_flag_type f) +{ + m_position = p1; + m_end = p2; + m_flags = f; + format_all(); + return m_out; } -#else +template +void basic_regex_formatter::format_all() +{ + // over and over: + while(m_position != m_end) + { + switch(*m_position) + { + case '&': + if(m_flags & ::boost::regex_constants::format_sed) + { + ++m_position; + put(m_results[0]); + break; + } + put(*m_position++); + break; + case '\\': + format_escape(); + break; + case '(': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + format_until_scope_end(); + BOOST_ASSERT(*m_position == static_cast(')')); + ++m_position; // skip the closing ')' + break; + } + put(*m_position); + ++m_position; + break; + case ')': + case ':': + if(m_flags & boost::regex_constants::format_all) + { + return; + } + put(*m_position); + ++m_position; + break; + case '?': + if(m_flags & boost::regex_constants::format_all) + { + ++m_position; + format_conditional(); + break; + } + put(*m_position); + ++m_position; + break; + case '$': + if((m_flags & format_sed) == 0) + { + format_perl(); + break; + } + // fall through, not a special character: + default: + put(*m_position); + ++m_position; + break; + } + } +} -template -inline void oi_assign(T* p, T v) +template +void basic_regex_formatter::format_perl() { // - // if you get a compile time error in here then you either - // need to rewrite your output iterator to make it assignable - // (as is required by the standard), or define - // BOOST_NO_STD_OUTPUT_ITERATOR_ASSIGN to use the ugly hack above - *p = v; -} - -#endif - - -#if defined(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE) -// -// Ugly ugly hack, -// template don't merge if they contain switch statements so declare these -// templates in unnamed namespace (ie with internal linkage), each translation -// unit then gets its own local copy, it works seemlessly but bloats the app. -namespace{ -#endif - -// -// algorithm reg_format: -// takes the result of a match and a format string -// and merges them to produce a new string which -// is sent to an OutputIterator, -// _reg_format_aux does the actual work: -// -template -OutputIterator BOOST_REGEX_CALL _reg_format_aux(OutputIterator out, - const match_results& m, - const charT*& fmt, - match_flag_type flags, const traits_type& traits_inst) -{ -#ifdef __BORLANDC__ -#pragma option push -w-8037 -#endif - const charT* fmt_end = fmt; - while(*fmt_end) ++ fmt_end; - - typedef typename traits_type::size_type traits_size_type; - typedef typename traits_type::string_type traits_string_type; - - while(*fmt) + // On entry *m_position points to a '$' character + // output the information that goes with it: + // + BOOST_ASSERT(*m_position == '$'); + // + // see if this is a trailing '$': + // + if(++m_position == m_end) { - switch(traits_inst.syntax_type(*fmt)) + --m_position; + put(*m_position); + ++m_position; + return; + } + // + // OK find out what kind it is: + // + switch(*m_position) + { + case '&': + ++m_position; + put(this->m_results[0]); + break; + case '`': + ++m_position; + put(this->m_results.prefix()); + break; + case '\'': + ++m_position; + put(this->m_results.suffix()); + break; + case '$': + put(*m_position++); + break; + default: + // see if we have a number: { - case regex_constants::syntax_dollar: - if(flags & format_sed) + std::ptrdiff_t len = (std::min)(static_cast(2), std::distance(m_position, m_end)); + int v = m_traits.toi(m_position, m_position + len, 10); + if(v < 0) { - // no perl style replacement, - // $ is an ordinary character: - goto default_opt; - } - ++fmt; - if(*fmt == 0) // oops trailing $ - { - --fmt; - *out = *fmt; - ++out; - return out; - } - switch(traits_inst.syntax_type(*fmt)) - { - case regex_constants::escape_type_start_buffer: - oi_assign(&out, re_copy_out(out, Iterator(m[-1].first), Iterator(m[-1].second))); - ++fmt; - continue; - case regex_constants::escape_type_end_buffer: - oi_assign(&out, re_copy_out(out, Iterator(m[-2].first), Iterator(m[-2].second))); - ++fmt; - continue; - case regex_constants::syntax_digit: - { -expand_sub: - unsigned int index = traits_inst.toi(fmt, fmt_end, 10); - if(index < m.size()) - oi_assign(&out, re_copy_out(out, Iterator(m[index].first), Iterator(m[index].second))); - continue; - } - } - // anything else: - if(*fmt == '&') - { - oi_assign(&out, re_copy_out(out, Iterator(m[0].first), Iterator(m[0].second))); - ++fmt; - } - else - { - // probably an error, treat as a literal '$' - --fmt; - *out = *fmt; - ++out; - ++fmt; - } - continue; - case regex_constants::syntax_escape: - { - // escape sequence: - ++fmt; - charT c(*fmt); - if(*fmt == 0) - { - --fmt; - *out = *fmt; - ++out; - ++fmt; - return out; - } - switch(traits_inst.syntax_type(*fmt)) - { - case regex_constants::escape_type_control_a: - c = '\a'; - ++fmt; + // leave the $ as is, and carry on: + --m_position; + put(*m_position); + ++m_position; break; - case regex_constants::escape_type_control_f: - c = '\f'; - ++fmt; - break; - case regex_constants::escape_type_control_n: - c = '\n'; - ++fmt; - break; - case regex_constants::escape_type_control_r: - c = '\r'; - ++fmt; - break; - case regex_constants::escape_type_control_t: - c = '\t'; - ++fmt; - break; - case regex_constants::escape_type_control_v: - c = '\v'; - ++fmt; - break; - case regex_constants::escape_type_hex: - ++fmt; - if(fmt == fmt_end) - { - *out = *--fmt; - ++out; - return out; - } - // maybe have \x{ddd} - if(traits_inst.syntax_type(*fmt) == regex_constants::syntax_open_brace) - { - ++fmt; - if(fmt == fmt_end) - { - fmt -= 2; - *out = *fmt; - ++out; - ++fmt; - continue; - } - int val = traits_inst.toi(fmt, fmt_end, 16); - if(val < 0) - { - fmt -= 2; - *out = *fmt; - ++out; - ++fmt; - continue; - } - c = static_cast(val); - if(traits_inst.syntax_type(*fmt) != regex_constants::syntax_close_brace) - { - while(traits_inst.syntax_type(*fmt) != regex_constants::syntax_escape) - --fmt; - ++fmt; - *out = *fmt; - ++out; - ++fmt; - continue; - } - ++fmt; - break; - } - else - { - int val = traits_inst.toi(fmt, fmt_end, 16); - if(val < 0) - { - --fmt; - *out = *fmt; - ++out; - ++fmt; - continue; - } - c = static_cast(val); - } - break; - case regex_constants::escape_type_ascii_control: - ++fmt; - if(fmt == fmt_end) - { - --fmt; - *out = *fmt; - ++out; - return out; - } - if( (*fmt < static_cast('@')) || (*fmt > static_cast('z')) ) - { - --fmt; - *out = *fmt; - ++out; - ++fmt; - break; - } - c = static_cast(*fmt - static_cast('@')); - ++fmt; - break; - case regex_constants::escape_type_e: - c = (charT)27; - ++fmt; - break; - case regex_constants::syntax_digit: - if(flags & format_sed) - goto expand_sub; - else - c = static_cast(traits_inst.toi(fmt, fmt_end, 8)); - break; - default: - //c = *fmt; - ++fmt; } - *out = c; - ++out; - continue; - } - case regex_constants::syntax_open_mark: - if(0 == (flags & format_all)) - { - *out = *fmt; - ++out; - ++fmt; - continue; - } - else - { - ++fmt; // recurse - oi_assign(&out, _reg_format_aux(out, m, fmt, flags, traits_inst)); - continue; - } - case regex_constants::syntax_close_mark: - if(0 == (flags & format_all)) - { - *out = *fmt; - ++out; - ++fmt; - continue; - } - else - { - ++fmt; // return from recursion - return out; - } - case regex_constants::syntax_colon: - if(flags & regex_constants::format_is_if) - { - ++fmt; - return out; - } - *out = *fmt; - ++out; - ++fmt; - continue; - case regex_constants::syntax_question: - { - if(0 == (flags & format_all)) - { - *out = *fmt; - ++out; - ++fmt; - continue; - } - else - { - ++fmt; - if(*fmt == 0) - { - --fmt; - *out = *fmt; - ++out; - ++fmt; - return out; - } - unsigned int id = traits_inst.toi(fmt, fmt_end, 10); - if(m[id].matched) - { - oi_assign(&out, _reg_format_aux(out, m, fmt, flags | regex_constants::format_is_if, traits_inst)); - if(traits_inst.syntax_type(*(fmt-1)) == regex_constants::syntax_colon) - re_skip_format(fmt, traits_inst); - } - else - { - re_skip_format(fmt, traits_inst); - if(traits_inst.syntax_type(*(fmt-1)) == regex_constants::syntax_colon) - oi_assign(&out, _reg_format_aux(out, m, fmt, flags | regex_constants::format_is_if, traits_inst)); - } - return out; - } - } - default: -default_opt: - if((flags & format_sed) && (*fmt == '&')) - { - oi_assign(&out, re_copy_out(out, Iterator(m[0].first), Iterator(m[0].second))); - ++fmt; - continue; - } - *out = *fmt; - ++out; - ++fmt; + // otherwise output sub v: + put(this->m_results[v]); } } - - return out; -#ifdef __BORLANDC__ -#pragma option pop -#endif } -#if defined(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE) -} // namespace -#endif +template +void basic_regex_formatter::format_escape() +{ + // skip the escape and check for trailing escape: + if(++m_position == m_end) + { + put(static_cast('\\')); + return; + } + // now switch on the escape type: + switch(*m_position) + { + case 'a': + put(static_cast('\a')); + ++m_position; + break; + case 'f': + put(static_cast('\f')); + ++m_position; + break; + case 'n': + put(static_cast('\n')); + ++m_position; + break; + case 'r': + put(static_cast('\r')); + ++m_position; + break; + case 't': + put(static_cast('\t')); + ++m_position; + break; + case 'v': + put(static_cast('\v')); + ++m_position; + break; + case 'x': + if(++m_position == m_end) + { + put(static_cast('x')); + return; + } + // maybe have \x{ddd} + if(*m_position == static_cast('{')) + { + ++m_position; + int val = m_traits.toi(m_position, m_end, 16); + if(val < 0) + { + // invalid value treat everything as literals: + put(static_cast('x')); + put(static_cast('{')); + return; + } + if(*m_position != static_cast('}')) + { + while(*m_position != static_cast('\\')) + --m_position; + ++m_position; + put(*m_position++); + return; + } + ++m_position; + put(static_cast(val)); + return; + } + else + { + std::ptrdiff_t len = (std::min)(static_cast(2), std::distance(m_position, m_end)); + int val = m_traits.toi(m_position, m_position + len, 16); + if(val < 0) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast(val)); + } + break; + case 'c': + if(++m_position == m_end) + { + --m_position; + put(*m_position++); + return; + } + put(static_cast(*m_position++ % 32)); + break; + case 'e': + put(static_cast(27)); + ++m_position; + break; + default: + // see if we have a \n sed style backreference: + int v = m_traits.toi(m_position, m_position+1, 10); + if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed))) + { + put(m_results[v]); + break; + } + else if(v == 0) + { + // octal ecape sequence: + --m_position; + std::ptrdiff_t len = (std::min)(static_cast(4), std::distance(m_position, m_end)); + v = m_traits.toi(m_position, m_position + len, 8); + BOOST_ASSERT(v >= 0); + put(static_cast(v)); + break; + } + // Otherwise output the character "as is": + put(*m_position++); + break; + } +} + +template +void basic_regex_formatter::format_conditional() +{ + if(m_position == m_end) + { + // oops trailing '?': + put(static_cast('?')); + return; + } + std::ptrdiff_t len = (std::min)(static_cast(2), std::distance(m_position, m_end)); + int v = m_traits.toi(m_position, m_position + len, 10); + if(v < 0) + { + // oops not a number: + put(static_cast('?')); + return; + } + + // output varies depending upon whether sub-expression v matched or not: + if(m_results[v].matched) + { + format_all(); + if((m_position != m_end) && (*m_position == static_cast(':'))) + { + // skip the ':': + ++m_position; + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format the rest of this scope: + format_until_scope_end(); + // restore output state: + m_state = saved_state; + } + } + else + { + // save output state, then turn it off: + output_state saved_state = m_state; + m_state = output_none; + // format until ':' or ')': + format_all(); + // restore state: + m_state = saved_state; + if((m_position != m_end) && (*m_position == static_cast(':'))) + { + // skip the ':': + ++m_position; + // format the rest of this scope: + format_until_scope_end(); + } + } +} + +template +void basic_regex_formatter::format_until_scope_end() +{ + do + { + format_all(); + if((m_position == m_end) || (*m_position == static_cast(')'))) + return; + put(*m_position++); + }while(m_position != m_end); +} + +template +void basic_regex_formatter::put(char_type c) +{ + // write a single character to output + // according to which case translation mode we are in: + switch(this->m_state) + { + case output_none: + return; + case output_next_lower: + c = m_traits.tolower(c); + this->m_state = output_copy; + break; + case output_next_upper: + c = m_traits.toupper(c); + this->m_state = output_copy; + break; + case output_lower: + c = m_traits.tolower(c); + break; + case output_upper: + c = m_traits.toupper(c); + break; + default: + break; + } + *m_out = c; + ++m_out; +} + +template +void basic_regex_formatter::put(const sub_match_type& sub) +{ + typedef typename sub_match_type::iterator iterator_type; + iterator_type i = sub.first; + while(i != sub.second) + { + put(*i); + ++i; + } +} template class string_out_iterator @@ -447,30 +556,21 @@ public: } }; -template -class merge_out_predicate +template +OutputIterator regex_format_imp(OutputIterator out, + const match_results& m, + const charT* p1, const charT* p2, + match_flag_type flags, + const traits& t + ) { - OutputIterator* out; - Iterator* last; - const charT* fmt; - match_flag_type flags; - const traits_type* pt; + re_detail::basic_regex_formatter< + OutputIterator, + match_results, + traits > f(out, m, t); + return f.format(p1, p2, flags); +} -public: - merge_out_predicate(OutputIterator& o, Iterator& pi, const charT* f, match_flag_type format_flags, const traits_type& p) - : out(&o), last(&pi), fmt(f), flags(format_flags), pt(&p){} - - ~merge_out_predicate() {} - bool BOOST_REGEX_CALL operator()(const boost::match_results& m) - { - const charT* f = fmt; - if(0 == (flags & format_no_copy)) - oi_assign(out, re_copy_out(*out, Iterator(m[-1].first), Iterator(m[-1].second))); - oi_assign(out, _reg_format_aux(*out, m, f, flags, *pt)); - *last = m[-2].first; - return flags & format_first_only ? false : true; - } -}; } // namespace re_detail @@ -481,8 +581,8 @@ OutputIterator regex_format(OutputIterator out, match_flag_type flags = format_all ) { - regex_traits t; - return re_detail::_reg_format_aux(out, m, fmt, flags, t); + re_detail::trivial_format_traits traits; + return regex_format_imp(out, m, fmt, fmt + traits.length(fmt), flags, traits); } template @@ -492,9 +592,8 @@ OutputIterator regex_format(OutputIterator out, match_flag_type flags = format_all ) { - regex_traits t; - const charT* start = fmt.c_str(); - return re_detail::_reg_format_aux(out, m, start, flags, t); + re_detail::trivial_format_traits traits; + return regex_format_imp(out, m, fmt.data(), fmt.data() + fmt.size(), flags, traits); } template @@ -504,7 +603,8 @@ std::basic_string regex_format(const match_results& m, { std::basic_string result; re_detail::string_out_iterator > i(result); - regex_format(i, m, fmt, flags); + re_detail::trivial_format_traits traits; + regex_format_imp(i, m, fmt, fmt + traits.length(fmt), flags, traits); return result; } @@ -515,7 +615,8 @@ std::basic_string regex_format(const match_results& m, { std::basic_string result; re_detail::string_out_iterator > i(result); - regex_format(i, m, fmt.c_str(), flags); + re_detail::trivial_format_traits traits; + regex_format_imp(i, m, fmt.data(), fmt.data() + fmt.size(), flags, traits); return result; } diff --git a/include/boost/regex/v4/regex_iterator.hpp b/include/boost/regex/v4/regex_iterator.hpp index f01c21bf..f799a955 100644 --- a/include/boost/regex/v4/regex_iterator.hpp +++ b/include/boost/regex/v4/regex_iterator.hpp @@ -37,21 +37,21 @@ class regex_iterator_implementation match_results what; // current match BidirectionalIterator base; // start of sequence BidirectionalIterator end; // end of sequence - const regex_type* pre; // the expression + const regex_type re; // the expression match_flag_type flags; // flags for matching public: regex_iterator_implementation(const regex_type* p, BidirectionalIterator last, match_flag_type f) - : base(), end(last), pre(p), flags(f){} + : base(), end(last), re(*p), flags(f){} bool init(BidirectionalIterator first) { base = first; - return regex_search(first, end, what, *pre, flags); + return regex_search(first, end, what, re, flags); } bool compare(const regex_iterator_implementation& that) { if(this == &that) return true; - return (pre == that.pre) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); + return (re == that.re) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); } const match_results& get() { return what; } @@ -63,7 +63,7 @@ public: match_flag_type f(flags); if(!what.length()) f |= regex_constants::match_not_initial_null; - bool result = regex_search(next_start, end, what, *pre, f); + bool result = regex_search(next_start, end, what, re, f); if(result) what.set_base(base); return result; diff --git a/include/boost/regex/v4/regex_kmp.hpp b/include/boost/regex/v4/regex_kmp.hpp index eaea55e0..073a0e2e 100644 --- a/include/boost/regex/v4/regex_kmp.hpp +++ b/include/boost/regex/v4/regex_kmp.hpp @@ -55,7 +55,7 @@ kmp_info* kmp_compile(iterator first, iterator last, charT, Trans transla typedef typename boost::detail::rebind_allocator::type atype; int i, j, m; i = 0; - m = static_cast(boost::re_detail::distance(first, last)); + m = static_cast(::boost::re_detail::distance(first, last)); ++m; unsigned int size = sizeof(kmp_info) + sizeof(int)*m + sizeof(charT)*m; --m; diff --git a/include/boost/regex/v4/regex_raw_buffer.hpp b/include/boost/regex/v4/regex_raw_buffer.hpp index d4740d05..aea1b2e9 100644 --- a/include/boost/regex/v4/regex_raw_buffer.hpp +++ b/include/boost/regex/v4/regex_raw_buffer.hpp @@ -25,6 +25,8 @@ #include #endif +#include + namespace boost{ namespace re_detail{ diff --git a/include/boost/regex/v4/regex_replace.hpp b/include/boost/regex/v4/regex_replace.hpp index acfb7aa3..a6f9a550 100644 --- a/include/boost/regex/v4/regex_replace.hpp +++ b/include/boost/regex/v4/regex_replace.hpp @@ -28,18 +28,38 @@ namespace boost{ # include BOOST_ABI_PREFIX #endif -template +template OutputIterator regex_replace(OutputIterator out, - Iterator first, - Iterator last, + BidirectionalIterator first, + BidirectionalIterator last, const basic_regex& e, const charT* fmt, match_flag_type flags = match_default) { - Iterator l = first; - re_detail::merge_out_predicate oi(out, l, fmt, flags, e.get_traits()); - regex_grep(oi, first, last, e, flags); - return (flags & format_no_copy) ? out : re_detail::re_copy_out(out, l, last); + regex_iterator i(first, last, e, flags); + regex_iterator j; + if(i == j) + { + if(!(flags & regex_constants::format_no_copy)) + out = std::copy(first, last, out); + } + else + { + BidirectionalIterator last_m = first; + while(i != j) + { + if(!(flags & regex_constants::format_no_copy)) + out = std::copy(i->prefix().first, i->prefix().second, out); + out = i->format(out, fmt, flags, e); + last_m = (*i)[0].second; + if(flags & regex_constants::format_first_only) + break; + ++i; + } + if(!(flags & regex_constants::format_no_copy)) + out = std::copy(last_m, last, out); + } + return out; } template diff --git a/include/boost/regex/v4/regex_token_iterator.hpp b/include/boost/regex/v4/regex_token_iterator.hpp index 8dfe1612..78b20315 100644 --- a/include/boost/regex/v4/regex_token_iterator.hpp +++ b/include/boost/regex/v4/regex_token_iterator.hpp @@ -54,7 +54,7 @@ class regex_token_iterator_implementation match_results what; // current match BidirectionalIterator end; // end of search area - const regex_type* pre; // the expression + const regex_type re; // the expression match_flag_type flags; // match flags value_type result; // the current string result int N; // the current sub-expression being enumerated @@ -62,15 +62,15 @@ class regex_token_iterator_implementation public: regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, int sub, match_flag_type f) - : end(last), pre(p), flags(f){ subs.push_back(sub); } + : end(last), re(*p), flags(f){ subs.push_back(sub); } regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const std::vector& v, match_flag_type f) - : end(last), pre(p), subs(v), flags(f){} + : end(last), re(*p), flags(f), subs(v){} #if (BOOST_WORKAROUND(__BORLANDC__, >= 0x560) && BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570)))\ || BOOST_WORKAROUND(BOOST_MSVC, < 1300) \ || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) template regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const T& submatches, match_flag_type f) - : end(last), pre(p), flags(f) + : end(last), re(*p), flags(f) { // assert that T really is an array: BOOST_STATIC_ASSERT(::boost::is_array::value); @@ -83,7 +83,7 @@ public: #else template regex_token_iterator_implementation(const regex_type* p, BidirectionalIterator last, const int (&submatches)[CN], match_flag_type f) - : end(last), pre(p), flags(f) + : end(last), re(*p), flags(f) { for(std::size_t i = 0; i < CN; ++i) { @@ -95,7 +95,7 @@ public: bool init(BidirectionalIterator first) { N = 0; - if(regex_search(first, end, what, *pre, flags) == true) + if(regex_search(first, end, what, re, flags) == true) { N = 0; result = ((subs[N] == -1) ? what.prefix() : what[(int)subs[N]]); @@ -113,7 +113,7 @@ public: bool compare(const regex_token_iterator_implementation& that) { if(this == &that) return true; - return (pre == that.pre) + return (re == that.re) && (end == that.end) && (flags == that.flags) && (N == that.N) @@ -135,7 +135,7 @@ public: if(what.prefix().first != what[0].second) flags |= match_prev_avail; BidirectionalIterator last_end(what[0].second); - if(regex_search(last_end, end, what, *pre, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags))) + if(regex_search(last_end, end, what, re, ((what[0].first == what[0].second) ? flags | regex_constants::match_not_initial_null : flags))) { N =0; result =((subs[N] == -1) ? what.prefix() : what[subs[N]]); diff --git a/include/boost/regex/v4/regex_traits.hpp b/include/boost/regex/v4/regex_traits.hpp index 93b7b678..febc80d7 100644 --- a/include/boost/regex/v4/regex_traits.hpp +++ b/include/boost/regex/v4/regex_traits.hpp @@ -19,11 +19,11 @@ #ifndef BOOST_REGEX_TRAITS_HPP_INCLUDED #define BOOST_REGEX_TRAITS_HPP_INCLUDED -#ifndef BOOST_RE_CREGEX_HPP -#include +#ifndef BOOST_REGEX_CONFIG_HPP +#include #endif -#ifndef BOOST_REGEX_CSTRING_HPP -#include +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include #endif #ifndef BOOST_REGEX_SYNTAX_TYPE_HPP #include @@ -34,6 +34,9 @@ #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED #include #endif +#ifndef BOOST_REGEX_FWD_HPP_INCLUDED +#include +#endif #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX diff --git a/include/boost/regex/v4/regex_workaround.hpp b/include/boost/regex/v4/regex_workaround.hpp new file mode 100644 index 00000000..bb3c7223 --- /dev/null +++ b/include/boost/regex/v4/regex_workaround.hpp @@ -0,0 +1,114 @@ +/* + * + * Copyright (c) 1998-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 regex_workarounds.cpp + * VERSION see + * DESCRIPTION: Declares Misc workarounds. + */ + +#ifndef BOOST_REGEX_WORKAROUND_HPP +#define BOOST_REGEX_WORKAROUND_HPP + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef BOOST_NO_STD_LOCALE +# include +#endif + +namespace boost{ namespace re_detail{ +#ifdef BOOST_NO_STD_DISTANCE +template +std::ptrdiff_t distance(const T& x, const T& y) +{ return y - x; } +#else +using std::distance; +#endif +}} + + +#ifdef BOOST_REGEX_NO_BOOL +# define BOOST_REGEX_MAKE_BOOL(x) static_cast((x) ? true : false) +#else +# ifdef BOOST_MSVC + // warning suppression with VC6: +# pragma warning(disable: 4800) +# pragma warning(disable: 4786) +# endif +# define BOOST_REGEX_MAKE_BOOL(x) static_cast(x) +#endif + +/***************************************************************************** + * + * Fix broken broken namespace support: + * + ****************************************************************************/ + +#if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus) + +namespace std{ + using ::ptrdiff_t; + using ::size_t; + using ::abs; +} + +#endif + +/***************************************************************************** + * + * helper functions pointer_construct/pointer_destroy: + * + ****************************************************************************/ + +#ifdef __cplusplus +namespace boost{ namespace re_detail{ + +#ifdef BOOST_MSVC +#pragma warning (push) +#pragma warning (disable : 4100) +#endif + +template +inline void pointer_destroy(T* p) +{ p->~T(); (void)p; } + +#ifdef BOOST_MSVC +#pragma warning (pop) +#endif + +template +inline void pointer_construct(T* p, const T& t) +{ new (p) T(t); } + +}} // namespaces +#endif + +#endif // include guard diff --git a/include/boost/regex/v4/states.hpp b/include/boost/regex/v4/states.hpp index d6c222fa..42ff7e5e 100644 --- a/include/boost/regex/v4/states.hpp +++ b/include/boost/regex/v4/states.hpp @@ -161,7 +161,7 @@ enum force_newline = 2, test_not_newline = 2, - test_newline = 3, + test_newline = 3 }; struct re_dot : public re_syntax_base { diff --git a/include/boost/regex/v4/sub_match.hpp b/include/boost/regex/v4/sub_match.hpp index 10fbb1ce..2529f1d9 100644 --- a/include/boost/regex/v4/sub_match.hpp +++ b/include/boost/regex/v4/sub_match.hpp @@ -35,6 +35,8 @@ struct sub_match : public std::pair typedef typename re_detail::regex_iterator_traits::difference_type difference_type; #endif typedef BidiIterator iterator_type; + typedef BidiIterator iterator; + typedef BidiIterator const_iterator; bool matched; @@ -47,13 +49,13 @@ struct sub_match : public std::pair } difference_type BOOST_REGEX_CALL length()const { - difference_type n = boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); + difference_type n = ::boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); return n; } std::basic_string str()const { std::basic_string result; - std::size_t len = boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); + std::size_t len = ::boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); result.reserve(len); BidiIterator i = this->first; while(i != this->second) diff --git a/src/cregex.cpp b/src/cregex.cpp index 28bfeb6c..1a4b3e56 100644 --- a/src/cregex.cpp +++ b/src/cregex.cpp @@ -33,6 +33,12 @@ typedef boost::match_flag_type match_flag_type; #endif #include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::sprintf; +} +#endif + namespace boost{ #ifdef __BORLANDC__ @@ -359,7 +365,7 @@ void BuildFileList(std::list* pl, const char* files, bool recurse) while(dstart != dend) { - std::sprintf(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr); + (std::sprintf)(buf, "%s%s%s", dstart.path(), directory_iterator::separator(), ptr); BuildFileList(pl, buf, recurse); ++dstart; } diff --git a/src/fileiter.cpp b/src/fileiter.cpp index 87c07fb7..cd64d644 100644 --- a/src/fileiter.cpp +++ b/src/fileiter.cpp @@ -21,12 +21,28 @@ #include #include +#include +#include #ifdef BOOST_REGEX_V3 #include #else #include #endif +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::sprintf; + using ::fseek; + using ::fread; + using ::ftell; + using ::fopen; + using ::fclose; + using ::FILE; +} +#endif + + #ifndef BOOST_REGEX_NO_FILEITER #if defined(__CYGWIN__) || defined(__CYGWIN32__) @@ -787,9 +803,9 @@ unsigned _fi_attributes(const char* root, const char* name) { char buf[MAX_PATH]; if( ( (root[0] == *_fi_sep) || (root[0] == *_fi_sep_alt) ) && (root[1] == '\0') ) - std::sprintf(buf, "%s%s", root, name); + (std::sprintf)(buf, "%s%s", root, name); else - std::sprintf(buf, "%s%s%s", root, _fi_sep, name); + (std::sprintf)(buf, "%s%s%s", root, _fi_sep, name); DIR* d = opendir(buf); if(d) { diff --git a/src/posix_api.cpp b/src/posix_api.cpp index 1e986bb3..dc9bd4b3 100644 --- a/src/posix_api.cpp +++ b/src/posix_api.cpp @@ -19,8 +19,16 @@ #define BOOST_REGEX_SOURCE #include +#include #include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::sprintf; +} +#endif + + namespace boost{ namespace{ @@ -135,13 +143,13 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* { if(std::strcmp(e->re_endp, names[i]) == 0) { - std::sprintf(localbuf, "%d", i); + (std::sprintf)(localbuf, "%d", i); if(std::strlen(localbuf) < buf_size) std::strcpy(buf, localbuf); return std::strlen(localbuf) + 1; } } - std::sprintf(localbuf, "%d", 0); + (std::sprintf)(localbuf, "%d", 0); if(std::strlen(localbuf) < buf_size) std::strcpy(buf, localbuf); return std::strlen(localbuf) + 1; diff --git a/src/regex.cpp b/src/regex.cpp index 63be80b1..7bc6ad46 100644 --- a/src/regex.cpp +++ b/src/regex.cpp @@ -26,6 +26,13 @@ #if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300) # include #endif +#ifdef BOOST_REGEX_HAS_MS_STACK_GUARD +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#define NOGDI +#define NOUSER +#include +#endif #if defined(BOOST_REGEX_NON_RECURSIVE) && !defined(BOOST_REGEX_V3) #if BOOST_REGEX_MAX_CACHE_BLOCKS == 0 @@ -72,6 +79,29 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex::flag_type /* #ifdef BOOST_REGEX_HAS_MS_STACK_GUARD +static void execute_eror() +{ + // we only get here after a stack overflow, + // this has to be a separate proceedure because we + // can't mix __try{}__except block with local objects + // that have destructors: + reset_stack_guard_page(); + std::runtime_error err("Out of stack space, while attempting to match a regular expression."); + raise_runtime_error(err); +} + +bool BOOST_REGEX_CALL abstract_protected_call::execute()const +{ + __try{ + return this->call(); + }__except(EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) + { + execute_eror(); + } + // We never really get here at all: + return false; +} + BOOST_REGEX_DECL void BOOST_REGEX_CALL reset_stack_guard_page() { #if defined(BOOST_REGEX_HAS_MS_STACK_GUARD) && defined(_MSC_VER) && (_MSC_VER >= 1300) diff --git a/src/regex_raw_buffer.cpp b/src/regex_raw_buffer.cpp index dc13cd78..5d7d2d1f 100644 --- a/src/regex_raw_buffer.cpp +++ b/src/regex_raw_buffer.cpp @@ -1,8 +1,18 @@ #define BOOST_REGEX_SOURCE +#include +#include #include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::memcpy; + using ::memmove; +} +#endif + + namespace boost{ namespace re_detail{ void BOOST_REGEX_CALL raw_storage::resize(size_type n) diff --git a/src/regex_traits_defaults.cpp b/src/regex_traits_defaults.cpp index d5210c78..9d3aec6a 100644 --- a/src/regex_traits_defaults.cpp +++ b/src/regex_traits_defaults.cpp @@ -19,6 +19,23 @@ #define BOOST_REGEX_SOURCE #include +#include +#ifndef BOOST_NO_WREGEX +#include +#endif + +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::tolower; + using ::toupper; +#ifndef BOOST_NO_WREGEX + using ::towlower; + using ::towupper; +#endif +} +#endif + + namespace boost{ namespace re_detail{ BOOST_REGEX_DECL const char* BOOST_REGEX_CALL get_default_syntax(regex_constants::syntax_type n) @@ -113,7 +130,7 @@ BOOST_REGEX_DECL const char* BOOST_REGEX_CALL get_default_error_string(regex_con "", }; - return (n > REG_E_UNKNOWN) ? s_default_error_messages[REG_E_UNKNOWN] : s_default_error_messages[n]; + return (n > ::boost::regex_constants::error_unknown) ? s_default_error_messages[ ::boost::regex_constants::error_unknown] : s_default_error_messages[n]; } BOOST_REGEX_DECL bool BOOST_REGEX_CALL is_combining_implementation(boost::uint_least16_t c) @@ -239,6 +256,26 @@ BOOST_REGEX_DECL std::string BOOST_REGEX_CALL lookup_default_collate_name(const return std::string(); } +BOOST_REGEX_DECL char BOOST_REGEX_CALL global_lower(char c) +{ + return (std::tolower)(c); +} + +BOOST_REGEX_DECL char BOOST_REGEX_CALL global_upper(char c) +{ + return (std::toupper)(c); +} +#ifndef BOOST_NO_WREGEX +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_lower(wchar_t c) +{ + return (std::towlower)(c); +} + +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_upper(wchar_t c) +{ + return (std::towupper)(c); +} +#endif } // re_detail } // boost diff --git a/src/wide_posix_api.cpp b/src/wide_posix_api.cpp index be3d52d7..d21ee2c2 100644 --- a/src/wide_posix_api.cpp +++ b/src/wide_posix_api.cpp @@ -22,12 +22,22 @@ #ifndef BOOST_NO_WREGEX +#include #include #include #include #include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ +# ifndef BOOST_NO_SWPRINTF + using ::swprintf; +# endif +} +#endif + + namespace boost{ namespace { @@ -144,13 +154,13 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* { if(std::wcscmp(e->re_endp, wnames[i]) == 0) { - std::swprintf(localbuf, 5, L"%d", i); + (std::swprintf)(localbuf, 5, L"%d", i); if(std::wcslen(localbuf) < buf_size) std::wcscpy(buf, localbuf); return std::wcslen(localbuf) + 1; } } - std::swprintf(localbuf, 5, L"%d", 0); + (std::swprintf)(localbuf, 5, L"%d", 0); if(std::wcslen(localbuf) < buf_size) std::wcscpy(buf, localbuf); return std::wcslen(localbuf) + 1; diff --git a/test/Jamfile b/test/Jamfile index cd7fdb88..a78af05b 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -24,6 +24,7 @@ template regression :