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