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