File indexing completed on 2025-01-18 09:51:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
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
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
0062
0063
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
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
0189
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;
0198 const Results& m_results;
0199 OutputIterator m_out;
0200 ForwardIter m_position;
0201 ForwardIter m_end;
0202 match_flag_type m_flags;
0203 output_state m_state;
0204 output_state m_restore_state;
0205 bool m_have_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
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;
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
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
0308
0309
0310 BOOST_REGEX_ASSERT(*m_position == '$');
0311
0312
0313
0314 if(++m_position == m_end)
0315 {
0316 --m_position;
0317 put(*m_position);
0318 ++m_position;
0319 return;
0320 }
0321
0322
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
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
0368 {
0369 std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
0370
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
0375 if(!handle_perl_verb(have_brace))
0376 {
0377
0378 m_position = --save_position;
0379 put(*m_position);
0380 ++m_position;
0381 }
0382 break;
0383 }
0384
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
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
0515 if(++m_position == m_end)
0516 {
0517 put(static_cast<char_type>('\\'));
0518 return;
0519 }
0520
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
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
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
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
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
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
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
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
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
0695 put(static_cast<char_type>('?'));
0696 return;
0697 }
0698
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
0710 put(static_cast<char_type>('?'));
0711 return;
0712 }
0713
0714
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
0723 ++m_position;
0724
0725 output_state saved_state = m_state;
0726 m_state = output_none;
0727
0728 format_until_scope_end();
0729
0730 m_state = saved_state;
0731 }
0732 }
0733 else
0734 {
0735
0736 output_state saved_state = m_state;
0737 m_state = output_none;
0738
0739 m_have_conditional = true;
0740 format_all();
0741 m_have_conditional = false;
0742
0743 m_state = saved_state;
0744 if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
0745 {
0746
0747 ++m_position;
0748
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
0770
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
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
0938
0939
0940
0941
0942
0943
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
0956
0957
0958 BOOST_STATIC_ASSERT( boost::is_class<F>::value && !has_const_iterator<F>::value ? (type::value > 1) : true);
0959 };
0960
0961 #else
0962
0963 template <class F, class M, class O>
0964 struct format_traits
0965 {
0966 public:
0967
0968
0969
0970
0971
0972
0973
0974
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
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 )
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 )
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
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
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 }
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 }
1151
1152 #endif
1153
1154
1155
1156
1157
1158