From fce31e980084443945494c677e423b71f8979063 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Sat, 5 Jun 2004 11:45:27 +0000 Subject: [PATCH] Updated concepts checks: Use of traits class is now in line with the std. Added c_regex_traits and w32_regex_traits (first cuts). [SVN r23030] --- include/boost/regex/concepts.hpp | 829 ++++++++++++++++++ include/boost/regex/pattern_except.hpp | 25 +- include/boost/regex/v4/basic_regex.hpp | 108 ++- .../boost/regex/v4/basic_regex_creator.hpp | 41 +- include/boost/regex/v4/basic_regex_parser.hpp | 30 +- include/boost/regex/v4/c_regex_traits.hpp | 146 +++ include/boost/regex/v4/cpp_regex_traits.hpp | 40 +- include/boost/regex/v4/error_type.hpp | 45 +- include/boost/regex/v4/perl_matcher.hpp | 34 +- .../boost/regex/v4/perl_matcher_common.hpp | 26 +- include/boost/regex/v4/regex_format.hpp | 87 +- include/boost/regex/v4/regex_iterator.hpp | 2 +- include/boost/regex/v4/regex_match.hpp | 112 +++ include/boost/regex/v4/regex_split.hpp | 4 +- .../boost/regex/v4/regex_token_iterator.hpp | 2 +- include/boost/regex/v4/regex_traits.hpp | 102 +++ .../boost/regex/v4/regex_traits_defaults.hpp | 117 ++- include/boost/regex/v4/regex_workaround.hpp | 2 + include/boost/regex/v4/sub_match.hpp | 17 +- include/boost/regex/v4/w32_regex_traits.hpp | 654 ++++++++++++++ src/cpp_regex_traits.cpp | 6 + src/cregex.cpp | 2 +- src/fileiter.cpp | 5 + src/posix_api.cpp | 11 +- src/regex.cpp | 7 +- src/regex_traits_defaults.cpp | 391 +++++++++ src/wide_posix_api.cpp | 25 +- test/concepts/concept_check.cpp | 119 +-- test/concepts/wide_concept_check.cpp | 71 -- test/regress/test.hpp | 8 +- test/regress/test_deprecated.cpp | 4 +- test/regress/test_regex_search.hpp | 2 +- 32 files changed, 2667 insertions(+), 407 deletions(-) create mode 100644 include/boost/regex/concepts.hpp create mode 100644 include/boost/regex/v4/c_regex_traits.hpp create mode 100644 include/boost/regex/v4/w32_regex_traits.hpp delete mode 100644 test/concepts/wide_concept_check.cpp diff --git a/include/boost/regex/concepts.hpp b/include/boost/regex/concepts.hpp new file mode 100644 index 00000000..8773c1de --- /dev/null +++ b/include/boost/regex/concepts.hpp @@ -0,0 +1,829 @@ +/* + * + * 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 concepts.hpp + * VERSION see + * DESCRIPTION: Declares regular expression concepts. + */ + +#ifndef BOOST_REGEX_CONCEPTS_HPP_INCLUDED +#define BOOST_REGEX_CONCEPTS_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost{ + +// +// bitmask_archetype: +// this can be either an integer type, an enum, or a std::bitset, +// we use the latter as the architype as it offers the "strictest" +// of the possible interfaces: +// +typedef std::bitset<512> bitmask_archetype; +// +// char_architype: +// A strict model for the character type interface. +// +struct char_architype +{ + // default constructable: + char_architype(); + // copy constructable / assignable: + char_architype(const char_architype&); + char_architype& operator=(const char_architype&); + // constructable from an integral value: + char_architype(unsigned long val); + // comparable: + bool operator==(const char_architype&)const; + bool operator!=(const char_architype&)const; + bool operator<(const char_architype&)const; + bool operator<=(const char_architype&)const; + bool operator>=(const char_architype&)const; + bool operator>(const char_architype&)const; + // conversion to integral type: + operator long()const; +}; +// +// char_architype can not be used with basic_string: +// +} // namespace boost +namespace std{ + template<> struct char_traits{}; +} +namespace boost{ +// +// regex_traits_architype: +// A strict interpretation of the regular expression traits class requirements. +// +template +struct regex_traits_architype +{ +public: + regex_traits_architype(); + typedef charT char_type; + typedef std::size_t size_type; + typedef std::vector string_type; + typedef copy_constructible_archetype > locale_type; + typedef bitmask_archetype char_class_type; + + static size_type length(const char_type* ) { return 0; } + + charT translate(charT ) const { return charT(); } + charT translate_nocase(charT ) const { return static_object::get(); } + + template + string_type transform(ForwardIterator , ForwardIterator ) const + { return static_object::get(); } + template + string_type transform_primary(ForwardIterator , ForwardIterator ) const + { return static_object::get(); } + + template + char_class_type lookup_classname(ForwardIterator , ForwardIterator ) const + { return static_object::get(); } + template + string_type lookup_collatename(ForwardIterator , ForwardIterator ) const + { return static_object::get(); } + + bool isctype(charT, char_class_type) const + { return false; } + int value(charT, int) const + { return 0; } + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return static_object::get(); } + +private: + // this type is not copyable: + regex_traits_architype(const regex_traits_architype&); + regex_traits_architype& operator=(const regex_traits_architype&); +}; + +// +// alter this to std::tr1, to test a std implementation: +// +namespace global_regex_namespace = ::boost; + +template +struct BitmaskConcept +{ + void constraints() + { + function_requires >(); + function_requires >(); + + m_mask1 = m_mask2 | m_mask3; + m_mask1 = m_mask2 & m_mask3; + m_mask1 = m_mask2 ^ m_mask3; + + m_mask1 = ~m_mask2; + + m_mask1 |= m_mask2; + m_mask1 &= m_mask2; + m_mask1 ^= m_mask2; + } + Bitmask m_mask1, m_mask2, m_mask3; +}; + +template +struct RegexTraitsConcept +{ + RegexTraitsConcept(); + // required typedefs: + typedef typename traits::char_type char_type; + typedef typename traits::size_type size_type; + typedef typename traits::string_type string_type; + typedef typename traits::locale_type locale_type; + typedef typename traits::char_class_type char_class_type; + + void constraints() + { + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + function_requires >(); + + size_type n = traits::length(m_pointer); + ignore_unused_variable_warning(n); + + char_type c = m_ctraits.translate(m_char); + ignore_unused_variable_warning(c); + c = m_ctraits.translate_nocase(m_char); + + //string_type::foobar bar; + string_type s1 = m_ctraits.transform(m_pointer, m_pointer); + ignore_unused_variable_warning(s1); + + string_type s2 = m_ctraits.transform_primary(m_pointer, m_pointer); + ignore_unused_variable_warning(s2); + + char_class_type cc = m_ctraits.lookup_classname(m_pointer, m_pointer); + ignore_unused_variable_warning(cc); + + string_type s3 = m_ctraits.lookup_collatename(m_pointer, m_pointer); + ignore_unused_variable_warning(s3); + + bool b = m_ctraits.isctype(m_char, cc); + ignore_unused_variable_warning(b); + + int v = m_ctraits.value(m_char, 16); + ignore_unused_variable_warning(v); + + locale_type l(m_ctraits.getloc()); + m_traits.imbue(l); + ignore_unused_variable_warning(l); + } + traits m_traits; + const traits m_ctraits; + const char_type* m_pointer; + char_type m_char; +}; + +// +// helper class to compute what traits class a regular expression type is using: +// +template +struct regex_traits_computer; + +template +struct regex_traits_computer< global_regex_namespace::basic_regex > +{ + typedef traits type; +}; + +// +// BaseRegexConcept does not test anything dependent on basic_string, +// in case our charT does not have an associated char_traits: +// +template +struct BaseRegexConcept +{ + typedef typename Regex::value_type value_type; + typedef typename Regex::size_type size_type; + typedef typename Regex::flag_type flag_type; + typedef typename Regex::locale_type locale_type; + typedef input_iterator_archetype input_iterator_type; + + // derived test types: + typedef const value_type* pointer_type; + typedef bidirectional_iterator_archetype BidiIterator; + typedef global_regex_namespace::sub_match sub_match_type; + typedef global_regex_namespace::match_results match_results_type; + typedef output_iterator_archetype OutIterator; + typedef typename regex_traits_computer::type traits_type; + typedef global_regex_namespace::regex_iterator regex_iterator_type; + typedef global_regex_namespace::regex_token_iterator regex_token_iterator_type; + + void global_constraints() + { + // + // test non-template components: + // + function_requires >(); + global_regex_namespace::regex_constants::syntax_option_type opts + = global_regex_namespace::regex_constants::icase + | global_regex_namespace::regex_constants::nosubs + | global_regex_namespace::regex_constants::optimize + | global_regex_namespace::regex_constants::collate + | global_regex_namespace::regex_constants::ECMAScript + | global_regex_namespace::regex_constants::basic + | global_regex_namespace::regex_constants::extended + | global_regex_namespace::regex_constants::awk + | global_regex_namespace::regex_constants::grep + | global_regex_namespace::regex_constants::egrep; + ignore_unused_variable_warning(opts); + + function_requires >(); + global_regex_namespace::regex_constants::match_flag_type mopts + = global_regex_namespace::regex_constants::match_default + | global_regex_namespace::regex_constants::match_not_bol + | global_regex_namespace::regex_constants::match_not_eol + | global_regex_namespace::regex_constants::match_not_bow + | global_regex_namespace::regex_constants::match_not_eow + | global_regex_namespace::regex_constants::match_any + | global_regex_namespace::regex_constants::match_not_null + | global_regex_namespace::regex_constants::match_continuous + | global_regex_namespace::regex_constants::match_partial + | global_regex_namespace::regex_constants::match_prev_avail + | global_regex_namespace::regex_constants::format_default + | global_regex_namespace::regex_constants::format_sed + | global_regex_namespace::regex_constants::format_perl + | global_regex_namespace::regex_constants::format_no_copy + | global_regex_namespace::regex_constants::format_first_only; + ignore_unused_variable_warning(mopts); + + BOOST_STATIC_ASSERT((::boost::is_enum::value)); + global_regex_namespace::regex_constants::error_type e1 = global_regex_namespace::regex_constants::error_collate; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_ctype; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_escape; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_backref; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_brack; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_paren; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_brace; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_badbrace; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_range; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_space; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_badrepeat; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_complexity; + ignore_unused_variable_warning(e1); + e1 = global_regex_namespace::regex_constants::error_stack; + ignore_unused_variable_warning(e1); + + BOOST_STATIC_ASSERT((::boost::is_base_and_derived::value )); + const global_regex_namespace::regex_error except(e1); + e1 = except.code(); + + typedef typename Regex::value_type value_type; + function_requires< RegexTraitsConcept > >(); + function_requires< BaseRegexConcept > >(); + } + void constraints() + { + global_constraints(); + + BOOST_STATIC_ASSERT((::boost::is_same< flag_type, global_regex_namespace::regex_constants::syntax_option_type>::value)); + flag_type opts + = Regex::icase + | Regex::nosubs + | Regex::optimize + | Regex::collate + | Regex::ECMAScript + | Regex::basic + | Regex::extended + | Regex::awk + | Regex::grep + | Regex::egrep; + ignore_unused_variable_warning(opts); + + function_requires >(); + function_requires >(); + + // Regex constructors: + Regex e1(m_pointer); + ignore_unused_variable_warning(e1); + Regex e2(m_pointer, m_flags); + ignore_unused_variable_warning(e2); + Regex e3(m_pointer, m_size, m_flags); + ignore_unused_variable_warning(e3); + Regex e4(in1, in2); + ignore_unused_variable_warning(e4); + Regex e5(in1, in2, m_flags); + ignore_unused_variable_warning(e5); + + // assign etc: + Regex e; + e = m_pointer; + e = e1; + e.assign(e1); + e.assign(m_pointer); + e.assign(m_pointer, m_flags); + e.assign(m_pointer, m_size, m_flags); + e.assign(in1, in2); + e.assign(in1, in2, m_flags); + + // access: + const Regex ce; + bool b = ce.empty(); + ignore_unused_variable_warning(b); + size_type i = ce.mark_count(); + ignore_unused_variable_warning(i); + m_flags = ce.flags(); + e.imbue(ce.getloc()); + e.swap(e1); + + global_regex_namespace::swap(e, e1); + + // sub_match: + BOOST_STATIC_ASSERT((::boost::is_base_and_derived, sub_match_type>::value)); + typedef typename sub_match_type::value_type sub_value_type; + typedef typename sub_match_type::difference_type sub_diff_type; + typedef typename sub_match_type::iterator sub_iter_type; + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + b = m_sub.matched; + ignore_unused_variable_warning(b); + BidiIterator bi = m_sub.first; + ignore_unused_variable_warning(bi); + bi = m_sub.second; + ignore_unused_variable_warning(bi); + sub_diff_type diff = m_sub.length(); + ignore_unused_variable_warning(diff); + // match_results tests: + typedef typename match_results_type::value_type mr_value_type; + typedef typename match_results_type::const_reference mr_const_reference; + typedef typename match_results_type::reference mr_reference; + typedef typename match_results_type::const_iterator mr_const_iterator; + typedef typename match_results_type::iterator mr_iterator; + typedef typename match_results_type::difference_type mr_difference_type; + typedef typename match_results_type::size_type mr_size_type; + typedef typename match_results_type::allocator_type mr_allocator_type; + typedef typename match_results_type::char_type mr_char_type; + typedef typename match_results_type::string_type mr_string_type; + + match_results_type m1; + mr_allocator_type at; + match_results_type m2(at); + match_results_type m3(m1); + m1 = m2; + + mr_size_type mrs = m_cresults.size(); + ignore_unused_variable_warning(mrs); + mrs = m_cresults.max_size(); + ignore_unused_variable_warning(mrs); + b = m_cresults.empty(); + ignore_unused_variable_warning(b); + mr_difference_type mrd = m_cresults.length(); + ignore_unused_variable_warning(mrd); + mrd = m_cresults.length(mrs); + ignore_unused_variable_warning(mrd); + mrd = m_cresults.position(); + ignore_unused_variable_warning(mrd); + mrd = m_cresults.position(mrs); + ignore_unused_variable_warning(mrd); + + mr_const_reference mrcr = m_cresults[m_size]; + ignore_unused_variable_warning(mrcr); + mr_const_reference mrcr2 = m_cresults.prefix(); + ignore_unused_variable_warning(mrcr2); + mr_const_reference mrcr3 = m_cresults.suffix(); + ignore_unused_variable_warning(mrcr3); + mr_const_iterator mrci = m_cresults.begin(); + ignore_unused_variable_warning(mrci); + mrci = m_cresults.end(); + ignore_unused_variable_warning(mrci); + + mr_allocator_type at2 = m_cresults.get_allocator(); + m_results.swap(m_results); + global_regex_namespace::swap(m_results, m_results); + + // regex_match: + b = global_regex_namespace::regex_match(m_in, m_in, m_results, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_in, m_in, m_results, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_in, m_in, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_in, m_in, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, m_pmatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, m_pmatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_pointer, e, m_mft); + ignore_unused_variable_warning(b); + // regex_search: + b = global_regex_namespace::regex_search(m_in, m_in, m_results, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_in, m_in, m_results, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_in, m_in, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_in, m_in, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, m_pmatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, m_pmatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_pointer, e, m_mft); + ignore_unused_variable_warning(b); + + // regex_iterator: + typedef typename regex_iterator_type::regex_type rit_regex_type; + typedef typename regex_iterator_type::value_type rit_value_type; + typedef typename regex_iterator_type::difference_type rit_difference_type; + typedef typename regex_iterator_type::pointer rit_pointer; + typedef typename regex_iterator_type::reference rit_reference; + typedef typename regex_iterator_type::iterator_category rit_iterator_category; + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_convertible::value)); + // this takes care of most of the checks needed: + function_requires >(); + regex_iterator_type iter1(m_in, m_in, e); + ignore_unused_variable_warning(iter1); + regex_iterator_type iter2(m_in, m_in, e, m_mft); + ignore_unused_variable_warning(iter2); + + // regex_token_iterator: + typedef typename regex_token_iterator_type::regex_type rtit_regex_type; + typedef typename regex_token_iterator_type::value_type rtit_value_type; + typedef typename regex_token_iterator_type::difference_type rtit_difference_type; + typedef typename regex_token_iterator_type::pointer rtit_pointer; + typedef typename regex_token_iterator_type::reference rtit_reference; + typedef typename regex_token_iterator_type::iterator_category rtit_iterator_category; + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_convertible::value)); + // this takes care of most of the checks needed: + function_requires >(); + regex_token_iterator_type ti1(m_in, m_in, e); + ignore_unused_variable_warning(ti1); + regex_token_iterator_type ti2(m_in, m_in, e, 0); + ignore_unused_variable_warning(ti2); + regex_token_iterator_type ti3(m_in, m_in, e, 0, m_mft); + ignore_unused_variable_warning(ti3); + std::vector subs; + regex_token_iterator_type ti4(m_in, m_in, e, subs); + ignore_unused_variable_warning(ti4); + regex_token_iterator_type ti5(m_in, m_in, e, subs, m_mft); + ignore_unused_variable_warning(ti5); + static const int i_array[] = { 1, 2, 3, }; + regex_token_iterator_type ti6(m_in, m_in, e, i_array); + ignore_unused_variable_warning(ti6); + regex_token_iterator_type ti7(m_in, m_in, e, i_array, m_mft); + ignore_unused_variable_warning(ti7); + } + + pointer_type m_pointer; + flag_type m_flags; + size_type m_size; + input_iterator_type in1, in2; + const sub_match_type m_sub; + const value_type m_char; + match_results_type m_results; + const match_results_type m_cresults; + OutIterator m_out; + 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&); +}; + +// +// RegexConcept: +// Test every interface in the std: +// +template +struct RegexConcept +{ + typedef typename Regex::value_type value_type; + typedef typename Regex::size_type size_type; + typedef typename Regex::flag_type flag_type; + typedef typename Regex::locale_type locale_type; + + // derived test types: + typedef const value_type* pointer_type; + typedef std::basic_string string_type; + typedef boost::bidirectional_iterator_archetype BidiIterator; + typedef global_regex_namespace::sub_match sub_match_type; + typedef global_regex_namespace::match_results match_results_type; + typedef output_iterator_archetype OutIterator; + + + void constraints() + { + function_requires >(); + // string based construct: + Regex e1(m_string); + ignore_unused_variable_warning(e1); + Regex e2(m_string, m_flags); + ignore_unused_variable_warning(e2); + + // assign etc: + Regex e; + e = m_string; + e.assign(m_string); + e.assign(m_string, m_flags); + + // sub_match: + string_type s(m_sub); + ignore_unused_variable_warning(s); + s = m_sub.str(); + ignore_unused_variable_warning(s); + int i = m_sub.compare(m_string); + ignore_unused_variable_warning(i); + + int i2 = m_sub.compare(m_sub); + ignore_unused_variable_warning(i2); + i2 = m_sub.compare(m_pointer); + ignore_unused_variable_warning(i2); + + bool b = m_sub == m_sub; + ignore_unused_variable_warning(b); + b = m_sub != m_sub; + ignore_unused_variable_warning(b); + b = m_sub <= m_sub; + ignore_unused_variable_warning(b); + b = m_sub <= m_sub; + ignore_unused_variable_warning(b); + b = m_sub > m_sub; + ignore_unused_variable_warning(b); + b = m_sub >= m_sub; + ignore_unused_variable_warning(b); + + b = m_sub == m_pointer; + ignore_unused_variable_warning(b); + b = m_sub != m_pointer; + ignore_unused_variable_warning(b); + b = m_sub <= m_pointer; + ignore_unused_variable_warning(b); + b = m_sub <= m_pointer; + ignore_unused_variable_warning(b); + b = m_sub > m_pointer; + ignore_unused_variable_warning(b); + b = m_sub >= m_pointer; + ignore_unused_variable_warning(b); + + b = m_pointer == m_sub; + ignore_unused_variable_warning(b); + b = m_pointer != m_sub; + ignore_unused_variable_warning(b); + b = m_pointer <= m_sub; + ignore_unused_variable_warning(b); + b = m_pointer <= m_sub; + ignore_unused_variable_warning(b); + b = m_pointer > m_sub; + ignore_unused_variable_warning(b); + b = m_pointer >= m_sub; + ignore_unused_variable_warning(b); + + b = m_sub == m_char; + ignore_unused_variable_warning(b); + b = m_sub != m_char; + ignore_unused_variable_warning(b); + b = m_sub <= m_char; + ignore_unused_variable_warning(b); + b = m_sub <= m_char; + ignore_unused_variable_warning(b); + b = m_sub > m_char; + ignore_unused_variable_warning(b); + b = m_sub >= m_char; + ignore_unused_variable_warning(b); + + b = m_char == m_sub; + ignore_unused_variable_warning(b); + b = m_char != m_sub; + ignore_unused_variable_warning(b); + b = m_char <= m_sub; + ignore_unused_variable_warning(b); + b = m_char <= m_sub; + ignore_unused_variable_warning(b); + b = m_char > m_sub; + ignore_unused_variable_warning(b); + b = m_char >= m_sub; + ignore_unused_variable_warning(b); + + b = m_sub == m_string; + ignore_unused_variable_warning(b); + b = m_sub != m_string; + ignore_unused_variable_warning(b); + b = m_sub <= m_string; + ignore_unused_variable_warning(b); + b = m_sub <= m_string; + ignore_unused_variable_warning(b); + b = m_sub > m_string; + ignore_unused_variable_warning(b); + b = m_sub >= m_string; + ignore_unused_variable_warning(b); + + b = m_string == m_sub; + ignore_unused_variable_warning(b); + b = m_string != m_sub; + ignore_unused_variable_warning(b); + b = m_string <= m_sub; + ignore_unused_variable_warning(b); + b = m_string <= m_sub; + ignore_unused_variable_warning(b); + b = m_string > m_sub; + ignore_unused_variable_warning(b); + b = m_string >= m_sub; + ignore_unused_variable_warning(b); + + // match results: + m_string = m_results.str(); + ignore_unused_variable_warning(m_string); + m_string = m_results.str(0); + ignore_unused_variable_warning(m_string); + m_out = m_cresults.format(m_out, m_string); + m_out = m_cresults.format(m_out, m_string, m_mft); + m_string = m_cresults.format(m_string); + ignore_unused_variable_warning(m_string); + m_string = m_cresults.format(m_string, m_mft); + ignore_unused_variable_warning(m_string); + + // regex_match: + b = global_regex_namespace::regex_match(m_string, m_smatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_string, m_smatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_string, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_match(m_string, e, m_mft); + ignore_unused_variable_warning(b); + + // regex_search: + b = global_regex_namespace::regex_search(m_string, m_smatch, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_string, m_smatch, e, m_mft); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_string, e); + ignore_unused_variable_warning(b); + b = global_regex_namespace::regex_search(m_string, e, m_mft); + ignore_unused_variable_warning(b); + + // regex_replace: + m_out = global_regex_namespace::regex_replace(m_out, m_in, m_in, e, m_string, m_mft); + m_out = global_regex_namespace::regex_replace(m_out, m_in, m_in, e, m_string); + m_string = global_regex_namespace::regex_replace(m_string, e, m_string, m_mft); + ignore_unused_variable_warning(m_string); + m_string = global_regex_namespace::regex_replace(m_string, e, m_string); + ignore_unused_variable_warning(m_string); + + } + + flag_type m_flags; + string_type m_string; + const sub_match_type m_sub; + match_results_type m_results; + pointer_type m_pointer; + value_type m_char; + const match_results_type m_cresults; + OutIterator m_out; + 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&); +}; + +// +// BoostRegexConcept: +// Test every interface in the Boost implementation: +// +template +struct BoostRegexConcept +{ + typedef typename Regex::value_type value_type; + typedef typename Regex::size_type size_type; + typedef typename Regex::flag_type flag_type; + typedef typename Regex::locale_type locale_type; + + // derived test types: + typedef const value_type* pointer_type; + typedef std::basic_string string_type; + typedef typename Regex::const_iterator const_iterator; + typedef bidirectional_iterator_archetype BidiIterator; + typedef global_regex_namespace::sub_match sub_match_type; + typedef global_regex_namespace::match_results match_results_type; + + void constraints() + { + function_requires >(); + const global_regex_namespace::regex_error except(global_regex_namespace::regex_constants::error_collate); + std::ptrdiff_t pt = except.position(); + ignore_unused_variable_warning(pt); + const Regex ce, ce2; + m_stream << ce; + unsigned i = ce.error_code(); + ignore_unused_variable_warning(i); + pointer_type p = ce.expression(); + ignore_unused_variable_warning(p); + int i2 = ce.compare(ce2); + ignore_unused_variable_warning(i2); + bool b = ce == ce2; + ignore_unused_variable_warning(b); + b = ce != ce2; + ignore_unused_variable_warning(b); + b = ce < ce2; + ignore_unused_variable_warning(b); + b = ce > ce2; + ignore_unused_variable_warning(b); + b = ce <= ce2; + ignore_unused_variable_warning(b); + b = ce >= ce2; + ignore_unused_variable_warning(b); + i = ce.status(); + ignore_unused_variable_warning(i); + size_type s = ce.max_size(); + ignore_unused_variable_warning(s); + s = ce.size(); + ignore_unused_variable_warning(s); + const_iterator pi = ce.begin(); + ignore_unused_variable_warning(pi); + pi = ce.end(); + ignore_unused_variable_warning(pi); + string_type s2 = ce.str(); + ignore_unused_variable_warning(s2); + + m_string = m_sub + m_sub; + ignore_unused_variable_warning(m_string); + m_string = m_sub + m_pointer; + ignore_unused_variable_warning(m_string); + m_string = m_pointer + m_sub; + ignore_unused_variable_warning(m_string); + m_string = m_sub + m_string; + ignore_unused_variable_warning(m_string); + m_string = m_string + m_sub; + ignore_unused_variable_warning(m_string); + m_string = m_sub + m_char; + ignore_unused_variable_warning(m_string); + m_string = m_char + m_sub; + ignore_unused_variable_warning(m_string); + + m_stream << m_sub; + m_stream << m_cresults; + } + + std::basic_ostream m_stream; + sub_match_type m_sub; + pointer_type m_pointer; + string_type m_string; + 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&); +}; + +} + +#endif diff --git a/include/boost/regex/pattern_except.hpp b/include/boost/regex/pattern_except.hpp index ae183e1d..19078fa1 100644 --- a/include/boost/regex/pattern_except.hpp +++ b/include/boost/regex/pattern_except.hpp @@ -37,23 +37,13 @@ namespace boost{ #pragma warning(push) #pragma warning(disable : 4275) #endif -class BOOST_REGEX_DECL bad_pattern : public std::runtime_error + class BOOST_REGEX_DECL regex_error : public std::runtime_error { public: - explicit bad_pattern(const std::string& s) : std::runtime_error(s){}; - ~bad_pattern() throw(); -}; -#ifdef BOOST_MSVC -#pragma warning(pop) -#endif - -class BOOST_REGEX_DECL bad_expression : public bad_pattern -{ -public: - explicit bad_expression(const std::string& s, regex_constants::error_type err, std::ptrdiff_t pos) - : bad_pattern(s), m_error_code(err), m_position(pos) {} - ~bad_expression() throw(); - regex_constants::error_type errorno()const + explicit regex_error(const std::string& s, regex_constants::error_type err, std::ptrdiff_t pos); + explicit regex_error(regex_constants::error_type err); + ~regex_error() throw(); + regex_constants::error_type code()const { return m_error_code; } std::ptrdiff_t position()const { return m_position; } @@ -62,12 +52,15 @@ private: std::ptrdiff_t m_position; }; +typedef regex_error bad_pattern; +typedef regex_error bad_expression; + 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 raise_error(const traits& t, regex_constants::error_type code) { (void)t; // warning suppression std::runtime_error e(t.error_string(code)); diff --git a/include/boost/regex/v4/basic_regex.hpp b/include/boost/regex/v4/basic_regex.hpp index 15a5fce6..1696266b 100644 --- a/include/boost/regex/v4/basic_regex.hpp +++ b/include/boost/regex/v4/basic_regex.hpp @@ -47,10 +47,15 @@ struct regex_data typedef regex_constants::syntax_option_type flag_type; typedef std::size_t size_type; - regex_data(const traits& t) : m_traits(t) {} - regex_data(){} + regex_data(const ::boost::shared_ptr< + ::boost::regex_traits_wrapper >& t) + : m_ptraits(t) {} + regex_data() + : m_ptraits(new ::boost::regex_traits_wrapper()) {} - traits m_traits; // traits class instance + ::boost::shared_ptr< + ::boost::regex_traits_wrapper + > m_ptraits; // traits class instance flag_type m_flags; // flags with which we were compiled int m_status; // error code (0 implies OK). const charT* m_expression; // the original expression @@ -78,7 +83,8 @@ public: typedef const charT* const_iterator; basic_regex_implementation(){} - basic_regex_implementation(const traits& t) + basic_regex_implementation(const ::boost::shared_ptr< + ::boost::regex_traits_wrapper >& t) : regex_data(t) {} void assign(const charT* arg_first, const charT* arg_last, @@ -91,11 +97,11 @@ public: locale_type BOOST_REGEX_CALL imbue(locale_type l) { - return this->m_traits.imbue(l); + return this->m_ptraits->imbue(l); } locale_type BOOST_REGEX_CALL getloc()const { - return this->m_traits.getloc(); + return this->m_ptraits->getloc(); } std::basic_string BOOST_REGEX_CALL str()const { @@ -146,9 +152,9 @@ public: { return this->m_startmap; } - const traits& get_traits()const + const ::boost::regex_traits_wrapper& get_traits()const { - return this->m_traits; + return *(this->m_ptraits); } bool can_be_null()const { @@ -218,7 +224,7 @@ public: } basic_regex& BOOST_REGEX_CALL operator=(const charT* ptr) { - return assign(ptr, regex_constants::normal); + return assign(ptr); } // @@ -239,12 +245,7 @@ public: basic_regex& assign(const charT* p1, const charT* p2, - flag_type f = regex_constants::normal) - { - cow(); - m_pimpl->assign(p1, p2, f); - return *this; - } + flag_type f = regex_constants::normal); #if !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__) template @@ -262,8 +263,9 @@ public: template basic_regex(InputIterator arg_first, InputIterator arg_last, flag_type f = regex_constants::normal) { - std::basic_string a(arg_first, arg_last); - assign(a.data(), a.data() + a.size(), f); + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + assign(&*a.begin(), &*a.end(), f); } template @@ -285,8 +287,11 @@ public: InputIterator arg_last, flag_type f = regex_constants::normal) { - std::basic_string a(arg_first, arg_last); - return assign(a.data(), a.data() + a.size(), f); + typedef typename traits::string_type seq_type; + seq_type a(arg_first, arg_last); + const charT* p1 = &*a.begin(); + const charT* p2 = &*a.end(); + return assign(p1, p2, f); } #else unsigned int BOOST_REGEX_CALL set_expression(const std::basic_string& p, flag_type f = regex_constants::normal) @@ -315,11 +320,7 @@ public: // // locale: - locale_type BOOST_REGEX_CALL imbue(locale_type l) - { - cow(); - return m_pimpl->imbue(l); - } + locale_type BOOST_REGEX_CALL imbue(locale_type l); locale_type BOOST_REGEX_CALL getloc()const { return m_pimpl.get() ? m_pimpl->getloc() : locale_type(); @@ -405,7 +406,7 @@ public: { return compare(e) == 0; } - bool operator != (const basic_regex& e) + bool BOOST_REGEX_CALL operator != (const basic_regex& e)const { return compare(e) != 0; } @@ -465,7 +466,7 @@ public: assert(m_pimpl.get()); return m_pimpl->get_map(); } - const traits& get_traits()const + const ::boost::regex_traits_wrapper& get_traits()const { assert(m_pimpl.get()); return m_pimpl->get_traits(); @@ -483,20 +484,51 @@ public: private: shared_ptr > m_pimpl; - void cow() - { - // copy-on-write - if(!m_pimpl.get()) - { - m_pimpl = shared_ptr >(new re_detail::basic_regex_implementation()); - } - else if(!m_pimpl.unique()) - { - m_pimpl = shared_ptr >(new re_detail::basic_regex_implementation(m_pimpl->get_traits())); - } - } }; +// +// out of line members; +// these are the only members that mutate the basic_regex object, +// and are designed to provide the strong exception guarentee +// (in the event of a throw, the state of the object remains unchanged). +// +template +basic_regex& basic_regex::assign(const charT* p1, + const charT* p2, + flag_type f) +{ + shared_ptr > temp; + if(!m_pimpl.get()) + { + temp = shared_ptr >(new re_detail::basic_regex_implementation()); + } + else if(!m_pimpl.unique()) + { + temp = shared_ptr >(new re_detail::basic_regex_implementation(m_pimpl->m_ptraits)); + } + temp->assign(p1, p2, f); + temp.swap(m_pimpl); + return *this; +} + +template +typename basic_regex::locale_type BOOST_REGEX_CALL basic_regex::imbue(locale_type l) +{ + shared_ptr > temp(new re_detail::basic_regex_implementation()); + locale_type result = temp->imbue(l); + temp.swap(m_pimpl); + return result; +} + +// +// non-members: +// +template +void swap(basic_regex& e1, basic_regex& e2) +{ + e1.swap(e2); +} + #ifndef BOOST_NO_STD_LOCALE template std::basic_ostream& diff --git a/include/boost/regex/v4/basic_regex_creator.hpp b/include/boost/regex/v4/basic_regex_creator.hpp index 2b30592a..863e3cad 100644 --- a/include/boost/regex/v4/basic_regex_creator.hpp +++ b/include/boost/regex/v4/basic_regex_creator.hpp @@ -31,8 +31,14 @@ namespace re_detail{ template struct digraph : public std::pair { - digraph(charT c1 = 0, charT c2 = 0) : std::pair(c1, c2){} - digraph(const std::basic_string& s) : std::pair() + digraph() : std::pair(0, 0){} + digraph(charT c1) : std::pair(c1, 0){} + digraph(charT c1, charT c2) : std::pair(c1, c2){} +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) + digraph(const digraph& d) : std::pair(d.first, d.second){} +#endif + template + digraph(const Seq& s) : std::pair() { BOOST_ASSERT(s.size() <= 2); BOOST_ASSERT(s.size()); @@ -202,7 +208,8 @@ public: void finalize(const charT* p1, const charT* p2); protected: regex_data* m_pdata; // pointer to the basic_regex_data struct we are filling in - const traits& m_traits; // convenience reference to traits class + const ::boost::regex_traits_wrapper& + m_traits; // convenience reference to traits class re_syntax_base* m_last_state; // the last state we added bool m_icase; // true for case insensitive matches unsigned m_repeater_id; // the id of the next repeater @@ -232,7 +239,7 @@ private: template basic_regex_creator::basic_regex_creator(regex_data* data) - : m_pdata(data), m_traits(data->m_traits), m_last_state(0), m_repeater_id(0), m_has_backrefs(false), m_backrefs(0) + : m_pdata(data), m_traits(*(data->m_ptraits)), m_last_state(0), m_repeater_id(0), m_has_backrefs(false), m_backrefs(0) { m_pdata->m_data.clear(); static const charT w = 'w'; @@ -245,11 +252,11 @@ basic_regex_creator::basic_regex_creator(regex_data @@ -329,7 +336,7 @@ template re_syntax_base* basic_regex_creator::append_set( const basic_char_set& char_set, mpl::false_*) { - typedef std::basic_string string_type; + typedef typename traits::string_type string_type; typedef typename basic_char_set::list_iterator item_iterator; typedef typename traits::char_class_type mask_type; @@ -414,9 +421,9 @@ re_syntax_base* basic_regex_creator::append_set( return 0; } charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s1.size() + s2.size() + 2) ) ); - std::memcpy(p, s1.c_str(), sizeof(charT) * (s1.size() + 1)); + std::memcpy(p, &*s1.begin(), sizeof(charT) * (s1.size() + 1)); p += s1.size() + 1; - std::memcpy(p, s2.c_str(), sizeof(charT) * (s2.size() + 1)); + std::memcpy(p, &*s2.begin(), sizeof(charT) * (s2.size() + 1)); } // // now process the equivalence classes: @@ -436,7 +443,7 @@ re_syntax_base* basic_regex_creator::append_set( if(s.empty()) return 0; // invalid or unsupported equivalence class charT* p = static_cast(this->m_pdata->m_data.extend(sizeof(charT) * (s.size()+1) ) ); - std::memcpy(p, s.c_str(), sizeof(charT) * (s.size() + 1)); + std::memcpy(p, &*s.begin(), sizeof(charT) * (s.size() + 1)); ++first; } // @@ -450,7 +457,7 @@ template re_syntax_base* basic_regex_creator::append_set( const basic_char_set& char_set, mpl::true_*) { - typedef std::basic_string string_type; + typedef typename traits::string_type string_type; typedef typename basic_char_set::list_iterator item_iterator; re_set* result = static_cast(append_state(syntax_element_set, sizeof(re_set))); @@ -529,7 +536,7 @@ re_syntax_base* basic_regex_creator::append_set( { for(unsigned i = 0; i < (1u << CHAR_BIT); ++i) { - if(this->m_traits.is_class(static_cast(i), m)) + if(this->m_traits.isctype(static_cast(i), m)) result->_map[i] = true; } } @@ -817,7 +824,7 @@ void basic_regex_creator::create_startmap(re_syntax_base* state, l_map[0] |= mask_init; for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) { - if(!m_traits.is_class(static_cast(i), m_word_mask)) + if(!m_traits.isctype(static_cast(i), m_word_mask)) l_map[i] &= static_cast(~mask); } } @@ -832,7 +839,7 @@ void basic_regex_creator::create_startmap(re_syntax_base* state, l_map[0] |= mask_init; for(unsigned int i = 0; i < (1u << CHAR_BIT); ++i) { - if(m_traits.is_class(static_cast(i), m_word_mask)) + if(m_traits.isctype(static_cast(i), m_word_mask)) l_map[i] &= static_cast(~mask); } } diff --git a/include/boost/regex/v4/basic_regex_parser.hpp b/include/boost/regex/v4/basic_regex_parser.hpp index b592ae96..8bb7867f 100644 --- a/include/boost/regex/v4/basic_regex_parser.hpp +++ b/include/boost/regex/v4/basic_regex_parser.hpp @@ -119,8 +119,8 @@ void basic_regex_parser::parse(const charT* p1, const charT* p2, template void basic_regex_parser::fail(regex_constants::error_type error_code, std::ptrdiff_t position) { - std::string message = this->m_pdata->m_traits.error_string(error_code); - boost::bad_expression e(message, error_code, position); + std::string message = this->m_pdata->m_ptraits->error_string(error_code); + boost::regex_error e(message, error_code, position); boost::throw_exception(e); } @@ -256,7 +256,7 @@ bool basic_regex_parser::parse_literal() ((this->flags() & (regbase::main_option_type|regbase::mod_x|regbase::no_perl_ex)) != regbase::mod_x) - || !this->m_traits.is_class(*m_position, this->m_mask_space)) + || !this->m_traits.isctype(*m_position, this->m_mask_space)) this->append_literal(*m_position); ++m_position; return true; @@ -584,7 +584,7 @@ bool basic_regex_parser::parse_repeat_range(bool isbasic) std::size_t min, max; int v; // skip whitespace: - while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space)) + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) ++m_position; // fail if at end: if(this->m_position == this->m_end) @@ -592,7 +592,7 @@ bool basic_regex_parser::parse_repeat_range(bool isbasic) // get min: v = this->m_traits.toi(m_position, m_end, 10); // skip whitespace: - while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space)) + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) ++m_position; if(v < 0) fail(regex_constants::error_badbrace, this->m_position - this->m_base); @@ -605,7 +605,7 @@ bool basic_regex_parser::parse_repeat_range(bool isbasic) // move on and error check: ++m_position; // skip whitespace: - while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space)) + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) ++m_position; if(this->m_position == this->m_end) fail(regex_constants::error_brace, this->m_position - this->m_base); @@ -619,7 +619,7 @@ bool basic_regex_parser::parse_repeat_range(bool isbasic) max = min; } // skip whitespace: - while((m_position != m_end) && this->m_traits.is_class(*m_position, this->m_mask_space)) + while((m_position != m_end) && this->m_traits.isctype(*m_position, this->m_mask_space)) ++m_position; // OK now check trailing }: if(this->m_position == this->m_end) @@ -759,7 +759,7 @@ bool basic_regex_parser::parse_set() == regex_constants::escape_type_class) { char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); - if(m) + if(m != 0) { char_set.add_class(m); break; @@ -770,7 +770,7 @@ bool basic_regex_parser::parse_set() { // negated character classes aren't supported: char_class_type m = this->m_traits.lookup_classname(m_position, m_position+1); - if(m) + if(m != 0) { fail(regex_constants::error_escape, m_position - m_base); } @@ -835,7 +835,7 @@ bool basic_regex_parser::parse_inner_set(basic_char_setm_traits.lookup_classname(name_first, name_last); - if(0 == m) + if(m == 0) { if(char_set.empty() && (name_last - name_first == 1)) { @@ -909,7 +909,7 @@ bool basic_regex_parser::parse_inner_set(basic_char_set void basic_regex_parser::parse_set_literal(basic_char_set& char_set) { - digraph start_range = get_next_set_literal(char_set); + digraph start_range(get_next_set_literal(char_set)); if(m_end == m_position) fail(regex_constants::error_brack, m_position - m_base); if(this->m_traits.syntax_type(*m_position) == regex_constants::syntax_dash) @@ -1006,7 +1006,7 @@ charT basic_regex_parser::unescape_character() charT result(0); if(m_position == m_end) fail(regex_constants::error_escape, m_position - m_base); - switch(this->m_traits.syntax_type(*m_position)) + switch(this->m_traits.escape_syntax_type(*m_position)) { case regex_constants::escape_type_control_a: result = charT('\a'); @@ -1127,7 +1127,7 @@ bool basic_regex_parser::parse_backref() this->append_literal(c); } else - fail(regex_constants::error_subreg, m_position - m_end); + fail(regex_constants::error_backref, m_position - m_end); return true; } @@ -1161,7 +1161,7 @@ bool basic_regex_parser::parse_QE() return false; } // check to see if it's a \E: - if(this->m_traits.syntax_type(*m_position) == regex_constants::escape_type_E) + if(this->m_traits.escape_syntax_type(*m_position) == regex_constants::escape_type_E) { ++m_position; end = m_position - 2; @@ -1450,7 +1450,7 @@ regex_constants::syntax_option_type basic_regex_parser::parse_opt } while(!breakout); - if(*m_position == '-') + if(*m_position == static_cast('-')) { if(++m_position == m_end) fail(regex_constants::error_paren, m_position - m_base); diff --git a/include/boost/regex/v4/c_regex_traits.hpp b/include/boost/regex/v4/c_regex_traits.hpp new file mode 100644 index 00000000..f15c8084 --- /dev/null +++ b/include/boost/regex/v4/c_regex_traits.hpp @@ -0,0 +1,146 @@ +/* + * + * 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.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class that wraps the global C locale. + */ + +#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_C_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_CONFIG_HPP +#include +#endif +#ifndef BOOST_REGEX_WORKAROUND_HPP +#include +#endif + +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strlen; using ::tolower; +} +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost{ + +template +struct c_regex_traits; + +template<> +struct BOOST_REGEX_DECL c_regex_traits +{ + c_regex_traits(){} + typedef char char_type; + typedef std::size_t size_type; + typedef std::string string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::strlen)(p); + } + + char translate(char c) const + { + return c; + } + char translate_nocase(char c) const + { + return (std::tolower)(c); + } + + static string_type BOOST_REGEX_CALL transform(const char* p1, const char* p2); + static string_type BOOST_REGEX_CALL transform_primary(const char* p1, const char* p2); + + static char_class_type BOOST_REGEX_CALL lookup_classname(const char* p1, const char* p2); + static string_type BOOST_REGEX_CALL lookup_collatename(const char* p1, const char* p2); + + static bool BOOST_REGEX_CALL isctype(char, char_class_type); + static int BOOST_REGEX_CALL value(char, int); + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#ifndef BOOST_NO_WREGEX +template<> +struct BOOST_REGEX_DECL c_regex_traits +{ + c_regex_traits(){} + typedef wchar_t char_type; + typedef std::size_t size_type; + typedef std::wstring string_type; + struct locale_type{}; + typedef boost::uint32_t char_class_type; + + static size_type length(const char_type* p) + { + return (std::wcslen)(p); + } + + wchar_t translate(wchar_t c) const + { + return c; + } + wchar_t translate_nocase(wchar_t c) const + { + return (std::towlower)(c); + } + + string_type BOOST_REGEX_CALL transform(const wchar_t* p1, const wchar_t* p2) const; + string_type BOOST_REGEX_CALL transform_primary(const wchar_t* p1, const wchar_t* p2) const; + + char_class_type BOOST_REGEX_CALL lookup_classname(const wchar_t* p1, const wchar_t* p2) const; + string_type BOOST_REGEX_CALL lookup_collatename(const wchar_t* p1, const wchar_t* p2) const; + + bool BOOST_REGEX_CALL isctype(wchar_t, char_class_type) const; + int BOOST_REGEX_CALL value(wchar_t, int) const; + + locale_type imbue(locale_type l) + { return l; } + locale_type getloc()const + { return locale_type(); } + +private: + // this type is not copyable: + c_regex_traits(const c_regex_traits&); + c_regex_traits& operator=(const c_regex_traits&); +}; + +#endif // BOOST_NO_WREGEX + +} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif + + + diff --git a/include/boost/regex/v4/cpp_regex_traits.hpp b/include/boost/regex/v4/cpp_regex_traits.hpp index d1c1dec7..8447af86 100644 --- a/include/boost/regex/v4/cpp_regex_traits.hpp +++ b/include/boost/regex/v4/cpp_regex_traits.hpp @@ -67,8 +67,8 @@ public: const charT* getnext() { return this->gptr(); } protected: std::basic_streambuf* setbuf(char_type* s, streamsize n); - //typename parser_buf::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which); - //typename parser_buf::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which); + typename parser_buf::pos_type seekpos(pos_type sp, ::std::ios_base::openmode which); + typename parser_buf::pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which); private: parser_buf& operator=(const parser_buf&); parser_buf(const parser_buf&); @@ -82,7 +82,6 @@ parser_buf::setbuf(char_type* s, streamsize n) return this; } -#if 0 template typename parser_buf::pos_type parser_buf::seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) @@ -141,7 +140,6 @@ parser_buf::seekpos(pos_type sp, ::std::ios_base::openmode which) } return pos_type(off_type(-1)); } -#endif // // class cpp_regex_traits_base: @@ -422,13 +420,13 @@ typename cpp_regex_traits_implementation::string_type case sort_fixed: { // get a regular sort key, and then truncate it: - result.assign(this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size())); + result.assign(this->m_pcollate->transform(p1, p2)); result.erase(this->m_collate_delim); break; } case sort_delim: // get a regular sort key, and then truncate everything after the delim: - result.assign(this->m_pcollate->transform(&*result.begin(), &*result.begin() + result.size())); + result.assign(this->m_pcollate->transform(p1, p2)); std::size_t i; for(i = 0; i < result.size(); ++i) { @@ -511,7 +509,9 @@ cpp_regex_traits_implementation::cpp_regex_traits_implementation(const st // // Error messages: // - for(boost::regex_constants::error_type i = 0; i <= boost::regex_constants::error_unknown; ++i) + for(boost::regex_constants::error_type i = static_cast(0); + i <= boost::regex_constants::error_unknown; + i = static_cast(i + 1)) { const char* p = get_default_error_string(i); string_type default_message; @@ -609,15 +609,6 @@ boost::shared_ptr > create_cpp_regex_trai return boost::shared_ptr >(new cpp_regex_traits_implementation(l)); } -// -// helpers to suppress warnings: -// -template -inline bool is_extended(charT c) -{ return c > 256; } -inline bool is_extended(char) -{ return false; } - } // re_detail template @@ -632,6 +623,8 @@ public: typedef std::locale locale_type; typedef boost::uint_least32_t char_class_type; + struct boost_extensions_tag{}; + cpp_regex_traits() : m_pimpl(re_detail::create_cpp_regex_traits(std::locale())) { } @@ -647,6 +640,14 @@ public: { return m_pimpl->escape_syntax_type(c); } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return m_pimpl->m_pctype->tolower(c); + } charT translate(charT c, bool icase) const { return icase ? m_pimpl->m_pctype->tolower(c) : c; @@ -675,7 +676,7 @@ public: { return m_pimpl->lookup_collatename(p1, p2); } - bool is_class(charT c, char_class_type f) const + bool isctype(charT c, char_class_type f) const { typedef typename std::ctype::mask ctype_mask; if((f & re_detail::cpp_regex_traits_implementation::mask_base) @@ -693,6 +694,11 @@ public: return false; } int toi(const charT*& p1, const charT* p2, int radix)const; + int value(charT c, int radix)const + { + const charT* pc = &c; + return toi(pc, pc + 1, radix); + } locale_type imbue(locale_type l) { std::locale result(getloc()); diff --git a/include/boost/regex/v4/error_type.hpp b/include/boost/regex/v4/error_type.hpp index b8d6b35f..e3ac1121 100644 --- a/include/boost/regex/v4/error_type.hpp +++ b/include/boost/regex/v4/error_type.hpp @@ -30,29 +30,30 @@ namespace boost{ #ifdef __cplusplus namespace regex_constants{ -typedef unsigned error_type; +enum error_type{ -static const error_type error_ok = 0; // not used -static const error_type error_no_match = 1; // not used -static const error_type error_bad_pattern = 2; -static const error_type error_collate = 3; -static const error_type error_ctype = 4; -static const error_type error_escape = 5; -static const error_type error_subreg = 6; -static const error_type error_brack = 7; -static const error_type error_paren = 8; -static const error_type error_brace = 9; -static const error_type error_badbrace = 10; -static const error_type error_range = 11; -static const error_type error_space = 12; -static const error_type error_badrepeat = 13; -static const error_type error_end = 14; // not used -static const error_type error_size = 15; -static const error_type error_right_paren = 16; // not used -static const error_type error_empty = 17; -static const error_type error_complexity = 18; -static const error_type error_stack = 19; -static const error_type error_unknown = 20; + error_ok = 0, // not used + error_no_match = 1, // not used + error_bad_pattern = 2, + error_collate = 3, + error_ctype = 4, + error_escape = 5, + error_backref = 6, + error_brack = 7, + error_paren = 8, + error_brace = 9, + error_badbrace = 10, + error_range = 11, + error_space = 12, + error_badrepeat = 13, + error_end = 14, // not used + error_size = 15, + error_right_paren = 16, // not used + error_empty = 17, + error_complexity = 18, + error_stack = 19, + error_unknown = 20 +}; } } diff --git a/include/boost/regex/v4/perl_matcher.hpp b/include/boost/regex/v4/perl_matcher.hpp index 5f7bc86d..ceb1d6c7 100644 --- a/include/boost/regex/v4/perl_matcher.hpp +++ b/include/boost/regex/v4/perl_matcher.hpp @@ -31,7 +31,7 @@ BOOST_REGEX_DECL void BOOST_REGEX_CALL verify_options(boost::regex::flag_type ef template bool can_start(charT c, const unsigned char* map, unsigned char mask) { - return ((c < 0) ? true : ((c >= (1 << CHAR_BIT)) ? true : map[c] & mask)); + return ((c < static_cast(0)) ? true : ((c >= static_cast(1 << CHAR_BIT)) ? true : map[c] & mask)); } inline bool can_start(char c, const unsigned char* map, unsigned char mask) { @@ -66,7 +66,9 @@ inline bool can_start(wchar_t c, const unsigned char* map, unsigned char mask) // which succeeds when it should not. // #ifndef _RWSTD_VER -# define STR_COMP(s,p) s.compare(p) +template +inline int string_compare(const std::basic_string& s, const C* p) +{ return s.compare(p); } #else template inline int string_compare(const std::basic_string& s, const C* p) @@ -77,13 +79,25 @@ inline int string_compare(const std::string& s, const char* p) inline int string_compare(const std::wstring& s, const wchar_t* p) { return std::wcscmp(s.c_str(), p); } #endif -# define STR_COMP(s,p) string_compare(s,p) #endif +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1310) +template +inline int string_compare(const Seq& s, const C* p) +{ + std::size_t i = 0; + while(p[i] && (p[i] == s[i])) + { + ++i; + } + return s[i] - p[i]; +} +#endif +# define STR_COMP(s,p) string_compare(s,p) template inline const charT* re_skip_past_null(const charT* p) { - while (*p != 0) ++p; + while (*p != static_cast(0)) ++p; return ++p; } @@ -101,7 +115,7 @@ iterator BOOST_REGEX_CALL re_is_set_member(iterator next, if(next == last) return next; typedef typename traits_type::string_type traits_string_type; - const traits_type& traits_inst = e.m_traits; + const ::boost::regex_traits_wrapper& traits_inst = *(e.m_ptraits); // dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never // referenced @@ -112,12 +126,12 @@ iterator BOOST_REGEX_CALL re_is_set_member(iterator next, for(i = 0; i < set_->csingles; ++i) { ptr = next; - if(*p == 0) + if(*p == static_cast(0)) { // treat null string as special case: if(traits_inst.translate(*ptr, icase) != *p) { - while(*p == 0)++p; + while(*p == static_cast(0))++p; continue; } return set_->isnot ? next : (ptr == next) ? ++next : ptr; @@ -132,7 +146,7 @@ iterator BOOST_REGEX_CALL re_is_set_member(iterator next, ++ptr; } - if(*p == 0) // if null we've matched + if(*p == static_cast(0)) // if null we've matched return set_->isnot ? next : (ptr == next) ? ++next : ptr; p = re_skip_past_null(p); // skip null @@ -188,7 +202,7 @@ iterator BOOST_REGEX_CALL re_is_set_member(iterator next, } } } - if(traits_inst.is_class(col, set_->cclasses) == true) + if(traits_inst.isctype(col, set_->cclasses) == true) return set_->isnot ? next : ++next; return set_->isnot ? ++next : next; } @@ -365,7 +379,7 @@ private: // the expression being examined: const basic_regex& re; // the expression's traits class: - const traits& traits_inst; + const ::boost::regex_traits_wrapper& traits_inst; // the next state in the machine being matched: const re_syntax_base* pstate; // matching flags in use: diff --git a/include/boost/regex/v4/perl_matcher_common.hpp b/include/boost/regex/v4/perl_matcher_common.hpp index ad7790f3..b281ee6f 100644 --- a/include/boost/regex/v4/perl_matcher_common.hpp +++ b/include/boost/regex/v4/perl_matcher_common.hpp @@ -353,7 +353,7 @@ bool perl_matcher::match_start_line() --t; if(position != last) { - if(is_separator(*t) && !((*t == '\r') && (*position == '\n')) ) + if(is_separator(*t) && !((*t == static_cast('\r')) && (*position == static_cast('\n'))) ) { pstate = pstate->next.p; return true; @@ -382,7 +382,7 @@ bool perl_matcher::match_end_line() // check that we're not in the middle of \r\n sequence BidiIterator t(position); --t; - if((*t == '\r') && (*position == '\n')) + if((*t == static_cast('\r')) && (*position == static_cast('\n'))) { return false; } @@ -449,9 +449,9 @@ bool perl_matcher::match_word_boundary() { // prev and this character must be opposites: #if defined(BOOST_REGEX_USE_C_LOCALE) && defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95) - b = traits::is_class(*position, m_word_mask); + b = traits::isctype(*position, m_word_mask); #else - b = traits_inst.is_class(*position, m_word_mask); + b = traits_inst.isctype(*position, m_word_mask); #endif } else @@ -468,7 +468,7 @@ bool perl_matcher::match_word_boundary() else { --position; - b ^= traits_inst.is_class(*position, m_word_mask); + b ^= traits_inst.isctype(*position, m_word_mask); ++position; } if(b) @@ -485,7 +485,7 @@ bool perl_matcher::match_within_word() if(position == last) return false; // both prev and this character must be m_word_mask: - if(traits_inst.is_class(*position, m_word_mask)) + if(traits_inst.isctype(*position, m_word_mask)) { bool b; if((position == base) && ((m_match_flags & match_prev_avail) == 0)) @@ -493,7 +493,7 @@ bool perl_matcher::match_within_word() else { --position; - b = traits_inst.is_class(*position, m_word_mask); + b = traits_inst.isctype(*position, m_word_mask); ++position; } if(b) @@ -510,7 +510,7 @@ bool perl_matcher::match_word_start() { if(position == last) return false; // can't be starting a word if we're already at the end of input - if(!traits_inst.is_class(*position, m_word_mask)) + if(!traits_inst.isctype(*position, m_word_mask)) return false; // next character isn't a word character if((position == base) && ((m_match_flags & match_prev_avail) == 0)) { @@ -522,7 +522,7 @@ bool perl_matcher::match_word_start() // otherwise inside buffer: BidiIterator t(position); --t; - if(traits_inst.is_class(*t, m_word_mask)) + if(traits_inst.isctype(*t, m_word_mask)) return false; // previous character not non-word } // OK we have a match: @@ -537,7 +537,7 @@ bool perl_matcher::match_word_end() return false; // start of buffer can't be end of word BidiIterator t(position); --t; - if(traits_inst.is_class(*t, m_word_mask) == false) + if(traits_inst.isctype(*t, m_word_mask) == false) return false; // previous character wasn't a word character if(position == last) @@ -548,7 +548,7 @@ bool perl_matcher::match_word_end() else { // otherwise inside buffer: - if(traits_inst.is_class(*position, m_word_mask)) + if(traits_inst.isctype(*position, m_word_mask)) return false; // next character is a word character } pstate = pstate->next.p; @@ -745,9 +745,9 @@ bool perl_matcher::find_restart_word() return true; do { - while((position != last) && traits_inst.is_class(*position, m_word_mask)) + while((position != last) && traits_inst.isctype(*position, m_word_mask)) ++position; - while((position != last) && !traits_inst.is_class(*position, m_word_mask)) + while((position != last) && !traits_inst.isctype(*position, m_word_mask)) ++position; if(position == last) break; diff --git a/include/boost/regex/v4/regex_format.hpp b/include/boost/regex/v4/regex_format.hpp index dc2d14f3..13fe740c 100644 --- a/include/boost/regex/v4/regex_format.hpp +++ b/include/boost/regex/v4/regex_format.hpp @@ -36,84 +36,6 @@ class match_results; namespace re_detail{ -// -// helper functions: -// -template -std::ptrdiff_t global_length(const charT* p) -{ - std::ptrdiff_t n = 0; - while(*p) - { - ++p; - ++n; - } - 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; -} - - // // struct trivial_format_traits: // defines minimum localisation support for formatting @@ -136,9 +58,14 @@ struct trivial_format_traits { return ::boost::re_detail::global_upper(c); } - static int toi(const charT*& p1, const charT* p2, int radix) + static int value(const charT c, int radix) { - return global_toi(p1, p2, radix); + int result = global_value(c); + return result >= radix ? -1 : result; + } + int toi(const charT*& p1, const charT* p2, int radix)const + { + return global_toi(p1, p2, radix, *this); } }; diff --git a/include/boost/regex/v4/regex_iterator.hpp b/include/boost/regex/v4/regex_iterator.hpp index f799a955..29c7fbd8 100644 --- a/include/boost/regex/v4/regex_iterator.hpp +++ b/include/boost/regex/v4/regex_iterator.hpp @@ -51,7 +51,7 @@ public: bool compare(const regex_iterator_implementation& that) { if(this == &that) return true; - return (re == that.re) && (end == that.end) && (flags == that.flags) && (what[0].first == that.what[0].first) && (what[0].second == that.what[0].second); + return (&re.get_data() == &that.re.get_data()) && (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; } diff --git a/include/boost/regex/v4/regex_match.hpp b/include/boost/regex/v4/regex_match.hpp index 9e4822b5..bc52750d 100644 --- a/include/boost/regex/v4/regex_match.hpp +++ b/include/boost/regex/v4/regex_match.hpp @@ -107,6 +107,34 @@ inline bool regex_match(const char* str, match_results m; return regex_match(str, str + regex::traits_type::length(str), m, e, flags); } +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); +} +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); +} #ifndef BOOST_NO_WREGEX inline bool regex_match(const wchar_t* str, wcmatch& m, @@ -122,6 +150,34 @@ inline bool regex_match(const wchar_t* str, match_results m; return regex_match(str, str + wregex::traits_type::length(str), m, e, flags); } +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); +} +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 inline bool regex_match(const std::string& s, smatch& m, @@ -137,6 +193,34 @@ inline bool regex_match(const std::string& s, match_results m; return regex_match(s.begin(), s.end(), m, e, flags); } +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); +} +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); +} #if !defined(BOOST_NO_WREGEX) inline bool regex_match(const std::basic_string& s, match_results::const_iterator>& m, @@ -152,6 +236,34 @@ inline bool regex_match(const std::basic_string& s, match_results::const_iterator> m; return regex_match(s.begin(), s.end(), m, e, flags); } +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); +} +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 diff --git a/include/boost/regex/v4/regex_split.hpp b/include/boost/regex/v4/regex_split.hpp index ff1bf74a..b02e01e7 100644 --- a/include/boost/regex/v4/regex_split.hpp +++ b/include/boost/regex/v4/regex_split.hpp @@ -63,7 +63,7 @@ bool split_pred::operator() // output sub-expressions only: for(unsigned i = 1; i < what.size(); ++i) { - *(*p_out) = static_cast(what[i]); + *(*p_out) = what.str(i); ++(*p_out); if(0 == --*p_max) return false; } @@ -75,7 +75,7 @@ bool split_pred::operator() const sub_match& sub = what[-1]; if((sub.first != sub.second) || (*p_max != initial_max)) { - *(*p_out) = static_cast(sub); + *(*p_out) = sub.str(); ++(*p_out); return --*p_max; } diff --git a/include/boost/regex/v4/regex_token_iterator.hpp b/include/boost/regex/v4/regex_token_iterator.hpp index 78b20315..056c4e5f 100644 --- a/include/boost/regex/v4/regex_token_iterator.hpp +++ b/include/boost/regex/v4/regex_token_iterator.hpp @@ -113,7 +113,7 @@ public: bool compare(const regex_token_iterator_implementation& that) { if(this == &that) return true; - return (re == that.re) + return (&re.get_data() == &that.re.get_data()) && (end == that.end) && (flags == that.flags) && (N == that.N) diff --git a/include/boost/regex/v4/regex_traits.hpp b/include/boost/regex/v4/regex_traits.hpp index febc80d7..d7325836 100644 --- a/include/boost/regex/v4/regex_traits.hpp +++ b/include/boost/regex/v4/regex_traits.hpp @@ -34,10 +34,19 @@ #ifndef BOOST_CPP_REGEX_TRAITS_HPP_INCLUDED #include #endif +#ifndef BOOST_C_REGEX_TRAITS_HPP_INCLUDED +#include +#endif +#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +#include +#endif #ifndef BOOST_REGEX_FWD_HPP_INCLUDED #include #endif +#include "boost/mpl/aux_/has_xxx.hpp" +#include + #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif @@ -50,6 +59,99 @@ struct regex_traits : public implementationT regex_traits() : implementationT() {} }; +// +// class regex_traits_wrapper. +// this is what our implementation will actually store; +// it provides default implementations of the "optional" +// interfaces that we support, in addition to the +// required "standard" ones: +// +namespace re_detail{ +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +BOOST_MPL_HAS_XXX_TRAIT_DEF(boost_extensions_tag) +#else +template +struct has_boost_extensions_tag +{ + BOOST_STATIC_CONSTANT(bool, value = false); +}; +#endif + +template +struct default_wrapper : public BaseT +{ + typedef typename BaseT::char_type char_type; + std::string error_string(::boost::regex_constants::error_type e)const + { + return ::boost::re_detail::get_default_error_string(e); + } + ::boost::regex_constants::syntax_type syntax_type(char_type c)const + { + return ((c & 0x7f) == c) ? get_default_syntax_type(static_cast(c)) : ::boost::regex_constants::syntax_char; + } + ::boost::regex_constants::escape_syntax_type escape_syntax_type(char_type c)const + { + return ((c & 0x7f) == c) ? get_default_escape_syntax_type(static_cast(c)) : ::boost::regex_constants::escape_type_identity; + } + int toi(const char_type*& p1, const char_type* p2, int radix)const + { + return ::boost::re_detail::global_toi(p1, p2, radix, *this); + } + char_type translate(char_type c, bool icase)const + { + return (icase ? this->translate_nocase(c) : this->translate(c)); + } + char_type translate(char_type c)const + { + return BaseT::translate(c); + } + char_type tolower(char_type c)const + { + return ::boost::re_detail::global_lower(c); + } + char_type toupper(char_type c)const + { + return ::boost::re_detail::global_upper(c); + } +}; + +template +struct compute_wrapper_base +{ + typedef BaseT type; +}; +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct compute_wrapper_base +{ + typedef default_wrapper type; +}; +#else +template <> +struct compute_wrapper_base, false> +{ + typedef default_wrapper > type; +}; +#ifndef BOOST_NO_WREGEX +template <> +struct compute_wrapper_base, false> +{ + typedef default_wrapper > type; +}; +#endif +#endif + +} // namespace re_detail + +template +struct regex_traits_wrapper + : public ::boost::re_detail::compute_wrapper_base< + BaseT, + ::boost::re_detail::has_boost_extensions_tag::value + >::type +{ +}; + } // namespace boost #ifdef BOOST_HAS_ABI_HEADERS diff --git a/include/boost/regex/v4/regex_traits_defaults.hpp b/include/boost/regex/v4/regex_traits_defaults.hpp index 0409f6bd..e5376e91 100644 --- a/include/boost/regex/v4/regex_traits_defaults.hpp +++ b/include/boost/regex/v4/regex_traits_defaults.hpp @@ -23,10 +23,36 @@ # include BOOST_ABI_PREFIX #endif +#ifndef BOOST_REGEX_SYNTAX_TYPE_HPP +#include +#endif +#ifndef BOOST_REGEX_ERROR_TYPE_HPP +#include +#endif + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::strlen; +} +#endif + namespace boost{ namespace re_detail{ + +// +// helpers to suppress warnings: +// +template +inline bool is_extended(charT c) +{ return c > 256; } +inline bool is_extended(char) +{ return false; } + + BOOST_REGEX_DECL const char* BOOST_REGEX_CALL get_default_syntax(regex_constants::syntax_type n); BOOST_REGEX_DECL const char* BOOST_REGEX_CALL get_default_error_string(regex_constants::error_type n); +BOOST_REGEX_DECL regex_constants::syntax_type BOOST_REGEX_CALL get_default_syntax_type(char c); +BOOST_REGEX_DECL regex_constants::escape_syntax_type BOOST_REGEX_CALL get_default_escape_syntax_type(char c); // is charT c a combining character? BOOST_REGEX_DECL bool BOOST_REGEX_CALL is_combining_implementation(uint_least16_t s); @@ -34,7 +60,7 @@ BOOST_REGEX_DECL bool BOOST_REGEX_CALL is_combining_implementation(uint_least16_ template inline bool is_combining(charT c) { - return (c < 0) ? false : ((c > (std::numeric_limits::max)()) ? false : is_combining_implementation(static_cast(c))); + return (c < static_cast(0)) ? false : ((c > static_cast((std::numeric_limits::max)())) ? false : is_combining_implementation(static_cast(c))); } template <> inline bool is_combining(char) @@ -79,7 +105,7 @@ inline bool is_combining(wchar_t c) template inline bool is_separator(charT c) { - return BOOST_REGEX_MAKE_BOOL((c == '\n') || (c == '\r') || (static_cast(c) == 0x2028) || (static_cast(c) == 0x2029)); + return BOOST_REGEX_MAKE_BOOL((c == static_cast('\n')) || (c == static_cast('\r')) || (static_cast(c) == 0x2028) || (static_cast(c) == 0x2029)); } template <> inline bool is_separator(char c) @@ -163,31 +189,82 @@ int get_default_class_id(const charT* p1, const charT* p2) return -1; } -#if 0 // -// parse_value: -// covert a character sequence into a value, return -1 if no digits found: +// helper functions: // -template -int parse_value(const charT*& p1, const charT* p2, const traits& traits_inst, int radix = 10) +template +std::ptrdiff_t global_length(const charT* p) { - return traits_inst.toi(p1, p2, radix); -#if 0 - int value = 0; - if(traits_inst.value(*p1) < 0) - return -1; - while(p1 != p2) + std::ptrdiff_t n = 0; + while(*p) { - int v2 = traits_inst.value(*p1); - if(v2 < 0) break; - value *= radix; - value += v2; - ++p1; + ++p; + ++n; } - return value; -#endif + 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 BOOST_REGEX_CALL global_lower(charT c) +{ + return c; +} +template +inline charT BOOST_REGEX_CALL 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 > f) return -1; + if(c >= a) return 10 + (c - a); + if(c > F) return -1; + if(c >= A) return 10 + (c - A); + if(c > nine) return -1; + if(c >= zero) return c - zero; + return -1; +} +template +int global_toi(const charT*& p1, const charT* p2, int radix, const traits& t) +{ + int next_value = t.value(*p1, radix); + if((p1 == p2) || (next_value < 0) || (next_value >= radix)) + return -1; + int result = 0; + while(p1 != p2) + { + next_value = t.value(*p1, radix); + if((next_value < 0) || (next_value >= radix)) + break; + result *= radix; + result += next_value; + ++p1; + } + return result; +} } // re_detail } // boost diff --git a/include/boost/regex/v4/regex_workaround.hpp b/include/boost/regex/v4/regex_workaround.hpp index bb3c7223..41be928c 100644 --- a/include/boost/regex/v4/regex_workaround.hpp +++ b/include/boost/regex/v4/regex_workaround.hpp @@ -78,6 +78,8 @@ namespace std{ using ::ptrdiff_t; using ::size_t; using ::abs; + using ::memset; + using ::memcpy; } #endif diff --git a/include/boost/regex/v4/sub_match.hpp b/include/boost/regex/v4/sub_match.hpp index 2529f1d9..2160d8da 100644 --- a/include/boost/regex/v4/sub_match.hpp +++ b/include/boost/regex/v4/sub_match.hpp @@ -42,11 +42,18 @@ struct sub_match : public std::pair sub_match() : std::pair(), matched(false) {} sub_match(BidiIterator i) : std::pair(i, i), matched(false) {} - +#if !defined(BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS) && !BOOST_WORKAROUND(BOOST_MSVC, < 1310) + template + operator std::basic_string ()const + { + return std::basic_string(first, second); + } +#else operator std::basic_string ()const { return str(); } +#endif difference_type BOOST_REGEX_CALL length()const { difference_type n = ::boost::re_detail::distance((BidiIterator)this->first, (BidiIterator)this->second); @@ -71,6 +78,14 @@ struct sub_match : public std::pair return static_cast(matched) - static_cast(s.matched); return str().compare(s.str()); } + int compare(const std::basic_string& s)const + { + return str().compare(s); + } + int compare(const value_type* p)const + { + return str().compare(p); + } bool operator==(const sub_match& that)const { return compare(that) == 0; } diff --git a/include/boost/regex/v4/w32_regex_traits.hpp b/include/boost/regex/v4/w32_regex_traits.hpp new file mode 100644 index 00000000..6f692eca --- /dev/null +++ b/include/boost/regex/v4/w32_regex_traits.hpp @@ -0,0 +1,654 @@ +/* + * + * 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.hpp + * VERSION see + * DESCRIPTION: Declares regular expression traits class w32_regex_traits. + */ + +#ifndef BOOST_W32_REGEX_TRAITS_HPP_INCLUDED +#define BOOST_W32_REGEX_TRAITS_HPP_INCLUDED + +#ifndef BOOST_REGEX_TRAITS_DEFAULTS_HPP_INCLUDED +#include +#endif +#ifdef BOOST_HAS_THREADS +#include +#endif +#ifndef BOOST_REGEX_PRIMARY_TRANSFORM +#include +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4786) +#endif + +namespace boost{ + +// +// forward declaration is needed by some compilers: +// +template +class w32_regex_traits; + +namespace re_detail{ + +// +// start by typedeffing the types we'll need: +// +typedef ::boost::uint32_t lcid_type; // placeholder for LCID. +typedef ::boost::shared_ptr cat_type; // placeholder for dll HANDLE. + +// +// then add wrappers around the actual Win32 API's (ie implementation hiding): +// +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); +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_lower(wchar_t, lcid_type); +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(char, lcid_type); +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is_upper(wchar_t, lcid_type); +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); +BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_cat_get(const cat_type& cat, lcid_type id, int i, const std::wstring& def); +BOOST_REGEX_DECL std::string BOOST_REGEX_CALL w32_transform(lcid_type id, const char* p1, const char* p2); +BOOST_REGEX_DECL std::wstring BOOST_REGEX_CALL w32_transform(lcid_type id, const wchar_t* p1, const wchar_t* p2); +BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_tolower(char c, lcid_type); +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_tolower(wchar_t c, lcid_type); +BOOST_REGEX_DECL char BOOST_REGEX_CALL w32_toupper(char c, lcid_type); +BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL w32_toupper(wchar_t c, lcid_type); +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, char c); +BOOST_REGEX_DECL bool BOOST_REGEX_CALL w32_is(lcid_type, boost::uint32_t mask, wchar_t c); +// +// class w32_regex_traits_base: +// acts as a container for locale and the facets we are using. +// +template +struct w32_regex_traits_base +{ + w32_regex_traits_base(lcid_type l) + { imbue(l); } + lcid_type imbue(lcid_type l); + + lcid_type m_locale; +}; + +template +inline lcid_type w32_regex_traits_base::imbue(lcid_type l) +{ + lcid_type result(m_locale); + m_locale = l; + return result; +} + +// +// class w32_regex_traits_char_layer: +// implements methods that require specialisation for narrow characters: +// +template +class w32_regex_traits_char_layer : public w32_regex_traits_base +{ + typedef std::basic_string string_type; + typedef std::map map_type; + typedef typename map_type::const_iterator map_iterator_type; +public: + w32_regex_traits_char_layer(const lcid_type l); + + regex_constants::syntax_type syntax_type(charT c)const + { + map_iterator_type i = m_char_map.find(c); + return ((i == m_char_map.end()) ? 0 : i->second); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + map_iterator_type i = m_char_map.find(c); + if(i == m_char_map.end()) + { + if(::boost::re_detail::w32_is_lower(c, this->m_locale)) return regex_constants::escape_type_class; + if(::boost::re_detail::w32_is_upper(c, this->m_locale)) return regex_constants::escape_type_not_class; + return 0; + } + return i->second; + } + +private: + string_type get_default_message(regex_constants::syntax_type); + // TODO: use a hash table when available! + map_type m_char_map; +}; + +template +w32_regex_traits_char_layer::w32_regex_traits_char_layer(::boost::re_detail::lcid_type l) + : w32_regex_traits_base(l) +{ + // we need to start by initialising our syntax map so we know which + // character is used for which purpose: + 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, m_locale, i, get_default_message(i)); + for(typename string_type::size_type j = 0; j < mss.size(); ++j) + { + m_char_map[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; + } + } + } +} + +template +typename w32_regex_traits_char_layer::string_type + w32_regex_traits_char_layer::get_default_message(regex_constants::syntax_type i) +{ + const char* ptr = get_default_syntax(i); + string_type result; + while(ptr && *ptr) + { + result.append(1, static_cast(*ptr)); + ++ptr; + } + return result; +} + +// +// specialised version for narrow characters: +// +template <> +class BOOST_REGEX_DECL w32_regex_traits_char_layer : public w32_regex_traits_base +{ + typedef std::string string_type; +public: + w32_regex_traits_char_layer(::boost::re_detail::lcid_type l) + : w32_regex_traits_base(l) + { + init(); + } + + regex_constants::syntax_type syntax_type(char c)const + { + return m_char_map[static_cast(c)]; + } + regex_constants::escape_syntax_type escape_syntax_type(char c) const + { + return m_char_map[static_cast(c)]; + } + +private: + regex_constants::syntax_type m_char_map[1u << CHAR_BIT]; + void init(); +}; + +// +// class w32_regex_traits_implementation: +// provides pimpl implementation for w32_regex_traits. +// +template +class w32_regex_traits_implementation : public w32_regex_traits_char_layer +{ +public: + typedef typename w32_regex_traits::char_class_type char_class_type; + BOOST_STATIC_CONSTANT(char_class_type, mask_word = 0x0400); // must be C1_DEFINED << 1 + BOOST_STATIC_CONSTANT(char_class_type, mask_unicode = 0x0800); // must be C1_DEFINED << 2 + BOOST_STATIC_CONSTANT(char_class_type, mask_base = 0x3ff); // all the masks used by the CT_CTYPE1 group + + typedef std::basic_string string_type; + typedef charT char_type; + w32_regex_traits_implementation(::boost::re_detail::lcid_type l); + std::string error_string(regex_constants::error_type n) const + { + if(!m_error_strings.empty()) + { + std::map::const_iterator p = m_error_strings.find(n); + return (p == m_error_strings.end()) ? std::string(get_default_error_string(n)) : p->second; + } + return get_default_error_string(n); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + char_class_type result = lookup_classname_imp(p1, p2); + if(result == 0) + { + typedef typename string_type::size_type size_type; + string_type temp(p1, p2); + for(size_type i = 0; i < temp.size(); ++i) + temp[i] = ::boost::re_detail::w32_tolower(temp[i], this->m_locale); + result = lookup_classname_imp(&*temp.begin(), &*temp.begin() + temp.size()); + } + return result; + } + string_type lookup_collatename(const charT* p1, const charT* p2) const; + string_type transform_primary(const charT* p1, const charT* p2) const; + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::re_detail::w32_transform(this->m_locale, p1, p2); + } +private: + std::map m_error_strings; // error messages indexed by numberic ID + std::map m_custom_class_names; // character class names + std::map m_custom_collate_names; // collating element names + unsigned m_collate_type; // the form of the collation string + charT m_collate_delim; // the collation group delimiter + // + // helpers: + // + char_class_type lookup_classname_imp(const charT* p1, const charT* p2) const; +}; + +template +typename w32_regex_traits_implementation::string_type + w32_regex_traits_implementation::transform_primary(const charT* p1, const charT* p2) const +{ + string_type result; + // + // What we do here depends upon the format of the sort key returned by + // sort key returned by this->transform: + // + switch(m_collate_type) + { + case sort_C: + case sort_unknown: + // the best we can do is translate to lower case, then get a regular sort key: + { + result.assign(p1, p2); + typedef typename string_type::size_type size_type; + for(size_type i = 0; i < result.size(); ++i) + result[i] = ::boost::re_detail::w32_tolower(result[i], this->m_locale); + result = this->transform(&*result.begin(), &*result.begin() + result.size()); + break; + } + case sort_fixed: + { + // get a regular sort key, and then truncate it: + result.assign(this->transform(p1, p2)); + result.erase(this->m_collate_delim); + break; + } + case sort_delim: + // get a regular sort key, and then truncate everything after the delim: + result.assign(this->transform(p1, p2)); + std::size_t i; + for(i = 0; i < result.size(); ++i) + { + if(result[i] == m_collate_delim) + break; + } + result.erase(i); + break; + } + return result; +} + +template +typename w32_regex_traits_implementation::string_type + w32_regex_traits_implementation::lookup_collatename(const charT* p1, const charT* p2) const +{ + typedef typename std::map::const_iterator iter_type; + if(m_custom_collate_names.size()) + { + iter_type pos = m_custom_collate_names.find(string_type(p1, p2)); + if(pos != m_custom_collate_names.end()) + return pos->second; + } +#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 = 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(); +} + +template +w32_regex_traits_implementation::w32_regex_traits_implementation(::boost::re_detail::lcid_type l) +: w32_regex_traits_char_layer(l) +{ + 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) + { + // + // Error messages: + // + for(boost::regex_constants::error_type i = static_cast(0); + i <= boost::regex_constants::error_unknown; + i = static_cast(i + 1)) + { + const char* p = get_default_error_string(i); + string_type default_message; + while(*p) + { + default_message.append(1, static_cast(*p)); + ++p; + } + string_type s = ::boost::re_detail::w32_cat_get(cat, this->m_locale, i+200, default_message); + std::string result; + for(std::string::size_type j = 0; j < s.size(); ++j) + { + result.append(1, static_cast(s[j])); + } + m_error_strings[i] = result; + } + // + // Custom class names: + // + static const char_class_type masks[] = + { + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + 0x0080u, // C1_XDIGIT + 0x0040u, // C1_BLANK + w32_regex_traits_implementation::mask_word, + w32_regex_traits_implementation::mask_unicode, + }; + static const string_type null_string; + for(unsigned int j = 0; j <= 13; ++j) + { + string_type s(::boost::re_detail::w32_cat_get(cat, this->m_locale, j+300, null_string)); + if(s.size()) + this->m_custom_class_names[s] = masks[j]; + } + } + // + // get the collation format used by m_pcollate: + // + m_collate_type = re_detail::find_sort_syntax(this, &m_collate_delim); +} + +template +typename w32_regex_traits_implementation::char_class_type + w32_regex_traits_implementation::lookup_classname_imp(const charT* p1, const charT* p2) const +{ + static const char_class_type masks[] = + { + 0, + 0x0104u, // C1_ALPHA | C1_DIGIT + 0x0100u, // C1_ALPHA + 0x0040u, // C1_BLANK + 0x0020u, // C1_CNTRL + 0x0004u, // C1_DIGIT + 0x0004u, // C1_DIGIT + (~(0x0020u|0x0008u|0x0040) & 0x01ffu) | 0x0400u, // not C1_CNTRL or C1_SPACE or C1_BLANK + 0x0002u, // C1_LOWER + 0x0002u, // C1_LOWER + (~0x0020u & 0x01ffu) | 0x0400, // not C1_CNTRL + 0x0010u, // C1_PUNCT + 0x0008u, // C1_SPACE + 0x0008u, // C1_SPACE + 0x0001u, // C1_UPPER + w32_regex_traits_implementation::mask_unicode, + 0x0001u, // C1_UPPER + 0x0104u | w32_regex_traits_implementation::mask_word, + 0x0104u | w32_regex_traits_implementation::mask_word, + 0x0080u, // C1_XDIGIT + }; + if(m_custom_class_names.size()) + { + typedef typename std::map, char_class_type>::const_iterator map_iter; + map_iter pos = m_custom_class_names.find(string_type(p1, p2)); + if(pos != m_custom_class_names.end()) + return pos->second; + } + std::size_t id = 1 + re_detail::get_default_class_id(p1, p2); + assert(id < sizeof(masks) / sizeof(masks[0])); + return masks[id]; +} + + +template +boost::shared_ptr > create_w32_regex_traits(::boost::re_detail::lcid_type l BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(charT)) +{ + // TODO: create a cache for previously constructed objects. + return boost::shared_ptr >(new w32_regex_traits_implementation(l)); +} + +} // re_detail + +template +class w32_regex_traits +{ +private: + typedef std::ctype ctype_type; +public: + typedef charT char_type; + typedef std::size_t size_type; + typedef std::basic_string string_type; + typedef ::boost::re_detail::lcid_type locale_type; + typedef boost::uint_least32_t char_class_type; + + struct boost_extensions_tag{}; + + w32_regex_traits() + : m_pimpl(re_detail::create_w32_regex_traits(::boost::re_detail::w32_get_default_locale())) + { } + static size_type length(const char_type* p) + { + return std::char_traits::length(p); + } + regex_constants::syntax_type syntax_type(charT c)const + { + return m_pimpl->syntax_type(c); + } + regex_constants::escape_syntax_type escape_syntax_type(charT c) const + { + return m_pimpl->escape_syntax_type(c); + } + charT translate(charT c) const + { + return c; + } + charT translate_nocase(charT c) const + { + return ::boost::re_detail::w32_tolower(c, this->m_pimpl->m_locale); + } + charT translate(charT c, bool icase) const + { + return icase ? ::boost::re_detail::w32_tolower(c, this->m_pimpl->m_locale) : c; + } + charT tolower(charT c) const + { + return ::boost::re_detail::w32_tolower(c, this->m_pimpl->m_locale); + } + charT toupper(charT c) const + { + return ::boost::re_detail::w32_toupper(c, this->m_pimpl->m_locale); + } + string_type transform(const charT* p1, const charT* p2) const + { + return ::boost::re_detail::w32_transform(this->m_pimpl->m_locale, p1, p2); + } + string_type transform_primary(const charT* p1, const charT* p2) const + { + return m_pimpl->transform_primary(p1, p2); + } + char_class_type lookup_classname(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_classname(p1, p2); + } + string_type lookup_collatename(const charT* p1, const charT* p2) const + { + return m_pimpl->lookup_collatename(p1, p2); + } + bool isctype(charT c, char_class_type f) const + { + if((f & re_detail::w32_regex_traits_implementation::mask_base) + && (::boost::re_detail::w32_is(this->m_pimpl->m_locale, f & re_detail::w32_regex_traits_implementation::mask_base, c))) + return true; + else if((f & re_detail::w32_regex_traits_implementation::mask_unicode) && re_detail::is_extended(c)) + return true; + else if((f & re_detail::w32_regex_traits_implementation::mask_word) && (c == '_')) + return true; + return false; + } + int toi(const charT*& p1, const charT* p2, int radix)const + { + return ::boost::re_detail::global_toi(p1, p2, radix, *this); + } + int value(charT c, int radix)const + { + return ::boost::re_detail::global_value(c); + } + locale_type imbue(locale_type l) + { + ::boost::re_detail::lcid_type result(getloc()); + m_pimpl = re_detail::create_w32_regex_traits(l); + return result; + } + locale_type getloc()const + { + return m_pimpl->m_locale; + } + std::string error_string(regex_constants::error_type n) const + { + return m_pimpl->error_string(n); + } + + // + // extension: + // set the name of the message catalog in use (defaults to "boost_regex"). + // + static std::string catalog_name(const std::string& name); + static std::string get_catalog_name(); + +private: + boost::shared_ptr > m_pimpl; + // + // catalog name handler: + // + static std::string& get_catalog_name_inst(); + +#ifdef BOOST_HAS_THREADS + static static_mutex& get_mutex_inst(); +#endif +}; + +template +std::string w32_regex_traits::catalog_name(const std::string& name) +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + get_catalog_name_inst() = name; + return result; +} + +template +std::string& w32_regex_traits::get_catalog_name_inst() +{ + static std::string s_name; + return s_name; +} + +template +std::string w32_regex_traits::get_catalog_name() +{ +#ifdef BOOST_HAS_THREADS + static_mutex::scoped_lock lk(get_mutex_inst()); +#endif + std::string result(get_catalog_name_inst()); + return result; +} + +#ifdef BOOST_HAS_THREADS +template +static_mutex& w32_regex_traits::get_mutex_inst() +{ + static static_mutex s_mutex = BOOST_STATIC_MUTEX_INIT; + return s_mutex; +} +#endif + + +} // boost + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif diff --git a/src/cpp_regex_traits.cpp b/src/cpp_regex_traits.cpp index be8ce1b6..4faf7f8c 100644 --- a/src/cpp_regex_traits.cpp +++ b/src/cpp_regex_traits.cpp @@ -19,6 +19,12 @@ #define BOOST_REGEX_SOURCE #include +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std{ + using ::memset; +} +#endif + namespace boost{ namespace re_detail{ void cpp_regex_traits_char_layer::init() diff --git a/src/cregex.cpp b/src/cregex.cpp index 1a4b3e56..693906eb 100644 --- a/src/cregex.cpp +++ b/src/cregex.cpp @@ -35,7 +35,7 @@ typedef boost::match_flag_type match_flag_type; #if defined(BOOST_NO_STDC_NAMESPACE) namespace std{ - using ::sprintf; + using ::sprintf; using ::strcpy; using ::strcat; } #endif diff --git a/src/fileiter.cpp b/src/fileiter.cpp index cd64d644..2ad4c121 100644 --- a/src/fileiter.cpp +++ b/src/fileiter.cpp @@ -39,6 +39,11 @@ namespace std{ using ::fopen; using ::fclose; using ::FILE; + using ::strcpy; + using ::strcpy; + using ::strcat; + using ::strcmp; + using ::strlen; } #endif diff --git a/src/posix_api.cpp b/src/posix_api.cpp index dc9bd4b3..7143f576 100644 --- a/src/posix_api.cpp +++ b/src/posix_api.cpp @@ -25,6 +25,8 @@ #if defined(BOOST_NO_STDC_NAMESPACE) namespace std{ using ::sprintf; + using ::strcpy; + using ::strcmp; } #endif @@ -104,9 +106,9 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompA(regex_tA* expression, const char result = static_cast(expression->guts)->error_code(); #ifndef BOOST_NO_EXCEPTIONS } - catch(const boost::bad_expression& be) + catch(const boost::regex_error& be) { - result = be.errorno(); + result = be.code(); } catch(...) { @@ -158,11 +160,10 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorA(int code, const regex_tA* { std::string p; if((e) && (e->re_magic == magic_value)) - p = static_cast(e->guts)->get_traits().error_string(code); + p = static_cast(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code)); else { - boost::regex_traits t; - p = t.error_string(code); + p = re_detail::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code)); } std::size_t len = p.size(); if(len < buf_size) diff --git a/src/regex.cpp b/src/regex.cpp index 7bc6ad46..2a5b2d70 100644 --- a/src/regex.cpp +++ b/src/regex.cpp @@ -50,8 +50,11 @@ namespace boost{ // that dll builds contain the Virtual table for these // types - this ensures that exceptions can be thrown // from the dll and caught in an exe. -bad_pattern::~bad_pattern() throw() {} -bad_expression::~bad_expression() throw() {} +regex_error::regex_error(const std::string& s, regex_constants::error_type err, std::ptrdiff_t pos) + : std::runtime_error(s), m_error_code(err), m_position(pos) {} +regex_error::regex_error(regex_constants::error_type err) + : std::runtime_error(::boost::re_detail::get_default_error_string(err)), m_error_code(err), m_position(0) {} +regex_error::~regex_error() throw() {} namespace re_detail{ diff --git a/src/regex_traits_defaults.cpp b/src/regex_traits_defaults.cpp index 9d3aec6a..522f6a57 100644 --- a/src/regex_traits_defaults.cpp +++ b/src/regex_traits_defaults.cpp @@ -277,5 +277,396 @@ BOOST_REGEX_DECL wchar_t BOOST_REGEX_CALL global_upper(wchar_t c) } #endif +BOOST_REGEX_DECL regex_constants::escape_syntax_type BOOST_REGEX_CALL get_default_escape_syntax_type(char c) +{ + // + // char_syntax determines how the compiler treats a given character + // in a regular expression. + // + static regex_constants::escape_syntax_type char_syntax[] = { + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /* */ // 32 + regex_constants::escape_type_identity, /*!*/ + regex_constants::escape_type_identity, /*"*/ + regex_constants::escape_type_identity, /*#*/ + regex_constants::escape_type_identity, /*$*/ + regex_constants::escape_type_identity, /*%*/ + regex_constants::escape_type_identity, /*&*/ + regex_constants::escape_type_end_buffer, /*'*/ + regex_constants::syntax_open_mark, /*(*/ + regex_constants::syntax_close_mark, /*)*/ + regex_constants::escape_type_identity, /***/ + regex_constants::syntax_plus, /*+*/ + regex_constants::escape_type_identity, /*,*/ + regex_constants::escape_type_identity, /*-*/ + regex_constants::escape_type_identity, /*.*/ + regex_constants::escape_type_identity, /*/*/ + regex_constants::escape_type_decimal, /*0*/ + regex_constants::escape_type_backref, /*1*/ + regex_constants::escape_type_backref, /*2*/ + regex_constants::escape_type_backref, /*3*/ + regex_constants::escape_type_backref, /*4*/ + regex_constants::escape_type_backref, /*5*/ + regex_constants::escape_type_backref, /*6*/ + regex_constants::escape_type_backref, /*7*/ + regex_constants::escape_type_backref, /*8*/ + regex_constants::escape_type_backref, /*9*/ + regex_constants::escape_type_identity, /*:*/ + regex_constants::escape_type_identity, /*;*/ + regex_constants::escape_type_left_word, /*<*/ + regex_constants::escape_type_identity, /*=*/ + regex_constants::escape_type_right_word, /*>*/ + regex_constants::syntax_question, /*?*/ + regex_constants::escape_type_identity, /*@*/ + regex_constants::escape_type_start_buffer, /*A*/ + regex_constants::escape_type_not_word_assert, /*B*/ + regex_constants::escape_type_C, /*C*/ + regex_constants::escape_type_not_class, /*D*/ + regex_constants::escape_type_E, /*E*/ + regex_constants::escape_type_not_class, /*F*/ + regex_constants::escape_type_G, /*G*/ + regex_constants::escape_type_not_class, /*H*/ + regex_constants::escape_type_not_class, /*I*/ + regex_constants::escape_type_not_class, /*J*/ + regex_constants::escape_type_not_class, /*K*/ + regex_constants::escape_type_not_class, /*L*/ + regex_constants::escape_type_not_class, /*M*/ + regex_constants::escape_type_not_class, /*N*/ + regex_constants::escape_type_not_class, /*O*/ + regex_constants::escape_type_not_class, /*P*/ + regex_constants::escape_type_Q, /*Q*/ + regex_constants::escape_type_not_class, /*R*/ + regex_constants::escape_type_not_class, /*S*/ + regex_constants::escape_type_not_class, /*T*/ + regex_constants::escape_type_not_class, /*U*/ + regex_constants::escape_type_not_class, /*V*/ + regex_constants::escape_type_not_class, /*W*/ + regex_constants::escape_type_X, /*X*/ + regex_constants::escape_type_not_class, /*Y*/ + regex_constants::escape_type_Z, /*Z*/ + regex_constants::escape_type_identity, /*[*/ + regex_constants::escape_type_identity, /*\*/ + regex_constants::escape_type_identity, /*]*/ + regex_constants::escape_type_identity, /*^*/ + regex_constants::escape_type_identity, /*_*/ + regex_constants::escape_type_start_buffer, /*`*/ + regex_constants::escape_type_control_a, /*a*/ + regex_constants::escape_type_word_assert, /*b*/ + regex_constants::escape_type_ascii_control, /*c*/ + regex_constants::escape_type_class, /*d*/ + regex_constants::escape_type_e, /*e*/ + regex_constants::escape_type_control_f, /*f*/ + regex_constants::escape_type_class, /*g*/ + regex_constants::escape_type_class, /*h*/ + regex_constants::escape_type_class, /*i*/ + regex_constants::escape_type_class, /*j*/ + regex_constants::escape_type_class, /*k*/ + regex_constants::escape_type_class, /*l*/ + regex_constants::escape_type_class, /*m*/ + regex_constants::escape_type_control_n, /*n*/ + regex_constants::escape_type_class, /*o*/ + regex_constants::escape_type_class, /*p*/ + regex_constants::escape_type_class, /*q*/ + regex_constants::escape_type_control_r, /*r*/ + regex_constants::escape_type_class, /*s*/ + regex_constants::escape_type_control_t, /*t*/ + regex_constants::escape_type_class, /*u*/ + regex_constants::escape_type_control_v, /*v*/ + regex_constants::escape_type_class, /*w*/ + regex_constants::escape_type_hex, /*x*/ + regex_constants::escape_type_class, /*y*/ + regex_constants::escape_type_end_buffer, /*z*/ + regex_constants::syntax_open_brace, /*{*/ + regex_constants::syntax_or, /*|*/ + regex_constants::syntax_close_brace, /*}*/ + regex_constants::escape_type_identity, /*~*/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + regex_constants::escape_type_identity, /**/ + }; + + return char_syntax[(unsigned char)c]; +} + +BOOST_REGEX_DECL regex_constants::syntax_type BOOST_REGEX_CALL get_default_syntax_type(char c) +{ + // + // char_syntax determines how the compiler treats a given character + // in a regular expression. + // + static regex_constants::syntax_type char_syntax[] = { + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_newline, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /* */ // 32 + regex_constants::syntax_not, /*!*/ + regex_constants::syntax_char, /*"*/ + regex_constants::syntax_hash, /*#*/ + regex_constants::syntax_dollar, /*$*/ + regex_constants::syntax_char, /*%*/ + regex_constants::syntax_char, /*&*/ + regex_constants::syntax_char, /*'*/ + regex_constants::syntax_open_mark, /*(*/ + regex_constants::syntax_close_mark, /*)*/ + regex_constants::syntax_star, /***/ + regex_constants::syntax_plus, /*+*/ + regex_constants::syntax_comma, /*,*/ + regex_constants::syntax_dash, /*-*/ + regex_constants::syntax_dot, /*.*/ + regex_constants::syntax_char, /*/*/ + regex_constants::syntax_digit, /*0*/ + regex_constants::syntax_digit, /*1*/ + regex_constants::syntax_digit, /*2*/ + regex_constants::syntax_digit, /*3*/ + regex_constants::syntax_digit, /*4*/ + regex_constants::syntax_digit, /*5*/ + regex_constants::syntax_digit, /*6*/ + regex_constants::syntax_digit, /*7*/ + regex_constants::syntax_digit, /*8*/ + regex_constants::syntax_digit, /*9*/ + regex_constants::syntax_colon, /*:*/ + regex_constants::syntax_char, /*;*/ + regex_constants::escape_type_left_word, /*<*/ + regex_constants::syntax_equal, /*=*/ + regex_constants::escape_type_right_word, /*>*/ + regex_constants::syntax_question, /*?*/ + regex_constants::syntax_char, /*@*/ + regex_constants::syntax_char, /*A*/ + regex_constants::syntax_char, /*B*/ + regex_constants::syntax_char, /*C*/ + regex_constants::syntax_char, /*D*/ + regex_constants::syntax_char, /*E*/ + regex_constants::syntax_char, /*F*/ + regex_constants::syntax_char, /*G*/ + regex_constants::syntax_char, /*H*/ + regex_constants::syntax_char, /*I*/ + regex_constants::syntax_char, /*J*/ + regex_constants::syntax_char, /*K*/ + regex_constants::syntax_char, /*L*/ + regex_constants::syntax_char, /*M*/ + regex_constants::syntax_char, /*N*/ + regex_constants::syntax_char, /*O*/ + regex_constants::syntax_char, /*P*/ + regex_constants::syntax_char, /*Q*/ + regex_constants::syntax_char, /*R*/ + regex_constants::syntax_char, /*S*/ + regex_constants::syntax_char, /*T*/ + regex_constants::syntax_char, /*U*/ + regex_constants::syntax_char, /*V*/ + regex_constants::syntax_char, /*W*/ + regex_constants::syntax_char, /*X*/ + regex_constants::syntax_char, /*Y*/ + regex_constants::syntax_char, /*Z*/ + regex_constants::syntax_open_set, /*[*/ + regex_constants::syntax_escape, /*\*/ + regex_constants::syntax_close_set, /*]*/ + regex_constants::syntax_caret, /*^*/ + regex_constants::syntax_char, /*_*/ + regex_constants::syntax_char, /*`*/ + regex_constants::syntax_char, /*a*/ + regex_constants::syntax_char, /*b*/ + regex_constants::syntax_char, /*c*/ + regex_constants::syntax_char, /*d*/ + regex_constants::syntax_char, /*e*/ + regex_constants::syntax_char, /*f*/ + regex_constants::syntax_char, /*g*/ + regex_constants::syntax_char, /*h*/ + regex_constants::syntax_char, /*i*/ + regex_constants::syntax_char, /*j*/ + regex_constants::syntax_char, /*k*/ + regex_constants::syntax_char, /*l*/ + regex_constants::syntax_char, /*m*/ + regex_constants::syntax_char, /*n*/ + regex_constants::syntax_char, /*o*/ + regex_constants::syntax_char, /*p*/ + regex_constants::syntax_char, /*q*/ + regex_constants::syntax_char, /*r*/ + regex_constants::syntax_char, /*s*/ + regex_constants::syntax_char, /*t*/ + regex_constants::syntax_char, /*u*/ + regex_constants::syntax_char, /*v*/ + regex_constants::syntax_char, /*w*/ + regex_constants::syntax_char, /*x*/ + regex_constants::syntax_char, /*y*/ + regex_constants::syntax_char, /*z*/ + regex_constants::syntax_open_brace, /*{*/ + regex_constants::syntax_or, /*|*/ + regex_constants::syntax_close_brace, /*}*/ + regex_constants::syntax_char, /*~*/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + regex_constants::syntax_char, /**/ + }; + + return char_syntax[(unsigned char)c]; +} + + } // re_detail } // boost diff --git a/src/wide_posix_api.cpp b/src/wide_posix_api.cpp index d21ee2c2..5928076a 100644 --- a/src/wide_posix_api.cpp +++ b/src/wide_posix_api.cpp @@ -114,9 +114,9 @@ BOOST_REGEX_DECL int BOOST_REGEX_CCALL regcompW(regex_tW* expression, const wcha result = static_cast(expression->guts)->error_code(); #ifndef BOOST_NO_EXCEPTIONS } - catch(const boost::bad_expression& be) + catch(const boost::regex_error& be) { - result = be.errorno(); + result = be.code(); } catch(...) { @@ -168,18 +168,19 @@ BOOST_REGEX_DECL regsize_t BOOST_REGEX_CCALL regerrorW(int code, const regex_tW* #endif if(code <= REG_E_UNKNOWN) { - regex_traits rt; - const regex_traits* pt = &rt; - if(e && (e->re_magic == wmagic_value)) - pt = &static_cast(e->guts)->get_traits(); - (void)pt; // warning suppression - std::string p = pt->error_string(code); - if(p.size() < buf_size) + std::string p; + if((e) && (e->re_magic == wmagic_value)) + p = static_cast(e->guts)->get_traits().error_string(static_cast< ::boost::regex_constants::error_type>(code)); + else { - std::copy(p.begin(), p.end(), buf); - buf[p.size()] = 0; + p = re_detail::get_default_error_string(static_cast< ::boost::regex_constants::error_type>(code)); } - return p.size() + 1; + std::size_t len = p.size(); + if(len < buf_size) + { + std::copy(p.c_str(), p.c_str() + p.size() + 1, buf); + } + return len + 1; } if(buf_size) *buf = 0; diff --git a/test/concepts/concept_check.cpp b/test/concepts/concept_check.cpp index 6cfc9c38..e90ceafb 100644 --- a/test/concepts/concept_check.cpp +++ b/test/concepts/concept_check.cpp @@ -9,84 +9,87 @@ * */ - -#include // for abort -#include - #if defined(BOOST_MSVC) // this lets us compile at warning level 4 without seeing concept-check related warnings # pragma warning(disable:4100) #endif - -#include -#include +#ifdef __BORLANDC__ +#pragma option -w-8019 -w-8004 -w-8008 +#endif +#include +#include #include -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std{ using ::abort; } -#endif +boost::re_detail::digraph get_next_set_literal(); int main() { // VC6 and VC7 can't cope with the iterator architypes, // don't bother testing as it doesn't work: -#if !BOOST_WORKAROUND(_MSC_VER, < 1310) - typedef boost::bidirectional_iterator_archetype iterator_type; - typedef boost::input_iterator_archetype input_iterator_type; - input_iterator_type i, j; -#if!defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__GNUC__, < 3) - boost::regex r(i, j); - r.assign(i, j); -#else - boost::regex r; -#endif - iterator_type a, b; - boost::detail::dummy_constructor dummy; - boost::output_iterator_archetype out(dummy); - std::string s; - boost::match_results what; - - boost::regex_match(a, b, r); - boost::regex_match(a, b, what, r); - boost::regex_search(a, b, r); - boost::regex_search(a, b, what, r); - out = boost::regex_replace(out, a, b, r, s, boost::match_default); - s = boost::regex_replace(s, r, s, boost::match_default); - - out = what.format(out, s, boost::format_default); - s = what.format(s, boost::format_default); - +#if !BOOST_WORKAROUND(_MSC_VER, < 1310) && !defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__) && !BOOST_WORKAROUND(__GNUC__, < 3) boost::function_requires< - boost::ForwardIteratorConcept< - boost::regex_iterator + boost::RegexTraitsConcept< + boost::regex_traits > >(); - // this fails with glibc++v2 : -#if !BOOST_WORKAROUND(__GNUC__, < 3) && !BOOST_WORKAROUND(BOOST_MSVC, <1300) boost::function_requires< - boost::ForwardIteratorConcept< - boost::regex_token_iterator + boost::BoostRegexConcept< + boost::basic_regex > + > + >(); +#ifndef BOOST_NO_WREGEX + boost::function_requires< + boost::BoostRegexConcept< + boost::basic_regex > + > + >(); +#endif + boost::function_requires< + boost::BoostRegexConcept< + boost::basic_regex > + > + >(); +#ifndef BOOST_NO_WREGEX + boost::function_requires< + boost::BoostRegexConcept< + boost::basic_regex > + > + >(); +#endif + boost::function_requires< + boost::RegexTraitsConcept< + boost::regex_traits + > + >(); + boost::function_requires< + boost::BoostRegexConcept< + boost::basic_regex > + > + >(); +#ifndef BOOST_NO_WREGEX + boost::function_requires< + boost::BoostRegexConcept< + boost::basic_regex > > >(); #endif - // - // verify basic_regex member functions: - // - const char* c_exp = "abc"; - r = c_exp; - r = r; - r = s; - if((r.mark_count()) || (0 == r.max_size()) || (r.empty()) || (0 == r.size()) || (r.begin() == r.end())) std::abort(); - r.assign(r); - r.assign(c_exp); - r.assign(c_exp, boost::regex::perl); - r.assign(c_exp, 1, boost::regex::perl); - r.assign(s); - r.assign(s, boost::regex::perl); - r.assign(c_exp, c_exp+1); - r.assign(c_exp, c_exp+1, boost::regex::perl); + // + // now test the regex_traits concepts: + // + typedef boost::basic_regex > regex_traits_tester_type1; + boost::function_requires< + boost::BoostRegexConcept< + regex_traits_tester_type1 + > + >(); + typedef boost::basic_regex > regex_traits_tester_type2; + boost::function_requires< + boost::BaseRegexConcept< + regex_traits_tester_type2 + > + >(); #endif return 0; } diff --git a/test/concepts/wide_concept_check.cpp b/test/concepts/wide_concept_check.cpp deleted file mode 100644 index 8b33c504..00000000 --- a/test/concepts/wide_concept_check.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * - * Copyright (c) 2003 - * 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) - * - */ - -#include -#include -#if defined(BOOST_MSVC) -// this lets us compile at warning level 4 without seeing concept-check related warnings -# pragma warning(disable:4100) -#endif -#include -#include - - -int main() -{ -#ifndef BOOST_NO_WREGEX - // VC6 and VC7 can't cope with the iterator architypes, - // don't bother testing as it doesn't work: -#if !BOOST_WORKAROUND(_MSC_VER, < 1310) - typedef boost::bidirectional_iterator_archetype iterator_type; - typedef boost::input_iterator_archetype input_iterator_type; - input_iterator_type i, j; -#if!defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(__IBMCPP__) - boost::wregex r(i, j); - r.assign(i, j); -#else - boost::wregex r; -#endif - iterator_type a, b; - boost::detail::dummy_constructor dummy; - boost::output_iterator_archetype out(dummy); - std::wstring s; - boost::match_results what; - - boost::regex_match(a, b, r); - boost::regex_match(a, b, what, r); - boost::regex_search(a, b, r); - boost::regex_search(a, b, what, r); - out = boost::regex_replace(out, a, b, r, s, boost::match_default); - s = boost::regex_replace(s, r, s, boost::match_default); - - out = what.format(out, s, boost::format_default); - s = what.format(s, boost::format_default); - - boost::function_requires< - boost::ForwardIteratorConcept< - boost::regex_iterator - > - >(); - // this fails with glibc++v2 : -#if !BOOST_WORKAROUND(__GNUC__, < 3) && !BOOST_WORKAROUND(BOOST_MSVC, <1300) - boost::function_requires< - boost::ForwardIteratorConcept< - boost::regex_token_iterator - > - >(); -#endif // GCC 2.x -#endif // MSVC 6 -#endif // BOOST_NO_WREGEX - return 0; -} - - diff --git a/test/regress/test.hpp b/test/regress/test.hpp index a45096c5..055e7f4d 100644 --- a/test/regress/test.hpp +++ b/test/regress/test.hpp @@ -15,8 +15,12 @@ template void test(const charT& c, const tagT& tag) { - boost::basic_regex e; - test(e, tag); + boost::basic_regex > e1; + test(e1, tag); + boost::basic_regex > e2; + test(e2, tag); + boost::basic_regex > e3; + test(e3, tag); // test old depecated code: test_deprecated(c, tag); } diff --git a/test/regress/test_deprecated.cpp b/test/regress/test_deprecated.cpp index c5b33735..f74fad1f 100644 --- a/test/regress/test_deprecated.cpp +++ b/test/regress/test_deprecated.cpp @@ -229,7 +229,7 @@ void test_deprecated(const char&, const test_invalid_regex_tag&) // OK try and compile the expression: boost::regex_tA re; - if(regcompA(&re, expression.c_str(), posix_options) == 0) + if(boost::regcompA(&re, expression.c_str(), posix_options) == 0) { boost::regfreeA(&re); BOOST_REGEX_TEST_ERROR("Expression : \"" << expression.c_str() << "\" unexpectedly compiled with the POSIX C API.", char); @@ -281,7 +281,7 @@ void test_deprecated(const wchar_t&, const test_invalid_regex_tag&) // OK try and compile the expression: boost::regex_tW re; - if(regcompW(&re, expression.c_str(), posix_options) == 0) + if(boost::regcompW(&re, expression.c_str(), posix_options) == 0) { boost::regfreeW(&re); BOOST_REGEX_TEST_ERROR("Expression : \"" << expression.c_str() << "\" unexpectedly compiled with the POSIX C API.", wchar_t); diff --git a/test/regress/test_regex_search.hpp b/test/regress/test_regex_search.hpp index 99d97276..f39f0ac8 100644 --- a/test/regress/test_regex_search.hpp +++ b/test/regress/test_regex_search.hpp @@ -87,7 +87,7 @@ template void test_regex_iterator(boost::basic_regex& r) { typedef typename std::basic_string::const_iterator const_iterator; - typedef boost::regex_iterator test_iterator; + typedef boost::regex_iterator test_iterator; const std::basic_string& search_text = test_info::search_text(); boost::regex_constants::match_flag_type opts = test_info::match_options(); const int* answer_table = test_info::answer_table();