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