1 /////////////////////////////////////////////////////////////////////////////// 2 /// \file basic_regex.hpp 3 /// Contains the definition of the basic_regex\<\> class template and its 4 /// associated helper functions. 5 // 6 // Copyright 2008 Eric Niebler. Distributed under the Boost 7 // Software License, Version 1.0. (See accompanying file 8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 9 10 #ifndef BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005 11 #define BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005 12 13 // MS compatible compilers support #pragma once 14 #if defined(_MSC_VER) 15 # pragma once 16 #endif 17 18 #include <boost/config.hpp> 19 #include <boost/mpl/bool.hpp> 20 #include <boost/xpressive/xpressive_fwd.hpp> 21 #include <boost/xpressive/regex_constants.hpp> 22 #include <boost/xpressive/detail/detail_fwd.hpp> 23 #include <boost/xpressive/detail/core/regex_impl.hpp> 24 #include <boost/xpressive/detail/core/regex_domain.hpp> 25 26 // Doxygen can't handle proto :-( 27 #ifndef BOOST_XPRESSIVE_DOXYGEN_INVOKED 28 # include <boost/xpressive/detail/static/grammar.hpp> 29 # include <boost/proto/extends.hpp> 30 #endif 31 32 #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD 33 # include <excpt.h> // for _exception_code() 34 # include <malloc.h> // for _resetstkoflw() 35 #endif 36 37 namespace boost { namespace xpressive 38 { 39 40 namespace detail 41 { throw_on_stack_error(bool stack_error)42 inline void throw_on_stack_error(bool stack_error) 43 { 44 BOOST_XPR_ENSURE_(!stack_error, regex_constants::error_stack, "Regex stack space exhausted"); 45 } 46 } 47 48 /////////////////////////////////////////////////////////////////////////////// 49 // basic_regex 50 // 51 /// \brief Class template basic_regex\<\> is a class for holding a compiled regular expression. 52 template<typename BidiIter> 53 struct basic_regex 54 : proto::extends< 55 proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0> 56 , basic_regex<BidiIter> 57 , detail::regex_domain 58 > 59 { 60 private: 61 typedef proto::expr<proto::tag::terminal, proto::term<detail::tracking_ptr<detail::regex_impl<BidiIter> > >, 0> pimpl_type; 62 typedef proto::extends<pimpl_type, basic_regex<BidiIter>, detail::regex_domain> base_type; 63 64 public: 65 typedef BidiIter iterator_type; 66 typedef typename iterator_value<BidiIter>::type char_type; 67 // For compatibility with std::basic_regex 68 typedef typename iterator_value<BidiIter>::type value_type; 69 typedef typename detail::string_type<char_type>::type string_type; 70 typedef regex_constants::syntax_option_type flag_type; 71 72 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ECMAScript = regex_constants::ECMAScript); 73 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, icase = regex_constants::icase_); 74 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, nosubs = regex_constants::nosubs); 75 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, optimize = regex_constants::optimize); 76 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, collate = regex_constants::collate); 77 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, single_line = regex_constants::single_line); 78 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_null = regex_constants::not_dot_null); 79 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, not_dot_newline = regex_constants::not_dot_newline); 80 BOOST_STATIC_CONSTANT(regex_constants::syntax_option_type, ignore_white_space = regex_constants::ignore_white_space); 81 82 /// \post regex_id() == 0 83 /// \post mark_count() == 0 basic_regexboost::xpressive::basic_regex84 basic_regex() 85 : base_type() 86 { 87 } 88 89 /// \param that The basic_regex object to copy. 90 /// \post regex_id() == that.regex_id() 91 /// \post mark_count() == that.mark_count() basic_regexboost::xpressive::basic_regex92 basic_regex(basic_regex<BidiIter> const &that) 93 : base_type(that) 94 { 95 } 96 97 /// \param that The basic_regex object to copy. 98 /// \post regex_id() == that.regex_id() 99 /// \post mark_count() == that.mark_count() 100 /// \return *this operator =boost::xpressive::basic_regex101 basic_regex<BidiIter> &operator =(basic_regex<BidiIter> const &that) 102 { 103 proto::value(*this) = proto::value(that); 104 return *this; 105 } 106 107 /// Construct from a static regular expression. 108 /// 109 /// \param expr The static regular expression 110 /// \pre Expr is the type of a static regular expression. 111 /// \post regex_id() != 0 112 /// \post mark_count() \>= 0 113 template<typename Expr> basic_regexboost::xpressive::basic_regex114 basic_regex(Expr const &expr) 115 : base_type() 116 { 117 BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type); 118 this->compile_(expr, is_valid_regex<Expr, char_type>()); 119 } 120 121 /// Construct from a static regular expression. 122 /// 123 /// \param expr The static regular expression. 124 /// \pre Expr is the type of a static regular expression. 125 /// \post regex_id() != 0 126 /// \post mark_count() \>= 0 127 /// \throw std::bad_alloc on out of memory 128 /// \return *this 129 template<typename Expr> operator =boost::xpressive::basic_regex130 basic_regex<BidiIter> &operator =(Expr const &expr) 131 { 132 BOOST_XPRESSIVE_CHECK_REGEX(Expr, char_type); 133 this->compile_(expr, is_valid_regex<Expr, char_type>()); 134 return *this; 135 } 136 137 /// Returns the count of capturing sub-expressions in this regular expression 138 /// mark_countboost::xpressive::basic_regex139 std::size_t mark_count() const 140 { 141 return proto::value(*this) ? proto::value(*this)->mark_count_ : 0; 142 } 143 144 /// Returns a token which uniquely identifies this regular expression. 145 /// regex_idboost::xpressive::basic_regex146 regex_id_type regex_id() const 147 { 148 return proto::value(*this) ? proto::value(*this)->xpr_.get() : 0; 149 } 150 151 /// Swaps the contents of this basic_regex object with another. 152 /// 153 /// \param that The other basic_regex object. 154 /// \attention This is a shallow swap that does not do reference tracking. 155 /// If you embed a basic_regex object by reference in another 156 /// regular expression and then swap its contents with another 157 /// basic_regex object, the change will not be visible to the 158 /// enclosing regular expression. It is done this way to ensure 159 /// that swap() cannot throw. 160 /// \throw nothrow swapboost::xpressive::basic_regex161 void swap(basic_regex<BidiIter> &that) // throw() 162 { 163 proto::value(*this).swap(proto::value(that)); 164 } 165 166 /// Factory method for building a regex object from a range of characters. 167 /// Equivalent to regex_compiler\< BidiIter \>().compile(begin, end, flags); 168 /// 169 /// \param begin The beginning of a range of characters representing the 170 /// regular expression to compile. 171 /// \param end The end of a range of characters representing the 172 /// regular expression to compile. 173 /// \param flags Optional bitmask that determines how the pat string is 174 /// interpreted. (See syntax_option_type.) 175 /// \return A basic_regex object corresponding to the regular expression 176 /// represented by the character range. 177 /// \pre [begin,end) is a valid range. 178 /// \pre The range of characters specified by [begin,end) contains a 179 /// valid string-based representation of a regular expression. 180 /// \throw regex_error when the range of characters has invalid regular 181 /// expression syntax. 182 template<typename InputIter> compileboost::xpressive::basic_regex183 static basic_regex<BidiIter> compile(InputIter begin, InputIter end, flag_type flags = regex_constants::ECMAScript) 184 { 185 return regex_compiler<BidiIter>().compile(begin, end, flags); 186 } 187 188 /// \overload 189 /// 190 template<typename InputRange> compileboost::xpressive::basic_regex191 static basic_regex<BidiIter> compile(InputRange const &pat, flag_type flags = regex_constants::ECMAScript) 192 { 193 return regex_compiler<BidiIter>().compile(pat, flags); 194 } 195 196 /// \overload 197 /// compileboost::xpressive::basic_regex198 static basic_regex<BidiIter> compile(char_type const *begin, flag_type flags = regex_constants::ECMAScript) 199 { 200 return regex_compiler<BidiIter>().compile(begin, flags); 201 } 202 203 /// \overload 204 /// compileboost::xpressive::basic_regex205 static basic_regex<BidiIter> compile(char_type const *begin, std::size_t len, flag_type flags) 206 { 207 return regex_compiler<BidiIter>().compile(begin, len, flags); 208 } 209 210 private: 211 friend struct detail::core_access<BidiIter>; 212 213 // Avoid a common programming mistake. Construction from a string is 214 // ambiguous. It could mean: 215 // sregex rx = sregex::compile(str); // compile the string into a regex 216 // or 217 // sregex rx = as_xpr(str); // treat the string as a literal 218 // Since there is no easy way to disambiguate, it is disallowed. You must 219 // say what you mean. 220 221 /// INTERNAL ONLY 222 basic_regex(char_type const *); 223 /// INTERNAL ONLY 224 basic_regex(string_type const &); 225 226 /// INTERNAL ONLY match_boost::xpressive::basic_regex227 bool match_(detail::match_state<BidiIter> &state) const 228 { 229 #if BOOST_XPRESSIVE_HAS_MS_STACK_GUARD 230 bool success = false, stack_error = false; 231 __try 232 { 233 success = proto::value(*this)->xpr_->match(state); 234 } 235 __except(_exception_code() == 0xC00000FDUL) 236 { 237 stack_error = true; 238 _resetstkoflw(); 239 } 240 detail::throw_on_stack_error(stack_error); 241 return success; 242 #else 243 return proto::value(*this)->xpr_->match(state); 244 #endif 245 } 246 247 // Compiles valid static regexes into a state machine. 248 /// INTERNAL ONLY 249 template<typename Expr> compile_boost::xpressive::basic_regex250 void compile_(Expr const &expr, mpl::true_) 251 { 252 detail::static_compile(expr, proto::value(*this).get()); 253 } 254 255 // No-op for invalid static regexes. 256 /// INTERNAL ONLY 257 template<typename Expr> compile_boost::xpressive::basic_regex258 void compile_(Expr const &, mpl::false_) 259 { 260 } 261 }; 262 263 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION 264 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ECMAScript; 265 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::icase; 266 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::nosubs; 267 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::optimize; 268 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::collate; 269 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::single_line; 270 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_null; 271 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::not_dot_newline; 272 template<typename BidiIter> regex_constants::syntax_option_type const basic_regex<BidiIter>::ignore_white_space; 273 #endif 274 275 /////////////////////////////////////////////////////////////////////////////// 276 // swap 277 /// \brief Swaps the contents of two basic_regex objects. 278 /// \param left The first basic_regex object. 279 /// \param right The second basic_regex object. 280 /// \attention This is a shallow swap that does not do reference tracking. 281 /// If you embed a basic_regex object by reference in another 282 /// regular expression and then swap its contents with another 283 /// basic_regex object, the change will not be visible to the 284 /// enclosing regular expression. It is done this way to ensure 285 /// that swap() cannot throw. 286 /// \throw nothrow 287 template<typename BidiIter> swap(basic_regex<BidiIter> & left,basic_regex<BidiIter> & right)288 inline void swap(basic_regex<BidiIter> &left, basic_regex<BidiIter> &right) // throw() 289 { 290 left.swap(right); 291 } 292 293 }} // namespace boost::xpressive 294 295 #endif // BOOST_XPRESSIVE_BASIC_REGEX_HPP_EAN_10_04_2005 296