1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ossrv_pub/boost_apis/boost/xpressive/match_results.hpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,524 @@
1.4 +///////////////////////////////////////////////////////////////////////////////
1.5 +/// \file match_results.hpp
1.6 +/// Contains the definition of the match_results type and associated helpers.
1.7 +/// The match_results type holds the results of a regex_match() or
1.8 +/// regex_search() operation.
1.9 +//
1.10 +// Copyright 2004 Eric Niebler. Distributed under the Boost
1.11 +// Software License, Version 1.0. (See accompanying file
1.12 +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
1.13 +
1.14 +#ifndef BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
1.15 +#define BOOST_XPRESSIVE_MATCH_RESULTS_HPP_EAN_10_04_2005
1.16 +
1.17 +// MS compatible compilers support #pragma once
1.18 +#if defined(_MSC_VER) && (_MSC_VER >= 1020)
1.19 +# pragma once
1.20 +#endif
1.21 +
1.22 +#include <iterator>
1.23 +#include <boost/assert.hpp>
1.24 +#include <boost/shared_ptr.hpp>
1.25 +#include <boost/iterator_adaptors.hpp>
1.26 +#if BOOST_ITERATOR_ADAPTORS_VERSION >= 0x0200
1.27 +# include <boost/iterator/filter_iterator.hpp>
1.28 +#endif
1.29 +#include <boost/xpressive/regex_constants.hpp>
1.30 +#include <boost/xpressive/detail/detail_fwd.hpp>
1.31 +#include <boost/xpressive/detail/core/sub_match_vector.hpp>
1.32 +#include <boost/xpressive/detail/utility/sequence_stack.hpp>
1.33 +#include <boost/xpressive/detail/core/results_cache.hpp>
1.34 +#include <boost/xpressive/detail/core/action_state.hpp>
1.35 +#include <boost/xpressive/detail/utility/literals.hpp>
1.36 +#include <boost/xpressive/detail/utility/algorithm.hpp>
1.37 +
1.38 +namespace boost { namespace xpressive { namespace detail
1.39 +{
1.40 +
1.41 +///////////////////////////////////////////////////////////////////////////////
1.42 +// results_extras
1.43 +//
1.44 +template<typename BidiIter>
1.45 +struct results_extras
1.46 +{
1.47 + sequence_stack<sub_match_impl<BidiIter> > sub_match_stack_;
1.48 + results_cache<BidiIter> results_cache_;
1.49 +};
1.50 +
1.51 +///////////////////////////////////////////////////////////////////////////////
1.52 +// results_traits
1.53 +//
1.54 +template<typename Char>
1.55 +struct results_traits
1.56 +{
1.57 + static int value(Char ch, int radix = 10)
1.58 + {
1.59 + BOOST_ASSERT(10 == radix);
1.60 + if(ch >= BOOST_XPR_CHAR_(Char, '0') && ch <= BOOST_XPR_CHAR_(Char, '9'))
1.61 + {
1.62 + return ch - BOOST_XPR_CHAR_(Char, '0');
1.63 + }
1.64 + return -1;
1.65 + }
1.66 +};
1.67 +
1.68 +} // namespace detail
1.69 +
1.70 +///////////////////////////////////////////////////////////////////////////////
1.71 +// match_results
1.72 +/// \brief Class template match_results\<\> holds the results of a regex_match() or a
1.73 +/// regex_search() as a collection of sub_match objects.
1.74 +///
1.75 +/// Class template match_results\<\> denotes a collection of sequences representing the result of
1.76 +/// a regular expression match. Storage for the collection is allocated and freed as necessary by
1.77 +/// the member functions of class match_results\<\>.
1.78 +///
1.79 +/// The class template match_results\<\> conforms to the requirements of a Sequence, as specified
1.80 +/// in (lib.sequence.reqmts), except that only operations defined for const-qualified Sequences are
1.81 +/// supported.
1.82 +template<typename BidiIter>
1.83 +struct match_results
1.84 +{
1.85 +private:
1.86 + struct dummy { int i_; };
1.87 + typedef int dummy::*bool_type;
1.88 +
1.89 +public:
1.90 + typedef typename iterator_value<BidiIter>::type char_type;
1.91 + typedef std::basic_string<char_type> string_type;
1.92 + typedef std::size_t size_type;
1.93 + typedef sub_match<BidiIter> value_type;
1.94 + typedef typename iterator_difference<BidiIter>::type difference_type;
1.95 + typedef value_type const &reference;
1.96 + typedef value_type const &const_reference;
1.97 +
1.98 + typedef typename detail::sub_match_vector<BidiIter>::iterator iterator;
1.99 + typedef typename detail::sub_match_vector<BidiIter>::const_iterator const_iterator;
1.100 + typedef typename detail::nested_results<BidiIter> nested_results_type;
1.101 +
1.102 + /// \post regex_id() == 0
1.103 + /// \post size() == 0
1.104 + /// \post empty() == true
1.105 + match_results()
1.106 + : regex_id_(0)
1.107 + , sub_matches_()
1.108 + , base_()
1.109 + , prefix_()
1.110 + , suffix_()
1.111 + , nested_results_()
1.112 + , action_state_()
1.113 + , extras_ptr_()
1.114 + {
1.115 + }
1.116 +
1.117 + /// \param that The match_results object to copy
1.118 + /// \post regex_id() == that.regex_id().
1.119 + /// \post size() == that.size().
1.120 + /// \post empty() == that.empty().
1.121 + /// \post str(n) == that.str(n) for all positive integers n \< that.size().
1.122 + /// \post prefix() == that.prefix().
1.123 + /// \post suffix() == that.suffix().
1.124 + /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
1.125 + /// \post length(n) == that.length(n) for all positive integers n \< that.size().
1.126 + /// \post position(n) == that.position(n) for all positive integers n \< that.size().
1.127 + match_results(match_results<BidiIter> const &that)
1.128 + : regex_id_(that.regex_id_)
1.129 + , sub_matches_()
1.130 + , base_()
1.131 + , prefix_()
1.132 + , suffix_()
1.133 + , nested_results_()
1.134 + , action_state_(that.action_state_)
1.135 + , extras_ptr_()
1.136 + {
1.137 + if(that)
1.138 + {
1.139 + extras_type &extras = this->get_extras_();
1.140 + std::size_t size = that.sub_matches_.size();
1.141 + detail::sub_match_impl<BidiIter> *sub_matches = extras.sub_match_stack_.push_sequence(size);
1.142 + detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size, that.sub_matches_);
1.143 +
1.144 + // BUGBUG this doesn't share the extras::sequence_stack
1.145 + this->nested_results_ = that.nested_results_;
1.146 + this->prefix_ = that.prefix_;
1.147 + this->suffix_ = that.suffix_;
1.148 + this->base_ = that.base_;
1.149 + }
1.150 + }
1.151 +
1.152 + ~match_results()
1.153 + {
1.154 + }
1.155 +
1.156 + /// \param that The match_results object to copy.
1.157 + /// \post regex_id() == that.regex_id().
1.158 + /// \post size() == that.size().
1.159 + /// \post empty() == that.empty().
1.160 + /// \post str(n) == that.str(n) for all positive integers n \< that.size().
1.161 + /// \post prefix() == that.prefix().
1.162 + /// \post suffix() == that.suffix().
1.163 + /// \post (*this)[n] == that[n] for all positive integers n \< that.size().
1.164 + /// \post length(n) == that.length(n) for all positive integers n \< that.size().
1.165 + /// \post position(n) == that.position(n) for all positive integers n \< that.size().
1.166 + match_results<BidiIter> &operator =(match_results<BidiIter> const &that)
1.167 + {
1.168 + match_results<BidiIter>(that).swap(*this);
1.169 + return *this;
1.170 + }
1.171 +
1.172 + /// Returns the number of sub_match elements stored in *this.
1.173 + ///
1.174 + size_type size() const
1.175 + {
1.176 + return this->sub_matches_.size();
1.177 + }
1.178 +
1.179 + /// Returns size() == 0.
1.180 + ///
1.181 + bool empty() const
1.182 + {
1.183 + return 0 == this->size();
1.184 + }
1.185 +
1.186 + /// Returns (*this)[sub].length().
1.187 + ///
1.188 + difference_type length(size_type sub = 0) const
1.189 + {
1.190 + return (*this)[ sub ].length();
1.191 + }
1.192 +
1.193 + /// If !(*this)[sub].matched then returns -1. Otherwise returns std::distance(base, (*this)[sub].first),
1.194 + /// where base is the start iterator of the sequence that was searched. [Note – unless this is part
1.195 + /// of a repeated search with a regex_iterator then base is the same as prefix().first – end note]
1.196 + difference_type position(size_type sub = 0) const
1.197 + {
1.198 + return (*this)[ sub ].matched ? std::distance(this->base_, (*this)[ sub ].first) : -1;
1.199 + }
1.200 +
1.201 + /// Returns string_type((*this)[sub]).
1.202 + ///
1.203 + string_type str(size_type sub = 0) const
1.204 + {
1.205 + return (*this)[ sub ].str();
1.206 + }
1.207 +
1.208 + /// Returns a reference to the sub_match object representing the sequence that
1.209 + /// matched marked sub-expression sub. If sub == 0 then returns a reference to a sub_match object
1.210 + /// representing the sequence that matched the whole regular expression.
1.211 + /// \pre sub \< (*this).size().
1.212 + const_reference operator [](size_type sub) const
1.213 + {
1.214 + return this->sub_matches_[ sub ];
1.215 + }
1.216 +
1.217 + /// \overload
1.218 + ///
1.219 + const_reference operator [](detail::mark_tag const &mark) const
1.220 + {
1.221 + return this->sub_matches_[ detail::get_mark_number(mark) ];
1.222 + }
1.223 +
1.224 + /// Returns a reference to the sub_match object representing the character sequence from
1.225 + /// the start of the string being matched/searched, to the start of the match found.
1.226 + ///
1.227 + const_reference prefix() const
1.228 + {
1.229 + return this->prefix_;
1.230 + }
1.231 +
1.232 + /// Returns a reference to the sub_match object representing the character sequence from
1.233 + /// the end of the match found to the end of the string being matched/searched.
1.234 + ///
1.235 + const_reference suffix() const
1.236 + {
1.237 + return this->suffix_;
1.238 + }
1.239 +
1.240 + /// Returns a starting iterator that enumerates over all the marked sub-expression matches
1.241 + /// stored in *this.
1.242 + ///
1.243 + const_iterator begin() const
1.244 + {
1.245 + return this->sub_matches_.begin();
1.246 + }
1.247 +
1.248 + /// Returns a terminating iterator that enumerates over all the marked sub-expression
1.249 + /// matches stored in *this.
1.250 + ///
1.251 + const_iterator end() const
1.252 + {
1.253 + return this->sub_matches_.end();
1.254 + }
1.255 +
1.256 + /// Returns a true value if(*this)[0].matched, else returns a false value.
1.257 + ///
1.258 + operator bool_type() const
1.259 + {
1.260 + return (*this)[ 0 ].matched ? &dummy::i_ : 0;
1.261 + }
1.262 +
1.263 + /// Returns true if empty() || !(*this)[0].matched, else returns false.
1.264 + ///
1.265 + bool operator !() const
1.266 + {
1.267 + return this->empty() || !(*this)[ 0 ].matched;
1.268 + }
1.269 +
1.270 + /// Returns the id of the basic_regex object most recently used with this match_results object.
1.271 + ///
1.272 + regex_id_type regex_id() const
1.273 + {
1.274 + return this->regex_id_;
1.275 + }
1.276 +
1.277 + /// Returns a Sequence of nested match_results elements.
1.278 + ///
1.279 + nested_results_type const &nested_results() const
1.280 + {
1.281 + return this->nested_results_;
1.282 + }
1.283 +
1.284 + /// Copies the character sequence [fmt.begin(), fmt.end()) to OutputIterator out. For each format
1.285 + /// specifier or escape sequence in fmt, replace that sequence with either the character(s) it
1.286 + /// represents, or the sequence within *this to which it refers. The bitmasks specified in flags
1.287 + /// determines what format specifiers or escape sequences are recognized, by default this is the
1.288 + /// format used by ECMA-262, ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
1.289 + template<typename OutputIterator>
1.290 + OutputIterator format
1.291 + (
1.292 + OutputIterator out
1.293 + , const string_type &fmt
1.294 + , regex_constants::match_flag_type flags = regex_constants::format_default
1.295 + ) const
1.296 + {
1.297 + detail::results_traits<char_type> traits;
1.298 + typename string_type::const_iterator cur = fmt.begin(), end = fmt.end();
1.299 +
1.300 + if(0 != (regex_constants::format_literal & flags))
1.301 + {
1.302 + out = std::copy(cur, end, out);
1.303 + }
1.304 + else while(cur != end)
1.305 + {
1.306 + if(BOOST_XPR_CHAR_(char_type, '$') != *cur)
1.307 + {
1.308 + *out++ = *cur++;
1.309 + }
1.310 + else if(++cur == end)
1.311 + {
1.312 + *out++ = BOOST_XPR_CHAR_(char_type, '$');
1.313 + }
1.314 + else if(BOOST_XPR_CHAR_(char_type, '$') == *cur)
1.315 + {
1.316 + *out++ = *cur++;
1.317 + }
1.318 + else if(BOOST_XPR_CHAR_(char_type, '&') == *cur) // whole match
1.319 + {
1.320 + ++cur;
1.321 + out = std::copy((*this)[ 0 ].first, (*this)[ 0 ].second, out);
1.322 + }
1.323 + else if(BOOST_XPR_CHAR_(char_type, '`') == *cur) // prefix
1.324 + {
1.325 + ++cur;
1.326 + out = std::copy(this->prefix().first, this->prefix().second, out);
1.327 + }
1.328 + else if(BOOST_XPR_CHAR_(char_type, '\'') == *cur) // suffix
1.329 + {
1.330 + ++cur;
1.331 + out = std::copy(this->suffix().first, this->suffix().second, out);
1.332 + }
1.333 + else if(-1 != traits.value(*cur, 10)) // a sub-match
1.334 + {
1.335 + int max = static_cast<int>(this->size() - 1);
1.336 + int br_nbr = detail::toi(cur, end, traits, 10, max);
1.337 + detail::ensure(0 != br_nbr, regex_constants::error_subreg, "invalid back-reference");
1.338 + out = std::copy((*this)[ br_nbr ].first, (*this)[ br_nbr ].second, out);
1.339 + }
1.340 + else
1.341 + {
1.342 + *out++ = BOOST_XPR_CHAR_(char_type, '$');
1.343 + *out++ = *cur++;
1.344 + }
1.345 + }
1.346 +
1.347 + return out;
1.348 + }
1.349 +
1.350 + /// Returns a copy of the string fmt. For each format specifier or escape sequence in fmt,
1.351 + /// replace that sequence with either the character(s) it represents, or the sequence within
1.352 + /// *this to which it refers. The bitmasks specified in flags determines what format specifiers
1.353 + /// or escape sequences are recognized, by default this is the format used by ECMA-262,
1.354 + /// ECMAScript Language Specification, Chapter 15 part 5.4.11 String.prototype.replace.
1.355 + string_type format(const string_type &fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const
1.356 + {
1.357 + string_type result;
1.358 + result.reserve(fmt.length() * 2);
1.359 + this->format(std::back_inserter(result), fmt, flags);
1.360 + return result;
1.361 + }
1.362 +
1.363 + /// Swaps the contents of two match_results objects. Guaranteed not to throw.
1.364 + /// \param that The match_results object to swap with.
1.365 + /// \post *this contains the sequence of matched sub-expressions that were in that,
1.366 + /// that contains the sequence of matched sub-expressions that were in *this.
1.367 + /// \throw nothrow
1.368 + void swap(match_results<BidiIter> &that) // throw()
1.369 + {
1.370 + std::swap(this->regex_id_, that.regex_id_);
1.371 + this->sub_matches_.swap(that.sub_matches_);
1.372 + std::swap(this->base_, that.base_);
1.373 + std::swap(this->prefix_, that.prefix_);
1.374 + std::swap(this->suffix_, that.suffix_);
1.375 + this->nested_results_.swap(that.nested_results_);
1.376 + std::swap(this->action_state_, that.action_state_);
1.377 + this->extras_ptr_.swap(that.extras_ptr_);
1.378 + }
1.379 +
1.380 + /// INTERNAL ONLY
1.381 + match_results<BidiIter> const &operator ()(regex_id_type regex_id, size_type index = 0) const
1.382 + {
1.383 + // BUGBUG this is linear, make it O(1)
1.384 + static match_results<BidiIter> const s_null;
1.385 +
1.386 + regex_id_filter_predicate<BidiIter> pred(regex_id);
1.387 + typename nested_results_type::const_iterator
1.388 + begin = this->nested_results_.begin()
1.389 + , end = this->nested_results_.end()
1.390 + , cur = detail::find_nth_if(begin, end, index, pred);
1.391 +
1.392 + return (cur == end) ? s_null : *cur;
1.393 + }
1.394 +
1.395 + /// INTERNAL ONLY
1.396 + match_results<BidiIter> const &operator ()(basic_regex<BidiIter> const &rex, std::size_t index = 0) const
1.397 + {
1.398 + return (*this)(rex.regex_id(), index);
1.399 + }
1.400 +
1.401 + // state:
1.402 + /// INTERNAL ONLY
1.403 + template<typename State>
1.404 + void set_action_state(State &state)
1.405 + {
1.406 + this->action_state_.set(state);
1.407 + }
1.408 +
1.409 + /// INTERNAL ONLY
1.410 + template<typename State>
1.411 + State &get_action_state() const
1.412 + {
1.413 + return this->action_state_.BOOST_NESTED_TEMPLATE get<State>();
1.414 + }
1.415 +
1.416 +private:
1.417 +
1.418 + friend struct detail::core_access<BidiIter>;
1.419 + typedef detail::results_extras<BidiIter> extras_type;
1.420 +
1.421 + /// INTERNAL ONLY
1.422 + void init_
1.423 + (
1.424 + regex_id_type regex_id
1.425 + , detail::sub_match_impl<BidiIter> *sub_matches
1.426 + , size_type size
1.427 + )
1.428 + {
1.429 + this->regex_id_ = regex_id;
1.430 + detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, sub_matches, size);
1.431 + }
1.432 +
1.433 + /// INTERNAL ONLY
1.434 + extras_type &get_extras_()
1.435 + {
1.436 + if(!this->extras_ptr_)
1.437 + {
1.438 + this->extras_ptr_.reset(new extras_type);
1.439 + }
1.440 +
1.441 + return *this->extras_ptr_;
1.442 + }
1.443 +
1.444 + /// INTERNAL ONLY
1.445 + void set_prefix_suffix_(BidiIter begin, BidiIter end)
1.446 + {
1.447 + this->base_ = begin;
1.448 +
1.449 + this->prefix_.first = begin;
1.450 + this->prefix_.second = (*this)[ 0 ].first;
1.451 + this->prefix_.matched = this->prefix_.first != this->prefix_.second;
1.452 +
1.453 + this->suffix_.first = (*this)[ 0 ].second;
1.454 + this->suffix_.second = end;
1.455 + this->suffix_.matched = this->suffix_.first != this->suffix_.second;
1.456 +
1.457 + typename nested_results_type::iterator ibegin = this->nested_results_.begin();
1.458 + typename nested_results_type::iterator iend = this->nested_results_.end();
1.459 + for( ; ibegin != iend; ++ibegin )
1.460 + {
1.461 + ibegin->set_prefix_suffix_(begin, end);
1.462 + }
1.463 + }
1.464 +
1.465 + /// INTERNAL ONLY
1.466 + void reset_()
1.467 + {
1.468 + detail::core_access<BidiIter>::init_sub_match_vector(this->sub_matches_, 0, 0);
1.469 + }
1.470 +
1.471 + /// INTERNAL ONLY
1.472 + void set_base_(BidiIter base)
1.473 + {
1.474 + this->base_ = base;
1.475 +
1.476 + typename nested_results_type::iterator ibegin = this->nested_results_.begin();
1.477 + typename nested_results_type::iterator iend = this->nested_results_.end();
1.478 + for( ; ibegin != iend; ++ibegin )
1.479 + {
1.480 + ibegin->set_base_(base);
1.481 + }
1.482 + }
1.483 +
1.484 + regex_id_type regex_id_;
1.485 + detail::sub_match_vector<BidiIter> sub_matches_;
1.486 + BidiIter base_;
1.487 + sub_match<BidiIter> prefix_;
1.488 + sub_match<BidiIter> suffix_;
1.489 + nested_results_type nested_results_;
1.490 + detail::action_state action_state_;
1.491 + shared_ptr<extras_type> extras_ptr_;
1.492 +};
1.493 +
1.494 +///////////////////////////////////////////////////////////////////////////////
1.495 +// action_state_cast
1.496 +/// INTERNAL ONLY
1.497 +template<typename State, typename BidiIter>
1.498 +inline State &action_state_cast(match_results<BidiIter> const &what)
1.499 +{
1.500 + return what.BOOST_NESTED_TEMPLATE get_action_state<State>();
1.501 +}
1.502 +
1.503 +///////////////////////////////////////////////////////////////////////////////
1.504 +// regex_id_filter_predicate
1.505 +//
1.506 +template<typename BidiIter>
1.507 +struct regex_id_filter_predicate
1.508 + : std::unary_function<match_results<BidiIter>, bool>
1.509 +{
1.510 + regex_id_filter_predicate(regex_id_type regex_id)
1.511 + : regex_id_(regex_id)
1.512 + {
1.513 + }
1.514 +
1.515 + bool operator ()(match_results<BidiIter> const &res) const
1.516 + {
1.517 + return this->regex_id_ == res.regex_id();
1.518 + }
1.519 +
1.520 +private:
1.521 +
1.522 + regex_id_type regex_id_;
1.523 +};
1.524 +
1.525 +}} // namespace boost::xpressive
1.526 +
1.527 +#endif