| /* |
| * |
| * Copyright (c) 1998-2009 John Maddock |
| * Copyright 2008 Eric Niebler. |
| * |
| * Use, modification and distribution are subject to the |
| * Boost Software License, Version 1.0. (See accompanying file |
| * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| * |
| */ |
| |
| /* |
| * LOCATION: see http://www.boost.org for most recent version. |
| * FILE regex_format.hpp |
| * VERSION see <ndnboost/version.hpp> |
| * DESCRIPTION: Provides formatting output routines for search and replace |
| * operations. Note this is an internal header file included |
| * by regex.hpp, do not include on its own. |
| */ |
| |
| #ifndef NDNBOOST_REGEX_FORMAT_HPP |
| #define NDNBOOST_REGEX_FORMAT_HPP |
| |
| #include <ndnboost/type_traits/is_pointer.hpp> |
| #include <ndnboost/type_traits/is_function.hpp> |
| #include <ndnboost/type_traits/is_class.hpp> |
| #include <ndnboost/type_traits/is_same.hpp> |
| #include <ndnboost/type_traits/is_convertible.hpp> |
| #include <ndnboost/type_traits/remove_pointer.hpp> |
| #include <ndnboost/type_traits/remove_cv.hpp> |
| #include <ndnboost/mpl/if.hpp> |
| #include <ndnboost/mpl/and.hpp> |
| #include <ndnboost/mpl/not.hpp> |
| #ifndef NDNBOOST_NO_SFINAE |
| #include <ndnboost/mpl/has_xxx.hpp> |
| #endif |
| #include <ndnboost/ref.hpp> |
| |
| namespace ndnboost{ |
| |
| #ifdef NDNBOOST_MSVC |
| #pragma warning(push) |
| #pragma warning(disable: 4103) |
| #endif |
| #ifdef NDNBOOST_HAS_ABI_HEADERS |
| # include NDNBOOST_ABI_PREFIX |
| #endif |
| #ifdef NDNBOOST_MSVC |
| #pragma warning(pop) |
| #endif |
| |
| // |
| // Forward declaration: |
| // |
| template <class BidiIterator, class Allocator = NDNBOOST_DEDUCED_TYPENAME std::vector<sub_match<BidiIterator> >::allocator_type > |
| class match_results; |
| |
| namespace re_detail{ |
| |
| // |
| // struct trivial_format_traits: |
| // defines minimum localisation support for formatting |
| // in the case that the actual regex traits is unavailable. |
| // |
| template <class charT> |
| struct trivial_format_traits |
| { |
| typedef charT char_type; |
| |
| static std::ptrdiff_t length(const charT* p) |
| { |
| return global_length(p); |
| } |
| static charT tolower(charT c) |
| { |
| return ::ndnboost::re_detail::global_lower(c); |
| } |
| static charT toupper(charT c) |
| { |
| return ::ndnboost::re_detail::global_upper(c); |
| } |
| static int value(const charT c, int 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); |
| } |
| }; |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| class basic_regex_formatter |
| { |
| public: |
| typedef typename traits::char_type char_type; |
| basic_regex_formatter(OutputIterator o, const Results& r, const traits& t) |
| : m_traits(t), m_results(r), m_out(o), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {} |
| OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f); |
| OutputIterator format(ForwardIter p1, match_flag_type f) |
| { |
| return format(p1, p1 + m_traits.length(p1), f); |
| } |
| private: |
| typedef typename Results::value_type sub_match_type; |
| enum output_state |
| { |
| output_copy, |
| output_next_lower, |
| output_next_upper, |
| output_lower, |
| output_upper, |
| output_none |
| }; |
| |
| void put(char_type c); |
| void put(const sub_match_type& sub); |
| void format_all(); |
| void format_perl(); |
| void format_escape(); |
| void format_conditional(); |
| void format_until_scope_end(); |
| bool handle_perl_verb(bool have_brace); |
| |
| inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::false_&) |
| { |
| std::vector<char_type> v(i, j); |
| return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size()) |
| : this->m_results.named_subexpression(static_cast<const char_type*>(0), static_cast<const char_type*>(0)); |
| } |
| inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::true_&) |
| { |
| return this->m_results.named_subexpression(i, j); |
| } |
| inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j) |
| { |
| typedef typename ndnboost::is_convertible<ForwardIter, const char_type*>::type tag_type; |
| return get_named_sub(i, j, tag_type()); |
| } |
| inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::false_&) |
| { |
| std::vector<char_type> v(i, j); |
| return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size()) |
| : this->m_results.named_subexpression_index(static_cast<const char_type*>(0), static_cast<const char_type*>(0)); |
| } |
| inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::true_&) |
| { |
| return this->m_results.named_subexpression_index(i, j); |
| } |
| inline int get_named_sub_index(ForwardIter i, ForwardIter j) |
| { |
| typedef typename ndnboost::is_convertible<ForwardIter, const char_type*>::type tag_type; |
| return get_named_sub_index(i, j, tag_type()); |
| } |
| #ifdef NDNBOOST_MSVC |
| // msvc-8.0 issues a spurious warning on the call to std::advance here: |
| #pragma warning(push) |
| #pragma warning(disable:4244) |
| #endif |
| inline int toi(ForwardIter& i, ForwardIter j, int base, const ndnboost::mpl::false_&) |
| { |
| if(i != j) |
| { |
| std::vector<char_type> v(i, j); |
| const char_type* start = &v[0]; |
| const char_type* pos = start; |
| int r = m_traits.toi(pos, &v[0] + v.size(), base); |
| std::advance(i, pos - start); |
| return r; |
| } |
| return -1; |
| } |
| #ifdef NDNBOOST_MSVC |
| #pragma warning(pop) |
| #endif |
| inline int toi(ForwardIter& i, ForwardIter j, int base, const ndnboost::mpl::true_&) |
| { |
| return m_traits.toi(i, j, base); |
| } |
| inline int toi(ForwardIter& i, ForwardIter j, int base) |
| { |
| #if defined(_MSC_VER) && defined(__INTEL_COMPILER) && ((__INTEL_COMPILER == 9999) || (__INTEL_COMPILER == 1210)) |
| // Workaround for Intel support issue #656654. |
| // See also https://svn.boost.org/trac/boost/ticket/6359 |
| return toi(i, j, base, mpl::false_()); |
| #else |
| typedef typename ndnboost::is_convertible<ForwardIter, const char_type*&>::type tag_type; |
| return toi(i, j, base, tag_type()); |
| #endif |
| } |
| |
| const traits& m_traits; // the traits class for localised formatting operations |
| const Results& m_results; // the match_results being used. |
| OutputIterator m_out; // where to send output. |
| ForwardIter m_position; // format string, current position |
| ForwardIter m_end; // format string end |
| match_flag_type m_flags; // format flags to use |
| output_state m_state; // what to do with the next character |
| output_state m_restore_state; // what state to restore to. |
| bool m_have_conditional; // we are parsing a conditional |
| private: |
| basic_regex_formatter(const basic_regex_formatter&); |
| basic_regex_formatter& operator=(const basic_regex_formatter&); |
| }; |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format(ForwardIter p1, ForwardIter p2, match_flag_type f) |
| { |
| m_position = p1; |
| m_end = p2; |
| m_flags = f; |
| format_all(); |
| return m_out; |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all() |
| { |
| // over and over: |
| while(m_position != m_end) |
| { |
| switch(*m_position) |
| { |
| case '&': |
| if(m_flags & ::ndnboost::regex_constants::format_sed) |
| { |
| ++m_position; |
| put(m_results[0]); |
| break; |
| } |
| put(*m_position++); |
| break; |
| case '\\': |
| format_escape(); |
| break; |
| case '(': |
| if(m_flags & ndnboost::regex_constants::format_all) |
| { |
| ++m_position; |
| bool have_conditional = m_have_conditional; |
| m_have_conditional = false; |
| format_until_scope_end(); |
| m_have_conditional = have_conditional; |
| if(m_position == m_end) |
| return; |
| NDNBOOST_ASSERT(*m_position == static_cast<char_type>(')')); |
| ++m_position; // skip the closing ')' |
| break; |
| } |
| put(*m_position); |
| ++m_position; |
| break; |
| case ')': |
| if(m_flags & ndnboost::regex_constants::format_all) |
| { |
| return; |
| } |
| put(*m_position); |
| ++m_position; |
| break; |
| case ':': |
| if((m_flags & ndnboost::regex_constants::format_all) && m_have_conditional) |
| { |
| return; |
| } |
| put(*m_position); |
| ++m_position; |
| break; |
| case '?': |
| if(m_flags & ndnboost::regex_constants::format_all) |
| { |
| ++m_position; |
| format_conditional(); |
| break; |
| } |
| put(*m_position); |
| ++m_position; |
| break; |
| case '$': |
| if((m_flags & format_sed) == 0) |
| { |
| format_perl(); |
| break; |
| } |
| // not a special character: |
| NDNBOOST_FALLTHROUGH; |
| default: |
| put(*m_position); |
| ++m_position; |
| break; |
| } |
| } |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_perl() |
| { |
| // |
| // On entry *m_position points to a '$' character |
| // output the information that goes with it: |
| // |
| NDNBOOST_ASSERT(*m_position == '$'); |
| // |
| // see if this is a trailing '$': |
| // |
| if(++m_position == m_end) |
| { |
| --m_position; |
| put(*m_position); |
| ++m_position; |
| return; |
| } |
| // |
| // OK find out what kind it is: |
| // |
| bool have_brace = false; |
| ForwardIter save_position = m_position; |
| switch(*m_position) |
| { |
| case '&': |
| ++m_position; |
| put(this->m_results[0]); |
| break; |
| case '`': |
| ++m_position; |
| put(this->m_results.prefix()); |
| break; |
| case '\'': |
| ++m_position; |
| put(this->m_results.suffix()); |
| break; |
| case '$': |
| put(*m_position++); |
| break; |
| case '+': |
| if((++m_position != m_end) && (*m_position == '{')) |
| { |
| ForwardIter base = ++m_position; |
| while((m_position != m_end) && (*m_position != '}')) ++m_position; |
| if(m_position != m_end) |
| { |
| // Named sub-expression: |
| put(get_named_sub(base, m_position)); |
| ++m_position; |
| break; |
| } |
| else |
| { |
| m_position = --base; |
| } |
| } |
| put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]); |
| break; |
| case '{': |
| have_brace = true; |
| ++m_position; |
| NDNBOOST_FALLTHROUGH; |
| default: |
| // see if we have a number: |
| { |
| std::ptrdiff_t len = ::ndnboost::re_detail::distance(m_position, m_end); |
| //len = (std::min)(static_cast<std::ptrdiff_t>(2), len); |
| int v = this->toi(m_position, m_position + len, 10); |
| if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}')))) |
| { |
| // Look for a Perl-5.10 verb: |
| if(!handle_perl_verb(have_brace)) |
| { |
| // leave the $ as is, and carry on: |
| m_position = --save_position; |
| put(*m_position); |
| ++m_position; |
| } |
| break; |
| } |
| // otherwise output sub v: |
| put(this->m_results[v]); |
| if(have_brace) |
| ++m_position; |
| } |
| } |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| bool basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::handle_perl_verb(bool have_brace) |
| { |
| // |
| // We may have a capitalised string containing a Perl action: |
| // |
| static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' }; |
| static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' }; |
| static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' }; |
| static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' }; |
| static const char_type LAST_SUBMATCH_RESULT[] = { 'L', 'A', 'S', 'T', '_', 'S', 'U', 'B', 'M', 'A', 'T', 'C', 'H', '_', 'R', 'E', 'S', 'U', 'L', 'T' }; |
| static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' }; |
| |
| if(m_position == m_end) |
| return false; |
| if(have_brace && (*m_position == '^')) |
| ++m_position; |
| |
| std::ptrdiff_t max_len = m_end - m_position; |
| |
| if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH)) |
| { |
| m_position += 5; |
| if(have_brace) |
| { |
| if((m_position != m_end) && (*m_position == '}')) |
| ++m_position; |
| else |
| { |
| m_position -= 5; |
| return false; |
| } |
| } |
| put(this->m_results[0]); |
| return true; |
| } |
| if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH)) |
| { |
| m_position += 8; |
| if(have_brace) |
| { |
| if((m_position != m_end) && (*m_position == '}')) |
| ++m_position; |
| else |
| { |
| m_position -= 8; |
| return false; |
| } |
| } |
| put(this->m_results.prefix()); |
| return true; |
| } |
| if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH)) |
| { |
| m_position += 9; |
| if(have_brace) |
| { |
| if((m_position != m_end) && (*m_position == '}')) |
| ++m_position; |
| else |
| { |
| m_position -= 9; |
| return false; |
| } |
| } |
| put(this->m_results.suffix()); |
| return true; |
| } |
| if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH)) |
| { |
| m_position += 16; |
| if(have_brace) |
| { |
| if((m_position != m_end) && (*m_position == '}')) |
| ++m_position; |
| else |
| { |
| m_position -= 16; |
| return false; |
| } |
| } |
| put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]); |
| return true; |
| } |
| if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT)) |
| { |
| m_position += 20; |
| if(have_brace) |
| { |
| if((m_position != m_end) && (*m_position == '}')) |
| ++m_position; |
| else |
| { |
| m_position -= 20; |
| return false; |
| } |
| } |
| put(this->m_results.get_last_closed_paren()); |
| return true; |
| } |
| if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT)) |
| { |
| m_position += 2; |
| if(have_brace) |
| { |
| if((m_position != m_end) && (*m_position == '}')) |
| ++m_position; |
| else |
| { |
| m_position -= 2; |
| return false; |
| } |
| } |
| put(this->m_results.get_last_closed_paren()); |
| return true; |
| } |
| return false; |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_escape() |
| { |
| // skip the escape and check for trailing escape: |
| if(++m_position == m_end) |
| { |
| put(static_cast<char_type>('\\')); |
| return; |
| } |
| // now switch on the escape type: |
| switch(*m_position) |
| { |
| case 'a': |
| put(static_cast<char_type>('\a')); |
| ++m_position; |
| break; |
| case 'f': |
| put(static_cast<char_type>('\f')); |
| ++m_position; |
| break; |
| case 'n': |
| put(static_cast<char_type>('\n')); |
| ++m_position; |
| break; |
| case 'r': |
| put(static_cast<char_type>('\r')); |
| ++m_position; |
| break; |
| case 't': |
| put(static_cast<char_type>('\t')); |
| ++m_position; |
| break; |
| case 'v': |
| put(static_cast<char_type>('\v')); |
| ++m_position; |
| break; |
| case 'x': |
| if(++m_position == m_end) |
| { |
| put(static_cast<char_type>('x')); |
| return; |
| } |
| // maybe have \x{ddd} |
| if(*m_position == static_cast<char_type>('{')) |
| { |
| ++m_position; |
| int val = this->toi(m_position, m_end, 16); |
| if(val < 0) |
| { |
| // invalid value treat everything as literals: |
| put(static_cast<char_type>('x')); |
| put(static_cast<char_type>('{')); |
| return; |
| } |
| if((m_position == m_end) || (*m_position != static_cast<char_type>('}'))) |
| { |
| --m_position; |
| while(*m_position != static_cast<char_type>('\\')) |
| --m_position; |
| ++m_position; |
| put(*m_position++); |
| return; |
| } |
| ++m_position; |
| put(static_cast<char_type>(val)); |
| return; |
| } |
| else |
| { |
| std::ptrdiff_t len = ::ndnboost::re_detail::distance(m_position, m_end); |
| len = (std::min)(static_cast<std::ptrdiff_t>(2), len); |
| int val = this->toi(m_position, m_position + len, 16); |
| if(val < 0) |
| { |
| --m_position; |
| put(*m_position++); |
| return; |
| } |
| put(static_cast<char_type>(val)); |
| } |
| break; |
| case 'c': |
| if(++m_position == m_end) |
| { |
| --m_position; |
| put(*m_position++); |
| return; |
| } |
| put(static_cast<char_type>(*m_position++ % 32)); |
| break; |
| case 'e': |
| put(static_cast<char_type>(27)); |
| ++m_position; |
| break; |
| default: |
| // see if we have a perl specific escape: |
| if((m_flags & ndnboost::regex_constants::format_sed) == 0) |
| { |
| bool breakout = false; |
| switch(*m_position) |
| { |
| case 'l': |
| ++m_position; |
| m_restore_state = m_state; |
| m_state = output_next_lower; |
| breakout = true; |
| break; |
| case 'L': |
| ++m_position; |
| m_state = output_lower; |
| breakout = true; |
| break; |
| case 'u': |
| ++m_position; |
| m_restore_state = m_state; |
| m_state = output_next_upper; |
| breakout = true; |
| break; |
| case 'U': |
| ++m_position; |
| m_state = output_upper; |
| breakout = true; |
| break; |
| case 'E': |
| ++m_position; |
| m_state = output_copy; |
| breakout = true; |
| break; |
| } |
| if(breakout) |
| break; |
| } |
| // see if we have a \n sed style backreference: |
| std::ptrdiff_t len = ::ndnboost::re_detail::distance(m_position, m_end); |
| len = (std::min)(static_cast<std::ptrdiff_t>(1), len); |
| int v = this->toi(m_position, m_position+len, 10); |
| if((v > 0) || ((v == 0) && (m_flags & ::ndnboost::regex_constants::format_sed))) |
| { |
| put(m_results[v]); |
| break; |
| } |
| else if(v == 0) |
| { |
| // octal ecape sequence: |
| --m_position; |
| len = ::ndnboost::re_detail::distance(m_position, m_end); |
| len = (std::min)(static_cast<std::ptrdiff_t>(4), len); |
| v = this->toi(m_position, m_position + len, 8); |
| NDNBOOST_ASSERT(v >= 0); |
| put(static_cast<char_type>(v)); |
| break; |
| } |
| // Otherwise output the character "as is": |
| put(*m_position++); |
| break; |
| } |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional() |
| { |
| if(m_position == m_end) |
| { |
| // oops trailing '?': |
| put(static_cast<char_type>('?')); |
| return; |
| } |
| int v; |
| if(*m_position == '{') |
| { |
| ForwardIter base = m_position; |
| ++m_position; |
| v = this->toi(m_position, m_end, 10); |
| if(v < 0) |
| { |
| // Try a named subexpression: |
| while((m_position != m_end) && (*m_position != '}')) |
| ++m_position; |
| v = this->get_named_sub_index(base + 1, m_position); |
| } |
| if((v < 0) || (*m_position != '}')) |
| { |
| m_position = base; |
| // oops trailing '?': |
| put(static_cast<char_type>('?')); |
| return; |
| } |
| // Skip trailing '}': |
| ++m_position; |
| } |
| else |
| { |
| std::ptrdiff_t len = ::ndnboost::re_detail::distance(m_position, m_end); |
| len = (std::min)(static_cast<std::ptrdiff_t>(2), len); |
| v = this->toi(m_position, m_position + len, 10); |
| } |
| if(v < 0) |
| { |
| // oops not a number: |
| put(static_cast<char_type>('?')); |
| return; |
| } |
| |
| // output varies depending upon whether sub-expression v matched or not: |
| if(m_results[v].matched) |
| { |
| m_have_conditional = true; |
| format_all(); |
| m_have_conditional = false; |
| if((m_position != m_end) && (*m_position == static_cast<char_type>(':'))) |
| { |
| // skip the ':': |
| ++m_position; |
| // save output state, then turn it off: |
| output_state saved_state = m_state; |
| m_state = output_none; |
| // format the rest of this scope: |
| format_until_scope_end(); |
| // restore output state: |
| m_state = saved_state; |
| } |
| } |
| else |
| { |
| // save output state, then turn it off: |
| output_state saved_state = m_state; |
| m_state = output_none; |
| // format until ':' or ')': |
| m_have_conditional = true; |
| format_all(); |
| m_have_conditional = false; |
| // restore state: |
| m_state = saved_state; |
| if((m_position != m_end) && (*m_position == static_cast<char_type>(':'))) |
| { |
| // skip the ':': |
| ++m_position; |
| // format the rest of this scope: |
| format_until_scope_end(); |
| } |
| } |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end() |
| { |
| do |
| { |
| format_all(); |
| if((m_position == m_end) || (*m_position == static_cast<char_type>(')'))) |
| return; |
| put(*m_position++); |
| }while(m_position != m_end); |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(char_type c) |
| { |
| // write a single character to output |
| // according to which case translation mode we are in: |
| switch(this->m_state) |
| { |
| case output_none: |
| return; |
| case output_next_lower: |
| c = m_traits.tolower(c); |
| this->m_state = m_restore_state; |
| break; |
| case output_next_upper: |
| c = m_traits.toupper(c); |
| this->m_state = m_restore_state; |
| break; |
| case output_lower: |
| c = m_traits.tolower(c); |
| break; |
| case output_upper: |
| c = m_traits.toupper(c); |
| break; |
| default: |
| break; |
| } |
| *m_out = c; |
| ++m_out; |
| } |
| |
| template <class OutputIterator, class Results, class traits, class ForwardIter> |
| void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(const sub_match_type& sub) |
| { |
| typedef typename sub_match_type::iterator iterator_type; |
| iterator_type i = sub.first; |
| while(i != sub.second) |
| { |
| put(*i); |
| ++i; |
| } |
| } |
| |
| template <class S> |
| class string_out_iterator |
| #ifndef NDNBOOST_NO_STD_ITERATOR |
| : public std::iterator<std::output_iterator_tag, typename S::value_type> |
| #endif |
| { |
| S* out; |
| public: |
| string_out_iterator(S& s) : out(&s) {} |
| string_out_iterator& operator++() { return *this; } |
| string_out_iterator& operator++(int) { return *this; } |
| string_out_iterator& operator*() { return *this; } |
| string_out_iterator& operator=(typename S::value_type v) |
| { |
| out->append(1, v); |
| return *this; |
| } |
| |
| #ifdef NDNBOOST_NO_STD_ITERATOR |
| typedef std::ptrdiff_t difference_type; |
| typedef typename S::value_type value_type; |
| typedef value_type* pointer; |
| typedef value_type& reference; |
| typedef std::output_iterator_tag iterator_category; |
| #endif |
| }; |
| |
| template <class OutputIterator, class Iterator, class Alloc, class ForwardIter, class traits> |
| OutputIterator regex_format_imp(OutputIterator out, |
| const match_results<Iterator, Alloc>& m, |
| ForwardIter p1, ForwardIter p2, |
| match_flag_type flags, |
| const traits& t |
| ) |
| { |
| if(flags & regex_constants::format_literal) |
| { |
| return re_detail::copy(p1, p2, out); |
| } |
| |
| re_detail::basic_regex_formatter< |
| OutputIterator, |
| match_results<Iterator, Alloc>, |
| traits, ForwardIter> f(out, m, t); |
| return f.format(p1, p2, flags); |
| } |
| |
| #ifndef NDNBOOST_NO_SFINAE |
| |
| NDNBOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator) |
| |
| struct any_type |
| { |
| template <class T> |
| any_type(const T&); |
| template <class T, class U> |
| any_type(const T&, const U&); |
| template <class T, class U, class V> |
| any_type(const T&, const U&, const V&); |
| }; |
| typedef char no_type; |
| typedef char (&unary_type)[2]; |
| typedef char (&binary_type)[3]; |
| typedef char (&ternary_type)[4]; |
| |
| no_type check_is_formatter(unary_type, binary_type, ternary_type); |
| template<typename T> |
| unary_type check_is_formatter(T const &, binary_type, ternary_type); |
| template<typename T> |
| binary_type check_is_formatter(unary_type, T const &, ternary_type); |
| template<typename T, typename U> |
| binary_type check_is_formatter(T const &, U const &, ternary_type); |
| template<typename T> |
| ternary_type check_is_formatter(unary_type, binary_type, T const &); |
| template<typename T, typename U> |
| ternary_type check_is_formatter(T const &, binary_type, U const &); |
| template<typename T, typename U> |
| ternary_type check_is_formatter(unary_type, T const &, U const &); |
| template<typename T, typename U, typename V> |
| ternary_type check_is_formatter(T const &, U const &, V const &); |
| |
| struct unary_binary_ternary |
| { |
| typedef unary_type (*unary_fun)(any_type); |
| typedef binary_type (*binary_fun)(any_type, any_type); |
| typedef ternary_type (*ternary_fun)(any_type, any_type, any_type); |
| operator unary_fun(); |
| operator binary_fun(); |
| operator ternary_fun(); |
| }; |
| |
| template<typename Formatter, bool IsFunction = ndnboost::is_function<Formatter>::value> |
| struct formatter_wrapper |
| : Formatter |
| , unary_binary_ternary |
| { |
| formatter_wrapper(){} |
| }; |
| |
| template<typename Formatter> |
| struct formatter_wrapper<Formatter, true> |
| : unary_binary_ternary |
| { |
| operator Formatter *(); |
| }; |
| |
| template<typename Formatter> |
| struct formatter_wrapper<Formatter *, false> |
| : unary_binary_ternary |
| { |
| operator Formatter *(); |
| }; |
| |
| template <class F, class M, class O> |
| struct format_traits_imp |
| { |
| private: |
| // |
| // F must be a pointer, a function, or a class with a function call operator: |
| // |
| NDNBOOST_STATIC_ASSERT((::ndnboost::is_pointer<F>::value || ::ndnboost::is_function<F>::value || ::ndnboost::is_class<F>::value)); |
| static formatter_wrapper<typename unwrap_reference<F>::type> f; |
| static M m; |
| static O out; |
| static ndnboost::regex_constants::match_flag_type flags; |
| public: |
| NDNBOOST_STATIC_CONSTANT(int, value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags)))); |
| }; |
| |
| template <class F, class M, class O> |
| struct format_traits |
| { |
| public: |
| // |
| // Type is mpl::int_<N> where N is one of: |
| // |
| // 0 : F is a pointer to a presumably null-terminated string. |
| // 1 : F is a character-container such as a std::string. |
| // 2 : F is a Unary Functor. |
| // 3 : F is a Binary Functor. |
| // 4 : F is a Ternary Functor. |
| // |
| typedef typename ndnboost::mpl::if_< |
| ndnboost::mpl::and_<ndnboost::is_pointer<F>, ndnboost::mpl::not_<ndnboost::is_function<typename ndnboost::remove_pointer<F>::type> > >, |
| ndnboost::mpl::int_<0>, |
| typename ndnboost::mpl::if_< |
| has_const_iterator<F>, |
| ndnboost::mpl::int_<1>, |
| ndnboost::mpl::int_<format_traits_imp<F, M, O>::value> |
| >::type |
| >::type type; |
| // |
| // This static assertion will fail if the functor passed does not accept |
| // the same type of arguments passed. |
| // |
| NDNBOOST_STATIC_ASSERT( ndnboost::is_class<F>::value && !has_const_iterator<F>::value ? (type::value > 1) : true); |
| }; |
| |
| #else // NDNBOOST_NO_SFINAE |
| |
| template <class F, class M, class O> |
| struct format_traits |
| { |
| public: |
| // |
| // Type is mpl::int_<N> where N is one of: |
| // |
| // 0 : F is a pointer to a presumably null-terminated string. |
| // 1 : F is a character-container such as a std::string. |
| // |
| // Other options such as F being a Functor are not supported without |
| // SFINAE support. |
| // |
| typedef typename ndnboost::mpl::if_< |
| ndnboost::is_pointer<F>, |
| ndnboost::mpl::int_<0>, |
| ndnboost::mpl::int_<1> |
| >::type type; |
| }; |
| |
| #endif // NDNBOOST_NO_SFINAE |
| |
| template <class Base, class Match> |
| struct format_functor3 |
| { |
| format_functor3(Base b) : func(b) {} |
| template <class OutputIter> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type f) |
| { |
| return ndnboost::unwrap_ref(func)(m, i, f); |
| } |
| template <class OutputIter, class Traits> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type f, const Traits&) |
| { |
| return (*this)(m, i, f); |
| } |
| private: |
| Base func; |
| format_functor3(const format_functor3&); |
| format_functor3& operator=(const format_functor3&); |
| }; |
| |
| template <class Base, class Match> |
| struct format_functor2 |
| { |
| format_functor2(Base b) : func(b) {} |
| template <class OutputIter> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type /*f*/) |
| { |
| return ndnboost::unwrap_ref(func)(m, i); |
| } |
| template <class OutputIter, class Traits> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type f, const Traits&) |
| { |
| return (*this)(m, i, f); |
| } |
| private: |
| Base func; |
| format_functor2(const format_functor2&); |
| format_functor2& operator=(const format_functor2&); |
| }; |
| |
| template <class Base, class Match> |
| struct format_functor1 |
| { |
| format_functor1(Base b) : func(b) {} |
| |
| template <class S, class OutputIter> |
| OutputIter do_format_string(const S& s, OutputIter i) |
| { |
| return re_detail::copy(s.begin(), s.end(), i); |
| } |
| template <class S, class OutputIter> |
| inline OutputIter do_format_string(const S* s, OutputIter i) |
| { |
| while(s && *s) |
| { |
| *i = *s; |
| ++i; |
| ++s; |
| } |
| return i; |
| } |
| template <class OutputIter> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type /*f*/) |
| { |
| return do_format_string(ndnboost::unwrap_ref(func)(m), i); |
| } |
| template <class OutputIter, class Traits> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type f, const Traits&) |
| { |
| return (*this)(m, i, f); |
| } |
| private: |
| Base func; |
| format_functor1(const format_functor1&); |
| format_functor1& operator=(const format_functor1&); |
| }; |
| |
| template <class charT, class Match, class Traits> |
| struct format_functor_c_string |
| { |
| format_functor_c_string(const charT* ps) : func(ps) {} |
| |
| template <class OutputIter> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type f, const Traits& t = Traits()) |
| { |
| //typedef typename Match::char_type char_type; |
| const charT* end = func; |
| while(*end) ++end; |
| return regex_format_imp(i, m, func, end, f, t); |
| } |
| private: |
| const charT* func; |
| format_functor_c_string(const format_functor_c_string&); |
| format_functor_c_string& operator=(const format_functor_c_string&); |
| }; |
| |
| template <class Container, class Match, class Traits> |
| struct format_functor_container |
| { |
| format_functor_container(const Container& c) : func(c) {} |
| |
| template <class OutputIter> |
| OutputIter operator()(const Match& m, OutputIter i, ndnboost::regex_constants::match_flag_type f, const Traits& t = Traits()) |
| { |
| //typedef typename Match::char_type char_type; |
| return re_detail::regex_format_imp(i, m, func.begin(), func.end(), f, t); |
| } |
| private: |
| const Container& func; |
| format_functor_container(const format_functor_container&); |
| format_functor_container& operator=(const format_functor_container&); |
| }; |
| |
| template <class Func, class Match, class OutputIterator, class Traits = re_detail::trivial_format_traits<typename Match::char_type> > |
| struct compute_functor_type |
| { |
| typedef typename format_traits<Func, Match, OutputIterator>::type tag; |
| typedef typename ndnboost::remove_cv< typename ndnboost::remove_pointer<Func>::type>::type maybe_char_type; |
| |
| typedef typename mpl::if_< |
| ::ndnboost::is_same<tag, mpl::int_<0> >, format_functor_c_string<maybe_char_type, Match, Traits>, |
| typename mpl::if_< |
| ::ndnboost::is_same<tag, mpl::int_<1> >, format_functor_container<Func, Match, Traits>, |
| typename mpl::if_< |
| ::ndnboost::is_same<tag, mpl::int_<2> >, format_functor1<Func, Match>, |
| typename mpl::if_< |
| ::ndnboost::is_same<tag, mpl::int_<3> >, format_functor2<Func, Match>, |
| format_functor3<Func, Match> |
| >::type |
| >::type |
| >::type |
| >::type type; |
| }; |
| |
| } // namespace re_detail |
| |
| template <class OutputIterator, class Iterator, class Allocator, class Functor> |
| inline OutputIterator regex_format(OutputIterator out, |
| const match_results<Iterator, Allocator>& m, |
| Functor fmt, |
| match_flag_type flags = format_all |
| ) |
| { |
| return m.format(out, fmt, flags); |
| } |
| |
| template <class Iterator, class Allocator, class Functor> |
| inline std::basic_string<typename match_results<Iterator, Allocator>::char_type> regex_format(const match_results<Iterator, Allocator>& m, |
| Functor fmt, |
| match_flag_type flags = format_all) |
| { |
| return m.format(fmt, flags); |
| } |
| |
| #ifdef NDNBOOST_MSVC |
| #pragma warning(push) |
| #pragma warning(disable: 4103) |
| #endif |
| #ifdef NDNBOOST_HAS_ABI_HEADERS |
| # include NDNBOOST_ABI_SUFFIX |
| #endif |
| #ifdef NDNBOOST_MSVC |
| #pragma warning(pop) |
| #endif |
| |
| } // namespace ndnboost |
| |
| #endif // NDNBOOST_REGEX_FORMAT_HPP |
| |
| |
| |
| |
| |
| |