Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/boost/xpressive/regex_algorithms.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 17 years ago

updated boost from 1_33_1 to 1_34_1

File size: 16.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////
2/// \file regex_algorithms.hpp
3/// Contains the regex_match(), regex_search() and regex_replace() algorithms.
4//
5//  Copyright 2004 Eric Niebler. Distributed under the Boost
6//  Software License, Version 1.0. (See accompanying file
7//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8
9#ifndef BOOST_XPRESSIVE_ALGORITHMS_HPP_EAN_10_04_2005
10#define BOOST_XPRESSIVE_ALGORITHMS_HPP_EAN_10_04_2005
11
12// MS compatible compilers support #pragma once
13#if defined(_MSC_VER) && (_MSC_VER >= 1020)
14# pragma once
15#endif
16
17#include <iterator>
18#include <boost/xpressive/detail/detail_fwd.hpp>
19#include <boost/xpressive/detail/core/state.hpp>
20#include <boost/xpressive/detail/utility/save_restore.hpp>
21
22namespace boost { namespace xpressive
23{
24
25///////////////////////////////////////////////////////////////////////////////
26// regex_match
27///////////////////////////////////////////////////////////////////////////////
28
29/// \brief See if a regex matches a sequence from beginning to end.
30///
31/// Determines whether there is an exact match between the regular expression re,
32/// and all of the sequence [begin, end).
33///
34/// \pre Types BidiIter and OtherBidiIter meet the requirements of a Bidirectional Iterator (24.1.4).
35/// \pre OtherBidiIter is convertible to BidiIter.
36/// \pre [begin,end) denotes a valid iterator range.
37/// \param begin The beginning of the sequence.
38/// \param end The end of the sequence.
39/// \param what The match_results struct into which the sub_matches will be written
40/// \param re The regular expression object to use
41/// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
42/// \return true if a match is found, false otherwise
43/// \throw regex_error on stack exhaustion
44template<typename OtherBidiIter, typename BidiIter>
45inline bool regex_match
46(
47    OtherBidiIter begin
48  , OtherBidiIter end
49  , match_results<BidiIter> &what
50  , basic_regex<BidiIter> const &re
51  , regex_constants::match_flag_type flags = regex_constants::match_default
52)
53{
54    typedef detail::core_access<BidiIter> access;
55
56    // an invlid regex matches nothing
57    if(!access::invalid(re))
58    {
59        // the state object holds matching state and
60        // is passed by reference to all the matchers
61        detail::state_type<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
62        state.flags_.match_all_ = true;
63        state.sub_match(0).begin_ = begin;
64
65        if(access::match(re, state))
66        {
67            access::set_prefix_suffix(what, begin, end);
68            return true;
69        }
70
71        // handle partial matches
72        else if(state.found_partial_match_ && 0 != (flags & regex_constants::match_partial))
73        {
74            return state.set_partial_match(), true;
75        }
76    }
77
78    access::reset(what);
79    return false;
80}
81
82/// \overload
83template<typename OtherBidiIter, typename BidiIter>
84inline bool regex_match
85(
86    OtherBidiIter begin
87  , OtherBidiIter end
88  , basic_regex<BidiIter> const &re
89  , regex_constants::match_flag_type flags = regex_constants::match_default
90)
91{
92    // BUGBUG this is inefficient
93    match_results<BidiIter> what;
94    return regex_match(begin, end, what, re, flags);
95}
96
97/// \overload
98template<typename Char>
99inline bool regex_match
100(
101    Char const *begin
102  , match_results<Char const*> &what
103  , basic_regex<Char const*> const &re
104  , regex_constants::match_flag_type flags = regex_constants::match_default
105)
106{
107    // BUGBUG this is inefficient
108    Char const *end = begin + std::char_traits<Char>::length(begin);
109    return regex_match(begin, end, what, re, flags);
110}
111
112/// \overload
113template<typename Char, typename Traits, typename Alloc>
114inline bool regex_match
115(
116    std::basic_string<Char, Traits, Alloc> const &str
117  , match_results<typename std::basic_string<Char, Traits, Alloc>::const_iterator> &what
118  , basic_regex<typename std::basic_string<Char, Traits, Alloc>::const_iterator> const &re
119  , regex_constants::match_flag_type flags = regex_constants::match_default
120)
121{
122    return regex_match(str.begin(), str.end(), what, re, flags);
123}
124
125/// \overload
126template<typename Char>
127inline bool regex_match
128(
129    Char const *begin
130  , basic_regex<Char const *> const &re
131  , regex_constants::match_flag_type flags = regex_constants::match_default
132)
133{
134    // BUGBUG this is inefficient
135    match_results<Char const *> what;
136    return regex_match(begin, what, re, flags);
137}
138
139/// \overload
140template<typename Char, typename Traits, typename Alloc>
141inline bool regex_match
142(
143    std::basic_string<Char, Traits, Alloc> const &str
144  , basic_regex<typename std::basic_string<Char, Traits, Alloc>::const_iterator> const &re
145  , regex_constants::match_flag_type flags = regex_constants::match_default
146)
147{
148    // BUGBUG this is inefficient
149    match_results<typename std::basic_string<Char, Traits, Alloc>::const_iterator> what;
150    return regex_match(str, what, re, flags);
151}
152
153
154///////////////////////////////////////////////////////////////////////////////
155// regex_search
156///////////////////////////////////////////////////////////////////////////////
157
158namespace detail
159{
160///////////////////////////////////////////////////////////////////////////////
161// regex_search_impl
162template<typename BidiIter>
163inline bool regex_search_impl
164(
165    state_type<BidiIter> &state
166  , basic_regex<BidiIter> const &re
167  , bool not_initial_null = false
168)
169{
170    typedef core_access<BidiIter> access;
171    typedef typename iterator_value<BidiIter>::type char_type;
172    match_results<BidiIter> &what = *state.context_.results_ptr_;
173
174    // an invlid regex matches nothing
175    if(!access::invalid(re))
176    {
177        bool const partial_ok = state.flags_.match_partial_;
178        save_restore<bool> not_null(state.flags_.match_not_null_, state.flags_.match_not_null_ || not_initial_null);
179        state.flags_.match_prev_avail_ = state.flags_.match_prev_avail_ || !state.bos();
180
181        regex_impl<BidiIter> const &impl = *access::get_regex_impl(re);
182        BidiIter const begin = state.cur_, end = state.end_;
183        BidiIter &sub0begin = state.sub_match(0).begin_;
184        sub0begin = state.cur_;
185
186        // If match_continuous is set, we only need to check for a match at the current position
187        if(state.flags_.match_continuous_)
188        {
189            if(access::match(re, state))
190            {
191                access::set_prefix_suffix(what, begin, end);
192                return true;
193            }
194
195            // handle partial matches
196            else if(partial_ok && state.found_partial_match_)
197            {
198                state.set_partial_match();
199                return true;
200            }
201        }
202
203        // If we have a finder, use it to find where a potential match can start
204        else if(impl.finder_)
205        {
206            finder<BidiIter> const &find = *impl.finder_;
207            if(find(state))
208            {
209                if(state.cur_ != begin)
210                {
211                    not_null.restore();
212                }
213
214                do
215                {
216                    sub0begin = state.cur_;
217                    if(access::match(re, state))
218                    {
219                        access::set_prefix_suffix(what, begin, end);
220                        return true;
221                    }
222
223                    // handle partial matches
224                    else if(partial_ok && state.found_partial_match_)
225                    {
226                        state.set_partial_match();
227                        return true;
228                    }
229
230                    BOOST_ASSERT(state.cur_ == sub0begin);
231                    not_null.restore();
232                }
233                while(state.cur_ != state.end_ && (++state.cur_, find(state)));
234            }
235        }
236
237        // Otherwise, use brute force search at every position.
238        else
239        {
240            for(;;)
241            {
242                if(access::match(re, state))
243                {
244                    access::set_prefix_suffix(what, begin, end);
245                    return true;
246                }
247
248                // handle partial matches
249                else if(partial_ok && state.found_partial_match_)
250                {
251                    state.set_partial_match();
252                    return true;
253                }
254
255                else if(end == sub0begin)
256                {
257                    break;
258                }
259
260                BOOST_ASSERT(state.cur_ == sub0begin);
261                state.cur_ = ++sub0begin;
262                not_null.restore();
263            }
264        }
265    }
266
267    access::reset(what);
268    return false;
269}
270} // namespace detail
271
272
273/// \brief Determines whether there is some sub-sequence within [begin,end) that matches the regular expression re.
274///
275/// Determines whether there is some sub-sequence within [begin,end) that matches the regular expression re.
276///
277/// \pre Types BidiIter and OtherBidiIter meet the requirements of a Bidirectional Iterator (24.1.4).
278/// \pre OtherBidiIter is convertible to BidiIter.
279/// \pre [begin,end) denotes a valid iterator range.
280/// \param begin The beginning of the sequence
281/// \param end The end of the sequence
282/// \param what The match_results struct into which the sub_matches will be written
283/// \param re The regular expression object to use
284/// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
285/// \return true if a match is found, false otherwise
286/// \throw regex_error on stack exhaustion
287template<typename OtherBidiIter, typename BidiIter>
288inline bool regex_search
289(
290    OtherBidiIter begin
291  , OtherBidiIter end
292  , match_results<BidiIter> &what
293  , basic_regex<BidiIter> const &re
294  , regex_constants::match_flag_type flags = regex_constants::match_default
295)
296{
297    typedef detail::core_access<BidiIter> access;
298
299    // an invlid regex matches nothing
300    if(!access::invalid(re))
301    {
302        // the state object holds matching state and
303        // is passed by reference to all the matchers
304        detail::state_type<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
305        return detail::regex_search_impl(state, re);
306    }
307
308    access::reset(what);
309    return false;
310}
311
312/// \overload
313template<typename OtherBidiIter, typename BidiIter>
314inline bool regex_search
315(
316    OtherBidiIter begin
317  , OtherBidiIter end
318  , basic_regex<BidiIter> const &re
319  , regex_constants::match_flag_type flags = regex_constants::match_default
320)
321{
322    // BUGBUG this is inefficient
323    match_results<BidiIter> what;
324    return regex_search(begin, end, what, re, flags);
325}
326
327/// \overload
328template<typename Char>
329inline bool regex_search
330(
331    Char const *begin
332  , match_results<Char const*> &what
333  , basic_regex<Char const*> const &re
334  , regex_constants::match_flag_type flags = regex_constants::match_default
335)
336{
337    // BUGBUG this is inefficient
338    Char const *end = begin + std::char_traits<Char>::length(begin);
339    return regex_search(begin, end, what, re, flags);
340}
341
342/// \overload
343template<typename Char, typename Traits, typename Alloc>
344inline bool regex_search
345(
346    std::basic_string<Char, Traits, Alloc> const &str
347  , match_results<typename std::basic_string<Char, Traits, Alloc>::const_iterator> &what
348  , basic_regex<typename std::basic_string<Char, Traits, Alloc>::const_iterator> const &re
349  , regex_constants::match_flag_type flags = regex_constants::match_default
350)
351{
352    return regex_search(str.begin(), str.end(), what, re, flags);
353}
354
355/// \overload
356template<typename Char>
357inline bool regex_search
358(
359    Char const *begin
360  , basic_regex<Char const *> const &re
361  , regex_constants::match_flag_type flags = regex_constants::match_default
362)
363{
364    // BUGBUG this is inefficient
365    match_results<Char const *> what;
366    return regex_search(begin, what, re, flags);
367}
368
369/// \overload
370template<typename Char, typename Traits, typename Alloc>
371inline bool regex_search
372(
373    std::basic_string<Char, Traits, Alloc> const &str
374  , basic_regex<typename std::basic_string<Char, Traits, Alloc>::const_iterator> const &re
375  , regex_constants::match_flag_type flags = regex_constants::match_default
376)
377{
378    // BUGBUG this is inefficient
379    match_results<typename std::basic_string<Char, Traits, Alloc>::const_iterator> what;
380    return regex_search(str, what, re, flags);
381}
382
383
384///////////////////////////////////////////////////////////////////////////////
385// regex_replace
386///////////////////////////////////////////////////////////////////////////////
387
388
389/// \brief Build an output sequence given an input sequence, a regex, and a format string.
390///
391/// Constructs a regex_iterator object: regex_iterator\< BidiIter \> i(begin, end, re, flags),
392/// and uses i to enumerate through all of the matches m of type match_results\< BidiIter \> that
393/// occur within the sequence [begin, end). If no such matches are found and !(flags \& format_no_copy)
394/// then calls std::copy(begin, end, out). Otherwise, for each match found, if !(flags \& format_no_copy)
395/// calls std::copy(m.prefix().first, m.prefix().second, out), and then calls m.format(out, fmt, flags).
396/// Finally if !(flags \& format_no_copy) calls std::copy(last_m.suffix().first, last_m.suffix().second, out)
397/// where last_m is a copy of the last match found. If flags \& format_first_only is non-zero then only
398/// the first match found is replaced.
399///
400/// \pre Types BidiIter and OtherBidiIter meet the requirements of a Bidirectional Iterator (24.1.4).
401/// \pre Type OutIter meets the requirements of an Output Iterator (24.1.2).
402/// \pre OtherBidiIter is convertible to BidiIter.
403/// \pre [begin,end) denotes a valid iterator range.
404///
405/// \param out An output iterator into which the output sequence is written.
406/// \param begin The beginning of the input sequence.
407/// \param end The end of the input sequence.
408/// \param re The regular expression object to use.
409/// \param fmt The format string used to format the replacement sequence.
410/// \param flags Optional match flags, used to control how the expression is matched against the sequence. (See match_flag_type.)
411/// \return The value of the output iterator after the output sequence has been written to it.
412/// \throw regex_error on stack exhaustion or invalid format string.
413template<typename OutIter, typename OtherBidiIter, typename BidiIter>
414inline OutIter regex_replace
415(
416    OutIter out
417  , OtherBidiIter begin
418  , OtherBidiIter end
419  , basic_regex<BidiIter> const &re
420  , std::basic_string<typename iterator_value<BidiIter>::type> const &fmt
421  , regex_constants::match_flag_type flags = regex_constants::match_default
422)
423{
424    using namespace regex_constants;
425    typedef detail::core_access<BidiIter> access;
426
427    BidiIter cur = begin;
428    match_results<BidiIter> what;
429    detail::state_type<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags);
430    bool const yes_copy = (0 == (flags & format_no_copy));
431
432    if(detail::regex_search_impl(state, re))
433    {
434        if(yes_copy)
435        {
436            out = std::copy(cur, what[0].first, out);
437        }
438
439        out = what.format(out, fmt, flags);
440        cur = state.cur_ = what[0].second;
441
442        if(0 == (flags & format_first_only))
443        {
444            bool not_null = (0 == what.length());
445            state.reset(what, *access::get_regex_impl(re));
446            while(detail::regex_search_impl(state, re, not_null))
447            {
448                if(yes_copy)
449                {
450                    out = std::copy(cur, what[0].first, out);
451                }
452
453                access::set_prefix_suffix(what, begin, end);
454                out = what.format(out, fmt, flags);
455                cur = state.cur_ = what[0].second;
456                not_null = (0 == what.length());
457                state.reset(what, *access::get_regex_impl(re));
458            }
459        }
460    }
461
462    if(yes_copy)
463    {
464        out = std::copy(cur, static_cast<BidiIter>(end), out);
465    }
466
467    return out;
468}
469
470/// \overload
471template<typename Char>
472inline std::basic_string<Char> regex_replace
473(
474    std::basic_string<Char> const &str
475  , basic_regex<typename std::basic_string<Char>::const_iterator> const &re
476  , std::basic_string<Char> const &fmt
477  , regex_constants::match_flag_type flags = regex_constants::match_default
478)
479{
480    std::basic_string<Char> result;
481    result.reserve(fmt.length() * 2);
482    regex_replace(std::back_inserter(result), str.begin(), str.end(), re, fmt, flags);
483    return result;
484}
485
486}} // namespace boost::xpressive
487
488#endif
Note: See TracBrowser for help on using the repository browser.