regex_format.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 655 行 · 第 1/2 页
HPP
655 行
/* * * Copyright (c) 1998-2002 * John Maddock * * Use, modification and distribution are subject to the * Boost Software License, Version 1.0. (See accompanying file * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) * */ /* * LOCATION: see http://www.boost.org for most recent version. * FILE regex_format.hpp * VERSION see <boost/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 BOOST_REGEX_FORMAT_HPP#define BOOST_REGEX_FORMAT_HPPnamespace boost{#ifdef BOOST_MSVC#pragma warning(push)#pragma warning(disable: 4103)#endif#ifdef BOOST_HAS_ABI_HEADERS# include BOOST_ABI_PREFIX#endif#ifdef BOOST_MSVC#pragma warning(pop)#endif//// Forward declaration:// template <class BidiIterator, class Allocator = BOOST_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 ::boost::re_detail::global_lower(c); } static charT toupper(charT c) { return ::boost::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 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(const char_type* p1, const char_type* p2, match_flag_type f); OutputIterator format(const char_type* p1, match_flag_type f) { return format(p1, p1 + m_traits.length(p1), f); }private: typedef typename Results::value_type sub_match_type; enum output_state { output_copy, output_next_lower, output_next_upper, output_lower, output_upper, output_none }; void put(char_type c); void put(const sub_match_type& sub); void format_all(); void format_perl(); void format_escape(); void format_conditional(); void format_until_scope_end(); const traits& m_traits; // the traits class for localised formatting operations const Results& m_results; // the match_results being used. OutputIterator m_out; // where to send output. const char_type* m_position; // format string, current position const char_type* m_end; // format string end match_flag_type m_flags; // format flags to use output_state m_state; // what to do with the next character output_state m_restore_state; // what state to restore to. bool m_have_conditional; // we are parsing a conditionalprivate: basic_regex_formatter(const basic_regex_formatter&); basic_regex_formatter& operator=(const basic_regex_formatter&);};template <class OutputIterator, class Results, class traits>OutputIterator basic_regex_formatter<OutputIterator, Results, traits>::format(const char_type* p1, const char_type* p2, match_flag_type f){ m_position = p1; m_end = p2; m_flags = f; format_all(); return m_out;}template <class OutputIterator, class Results, class traits>void basic_regex_formatter<OutputIterator, Results, traits>::format_all(){ // over and over: while(m_position != m_end) { switch(*m_position) { case '&': if(m_flags & ::boost::regex_constants::format_sed) { ++m_position; put(m_results[0]); break; } put(*m_position++); break; case '\\': format_escape(); break; case '(': if(m_flags & boost::regex_constants::format_all) { ++m_position; 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; BOOST_ASSERT(*m_position == static_cast<char_type>(')')); ++m_position; // skip the closing ')' break; } put(*m_position); ++m_position; break; case ')': if(m_flags & boost::regex_constants::format_all) { return; } put(*m_position); ++m_position; break; case ':': if((m_flags & boost::regex_constants::format_all) && m_have_conditional) { return; } put(*m_position); ++m_position; break; case '?': if(m_flags & boost::regex_constants::format_all) { ++m_position; format_conditional(); break; } put(*m_position); ++m_position; break; case '$': if((m_flags & format_sed) == 0) { format_perl(); break; } // fall through, not a special character: default: put(*m_position); ++m_position; break; } }}template <class OutputIterator, class Results, class traits>void basic_regex_formatter<OutputIterator, Results, traits>::format_perl(){ // // On entry *m_position points to a '$' character // output the information that goes with it: // BOOST_ASSERT(*m_position == '$'); // // see if this is a trailing '$': // if(++m_position == m_end) { --m_position; put(*m_position); ++m_position; return; } // // OK find out what kind it is: // switch(*m_position) { case '&': ++m_position; put(this->m_results[0]); break; case '`': ++m_position; put(this->m_results.prefix()); break; case '\'': ++m_position; put(this->m_results.suffix()); break; case '$': put(*m_position++); break; default: // see if we have a number: { std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end); len = (std::min)(static_cast<std::ptrdiff_t>(2), len); int v = m_traits.toi(m_position, m_position + len, 10); if(v < 0) { // leave the $ as is, and carry on: --m_position; put(*m_position); ++m_position; break; } // otherwise output sub v: put(this->m_results[v]); } }}template <class OutputIterator, class Results, class traits>void basic_regex_formatter<OutputIterator, Results, traits>::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 = m_traits.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 != static_cast<char_type>('}')) { while(*m_position != static_cast<char_type>('\\')) --m_position;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?