Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file basic_regex.hpp Chris@16: /// Contains the definition of the basic_regex\<\> class template and its Chris@16: /// associated helper functions. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005 Chris@16: #define BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005 Chris@16: Chris@16: // MS compatible compilers support #pragma once Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // Doxygen can't handle proto :-( Chris@16: #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED Chris@16: # include Chris@16: # include Chris@16: #endif Chris@16: Chris@16: #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD Chris@16: # include // for _exception_code() Chris@16: # include // for _resetstkoflw() Chris@16: #endif Chris@16: Chris@16: namespace boost { namespace xpressive Chris@16: { Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: inline void throw_on_stack_error(bool stack_error) Chris@16: { Chris@16: BOOST_XPR_ENSURE_(!stack_error, regex_constants::error_stack, "Regex stack space exhausted"); Chris@16: } Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // basic_regex Chris@16: // Chris@16: /// \brief Class template basic_regex\<\> is a class for holding a compiled regular expression. Chris@16: template Chris@16: struct basic_regex Chris@16: : proto::extends< Chris@16: proto::expr > >, 0> Chris@16: , basic_regex Chris@16: , detail::regex_domain Chris@16: > Chris@16: { Chris@16: private: Chris@16: typedef proto::expr > >, 0> pimpl_type; Chris@16: typedef proto::extends, detail::regex_domain> base_type; Chris@16: Chris@16: public: Chris@16: typedef BidiIter iterator_type; Chris@16: typedef typename iterator_value::type char_type; Chris@16: // For compatibility with std::basic_regex Chris@16: typedef typename iterator_value::type value_type; Chris@16: typedef typename detail::string_type::type string_type; Chris@16: typedef regex_constants::syntax_option_type flag_type; Chris@16: Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ECMAScript = regex_constants::ECMAScript); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, icase = regex_constants::icase_); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, nosubs = regex_constants::nosubs); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, optimize = regex_constants::optimize); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, collate = regex_constants::collate); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, single_line = regex_constants::single_line); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_null = regex_constants::not_dot_null); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_newline = regex_constants::not_dot_newline); Chris@16: BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ignore_white_space = regex_constants::ignore_white_space); Chris@16: Chris@16: /// \post regex_id() == 0 Chris@16: /// \post mark_count() == 0 Chris@16: basic_regex() Chris@16: : base_type() Chris@16: { Chris@16: } Chris@16: Chris@16: /// \param that The basic_regex object to copy. Chris@16: /// \post regex_id() == that.regex_id() Chris@16: /// \post mark_count() == that.mark_count() Chris@16: basic_regex(basic_regex const &that) Chris@16: : base_type(that) Chris@16: { Chris@16: } Chris@16: Chris@16: /// \param that The basic_regex object to copy. Chris@16: /// \post regex_id() == that.regex_id() Chris@16: /// \post mark_count() == that.mark_count() Chris@16: /// \return *this Chris@16: basic_regex &operator =(basic_regex const &that) Chris@16: { Chris@16: proto::value(*this) = proto::value(that); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /// Construct from a static regular expression. Chris@16: /// Chris@16: /// \param expr The static regular expression Chris@16: /// \pre Expr is the type of a static regular expression. Chris@16: /// \post regex_id() != 0 Chris@16: /// \post mark_count() \>= 0 Chris@16: template Chris@16: basic_regex(Expr const &expr) Chris@16: : base_type() Chris@16: { Chris@16: BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type); Chris@16: this->compile_(expr, is_valid_regex()); Chris@16: } Chris@16: Chris@16: /// Construct from a static regular expression. Chris@16: /// Chris@16: /// \param expr The static regular expression. Chris@16: /// \pre Expr is the type of a static regular expression. Chris@16: /// \post regex_id() != 0 Chris@16: /// \post mark_count() \>= 0 Chris@16: /// \throw std::bad_alloc on out of memory Chris@16: /// \return *this Chris@16: template Chris@16: basic_regex &operator =(Expr const &expr) Chris@16: { Chris@16: BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type); Chris@16: this->compile_(expr, is_valid_regex()); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /// Returns the count of capturing sub-expressions in this regular expression Chris@16: /// Chris@16: std::size_t mark_count() const Chris@16: { Chris@16: return proto::value(*this) ? proto::value(*this)->mark_count_ : 0; Chris@16: } Chris@16: Chris@16: /// Returns a token which uniquely identifies this regular expression. Chris@16: /// Chris@16: regex_id_type regex_id() const Chris@16: { Chris@16: return proto::value(*this) ? proto::value(*this)->xpr_.get() : 0; Chris@16: } Chris@16: Chris@16: /// Swaps the contents of this basic_regex object with another. Chris@16: /// Chris@16: /// \param that The other basic_regex object. Chris@16: /// \attention This is a shallow swap that does not do reference tracking. Chris@16: /// If you embed a basic_regex object by reference in another Chris@16: /// regular expression and then swap its contents with another Chris@16: /// basic_regex object, the change will not be visible to the Chris@16: /// enclosing regular expression. It is done this way to ensure Chris@16: /// that swap() cannot throw. Chris@16: /// \throw nothrow Chris@16: void swap(basic_regex &that) // throw() Chris@16: { Chris@16: proto::value(*this).swap(proto::value(that)); Chris@16: } Chris@16: Chris@16: /// Factory method for building a regex object from a range of characters. Chris@16: /// Equivalent to regex_compiler\< BidiIter \>().compile(begin, end, flags); Chris@16: /// Chris@16: /// \param begin The beginning of a range of characters representing the Chris@16: /// regular expression to compile. Chris@16: /// \param end The end of a range of characters representing the Chris@16: /// regular expression to compile. Chris@16: /// \param flags Optional bitmask that determines how the pat string is Chris@16: /// interpreted. (See syntax_option_type.) Chris@16: /// \return A basic_regex object corresponding to the regular expression Chris@16: /// represented by the character range. Chris@16: /// \pre [begin,end) is a valid range. Chris@16: /// \pre The range of characters specified by [begin,end) contains a Chris@16: /// valid string-based representation of a regular expression. Chris@16: /// \throw regex_error when the range of characters has invalid regular Chris@16: /// expression syntax. Chris@16: template Chris@16: static basic_regex compile(InputIter begin, InputIter end, flag_type flags = regex_constants::ECMAScript) Chris@16: { Chris@16: return regex_compiler().compile(begin, end, flags); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: static basic_regex compile(InputRange const &pat, flag_type flags = regex_constants::ECMAScript) Chris@16: { Chris@16: return regex_compiler().compile(pat, flags); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: static basic_regex compile(char_type const *begin, flag_type flags = regex_constants::ECMAScript) Chris@16: { Chris@16: return regex_compiler().compile(begin, flags); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: static basic_regex compile(char_type const *begin, std::size_t len, flag_type flags) Chris@16: { Chris@16: return regex_compiler().compile(begin, len, flags); Chris@16: } Chris@16: Chris@16: private: Chris@16: friend struct detail::core_access; Chris@16: Chris@16: // Avoid a common programming mistake. Construction from a string is Chris@16: // ambiguous. It could mean: Chris@16: // sregex rx = sregex::compile(str); // compile the string into a regex Chris@16: // or Chris@16: // sregex rx = as_xpr(str); // treat the string as a literal Chris@16: // Since there is no easy way to disambiguate, it is disallowed. You must Chris@16: // say what you mean. Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: basic_regex(char_type const *); Chris@16: /// INTERNAL ONLY Chris@16: basic_regex(string_type const &); Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: bool match_(detail::match_state &state) const Chris@16: { Chris@16: #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD Chris@16: bool success = false, stack_error = false; Chris@16: __try Chris@16: { Chris@16: success = proto::value(*this)->xpr_->match(state); Chris@16: } Chris@16: __except(_exception_code() == 0xC00000FDUL) Chris@16: { Chris@16: stack_error = true; Chris@16: _resetstkoflw(); Chris@16: } Chris@16: detail::throw_on_stack_error(stack_error); Chris@16: return success; Chris@16: #else Chris@16: return proto::value(*this)->xpr_->match(state); Chris@16: #endif Chris@16: } Chris@16: Chris@16: // Compiles valid static regexes into a state machine. Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: void compile_(Expr const &expr, mpl::true_) Chris@16: { Chris@16: detail::static_compile(expr, proto::value(*this).get()); Chris@16: } Chris@16: Chris@16: // No-op for invalid static regexes. Chris@16: /// INTERNAL ONLY Chris@16: template Chris@16: void compile_(Expr const &, mpl::false_) Chris@16: { Chris@16: } Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@16: template regex_constants::syntax_option_type const basic_regex::ECMAScript; Chris@16: template regex_constants::syntax_option_type const basic_regex::icase; Chris@16: template regex_constants::syntax_option_type const basic_regex::nosubs; Chris@16: template regex_constants::syntax_option_type const basic_regex::optimize; Chris@16: template regex_constants::syntax_option_type const basic_regex::collate; Chris@16: template regex_constants::syntax_option_type const basic_regex::single_line; Chris@16: template regex_constants::syntax_option_type const basic_regex::not_dot_null; Chris@16: template regex_constants::syntax_option_type const basic_regex::not_dot_newline; Chris@16: template regex_constants::syntax_option_type const basic_regex::ignore_white_space; Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // swap Chris@16: /// \brief Swaps the contents of two basic_regex objects. Chris@16: /// \param left The first basic_regex object. Chris@16: /// \param right The second basic_regex object. Chris@16: /// \attention This is a shallow swap that does not do reference tracking. Chris@16: /// If you embed a basic_regex object by reference in another Chris@16: /// regular expression and then swap its contents with another Chris@16: /// basic_regex object, the change will not be visible to the Chris@16: /// enclosing regular expression. It is done this way to ensure Chris@16: /// that swap() cannot throw. Chris@16: /// \throw nothrow Chris@16: template Chris@16: inline void swap(basic_regex &left, basic_regex &right) // throw() Chris@16: { Chris@16: left.swap(right); Chris@16: } Chris@16: Chris@16: }} // namespace boost::xpressive Chris@16: Chris@16: #endif // BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005