/////////////////////////////////////////////////////////////////////////////// | |
/// \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) && (_MSC_VER >= 1020) | |
# pragma once | |
#endif | |
#include <boost/config.hpp> | |
#include <boost/mpl/bool.hpp> | |
#include <boost/xpressive/xpressive_fwd.hpp> | |
#include <boost/xpressive/regex_constants.hpp> | |
#include <boost/xpressive/detail/detail_fwd.hpp> | |
#include <boost/xpressive/detail/core/regex_impl.hpp> | |
#include <boost/xpressive/detail/core/regex_domain.hpp> | |
// Doxygen can't handle proto :-( | |
#ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED | |
# include <boost/xpressive/detail/static/grammar.hpp> | |
# include <boost/proto/extends.hpp> | |
#endif | |
#if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD | |
# include <excpt.h> // for _exception_code() | |
# include <malloc.h> // 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<typename BidiIter> | |
struct basic_regex | |
: proto::extends< | |
proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0> | |
, basic_regex<BidiIter> | |
, detail::regex_domain | |
> | |
{ | |
private: | |
typedef proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0> pimpl_type; | |
typedef proto::extends<pimpl_type, basic_regex<BidiIter>, detail::regex_domain> base_type; | |
public: | |
typedef BidiIter iterator_type; | |
typedef typename iterator_value<BidiIter>::type char_type; | |
// For compatibility with std::basic_regex | |
typedef typename iterator_value<BidiIter>::type value_type; | |
typedef typename detail::string_type<char_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<BidiIter> 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<BidiIter> &operator =(basic_regex<BidiIter> 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<typename Expr> | |
basic_regex(Expr const &expr) | |
: base_type() | |
{ | |
BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type); | |
this->compile_(expr, is_valid_regex<Expr, char_type>()); | |
} | |
/// 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<typename Expr> | |
basic_regex<BidiIter> &operator =(Expr const &expr) | |
{ | |
BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type); | |
this->compile_(expr, is_valid_regex<Expr, char_type>()); | |
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<BidiIter> &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<typename InputIter> | |
static basic_regex<BidiIter> compile(InputIter begin, InputIter end, flag_type flags = regex_constants::ECMAScript) | |
{ | |
return regex_compiler<BidiIter>().compile(begin, end, flags); | |
} | |
/// \overload | |
/// | |
template<typename InputRange> | |
static basic_regex<BidiIter> compile(InputRange const &pat, flag_type flags = regex_constants::ECMAScript) | |
{ | |
return regex_compiler<BidiIter>().compile(pat, flags); | |
} | |
/// \overload | |
/// | |
static basic_regex<BidiIter> compile(char_type const *begin, flag_type flags = regex_constants::ECMAScript) | |
{ | |
return regex_compiler<BidiIter>().compile(begin, flags); | |
} | |
/// \overload | |
/// | |
static basic_regex<BidiIter> compile(char_type const *begin, std::size_t len, flag_type flags) | |
{ | |
return regex_compiler<BidiIter>().compile(begin, len, flags); | |
} | |
private: | |
friend struct detail::core_access<BidiIter>; | |
// 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<BidiIter> &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<typename Expr> | |
void compile_(Expr const &expr, mpl::true_) | |
{ | |
detail::static_compile(expr, proto::value(*this).get()); | |
} | |
// No-op for invalid static regexes. | |
/// INTERNAL ONLY | |
template<typename Expr> | |
void compile_(Expr const &, mpl::false_) | |
{ | |
} | |
}; | |
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ECMAScript; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::icase; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::nosubs; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::optimize; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::collate; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::single_line; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_null; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_newline; | |
template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::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<typename BidiIter> | |
inline void swap(basic_regex<BidiIter> &left, basic_regex<BidiIter> &right) // throw() | |
{ | |
left.swap(right); | |
} | |
}} // namespace boost::xpressive | |
#endif // BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005 |