Coverage Report

Created: 2026-06-30 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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