]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 |