1 | /////////////////////////////////////////////////////////////////////////////// |
2 | /// \file regex_algorithms.hpp |
3 | /// Contains the regex_match(), regex_search() and regex_replace() algorithms. |
4 | // |
5 | // Copyright 2008 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) |
14 | # pragma once |
15 | #endif |
16 | |
17 | #include <string> |
18 | #include <iterator> |
19 | #include <boost/mpl/or.hpp> |
20 | #include <boost/range/end.hpp> |
21 | #include <boost/range/begin.hpp> |
22 | #include <boost/mpl/identity.hpp> |
23 | #include <boost/utility/enable_if.hpp> |
24 | #include <boost/type_traits/add_const.hpp> |
25 | #include <boost/type_traits/is_pointer.hpp> |
26 | #include <boost/type_traits/remove_const.hpp> |
27 | #include <boost/xpressive/match_results.hpp> |
28 | #include <boost/xpressive/detail/detail_fwd.hpp> |
29 | #include <boost/xpressive/detail/core/state.hpp> |
30 | #include <boost/xpressive/detail/utility/save_restore.hpp> |
31 | |
32 | /// INTERNAL ONLY |
33 | /// |
34 | #define BOOST_XPR_NONDEDUCED_TYPE_(x) typename mpl::identity<x>::type |
35 | |
36 | namespace boost { namespace xpressive |
37 | { |
38 | |
39 | /////////////////////////////////////////////////////////////////////////////// |
40 | // regex_match |
41 | /////////////////////////////////////////////////////////////////////////////// |
42 | |
43 | namespace detail |
44 | { |
45 | /////////////////////////////////////////////////////////////////////////////// |
46 | // regex_match_impl |
47 | template<typename BidiIter> |
48 | inline bool regex_match_impl |
49 | ( |
50 | BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
51 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
52 | , match_results<BidiIter> &what |
53 | , basic_regex<BidiIter> const &re |
54 | , regex_constants::match_flag_type flags = regex_constants::match_default |
55 | ) |
56 | { |
57 | typedef detail::core_access<BidiIter> access; |
58 | BOOST_ASSERT(0 != re.regex_id()); |
59 | |
60 | // the state object holds matching state and |
61 | // is passed by reference to all the matchers |
62 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
63 | state.flags_.match_all_ = true; |
64 | state.sub_match(0).begin_ = begin; |
65 | |
66 | if(access::match(re, state)) |
67 | { |
68 | access::set_prefix_suffix(what, begin, end); |
69 | return true; |
70 | } |
71 | |
72 | // handle partial matches |
73 | else if(state.found_partial_match_ && 0 != (flags & regex_constants::match_partial)) |
74 | { |
75 | state.set_partial_match(); |
76 | return true; |
77 | } |
78 | |
79 | access::reset(what); |
80 | return false; |
81 | } |
82 | } // namespace detail |
83 | |
84 | /// \brief See if a regex matches a sequence from beginning to end. |
85 | /// |
86 | /// Determines whether there is an exact match between the regular expression \c re, |
87 | /// and all of the sequence <tt>[begin, end)</tt>. |
88 | /// |
89 | /// \pre Type \c BidiIter meets the requirements of a Bidirectional Iterator (24.1.4). |
90 | /// \pre <tt>[begin,end)</tt> denotes a valid iterator range. |
91 | /// \param begin The beginning of the sequence. |
92 | /// \param end The end of the sequence. |
93 | /// \param what The \c match_results struct into which the sub_matches will be written |
94 | /// \param re The regular expression object to use |
95 | /// \param flags Optional match flags, used to control how the expression is matched |
96 | /// against the sequence. (See \c match_flag_type.) |
97 | /// \return \c true if a match is found, \c false otherwise |
98 | /// \throw regex_error on stack exhaustion |
99 | template<typename BidiIter> |
100 | inline bool regex_match |
101 | ( |
102 | BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
103 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
104 | , match_results<BidiIter> &what |
105 | , basic_regex<BidiIter> const &re |
106 | , regex_constants::match_flag_type flags = regex_constants::match_default |
107 | ) |
108 | { |
109 | typedef detail::core_access<BidiIter> access; |
110 | |
111 | if(0 == re.regex_id()) |
112 | { |
113 | access::reset(what); |
114 | return false; |
115 | } |
116 | |
117 | return detail::regex_match_impl(begin, end, what, re, flags); |
118 | } |
119 | |
120 | /// \overload |
121 | /// |
122 | template<typename BidiIter> |
123 | inline bool regex_match |
124 | ( |
125 | BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
126 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
127 | , basic_regex<BidiIter> const &re |
128 | , regex_constants::match_flag_type flags = regex_constants::match_default |
129 | ) |
130 | { |
131 | if(0 == re.regex_id()) |
132 | { |
133 | return false; |
134 | } |
135 | |
136 | // BUGBUG this is inefficient |
137 | match_results<BidiIter> what; |
138 | return detail::regex_match_impl(begin, end, what, re, flags); |
139 | } |
140 | |
141 | /// \overload |
142 | /// |
143 | template<typename Char> |
144 | inline bool regex_match |
145 | ( |
146 | BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin |
147 | , match_results<Char *> &what |
148 | , basic_regex<Char *> const &re |
149 | , regex_constants::match_flag_type flags = regex_constants::match_default |
150 | ) |
151 | { |
152 | typedef detail::core_access<Char *> access; |
153 | |
154 | if(0 == re.regex_id()) |
155 | { |
156 | access::reset(what); |
157 | return false; |
158 | } |
159 | |
160 | // BUGBUG this is inefficient |
161 | typedef typename remove_const<Char>::type char_type; |
162 | Char *end = begin + std::char_traits<char_type>::length(begin); |
163 | return detail::regex_match_impl(begin, end, what, re, flags); |
164 | } |
165 | |
166 | /// \overload |
167 | /// |
168 | template<typename BidiRange, typename BidiIter> |
169 | inline bool regex_match |
170 | ( |
171 | BidiRange &rng |
172 | , match_results<BidiIter> &what |
173 | , basic_regex<BidiIter> const &re |
174 | , regex_constants::match_flag_type flags = regex_constants::match_default |
175 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
176 | ) |
177 | { |
178 | typedef detail::core_access<BidiIter> access; |
179 | |
180 | if(0 == re.regex_id()) |
181 | { |
182 | access::reset(what); |
183 | return false; |
184 | } |
185 | |
186 | // Note that the result iterator of the range must be convertible |
187 | // to BidiIter here. |
188 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
189 | return detail::regex_match_impl(begin, end, what, re, flags); |
190 | } |
191 | |
192 | /// \overload |
193 | /// |
194 | template<typename BidiRange, typename BidiIter> |
195 | inline bool regex_match |
196 | ( |
197 | BidiRange const &rng |
198 | , match_results<BidiIter> &what |
199 | , basic_regex<BidiIter> const &re |
200 | , regex_constants::match_flag_type flags = regex_constants::match_default |
201 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
202 | ) |
203 | { |
204 | typedef detail::core_access<BidiIter> access; |
205 | |
206 | if(0 == re.regex_id()) |
207 | { |
208 | access::reset(what); |
209 | return false; |
210 | } |
211 | |
212 | // Note that the result iterator of the range must be convertible |
213 | // to BidiIter here. |
214 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
215 | return detail::regex_match_impl(begin, end, what, re, flags); |
216 | } |
217 | |
218 | /// \overload |
219 | /// |
220 | template<typename Char> |
221 | inline bool regex_match |
222 | ( |
223 | BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin |
224 | , basic_regex<Char *> const &re |
225 | , regex_constants::match_flag_type flags = regex_constants::match_default |
226 | ) |
227 | { |
228 | if(0 == re.regex_id()) |
229 | { |
230 | return false; |
231 | } |
232 | |
233 | // BUGBUG this is inefficient |
234 | match_results<Char *> what; |
235 | typedef typename remove_const<Char>::type char_type; |
236 | Char *end = begin + std::char_traits<char_type>::length(begin); |
237 | return detail::regex_match_impl(begin, end, what, re, flags); |
238 | } |
239 | |
240 | /// \overload |
241 | /// |
242 | template<typename BidiRange, typename BidiIter> |
243 | inline bool regex_match |
244 | ( |
245 | BidiRange &rng |
246 | , basic_regex<BidiIter> const &re |
247 | , regex_constants::match_flag_type flags = regex_constants::match_default |
248 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
249 | ) |
250 | { |
251 | if(0 == re.regex_id()) |
252 | { |
253 | return false; |
254 | } |
255 | |
256 | // BUGBUG this is inefficient |
257 | match_results<BidiIter> what; |
258 | // Note that the result iterator of the range must be convertible |
259 | // to BidiIter here. |
260 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
261 | return detail::regex_match_impl(begin, end, what, re, flags); |
262 | } |
263 | |
264 | /// \overload |
265 | /// |
266 | template<typename BidiRange, typename BidiIter> |
267 | inline bool regex_match |
268 | ( |
269 | BidiRange const &rng |
270 | , basic_regex<BidiIter> const &re |
271 | , regex_constants::match_flag_type flags = regex_constants::match_default |
272 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
273 | ) |
274 | { |
275 | if(0 == re.regex_id()) |
276 | { |
277 | return false; |
278 | } |
279 | |
280 | // BUGBUG this is inefficient |
281 | match_results<BidiIter> what; |
282 | // Note that the result iterator of the range must be convertible |
283 | // to BidiIter here. |
284 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
285 | return detail::regex_match_impl(begin, end, what, re, flags); |
286 | } |
287 | |
288 | |
289 | /////////////////////////////////////////////////////////////////////////////// |
290 | // regex_search |
291 | /////////////////////////////////////////////////////////////////////////////// |
292 | |
293 | namespace detail |
294 | { |
295 | /////////////////////////////////////////////////////////////////////////////// |
296 | // regex_search_impl |
297 | template<typename BidiIter> |
298 | inline bool regex_search_impl |
299 | ( |
300 | match_state<BidiIter> &state |
301 | , basic_regex<BidiIter> const &re |
302 | , bool not_initial_null = false |
303 | ) |
304 | { |
305 | typedef core_access<BidiIter> access; |
306 | match_results<BidiIter> &what = *state.context_.results_ptr_; |
307 | BOOST_ASSERT(0 != re.regex_id()); |
308 | |
309 | bool const partial_ok = state.flags_.match_partial_; |
310 | save_restore<bool> not_null(state.flags_.match_not_null_, state.flags_.match_not_null_ || not_initial_null); |
311 | state.flags_.match_prev_avail_ = state.flags_.match_prev_avail_ || !state.bos(); |
312 | |
313 | regex_impl<BidiIter> const &impl = *access::get_regex_impl(re); |
314 | BidiIter const begin = state.cur_, end = state.end_; |
315 | BidiIter &sub0begin = state.sub_match(0).begin_; |
316 | sub0begin = state.cur_; |
317 | |
318 | // If match_continuous is set, we only need to check for a match at the current position |
319 | if(state.flags_.match_continuous_) |
320 | { |
321 | if(access::match(re, state)) |
322 | { |
323 | access::set_prefix_suffix(what, begin, end); |
324 | return true; |
325 | } |
326 | |
327 | // handle partial matches |
328 | else if(partial_ok && state.found_partial_match_) |
329 | { |
330 | state.set_partial_match(); |
331 | return true; |
332 | } |
333 | } |
334 | |
335 | // If we have a finder, use it to find where a potential match can start |
336 | else if(impl.finder_ && (!partial_ok || impl.finder_->ok_for_partial_matches())) |
337 | { |
338 | finder<BidiIter> const &find = *impl.finder_; |
339 | if(find(state)) |
340 | { |
341 | if(state.cur_ != begin) |
342 | { |
343 | not_null.restore(); |
344 | } |
345 | |
346 | do |
347 | { |
348 | sub0begin = state.cur_; |
349 | if(access::match(re, state)) |
350 | { |
351 | access::set_prefix_suffix(what, begin, end); |
352 | return true; |
353 | } |
354 | |
355 | // handle partial matches |
356 | else if(partial_ok && state.found_partial_match_) |
357 | { |
358 | state.set_partial_match(); |
359 | return true; |
360 | } |
361 | |
362 | BOOST_ASSERT(state.cur_ == sub0begin); |
363 | not_null.restore(); |
364 | } |
365 | while(state.cur_ != state.end_ && (++state.cur_, find(state))); |
366 | } |
367 | } |
368 | |
369 | // Otherwise, use brute force search at every position. |
370 | else |
371 | { |
372 | for(;;) |
373 | { |
374 | if(access::match(re, state)) |
375 | { |
376 | access::set_prefix_suffix(what, begin, end); |
377 | return true; |
378 | } |
379 | |
380 | // handle partial matches |
381 | else if(partial_ok && state.found_partial_match_) |
382 | { |
383 | state.set_partial_match(); |
384 | return true; |
385 | } |
386 | |
387 | else if(end == sub0begin) |
388 | { |
389 | break; |
390 | } |
391 | |
392 | BOOST_ASSERT(state.cur_ == sub0begin); |
393 | state.cur_ = ++sub0begin; |
394 | not_null.restore(); |
395 | } |
396 | } |
397 | |
398 | access::reset(what); |
399 | return false; |
400 | } |
401 | } // namespace detail |
402 | |
403 | |
404 | /// \brief Determines whether there is some sub-sequence within <tt>[begin,end)</tt> |
405 | /// that matches the regular expression \c re. |
406 | /// |
407 | /// Determines whether there is some sub-sequence within <tt>[begin,end)</tt> that matches |
408 | /// the regular expression \c re. |
409 | /// |
410 | /// \pre Type \c BidiIter meets the requirements of a Bidirectional Iterator (24.1.4). |
411 | /// \pre <tt>[begin,end)</tt> denotes a valid iterator range. |
412 | /// \param begin The beginning of the sequence |
413 | /// \param end The end of the sequence |
414 | /// \param what The \c match_results struct into which the sub_matches will be written |
415 | /// \param re The regular expression object to use |
416 | /// \param flags Optional match flags, used to control how the expression is matched against |
417 | /// the sequence. (See \c match_flag_type.) |
418 | /// \return \c true if a match is found, \c false otherwise |
419 | /// \throw regex_error on stack exhaustion |
420 | template<typename BidiIter> |
421 | inline bool regex_search |
422 | ( |
423 | BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
424 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
425 | , match_results<BidiIter> &what |
426 | , basic_regex<BidiIter> const &re |
427 | , regex_constants::match_flag_type flags = regex_constants::match_default |
428 | ) |
429 | { |
430 | typedef detail::core_access<BidiIter> access; |
431 | |
432 | // a default-constructed regex matches nothing |
433 | if(0 == re.regex_id()) |
434 | { |
435 | access::reset(what); |
436 | return false; |
437 | } |
438 | |
439 | // the state object holds matching state and |
440 | // is passed by reference to all the matchers |
441 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
442 | return detail::regex_search_impl(state, re); |
443 | } |
444 | |
445 | /// \overload |
446 | /// |
447 | template<typename BidiIter> |
448 | inline bool regex_search |
449 | ( |
450 | BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
451 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
452 | , basic_regex<BidiIter> const &re |
453 | , regex_constants::match_flag_type flags = regex_constants::match_default |
454 | ) |
455 | { |
456 | typedef detail::core_access<BidiIter> access; |
457 | |
458 | // a default-constructed regex matches nothing |
459 | if(0 == re.regex_id()) |
460 | { |
461 | return false; |
462 | } |
463 | |
464 | // BUGBUG this is inefficient |
465 | match_results<BidiIter> what; |
466 | // the state object holds matching state and |
467 | // is passed by reference to all the matchers |
468 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
469 | return detail::regex_search_impl(state, re); |
470 | } |
471 | |
472 | /// \overload |
473 | /// |
474 | template<typename Char> |
475 | inline bool regex_search |
476 | ( |
477 | BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin |
478 | , match_results<Char *> &what |
479 | , basic_regex<Char *> const &re |
480 | , regex_constants::match_flag_type flags = regex_constants::match_default |
481 | ) |
482 | { |
483 | typedef detail::core_access<Char *> access; |
484 | |
485 | // a default-constructed regex matches nothing |
486 | if(0 == re.regex_id()) |
487 | { |
488 | access::reset(what); |
489 | return false; |
490 | } |
491 | |
492 | // BUGBUG this is inefficient |
493 | typedef typename remove_const<Char>::type char_type; |
494 | Char *end = begin + std::char_traits<char_type>::length(begin); |
495 | // the state object holds matching state and |
496 | // is passed by reference to all the matchers |
497 | detail::match_state<Char *> state(begin, end, what, *access::get_regex_impl(re), flags); |
498 | return detail::regex_search_impl(state, re); |
499 | } |
500 | |
501 | /// \overload |
502 | /// |
503 | template<typename BidiRange, typename BidiIter> |
504 | inline bool regex_search |
505 | ( |
506 | BidiRange &rng |
507 | , match_results<BidiIter> &what |
508 | , basic_regex<BidiIter> const &re |
509 | , regex_constants::match_flag_type flags = regex_constants::match_default |
510 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
511 | ) |
512 | { |
513 | typedef detail::core_access<BidiIter> access; |
514 | |
515 | // a default-constructed regex matches nothing |
516 | if(0 == re.regex_id()) |
517 | { |
518 | access::reset(what); |
519 | return false; |
520 | } |
521 | |
522 | // Note that the result iterator of the range must be convertible |
523 | // to BidiIter here. |
524 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
525 | // the state object holds matching state and |
526 | // is passed by reference to all the matchers |
527 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
528 | return detail::regex_search_impl(state, re); |
529 | } |
530 | |
531 | /// \overload |
532 | /// |
533 | template<typename BidiRange, typename BidiIter> |
534 | inline bool regex_search |
535 | ( |
536 | BidiRange const &rng |
537 | , match_results<BidiIter> &what |
538 | , basic_regex<BidiIter> const &re |
539 | , regex_constants::match_flag_type flags = regex_constants::match_default |
540 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
541 | ) |
542 | { |
543 | typedef detail::core_access<BidiIter> access; |
544 | |
545 | // a default-constructed regex matches nothing |
546 | if(0 == re.regex_id()) |
547 | { |
548 | access::reset(what); |
549 | return false; |
550 | } |
551 | |
552 | // Note that the result iterator of the range must be convertible |
553 | // to BidiIter here. |
554 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
555 | // the state object holds matching state and |
556 | // is passed by reference to all the matchers |
557 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
558 | return detail::regex_search_impl(state, re); |
559 | } |
560 | |
561 | /// \overload |
562 | /// |
563 | template<typename Char> |
564 | inline bool regex_search |
565 | ( |
566 | BOOST_XPR_NONDEDUCED_TYPE_(Char) *begin |
567 | , basic_regex<Char *> const &re |
568 | , regex_constants::match_flag_type flags = regex_constants::match_default |
569 | ) |
570 | { |
571 | typedef detail::core_access<Char *> access; |
572 | |
573 | // a default-constructed regex matches nothing |
574 | if(0 == re.regex_id()) |
575 | { |
576 | return false; |
577 | } |
578 | |
579 | // BUGBUG this is inefficient |
580 | match_results<Char *> what; |
581 | // BUGBUG this is inefficient |
582 | typedef typename remove_const<Char>::type char_type; |
583 | Char *end = begin + std::char_traits<char_type>::length(begin); |
584 | // the state object holds matching state and |
585 | // is passed by reference to all the matchers |
586 | detail::match_state<Char *> state(begin, end, what, *access::get_regex_impl(re), flags); |
587 | return detail::regex_search_impl(state, re); |
588 | } |
589 | |
590 | /// \overload |
591 | /// |
592 | template<typename BidiRange, typename BidiIter> |
593 | inline bool regex_search |
594 | ( |
595 | BidiRange &rng |
596 | , basic_regex<BidiIter> const &re |
597 | , regex_constants::match_flag_type flags = regex_constants::match_default |
598 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
599 | ) |
600 | { |
601 | typedef detail::core_access<BidiIter> access; |
602 | |
603 | // a default-constructed regex matches nothing |
604 | if(0 == re.regex_id()) |
605 | { |
606 | return false; |
607 | } |
608 | |
609 | // BUGBUG this is inefficient |
610 | match_results<BidiIter> what; |
611 | // Note that the result iterator of the range must be convertible |
612 | // to BidiIter here. |
613 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
614 | // the state object holds matching state and |
615 | // is passed by reference to all the matchers |
616 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
617 | return detail::regex_search_impl(state, re); |
618 | } |
619 | |
620 | /// \overload |
621 | /// |
622 | template<typename BidiRange, typename BidiIter> |
623 | inline bool regex_search |
624 | ( |
625 | BidiRange const &rng |
626 | , basic_regex<BidiIter> const &re |
627 | , regex_constants::match_flag_type flags = regex_constants::match_default |
628 | , typename disable_if<detail::is_char_ptr<BidiRange> >::type * = 0 |
629 | ) |
630 | { |
631 | typedef detail::core_access<BidiIter> access; |
632 | |
633 | // a default-constructed regex matches nothing |
634 | if(0 == re.regex_id()) |
635 | { |
636 | return false; |
637 | } |
638 | |
639 | // BUGBUG this is inefficient |
640 | match_results<BidiIter> what; |
641 | // Note that the result iterator of the range must be convertible |
642 | // to BidiIter here. |
643 | BidiIter begin = boost::begin(rng), end = boost::end(rng); |
644 | // the state object holds matching state and |
645 | // is passed by reference to all the matchers |
646 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
647 | return detail::regex_search_impl(state, re); |
648 | } |
649 | |
650 | |
651 | /////////////////////////////////////////////////////////////////////////////// |
652 | // regex_replace |
653 | /////////////////////////////////////////////////////////////////////////////// |
654 | |
655 | namespace detail |
656 | { |
657 | /////////////////////////////////////////////////////////////////////////////// |
658 | // regex_replace_impl |
659 | template<typename OutIter, typename BidiIter, typename Formatter> |
660 | inline OutIter regex_replace_impl |
661 | ( |
662 | OutIter out |
663 | , BidiIter begin |
664 | , BidiIter end |
665 | , basic_regex<BidiIter> const &re |
666 | , Formatter const &format |
667 | , regex_constants::match_flag_type flags = regex_constants::match_default |
668 | ) |
669 | { |
670 | using namespace regex_constants; |
671 | typedef detail::core_access<BidiIter> access; |
672 | BOOST_ASSERT(0 != re.regex_id()); |
673 | |
674 | BidiIter cur = begin; |
675 | match_results<BidiIter> what; |
676 | detail::match_state<BidiIter> state(begin, end, what, *access::get_regex_impl(re), flags); |
677 | bool const yes_copy = (0 == (flags & format_no_copy)); |
678 | |
679 | if(detail::regex_search_impl(state, re)) |
680 | { |
681 | if(yes_copy) |
682 | { |
683 | out = std::copy(cur, what[0].first, out); |
684 | } |
685 | |
686 | out = what.format(out, format, flags); |
687 | cur = state.cur_ = state.next_search_ = what[0].second; |
688 | |
689 | if(0 == (flags & format_first_only)) |
690 | { |
691 | bool not_null = (0 == what.length()); |
692 | state.reset(what, *access::get_regex_impl(re)); |
693 | while(detail::regex_search_impl(state, re, not_null)) |
694 | { |
695 | if(yes_copy) |
696 | { |
697 | out = std::copy(cur, what[0].first, out); |
698 | } |
699 | |
700 | access::set_prefix_suffix(what, begin, end); |
701 | out = what.format(out, format, flags); |
702 | cur = state.cur_ = state.next_search_ = what[0].second; |
703 | not_null = (0 == what.length()); |
704 | state.reset(what, *access::get_regex_impl(re)); |
705 | } |
706 | } |
707 | } |
708 | |
709 | if(yes_copy) |
710 | { |
711 | out = std::copy(cur, end, out); |
712 | } |
713 | |
714 | return out; |
715 | } |
716 | } // namespace detail |
717 | |
718 | /// \brief Build an output sequence given an input sequence, a regex, and a format string or |
719 | /// a formatter object, function, or expression. |
720 | /// |
721 | /// Constructs a \c regex_iterator object: <tt>regex_iterator\< BidiIter \> i(begin, end, re, flags)</tt>, |
722 | /// and uses \c i to enumerate through all of the matches m of type <tt>match_results\< BidiIter \></tt> that |
723 | /// occur within the sequence <tt>[begin, end)</tt>. If no such matches are found and <tt>!(flags \& format_no_copy)</tt> |
724 | /// then calls <tt>std::copy(begin, end, out)</tt>. Otherwise, for each match found, if <tt>!(flags \& format_no_copy)</tt> |
725 | /// calls <tt>std::copy(m.prefix().first, m.prefix().second, out)</tt>, and then calls <tt>m.format(out, format, flags)</tt>. |
726 | /// Finally if <tt>!(flags \& format_no_copy)</tt> calls <tt>std::copy(last_m.suffix().first, last_m.suffix().second, out)</tt> |
727 | /// where \c last_m is a copy of the last match found. |
728 | /// |
729 | /// If <tt>flags \& format_first_only</tt> is non-zero then only the first match found is replaced. |
730 | /// |
731 | /// \pre Type \c BidiIter meets the requirements of a Bidirectional Iterator (24.1.4). |
732 | /// \pre Type \c OutIter meets the requirements of an Output Iterator (24.1.2). |
733 | /// \pre Type \c Formatter models \c ForwardRange, <tt>Callable\<match_results\<BidiIter\> \></tt>, |
734 | /// <tt>Callable\<match_results\<BidiIter\>, OutIter\></tt>, or |
735 | /// <tt>Callable\<match_results\<BidiIter\>, OutIter, regex_constants::match_flag_type\></tt>; |
736 | /// or else it is a null-terminated format string, or an expression template |
737 | /// representing a formatter lambda expression. |
738 | /// \pre <tt>[begin,end)</tt> denotes a valid iterator range. |
739 | /// \param out An output iterator into which the output sequence is written. |
740 | /// \param begin The beginning of the input sequence. |
741 | /// \param end The end of the input sequence. |
742 | /// \param re The regular expression object to use. |
743 | /// \param format The format string used to format the replacement sequence, |
744 | /// or a formatter function, function object, or expression. |
745 | /// \param flags Optional match flags, used to control how the expression is matched against |
746 | /// the sequence. (See \c match_flag_type.) |
747 | /// \return The value of the output iterator after the output sequence has been written to it. |
748 | /// \throw regex_error on stack exhaustion or invalid format string. |
749 | template<typename OutIter, typename BidiIter, typename Formatter> |
750 | inline OutIter regex_replace |
751 | ( |
752 | OutIter out |
753 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
754 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
755 | , basic_regex<BidiIter> const &re |
756 | , Formatter const &format |
757 | , regex_constants::match_flag_type flags = regex_constants::match_default |
758 | , typename disable_if<detail::is_char_ptr<Formatter> >::type * = 0 |
759 | ) |
760 | { |
761 | // Default-constructed regexes match nothing |
762 | if(0 == re.regex_id()) |
763 | { |
764 | if((0 == (flags & regex_constants::format_no_copy))) |
765 | { |
766 | out = std::copy(begin, end, out); |
767 | } |
768 | |
769 | return out; |
770 | } |
771 | |
772 | return detail::regex_replace_impl(out, begin, end, re, format, flags); |
773 | } |
774 | |
775 | /// \overload |
776 | /// |
777 | template<typename OutIter, typename BidiIter> |
778 | inline OutIter regex_replace |
779 | ( |
780 | OutIter out |
781 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) begin |
782 | , BOOST_XPR_NONDEDUCED_TYPE_(BidiIter) end |
783 | , basic_regex<BidiIter> const &re |
784 | , typename iterator_value<BidiIter>::type const *format |
785 | , regex_constants::match_flag_type flags = regex_constants::match_default |
786 | ) |
787 | { |
788 | // Default-constructed regexes match nothing |
789 | if(0 == re.regex_id()) |
790 | { |
791 | if((0 == (flags & regex_constants::format_no_copy))) |
792 | { |
793 | out = std::copy(begin, end, out); |
794 | } |
795 | |
796 | return out; |
797 | } |
798 | |
799 | return detail::regex_replace_impl(out, begin, end, re, format, flags); |
800 | } |
801 | |
802 | /// \overload |
803 | /// |
804 | template<typename BidiContainer, typename BidiIter, typename Formatter> |
805 | inline BidiContainer regex_replace |
806 | ( |
807 | BidiContainer &str |
808 | , basic_regex<BidiIter> const &re |
809 | , Formatter const &format |
810 | , regex_constants::match_flag_type flags = regex_constants::match_default |
811 | , typename disable_if<mpl::or_<detail::is_char_ptr<BidiContainer>, detail::is_char_ptr<Formatter> > >::type * = 0 |
812 | ) |
813 | { |
814 | BidiContainer result; |
815 | // Note that the result iterator of the range must be convertible |
816 | // to BidiIter here. |
817 | BidiIter begin = boost::begin(str), end = boost::end(str); |
818 | |
819 | // Default-constructed regexes match nothing |
820 | if(0 == re.regex_id()) |
821 | { |
822 | if((0 == (flags & regex_constants::format_no_copy))) |
823 | { |
824 | std::copy(begin, end, std::back_inserter(result)); |
825 | } |
826 | |
827 | return result; |
828 | } |
829 | |
830 | detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags); |
831 | return result; |
832 | } |
833 | |
834 | /// \overload |
835 | /// |
836 | template<typename BidiContainer, typename BidiIter, typename Formatter> |
837 | inline BidiContainer regex_replace |
838 | ( |
839 | BidiContainer const &str |
840 | , basic_regex<BidiIter> const &re |
841 | , Formatter const &format |
842 | , regex_constants::match_flag_type flags = regex_constants::match_default |
843 | , typename disable_if<mpl::or_<detail::is_char_ptr<BidiContainer>, detail::is_char_ptr<Formatter> > >::type * = 0 |
844 | ) |
845 | { |
846 | BidiContainer result; |
847 | // Note that the result iterator of the range must be convertible |
848 | // to BidiIter here. |
849 | BidiIter begin = boost::begin(str), end = boost::end(str); |
850 | |
851 | // Default-constructed regexes match nothing |
852 | if(0 == re.regex_id()) |
853 | { |
854 | if((0 == (flags & regex_constants::format_no_copy))) |
855 | { |
856 | std::copy(begin, end, std::back_inserter(result)); |
857 | } |
858 | |
859 | return result; |
860 | } |
861 | |
862 | detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags); |
863 | return result; |
864 | } |
865 | |
866 | /// \overload |
867 | /// |
868 | template<typename Char, typename Formatter> |
869 | inline std::basic_string<typename remove_const<Char>::type> regex_replace |
870 | ( |
871 | BOOST_XPR_NONDEDUCED_TYPE_(Char) *str |
872 | , basic_regex<Char *> const &re |
873 | , Formatter const &format |
874 | , regex_constants::match_flag_type flags = regex_constants::match_default |
875 | , typename disable_if<detail::is_char_ptr<Formatter> >::type * = 0 |
876 | ) |
877 | { |
878 | typedef typename remove_const<Char>::type char_type; |
879 | std::basic_string<char_type> result; |
880 | |
881 | // Default-constructed regexes match nothing |
882 | if(0 == re.regex_id()) |
883 | { |
884 | if((0 == (flags & regex_constants::format_no_copy))) |
885 | { |
886 | result = str; |
887 | } |
888 | |
889 | return result; |
890 | } |
891 | |
892 | Char *end = str + std::char_traits<char_type>::length(str); |
893 | detail::regex_replace_impl(std::back_inserter(result), str, end, re, format, flags); |
894 | return result; |
895 | } |
896 | |
897 | /// \overload |
898 | /// |
899 | template<typename BidiContainer, typename BidiIter> |
900 | inline BidiContainer regex_replace |
901 | ( |
902 | BidiContainer &str |
903 | , basic_regex<BidiIter> const &re |
904 | , typename iterator_value<BidiIter>::type const *format |
905 | , regex_constants::match_flag_type flags = regex_constants::match_default |
906 | , typename disable_if<detail::is_char_ptr<BidiContainer> >::type * = 0 |
907 | ) |
908 | { |
909 | BidiContainer result; |
910 | // Note that the result iterator of the range must be convertible |
911 | // to BidiIter here. |
912 | BidiIter begin = boost::begin(str), end = boost::end(str); |
913 | |
914 | // Default-constructed regexes match nothing |
915 | if(0 == re.regex_id()) |
916 | { |
917 | if((0 == (flags & regex_constants::format_no_copy))) |
918 | { |
919 | std::copy(begin, end, std::back_inserter(result)); |
920 | } |
921 | |
922 | return result; |
923 | } |
924 | |
925 | detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags); |
926 | return result; |
927 | } |
928 | |
929 | /// \overload |
930 | /// |
931 | template<typename BidiContainer, typename BidiIter> |
932 | inline BidiContainer regex_replace |
933 | ( |
934 | BidiContainer const &str |
935 | , basic_regex<BidiIter> const &re |
936 | , typename iterator_value<BidiIter>::type const *format |
937 | , regex_constants::match_flag_type flags = regex_constants::match_default |
938 | , typename disable_if<detail::is_char_ptr<BidiContainer> >::type * = 0 |
939 | ) |
940 | { |
941 | BidiContainer result; |
942 | // Note that the result iterator of the range must be convertible |
943 | // to BidiIter here. |
944 | BidiIter begin = boost::begin(str), end = boost::end(str); |
945 | |
946 | // Default-constructed regexes match nothing |
947 | if(0 == re.regex_id()) |
948 | { |
949 | if((0 == (flags & regex_constants::format_no_copy))) |
950 | { |
951 | std::copy(begin, end, std::back_inserter(result)); |
952 | } |
953 | |
954 | return result; |
955 | } |
956 | |
957 | detail::regex_replace_impl(std::back_inserter(result), begin, end, re, format, flags); |
958 | return result; |
959 | } |
960 | |
961 | /// \overload |
962 | /// |
963 | template<typename Char> |
964 | inline std::basic_string<typename remove_const<Char>::type> regex_replace |
965 | ( |
966 | BOOST_XPR_NONDEDUCED_TYPE_(Char) *str |
967 | , basic_regex<Char *> const &re |
968 | , typename add_const<Char>::type *format |
969 | , regex_constants::match_flag_type flags = regex_constants::match_default |
970 | ) |
971 | { |
972 | typedef typename remove_const<Char>::type char_type; |
973 | std::basic_string<char_type> result; |
974 | |
975 | // Default-constructed regexes match nothing |
976 | if(0 == re.regex_id()) |
977 | { |
978 | if((0 == (flags & regex_constants::format_no_copy))) |
979 | { |
980 | result = str; |
981 | } |
982 | |
983 | return result; |
984 | } |
985 | |
986 | Char *end = str + std::char_traits<char_type>::length(str); |
987 | detail::regex_replace_impl(std::back_inserter(result), str, end, re, format, flags); |
988 | return result; |
989 | } |
990 | |
991 | }} // namespace boost::xpressive |
992 | |
993 | #endif |
994 | |