]> git.lyx.org Git - lyx.git/blob - boost/boost/regex/v4/regex_format.hpp
update boost to 1.43: remove obsolete files, update .cpp
[lyx.git] / boost / boost / regex / v4 / regex_format.hpp
1 /*
2  *
3  * Copyright (c) 1998-2009 John Maddock
4  * Copyright 2008 Eric Niebler. 
5  *
6  * Use, modification and distribution are subject to the 
7  * Boost Software License, Version 1.0. (See accompanying file 
8  * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9  *
10  */
11
12  /*
13   *   LOCATION:    see http://www.boost.org for most recent version.
14   *   FILE         regex_format.hpp
15   *   VERSION      see <boost/version.hpp>
16   *   DESCRIPTION: Provides formatting output routines for search and replace
17   *                operations.  Note this is an internal header file included
18   *                by regex.hpp, do not include on its own.
19   */
20
21 #ifndef BOOST_REGEX_FORMAT_HPP
22 #define BOOST_REGEX_FORMAT_HPP
23
24 #include <boost/type_traits/is_pointer.hpp>
25 #include <boost/type_traits/is_function.hpp>
26 #include <boost/type_traits/is_class.hpp>
27 #include <boost/type_traits/is_same.hpp>
28 #include <boost/type_traits/is_convertible.hpp>
29 #include <boost/type_traits/remove_pointer.hpp>
30 #include <boost/type_traits/remove_cv.hpp>
31 #include <boost/mpl/if.hpp>
32 #include <boost/mpl/and.hpp>
33 #include <boost/mpl/not.hpp>
34 #ifndef BOOST_NO_SFINAE
35 #include <boost/mpl/has_xxx.hpp>
36 #endif
37 #include <boost/ref.hpp>
38
39 namespace boost{
40
41 #ifdef BOOST_MSVC
42 #pragma warning(push)
43 #pragma warning(disable: 4103)
44 #endif
45 #ifdef BOOST_HAS_ABI_HEADERS
46 #  include BOOST_ABI_PREFIX
47 #endif
48 #ifdef BOOST_MSVC
49 #pragma warning(pop)
50 #endif
51
52 //
53 // Forward declaration:
54 //
55    template <class BidiIterator, class Allocator = BOOST_DEDUCED_TYPENAME std::vector<sub_match<BidiIterator> >::allocator_type >
56 class match_results;
57
58 namespace re_detail{
59
60 //
61 // struct trivial_format_traits:
62 // defines minimum localisation support for formatting
63 // in the case that the actual regex traits is unavailable.
64 //
65 template <class charT>
66 struct trivial_format_traits
67 {
68    typedef charT char_type;
69
70    static std::ptrdiff_t length(const charT* p)
71    {
72       return global_length(p);
73    }
74    static charT tolower(charT c)
75    {
76       return ::boost::re_detail::global_lower(c);
77    }
78    static charT toupper(charT c)
79    {
80       return ::boost::re_detail::global_upper(c);
81    }
82    static int value(const charT c, int radix)
83    {
84       int result = global_value(c);
85       return result >= radix ? -1 : result;
86    }
87    int toi(const charT*& p1, const charT* p2, int radix)const
88    {
89       return global_toi(p1, p2, radix, *this);
90    }
91 };
92
93 template <class OutputIterator, class Results, class traits, class ForwardIter>
94 class basic_regex_formatter
95 {
96 public:
97    typedef typename traits::char_type char_type;
98    basic_regex_formatter(OutputIterator o, const Results& r, const traits& t)
99       : m_traits(t), m_results(r), m_out(o), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {}
100    OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f);
101    OutputIterator format(ForwardIter p1, match_flag_type f)
102    {
103       return format(p1, p1 + m_traits.length(p1), f);
104    }
105 private:
106    typedef typename Results::value_type sub_match_type;
107    enum output_state
108    {
109       output_copy,
110       output_next_lower,
111       output_next_upper,
112       output_lower,
113       output_upper,
114       output_none
115    };
116
117    void put(char_type c);
118    void put(const sub_match_type& sub);
119    void format_all();
120    void format_perl();
121    void format_escape();
122    void format_conditional();
123    void format_until_scope_end();
124    bool handle_perl_verb(bool have_brace);
125
126    inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::false_&)
127    {
128       std::vector<char_type> v(i, j);
129       return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size())
130          : this->m_results.named_subexpression(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
131    }
132    inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::true_&)
133    {
134       return this->m_results.named_subexpression(i, j);
135    }
136    inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j)
137    {
138       typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
139       return get_named_sub(i, j, tag_type());
140    }
141    inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::false_&)
142    {
143       std::vector<char_type> v(i, j);
144       return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size())
145          : this->m_results.named_subexpression_index(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
146    }
147    inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::true_&)
148    {
149       return this->m_results.named_subexpression_index(i, j);
150    }
151    inline int get_named_sub_index(ForwardIter i, ForwardIter j)
152    {
153       typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
154       return get_named_sub_index(i, j, tag_type());
155    }
156    inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::false_&)
157    {
158       if(i != j)
159       {
160          std::vector<char_type> v(i, j);
161          const char_type* start = &v[0];
162          const char_type* pos = start;
163          int r = m_traits.toi(pos, &v[0] + v.size(), base);
164          std::advance(i, pos - start);
165          return r;
166       }
167       return -1;
168    }
169    inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::true_&)
170    {
171       return m_traits.toi(i, j, base);
172    }
173    inline int toi(ForwardIter& i, ForwardIter j, int base)
174    {
175       typedef typename boost::is_convertible<ForwardIter, const char_type*&>::type tag_type;
176       return toi(i, j, base, tag_type());
177    }
178
179    const traits&    m_traits;       // the traits class for localised formatting operations
180    const Results&   m_results;     // the match_results being used.
181    OutputIterator   m_out;         // where to send output.
182    ForwardIter      m_position;  // format string, current position
183    ForwardIter      m_end;       // format string end
184    match_flag_type  m_flags;      // format flags to use
185    output_state     m_state;      // what to do with the next character
186    output_state     m_restore_state;  // what state to restore to.
187    bool             m_have_conditional; // we are parsing a conditional
188 private:
189    basic_regex_formatter(const basic_regex_formatter&);
190    basic_regex_formatter& operator=(const basic_regex_formatter&);
191 };
192
193 template <class OutputIterator, class Results, class traits, class ForwardIter>
194 OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format(ForwardIter p1, ForwardIter p2, match_flag_type f)
195 {
196    m_position = p1;
197    m_end = p2;
198    m_flags = f;
199    format_all();
200    return m_out;
201 }
202
203 template <class OutputIterator, class Results, class traits, class ForwardIter>
204 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all()
205 {
206    // over and over:
207    while(m_position != m_end)
208    {
209       switch(*m_position)
210       {
211       case '&':
212          if(m_flags & ::boost::regex_constants::format_sed)
213          {
214             ++m_position;
215             put(m_results[0]);
216             break;
217          }
218          put(*m_position++);
219          break;
220       case '\\':
221          format_escape();
222          break;
223       case '(':
224          if(m_flags & boost::regex_constants::format_all)
225          {
226             ++m_position;
227             bool have_conditional = m_have_conditional;
228             m_have_conditional = false;
229             format_until_scope_end();
230             m_have_conditional = have_conditional;
231             if(m_position == m_end)
232                return;
233             BOOST_ASSERT(*m_position == static_cast<char_type>(')'));
234             ++m_position;  // skip the closing ')'
235             break;
236          }
237          put(*m_position);
238          ++m_position;
239          break;
240       case ')':
241          if(m_flags & boost::regex_constants::format_all)
242          {
243             return;
244          }
245          put(*m_position);
246          ++m_position;
247          break;
248       case ':':
249          if((m_flags & boost::regex_constants::format_all) && m_have_conditional)
250          {
251             return;
252          }
253          put(*m_position);
254          ++m_position;
255          break;
256       case '?':
257          if(m_flags & boost::regex_constants::format_all)
258          {
259             ++m_position;
260             format_conditional();
261             break;
262          }
263          put(*m_position);
264          ++m_position;
265          break;
266       case '$':
267          if((m_flags & format_sed) == 0)
268          {
269             format_perl();
270             break;
271          }
272          // fall through, not a special character:
273       default:
274          put(*m_position);
275          ++m_position;
276          break;
277       }
278    }
279 }
280
281 template <class OutputIterator, class Results, class traits, class ForwardIter>
282 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_perl()
283 {
284    //
285    // On entry *m_position points to a '$' character
286    // output the information that goes with it:
287    //
288    BOOST_ASSERT(*m_position == '$');
289    //
290    // see if this is a trailing '$':
291    //
292    if(++m_position == m_end)
293    {
294       --m_position;
295       put(*m_position);
296       ++m_position;
297       return;
298    }
299    //
300    // OK find out what kind it is:
301    //
302    bool have_brace = false;
303    ForwardIter save_position = m_position;
304    switch(*m_position)
305    {
306    case '&':
307       ++m_position;
308       put(this->m_results[0]);
309       break;
310    case '`':
311       ++m_position;
312       put(this->m_results.prefix());
313       break;
314    case '\'':
315       ++m_position;
316       put(this->m_results.suffix());
317       break;
318    case '$':
319       put(*m_position++);
320       break;
321    case '+':
322       if((++m_position != m_end) && (*m_position == '{'))
323       {
324          ForwardIter base = ++m_position;
325          while((m_position != m_end) && (*m_position != '}')) ++m_position;
326          if(m_position != m_end)
327          {
328             // Named sub-expression:
329             put(get_named_sub(base, m_position));
330             ++m_position;
331             break;
332          }
333          else
334          {
335             m_position = --base;
336          }
337       }
338       put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]);
339       break;
340    case '{':
341       have_brace = true;
342       ++m_position;
343       // fall through....
344    default:
345       // see if we have a number:
346       {
347          std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
348          //len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
349          int v = this->toi(m_position, m_position + len, 10);
350          if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}'))))
351          {
352             // Look for a Perl-5.10 verb:
353             if(!handle_perl_verb(have_brace))
354             {
355                // leave the $ as is, and carry on:
356                m_position = --save_position;
357                put(*m_position);
358                ++m_position;
359             }
360             break;
361          }
362          // otherwise output sub v:
363          put(this->m_results[v]);
364          if(have_brace)
365             ++m_position;
366       }
367    }
368 }
369
370 template <class OutputIterator, class Results, class traits, class ForwardIter>
371 bool basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::handle_perl_verb(bool have_brace)
372 {
373    // 
374    // We may have a capitalised string containing a Perl action:
375    //
376    static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' };
377    static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' };
378    static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' };
379    static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' };
380    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' };
381    static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' };
382
383    if(m_position == m_end)
384       return false;
385    if(have_brace && (*m_position == '^'))
386       ++m_position;
387
388    std::ptrdiff_t max_len = m_end - m_position;
389
390    if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH))
391    {
392       m_position += 5;
393       if(have_brace)
394       {
395          if((m_position != m_end) && (*m_position == '}'))
396             ++m_position;
397          else
398          {
399             m_position -= 5;
400             return false;
401          }
402       }
403       put(this->m_results[0]);
404       return true;
405    }
406    if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH))
407    {
408       m_position += 8;
409       if(have_brace)
410       {
411          if((m_position != m_end) && (*m_position == '}'))
412             ++m_position;
413          else
414          {
415             m_position -= 8;
416             return false;
417          }
418       }
419       put(this->m_results.prefix());
420       return true;
421    }
422    if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH))
423    {
424       m_position += 9;
425       if(have_brace)
426       {
427          if((m_position != m_end) && (*m_position == '}'))
428             ++m_position;
429          else
430          {
431             m_position -= 9;
432             return false;
433          }
434       }
435       put(this->m_results.suffix());
436       return true;
437    }
438    if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH))
439    {
440       m_position += 16;
441       if(have_brace)
442       {
443          if((m_position != m_end) && (*m_position == '}'))
444             ++m_position;
445          else
446          {
447             m_position -= 16;
448             return false;
449          }
450       }
451       put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]);
452       return true;
453    }
454    if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT))
455    {
456       m_position += 20;
457       if(have_brace)
458       {
459          if((m_position != m_end) && (*m_position == '}'))
460             ++m_position;
461          else
462          {
463             m_position -= 20;
464             return false;
465          }
466       }
467       put(this->m_results.get_last_closed_paren());
468       return true;
469    }
470    if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT))
471    {
472       m_position += 2;
473       if(have_brace)
474       {
475          if((m_position != m_end) && (*m_position == '}'))
476             ++m_position;
477          else
478          {
479             m_position -= 2;
480             return false;
481          }
482       }
483       put(this->m_results.get_last_closed_paren());
484       return true;
485    }
486    return false;
487 }
488
489 template <class OutputIterator, class Results, class traits, class ForwardIter>
490 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_escape()
491 {
492    // skip the escape and check for trailing escape:
493    if(++m_position == m_end)
494    {
495       put(static_cast<char_type>('\\'));
496       return;
497    }
498    // now switch on the escape type:
499    switch(*m_position)
500    {
501    case 'a':
502       put(static_cast<char_type>('\a'));
503       ++m_position;
504       break;
505    case 'f':
506       put(static_cast<char_type>('\f'));
507       ++m_position;
508       break;
509    case 'n':
510       put(static_cast<char_type>('\n'));
511       ++m_position;
512       break;
513    case 'r':
514       put(static_cast<char_type>('\r'));
515       ++m_position;
516       break;
517    case 't':
518       put(static_cast<char_type>('\t'));
519       ++m_position;
520       break;
521    case 'v':
522       put(static_cast<char_type>('\v'));
523       ++m_position;
524       break;
525    case 'x':
526       if(++m_position == m_end)
527       {
528          put(static_cast<char_type>('x'));
529          return;
530       }
531       // maybe have \x{ddd}
532       if(*m_position == static_cast<char_type>('{'))
533       {
534          ++m_position;
535          int val = this->toi(m_position, m_end, 16);
536          if(val < 0)
537          {
538             // invalid value treat everything as literals:
539             put(static_cast<char_type>('x'));
540             put(static_cast<char_type>('{'));
541             return;
542          }
543          if((m_position == m_end) || (*m_position != static_cast<char_type>('}')))
544          {
545             --m_position;
546             while(*m_position != static_cast<char_type>('\\'))
547                --m_position;
548             ++m_position;
549             put(*m_position++);
550             return;
551          }
552          ++m_position;
553          put(static_cast<char_type>(val));
554          return;
555       }
556       else
557       {
558          std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
559          len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
560          int val = this->toi(m_position, m_position + len, 16);
561          if(val < 0)
562          {
563             --m_position;
564             put(*m_position++);
565             return;
566          }
567          put(static_cast<char_type>(val));
568       }
569       break;
570    case 'c':
571       if(++m_position == m_end)
572       {
573          --m_position;
574          put(*m_position++);
575          return;
576       }
577       put(static_cast<char_type>(*m_position++ % 32));
578       break;
579    case 'e':
580       put(static_cast<char_type>(27));
581       ++m_position;
582       break;
583    default:
584       // see if we have a perl specific escape:
585       if((m_flags & boost::regex_constants::format_sed) == 0)
586       {
587          bool breakout = false;
588          switch(*m_position)
589          {
590          case 'l':
591             ++m_position;
592             m_restore_state = m_state;
593             m_state = output_next_lower;
594             breakout = true;
595             break;
596          case 'L':
597             ++m_position;
598             m_state = output_lower;
599             breakout = true;
600             break;
601          case 'u':
602             ++m_position;
603             m_restore_state = m_state;
604             m_state = output_next_upper;
605             breakout = true;
606             break;
607          case 'U':
608             ++m_position;
609             m_state = output_upper;
610             breakout = true;
611             break;
612          case 'E':
613             ++m_position;
614             m_state = output_copy;
615             breakout = true;
616             break;
617          }
618          if(breakout)
619             break;
620       }
621       // see if we have a \n sed style backreference:
622       std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
623       len = (std::min)(static_cast<std::ptrdiff_t>(1), len);
624       int v = this->toi(m_position, m_position+len, 10);
625       if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed)))
626       {
627          put(m_results[v]);
628          break;
629       }
630       else if(v == 0)
631       {
632          // octal ecape sequence:
633          --m_position;
634          len = ::boost::re_detail::distance(m_position, m_end);
635          len = (std::min)(static_cast<std::ptrdiff_t>(4), len);
636          v = this->toi(m_position, m_position + len, 8);
637          BOOST_ASSERT(v >= 0);
638          put(static_cast<char_type>(v));
639          break;
640       }
641       // Otherwise output the character "as is":
642       put(*m_position++);
643       break;
644    }
645 }
646
647 template <class OutputIterator, class Results, class traits, class ForwardIter>
648 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional()
649 {
650    if(m_position == m_end)
651    {
652       // oops trailing '?':
653       put(static_cast<char_type>('?'));
654       return;
655    }
656    int v;
657    if(*m_position == '{')
658    {
659       ForwardIter base = m_position;
660       ++m_position;
661       v = this->toi(m_position, m_end, 10);
662       if(v < 0)
663       {
664          // Try a named subexpression:
665          while((m_position != m_end) && (*m_position != '}'))
666             ++m_position;
667          v = this->get_named_sub_index(base + 1, m_position);
668       }
669       if((v < 0) || (*m_position != '}'))
670       {
671          m_position = base;
672          // oops trailing '?':
673          put(static_cast<char_type>('?'));
674          return;
675       }
676       // Skip trailing '}':
677       ++m_position;
678    }
679    else
680    {
681       std::ptrdiff_t len = ::boost::re_detail::distance(m_position, m_end);
682       len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
683       v = this->toi(m_position, m_position + len, 10);
684    }
685    if(v < 0)
686    {
687       // oops not a number:
688       put(static_cast<char_type>('?'));
689       return;
690    }
691
692    // output varies depending upon whether sub-expression v matched or not:
693    if(m_results[v].matched)
694    {
695       m_have_conditional = true;
696       format_all();
697       m_have_conditional = false;
698       if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
699       {
700          // skip the ':':
701          ++m_position;
702          // save output state, then turn it off:
703          output_state saved_state = m_state;
704          m_state = output_none;
705          // format the rest of this scope:
706          format_until_scope_end();
707          // restore output state:
708          m_state = saved_state;
709       }
710    }
711    else
712    {
713       // save output state, then turn it off:
714       output_state saved_state = m_state;
715       m_state = output_none;
716       // format until ':' or ')':
717       m_have_conditional = true;
718       format_all();
719       m_have_conditional = false;
720       // restore state:
721       m_state = saved_state;
722       if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
723       {
724          // skip the ':':
725          ++m_position;
726          // format the rest of this scope:
727          format_until_scope_end();
728       }
729    }
730 }
731
732 template <class OutputIterator, class Results, class traits, class ForwardIter>
733 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end()
734 {
735    do
736    {
737       format_all();
738       if((m_position == m_end) || (*m_position == static_cast<char_type>(')')))
739          return;
740       put(*m_position++);
741    }while(m_position != m_end);
742 }
743
744 template <class OutputIterator, class Results, class traits, class ForwardIter>
745 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(char_type c)
746 {
747    // write a single character to output
748    // according to which case translation mode we are in:
749    switch(this->m_state)
750    {
751    case output_none:
752       return;
753    case output_next_lower:
754       c = m_traits.tolower(c);
755       this->m_state = m_restore_state;
756       break;
757    case output_next_upper:
758       c = m_traits.toupper(c);
759       this->m_state = m_restore_state;
760       break;
761    case output_lower:
762       c = m_traits.tolower(c);
763       break;
764    case output_upper:
765       c = m_traits.toupper(c);
766       break;
767    default:
768       break;
769    }
770    *m_out = c;
771    ++m_out;
772 }
773
774 template <class OutputIterator, class Results, class traits, class ForwardIter>
775 void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(const sub_match_type& sub)
776 {
777    typedef typename sub_match_type::iterator iterator_type;
778    iterator_type i = sub.first;
779    while(i != sub.second)
780    {
781       put(*i);
782       ++i;
783    }
784 }
785
786 template <class S>
787 class string_out_iterator
788 #ifndef BOOST_NO_STD_ITERATOR
789    : public std::iterator<std::output_iterator_tag, typename S::value_type>
790 #endif
791 {
792    S* out;
793 public:
794    string_out_iterator(S& s) : out(&s) {}
795    string_out_iterator& operator++() { return *this; }
796    string_out_iterator& operator++(int) { return *this; }
797    string_out_iterator& operator*() { return *this; }
798    string_out_iterator& operator=(typename S::value_type v) 
799    { 
800       out->append(1, v); 
801       return *this; 
802    }
803
804 #ifdef BOOST_NO_STD_ITERATOR
805    typedef std::ptrdiff_t difference_type;
806    typedef typename S::value_type value_type;
807    typedef value_type* pointer;
808    typedef value_type& reference;
809    typedef std::output_iterator_tag iterator_category;
810 #endif
811 };
812
813 template <class OutputIterator, class Iterator, class Alloc, class ForwardIter, class traits>
814 OutputIterator regex_format_imp(OutputIterator out,
815                           const match_results<Iterator, Alloc>& m,
816                           ForwardIter p1, ForwardIter p2,
817                           match_flag_type flags,
818                           const traits& t
819                          )
820 {
821    if(flags & regex_constants::format_literal)
822    {
823       return re_detail::copy(p1, p2, out);
824    }
825
826    re_detail::basic_regex_formatter<
827       OutputIterator, 
828       match_results<Iterator, Alloc>, 
829       traits, ForwardIter> f(out, m, t);
830    return f.format(p1, p2, flags);
831 }
832
833 #ifndef BOOST_NO_SFINAE
834
835 BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
836
837 struct any_type { any_type(...); };
838 typedef char no_type;
839 typedef char (&unary_type)[2];
840 typedef char (&binary_type)[3];
841 typedef char (&ternary_type)[4];
842
843 no_type check_is_formatter(unary_type, binary_type, ternary_type);
844 template<typename T>
845 unary_type check_is_formatter(T const &, binary_type, ternary_type);
846 template<typename T>
847 binary_type check_is_formatter(unary_type, T const &, ternary_type);
848 template<typename T, typename U>
849 binary_type check_is_formatter(T const &, U const &, ternary_type);
850 template<typename T>
851 ternary_type check_is_formatter(unary_type, binary_type, T const &);
852 template<typename T, typename U>
853 ternary_type check_is_formatter(T const &, binary_type, U const &);
854 template<typename T, typename U>
855 ternary_type check_is_formatter(unary_type, T const &, U const &);
856 template<typename T, typename U, typename V>
857 ternary_type check_is_formatter(T const &, U const &, V const &);
858
859 struct unary_binary_ternary
860 {
861     typedef unary_type (*unary_fun)(any_type);
862     typedef binary_type (*binary_fun)(any_type, any_type);
863     typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
864     operator unary_fun();
865     operator binary_fun();
866     operator ternary_fun();
867 };
868
869 template<typename Formatter, bool IsFunction = boost::is_function<Formatter>::value>
870 struct formatter_wrapper
871   : Formatter
872   , unary_binary_ternary
873 {
874    formatter_wrapper(){}
875 };
876
877 template<typename Formatter>
878 struct formatter_wrapper<Formatter, true>
879   : unary_binary_ternary
880 {
881     operator Formatter *();
882 };
883
884 template<typename Formatter>
885 struct formatter_wrapper<Formatter *, false>
886   : unary_binary_ternary
887 {
888     operator Formatter *();
889 };
890
891 template <class F, class M, class O>
892 struct format_traits_imp
893 {
894 private:
895    //
896    // F must be a pointer, a function, or a class with a function call operator:
897    //
898    BOOST_STATIC_ASSERT((::boost::is_pointer<F>::value || ::boost::is_function<F>::value || ::boost::is_class<F>::value));
899    static formatter_wrapper<typename unwrap_reference<F>::type> f;
900    static M m;
901    static O out;
902    static boost::regex_constants::match_flag_type flags;
903 public:
904    BOOST_STATIC_CONSTANT(int, value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags))));
905 };
906
907 template <class F, class M, class O>
908 struct format_traits
909 {
910 public:
911    // 
912    // Type is mpl::int_<N> where N is one of:
913    //
914    // 0 : F is a pointer to a presumably null-terminated string.
915    // 1 : F is a character-container such as a std::string.
916    // 2 : F is a Unary Functor.
917    // 3 : F is a Binary Functor.
918    // 4 : F is a Ternary Functor.
919    //
920    typedef typename boost::mpl::if_<
921       boost::mpl::and_<boost::is_pointer<F>, boost::mpl::not_<boost::is_function<typename boost::remove_pointer<F>::type> > >,
922       boost::mpl::int_<0>,
923       typename boost::mpl::if_<
924          has_const_iterator<F>,
925          boost::mpl::int_<1>,
926          boost::mpl::int_<format_traits_imp<F, M, O>::value>
927       >::type
928    >::type type;
929    //
930    // This static assertion will fail if the functor passed does not accept
931    // the same type of arguments passed.
932    //
933    BOOST_STATIC_ASSERT( boost::is_class<F>::value && !has_const_iterator<F>::value ? (type::value > 1) : true);
934 };
935
936 #else // BOOST_NO_SFINAE
937
938 template <class F, class M, class O>
939 struct format_traits
940 {
941 public:
942    // 
943    // Type is mpl::int_<N> where N is one of:
944    //
945    // 0 : F is a pointer to a presumably null-terminated string.
946    // 1 : F is a character-container such as a std::string.
947    //
948    // Other options such as F being a Functor are not supported without
949    // SFINAE support.
950    //
951    typedef typename boost::mpl::if_<
952       boost::is_pointer<F>,
953       boost::mpl::int_<0>,
954       boost::mpl::int_<1>
955    >::type type;
956 };
957
958 #endif // BOOST_NO_SFINAE
959
960 template <class Base, class Match>
961 struct format_functor3
962 {
963    format_functor3(Base b) : func(b) {}
964    template <class OutputIter>
965    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f)
966    {
967       return boost::unwrap_ref(func)(m, i, f);
968    }
969    template <class OutputIter, class Traits>
970    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
971    {
972       return (*this)(m, i, f);
973    }
974 private:
975    Base func;
976    format_functor3(const format_functor3&);
977    format_functor3& operator=(const format_functor3&);
978 };
979
980 template <class Base, class Match>
981 struct format_functor2
982 {
983    format_functor2(Base b) : func(b) {}
984    template <class OutputIter>
985    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
986    {
987       return boost::unwrap_ref(func)(m, i);
988    }
989    template <class OutputIter, class Traits>
990    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
991    {
992       return (*this)(m, i, f);
993    }
994 private:
995    Base func;
996    format_functor2(const format_functor2&);
997    format_functor2& operator=(const format_functor2&);
998 };
999
1000 template <class Base, class Match>
1001 struct format_functor1
1002 {
1003    format_functor1(Base b) : func(b) {}
1004
1005    template <class S, class OutputIter>
1006    OutputIter do_format_string(const S& s, OutputIter i)
1007    {
1008       return re_detail::copy(s.begin(), s.end(), i);
1009    }
1010    template <class S, class OutputIter>
1011    inline OutputIter do_format_string(const S* s, OutputIter i)
1012    {
1013       while(s && *s)
1014       {
1015          *i = *s;
1016          ++i;
1017          ++s;
1018       }
1019       return i;
1020    }
1021    template <class OutputIter>
1022    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
1023    {
1024       return do_format_string(boost::unwrap_ref(func)(m), i);
1025    }
1026    template <class OutputIter, class Traits>
1027    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
1028    {
1029       return (*this)(m, i, f);
1030    }
1031 private:
1032    Base func;
1033    format_functor1(const format_functor1&);
1034    format_functor1& operator=(const format_functor1&);
1035 };
1036
1037 template <class charT, class Match, class Traits>
1038 struct format_functor_c_string
1039 {
1040    format_functor_c_string(const charT* ps) : func(ps) {}
1041
1042    template <class OutputIter>
1043    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
1044    {
1045       typedef typename Match::char_type char_type;
1046       const charT* end = func;
1047       while(*end) ++end;
1048       return regex_format_imp(i, m, func, end, f, t);
1049    }
1050 private:
1051    const charT* func;
1052    format_functor_c_string(const format_functor_c_string&);
1053    format_functor_c_string& operator=(const format_functor_c_string&);
1054 };
1055
1056 template <class Container, class Match, class Traits>
1057 struct format_functor_container
1058 {
1059    format_functor_container(const Container& c) : func(c) {}
1060
1061    template <class OutputIter>
1062    OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
1063    {
1064       typedef typename Match::char_type char_type;
1065       return re_detail::regex_format_imp(i, m, func.begin(), func.end(), f, t);
1066    }
1067 private:
1068    const Container& func;
1069    format_functor_container(const format_functor_container&);
1070    format_functor_container& operator=(const format_functor_container&);
1071 };
1072
1073 template <class Func, class Match, class OutputIterator, class Traits = re_detail::trivial_format_traits<typename Match::char_type> >
1074 struct compute_functor_type
1075 {
1076    typedef typename format_traits<Func, Match, OutputIterator>::type tag;
1077    typedef typename boost::remove_cv< typename boost::remove_pointer<Func>::type>::type maybe_char_type;
1078
1079    typedef typename mpl::if_<
1080       ::boost::is_same<tag, mpl::int_<0> >, format_functor_c_string<maybe_char_type, Match, Traits>,
1081       typename mpl::if_<
1082          ::boost::is_same<tag, mpl::int_<1> >, format_functor_container<Func, Match, Traits>,
1083          typename mpl::if_<
1084             ::boost::is_same<tag, mpl::int_<2> >, format_functor1<Func, Match>,
1085             typename mpl::if_<
1086                ::boost::is_same<tag, mpl::int_<3> >, format_functor2<Func, Match>, 
1087                format_functor3<Func, Match>
1088             >::type
1089          >::type
1090       >::type
1091    >::type type;
1092 };
1093
1094 } // namespace re_detail
1095
1096 template <class OutputIterator, class Iterator, class Allocator, class Functor>
1097 inline OutputIterator regex_format(OutputIterator out,
1098                           const match_results<Iterator, Allocator>& m,
1099                           Functor fmt,
1100                           match_flag_type flags = format_all
1101                          )
1102 {
1103    return m.format(out, fmt, flags);
1104 }
1105
1106 template <class Iterator, class Allocator, class Functor>
1107 inline std::basic_string<typename match_results<Iterator, Allocator>::char_type> regex_format(const match_results<Iterator, Allocator>& m, 
1108                                       Functor fmt, 
1109                                       match_flag_type flags = format_all)
1110 {
1111    return m.format(fmt, flags);
1112 }
1113
1114 #ifdef BOOST_MSVC
1115 #pragma warning(push)
1116 #pragma warning(disable: 4103)
1117 #endif
1118 #ifdef BOOST_HAS_ABI_HEADERS
1119 #  include BOOST_ABI_SUFFIX
1120 #endif
1121 #ifdef BOOST_MSVC
1122 #pragma warning(pop)
1123 #endif
1124
1125 } // namespace boost
1126
1127 #endif  // BOOST_REGEX_FORMAT_HPP
1128
1129
1130
1131
1132
1133