Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:25

0001 /*
0002  *
0003  * Copyright (c) 1998-2009 John Maddock
0004  * Copyright 2008 Eric Niebler. 
0005  *
0006  * Use, modification and distribution are subject to the 
0007  * Boost Software License, Version 1.0. (See accompanying file 
0008  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009  *
0010  */
0011 
0012  /*
0013   *   LOCATION:    see http://www.boost.org for most recent version.
0014   *   FILE         regex_format.hpp
0015   *   VERSION      see <boost/version.hpp>
0016   *   DESCRIPTION: Provides formatting output routines for search and replace
0017   *                operations.  Note this is an internal header file included
0018   *                by regex.hpp, do not include on its own.
0019   */
0020 
0021 #ifndef BOOST_REGEX_FORMAT_HPP
0022 #define BOOST_REGEX_FORMAT_HPP
0023 
0024 #include <boost/type_traits/is_pointer.hpp>
0025 #include <boost/type_traits/is_function.hpp>
0026 #include <boost/type_traits/is_class.hpp>
0027 #include <boost/type_traits/is_same.hpp>
0028 #include <boost/type_traits/is_convertible.hpp>
0029 #include <boost/type_traits/remove_pointer.hpp>
0030 #include <boost/type_traits/remove_cv.hpp>
0031 #include <boost/mpl/if.hpp>
0032 #include <boost/mpl/and.hpp>
0033 #include <boost/mpl/not.hpp>
0034 #ifndef BOOST_NO_SFINAE
0035 #include <boost/mpl/has_xxx.hpp>
0036 #endif
0037 #include <boost/ref.hpp>
0038 
0039 namespace boost{
0040 
0041 #ifdef BOOST_MSVC
0042 #pragma warning(push)
0043 #pragma warning(disable: 4103)
0044 #endif
0045 #ifdef BOOST_HAS_ABI_HEADERS
0046 #  include BOOST_ABI_PREFIX
0047 #endif
0048 #ifdef BOOST_MSVC
0049 #pragma warning(pop)
0050 #endif
0051 
0052 //
0053 // Forward declaration:
0054 //
0055    template <class BidiIterator, class Allocator = BOOST_DEDUCED_TYPENAME std::vector<sub_match<BidiIterator> >::allocator_type >
0056 class match_results;
0057 
0058 namespace BOOST_REGEX_DETAIL_NS{
0059 
0060 //
0061 // struct trivial_format_traits:
0062 // defines minimum localisation support for formatting
0063 // in the case that the actual regex traits is unavailable.
0064 //
0065 template <class charT>
0066 struct trivial_format_traits
0067 {
0068    typedef charT char_type;
0069 
0070    static std::ptrdiff_t length(const charT* p)
0071    {
0072       return global_length(p);
0073    }
0074    static charT tolower(charT c)
0075    {
0076       return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c);
0077    }
0078    static charT toupper(charT c)
0079    {
0080       return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c);
0081    }
0082    static int value(const charT c, int radix)
0083    {
0084       int result = global_value(c);
0085       return result >= radix ? -1 : result;
0086    }
0087    int toi(const charT*& p1, const charT* p2, int radix)const
0088    {
0089       return (int)global_toi(p1, p2, radix, *this);
0090    }
0091 };
0092 
0093 #ifdef BOOST_MSVC
0094 #  pragma warning(push)
0095 #pragma warning(disable:26812)
0096 #endif
0097 template <class OutputIterator, class Results, class traits, class ForwardIter>
0098 class basic_regex_formatter
0099 {
0100 public:
0101    typedef typename traits::char_type char_type;
0102    basic_regex_formatter(OutputIterator o, const Results& r, const traits& t)
0103       : m_traits(t), m_results(r), m_out(o), m_position(), m_end(), m_flags(), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {}
0104    OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f);
0105    OutputIterator format(ForwardIter p1, match_flag_type f)
0106    {
0107       return format(p1, p1 + m_traits.length(p1), f);
0108    }
0109 private:
0110    typedef typename Results::value_type sub_match_type;
0111    enum output_state
0112    {
0113       output_copy,
0114       output_next_lower,
0115       output_next_upper,
0116       output_lower,
0117       output_upper,
0118       output_none
0119    };
0120 
0121    void put(char_type c);
0122    void put(const sub_match_type& sub);
0123    void format_all();
0124    void format_perl();
0125    void format_escape();
0126    void format_conditional();
0127    void format_until_scope_end();
0128    bool handle_perl_verb(bool have_brace);
0129 
0130    inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::false_&)
0131    {
0132       std::vector<char_type> v(i, j);
0133       return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size())
0134          : this->m_results.named_subexpression(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
0135    }
0136    inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::true_&)
0137    {
0138       return this->m_results.named_subexpression(i, j);
0139    }
0140    inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j)
0141    {
0142       typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
0143       return get_named_sub(i, j, tag_type());
0144    }
0145    inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::false_&)
0146    {
0147       std::vector<char_type> v(i, j);
0148       return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size())
0149          : this->m_results.named_subexpression_index(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
0150    }
0151    inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::true_&)
0152    {
0153       return this->m_results.named_subexpression_index(i, j);
0154    }
0155    inline int get_named_sub_index(ForwardIter i, ForwardIter j)
0156    {
0157       typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
0158       return get_named_sub_index(i, j, tag_type());
0159    }
0160 #ifdef BOOST_MSVC
0161    // msvc-8.0 issues a spurious warning on the call to std::advance here:
0162 #pragma warning(push)
0163 #pragma warning(disable:4244)
0164 #endif
0165    inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::false_&)
0166    {
0167       if(i != j)
0168       {
0169          std::vector<char_type> v(i, j);
0170          const char_type* start = &v[0];
0171          const char_type* pos = start;
0172          int r = (int)m_traits.toi(pos, &v[0] + v.size(), base);
0173          std::advance(i, pos - start);
0174          return r;
0175       }
0176       return -1;
0177    }
0178 #ifdef BOOST_MSVC
0179 #pragma warning(pop)
0180 #endif
0181    inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::true_&)
0182    {
0183       return m_traits.toi(i, j, base);
0184    }
0185    inline int toi(ForwardIter& i, ForwardIter j, int base)
0186    {
0187 #if defined(_MSC_VER) && defined(__INTEL_COMPILER) && ((__INTEL_COMPILER == 9999) || (__INTEL_COMPILER == 1210))
0188       // Workaround for Intel support issue #656654.
0189       // See also https://svn.boost.org/trac/boost/ticket/6359
0190       return toi(i, j, base, mpl::false_());
0191 #else
0192       typedef typename boost::is_convertible<ForwardIter, const char_type*&>::type tag_type;
0193       return toi(i, j, base, tag_type());
0194 #endif
0195    }
0196 
0197    const traits&    m_traits;       // the traits class for localised formatting operations
0198    const Results&   m_results;     // the match_results being used.
0199    OutputIterator   m_out;         // where to send output.
0200    ForwardIter      m_position;  // format string, current position
0201    ForwardIter      m_end;       // format string end
0202    match_flag_type  m_flags;      // format flags to use
0203    output_state     m_state;      // what to do with the next character
0204    output_state     m_restore_state;  // what state to restore to.
0205    bool             m_have_conditional; // we are parsing a conditional
0206 private:
0207    basic_regex_formatter(const basic_regex_formatter&);
0208    basic_regex_formatter& operator=(const basic_regex_formatter&);
0209 };
0210 #ifdef BOOST_MSVC
0211 #  pragma warning(pop)
0212 #endif
0213 
0214 template <class OutputIterator, class Results, class traits, class ForwardIter>
0215 OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format(ForwardIter p1, ForwardIter p2, match_flag_type f)
0216 {
0217    m_position = p1;
0218    m_end = p2;
0219    m_flags = f;
0220    format_all();
0221    return m_out;
0222 }
0223 
0224 template <class OutputIterator, class Results, class traits, class ForwardIter>
0225 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all()
0226 {
0227    // over and over:
0228    while(m_position != m_end)
0229    {
0230       switch(*m_position)
0231       {
0232       case '&':
0233          if(m_flags & ::boost::regex_constants::format_sed)
0234          {
0235             ++m_position;
0236             put(m_results[0]);
0237             break;
0238          }
0239          put(*m_position++);
0240          break;
0241       case '\\':
0242          format_escape();
0243          break;
0244       case '(':
0245          if(m_flags & boost::regex_constants::format_all)
0246          {
0247             ++m_position;
0248             bool have_conditional = m_have_conditional;
0249             m_have_conditional = false;
0250             format_until_scope_end();
0251             m_have_conditional = have_conditional;
0252             if(m_position == m_end)
0253                return;
0254             BOOST_REGEX_ASSERT(*m_position == static_cast<char_type>(')'));
0255             ++m_position;  // skip the closing ')'
0256             break;
0257          }
0258          put(*m_position);
0259          ++m_position;
0260          break;
0261       case ')':
0262          if(m_flags & boost::regex_constants::format_all)
0263          {
0264             return;
0265          }
0266          put(*m_position);
0267          ++m_position;
0268          break;
0269       case ':':
0270          if((m_flags & boost::regex_constants::format_all) && m_have_conditional)
0271          {
0272             return;
0273          }
0274          put(*m_position);
0275          ++m_position;
0276          break;
0277       case '?':
0278          if(m_flags & boost::regex_constants::format_all)
0279          {
0280             ++m_position;
0281             format_conditional();
0282             break;
0283          }
0284          put(*m_position);
0285          ++m_position;
0286          break;
0287       case '$':
0288          if((m_flags & format_sed) == 0)
0289          {
0290             format_perl();
0291             break;
0292          }
0293          // not a special character:
0294          BOOST_FALLTHROUGH;
0295       default:
0296          put(*m_position);
0297          ++m_position;
0298          break;
0299       }
0300    }
0301 }
0302 
0303 template <class OutputIterator, class Results, class traits, class ForwardIter>
0304 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_perl()
0305 {
0306    //
0307    // On entry *m_position points to a '$' character
0308    // output the information that goes with it:
0309    //
0310    BOOST_REGEX_ASSERT(*m_position == '$');
0311    //
0312    // see if this is a trailing '$':
0313    //
0314    if(++m_position == m_end)
0315    {
0316       --m_position;
0317       put(*m_position);
0318       ++m_position;
0319       return;
0320    }
0321    //
0322    // OK find out what kind it is:
0323    //
0324    bool have_brace = false;
0325    ForwardIter save_position = m_position;
0326    switch(*m_position)
0327    {
0328    case '&':
0329       ++m_position;
0330       put(this->m_results[0]);
0331       break;
0332    case '`':
0333       ++m_position;
0334       put(this->m_results.prefix());
0335       break;
0336    case '\'':
0337       ++m_position;
0338       put(this->m_results.suffix());
0339       break;
0340    case '$':
0341       put(*m_position++);
0342       break;
0343    case '+':
0344       if((++m_position != m_end) && (*m_position == '{'))
0345       {
0346          ForwardIter base = ++m_position;
0347          while((m_position != m_end) && (*m_position != '}')) ++m_position;
0348          if(m_position != m_end)
0349          {
0350             // Named sub-expression:
0351             put(get_named_sub(base, m_position));
0352             ++m_position;
0353             break;
0354          }
0355          else
0356          {
0357             m_position = --base;
0358          }
0359       }
0360       put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]);
0361       break;
0362    case '{':
0363       have_brace = true;
0364       ++m_position;
0365       BOOST_FALLTHROUGH;
0366    default:
0367       // see if we have a number:
0368       {
0369          std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
0370          //len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
0371          int v = this->toi(m_position, m_position + len, 10);
0372          if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}'))))
0373          {
0374             // Look for a Perl-5.10 verb:
0375             if(!handle_perl_verb(have_brace))
0376             {
0377                // leave the $ as is, and carry on:
0378                m_position = --save_position;
0379                put(*m_position);
0380                ++m_position;
0381             }
0382             break;
0383          }
0384          // otherwise output sub v:
0385          put(this->m_results[v]);
0386          if(have_brace)
0387             ++m_position;
0388       }
0389    }
0390 }
0391 
0392 template <class OutputIterator, class Results, class traits, class ForwardIter>
0393 bool basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::handle_perl_verb(bool have_brace)
0394 {
0395    // 
0396    // We may have a capitalised string containing a Perl action:
0397    //
0398    static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' };
0399    static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' };
0400    static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' };
0401    static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' };
0402    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' };
0403    static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' };
0404 
0405    if(m_position == m_end)
0406       return false;
0407    if(have_brace && (*m_position == '^'))
0408       ++m_position;
0409 
0410    std::ptrdiff_t max_len = m_end - m_position;
0411 
0412    if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH))
0413    {
0414       m_position += 5;
0415       if(have_brace)
0416       {
0417          if((m_position != m_end) && (*m_position == '}'))
0418             ++m_position;
0419          else
0420          {
0421             m_position -= 5;
0422             return false;
0423          }
0424       }
0425       put(this->m_results[0]);
0426       return true;
0427    }
0428    if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH))
0429    {
0430       m_position += 8;
0431       if(have_brace)
0432       {
0433          if((m_position != m_end) && (*m_position == '}'))
0434             ++m_position;
0435          else
0436          {
0437             m_position -= 8;
0438             return false;
0439          }
0440       }
0441       put(this->m_results.prefix());
0442       return true;
0443    }
0444    if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH))
0445    {
0446       m_position += 9;
0447       if(have_brace)
0448       {
0449          if((m_position != m_end) && (*m_position == '}'))
0450             ++m_position;
0451          else
0452          {
0453             m_position -= 9;
0454             return false;
0455          }
0456       }
0457       put(this->m_results.suffix());
0458       return true;
0459    }
0460    if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH))
0461    {
0462       m_position += 16;
0463       if(have_brace)
0464       {
0465          if((m_position != m_end) && (*m_position == '}'))
0466             ++m_position;
0467          else
0468          {
0469             m_position -= 16;
0470             return false;
0471          }
0472       }
0473       put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]);
0474       return true;
0475    }
0476    if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT))
0477    {
0478       m_position += 20;
0479       if(have_brace)
0480       {
0481          if((m_position != m_end) && (*m_position == '}'))
0482             ++m_position;
0483          else
0484          {
0485             m_position -= 20;
0486             return false;
0487          }
0488       }
0489       put(this->m_results.get_last_closed_paren());
0490       return true;
0491    }
0492    if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT))
0493    {
0494       m_position += 2;
0495       if(have_brace)
0496       {
0497          if((m_position != m_end) && (*m_position == '}'))
0498             ++m_position;
0499          else
0500          {
0501             m_position -= 2;
0502             return false;
0503          }
0504       }
0505       put(this->m_results.get_last_closed_paren());
0506       return true;
0507    }
0508    return false;
0509 }
0510 
0511 template <class OutputIterator, class Results, class traits, class ForwardIter>
0512 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_escape()
0513 {
0514    // skip the escape and check for trailing escape:
0515    if(++m_position == m_end)
0516    {
0517       put(static_cast<char_type>('\\'));
0518       return;
0519    }
0520    // now switch on the escape type:
0521    switch(*m_position)
0522    {
0523    case 'a':
0524       put(static_cast<char_type>('\a'));
0525       ++m_position;
0526       break;
0527    case 'f':
0528       put(static_cast<char_type>('\f'));
0529       ++m_position;
0530       break;
0531    case 'n':
0532       put(static_cast<char_type>('\n'));
0533       ++m_position;
0534       break;
0535    case 'r':
0536       put(static_cast<char_type>('\r'));
0537       ++m_position;
0538       break;
0539    case 't':
0540       put(static_cast<char_type>('\t'));
0541       ++m_position;
0542       break;
0543    case 'v':
0544       put(static_cast<char_type>('\v'));
0545       ++m_position;
0546       break;
0547    case 'x':
0548       if(++m_position == m_end)
0549       {
0550          put(static_cast<char_type>('x'));
0551          return;
0552       }
0553       // maybe have \x{ddd}
0554       if(*m_position == static_cast<char_type>('{'))
0555       {
0556          ++m_position;
0557          int val = this->toi(m_position, m_end, 16);
0558          if(val < 0)
0559          {
0560             // invalid value treat everything as literals:
0561             put(static_cast<char_type>('x'));
0562             put(static_cast<char_type>('{'));
0563             return;
0564          }
0565          if((m_position == m_end) || (*m_position != static_cast<char_type>('}')))
0566          {
0567             --m_position;
0568             while(*m_position != static_cast<char_type>('\\'))
0569                --m_position;
0570             ++m_position;
0571             put(*m_position++);
0572             return;
0573          }
0574          ++m_position;
0575          put(static_cast<char_type>(val));
0576          return;
0577       }
0578       else
0579       {
0580          std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
0581          len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
0582          int val = this->toi(m_position, m_position + len, 16);
0583          if(val < 0)
0584          {
0585             --m_position;
0586             put(*m_position++);
0587             return;
0588          }
0589          put(static_cast<char_type>(val));
0590       }
0591       break;
0592    case 'c':
0593       if(++m_position == m_end)
0594       {
0595          --m_position;
0596          put(*m_position++);
0597          return;
0598       }
0599       put(static_cast<char_type>(*m_position++ % 32));
0600       break;
0601    case 'e':
0602       put(static_cast<char_type>(27));
0603       ++m_position;
0604       break;
0605    default:
0606       // see if we have a perl specific escape:
0607       if((m_flags & boost::regex_constants::format_sed) == 0)
0608       {
0609          bool breakout = false;
0610          switch(*m_position)
0611          {
0612          case 'l':
0613             ++m_position;
0614             m_restore_state = m_state;
0615             m_state = output_next_lower;
0616             breakout = true;
0617             break;
0618          case 'L':
0619             ++m_position;
0620             m_state = output_lower;
0621             breakout = true;
0622             break;
0623          case 'u':
0624             ++m_position;
0625             m_restore_state = m_state;
0626             m_state = output_next_upper;
0627             breakout = true;
0628             break;
0629          case 'U':
0630             ++m_position;
0631             m_state = output_upper;
0632             breakout = true;
0633             break;
0634          case 'E':
0635             ++m_position;
0636             m_state = output_copy;
0637             breakout = true;
0638             break;
0639          }
0640          if(breakout)
0641             break;
0642       }
0643       // see if we have a \n sed style backreference:
0644       std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
0645       len = (std::min)(static_cast<std::ptrdiff_t>(1), len);
0646       int v = this->toi(m_position, m_position+len, 10);
0647       if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed)))
0648       {
0649          put(m_results[v]);
0650          break;
0651       }
0652       else if(v == 0)
0653       {
0654          // octal ecape sequence:
0655          --m_position;
0656          len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
0657          len = (std::min)(static_cast<std::ptrdiff_t>(4), len);
0658          v = this->toi(m_position, m_position + len, 8);
0659          BOOST_REGEX_ASSERT(v >= 0);
0660          put(static_cast<char_type>(v));
0661          break;
0662       }
0663       // Otherwise output the character "as is":
0664       put(*m_position++);
0665       break;
0666    }
0667 }
0668 
0669 template <class OutputIterator, class Results, class traits, class ForwardIter>
0670 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional()
0671 {
0672    if(m_position == m_end)
0673    {
0674       // oops trailing '?':
0675       put(static_cast<char_type>('?'));
0676       return;
0677    }
0678    int v;
0679    if(*m_position == '{')
0680    {
0681       ForwardIter base = m_position;
0682       ++m_position;
0683       v = this->toi(m_position, m_end, 10);
0684       if(v < 0)
0685       {
0686          // Try a named subexpression:
0687          while((m_position != m_end) && (*m_position != '}'))
0688             ++m_position;
0689          v = this->get_named_sub_index(base + 1, m_position);
0690       }
0691       if((v < 0) || (*m_position != '}'))
0692       {
0693          m_position = base;
0694          // oops trailing '?':
0695          put(static_cast<char_type>('?'));
0696          return;
0697       }
0698       // Skip trailing '}':
0699       ++m_position;
0700    }
0701    else
0702    {
0703       std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
0704       len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
0705       v = this->toi(m_position, m_position + len, 10);
0706    }
0707    if(v < 0)
0708    {
0709       // oops not a number:
0710       put(static_cast<char_type>('?'));
0711       return;
0712    }
0713 
0714    // output varies depending upon whether sub-expression v matched or not:
0715    if(m_results[v].matched)
0716    {
0717       m_have_conditional = true;
0718       format_all();
0719       m_have_conditional = false;
0720       if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
0721       {
0722          // skip the ':':
0723          ++m_position;
0724          // save output state, then turn it off:
0725          output_state saved_state = m_state;
0726          m_state = output_none;
0727          // format the rest of this scope:
0728          format_until_scope_end();
0729          // restore output state:
0730          m_state = saved_state;
0731       }
0732    }
0733    else
0734    {
0735       // save output state, then turn it off:
0736       output_state saved_state = m_state;
0737       m_state = output_none;
0738       // format until ':' or ')':
0739       m_have_conditional = true;
0740       format_all();
0741       m_have_conditional = false;
0742       // restore state:
0743       m_state = saved_state;
0744       if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
0745       {
0746          // skip the ':':
0747          ++m_position;
0748          // format the rest of this scope:
0749          format_until_scope_end();
0750       }
0751    }
0752 }
0753 
0754 template <class OutputIterator, class Results, class traits, class ForwardIter>
0755 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end()
0756 {
0757    do
0758    {
0759       format_all();
0760       if((m_position == m_end) || (*m_position == static_cast<char_type>(')')))
0761          return;
0762       put(*m_position++);
0763    }while(m_position != m_end);
0764 }
0765 
0766 template <class OutputIterator, class Results, class traits, class ForwardIter>
0767 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(char_type c)
0768 {
0769    // write a single character to output
0770    // according to which case translation mode we are in:
0771    switch(this->m_state)
0772    {
0773    case output_none:
0774       return;
0775    case output_next_lower:
0776       c = m_traits.tolower(c);
0777       this->m_state = m_restore_state;
0778       break;
0779    case output_next_upper:
0780       c = m_traits.toupper(c);
0781       this->m_state = m_restore_state;
0782       break;
0783    case output_lower:
0784       c = m_traits.tolower(c);
0785       break;
0786    case output_upper:
0787       c = m_traits.toupper(c);
0788       break;
0789    default:
0790       break;
0791    }
0792    *m_out = c;
0793    ++m_out;
0794 }
0795 
0796 template <class OutputIterator, class Results, class traits, class ForwardIter>
0797 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(const sub_match_type& sub)
0798 {
0799    typedef typename sub_match_type::iterator iterator_type;
0800    iterator_type i = sub.first;
0801    while(i != sub.second)
0802    {
0803       put(*i);
0804       ++i;
0805    }
0806 }
0807 
0808 template <class S>
0809 class string_out_iterator
0810 {
0811    S* out;
0812 public:
0813    string_out_iterator(S& s) : out(&s) {}
0814    string_out_iterator& operator++() { return *this; }
0815    string_out_iterator& operator++(int) { return *this; }
0816    string_out_iterator& operator*() { return *this; }
0817    string_out_iterator& operator=(typename S::value_type v) 
0818    { 
0819       out->append(1, v); 
0820       return *this; 
0821    }
0822 
0823    typedef std::ptrdiff_t difference_type;
0824    typedef typename S::value_type value_type;
0825    typedef value_type* pointer;
0826    typedef value_type& reference;
0827    typedef std::output_iterator_tag iterator_category;
0828 };
0829 
0830 template <class OutputIterator, class Iterator, class Alloc, class ForwardIter, class traits>
0831 OutputIterator regex_format_imp(OutputIterator out,
0832                           const match_results<Iterator, Alloc>& m,
0833                           ForwardIter p1, ForwardIter p2,
0834                           match_flag_type flags,
0835                           const traits& t
0836                          )
0837 {
0838    if(flags & regex_constants::format_literal)
0839    {
0840       return BOOST_REGEX_DETAIL_NS::copy(p1, p2, out);
0841    }
0842 
0843    BOOST_REGEX_DETAIL_NS::basic_regex_formatter<
0844       OutputIterator, 
0845       match_results<Iterator, Alloc>, 
0846       traits, ForwardIter> f(out, m, t);
0847    return f.format(p1, p2, flags);
0848 }
0849 
0850 #ifndef BOOST_NO_SFINAE
0851 
0852 BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
0853 
0854 struct any_type 
0855 {
0856    template <class T>
0857    any_type(const T&); 
0858    template <class T, class U>
0859    any_type(const T&, const U&); 
0860    template <class T, class U, class V>
0861    any_type(const T&, const U&, const V&); 
0862 };
0863 typedef char no_type;
0864 typedef char (&unary_type)[2];
0865 typedef char (&binary_type)[3];
0866 typedef char (&ternary_type)[4];
0867 
0868 no_type check_is_formatter(unary_type, binary_type, ternary_type);
0869 template<typename T>
0870 unary_type check_is_formatter(T const &, binary_type, ternary_type);
0871 template<typename T>
0872 binary_type check_is_formatter(unary_type, T const &, ternary_type);
0873 template<typename T, typename U>
0874 binary_type check_is_formatter(T const &, U const &, ternary_type);
0875 template<typename T>
0876 ternary_type check_is_formatter(unary_type, binary_type, T const &);
0877 template<typename T, typename U>
0878 ternary_type check_is_formatter(T const &, binary_type, U const &);
0879 template<typename T, typename U>
0880 ternary_type check_is_formatter(unary_type, T const &, U const &);
0881 template<typename T, typename U, typename V>
0882 ternary_type check_is_formatter(T const &, U const &, V const &);
0883 
0884 struct unary_binary_ternary
0885 {
0886     typedef unary_type (*unary_fun)(any_type);
0887     typedef binary_type (*binary_fun)(any_type, any_type);
0888     typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
0889     operator unary_fun();
0890     operator binary_fun();
0891     operator ternary_fun();
0892 };
0893 
0894 template<typename Formatter, bool IsFunction = boost::is_function<Formatter>::value>
0895 struct formatter_wrapper
0896   : Formatter
0897   , unary_binary_ternary
0898 {
0899    formatter_wrapper(){}
0900 };
0901 
0902 template<typename Formatter>
0903 struct formatter_wrapper<Formatter, true>
0904   : unary_binary_ternary
0905 {
0906     operator Formatter *();
0907 };
0908 
0909 template<typename Formatter>
0910 struct formatter_wrapper<Formatter *, false>
0911   : unary_binary_ternary
0912 {
0913     operator Formatter *();
0914 };
0915 
0916 template <class F, class M, class O>
0917 struct format_traits_imp
0918 {
0919 private:
0920    //
0921    // F must be a pointer, a function, or a class with a function call operator:
0922    //
0923    BOOST_STATIC_ASSERT((::boost::is_pointer<F>::value || ::boost::is_function<F>::value || ::boost::is_class<F>::value));
0924    static formatter_wrapper<typename unwrap_reference<F>::type> f;
0925    static M m;
0926    static O out;
0927    static boost::regex_constants::match_flag_type flags;
0928 public:
0929    BOOST_STATIC_CONSTANT(int, value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags))));
0930 };
0931 
0932 template <class F, class M, class O>
0933 struct format_traits
0934 {
0935 public:
0936    // 
0937    // Type is mpl::int_<N> where N is one of:
0938    //
0939    // 0 : F is a pointer to a presumably null-terminated string.
0940    // 1 : F is a character-container such as a std::string.
0941    // 2 : F is a Unary Functor.
0942    // 3 : F is a Binary Functor.
0943    // 4 : F is a Ternary Functor.
0944    //
0945    typedef typename boost::mpl::if_<
0946       boost::mpl::and_<boost::is_pointer<F>, boost::mpl::not_<boost::is_function<typename boost::remove_pointer<F>::type> > >,
0947       boost::mpl::int_<0>,
0948       typename boost::mpl::if_<
0949          has_const_iterator<F>,
0950          boost::mpl::int_<1>,
0951          boost::mpl::int_<format_traits_imp<F, M, O>::value>
0952       >::type
0953    >::type type;
0954    //
0955    // This static assertion will fail if the functor passed does not accept
0956    // the same type of arguments passed.
0957    //
0958    BOOST_STATIC_ASSERT( boost::is_class<F>::value && !has_const_iterator<F>::value ? (type::value > 1) : true);
0959 };
0960 
0961 #else // BOOST_NO_SFINAE
0962 
0963 template <class F, class M, class O>
0964 struct format_traits
0965 {
0966 public:
0967    // 
0968    // Type is mpl::int_<N> where N is one of:
0969    //
0970    // 0 : F is a pointer to a presumably null-terminated string.
0971    // 1 : F is a character-container such as a std::string.
0972    //
0973    // Other options such as F being a Functor are not supported without
0974    // SFINAE support.
0975    //
0976    typedef typename boost::mpl::if_<
0977       boost::is_pointer<F>,
0978       boost::mpl::int_<0>,
0979       boost::mpl::int_<1>
0980    >::type type;
0981 };
0982 
0983 #endif // BOOST_NO_SFINAE
0984 
0985 template <class Base, class Match>
0986 struct format_functor3
0987 {
0988    format_functor3(Base b) : func(b) {}
0989    template <class OutputIter>
0990    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f)
0991    {
0992       return boost::unwrap_ref(func)(m, i, f);
0993    }
0994    template <class OutputIter, class Traits>
0995    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
0996    {
0997       return (*this)(m, i, f);
0998    }
0999 private:
1000    Base func;
1001    format_functor3(const format_functor3&);
1002    format_functor3& operator=(const format_functor3&);
1003 };
1004 
1005 template <class Base, class Match>
1006 struct format_functor2
1007 {
1008    format_functor2(Base b) : func(b) {}
1009    template <class OutputIter>
1010    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
1011    {
1012       return boost::unwrap_ref(func)(m, i);
1013    }
1014    template <class OutputIter, class Traits>
1015    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
1016    {
1017       return (*this)(m, i, f);
1018    }
1019 private:
1020    Base func;
1021    format_functor2(const format_functor2&);
1022    format_functor2& operator=(const format_functor2&);
1023 };
1024 
1025 template <class Base, class Match>
1026 struct format_functor1
1027 {
1028    format_functor1(Base b) : func(b) {}
1029 
1030    template <class S, class OutputIter>
1031    OutputIter do_format_string(const S& s, OutputIter i)
1032    {
1033       return BOOST_REGEX_DETAIL_NS::copy(s.begin(), s.end(), i);
1034    }
1035    template <class S, class OutputIter>
1036    inline OutputIter do_format_string(const S* s, OutputIter i)
1037    {
1038       while(s && *s)
1039       {
1040          *i = *s;
1041          ++i;
1042          ++s;
1043       }
1044       return i;
1045    }
1046    template <class OutputIter>
1047    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
1048    {
1049       return do_format_string(boost::unwrap_ref(func)(m), i);
1050    }
1051    template <class OutputIter, class Traits>
1052    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
1053    {
1054       return (*this)(m, i, f);
1055    }
1056 private:
1057    Base func;
1058    format_functor1(const format_functor1&);
1059    format_functor1& operator=(const format_functor1&);
1060 };
1061 
1062 template <class charT, class Match, class Traits>
1063 struct format_functor_c_string
1064 {
1065    format_functor_c_string(const charT* ps) : func(ps) {}
1066 
1067    template <class OutputIter>
1068    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
1069    {
1070       //typedef typename Match::char_type char_type;
1071       const charT* end = func;
1072       while(*end) ++end;
1073       return regex_format_imp(i, m, func, end, f, t);
1074    }
1075 private:
1076    const charT* func;
1077    format_functor_c_string(const format_functor_c_string&);
1078    format_functor_c_string& operator=(const format_functor_c_string&);
1079 };
1080 
1081 template <class Container, class Match, class Traits>
1082 struct format_functor_container
1083 {
1084    format_functor_container(const Container& c) : func(c) {}
1085 
1086    template <class OutputIter>
1087    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
1088    {
1089       //typedef typename Match::char_type char_type;
1090       return BOOST_REGEX_DETAIL_NS::regex_format_imp(i, m, func.begin(), func.end(), f, t);
1091    }
1092 private:
1093    const Container& func;
1094    format_functor_container(const format_functor_container&);
1095    format_functor_container& operator=(const format_functor_container&);
1096 };
1097 
1098 template <class Func, class Match, class OutputIterator, class Traits = BOOST_REGEX_DETAIL_NS::trivial_format_traits<typename Match::char_type> >
1099 struct compute_functor_type
1100 {
1101    typedef typename format_traits<Func, Match, OutputIterator>::type tag;
1102    typedef typename boost::remove_cv< typename boost::remove_pointer<Func>::type>::type maybe_char_type;
1103 
1104    typedef typename mpl::if_<
1105       ::boost::is_same<tag, mpl::int_<0> >, format_functor_c_string<maybe_char_type, Match, Traits>,
1106       typename mpl::if_<
1107          ::boost::is_same<tag, mpl::int_<1> >, format_functor_container<Func, Match, Traits>,
1108          typename mpl::if_<
1109             ::boost::is_same<tag, mpl::int_<2> >, format_functor1<Func, Match>,
1110             typename mpl::if_<
1111                ::boost::is_same<tag, mpl::int_<3> >, format_functor2<Func, Match>, 
1112                format_functor3<Func, Match>
1113             >::type
1114          >::type
1115       >::type
1116    >::type type;
1117 };
1118 
1119 } // namespace BOOST_REGEX_DETAIL_NS
1120 
1121 template <class OutputIterator, class Iterator, class Allocator, class Functor>
1122 inline OutputIterator regex_format(OutputIterator out,
1123                           const match_results<Iterator, Allocator>& m,
1124                           Functor fmt,
1125                           match_flag_type flags = format_all
1126                          )
1127 {
1128    return m.format(out, fmt, flags);
1129 }
1130 
1131 template <class Iterator, class Allocator, class Functor>
1132 inline std::basic_string<typename match_results<Iterator, Allocator>::char_type> regex_format(const match_results<Iterator, Allocator>& m, 
1133                                       Functor fmt, 
1134                                       match_flag_type flags = format_all)
1135 {
1136    return m.format(fmt, flags);
1137 }
1138 
1139 #ifdef BOOST_MSVC
1140 #pragma warning(push)
1141 #pragma warning(disable: 4103)
1142 #endif
1143 #ifdef BOOST_HAS_ABI_HEADERS
1144 #  include BOOST_ABI_SUFFIX
1145 #endif
1146 #ifdef BOOST_MSVC
1147 #pragma warning(pop)
1148 #endif
1149 
1150 } // namespace boost
1151 
1152 #endif  // BOOST_REGEX_FORMAT_HPP
1153 
1154 
1155 
1156 
1157 
1158