• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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