/src/boost/boost/xpressive/basic_regex.hpp
Line | Count | Source |
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 | | { |
42 | | inline void throw_on_stack_error(bool stack_error) |
43 | 0 | { |
44 | 0 | BOOST_XPR_ENSURE_(!stack_error, regex_constants::error_stack, "Regex stack space exhausted"); |
45 | 0 | } |
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 |
84 | | 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() |
92 | | 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 |
101 | | 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> |
114 | | 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> |
130 | | 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 | | /// |
139 | | 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 | | /// |
146 | | 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 |
161 | | 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> |
183 | | 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> |
191 | | 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 | | /// |
198 | | 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 | | /// |
205 | | 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 |
227 | | 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> |
250 | | 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> |
258 | | 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> |
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 |