aboutsummaryrefslogtreecommitdiff
path: root/cutl/re.hxx
blob: 62b65e062fe952643ae5818f77c2a01e4ce89f5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
// file      : cutl/re.hxx
// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC
// license   : MIT; see accompanying LICENSE file

#ifndef CUTL_RE_HXX
#define CUTL_RE_HXX

#include <string>
#include <ostream>

#include <cutl/exception.hxx>

#include <cutl/details/config.hxx>
#include <cutl/details/export.hxx>

namespace cutl
{
  namespace re
  {
    struct LIBCUTL_EXPORT format_base: exception
    {
      format_base (std::string const& d): description_ (d) {}
      ~format_base () LIBCUTL_NOTHROW_NOEXCEPT {}

      std::string const&
      description () const
      {
        return description_;
      }

      virtual char const*
      what () const LIBCUTL_NOTHROW_NOEXCEPT;

    protected:
      std::string description_;
    };

    template <typename C>
    struct basic_format: format_base
    {
      basic_format (std::basic_string<C> const& e, std::string const& d)
          : format_base (d), regex_ (e) {}
      ~basic_format () LIBCUTL_NOTHROW_NOEXCEPT {}

      std::basic_string<C> const&
      regex () const
      {
        return regex_;
      }

    private:
      std::basic_string<C> regex_;
    };

    typedef basic_format<char> format;
    typedef basic_format<wchar_t> wformat;

    // Regular expression pattern.
    //
    template <typename C>
    struct basic_regex
    {
      typedef std::basic_string<C> string_type;

      ~basic_regex ();

      basic_regex (): impl_ (0) {init (0, false);}

      explicit
      basic_regex (string_type const& s, bool icase = false)
          : impl_ (0)
      {
        init (&s, icase);
      }

      basic_regex&
      operator= (string_type const& s)
      {
        init (&s, false);
        return *this;
      }

      basic_regex&
      assign (string_type const& s, bool icase = false)
      {
        init (&s, icase);
        return *this;
      }

      basic_regex (basic_regex const&);

      basic_regex&
      operator= (basic_regex const&);

    public:
      bool
      match (string_type const&) const;

      bool
      search (string_type const&) const;

      string_type
      replace (string_type const& s,
               string_type const& sub,
               bool first_only = false) const;

    public:
      string_type const&
      str () const
      {
        return str_;
      }

      bool
      empty () const
      {
        return str_.empty ();
      }

    private:
      void
      init (string_type const*, bool);

    private:
      struct impl;

      string_type str_; // Text representation of regex.
      impl* impl_;
    };

    template <typename C>
    inline std::basic_ostream<C>&
    operator<< (std::basic_ostream<C>& os, basic_regex<C> const& r)
    {
      return os << r.str ();
    }

    typedef basic_regex<char> regex;
    typedef basic_regex<wchar_t> wregex;

    // Regular expression pattern and substituation.
    //
    template <typename C>
    struct basic_regexsub
    {
      typedef basic_regex<C> regex_type;
      typedef std::basic_string<C> string_type;

      basic_regexsub () {}

      // Expression is of the form /regex/substitution/ where '/' can
      // be replaced with any delimiter. Delimiters must be escaped in
      // regex and substitution using back slashes (e.g., "\/"). Back
      // slashes themselves can be escaped using the double back slash
      // sequence (e.g., "\\").
      //
      explicit
      basic_regexsub (string_type const& e) {init (e);}

      basic_regexsub (string_type const& regex, string_type const& sub)
          : regex_ (regex), sub_ (sub)
      {
      }

      basic_regexsub (regex_type const& regex, string_type const& sub)
          : regex_ (regex), sub_ (sub)
      {
      }

      basic_regexsub&
      operator= (string_type const& e)
      {
        init (e);
        return *this;
      }

    public:
      bool
      match (string_type const& s) const
      {
        return regex_.match (s);
      }

      bool
      search (string_type const& s) const
      {
        return regex_.search (s);
      }

      string_type
      replace (string_type const& s, bool first_only = false) const
      {
        return regex_.replace (s, sub_, first_only);
      }

    public:
      const regex_type&
      regex () const
      {
        return regex_;
      }

      const string_type&
      substitution () const
      {
        return sub_;
      }

      bool
      empty () const
      {
        return sub_.empty () && regex_.empty ();
      }

    private:
      void
      init (string_type const&);

    private:
      regex_type regex_;
      string_type sub_;
    };

    typedef basic_regexsub<char> regexsub;
    typedef basic_regexsub<wchar_t> wregexsub;

    // Once-off regex execution.
    //
    template <typename C>
    inline bool
    match (std::basic_string<C> const& s, std::basic_string<C> const& regex)
    {
      basic_regex<C> r (regex);
      return r.match (s);
    }

    template <typename C>
    inline bool
    search (std::basic_string<C> const& s, std::basic_string<C> const& regex)
    {
      basic_regex<C> r (regex);
      return r.search (s);
    }

    template <typename C>
    inline std::basic_string<C>
    replace (std::basic_string<C> const& s,
             std::basic_string<C> const& regex,
             std::basic_string<C> const& sub,
             bool first_only = false)
    {
      basic_regex<C> r (regex);
      return r.replace (s, sub, first_only);
    }

    template <typename C>
    inline std::basic_string<C>
    replace (std::basic_string<C> const& s,
             std::basic_string<C> const& regexsub, // /regex/subst/
             bool first_only = false)
    {
      basic_regexsub<C> r (regexsub);
      return r.replace (s, first_only);
    }

    // Utility function for parsing expressions in the form /regex/subst/
    // where '/' can be replaced with any delimiter. This function handles
    // escaping. It return the position of the next delimiter and stores
    // the unescaped chunk in result or throws the format exception if
    // the expression is invalid.
    //
    template <typename C>
    typename std::basic_string<C>::size_type
    parse (std::basic_string<C> const& s,
           typename std::basic_string<C>::size_type start,
           std::basic_string<C>& result);
  }
}

#include <cutl/re/re.txx>

#endif // CUTL_RE_HXX