annotate DEPENDENCIES/generic/include/boost/xpressive/match_results.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 /// \file match_results.hpp
Chris@16 3 /// Contains the definition of the match_results type and associated helpers.
Chris@16 4 /// The match_results type holds the results of a regex_match() or
Chris@16 5 /// regex_search() operation.
Chris@16 6 //
Chris@16 7 // Copyright 2008 Eric Niebler. Distributed under the Boost
Chris@16 8 // Software License, Version 1.0. (See accompanying file
Chris@16 9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10 //
Chris@16 11 // Acknowledgements: Thanks to Markus Schoepflin for helping to track down
Chris@16 12 // a tricky formatting bug on HP Tru64, and to Steven Watanabe for suggesting
Chris@16 13 // the fix.
Chris@16 14
Chris@16 15 #ifndef BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
Chris@16 16 #define BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
Chris@16 17
Chris@16 18 // MS compatible compilers support #pragma once
Chris@101 19 #if defined(_MSC_VER)
Chris@16 20 # pragma once
Chris@16 21 #endif
Chris@16 22
Chris@16 23 #include <map>
Chris@16 24 #include <string>
Chris@16 25 #include <vector>
Chris@16 26 #include <utility>
Chris@16 27 #include <iterator>
Chris@16 28 #include <typeinfo>
Chris@16 29 #include <algorithm>
Chris@16 30 #include <boost/config.hpp>
Chris@16 31 #include <boost/assert.hpp>
Chris@16 32 #include <boost/integer.hpp>
Chris@16 33 #include <boost/mpl/if.hpp>
Chris@16 34 #include <boost/mpl/not.hpp>
Chris@16 35 #include <boost/mpl/size_t.hpp>
Chris@16 36 #include <boost/mpl/assert.hpp>
Chris@16 37 #include <boost/intrusive_ptr.hpp>
Chris@16 38 #include <boost/throw_exception.hpp>
Chris@16 39 #include <boost/iterator_adaptors.hpp>
Chris@16 40 #include <boost/utility/enable_if.hpp>
Chris@16 41 #include <boost/detail/workaround.hpp>
Chris@16 42 #include <boost/numeric/conversion/converter.hpp>
Chris@16 43 #include <boost/optional.hpp>
Chris@16 44 #include <boost/range/end.hpp>
Chris@16 45 #include <boost/range/begin.hpp>
Chris@16 46 #include <boost/range/as_literal.hpp>
Chris@16 47 #include <boost/range/const_iterator.hpp>
Chris@16 48 #include <boost/type_traits/is_function.hpp>
Chris@16 49 #if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
Chris@16 50 # include <boost/iterator/filter_iterator.hpp>
Chris@16 51 #endif
Chris@16 52 #include <boost/xpressive/regex_constants.hpp>
Chris@16 53 #include <boost/xpressive/detail/detail_fwd.hpp>
Chris@16 54 #include <boost/xpressive/detail/core/regex_impl.hpp>
Chris@16 55 #include <boost/xpressive/detail/core/sub_match_vector.hpp>
Chris@16 56 #include <boost/xpressive/detail/utility/sequence_stack.hpp>
Chris@16 57 #include <boost/xpressive/detail/core/results_cache.hpp>
Chris@16 58 #include <boost/xpressive/detail/utility/literals.hpp>
Chris@16 59 #include <boost/xpressive/detail/utility/algorithm.hpp>
Chris@16 60 #include <boost/xpressive/detail/utility/counted_base.hpp>
Chris@16 61 // Doxygen can't handle proto :-(
Chris@16 62 #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED
Chris@16 63 # include <boost/proto/proto_fwd.hpp>
Chris@16 64 # include <boost/proto/traits.hpp>
Chris@16 65 #endif
Chris@16 66
Chris@16 67 namespace boost { namespace xpressive { namespace detail
Chris@16 68 {
Chris@16 69
Chris@16 70 ///////////////////////////////////////////////////////////////////////////////
Chris@16 71 // type_info_less
Chris@16 72 //
Chris@16 73 struct type_info_less
Chris@16 74 {
Chris@16 75 bool operator()(std::type_info const *left, std::type_info const *right) const
Chris@16 76 {
Chris@16 77 return 0 != left->before(*right);
Chris@16 78 }
Chris@16 79 };
Chris@16 80
Chris@16 81 ///////////////////////////////////////////////////////////////////////////////
Chris@16 82 // ActionArgBinding
Chris@16 83 //
Chris@16 84 struct ActionArgBinding
Chris@16 85 : proto::assign<proto::terminal<action_arg<proto::_, proto::_> >, proto::terminal<proto::_> >
Chris@16 86 {
Chris@16 87 };
Chris@16 88
Chris@16 89 ///////////////////////////////////////////////////////////////////////////////
Chris@16 90 // results_extras
Chris@16 91 //
Chris@16 92 template<typename BidiIter>
Chris@16 93 struct results_extras
Chris@16 94 : counted_base<results_extras<BidiIter> >
Chris@16 95 {
Chris@16 96 sequence_stack<sub_match_impl<BidiIter> > sub_match_stack_;
Chris@16 97 results_cache<BidiIter> results_cache_;
Chris@16 98 };
Chris@16 99
Chris@16 100 ///////////////////////////////////////////////////////////////////////////////
Chris@16 101 // char_overflow_handler_
Chris@16 102 //
Chris@16 103 struct char_overflow_handler_
Chris@16 104 {
Chris@16 105 void operator ()(numeric::range_check_result result) const // throw(regex_error)
Chris@16 106 {
Chris@16 107 if(numeric::cInRange != result)
Chris@16 108 {
Chris@16 109 BOOST_THROW_EXCEPTION(
Chris@16 110 regex_error(
Chris@16 111 regex_constants::error_escape
Chris@16 112 , "character escape too large to fit in target character type"
Chris@16 113 )
Chris@16 114 );
Chris@16 115 }
Chris@16 116 }
Chris@16 117 };
Chris@16 118
Chris@16 119 ///////////////////////////////////////////////////////////////////////////////
Chris@16 120 // transform_op enum
Chris@16 121 //
Chris@16 122 enum transform_op { op_none = 0, op_upper = 1, op_lower = 2 };
Chris@16 123 enum transform_scope { scope_next = 0, scope_rest = 1 };
Chris@16 124
Chris@16 125 ///////////////////////////////////////////////////////////////////////////////
Chris@16 126 // case_converting_iterator
Chris@16 127 //
Chris@16 128 template<typename OutputIterator, typename Char>
Chris@16 129 struct case_converting_iterator
Chris@16 130 : std::iterator<std::output_iterator_tag, Char, void, void, case_converting_iterator<OutputIterator, Char> >
Chris@16 131 {
Chris@16 132 case_converting_iterator(OutputIterator const &out, traits<Char> const *tr)
Chris@16 133 : out_(out)
Chris@16 134 , traits_(tr)
Chris@16 135 , next_(op_none)
Chris@16 136 , rest_(op_none)
Chris@16 137 {}
Chris@16 138
Chris@16 139 OutputIterator base() const
Chris@16 140 {
Chris@16 141 return this->out_;
Chris@16 142 }
Chris@16 143
Chris@16 144 case_converting_iterator &operator ++()
Chris@16 145 {
Chris@16 146 ++this->out_;
Chris@16 147 this->next_ = op_none;
Chris@16 148 return *this;
Chris@16 149 }
Chris@16 150
Chris@16 151 case_converting_iterator operator ++(int)
Chris@16 152 {
Chris@16 153 case_converting_iterator tmp(*this);
Chris@16 154 ++*this;
Chris@16 155 return tmp;
Chris@16 156 }
Chris@16 157
Chris@16 158 case_converting_iterator &operator *()
Chris@16 159 {
Chris@16 160 return *this;
Chris@16 161 }
Chris@16 162
Chris@16 163 friend bool set_transform(case_converting_iterator &iter, transform_op trans, transform_scope scope)
Chris@16 164 {
Chris@16 165 BOOST_ASSERT(scope == scope_next || scope == scope_rest);
Chris@16 166 if(scope == scope_next)
Chris@16 167 iter.next_ = trans;
Chris@16 168 else
Chris@16 169 iter.rest_ = trans;
Chris@16 170 return true;
Chris@16 171 }
Chris@16 172
Chris@16 173 case_converting_iterator &operator =(Char ch)
Chris@16 174 {
Chris@16 175 switch(this->next_ ? this->next_ : this->rest_)
Chris@16 176 {
Chris@16 177 case op_lower:
Chris@16 178 ch = this->traits_->tolower(ch);
Chris@16 179 break;
Chris@16 180
Chris@16 181 case op_upper:
Chris@16 182 ch = this->traits_->toupper(ch);
Chris@16 183 break;
Chris@16 184
Chris@16 185 default:;
Chris@16 186 }
Chris@16 187
Chris@16 188 *this->out_ = ch;
Chris@16 189 return *this;
Chris@16 190 }
Chris@16 191
Chris@16 192 private:
Chris@16 193 OutputIterator out_;
Chris@16 194 traits<Char> const *traits_;
Chris@16 195 transform_op next_, rest_;
Chris@16 196 };
Chris@16 197
Chris@16 198 template<typename Iterator>
Chris@16 199 inline bool set_transform(Iterator &, transform_op, transform_scope)
Chris@16 200 {
Chris@16 201 return false;
Chris@16 202 }
Chris@16 203
Chris@16 204 ///////////////////////////////////////////////////////////////////////////////
Chris@16 205 // noop_output_iterator
Chris@16 206 //
Chris@16 207 template<typename Char>
Chris@16 208 struct noop_output_iterator
Chris@16 209 : std::iterator<std::output_iterator_tag, Char, void, void, noop_output_iterator<Char> >
Chris@16 210 {
Chris@16 211 noop_output_iterator &operator ++()
Chris@16 212 {
Chris@16 213 return *this;
Chris@16 214 }
Chris@16 215
Chris@16 216 noop_output_iterator &operator ++(int)
Chris@16 217 {
Chris@16 218 return *this;
Chris@16 219 }
Chris@16 220
Chris@16 221 noop_output_iterator &operator *()
Chris@16 222 {
Chris@16 223 return *this;
Chris@16 224 }
Chris@16 225
Chris@16 226 noop_output_iterator &operator =(Char const &)
Chris@16 227 {
Chris@16 228 return *this;
Chris@16 229 }
Chris@16 230 };
Chris@16 231
Chris@16 232 struct any_type { any_type(...); };
Chris@16 233 typedef char no_type;
Chris@16 234 typedef char (&unary_type)[2];
Chris@16 235 typedef char (&binary_type)[3];
Chris@16 236 typedef char (&ternary_type)[4];
Chris@16 237
Chris@16 238 no_type check_is_formatter(unary_type, binary_type, ternary_type);
Chris@16 239
Chris@16 240 template<typename T>
Chris@16 241 unary_type check_is_formatter(T const &, binary_type, ternary_type);
Chris@16 242
Chris@16 243 template<typename T>
Chris@16 244 binary_type check_is_formatter(unary_type, T const &, ternary_type);
Chris@16 245
Chris@16 246 template<typename T, typename U>
Chris@16 247 binary_type check_is_formatter(T const &, U const &, ternary_type);
Chris@16 248
Chris@16 249 template<typename T>
Chris@16 250 ternary_type check_is_formatter(unary_type, binary_type, T const &);
Chris@16 251
Chris@16 252 template<typename T, typename U>
Chris@16 253 ternary_type check_is_formatter(T const &, binary_type, U const &);
Chris@16 254
Chris@16 255 template<typename T, typename U>
Chris@16 256 ternary_type check_is_formatter(unary_type, T const &, U const &);
Chris@16 257
Chris@16 258 template<typename T, typename U, typename V>
Chris@16 259 ternary_type check_is_formatter(T const &, U const &, V const &);
Chris@16 260
Chris@16 261 struct unary_binary_ternary
Chris@16 262 {
Chris@16 263 typedef unary_type (*unary_fun)(any_type);
Chris@16 264 typedef binary_type (*binary_fun)(any_type, any_type);
Chris@16 265 typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
Chris@16 266 operator unary_fun();
Chris@16 267 operator binary_fun();
Chris@16 268 operator ternary_fun();
Chris@16 269 };
Chris@16 270
Chris@16 271 template<typename Formatter, bool IsFunction = is_function<Formatter>::value>
Chris@16 272 struct formatter_wrapper
Chris@16 273 : Formatter
Chris@16 274 , unary_binary_ternary
Chris@16 275 {
Chris@16 276 formatter_wrapper();
Chris@16 277 };
Chris@16 278
Chris@16 279 template<typename Formatter>
Chris@16 280 struct formatter_wrapper<Formatter, true>
Chris@16 281 : unary_binary_ternary
Chris@16 282 {
Chris@16 283 operator Formatter *();
Chris@16 284 };
Chris@16 285
Chris@16 286 template<typename Formatter>
Chris@16 287 struct formatter_wrapper<Formatter *, false>
Chris@16 288 : unary_binary_ternary
Chris@16 289 {
Chris@16 290 operator Formatter *();
Chris@16 291 };
Chris@16 292
Chris@16 293 template<typename Formatter, typename What, typename Out, typename Void = void>
Chris@16 294 struct formatter_arity
Chris@16 295 {
Chris@16 296 static formatter_wrapper<Formatter> &formatter;
Chris@16 297 static What &what;
Chris@16 298 static Out &out;
Chris@16 299 BOOST_STATIC_CONSTANT(
Chris@16 300 std::size_t
Chris@16 301 , value = sizeof(
Chris@16 302 check_is_formatter(
Chris@16 303 formatter(what)
Chris@16 304 , formatter(what, out)
Chris@16 305 , formatter(what, out, regex_constants::format_default)
Chris@16 306 )
Chris@16 307 ) - 1
Chris@16 308 );
Chris@16 309 typedef mpl::size_t<value> type;
Chris@16 310 };
Chris@16 311
Chris@16 312 template<typename Formatter, typename What, typename Out>
Chris@16 313 struct formatter_arity<Formatter, What, Out, typename Formatter::proto_is_expr_>
Chris@16 314 : mpl::size_t<4>
Chris@16 315 {};
Chris@16 316
Chris@16 317 template<typename T>
Chris@16 318 struct is_char_ptr
Chris@16 319 : mpl::false_
Chris@16 320 {};
Chris@16 321
Chris@16 322 template<typename T>
Chris@16 323 struct is_char_ptr<T *>
Chris@16 324 : mpl::not_<is_function<T> >
Chris@16 325 {};
Chris@16 326
Chris@16 327 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
Chris@16 328 // work around gcc-4.0.1 compiler bug wrt function references
Chris@16 329 template<typename T>
Chris@16 330 typename mpl::if_<is_function<T>, T *, T const &>::type
Chris@16 331 as_callable(T const &t)
Chris@16 332 {
Chris@16 333 return t;
Chris@16 334 }
Chris@16 335 #endif
Chris@16 336
Chris@16 337 } // detail
Chris@16 338
Chris@16 339 ///////////////////////////////////////////////////////////////////////////////
Chris@16 340 // match_results
Chris@16 341 /// \brief Class template match_results\<\> holds the results of a regex_match() or a
Chris@16 342 /// regex_search() as a collection of sub_match objects.
Chris@16 343 ///
Chris@16 344 /// Class template match_results\<\> denotes a collection of sequences representing the result of
Chris@16 345 /// a regular expression match. Storage for the collection is allocated and freed as necessary by
Chris@16 346 /// the member functions of class match_results\<\>.
Chris@16 347 ///
Chris@16 348 /// The class template match_results\<\> conforms to the requirements of a Sequence, as specified
Chris@16 349 /// in (lib.sequence.reqmts), except that only operations defined for const-qualified Sequences are
Chris@16 350 /// supported.
Chris@16 351 template<typename BidiIter>
Chris@16 352 struct match_results
Chris@16 353 {
Chris@16 354 private:
Chris@16 355 /// INTERNAL ONLY
Chris@16 356 ///
Chris@16 357 struct dummy { int i_; };
Chris@16 358 typedef int dummy::*bool_type;
Chris@16 359
Chris@16 360 public:
Chris@16 361 typedef typename iterator_value<BidiIter>::type char_type;
Chris@16 362 typedef typename detail::string_type<char_type>::type string_type;
Chris@16 363 typedef std::size_t size_type;
Chris@16 364 typedef sub_match<BidiIter> value_type;
Chris@16 365 typedef typename iterator_difference<BidiIter>::type difference_type;
Chris@16 366 typedef value_type const &reference;
Chris@16 367 typedef value_type const &const_reference;
Chris@16 368
Chris@16 369 typedef typename detail::sub_match_vector<BidiIter>::iterator iterator;
Chris@16 370 typedef typename detail::sub_match_vector<BidiIter>::const_iterator const_iterator;
Chris@16 371 typedef typename detail::nested_results<BidiIter> nested_results_type;
Chris@16 372
Chris@16 373 /// \post regex_id() == 0
Chris@16 374 /// \post size() == 0
Chris@16 375 /// \post empty() == true
Chris@16 376 /// \post str() == string_type()
Chris@16 377 match_results()
Chris@16 378 : regex_id_(0)
Chris@16 379 , sub_matches_()
Chris@16 380 , base_()
Chris@16 381 , prefix_()
Chris@16 382 , suffix_()
Chris@16 383 , nested_results_()
Chris@16 384 , extras_ptr_()
Chris@16 385 , traits_()
Chris@16 386 , args_()
Chris@16 387 , named_marks_()
Chris@16 388 {
Chris@16 389 }
Chris@16 390
Chris@16 391 /// \param that The match_results object to copy
Chris@16 392 /// \post regex_id() == that.regex_id().
Chris@16 393 /// \post size() == that.size().
Chris@16 394 /// \post empty() == that.empty().
Chris@16 395 /// \post str(n) == that.str(n) for all positive integers n \< that.size().
Chris@16 396 /// \post prefix() == that.prefix().
Chris@16 397 /// \post suffix() == that.suffix().
Chris@16 398 /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
Chris@16 399 /// \post length(n) == that.length(n) for all positive integers n \< that.size().
Chris@16 400 /// \post position(n) == that.position(n) for all positive integers n \< that.size().
Chris@16 401 match_results(match_results<BidiIter> const &that)
Chris@16 402 : regex_id_(that.regex_id_)
Chris@16 403 , sub_matches_()
Chris@16 404 , base_()
Chris@16 405 , prefix_()
Chris@16 406 , suffix_()
Chris@16 407 , nested_results_()
Chris@16 408 , extras_ptr_()
Chris@16 409 , traits_()
Chris@16 410 , args_(that.args_)
Chris@16 411 , named_marks_(that.named_marks_)
Chris@16 412 {
Chris@16 413 if(that)
Chris@16 414 {
Chris@16 415 extras_type &extras = this->get_extras_();
Chris@16 416 std::size_t size = that.sub_matches_.size();
Chris@16 417 detail::sub_match_impl<BidiIter> *sub_matches = extras.sub_match_stack_.push_sequence(size, detail::sub_match_impl<BidiIter>(*that.base_), detail::fill);
Chris@16 418 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size, that.sub_matches_);
Chris@16 419
Chris@16 420 this->base_ = that.base_;
Chris@16 421 this->prefix_ = that.prefix_;
Chris@16 422 this->suffix_ = that.suffix_;
Chris@16 423 // BUGBUG this doesn't share the extras::sequence_stack
Chris@16 424 this->nested_results_ = that.nested_results_;
Chris@16 425 this->traits_ = that.traits_;
Chris@16 426 }
Chris@16 427 }
Chris@16 428
Chris@16 429 ~match_results()
Chris@16 430 {
Chris@16 431 }
Chris@16 432
Chris@16 433 /// \param that The match_results object to copy.
Chris@16 434 /// \post regex_id() == that.regex_id().
Chris@16 435 /// \post size() == that.size().
Chris@16 436 /// \post empty() == that.empty().
Chris@16 437 /// \post str(n) == that.str(n) for all positive integers n \< that.size().
Chris@16 438 /// \post prefix() == that.prefix().
Chris@16 439 /// \post suffix() == that.suffix().
Chris@16 440 /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
Chris@16 441 /// \post length(n) == that.length(n) for all positive integers n \< that.size().
Chris@16 442 /// \post position(n) == that.position(n) for all positive integers n \< that.size().
Chris@16 443 match_results<BidiIter> &operator =(match_results<BidiIter> const &that)
Chris@16 444 {
Chris@16 445 match_results<BidiIter>(that).swap(*this);
Chris@16 446 return *this;
Chris@16 447 }
Chris@16 448
Chris@16 449 /// Returns one plus the number of marked sub-expressions in the regular
Chris@16 450 /// expression that was matched if *this represents the result of a
Chris@16 451 /// successful match. Otherwise returns 0.
Chris@16 452 size_type size() const
Chris@16 453 {
Chris@16 454 return this->sub_matches_.size();
Chris@16 455 }
Chris@16 456
Chris@16 457 /// Returns size() == 0.
Chris@16 458 ///
Chris@16 459 bool empty() const
Chris@16 460 {
Chris@16 461 return 0 == this->size();
Chris@16 462 }
Chris@16 463
Chris@16 464 /// Returns (*this)[sub].length().
Chris@16 465 ///
Chris@16 466 difference_type length(size_type sub = 0) const
Chris@16 467 {
Chris@16 468 return this->sub_matches_[ sub ].length();
Chris@16 469 }
Chris@16 470
Chris@16 471 /// If !(*this)[sub].matched then returns -1. Otherwise returns std::distance(base, (*this)[sub].first),
Chris@16 472 /// where base is the start iterator of the sequence that was searched. [Note - unless this is part
Chris@16 473 /// of a repeated search with a regex_iterator then base is the same as prefix().first - end note]
Chris@16 474 difference_type position(size_type sub = 0) const
Chris@16 475 {
Chris@16 476 return this->sub_matches_[ sub ].matched ? std::distance(*this->base_, this->sub_matches_[ sub ].first) : -1;
Chris@16 477 }
Chris@16 478
Chris@16 479 /// Returns (*this)[sub].str().
Chris@16 480 ///
Chris@16 481 string_type str(size_type sub = 0) const
Chris@16 482 {
Chris@16 483 return this->sub_matches_[ sub ].str();
Chris@16 484 }
Chris@16 485
Chris@16 486 /// Returns a reference to the sub_match object representing the sequence that
Chris@16 487 /// matched marked sub-expression sub. If sub == 0 then returns a reference to
Chris@16 488 /// a sub_match object representing the sequence that matched the whole regular
Chris@16 489 /// expression. If sub >= size() then returns a sub_match object representing an
Chris@16 490 /// unmatched sub-expression.
Chris@16 491 template<typename Sub>
Chris@16 492 const_reference operator [](Sub const &sub) const
Chris@16 493 {
Chris@16 494 return this->at_(sub);
Chris@16 495 }
Chris@16 496
Chris@16 497 /// Returns a reference to the sub_match object representing the character sequence from
Chris@16 498 /// the start of the string being matched/searched, to the start of the match found.
Chris@16 499 ///
Chris@16 500 /// \pre (*this)[0].matched is true
Chris@16 501 const_reference prefix() const
Chris@16 502 {
Chris@16 503 return this->prefix_ ? *this->prefix_ : this->sub_matches_[this->sub_matches_.size()];
Chris@16 504 }
Chris@16 505
Chris@16 506 /// Returns a reference to the sub_match object representing the character sequence from
Chris@16 507 /// the end of the match found to the end of the string being matched/searched.
Chris@16 508 ///
Chris@16 509 /// \pre (*this)[0].matched is true
Chris@16 510 const_reference suffix() const
Chris@16 511 {
Chris@16 512 return this->suffix_ ? *this->suffix_ : this->sub_matches_[this->sub_matches_.size()];
Chris@16 513 }
Chris@16 514
Chris@16 515 /// Returns a starting iterator that enumerates over all the marked sub-expression matches
Chris@16 516 /// stored in *this.
Chris@16 517 ///
Chris@16 518 const_iterator begin() const
Chris@16 519 {
Chris@16 520 return this->sub_matches_.begin();
Chris@16 521 }
Chris@16 522
Chris@16 523 /// Returns a terminating iterator that enumerates over all the marked sub-expression
Chris@16 524 /// matches stored in *this.
Chris@16 525 ///
Chris@16 526 const_iterator end() const
Chris@16 527 {
Chris@16 528 return this->sub_matches_.end();
Chris@16 529 }
Chris@16 530
Chris@16 531 /// Returns a true value if (*this)[0].matched, else returns a false value.
Chris@16 532 ///
Chris@16 533 operator bool_type() const
Chris@16 534 {
Chris@16 535 return (!this->empty() && this->sub_matches_[ 0 ].matched) ? &dummy::i_ : 0;
Chris@16 536 }
Chris@16 537
Chris@16 538 /// Returns true if empty() || !(*this)[0].matched, else returns false.
Chris@16 539 ///
Chris@16 540 bool operator !() const
Chris@16 541 {
Chris@16 542 return this->empty() || !this->sub_matches_[ 0 ].matched;
Chris@16 543 }
Chris@16 544
Chris@16 545 /// Returns the id of the basic_regex object most recently used with this match_results object.
Chris@16 546 ///
Chris@16 547 regex_id_type regex_id() const
Chris@16 548 {
Chris@16 549 return this->regex_id_;
Chris@16 550 }
Chris@16 551
Chris@16 552 /// Returns a Sequence of nested match_results elements.
Chris@16 553 ///
Chris@16 554 nested_results_type const &nested_results() const
Chris@16 555 {
Chris@16 556 return this->nested_results_;
Chris@16 557 }
Chris@16 558
Chris@16 559 /// If \c Format models \c ForwardRange or is a null-terminated string, this function
Chris@16 560 /// copies the character sequence in \c fmt to \c OutputIterator \c out. For each format
Chris@16 561 /// specifier or escape sequence in \c fmt, replace that sequence with either the character(s) it
Chris@16 562 /// represents, or the sequence within <tt>*this</tt> to which it refers. The bitmasks specified in flags
Chris@16 563 /// determines what format specifiers or escape sequences are recognized. By default, this is the
Chris@16 564 /// format used by ECMA-262, ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
Chris@16 565 ///
Chris@16 566 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
Chris@16 567 /// this function returns <tt>fmt(*this, out, flags)</tt>.
Chris@16 568 ///
Chris@16 569 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
Chris@16 570 /// returns <tt>fmt(*this, out)</tt>.
Chris@16 571 ///
Chris@16 572 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
Chris@16 573 /// returns <tt>std::copy(x.begin(), x.end(), out)</tt>, where \c x is the result of
Chris@16 574 /// calling <tt>fmt(*this)</tt>.
Chris@16 575 template<typename Format, typename OutputIterator>
Chris@16 576 OutputIterator format
Chris@16 577 (
Chris@16 578 OutputIterator out
Chris@16 579 , Format const &fmt
Chris@16 580 , regex_constants::match_flag_type flags = regex_constants::format_default
Chris@16 581 , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
Chris@16 582 ) const
Chris@16 583 {
Chris@16 584 // Is this a formatter object, or a format string?
Chris@16 585 typedef
Chris@16 586 typename detail::formatter_arity<
Chris@16 587 Format
Chris@16 588 , match_results<BidiIter>
Chris@16 589 , OutputIterator
Chris@16 590 >::type
Chris@16 591 arity;
Chris@16 592
Chris@16 593 return this->format_(out, fmt, flags, arity());
Chris@16 594 }
Chris@16 595
Chris@16 596 /// \overload
Chris@16 597 ///
Chris@16 598 template<typename OutputIterator>
Chris@16 599 OutputIterator format
Chris@16 600 (
Chris@16 601 OutputIterator out
Chris@16 602 , char_type const *fmt
Chris@16 603 , regex_constants::match_flag_type flags = regex_constants::format_default
Chris@16 604 ) const
Chris@16 605 {
Chris@16 606 return this->format_(out, boost::as_literal(fmt), flags, mpl::size_t<0>());
Chris@16 607 }
Chris@16 608
Chris@16 609 /// If \c Format models \c ForwardRange or is a null-terminated string, this function
Chris@16 610 /// returns a copy of the character sequence \c fmt. For each format specifier or escape sequence in \c fmt,
Chris@16 611 /// replace that sequence with either the character(s) it represents, or the sequence within
Chris@16 612 /// <tt>*this</tt> to which it refers. The bitmasks specified in \c flags determines what format specifiers
Chris@16 613 /// or escape sequences are recognized. By default this is the format used by ECMA-262,
Chris@16 614 /// ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
Chris@16 615 ///
Chris@16 616 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator, regex_constants::match_flag_type\></tt>,
Chris@16 617 /// this function returns a \c string_type object \c x populated by calling <tt>fmt(*this, out, flags)</tt>,
Chris@16 618 /// where \c out is a \c back_insert_iterator into \c x.
Chris@16 619 ///
Chris@16 620 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\>, OutputIterator\></tt>, this function
Chris@16 621 /// returns a \c string_type object \c x populated by calling <tt>fmt(*this, out)</tt>,
Chris@16 622 /// where \c out is a \c back_insert_iterator into \c x.
Chris@16 623 ///
Chris@16 624 /// Otherwise, if \c Format models <tt>Callable\<match_results\<BidiIter\> \></tt>, this function
Chris@16 625 /// returns <tt>fmt(*this)</tt>.
Chris@16 626 template<typename Format, typename OutputIterator>
Chris@16 627 string_type format
Chris@16 628 (
Chris@16 629 Format const &fmt
Chris@16 630 , regex_constants::match_flag_type flags = regex_constants::format_default
Chris@16 631 , typename disable_if<detail::is_char_ptr<Format> >::type * = 0
Chris@16 632 ) const
Chris@16 633 {
Chris@16 634 string_type result;
Chris@16 635 this->format(std::back_inserter(result), fmt, flags);
Chris@16 636 return result;
Chris@16 637 }
Chris@16 638
Chris@16 639 /// \overload
Chris@16 640 ///
Chris@16 641 string_type format
Chris@16 642 (
Chris@16 643 char_type const *fmt
Chris@16 644 , regex_constants::match_flag_type flags = regex_constants::format_default
Chris@16 645 ) const
Chris@16 646 {
Chris@16 647 string_type result;
Chris@16 648 this->format(std::back_inserter(result), fmt, flags);
Chris@16 649 return result;
Chris@16 650 }
Chris@16 651
Chris@16 652 /// Swaps the contents of two match_results objects. Guaranteed not to throw.
Chris@16 653 /// \param that The match_results object to swap with.
Chris@16 654 /// \post *this contains the sequence of matched sub-expressions that were in that,
Chris@16 655 /// that contains the sequence of matched sub-expressions that were in *this.
Chris@16 656 /// \throw nothrow
Chris@16 657 void swap(match_results<BidiIter> &that) // throw()
Chris@16 658 {
Chris@16 659 using std::swap;
Chris@16 660 swap(this->regex_id_, that.regex_id_);
Chris@16 661 this->sub_matches_.swap(that.sub_matches_);
Chris@16 662 this->base_.swap(that.base_);
Chris@16 663 this->prefix_.swap(that.prefix_);
Chris@16 664 this->suffix_.swap(that.suffix_);
Chris@16 665 this->nested_results_.swap(that.nested_results_);
Chris@16 666 this->extras_ptr_.swap(that.extras_ptr_);
Chris@16 667 this->traits_.swap(that.traits_);
Chris@16 668 this->args_.swap(that.args_);
Chris@16 669 }
Chris@16 670
Chris@16 671 /// TODO document me
Chris@16 672 ///
Chris@16 673 template<typename Arg>
Chris@16 674 match_results<BidiIter> &let(Arg const &arg)
Chris@16 675 {
Chris@16 676 typedef typename proto::result_of::left<Arg>::type left_type;
Chris@16 677 typedef typename proto::result_of::right<Arg>::type right_type;
Chris@16 678 typedef typename proto::result_of::value<left_type>::type arg_left_type;
Chris@16 679 typedef typename proto::result_of::value<right_type>::type arg_right_type;
Chris@16 680 BOOST_MPL_ASSERT((proto::matches<Arg, detail::ActionArgBinding>));
Chris@16 681 BOOST_MPL_ASSERT((is_same<typename arg_left_type::type, arg_right_type>));
Chris@16 682 this->args_[&typeid(proto::value(proto::left(arg)))] = &proto::value(proto::right(arg));
Chris@16 683 return *this;
Chris@16 684 }
Chris@16 685
Chris@16 686 /// INTERNAL ONLY
Chris@16 687 ///
Chris@16 688 match_results<BidiIter> const &operator ()(regex_id_type regex_id, size_type index = 0) const
Chris@16 689 {
Chris@16 690 // BUGBUG this is linear, make it O(1)
Chris@16 691 static match_results<BidiIter> const s_null;
Chris@16 692
Chris@16 693 regex_id_filter_predicate<BidiIter> pred(regex_id);
Chris@16 694 typename nested_results_type::const_iterator
Chris@16 695 begin = this->nested_results_.begin()
Chris@16 696 , end = this->nested_results_.end()
Chris@16 697 , cur = detail::find_nth_if(begin, end, index, pred);
Chris@16 698
Chris@16 699 return (cur == end) ? s_null : *cur;
Chris@16 700 }
Chris@16 701
Chris@16 702 /// INTERNAL ONLY
Chris@16 703 ///
Chris@16 704 match_results<BidiIter> const &operator ()(basic_regex<BidiIter> const &rex, std::size_t index = 0) const
Chris@16 705 {
Chris@16 706 return (*this)(rex.regex_id(), index);
Chris@16 707 }
Chris@16 708
Chris@16 709 private:
Chris@16 710
Chris@16 711 friend struct detail::core_access<BidiIter>;
Chris@16 712 typedef detail::results_extras<BidiIter> extras_type;
Chris@16 713
Chris@16 714 /// INTERNAL ONLY
Chris@16 715 ///
Chris@16 716 void init_
Chris@16 717 (
Chris@16 718 regex_id_type regex_id
Chris@16 719 , intrusive_ptr<detail::traits<char_type> const> const &tr
Chris@16 720 , detail::sub_match_impl<BidiIter> *sub_matches
Chris@16 721 , size_type size
Chris@16 722 , std::vector<detail::named_mark<char_type> > const &named_marks
Chris@16 723 )
Chris@16 724 {
Chris@16 725 this->traits_ = tr;
Chris@16 726 this->regex_id_ = regex_id;
Chris@16 727 this->named_marks_ = named_marks;
Chris@16 728 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size);
Chris@16 729 }
Chris@16 730
Chris@16 731 /// INTERNAL ONLY
Chris@16 732 ///
Chris@16 733 extras_type &get_extras_()
Chris@16 734 {
Chris@16 735 if(!this->extras_ptr_)
Chris@16 736 {
Chris@16 737 this->extras_ptr_ = new extras_type;
Chris@16 738 }
Chris@16 739
Chris@16 740 return *this->extras_ptr_;
Chris@16 741 }
Chris@16 742
Chris@16 743 /// INTERNAL ONLY
Chris@16 744 ///
Chris@16 745 void set_prefix_suffix_(BidiIter begin, BidiIter end)
Chris@16 746 {
Chris@16 747 this->base_ = begin;
Chris@16 748 this->prefix_ = sub_match<BidiIter>(begin, this->sub_matches_[ 0 ].first, begin != this->sub_matches_[ 0 ].first);
Chris@16 749 this->suffix_ = sub_match<BidiIter>(this->sub_matches_[ 0 ].second, end, this->sub_matches_[ 0 ].second != end);
Chris@16 750
Chris@16 751 typename nested_results_type::iterator ibegin = this->nested_results_.begin();
Chris@16 752 typename nested_results_type::iterator iend = this->nested_results_.end();
Chris@16 753 for( ; ibegin != iend; ++ibegin )
Chris@16 754 {
Chris@16 755 ibegin->set_prefix_suffix_(begin, end);
Chris@16 756 }
Chris@16 757 }
Chris@16 758
Chris@16 759 /// INTERNAL ONLY
Chris@16 760 ///
Chris@16 761 void reset_()
Chris@16 762 {
Chris@16 763 detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
Chris@16 764 }
Chris@16 765
Chris@16 766 /// INTERNAL ONLY
Chris@16 767 ///
Chris@16 768 void set_base_(BidiIter base)
Chris@16 769 {
Chris@16 770 this->base_ = base;
Chris@16 771
Chris@16 772 typename nested_results_type::iterator ibegin = this->nested_results_.begin();
Chris@16 773 typename nested_results_type::iterator iend = this->nested_results_.end();
Chris@16 774 for( ; ibegin != iend; ++ibegin )
Chris@16 775 {
Chris@16 776 ibegin->set_base_(base);
Chris@16 777 }
Chris@16 778 }
Chris@16 779
Chris@16 780 /// INTERNAL ONLY
Chris@16 781 ///
Chris@16 782 const_reference at_(size_type sub) const
Chris@16 783 {
Chris@16 784 return this->sub_matches_[ sub ];
Chris@16 785 }
Chris@16 786
Chris@16 787 /// INTERNAL ONLY
Chris@16 788 ///
Chris@16 789 const_reference at_(detail::basic_mark_tag const &mark) const
Chris@16 790 {
Chris@16 791 return this->sub_matches_[ detail::get_mark_number(mark) ];
Chris@16 792 }
Chris@16 793
Chris@16 794 /// INTERNAL ONLY
Chris@16 795 ///
Chris@16 796 const_reference at_(char_type const *name) const
Chris@16 797 {
Chris@16 798 for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
Chris@16 799 {
Chris@16 800 if(this->named_marks_[i].name_ == name)
Chris@16 801 {
Chris@16 802 return this->sub_matches_[ this->named_marks_[i].mark_nbr_ ];
Chris@16 803 }
Chris@16 804 }
Chris@16 805 BOOST_THROW_EXCEPTION(
Chris@16 806 regex_error(regex_constants::error_badmark, "invalid named back-reference")
Chris@16 807 );
Chris@16 808 // Should never execute, but if it does, this returns
Chris@16 809 // a "null" sub_match.
Chris@16 810 return this->sub_matches_[this->sub_matches_.size()];
Chris@16 811 }
Chris@16 812
Chris@16 813 /// INTERNAL ONLY
Chris@16 814 ///
Chris@16 815 const_reference at_(string_type const &name) const
Chris@16 816 {
Chris@16 817 return (*this)[name.c_str()];
Chris@16 818 }
Chris@16 819
Chris@16 820 /// INTERNAL ONLY
Chris@16 821 ///
Chris@16 822 template<typename OutputIterator, typename ForwardRange>
Chris@16 823 OutputIterator format2_(OutputIterator out, ForwardRange const &result) const
Chris@16 824 {
Chris@16 825 return std::copy(boost::begin(result), boost::end(result), out);
Chris@16 826 }
Chris@16 827
Chris@16 828 /// INTERNAL ONLY
Chris@16 829 ///
Chris@16 830 template<typename OutputIterator, typename Char>
Chris@16 831 OutputIterator format2_(OutputIterator out, Char const *const &result) const
Chris@16 832 {
Chris@16 833 Char const *tmp = result;
Chris@16 834 BOOST_ASSERT(0 != tmp);
Chris@16 835 for(; 0 != *tmp; ++tmp, ++out)
Chris@16 836 {
Chris@16 837 *out = *tmp;
Chris@16 838 }
Chris@16 839 return out;
Chris@16 840 }
Chris@16 841
Chris@16 842 /// INTERNAL ONLY
Chris@16 843 ///
Chris@16 844 template<typename OutputIterator, typename ForwardRange>
Chris@16 845 OutputIterator format_
Chris@16 846 (
Chris@16 847 OutputIterator out
Chris@16 848 , ForwardRange const &format
Chris@16 849 , regex_constants::match_flag_type flags
Chris@16 850 , mpl::size_t<0>
Chris@16 851 ) const
Chris@16 852 {
Chris@16 853 typedef typename range_const_iterator<ForwardRange>::type iterator;
Chris@16 854 iterator cur = boost::begin(format), end = boost::end(format);
Chris@16 855
Chris@16 856 if(0 != (regex_constants::format_literal & flags))
Chris@16 857 {
Chris@16 858 return std::copy(cur, end, out);
Chris@16 859 }
Chris@16 860 else if(0 != (regex_constants::format_perl & flags))
Chris@16 861 {
Chris@16 862 return this->format_perl_(cur, end, out);
Chris@16 863 }
Chris@16 864 else if(0 != (regex_constants::format_sed & flags))
Chris@16 865 {
Chris@16 866 return this->format_sed_(cur, end, out);
Chris@16 867 }
Chris@16 868 else if(0 != (regex_constants::format_all & flags))
Chris@16 869 {
Chris@16 870 return this->format_all_(cur, end, out);
Chris@16 871 }
Chris@16 872
Chris@16 873 return this->format_ecma_262_(cur, end, out);
Chris@16 874 }
Chris@16 875
Chris@16 876 /// INTERNAL ONLY
Chris@16 877 ///
Chris@16 878 template<typename OutputIterator, typename Callable1>
Chris@16 879 OutputIterator format_
Chris@16 880 (
Chris@16 881 OutputIterator out
Chris@16 882 , Callable1 const &format
Chris@16 883 , regex_constants::match_flag_type
Chris@16 884 , mpl::size_t<1>
Chris@16 885 ) const
Chris@16 886 {
Chris@16 887 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
Chris@16 888 return this->format2_(out, detail::as_callable(format)(*this));
Chris@16 889 #else
Chris@16 890 return this->format2_(out, format(*this));
Chris@16 891 #endif
Chris@16 892 }
Chris@16 893
Chris@16 894 /// INTERNAL ONLY
Chris@16 895 ///
Chris@16 896 template<typename OutputIterator, typename Callable2>
Chris@16 897 OutputIterator format_
Chris@16 898 (
Chris@16 899 OutputIterator out
Chris@16 900 , Callable2 const &format
Chris@16 901 , regex_constants::match_flag_type
Chris@16 902 , mpl::size_t<2>
Chris@16 903 ) const
Chris@16 904 {
Chris@16 905 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
Chris@16 906 return detail::as_callable(format)(*this, out);
Chris@16 907 #else
Chris@16 908 return format(*this, out);
Chris@16 909 #endif
Chris@16 910 }
Chris@16 911
Chris@16 912 /// INTERNAL ONLY
Chris@16 913 ///
Chris@16 914 template<typename OutputIterator, typename Callable3>
Chris@16 915 OutputIterator format_
Chris@16 916 (
Chris@16 917 OutputIterator out
Chris@16 918 , Callable3 const &format
Chris@16 919 , regex_constants::match_flag_type flags
Chris@16 920 , mpl::size_t<3>
Chris@16 921 ) const
Chris@16 922 {
Chris@16 923 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 0)
Chris@16 924 return detail::as_callable(format)(*this, out, flags);
Chris@16 925 #else
Chris@16 926 return format(*this, out, flags);
Chris@16 927 #endif
Chris@16 928 }
Chris@16 929
Chris@16 930 /// INTERNAL ONLY
Chris@16 931 ///
Chris@16 932 template<typename OutputIterator, typename Expr>
Chris@16 933 OutputIterator format_
Chris@16 934 (
Chris@16 935 OutputIterator out
Chris@16 936 , Expr const &format
Chris@16 937 , regex_constants::match_flag_type
Chris@16 938 , mpl::size_t<4>
Chris@16 939 ) const
Chris@16 940 {
Chris@16 941 // detail::ReplaceAlgo may be an incomplete type at this point, so
Chris@16 942 // we can't construct it directly.
Chris@16 943 typedef typename mpl::if_c<true, detail::ReplaceAlgo, OutputIterator>::type ReplaceAlgo;
Chris@16 944 return this->format2_(out, ReplaceAlgo()(format, 0, *this));
Chris@16 945 }
Chris@16 946
Chris@16 947 /// INTERNAL ONLY
Chris@16 948 ///
Chris@16 949 template<typename ForwardIterator, typename OutputIterator>
Chris@16 950 OutputIterator format_ecma_262_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
Chris@16 951 {
Chris@16 952 while(cur != end)
Chris@16 953 {
Chris@16 954 switch(*cur)
Chris@16 955 {
Chris@16 956 case BOOST_XPR_CHAR_(char_type, '$'):
Chris@16 957 out = this->format_backref_(++cur, end, out);
Chris@16 958 break;
Chris@16 959
Chris@16 960 default:
Chris@16 961 *out++ = *cur++;
Chris@16 962 break;
Chris@16 963 }
Chris@16 964 }
Chris@16 965
Chris@16 966 return out;
Chris@16 967 }
Chris@16 968
Chris@16 969 /// INTERNAL ONLY
Chris@16 970 ///
Chris@16 971 template<typename ForwardIterator, typename OutputIterator>
Chris@16 972 OutputIterator format_sed_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
Chris@16 973 {
Chris@16 974 while(cur != end)
Chris@16 975 {
Chris@16 976 switch(*cur)
Chris@16 977 {
Chris@16 978 case BOOST_XPR_CHAR_(char_type, '&'):
Chris@16 979 ++cur;
Chris@16 980 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
Chris@16 981 break;
Chris@16 982
Chris@16 983 case BOOST_XPR_CHAR_(char_type, '\\'):
Chris@16 984 out = this->format_escape_(++cur, end, out);
Chris@16 985 break;
Chris@16 986
Chris@16 987 default:
Chris@16 988 *out++ = *cur++;
Chris@16 989 break;
Chris@16 990 }
Chris@16 991 }
Chris@16 992
Chris@16 993 return out;
Chris@16 994 }
Chris@16 995
Chris@16 996 /// INTERNAL ONLY
Chris@16 997 ///
Chris@16 998 template<typename ForwardIterator, typename OutputIterator>
Chris@16 999 OutputIterator format_perl_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
Chris@16 1000 {
Chris@16 1001 detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
Chris@16 1002
Chris@16 1003 while(cur != end)
Chris@16 1004 {
Chris@16 1005 switch(*cur)
Chris@16 1006 {
Chris@16 1007 case BOOST_XPR_CHAR_(char_type, '$'):
Chris@16 1008 iout = this->format_backref_(++cur, end, iout);
Chris@16 1009 break;
Chris@16 1010
Chris@16 1011 case BOOST_XPR_CHAR_(char_type, '\\'):
Chris@16 1012 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
Chris@16 1013 {
Chris@16 1014 iout = this->format_named_backref_(++cur, end, iout);
Chris@16 1015 }
Chris@16 1016 else
Chris@16 1017 {
Chris@16 1018 iout = this->format_escape_(cur, end, iout);
Chris@16 1019 }
Chris@16 1020 break;
Chris@16 1021
Chris@16 1022 default:
Chris@16 1023 *iout++ = *cur++;
Chris@16 1024 break;
Chris@16 1025 }
Chris@16 1026 }
Chris@16 1027
Chris@16 1028 return iout.base();
Chris@16 1029 }
Chris@16 1030
Chris@16 1031 /// INTERNAL ONLY
Chris@16 1032 ///
Chris@16 1033 template<typename ForwardIterator, typename OutputIterator>
Chris@16 1034 OutputIterator format_all_(ForwardIterator cur, ForwardIterator end, OutputIterator out) const
Chris@16 1035 {
Chris@16 1036 detail::case_converting_iterator<OutputIterator, char_type> iout(out, this->traits_.get());
Chris@16 1037 iout = this->format_all_impl_(cur, end, iout);
Chris@16 1038 BOOST_XPR_ENSURE_(cur == end
Chris@16 1039 , regex_constants::error_paren, "unbalanced parentheses in format string");
Chris@16 1040 return iout.base();
Chris@16 1041 }
Chris@16 1042
Chris@16 1043 /// INTERNAL ONLY
Chris@16 1044 ///
Chris@16 1045 template<typename ForwardIterator, typename OutputIterator>
Chris@16 1046 OutputIterator format_all_impl_(ForwardIterator &cur, ForwardIterator end, OutputIterator out, bool metacolon = false) const
Chris@16 1047 {
Chris@16 1048 int max = 0, sub = 0;
Chris@16 1049 detail::noop_output_iterator<char_type> noop;
Chris@16 1050
Chris@16 1051 while(cur != end)
Chris@16 1052 {
Chris@16 1053 switch(*cur)
Chris@16 1054 {
Chris@16 1055 case BOOST_XPR_CHAR_(char_type, '$'):
Chris@16 1056 out = this->format_backref_(++cur, end, out);
Chris@16 1057 break;
Chris@16 1058
Chris@16 1059 case BOOST_XPR_CHAR_(char_type, '\\'):
Chris@16 1060 if(++cur != end && BOOST_XPR_CHAR_(char_type, 'g') == *cur)
Chris@16 1061 {
Chris@16 1062 out = this->format_named_backref_(++cur, end, out);
Chris@16 1063 }
Chris@16 1064 else
Chris@16 1065 {
Chris@16 1066 out = this->format_escape_(cur, end, out);
Chris@16 1067 }
Chris@16 1068 break;
Chris@16 1069
Chris@16 1070 case BOOST_XPR_CHAR_(char_type, '('):
Chris@16 1071 out = this->format_all_impl_(++cur, end, out);
Chris@16 1072 BOOST_XPR_ENSURE_(BOOST_XPR_CHAR_(char_type, ')') == *(cur-1)
Chris@16 1073 , regex_constants::error_paren, "unbalanced parentheses in format string");
Chris@16 1074 break;
Chris@16 1075
Chris@16 1076 case BOOST_XPR_CHAR_(char_type, '?'):
Chris@16 1077 BOOST_XPR_ENSURE_(++cur != end
Chris@16 1078 , regex_constants::error_subreg, "malformed conditional in format string");
Chris@16 1079 max = static_cast<int>(this->size() - 1);
Chris@16 1080 sub = detail::toi(cur, end, *this->traits_, 10, max);
Chris@16 1081 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
Chris@16 1082 if(this->sub_matches_[ sub ].matched)
Chris@16 1083 {
Chris@16 1084 out = this->format_all_impl_(cur, end, out, true);
Chris@16 1085 if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
Chris@16 1086 this->format_all_impl_(cur, end, noop);
Chris@16 1087 }
Chris@16 1088 else
Chris@16 1089 {
Chris@16 1090 this->format_all_impl_(cur, end, noop, true);
Chris@16 1091 if(BOOST_XPR_CHAR_(char_type, ':') == *(cur-1))
Chris@16 1092 out = this->format_all_impl_(cur, end, out);
Chris@16 1093 }
Chris@16 1094 return out;
Chris@16 1095
Chris@16 1096 case BOOST_XPR_CHAR_(char_type, ':'):
Chris@16 1097 if(metacolon)
Chris@16 1098 {
Chris@16 1099 BOOST_FALLTHROUGH;
Chris@16 1100 case BOOST_XPR_CHAR_(char_type, ')'):
Chris@16 1101 ++cur;
Chris@16 1102 return out;
Chris@16 1103 }
Chris@16 1104 BOOST_FALLTHROUGH;
Chris@16 1105
Chris@16 1106 default:
Chris@16 1107 *out++ = *cur++;
Chris@16 1108 break;
Chris@16 1109 }
Chris@16 1110 }
Chris@16 1111
Chris@16 1112 return out;
Chris@16 1113 }
Chris@16 1114
Chris@16 1115 /// INTERNAL ONLY
Chris@16 1116 ///
Chris@16 1117 template<typename ForwardIterator, typename OutputIterator>
Chris@16 1118 OutputIterator format_backref_
Chris@16 1119 (
Chris@16 1120 ForwardIterator &cur
Chris@16 1121 , ForwardIterator end
Chris@16 1122 , OutputIterator out
Chris@16 1123 ) const
Chris@16 1124 {
Chris@16 1125 if(cur == end)
Chris@16 1126 {
Chris@16 1127 *out++ = BOOST_XPR_CHAR_(char_type, '$');
Chris@16 1128 }
Chris@16 1129 else if(BOOST_XPR_CHAR_(char_type, '$') == *cur)
Chris@16 1130 {
Chris@16 1131 *out++ = *cur++;
Chris@16 1132 }
Chris@16 1133 else if(BOOST_XPR_CHAR_(char_type, '&') == *cur) // whole match
Chris@16 1134 {
Chris@16 1135 ++cur;
Chris@16 1136 out = std::copy(this->sub_matches_[ 0 ].first, this->sub_matches_[ 0 ].second, out);
Chris@16 1137 }
Chris@16 1138 else if(BOOST_XPR_CHAR_(char_type, '`') == *cur) // prefix
Chris@16 1139 {
Chris@16 1140 ++cur;
Chris@16 1141 out = std::copy(this->prefix().first, this->prefix().second, out);
Chris@16 1142 }
Chris@16 1143 else if(BOOST_XPR_CHAR_(char_type, '\'') == *cur) // suffix
Chris@16 1144 {
Chris@16 1145 ++cur;
Chris@16 1146 out = std::copy(this->suffix().first, this->suffix().second, out);
Chris@16 1147 }
Chris@16 1148 else if(-1 != this->traits_->value(*cur, 10)) // a sub-match
Chris@16 1149 {
Chris@16 1150 int max = static_cast<int>(this->size() - 1);
Chris@16 1151 int sub = detail::toi(cur, end, *this->traits_, 10, max);
Chris@16 1152 BOOST_XPR_ENSURE_(0 != sub, regex_constants::error_subreg, "invalid back-reference");
Chris@16 1153 if(this->sub_matches_[ sub ].matched)
Chris@16 1154 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
Chris@16 1155 }
Chris@16 1156 else
Chris@16 1157 {
Chris@16 1158 *out++ = BOOST_XPR_CHAR_(char_type, '$');
Chris@16 1159 *out++ = *cur++;
Chris@16 1160 }
Chris@16 1161
Chris@16 1162 return out;
Chris@16 1163 }
Chris@16 1164
Chris@16 1165 /// INTERNAL ONLY
Chris@16 1166 ///
Chris@16 1167 template<typename ForwardIterator, typename OutputIterator>
Chris@16 1168 OutputIterator format_escape_
Chris@16 1169 (
Chris@16 1170 ForwardIterator &cur
Chris@16 1171 , ForwardIterator end
Chris@16 1172 , OutputIterator out
Chris@16 1173 ) const
Chris@16 1174 {
Chris@16 1175 using namespace regex_constants;
Chris@16 1176 ForwardIterator tmp;
Chris@16 1177 // define an unsigned type the same size as char_type
Chris@16 1178 typedef typename boost::uint_t<CHAR_BIT * sizeof(char_type)>::least uchar_t;
Chris@16 1179 BOOST_MPL_ASSERT_RELATION(sizeof(uchar_t), ==, sizeof(char_type));
Chris@16 1180 typedef numeric::conversion_traits<uchar_t, int> converstion_traits;
Chris@16 1181 numeric::converter<int, uchar_t, converstion_traits, detail::char_overflow_handler_> converter;
Chris@16 1182
Chris@16 1183 if(cur == end)
Chris@16 1184 {
Chris@16 1185 *out++ = BOOST_XPR_CHAR_(char_type, '\\');
Chris@16 1186 return out;
Chris@16 1187 }
Chris@16 1188
Chris@16 1189 char_type ch = *cur++;
Chris@16 1190 switch(ch)
Chris@16 1191 {
Chris@16 1192 case BOOST_XPR_CHAR_(char_type, 'a'):
Chris@16 1193 *out++ = BOOST_XPR_CHAR_(char_type, '\a');
Chris@16 1194 break;
Chris@16 1195
Chris@16 1196 case BOOST_XPR_CHAR_(char_type, 'e'):
Chris@16 1197 *out++ = converter(27);
Chris@16 1198 break;
Chris@16 1199
Chris@16 1200 case BOOST_XPR_CHAR_(char_type, 'f'):
Chris@16 1201 *out++ = BOOST_XPR_CHAR_(char_type, '\f');
Chris@16 1202 break;
Chris@16 1203
Chris@16 1204 case BOOST_XPR_CHAR_(char_type, 'n'):
Chris@16 1205 *out++ = BOOST_XPR_CHAR_(char_type, '\n');
Chris@16 1206 break;
Chris@16 1207
Chris@16 1208 case BOOST_XPR_CHAR_(char_type, 'r'):
Chris@16 1209 *out++ = BOOST_XPR_CHAR_(char_type, '\r');
Chris@16 1210 break;
Chris@16 1211
Chris@16 1212 case BOOST_XPR_CHAR_(char_type, 't'):
Chris@16 1213 *out++ = BOOST_XPR_CHAR_(char_type, '\t');
Chris@16 1214 break;
Chris@16 1215
Chris@16 1216 case BOOST_XPR_CHAR_(char_type, 'v'):
Chris@16 1217 *out++ = BOOST_XPR_CHAR_(char_type, '\v');
Chris@16 1218 break;
Chris@16 1219
Chris@16 1220 case BOOST_XPR_CHAR_(char_type, 'x'):
Chris@16 1221 BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
Chris@16 1222 if(BOOST_XPR_CHAR_(char_type, '{') == *cur)
Chris@16 1223 {
Chris@16 1224 BOOST_XPR_ENSURE_(++cur != end, error_escape, "unexpected end of format found");
Chris@16 1225 tmp = cur;
Chris@16 1226 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xffff));
Chris@16 1227 BOOST_XPR_ENSURE_(4 == std::distance(tmp, cur) && cur != end && BOOST_XPR_CHAR_(char_type, '}') == *cur++
Chris@16 1228 , error_escape, "invalid hex escape : must be \\x { HexDigit HexDigit HexDigit HexDigit }");
Chris@16 1229 }
Chris@16 1230 else
Chris@16 1231 {
Chris@16 1232 tmp = cur;
Chris@16 1233 *out++ = converter(detail::toi(cur, end, *this->traits_, 16, 0xff));
Chris@16 1234 BOOST_XPR_ENSURE_(2 == std::distance(tmp, cur), error_escape
Chris@16 1235 , "invalid hex escape : must be \\x HexDigit HexDigit");
Chris@16 1236 }
Chris@16 1237 break;
Chris@16 1238
Chris@16 1239 case BOOST_XPR_CHAR_(char_type, 'c'):
Chris@16 1240 BOOST_XPR_ENSURE_(cur != end, error_escape, "unexpected end of format found");
Chris@16 1241 BOOST_XPR_ENSURE_
Chris@16 1242 (
Chris@16 1243 this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'a'), BOOST_XPR_CHAR_(char_type, 'z'), *cur)
Chris@16 1244 || this->traits_->in_range(BOOST_XPR_CHAR_(char_type, 'A'), BOOST_XPR_CHAR_(char_type, 'Z'), *cur)
Chris@16 1245 , error_escape
Chris@16 1246 , "invalid escape control letter; must be one of a-z or A-Z"
Chris@16 1247 );
Chris@16 1248 // Convert to character according to ECMA-262, section 15.10.2.10:
Chris@16 1249 *out++ = converter(*cur % 32);
Chris@16 1250 ++cur;
Chris@16 1251 break;
Chris@16 1252
Chris@16 1253 case BOOST_XPR_CHAR_(char_type, 'l'):
Chris@16 1254 if(!set_transform(out, detail::op_lower, detail::scope_next))
Chris@16 1255 {
Chris@16 1256 *out++ = BOOST_XPR_CHAR_(char_type, 'l');
Chris@16 1257 }
Chris@16 1258 break;
Chris@16 1259
Chris@16 1260 case BOOST_XPR_CHAR_(char_type, 'L'):
Chris@16 1261 if(!set_transform(out, detail::op_lower, detail::scope_rest))
Chris@16 1262 {
Chris@16 1263 *out++ = BOOST_XPR_CHAR_(char_type, 'L');
Chris@16 1264 }
Chris@16 1265 break;
Chris@16 1266
Chris@16 1267 case BOOST_XPR_CHAR_(char_type, 'u'):
Chris@16 1268 if(!set_transform(out, detail::op_upper, detail::scope_next))
Chris@16 1269 {
Chris@16 1270 *out++ = BOOST_XPR_CHAR_(char_type, 'u');
Chris@16 1271 }
Chris@16 1272 break;
Chris@16 1273
Chris@16 1274 case BOOST_XPR_CHAR_(char_type, 'U'):
Chris@16 1275 if(!set_transform(out, detail::op_upper, detail::scope_rest))
Chris@16 1276 {
Chris@16 1277 *out++ = BOOST_XPR_CHAR_(char_type, 'U');
Chris@16 1278 }
Chris@16 1279 break;
Chris@16 1280
Chris@16 1281 case BOOST_XPR_CHAR_(char_type, 'E'):
Chris@16 1282 if(!set_transform(out, detail::op_none, detail::scope_rest))
Chris@16 1283 {
Chris@16 1284 *out++ = BOOST_XPR_CHAR_(char_type, 'E');
Chris@16 1285 }
Chris@16 1286 break;
Chris@16 1287
Chris@16 1288 default:
Chris@16 1289 // BUGBUG what about backreferences like \12 ?
Chris@16 1290 if(0 < this->traits_->value(ch, 10))
Chris@16 1291 {
Chris@16 1292 int sub = this->traits_->value(ch, 10);
Chris@16 1293 if(this->sub_matches_[ sub ].matched)
Chris@16 1294 out = std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
Chris@16 1295 }
Chris@16 1296 else
Chris@16 1297 {
Chris@16 1298 *out++ = ch;
Chris@16 1299 }
Chris@16 1300 break;
Chris@16 1301 }
Chris@16 1302
Chris@16 1303 return out;
Chris@16 1304 }
Chris@16 1305
Chris@16 1306 /// INTERNAL ONLY
Chris@16 1307 ///
Chris@16 1308 template<typename ForwardIterator, typename OutputIterator>
Chris@16 1309 OutputIterator format_named_backref_
Chris@16 1310 (
Chris@16 1311 ForwardIterator &cur
Chris@16 1312 , ForwardIterator end
Chris@16 1313 , OutputIterator out
Chris@16 1314 ) const
Chris@16 1315 {
Chris@16 1316 using namespace regex_constants;
Chris@16 1317 BOOST_XPR_ENSURE_(cur != end && BOOST_XPR_CHAR_(char_type, '<') == *cur++
Chris@16 1318 , error_badmark, "invalid named back-reference");
Chris@16 1319 ForwardIterator begin = cur;
Chris@16 1320 for(; cur != end && BOOST_XPR_CHAR_(char_type, '>') != *cur; ++cur)
Chris@16 1321 {}
Chris@16 1322 BOOST_XPR_ENSURE_(cur != begin && cur != end && BOOST_XPR_CHAR_(char_type, '>') == *cur
Chris@16 1323 , error_badmark, "invalid named back-reference");
Chris@16 1324
Chris@16 1325 string_type name(begin, cur++);
Chris@16 1326 for(std::size_t i = 0; i < this->named_marks_.size(); ++i)
Chris@16 1327 {
Chris@16 1328 if(this->named_marks_[i].name_ == name)
Chris@16 1329 {
Chris@16 1330 std::size_t sub = this->named_marks_[i].mark_nbr_;
Chris@16 1331 return std::copy(this->sub_matches_[ sub ].first, this->sub_matches_[ sub ].second, out);
Chris@16 1332 }
Chris@16 1333 }
Chris@16 1334
Chris@16 1335 BOOST_THROW_EXCEPTION(regex_error(error_badmark, "invalid named back-reference"));
Chris@16 1336 // Should never get here
Chris@16 1337 return out;
Chris@16 1338 }
Chris@16 1339
Chris@16 1340 regex_id_type regex_id_;
Chris@16 1341 detail::sub_match_vector<BidiIter> sub_matches_;
Chris@16 1342 boost::optional<BidiIter> base_;
Chris@16 1343 boost::optional<sub_match<BidiIter> > prefix_;
Chris@16 1344 boost::optional<sub_match<BidiIter> > suffix_;
Chris@16 1345 nested_results_type nested_results_;
Chris@16 1346 intrusive_ptr<extras_type> extras_ptr_;
Chris@16 1347 intrusive_ptr<detail::traits<char_type> const> traits_;
Chris@16 1348 detail::action_args_type args_;
Chris@16 1349 std::vector<detail::named_mark<char_type> > named_marks_;
Chris@16 1350 };
Chris@16 1351
Chris@16 1352 ///////////////////////////////////////////////////////////////////////////////
Chris@16 1353 // regex_id_filter_predicate
Chris@16 1354 //
Chris@16 1355 template<typename BidiIter>
Chris@16 1356 struct regex_id_filter_predicate
Chris@16 1357 : std::unary_function<match_results<BidiIter>, bool>
Chris@16 1358 {
Chris@16 1359 regex_id_filter_predicate(regex_id_type regex_id)
Chris@16 1360 : regex_id_(regex_id)
Chris@16 1361 {
Chris@16 1362 }
Chris@16 1363
Chris@16 1364 bool operator ()(match_results<BidiIter> const &res) const
Chris@16 1365 {
Chris@16 1366 return this->regex_id_ == res.regex_id();
Chris@16 1367 }
Chris@16 1368
Chris@16 1369 private:
Chris@16 1370
Chris@16 1371 regex_id_type regex_id_;
Chris@16 1372 };
Chris@16 1373
Chris@16 1374 }} // namespace boost::xpressive
Chris@16 1375
Chris@16 1376 #ifdef BOOST_HAS_CONCEPTS
Chris@16 1377 // Better living through concepts. :-P
Chris@16 1378 namespace std
Chris@16 1379 {
Chris@16 1380 template<typename Iter_, typename Char_>
Chris@16 1381 concept_map OutputIterator<
Chris@16 1382 boost::xpressive::detail::case_converting_iterator<Iter_, Char_>
Chris@16 1383 , Char_
Chris@16 1384 >
Chris@16 1385 {};
Chris@16 1386
Chris@16 1387 template<typename Char_>
Chris@16 1388 concept_map OutputIterator<
Chris@16 1389 boost::xpressive::detail::noop_output_iterator<Char_>
Chris@16 1390 , Char_
Chris@16 1391 >
Chris@16 1392 {};
Chris@16 1393 }
Chris@16 1394 #endif
Chris@16 1395
Chris@16 1396 #endif