File indexing completed on 2025-01-18 09:53:53
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
0016 #define BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
0017
0018
0019 #if defined(_MSC_VER)
0020 # pragma once
0021 #endif
0022
0023 #include <map>
0024 #include <string>
0025 #include <vector>
0026 #include <utility>
0027 #include <iterator>
0028 #include <typeinfo>
0029 #include <algorithm>
0030 #include <boost/config.hpp>
0031 #include <boost/assert.hpp>
0032 #include <boost/integer.hpp>
0033 #include <boost/mpl/if.hpp>
0034 #include <boost/mpl/not.hpp>
0035 #include <boost/mpl/size_t.hpp>
0036 #include <boost/mpl/assert.hpp>
0037 #include <boost/intrusive_ptr.hpp>
0038 #include <boost/throw_exception.hpp>
0039 #include <boost/iterator_adaptors.hpp>
0040 #include <boost/utility/enable_if.hpp>
0041 #include <boost/detail/workaround.hpp>
0042 #include <boost/numeric/conversion/converter.hpp>
0043 #include <boost/optional.hpp>
0044 #include <boost/range/end.hpp>
0045 #include <boost/range/begin.hpp>
0046 #include <boost/range/as_literal.hpp>
0047 #include <boost/range/const_iterator.hpp>
0048 #include <boost/type_traits/is_function.hpp>
0049 #if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
0050 # include <boost/iterator/filter_iterator.hpp>
0051 #endif
0052 #include <boost/xpressive/regex_constants.hpp>
0053 #include <boost/xpressive/detail/detail_fwd.hpp>
0054 #include <boost/xpressive/detail/core/regex_impl.hpp>
0055 #include <boost/xpressive/detail/core/sub_match_vector.hpp>
0056 #include <boost/xpressive/detail/utility/sequence_stack.hpp>
0057 #include <boost/xpressive/detail/core/results_cache.hpp>
0058 #include <boost/xpressive/detail/utility/literals.hpp>
0059 #include <boost/xpressive/detail/utility/algorithm.hpp>
0060 #include <boost/xpressive/detail/utility/counted_base.hpp>
0061
0062 #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
0063 # include <boost/proto/proto_fwd.hpp>
0064 # include <boost/proto/traits.hpp>
0065 #endif
0066
0067 namespace boost { namespace xpressive { namespace detail
0068 {
0069
0070
0071
0072
0073 struct type_info_less
0074 {
0075 bool operator()(std::type_info const *left, std::type_info const *right) const
0076 {
0077 return 0 != left->before(*right);
0078 }
0079 };
0080
0081
0082
0083
0084 struct ActionArgBinding
0085 : proto::assign<proto::terminal<action_arg<proto::_, proto::_> >, proto::terminal<proto::_> >
0086 {
0087 };
0088
0089
0090
0091
0092 template<typename BidiIter>
0093 struct results_extras
0094 : counted_base<results_extras<BidiIter> >
0095 {
0096 sequence_stack<sub_match_impl<BidiIter> > sub_match_stack_;
0097 results_cache<BidiIter> results_cache_;
0098 };
0099
0100
0101
0102
0103 struct char_overflow_handler_
0104 {
0105 void operator ()(numeric::range_check_result result) const
0106 {
0107 if(numeric::cInRange != result)
0108 {
0109 BOOST_THROW_EXCEPTION(
0110 regex_error(
0111 regex_constants::error_escape
0112 , "character escape too large to fit in target character type"
0113 )
0114 );
0115 }
0116 }
0117 };
0118
0119
0120
0121
0122 enum transform_op { op_none = 0, op_upper = 1, op_lower = 2 };
0123 enum transform_scope { scope_next = 0, scope_rest = 1 };
0124
0125
0126
0127
0128 template<typename OutputIterator, typename Char>
0129 struct case_converting_iterator
0130 {
0131 typedef std::output_iterator_tag iterator_category;
0132 typedef Char value_type;
0133 typedef void difference_type;
0134 typedef void pointer;
0135 typedef case_converting_iterator<OutputIterator, Char> reference;
0136
0137 case_converting_iterator(OutputIterator const &out, traits<Char> const *tr)
0138 : out_(out)
0139 , traits_(tr)
0140 , next_(op_none)
0141 , rest_(op_none)
0142 {}
0143
0144 OutputIterator base() const
0145 {
0146 return this->out_;
0147 }
0148
0149 case_converting_iterator &operator ++()
0150 {
0151 ++this->out_;
0152 this->next_ = op_none;
0153 return *this;
0154 }
0155
0156 case_converting_iterator operator ++(int)
0157 {
0158 case_converting_iterator tmp(*this);
0159 ++*this;
0160 return tmp;
0161 }
0162
0163 case_converting_iterator &operator *()
0164 {
0165 return *this;
0166 }
0167
0168 friend bool set_transform(case_converting_iterator &iter, transform_op trans, transform_scope scope)
0169 {
0170 BOOST_ASSERT(scope == scope_next || scope == scope_rest);
0171 if(scope == scope_next)
0172 iter.next_ = trans;
0173 else
0174 iter.rest_ = trans;
0175 return true;
0176 }
0177
0178 case_converting_iterator &operator =(Char ch)
0179 {
0180 switch(this->next_ ? this->next_ : this->rest_)
0181 {
0182 case op_lower:
0183 ch = this->traits_->tolower(ch);
0184 break;
0185
0186 case op_upper:
0187 ch = this->traits_->toupper(ch);
0188 break;
0189
0190 default:;
0191 }
0192
0193 *this->out_ = ch;
0194 return *this;
0195 }
0196
0197 private:
0198 OutputIterator out_;
0199 traits<Char> const *traits_;
0200 transform_op next_, rest_;
0201 };
0202
0203 template<typename Iterator>
0204 inline bool set_transform(Iterator &, transform_op, transform_scope)
0205 {
0206 return false;
0207 }
0208
0209
0210
0211
0212 template<typename Char>
0213 struct noop_output_iterator
0214 {
0215 typedef std::output_iterator_tag iterator_category;
0216 typedef Char value_type;
0217 typedef void difference_type;
0218 typedef void pointer;
0219 typedef noop_output_iterator<Char> reference;
0220
0221 noop_output_iterator &operator ++()
0222 {
0223 return *this;
0224 }
0225
0226 noop_output_iterator &operator ++(int)
0227 {
0228 return *this;
0229 }
0230
0231 noop_output_iterator &operator *()
0232 {
0233 return *this;
0234 }
0235
0236 noop_output_iterator &operator =(Char const &)
0237 {
0238 return *this;
0239 }
0240 };
0241
0242 struct any_type { any_type(...); };
0243 typedef char no_type;
0244 typedef char (&unary_type)[2];
0245 typedef char (&binary_type)[3];
0246 typedef char (&ternary_type)[4];
0247
0248 no_type check_is_formatter(unary_type, binary_type, ternary_type);
0249
0250 template<typename T>
0251 unary_type check_is_formatter(T const &, binary_type, ternary_type);
0252
0253 template<typename T>
0254 binary_type check_is_formatter(unary_type, T const &, ternary_type);
0255
0256 template<typename T, typename U>
0257 binary_type check_is_formatter(T const &, U const &, ternary_type);
0258
0259 template<typename T>
0260 ternary_type check_is_formatter(unary_type, binary_type, T const &);
0261
0262 template<typename T, typename U>
0263 ternary_type check_is_formatter(T const &, binary_type, U const &);
0264
0265 template<typename T, typename U>
0266 ternary_type check_is_formatter(unary_type, T const &, U const &);
0267
0268 template<typename T, typename U, typename V>
0269 ternary_type check_is_formatter(T const &, U const &, V const &);
0270
0271 struct unary_binary_ternary
0272 {
0273 typedef unary_type (*unary_fun)(any_type);
0274 typedef binary_type (*binary_fun)(any_type, any_type);
0275 typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
0276 operator unary_fun();
0277 operator binary_fun();
0278 operator ternary_fun();
0279 };
0280
0281 template<typename Formatter, bool IsFunction = is_function<Formatter>::value>
0282 struct formatter_wrapper
0283 : Formatter
0284 , unary_binary_ternary
0285 {
0286 formatter_wrapper();
0287 };
0288
0289 template<typename Formatter>
0290 struct formatter_wrapper<Formatter, true>
0291 : unary_binary_ternary
0292 {
0293 operator Formatter *();
0294 };
0295
0296 template<typename Formatter>
0297 struct formatter_wrapper<Formatter *, false>
0298 : unary_binary_ternary
0299 {
0300 operator Formatter *();
0301 };
0302
0303 template<typename Formatter, typename What, typename Out, typename Void = void>
0304 struct formatter_arity
0305 {
0306 static formatter_wrapper<Formatter> &formatter;
0307 static What &what;
0308 static Out &out;
0309 BOOST_STATIC_CONSTANT(
0310 std::size_t
0311 , value = sizeof(
0312 check_is_formatter(
0313 formatter(what)
0314 , formatter(what, out)
0315 , formatter(what, out, regex_constants::format_default)
0316 )
0317 ) - 1
0318 );
0319 typedef mpl::size_t<value> type;
0320 };
0321
0322 template<typename Formatter, typename What, typename Out>
0323 struct formatter_arity<Formatter, What, Out, typename Formatter::proto_is_expr_>
0324 : mpl::size_t<4>
0325 {};
0326
0327 template<typename T>
0328 struct is_char_ptr
0329 : mpl::false_
0330 {};
0331
0332 template<typename T>
0333 struct is_char_ptr<T *>
0334 : mpl::not_<is_function<T> >
0335 {};
0336
0337 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0338
0339 template<typename T>
0340 typename mpl::if_<is_function<T>, T *, T const &>::type
0341 as_callable(T const &t)
0342 {
0343 return t;
0344 }
0345 #endif
0346
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361 template<typename BidiIter>
0362 struct match_results
0363 {
0364 private:
0365
0366
0367 struct dummy { int i_; };
0368 typedef int dummy::*bool_type;
0369
0370 public:
0371 typedef typename iterator_value<BidiIter>::type char_type;
0372 typedef typename detail::string_type<char_type>::type string_type;
0373 typedef std::size_t size_type;
0374 typedef sub_match<BidiIter> value_type;
0375 typedef typename iterator_difference<BidiIter>::type difference_type;
0376 typedef value_type const &reference;
0377 typedef value_type const &const_reference;
0378
0379 typedef typename detail::sub_match_vector<BidiIter>::iterator iterator;
0380 typedef typename detail::sub_match_vector<BidiIter>::const_iterator const_iterator;
0381 typedef typename detail::nested_results<BidiIter> nested_results_type;
0382
0383
0384
0385
0386
0387 match_results()
0388 : regex_id_(0)
0389 , sub_matches_()
0390 , base_()
0391 , prefix_()
0392 , suffix_()
0393 , nested_results_()
0394 , extras_ptr_()
0395 , traits_()
0396 , args_()
0397 , named_marks_()
0398 {
0399 }
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411 match_results(match_results<BidiIter> const &that)
0412 : regex_id_(that.regex_id_)
0413 , sub_matches_()
0414 , base_()
0415 , prefix_()
0416 , suffix_()
0417 , nested_results_()
0418 , extras_ptr_()
0419 , traits_()
0420 , args_(that.args_)
0421 , named_marks_(that.named_marks_)
0422 {
0423 if(that)
0424 {
0425 extras_type &extras = this->get_extras_();
0426 std::size_t size = that.sub_matches_.size();
0427 detail::sub_match_impl<BidiIter> *sub_matches = extras.sub_match_stack_.push_sequence(size, detail::sub_match_impl<BidiIter>(*that.base_), detail::fill);
0428 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size, that.sub_matches_);
0429
0430 this->base_ = that.base_;
0431 this->prefix_ = that.prefix_;
0432 this->suffix_ = that.suffix_;
0433
0434 this->nested_results_ = that.nested_results_;
0435 this->traits_ = that.traits_;
0436 }
0437 }
0438
0439 ~match_results()
0440 {
0441 }
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453 match_results<BidiIter> &operator =(match_results<BidiIter> const &that)
0454 {
0455 match_results<BidiIter>(that).swap(*this);
0456 return *this;
0457 }
0458
0459
0460
0461
0462 size_type size() const
0463 {
0464 return this->sub_matches_.size();
0465 }
0466
0467
0468
0469 bool empty() const
0470 {
0471 return 0 == this->size();
0472 }
0473
0474
0475
0476 difference_type length(size_type sub = 0) const
0477 {
0478 return this->sub_matches_[ sub ].length();
0479 }
0480
0481
0482
0483
0484 difference_type position(size_type sub = 0) const
0485 {
0486 return this->sub_matches_[ sub ].matched ? std::distance(*this->base_, this->sub_matches_[ sub ].first) : -1;
0487 }
0488
0489
0490
0491 string_type str(size_type sub = 0) const
0492 {
0493 return this->sub_matches_[ sub ].str();
0494 }
0495
0496
0497
0498
0499
0500
0501 template<typename Sub>
0502 const_reference operator [](Sub const &sub) const
0503 {
0504 return this->at_(sub);
0505 }
0506
0507
0508
0509
0510
0511 const_reference prefix() const
0512 {
0513 return this->prefix_ ? *this->prefix_ : this->sub_matches_[this->sub_matches_.size()];
0514 }
0515
0516
0517
0518
0519
0520 const_reference suffix() const
0521 {
0522 return this->suffix_ ? *this->suffix_ : this->sub_matches_[this->sub_matches_.size()];
0523 }
0524
0525
0526
0527
0528 const_iterator begin() const
0529 {
0530 return this->sub_matches_.begin();
0531 }
0532
0533
0534
0535
0536 const_iterator end() const
0537 {
0538 return this->sub_matches_.end();
0539 }
0540
0541
0542
0543 operator bool_type() const
0544 {
0545 return (!this->empty() && this->sub_matches_[ 0 ].matched) ? &dummy::i_ : 0;
0546 }
0547
0548
0549
0550 bool operator !() const
0551 {
0552 return this->empty() || !this->sub_matches_[ 0 ].matched;
0553 }
0554
0555
0556
0557 regex_id_type regex_id() const
0558 {
0559 return this->regex_id_;
0560 }
0561
0562
0563
0564 nested_results_type const &nested_results() const
0565 {
0566 return this->nested_results_;
0567 }
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585 template<typename Format, typename OutputIterator>
0586 OutputIterator format
0587 (
0588 OutputIterator out
0589 , Format const &fmt
0590 , regex_constants::match_flag_type flags = regex_constants::format_default
0591 , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
0592 ) const
0593 {
0594
0595 typedef
0596 typename detail::formatter_arity<
0597 Format
0598 , match_results<BidiIter>
0599 , OutputIterator
0600 >::type
0601 arity;
0602
0603 return this->format_(out, fmt, flags, arity());
0604 }
0605
0606
0607
0608 template<typename OutputIterator>
0609 OutputIterator format
0610 (
0611 OutputIterator out
0612 , char_type const *fmt
0613 , regex_constants::match_flag_type flags = regex_constants::format_default
0614 ) const
0615 {
0616 return this->format_(out, boost::as_literal(fmt), flags, mpl::size_t<0>());
0617 }
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636 template<typename Format, typename OutputIterator>
0637 string_type format
0638 (
0639 Format const &fmt
0640 , regex_constants::match_flag_type flags = regex_constants::format_default
0641 , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
0642 ) const
0643 {
0644 string_type result;
0645 this->format(std::back_inserter(result), fmt, flags);
0646 return result;
0647 }
0648
0649
0650
0651 string_type format
0652 (
0653 char_type const *fmt
0654 , regex_constants::match_flag_type flags = regex_constants::format_default
0655 ) const
0656 {
0657 string_type result;
0658 this->format(std::back_inserter(result), fmt, flags);
0659 return result;
0660 }
0661
0662
0663
0664
0665
0666
0667 void swap(match_results<BidiIter> &that)
0668 {
0669 using std::swap;
0670 swap(this->regex_id_, that.regex_id_);
0671 this->sub_matches_.swap(that.sub_matches_);
0672 this->base_.swap(that.base_);
0673 this->prefix_.swap(that.prefix_);
0674 this->suffix_.swap(that.suffix_);
0675 this->nested_results_.swap(that.nested_results_);
0676 this->extras_ptr_.swap(that.extras_ptr_);
0677 this->traits_.swap(that.traits_);
0678 this->args_.swap(that.args_);
0679 }
0680
0681
0682
0683 template<typename Arg>
0684 match_results<BidiIter> &let(Arg const &arg)
0685 {
0686 typedef typename proto::result_of::left<Arg>::type left_type;
0687 typedef typename proto::result_of::right<Arg>::type right_type;
0688 typedef typename proto::result_of::value<left_type>::type arg_left_type;
0689 typedef typename proto::result_of::value<right_type>::type arg_right_type;
0690 BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
0691 BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
0692 this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
0693 return *this;
0694 }
0695
0696
0697
0698 match_results<BidiIter> const &operator ()(regex_id_type regex_id, size_type index = 0) const
0699 {
0700
0701 static match_results<BidiIter> const s_null;
0702
0703 regex_id_filter_predicate<BidiIter> pred(regex_id);
0704 typename nested_results_type::const_iterator
0705 begin = this->nested_results_.begin()
0706 , end = this->nested_results_.end()
0707 , cur = detail::find_nth_if(begin, end, index, pred);
0708
0709 return (cur == end) ? s_null : *cur;
0710 }
0711
0712
0713
0714 match_results<BidiIter> const &operator ()(basic_regex<BidiIter> const &rex, std::size_t index = 0) const
0715 {
0716 return (*this)(rex.regex_id(), index);
0717 }
0718
0719 private:
0720
0721 friend struct detail::core_access<BidiIter>;
0722 typedef detail::results_extras<BidiIter> extras_type;
0723
0724
0725
0726 void init_
0727 (
0728 regex_id_type regex_id
0729 , intrusive_ptr<detail::traits<char_type> const> const &tr
0730 , detail::sub_match_impl<BidiIter> *sub_matches
0731 , size_type size
0732 , std::vector<detail::named_mark<char_type> > const &named_marks
0733 )
0734 {
0735 this->traits_ = tr;
0736 this->regex_id_ = regex_id;
0737 this->named_marks_ = named_marks;
0738 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size);
0739 }
0740
0741
0742
0743 extras_type &get_extras_()
0744 {
0745 if(!this->extras_ptr_)
0746 {
0747 this->extras_ptr_ = new extras_type;
0748 }
0749
0750 return *this->extras_ptr_;
0751 }
0752
0753
0754
0755 void set_prefix_suffix_(BidiIter begin, BidiIter end)
0756 {
0757 this->base_ = begin;
0758 this->prefix_ = sub_match<BidiIter>(begin, this->sub_matches_[ 0 ].first, begin != this->sub_matches_[ 0 ].first);
0759 this->suffix_ = sub_match<BidiIter>(this->sub_matches_[ 0 ].second, end, this->sub_matches_[ 0 ].second != end);
0760
0761 typename nested_results_type::iterator ibegin = this->nested_results_.begin();
0762 typename nested_results_type::iterator iend = this->nested_results_.end();
0763 for( ; ibegin != iend; ++ibegin )
0764 {
0765 ibegin->set_prefix_suffix_(begin, end);
0766 }
0767 }
0768
0769
0770
0771 void reset_()
0772 {
0773 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
0774 }
0775
0776
0777
0778 void set_base_(BidiIter base)
0779 {
0780 this->base_ = base;
0781
0782 typename nested_results_type::iterator ibegin = this->nested_results_.begin();
0783 typename nested_results_type::iterator iend = this->nested_results_.end();
0784 for( ; ibegin != iend; ++ibegin )
0785 {
0786 ibegin->set_base_(base);
0787 }
0788 }
0789
0790
0791
0792 const_reference at_(size_type sub) const
0793 {
0794 return this->sub_matches_[ sub ];
0795 }
0796
0797
0798
0799 const_reference at_(detail::basic_mark_tag const &mark) const
0800 {
0801 return this->sub_matches_[ detail::get_mark_number(mark) ];
0802 }
0803
0804
0805
0806 const_reference at_(char_type const *name) const
0807 {
0808 for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
0809 {
0810 if(this->named_marks_[i].name_ == name)
0811 {
0812 return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ];
0813 }
0814 }
0815 BOOST_THROW_EXCEPTION(
0816 regex_error(regex_constants::error_badmark, "invalid named back-reference")
0817 );
0818
0819
0820 return this->sub_matches_[this->sub_matches_.size()];
0821 }
0822
0823
0824
0825 const_reference at_(string_type const &name) const
0826 {
0827 return (*this)[name.c_str()];
0828 }
0829
0830
0831
0832 template<typename OutputIterator, typename ForwardRange>
0833 OutputIterator format2_(OutputIterator out, ForwardRange const &result) const
0834 {
0835 return std::copy(boost::begin(result), boost::end(result), out);
0836 }
0837
0838
0839
0840 template<typename OutputIterator, typename Char>
0841 OutputIterator format2_(OutputIterator out, Char const *const &result) const
0842 {
0843 Char const *tmp = result;
0844 BOOST_ASSERT(0 != tmp);
0845 for(; 0 != *tmp; ++tmp, ++out)
0846 {
0847 *out = *tmp;
0848 }
0849 return out;
0850 }
0851
0852
0853
0854 template<typename OutputIterator, typename ForwardRange>
0855 OutputIterator format_
0856 (
0857 OutputIterator out
0858 , ForwardRange const &format
0859 , regex_constants::match_flag_type flags
0860 , mpl::size_t<0>
0861 ) const
0862 {
0863 typedef typename range_const_iterator<ForwardRange>::type iterator;
0864 iterator cur = boost::begin(format), end = boost::end(format);
0865
0866 if(0 != (regex_constants::format_literal & flags))
0867 {
0868 return std::copy(cur, end, out);
0869 }
0870 else if(0 != (regex_constants::format_perl & flags))
0871 {
0872 return this->format_perl_(cur, end, out);
0873 }
0874 else if(0 != (regex_constants::format_sed & flags))
0875 {
0876 return this->format_sed_(cur, end, out);
0877 }
0878 else if(0 != (regex_constants::format_all & flags))
0879 {
0880 return this->format_all_(cur, end, out);
0881 }
0882
0883 return this->format_ecma_262_(cur, end, out);
0884 }
0885
0886
0887
0888 template<typename OutputIterator, typename Callable1>
0889 OutputIterator format_
0890 (
0891 OutputIterator out
0892 , Callable1 const &format
0893 , regex_constants::match_flag_type
0894 , mpl::size_t<1>
0895 ) const
0896 {
0897 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0898 return this->format2_(out, detail::as_callable(format)(*this));
0899 #else
0900 return this->format2_(out, format(*this));
0901 #endif
0902 }
0903
0904
0905
0906 template<typename OutputIterator, typename Callable2>
0907 OutputIterator format_
0908 (
0909 OutputIterator out
0910 , Callable2 const &format
0911 , regex_constants::match_flag_type
0912 , mpl::size_t<2>
0913 ) const
0914 {
0915 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0916 return detail::as_callable(format)(*this, out);
0917 #else
0918 return format(*this, out);
0919 #endif
0920 }
0921
0922
0923
0924 template<typename OutputIterator, typename Callable3>
0925 OutputIterator format_
0926 (
0927 OutputIterator out
0928 , Callable3 const &format
0929 , regex_constants::match_flag_type flags
0930 , mpl::size_t<3>
0931 ) const
0932 {
0933 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
0934 return detail::as_callable(format)(*this, out, flags);
0935 #else
0936 return format(*this, out, flags);
0937 #endif
0938 }
0939
0940
0941
0942 template<typename OutputIterator, typename Expr>
0943 OutputIterator format_
0944 (
0945 OutputIterator out
0946 , Expr const &format
0947 , regex_constants::match_flag_type
0948 , mpl::size_t<4>
0949 ) const
0950 {
0951
0952
0953 typedef typename mpl::if_c<true, detail::ReplaceAlgo, OutputIterator>::type ReplaceAlgo;
0954 return this->format2_(out, ReplaceAlgo()(format, 0, *this));
0955 }
0956
0957
0958
0959 template<typename ForwardIterator, typename OutputIterator>
0960 OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
0961 {
0962 while(cur != end)
0963 {
0964 switch(*cur)
0965 {
0966 case BOOST_XPR_CHAR_(char_type, '$'):
0967 out = this->format_backref_(++cur, end, out);
0968 break;
0969
0970 default:
0971 *out++ = *cur++;
0972 break;
0973 }
0974 }
0975
0976 return out;
0977 }
0978
0979
0980
0981 template<typename ForwardIterator, typename OutputIterator>
0982 OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
0983 {
0984 while(cur != end)
0985 {
0986 switch(*cur)
0987 {
0988 case BOOST_XPR_CHAR_(char_type, '&'):
0989 ++cur;
0990 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
0991 break;
0992
0993 case BOOST_XPR_CHAR_(char_type, '\\'):
0994 out = this->format_escape_(++cur, end, out);
0995 break;
0996
0997 default:
0998 *out++ = *cur++;
0999 break;
1000 }
1001 }
1002
1003 return out;
1004 }
1005
1006
1007
1008 template<typename ForwardIterator, typename OutputIterator>
1009 OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
1010 {
1011 detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
1012
1013 while(cur != end)
1014 {
1015 switch(*cur)
1016 {
1017 case BOOST_XPR_CHAR_(char_type, '$'):
1018 iout = this->format_backref_(++cur, end, iout);
1019 break;
1020
1021 case BOOST_XPR_CHAR_(char_type, '\\'):
1022 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
1023 {
1024 iout = this->format_named_backref_(++cur, end, iout);
1025 }
1026 else
1027 {
1028 iout = this->format_escape_(cur, end, iout);
1029 }
1030 break;
1031
1032 default:
1033 *iout++ = *cur++;
1034 break;
1035 }
1036 }
1037
1038 return iout.base();
1039 }
1040
1041
1042
1043 template<typename ForwardIterator, typename OutputIterator>
1044 OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
1045 {
1046 detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
1047 iout = this->format_all_impl_(cur, end, iout);
1048 BOOST_XPR_ENSURE_(cur == end
1049 , regex_constants::error_paren, "unbalanced parentheses in format string");
1050 return iout.base();
1051 }
1052
1053
1054
1055 template<typename ForwardIterator, typename OutputIterator>
1056 OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
1057 {
1058 int max = 0, sub = 0;
1059 detail::noop_output_iterator<char_type> noop;
1060
1061 while(cur != end)
1062 {
1063 switch(*cur)
1064 {
1065 case BOOST_XPR_CHAR_(char_type, '$'):
1066 out = this->format_backref_(++cur, end, out);
1067 break;
1068
1069 case BOOST_XPR_CHAR_(char_type, '\\'):
1070 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
1071 {
1072 out = this->format_named_backref_(++cur, end, out);
1073 }
1074 else
1075 {
1076 out = this->format_escape_(cur, end, out);
1077 }
1078 break;
1079
1080 case BOOST_XPR_CHAR_(char_type, '('):
1081 out = this->format_all_impl_(++cur, end, out);
1082 BOOST_XPR_ENSURE_(BOOST_XPR_CHAR_(char_type, ')') == *(cur-1)
1083 , regex_constants::error_paren, "unbalanced parentheses in format string");
1084 break;
1085
1086 case BOOST_XPR_CHAR_(char_type, '?'):
1087 BOOST_XPR_ENSURE_(++cur != end
1088 , regex_constants::error_subreg, "malformed conditional in format string");
1089 max = static_cast<int>(this->size() - 1);
1090 sub = detail::toi(cur, end, *this->traits_, 10, max);
1091 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
1092 if(this->sub_matches_[ sub ].matched)
1093 {
1094 out = this->format_all_impl_(cur, end, out, true);
1095 if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
1096 this->format_all_impl_(cur, end, noop);
1097 }
1098 else
1099 {
1100 this->format_all_impl_(cur, end, noop, true);
1101 if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
1102 out = this->format_all_impl_(cur, end, out);
1103 }
1104 return out;
1105
1106 case BOOST_XPR_CHAR_(char_type, ':'):
1107 if(metacolon)
1108 {
1109 BOOST_FALLTHROUGH;
1110 case BOOST_XPR_CHAR_(char_type, ')'):
1111 ++cur;
1112 return out;
1113 }
1114 BOOST_FALLTHROUGH;
1115
1116 default:
1117 *out++ = *cur++;
1118 break;
1119 }
1120 }
1121
1122 return out;
1123 }
1124
1125
1126
1127 template<typename ForwardIterator, typename OutputIterator>
1128 OutputIterator format_backref_
1129 (
1130 ForwardIterator &cur
1131 , ForwardIterator end
1132 , OutputIterator out
1133 ) const
1134 {
1135 if(cur == end)
1136 {
1137 *out++ = BOOST_XPR_CHAR_(char_type, '$');
1138 }
1139 else if(BOOST_XPR_CHAR_(char_type, '$') == *cur)
1140 {
1141 *out++ = *cur++;
1142 }
1143 else if(BOOST_XPR_CHAR_(char_type, '&') == *cur)
1144 {
1145 ++cur;
1146 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
1147 }
1148 else if(BOOST_XPR_CHAR_(char_type, '`') == *cur)
1149 {
1150 ++cur;
1151 out = std::copy(this->prefix().first, this->prefix().second, out);
1152 }
1153 else if(BOOST_XPR_CHAR_(char_type, '\'') == *cur)
1154 {
1155 ++cur;
1156 out = std::copy(this->suffix().first, this->suffix().second, out);
1157 }
1158 else if(-1 != this->traits_->value(*cur, 10))
1159 {
1160 int max = static_cast<int>(this->size() - 1);
1161 int sub = detail::toi(cur, end, *this->traits_, 10, max);
1162 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
1163 if(this->sub_matches_[ sub ].matched)
1164 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
1165 }
1166 else
1167 {
1168 *out++ = BOOST_XPR_CHAR_(char_type, '$');
1169 *out++ = *cur++;
1170 }
1171
1172 return out;
1173 }
1174
1175
1176
1177 template<typename ForwardIterator, typename OutputIterator>
1178 OutputIterator format_escape_
1179 (
1180 ForwardIterator &cur
1181 , ForwardIterator end
1182 , OutputIterator out
1183 ) const
1184 {
1185 using namespace regex_constants;
1186 ForwardIterator tmp;
1187
1188 typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
1189 BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
1190 typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
1191 numeric::converter<int, uchar_t, converstion_traits, detail::char_overflow_handler_> converter;
1192
1193 if(cur == end)
1194 {
1195 *out++ = BOOST_XPR_CHAR_(char_type, '\\');
1196 return out;
1197 }
1198
1199 char_type ch = *cur++;
1200 switch(ch)
1201 {
1202 case BOOST_XPR_CHAR_(char_type, 'a'):
1203 *out++ = BOOST_XPR_CHAR_(char_type, '\a');
1204 break;
1205
1206 case BOOST_XPR_CHAR_(char_type, 'e'):
1207 *out++ = converter(27);
1208 break;
1209
1210 case BOOST_XPR_CHAR_(char_type, 'f'):
1211 *out++ = BOOST_XPR_CHAR_(char_type, '\f');
1212 break;
1213
1214 case BOOST_XPR_CHAR_(char_type, 'n'):
1215 *out++ = BOOST_XPR_CHAR_(char_type, '\n');
1216 break;
1217
1218 case BOOST_XPR_CHAR_(char_type, 'r'):
1219 *out++ = BOOST_XPR_CHAR_(char_type, '\r');
1220 break;
1221
1222 case BOOST_XPR_CHAR_(char_type, 't'):
1223 *out++ = BOOST_XPR_CHAR_(char_type, '\t');
1224 break;
1225
1226 case BOOST_XPR_CHAR_(char_type, 'v'):
1227 *out++ = BOOST_XPR_CHAR_(char_type, '\v');
1228 break;
1229
1230 case BOOST_XPR_CHAR_(char_type, 'x'):
1231 BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
1232 if(BOOST_XPR_CHAR_(char_type, '{') == *cur)
1233 {
1234 BOOST_XPR_ENSURE_(++cur != end, error_escape, "unexpected end of format found");
1235 tmp = cur;
1236 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xffff));
1237 BOOST_XPR_ENSURE_(4 == std::distance(tmp, cur) && cur != end && BOOST_XPR_CHAR_(char_type, '}') == *cur++
1238 , error_escape, "invalid hex escape : must be \\x { HexDigit HexDigit HexDigit HexDigit }");
1239 }
1240 else
1241 {
1242 tmp = cur;
1243 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xff));
1244 BOOST_XPR_ENSURE_(2 == std::distance(tmp, cur), error_escape
1245 , "invalid hex escape : must be \\x HexDigit HexDigit");
1246 }
1247 break;
1248
1249 case BOOST_XPR_CHAR_(char_type, 'c'):
1250 BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
1251 BOOST_XPR_ENSURE_
1252 (
1253 this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *cur)
1254 || this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *cur)
1255 , error_escape
1256 , "invalid escape control letter; must be one of a-z or A-Z"
1257 );
1258
1259 *out++ = converter(*cur % 32);
1260 ++cur;
1261 break;
1262
1263 case BOOST_XPR_CHAR_(char_type, 'l'):
1264 if(!set_transform(out, detail::op_lower, detail::scope_next))
1265 {
1266 *out++ = BOOST_XPR_CHAR_(char_type, 'l');
1267 }
1268 break;
1269
1270 case BOOST_XPR_CHAR_(char_type, 'L'):
1271 if(!set_transform(out, detail::op_lower, detail::scope_rest))
1272 {
1273 *out++ = BOOST_XPR_CHAR_(char_type, 'L');
1274 }
1275 break;
1276
1277 case BOOST_XPR_CHAR_(char_type, 'u'):
1278 if(!set_transform(out, detail::op_upper, detail::scope_next))
1279 {
1280 *out++ = BOOST_XPR_CHAR_(char_type, 'u');
1281 }
1282 break;
1283
1284 case BOOST_XPR_CHAR_(char_type, 'U'):
1285 if(!set_transform(out, detail::op_upper, detail::scope_rest))
1286 {
1287 *out++ = BOOST_XPR_CHAR_(char_type, 'U');
1288 }
1289 break;
1290
1291 case BOOST_XPR_CHAR_(char_type, 'E'):
1292 if(!set_transform(out, detail::op_none, detail::scope_rest))
1293 {
1294 *out++ = BOOST_XPR_CHAR_(char_type, 'E');
1295 }
1296 break;
1297
1298 default:
1299
1300 if(0 < this->traits_->value(ch, 10))
1301 {
1302 int sub = this->traits_->value(ch, 10);
1303 if(this->sub_matches_[ sub ].matched)
1304 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
1305 }
1306 else
1307 {
1308 *out++ = ch;
1309 }
1310 break;
1311 }
1312
1313 return out;
1314 }
1315
1316
1317
1318 template<typename ForwardIterator, typename OutputIterator>
1319 OutputIterator format_named_backref_
1320 (
1321 ForwardIterator &cur
1322 , ForwardIterator end
1323 , OutputIterator out
1324 ) const
1325 {
1326 using namespace regex_constants;
1327 BOOST_XPR_ENSURE_(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
1328 , error_badmark, "invalid named back-reference");
1329 ForwardIterator begin = cur;
1330 for(; cur != end && BOOST_XPR_CHAR_(char_type, '>') != *cur; ++cur)
1331 {}
1332 BOOST_XPR_ENSURE_(cur != begin && cur != end && BOOST_XPR_CHAR_(char_type, '>') == *cur
1333 , error_badmark, "invalid named back-reference");
1334
1335 string_type name(begin, cur++);
1336 for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
1337 {
1338 if(this->named_marks_[i].name_ == name)
1339 {
1340 std::size_t sub = this->named_marks_[i].mark_nbr_;
1341 return std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
1342 }
1343 }
1344
1345 BOOST_THROW_EXCEPTION(regex_error(error_badmark, "invalid named back-reference"));
1346
1347 return out;
1348 }
1349
1350 regex_id_type regex_id_;
1351 detail::sub_match_vector<BidiIter> sub_matches_;
1352 boost::optional<BidiIter> base_;
1353 boost::optional<sub_match<BidiIter> > prefix_;
1354 boost::optional<sub_match<BidiIter> > suffix_;
1355 nested_results_type nested_results_;
1356 intrusive_ptr<extras_type> extras_ptr_;
1357 intrusive_ptr<detail::traits<char_type> const> traits_;
1358 detail::action_args_type args_;
1359 std::vector<detail::named_mark<char_type> > named_marks_;
1360 };
1361
1362
1363
1364
1365 template<typename BidiIter>
1366 struct regex_id_filter_predicate
1367 {
1368 typedef match_results<BidiIter> argument_type;
1369 typedef bool result_type;
1370
1371 regex_id_filter_predicate(regex_id_type regex_id)
1372 : regex_id_(regex_id)
1373 {
1374 }
1375
1376 bool operator ()(match_results<BidiIter> const &res) const
1377 {
1378 return this->regex_id_ == res.regex_id();
1379 }
1380
1381 private:
1382
1383 regex_id_type regex_id_;
1384 };
1385
1386 }}
1387
1388 #ifdef BOOST_HAS_CONCEPTS
1389
1390 namespace std
1391 {
1392 template<typename Iter_, typename Char_>
1393 concept_map OutputIterator<
1394 boost::xpressive::detail::case_converting_iterator<Iter_, Char_>
1395 , Char_
1396 >
1397 {};
1398
1399 template<typename Char_>
1400 concept_map OutputIterator<
1401 boost::xpressive::detail::noop_output_iterator<Char_>
1402 , Char_
1403 >
1404 {};
1405 }
1406 #endif
1407
1408 #endif