Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1707 lines
55 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. /*
  9. *
  10. * Copyright (c) 1998-9
  11. * Dr John Maddock
  12. *
  13. * Permission to use, copy, modify, distribute and sell this software
  14. * and its documentation for any purpose is hereby granted without fee,
  15. * provided that the above copyright notice appear in all copies and
  16. * that both that copyright notice and this permission notice appear
  17. * in supporting documentation. Dr John Maddock makes no representations
  18. * about the suitability of this software for any purpose.
  19. * It is provided "as is" without express or implied warranty.
  20. *
  21. */
  22. /*
  23. * FILE regmatch.h
  24. * VERSION 2.12
  25. * regular expression matching algorithms
  26. */
  27. #ifndef __REGMATCH_H
  28. #define __REGMATCH_H
  29. JM_NAMESPACE(__JM)
  30. template <class iterator, class charT, class traits_type, class Allocator>
  31. iterator RE_CALL re_is_set_member(iterator next,
  32. iterator last,
  33. re_set_long* set,
  34. const reg_expression<charT, traits_type, Allocator>& e)
  35. {
  36. const charT* p = (const charT*)(set+1);
  37. iterator ptr;
  38. unsigned int i;
  39. bool icase = e.flags() & regbase::icase;
  40. // try and match a single character, could be a multi-character
  41. // collating element...
  42. for(i = 0; i < set->csingles; ++i)
  43. {
  44. ptr = next;
  45. while(*p && (ptr != last))
  46. {
  47. if(traits_type::translate(*ptr, icase MAYBE_PASS_LOCALE(e.locale())) != *p)
  48. break;
  49. ++p;
  50. ++ptr;
  51. }
  52. if(*p == 0) // if null we've matched
  53. return set->isnot ? next : (ptr == next) ? ++next : ptr;
  54. while(*p)++p;
  55. ++p; // skip null
  56. }
  57. charT col = traits_type::translate(*next, icase MAYBE_PASS_LOCALE(e.locale()));
  58. if(set->cranges || set->cequivalents)
  59. {
  60. re_str<charT> s2(col);
  61. re_str<charT> s1;
  62. //
  63. // try and match a range, NB only a single character can match
  64. if(set->cranges)
  65. {
  66. if(e.flags() & regbase::nocollate)
  67. s1 = s2;
  68. else
  69. traits_type::transform(s1, s2 MAYBE_PASS_LOCALE(e.locale()));
  70. for(i = 0; i < set->cranges; ++i)
  71. {
  72. if(s1 <= p)
  73. {
  74. while(*p)++p;
  75. ++p;
  76. if(s1 >= p)
  77. return set->isnot ? next : ++next;
  78. }
  79. else
  80. {
  81. // skip first string
  82. while(*p)++p;
  83. ++p;
  84. }
  85. // skip second string
  86. while(*p)++p;
  87. ++p;
  88. }
  89. }
  90. //
  91. // try and match an equivalence class, NB only a single character can match
  92. if(set->cequivalents)
  93. {
  94. traits_type::transform_primary(s1, s2 MAYBE_PASS_LOCALE(e.locale()));
  95. for(i = 0; i < set->cequivalents; ++i)
  96. {
  97. if(s1 == p)
  98. return set->isnot ? next : ++next;
  99. // skip string
  100. while(*p)++p;
  101. ++p;
  102. }
  103. }
  104. }
  105. if(traits_type::is_class(col, set->cclasses MAYBE_PASS_LOCALE(e.locale())) == true)
  106. return set->isnot ? next : ++next;
  107. return set->isnot ? ++next : next;
  108. }
  109. template <class iterator, class Allocator>
  110. class __priv_match_data
  111. {
  112. public:
  113. typedef JM_MAYBE_TYPENAME REBIND_TYPE(int, Allocator) i_alloc;
  114. typedef JM_MAYBE_TYPENAME REBIND_TYPE(iterator, Allocator) it_alloc;
  115. reg_match_base<iterator, Allocator> temp_match;
  116. // failure stacks:
  117. jstack<reg_match_base<iterator, Allocator>, Allocator> matches;
  118. jstack<iterator, Allocator> prev_pos;
  119. jstack<const re_syntax_base*, Allocator> prev_record;
  120. jstack<int, Allocator> prev_acc;
  121. int* accumulators;
  122. unsigned int caccumulators;
  123. iterator* loop_starts;
  124. __priv_match_data(const reg_match_base<iterator, Allocator>&);
  125. ~__priv_match_data()
  126. {
  127. free();
  128. }
  129. void free();
  130. void set_accumulator_size(unsigned int size);
  131. int* get_accumulators()
  132. {
  133. return accumulators;
  134. }
  135. iterator* get_loop_starts()
  136. {
  137. return loop_starts;
  138. }
  139. };
  140. template <class iterator, class Allocator>
  141. __priv_match_data<iterator, Allocator>::__priv_match_data(const reg_match_base<iterator, Allocator>& m)
  142. : temp_match(m), matches(64, m.allocator()), prev_pos(64, m.allocator()), prev_record(64, m.allocator())
  143. {
  144. accumulators = 0;
  145. caccumulators = 0;
  146. loop_starts = 0;
  147. }
  148. template <class iterator, class Allocator>
  149. void __priv_match_data<iterator, Allocator>::set_accumulator_size(unsigned int size)
  150. {
  151. if(size > caccumulators)
  152. {
  153. free();
  154. caccumulators = size;
  155. accumulators = i_alloc(temp_match.allocator()).allocate(caccumulators);
  156. loop_starts = it_alloc(temp_match.allocator()).allocate(caccumulators);
  157. for(unsigned i = 0; i < caccumulators; ++i)
  158. new (loop_starts + i) iterator();
  159. }
  160. }
  161. template <class iterator, class Allocator>
  162. void __priv_match_data<iterator, Allocator>::free()
  163. {
  164. if(caccumulators)
  165. {
  166. //REBIND_INSTANCE(int, Allocator, temp_match.allocator()).deallocate(accumulators, caccumulators);
  167. i_alloc temp1(temp_match.allocator());
  168. temp1.deallocate(accumulators, caccumulators);
  169. for(unsigned i = 0; i < caccumulators; ++i)
  170. jm_destroy(loop_starts + i);
  171. //REBIND_INSTANCE(iterator, Allocator, temp_match.allocator()).deallocate(loop_starts, caccumulators);
  172. it_alloc temp2(temp_match.allocator());
  173. temp2.deallocate(loop_starts, caccumulators);
  174. }
  175. }
  176. //
  177. // proc query_match
  178. // returns true if the specified regular expression matches
  179. // at position first. Fills in what matched in m.
  180. //
  181. template <class iterator, class Allocator, class charT, class traits, class Allocator2>
  182. bool query_match(iterator first, iterator last, reg_match<iterator, Allocator>& m, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default)
  183. {
  184. // prepare m for failure:
  185. if((flags & match_init) == 0)
  186. {
  187. m.set_size(e.mark_count(), first, last);
  188. }
  189. __priv_match_data<iterator, Allocator> pd(m);
  190. iterator restart;
  191. return query_match_aux(first, last, m, e, flags, pd, &restart);
  192. }
  193. //
  194. // query_match convenience interfaces:
  195. #ifndef JM_NO_PARTIAL_FUNC_SPEC
  196. //
  197. // this isn't really a partial specialisation, but template function
  198. // overloading - if the compiler doesn't support partial specialisation
  199. // then it really won't support this either:
  200. template <class charT, class Allocator, class traits, class Allocator2>
  201. inline bool query_match(const charT* str,
  202. reg_match<const charT*, Allocator>& m,
  203. const reg_expression<charT, traits, Allocator2>& e,
  204. unsigned flags = match_default)
  205. {
  206. return query_match(str, str + traits::length(str), m, e, flags);
  207. }
  208. #ifndef JM_NO_STRING_H
  209. template <class ST, class SA, class Allocator, class charT, class traits, class Allocator2>
  210. inline bool query_match(const __JM_STD::basic_string<charT, ST, SA>& s,
  211. reg_match<typename __JM_STD::basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
  212. const reg_expression<charT, traits, Allocator2>& e,
  213. unsigned flags = match_default)
  214. {
  215. return query_match(s.begin(), s.end(), m, e, flags);
  216. }
  217. #endif
  218. #else // partial specialisation
  219. inline bool query_match(const char* str,
  220. cmatch& m,
  221. const regex& e,
  222. unsigned flags = match_default)
  223. {
  224. return query_match(str, str + regex::traits_type::length(str), m, e, flags);
  225. }
  226. #ifndef JM_NO_WCSTRING
  227. inline bool query_match(const wchar_t* str,
  228. wcmatch& m,
  229. const wregex& e,
  230. unsigned flags = match_default)
  231. {
  232. return query_match(str, str + wregex::traits_type::length(str), m, e, flags);
  233. }
  234. #endif
  235. #ifndef JM_NO_STRING_H
  236. inline bool query_match(const __JM_STD::string& s,
  237. reg_match<__JM_STD::string::const_iterator, regex::alloc_type>& m,
  238. const regex& e,
  239. unsigned flags = match_default)
  240. {
  241. return query_match(s.begin(), s.end(), m, e, flags);
  242. }
  243. #if !defined(JM_NO_STRING_DEF_ARGS) && !defined(JM_NO_WCSTRING)
  244. inline bool query_match(const __JM_STD::basic_string<wchar_t>& s,
  245. reg_match<__JM_STD::basic_string<wchar_t>::const_iterator, wregex::alloc_type>& m,
  246. const wregex& e,
  247. unsigned flags = match_default)
  248. {
  249. return query_match(s.begin(), s.end(), m, e, flags);
  250. }
  251. #endif
  252. #endif
  253. #endif
  254. #if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
  255. //
  256. // Ugly ugly hack,
  257. // template don't merge if they contain switch statements so declare these
  258. // templates in unnamed namespace (ie with internal linkage), each translation
  259. // unit then gets its own local copy, it works seemlessly but bloats the app.
  260. namespace{
  261. #endif
  262. template <class iterator, class Allocator, class charT, class traits, class Allocator2>
  263. bool query_match_aux(iterator first,
  264. iterator last,
  265. reg_match<iterator, Allocator>& m,
  266. const reg_expression<charT, traits, Allocator2>& e,
  267. unsigned flags,
  268. __priv_match_data<iterator, Allocator>& pd,
  269. iterator* restart)
  270. {
  271. if(e.flags() & regbase::failbit)
  272. return false;
  273. typedef typename traits::size_type traits_size_type;
  274. typedef typename traits::uchar_type traits_uchar_type;
  275. typedef typename is_byte<charT>::width_type width_type;
  276. #ifdef RE_LOCALE_CPP
  277. const __JM_STD::locale& locale_inst = e.locale();
  278. #endif
  279. // declare some local aliases to reduce pointer loads
  280. // good optimising compilers should make this unnecessary!!
  281. jstack<reg_match_base<iterator, Allocator>, Allocator>& matches = pd.matches;
  282. jstack<iterator, Allocator>& prev_pos = pd.prev_pos;
  283. jstack<const re_syntax_base*, Allocator>& prev_record = pd.prev_record;
  284. jstack<int, Allocator>& prev_acc = pd.prev_acc;
  285. reg_match_base<iterator, Allocator>& temp_match = pd.temp_match;
  286. temp_match.set_first(first);
  287. //temp_match.set_size(e.mark_count(), first, last);
  288. register const re_syntax_base* ptr = e.first();
  289. bool match_found = false;
  290. bool need_push_match = (e.mark_count() > 1);
  291. int cur_acc = -1; // no active accumulator
  292. pd.set_accumulator_size(e.repeat_count());
  293. int* accumulators = pd.get_accumulators();
  294. iterator* start_loop = pd.get_loop_starts();
  295. int k; // for loops
  296. bool icase = e.flags() & regbase::icase;
  297. *restart = first;
  298. iterator base = first;
  299. // prepare m for failure:
  300. /*
  301. if((flags & match_init) == 0)
  302. {
  303. m.init_fail(first, last);
  304. } */
  305. retry:
  306. while(first != last)
  307. {
  308. jm_assert(ptr);
  309. switch(ptr->type)
  310. {
  311. case syntax_element_match:
  312. match_jump:
  313. {
  314. // match found, save then fallback in case we missed a
  315. // longer one.
  316. if((flags & match_not_null) && (first == temp_match[0].first))
  317. goto failure;
  318. temp_match.set_second(first);
  319. m.maybe_assign(temp_match);
  320. match_found = true;
  321. if((flags & match_any) || ((first == last) && (need_push_match == false)))
  322. {
  323. // either we don't care what we match or we've matched
  324. // the whole string and can't match anything longer.
  325. while(matches.empty() == false)
  326. matches.pop();
  327. while(prev_pos.empty() == false)
  328. prev_pos.pop();
  329. while(prev_record.empty() == false)
  330. prev_record.pop();
  331. while(prev_acc.empty() == false)
  332. prev_acc.pop();
  333. return true;
  334. }
  335. }
  336. goto failure;
  337. case syntax_element_startmark:
  338. temp_match.set_first(first, ((re_brace*)ptr)->index);
  339. ptr = ptr->next.p;
  340. break;
  341. case syntax_element_endmark:
  342. temp_match.set_second(first, ((re_brace*)ptr)->index);
  343. ptr = ptr->next.p;
  344. break;
  345. case syntax_element_literal:
  346. {
  347. unsigned int len = ((re_literal*)ptr)->length;
  348. charT* what = (charT*)(((re_literal*)ptr) + 1);
  349. //
  350. // compare string with what we stored in
  351. // our records:
  352. for(unsigned int i = 0; i < len; ++i, ++first)
  353. {
  354. if((first == last) || (traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst)) != what[i]))
  355. goto failure;
  356. }
  357. ptr = ptr->next.p;
  358. break;
  359. }
  360. case syntax_element_start_line:
  361. outer_line_check:
  362. if(first == temp_match[0].first)
  363. {
  364. // we're at the start of the buffer
  365. if(flags & match_prev_avail)
  366. {
  367. inner_line_check:
  368. // check the previous value even though its before
  369. // the start of our "buffer".
  370. iterator t(first);
  371. --t;
  372. if(traits::is_separator(*t) && !((*t == '\r') && (*first == '\n')) )
  373. {
  374. ptr = ptr->next.p;
  375. continue;
  376. }
  377. goto failure;
  378. }
  379. if((flags & match_not_bol) == 0)
  380. {
  381. ptr = ptr->next.p;
  382. continue;
  383. }
  384. goto failure;
  385. }
  386. // we're in the middle of the string
  387. goto inner_line_check;
  388. case syntax_element_end_line:
  389. // we're not yet at the end so *first is always valid:
  390. if(traits::is_separator(*first))
  391. {
  392. if((first != base) || (flags & match_prev_avail))
  393. {
  394. // check that we're not in the middle of \r\n sequence
  395. iterator t(first);
  396. --t;
  397. if((*t == '\r') && (*first == '\n'))
  398. {
  399. goto failure;
  400. }
  401. }
  402. ptr = ptr->next.p;
  403. continue;
  404. }
  405. goto failure;
  406. case syntax_element_wild:
  407. // anything except possibly NULL or \n:
  408. if(traits::is_separator(*first))
  409. {
  410. if(flags & match_not_dot_newline)
  411. goto failure;
  412. ptr = ptr->next.p;
  413. ++first;
  414. continue;
  415. }
  416. if(*first == charT(0))
  417. {
  418. if(flags & match_not_dot_null)
  419. goto failure;
  420. ptr = ptr->next.p;
  421. ++first;
  422. continue;
  423. }
  424. ptr = ptr->next.p;
  425. ++first;
  426. break;
  427. case syntax_element_word_boundary:
  428. {
  429. // prev and this character must be opposites:
  430. bool b = traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst));
  431. if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
  432. {
  433. if(flags & match_not_bow)
  434. b ^= true;
  435. else
  436. b ^= false;
  437. }
  438. else
  439. {
  440. --first;
  441. b ^= traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst));
  442. ++first;
  443. }
  444. if(b)
  445. {
  446. ptr = ptr->next.p;
  447. continue;
  448. }
  449. goto failure;
  450. }
  451. case syntax_element_within_word:
  452. // both prev and this character must be char_class_word:
  453. if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)))
  454. {
  455. bool b;
  456. if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
  457. b = false;
  458. else
  459. {
  460. --first;
  461. b = traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst));
  462. ++first;
  463. }
  464. if(b)
  465. {
  466. ptr = ptr->next.p;
  467. continue;
  468. }
  469. }
  470. goto failure;
  471. case syntax_element_word_start:
  472. if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
  473. {
  474. // start of buffer:
  475. if(flags & match_not_bow)
  476. goto failure;
  477. if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)))
  478. {
  479. ptr = ptr->next.p;
  480. continue;
  481. }
  482. goto failure;
  483. }
  484. // otherwise inside buffer:
  485. if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)))
  486. {
  487. iterator t(first);
  488. --t;
  489. if(traits::is_class(*t, char_class_word MAYBE_PASS_LOCALE(locale_inst)) == false)
  490. {
  491. ptr = ptr->next.p;
  492. continue;
  493. }
  494. }
  495. goto failure; // if we fall through to here then we've failed
  496. case syntax_element_word_end:
  497. if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
  498. goto failure; // start of buffer can't be end of word
  499. // otherwise inside buffer:
  500. if(traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)) == false)
  501. {
  502. iterator t(first);
  503. --t;
  504. if(traits::is_class(*t, char_class_word MAYBE_PASS_LOCALE(locale_inst)))
  505. {
  506. ptr = ptr->next.p;
  507. continue;
  508. }
  509. }
  510. goto failure; // if we fall through to here then we've failed
  511. case syntax_element_buffer_start:
  512. if((first != temp_match[0].first) || (flags & match_not_bob))
  513. goto failure;
  514. // OK match:
  515. ptr = ptr->next.p;
  516. break;
  517. case syntax_element_buffer_end:
  518. if((first != last) || (flags & match_not_eob))
  519. goto failure;
  520. // OK match:
  521. ptr = ptr->next.p;
  522. break;
  523. case syntax_element_backref:
  524. {
  525. // compare with what we previously matched:
  526. iterator i = temp_match[((re_brace*)ptr)->index].first;
  527. iterator j = temp_match[((re_brace*)ptr)->index].second;
  528. while(i != j)
  529. {
  530. if((first == last) || (traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst)) != traits::translate(*i, icase MAYBE_PASS_LOCALE(locale_inst))))
  531. goto failure;
  532. ++i;
  533. ++first;
  534. }
  535. ptr = ptr->next.p;
  536. break;
  537. }
  538. case syntax_element_long_set:
  539. {
  540. // let the traits class do the work:
  541. iterator t = re_is_set_member(first, last, (re_set_long*)ptr, e);
  542. if(t != first)
  543. {
  544. ptr = ptr->next.p;
  545. first = t;
  546. continue;
  547. }
  548. goto failure;
  549. }
  550. case syntax_element_set:
  551. // lookup character in table:
  552. if(((re_set*)ptr)->__map[(traits_uchar_type)traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))])
  553. {
  554. ptr = ptr->next.p;
  555. ++first;
  556. continue;
  557. }
  558. goto failure;
  559. case syntax_element_jump:
  560. ptr = ((re_jump*)ptr)->alt.p;
  561. continue;
  562. case syntax_element_alt:
  563. {
  564. // alt_jump:
  565. if(reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_jump*)ptr)->__map, (unsigned char)mask_take, width_type()))
  566. {
  567. // we can take the first alternative,
  568. // see if we need to push next alternative:
  569. if(reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_jump*)ptr)->__map, mask_skip, width_type()))
  570. {
  571. if(need_push_match)
  572. matches.push(temp_match);
  573. for(k = 0; k <= cur_acc; ++k)
  574. prev_pos.push(start_loop[k]);
  575. prev_pos.push(first);
  576. prev_record.push(ptr);
  577. for(k = 0; k <= cur_acc; ++k)
  578. prev_acc.push(accumulators[k]);
  579. prev_acc.push(cur_acc);
  580. }
  581. ptr = ptr->next.p;
  582. continue;
  583. }
  584. if(reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_jump*)ptr)->__map, mask_skip, width_type()))
  585. {
  586. ptr = ((re_jump*)ptr)->alt.p;
  587. continue;
  588. }
  589. goto failure; // neither option is possible
  590. }
  591. case syntax_element_rep:
  592. {
  593. // repeater_jump:
  594. // if we're moving to a higher id (nested repeats etc)
  595. // zero out our accumualtors:
  596. if(cur_acc < ((re_repeat*)ptr)->id)
  597. {
  598. cur_acc = ((re_repeat*)ptr)->id;
  599. accumulators[cur_acc] = 0;
  600. start_loop[cur_acc] = iterator();
  601. }
  602. cur_acc = ((re_repeat*)ptr)->id;
  603. if(((re_repeat*)ptr)->leading)
  604. *restart = first;
  605. //charT c = traits::translate(*first MAYBE_PASS_LOCALE(locale_inst));
  606. // first of all test for special case where this is last element,
  607. // if that is the case then repeat as many times as possible:
  608. if(((re_repeat*)ptr)->alt.p->type == syntax_element_match)
  609. {
  610. // see if we can take the repeat:
  611. if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max)
  612. && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_take, width_type()))
  613. {
  614. // push terminating match as fallback:
  615. if((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min)
  616. {
  617. if((prev_record.empty() == false) && (prev_record.peek() == ((re_repeat*)ptr)->alt.p))
  618. {
  619. // we already have the required fallback
  620. // don't add any more, just update this one:
  621. if(need_push_match)
  622. matches.peek() = temp_match;
  623. prev_pos.peek() = first;
  624. }
  625. else
  626. {
  627. if(need_push_match)
  628. matches.push(temp_match);
  629. prev_pos.push(first);
  630. prev_record.push(((re_repeat*)ptr)->alt.p);
  631. }
  632. }
  633. // move to next item in list:
  634. if(first != start_loop[cur_acc])
  635. {
  636. ++accumulators[cur_acc];
  637. ptr = ptr->next.p;
  638. start_loop[cur_acc] = first;
  639. continue;
  640. }
  641. goto failure;
  642. }
  643. // see if we can skip the repeat:
  644. if(((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min)
  645. && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_skip, width_type()))
  646. {
  647. ptr = ((re_repeat*)ptr)->alt.p;
  648. continue;
  649. }
  650. // otherwise fail:
  651. goto failure;
  652. }
  653. // see if we can skip the repeat:
  654. if(((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min)
  655. && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_skip, width_type()))
  656. {
  657. // see if we can push failure info:
  658. if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max)
  659. && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_take, width_type()))
  660. {
  661. // check to see if the last loop matched a NULL string
  662. // if so then we really don't want to loop again:
  663. if(((unsigned int)accumulators[cur_acc] == ((re_repeat*)ptr)->min)
  664. || (first != start_loop[cur_acc]))
  665. {
  666. if(need_push_match)
  667. matches.push(temp_match);
  668. prev_pos.push(first);
  669. prev_record.push(ptr);
  670. for(k = 0; k <= cur_acc; ++k)
  671. prev_acc.push(accumulators[k]);
  672. //prev_acc.push(cur_acc);
  673. }
  674. }
  675. ptr = ((re_repeat*)ptr)->alt.p;
  676. continue;
  677. }
  678. // otherwise see if we can take the repeat:
  679. if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max)
  680. && reg_expression<charT, traits, Allocator2>::can_start(*first, ((re_repeat*)ptr)->__map, mask_take, width_type()) &&
  681. (first != start_loop[cur_acc]))
  682. {
  683. // move to next item in list:
  684. ++accumulators[cur_acc];
  685. ptr = ptr->next.p;
  686. start_loop[cur_acc] = first;
  687. continue;
  688. }
  689. // if we get here then neither option is allowed so fail:
  690. goto failure;
  691. }
  692. case syntax_element_combining:
  693. if(traits::is_combining(traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))))
  694. goto failure;
  695. ++first;
  696. while((first != last) && traits::is_combining(traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))))++first;
  697. ptr = ptr->next.p;
  698. continue;
  699. case syntax_element_soft_buffer_end:
  700. {
  701. if(flags & match_not_eob)
  702. goto failure;
  703. iterator p(first);
  704. while((p != last) && traits::is_separator(traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))))++p;
  705. if(p != last)
  706. goto failure;
  707. ptr = ptr->next.p;
  708. continue;
  709. }
  710. case syntax_element_restart_continue:
  711. if(first != temp_match[-1].first)
  712. goto failure;
  713. ptr = ptr->next.p;
  714. continue;
  715. default:
  716. jm_assert(0); // should never get to here!!
  717. return false;
  718. }
  719. }
  720. //
  721. // if we get to here then we've run out of characters to match against,
  722. // we could however still have non-character regex items left
  723. if(ptr->can_be_null == 0)
  724. goto failure;
  725. while(true)
  726. {
  727. jm_assert(ptr);
  728. switch(ptr->type)
  729. {
  730. case syntax_element_match:
  731. goto match_jump;
  732. case syntax_element_startmark:
  733. temp_match.set_first(first, ((re_brace*)ptr)->index);
  734. ptr = ptr->next.p;
  735. break;
  736. case syntax_element_endmark:
  737. temp_match.set_second(first, ((re_brace*)ptr)->index);
  738. ptr = ptr->next.p;
  739. break;
  740. case syntax_element_start_line:
  741. goto outer_line_check;
  742. case syntax_element_end_line:
  743. // we're at the end so *first is never valid:
  744. if((flags & match_not_eol) == 0)
  745. {
  746. ptr = ptr->next.p;
  747. continue;
  748. }
  749. goto failure;
  750. case syntax_element_word_boundary:
  751. case syntax_element_word_end:
  752. if(((flags & match_not_eow) == 0) && (first != temp_match[0].first))
  753. {
  754. iterator t(first);
  755. --t;
  756. if(traits::is_class(*t, char_class_word MAYBE_PASS_LOCALE(locale_inst)))
  757. {
  758. ptr = ptr->next.p;
  759. continue;
  760. }
  761. }
  762. goto failure;
  763. case syntax_element_buffer_end:
  764. case syntax_element_soft_buffer_end:
  765. if(flags & match_not_eob)
  766. goto failure;
  767. // OK match:
  768. ptr = ptr->next.p;
  769. break;
  770. case syntax_element_jump:
  771. ptr = ((re_jump*)ptr)->alt.p;
  772. continue;
  773. case syntax_element_alt:
  774. if(ptr->can_be_null & mask_take)
  775. {
  776. // we can test the first alternative,
  777. // see if we need to push next alternative:
  778. if(ptr->can_be_null & mask_skip)
  779. {
  780. if(need_push_match)
  781. matches.push(temp_match);
  782. for(k = 0; k <= cur_acc; ++k)
  783. prev_pos.push(start_loop[k]);
  784. prev_pos.push(first);
  785. prev_record.push(ptr);
  786. for(k = 0; k <= cur_acc; ++k)
  787. prev_acc.push(accumulators[k]);
  788. prev_acc.push(cur_acc);
  789. }
  790. ptr = ptr->next.p;
  791. continue;
  792. }
  793. if(ptr->can_be_null & mask_skip)
  794. {
  795. ptr = ((re_jump*)ptr)->alt.p;
  796. continue;
  797. }
  798. goto failure; // neither option is possible
  799. case syntax_element_rep:
  800. // if we're moving to a higher id (nested repeats etc)
  801. // zero out our accumualtors:
  802. if(cur_acc < ((re_repeat*)ptr)->id)
  803. {
  804. cur_acc = ((re_repeat*)ptr)->id;
  805. accumulators[cur_acc] = 0;
  806. start_loop[cur_acc] = first;
  807. }
  808. cur_acc = ((re_repeat*)ptr)->id;
  809. // see if we can skip the repeat:
  810. if(((unsigned int)accumulators[cur_acc] >= ((re_repeat*)ptr)->min)
  811. && (ptr->can_be_null & mask_skip))
  812. {
  813. // don't push failure info, there's no point:
  814. ptr = ((re_repeat*)ptr)->alt.p;
  815. continue;
  816. }
  817. // otherwise see if we can take the repeat:
  818. if(((unsigned int)accumulators[cur_acc] < ((re_repeat*)ptr)->max)
  819. && ((ptr->can_be_null & (mask_take | mask_skip)) == (mask_take | mask_skip)))
  820. {
  821. // move to next item in list:
  822. ++accumulators[cur_acc];
  823. ptr = ptr->next.p;
  824. start_loop[cur_acc] = first;
  825. continue;
  826. }
  827. // if we get here then neither option is allowed so fail:
  828. goto failure;
  829. case syntax_element_restart_continue:
  830. if(first != temp_match[-1].first)
  831. goto failure;
  832. ptr = ptr->next.p;
  833. continue;
  834. default:
  835. goto failure;
  836. }
  837. }
  838. failure:
  839. if(prev_record.empty() == false)
  840. {
  841. ptr = prev_record.peek();
  842. switch(ptr->type)
  843. {
  844. case syntax_element_alt:
  845. // get next alternative:
  846. ptr = ((re_jump*)ptr)->alt.p;
  847. if(need_push_match)
  848. matches.pop(temp_match);
  849. prev_acc.pop(cur_acc);
  850. for(k = cur_acc; k >= 0; --k)
  851. prev_acc.pop(accumulators[k]);
  852. prev_pos.pop(first);
  853. for(k = cur_acc; k >= 0; --k)
  854. prev_pos.pop(start_loop[k]);
  855. prev_record.pop();
  856. goto retry;
  857. case syntax_element_rep:
  858. // we're doing least number of repeats first,
  859. // increment count and repeat again:
  860. if(need_push_match)
  861. matches.pop(temp_match);
  862. prev_pos.pop(first);
  863. cur_acc = ((re_repeat*)ptr)->id;
  864. for(k = cur_acc; k >= 0; --k)
  865. prev_acc.pop(accumulators[k]);
  866. prev_record.pop();
  867. if((unsigned int)++accumulators[cur_acc] > ((re_repeat*)ptr)->max)
  868. goto failure; // repetions exhausted.
  869. ptr = ptr->next.p;
  870. start_loop[cur_acc] = first;
  871. goto retry;
  872. case syntax_element_match:
  873. if(need_push_match)
  874. matches.pop(temp_match);
  875. prev_pos.pop(first);
  876. prev_record.pop();
  877. goto retry;
  878. default:
  879. jm_assert(0);
  880. // mustn't get here!!
  881. }
  882. }
  883. if(match_found)
  884. return true;
  885. // if we get to here then everything has failed
  886. // and no match was found:
  887. return false;
  888. }
  889. #if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
  890. } // namespace
  891. #endif
  892. template <class iterator>
  893. void __skip_and_inc(unsigned int& clines, iterator& last_line, iterator& first, const iterator last)
  894. {
  895. while(first != last)
  896. {
  897. if(*first == '\n')
  898. {
  899. last_line = ++first;
  900. ++clines;
  901. }
  902. else
  903. ++first;
  904. }
  905. }
  906. template <class iterator>
  907. void __skip_and_dec(unsigned int& clines, iterator& last_line, iterator& first, iterator base, unsigned int len)
  908. {
  909. bool need_line = false;
  910. for(unsigned int i = 0; i < len; ++i)
  911. {
  912. --first;
  913. if(*first == '\n')
  914. {
  915. need_line = true;
  916. --clines;
  917. }
  918. }
  919. if(need_line)
  920. {
  921. last_line = first;
  922. if(last_line != base)
  923. --last_line;
  924. else
  925. return;
  926. while((last_line != base) && (*last_line != '\n'))
  927. --last_line;
  928. if(*last_line == '\n')
  929. ++last_line;
  930. }
  931. }
  932. template <class iterator>
  933. inline void __inc_one(unsigned int& clines, iterator& last_line, iterator& first)
  934. {
  935. if(*first == '\n')
  936. {
  937. last_line = ++first;
  938. ++clines;
  939. }
  940. else
  941. ++first;
  942. }
  943. template <class iterator, class Allocator>
  944. struct grep_search_predicate
  945. {
  946. reg_match<iterator, Allocator>* pm;
  947. grep_search_predicate(reg_match<iterator, Allocator>* p) : pm(p) {}
  948. bool operator()(const reg_match<iterator, Allocator>& m)
  949. {
  950. *pm = static_cast<const reg_match_base<iterator, Allocator>&>(m);
  951. return false;
  952. }
  953. };
  954. #if !defined(JM_NO_TEMPLATE_RETURNS) && !defined(JM_NO_PARTIAL_FUNC_SPEC)
  955. template <class iterator, class Allocator>
  956. inline const reg_match_base<iterator, Allocator>& grep_out_type(const grep_search_predicate<iterator, Allocator>& o, const Allocator&)
  957. {
  958. return *(o.pm);
  959. }
  960. #endif
  961. template <class T, class Allocator>
  962. inline const Allocator& grep_out_type(const T&, const Allocator& a)
  963. {
  964. return a;
  965. }
  966. #if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
  967. //
  968. // Ugly ugly hack,
  969. // template don't merge if they contain switch statements so declare these
  970. // templates in unnamed namespace (ie with internal linkage), each translation
  971. // unit then gets its own local copy, it works seemlessly but bloats the app.
  972. namespace{
  973. #endif
  974. //
  975. // reg_grep2:
  976. // find all non-overlapping matches within the sequence first last:
  977. //
  978. template <class Predicate, class I, class charT, class traits, class A, class A2>
  979. unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a)
  980. {
  981. if(e.flags() & regbase::failbit)
  982. return 0;
  983. typedef typename traits::size_type traits_size_type;
  984. typedef typename traits::uchar_type traits_uchar_type;
  985. typedef typename is_byte<charT>::width_type width_type;
  986. reg_match<I, A2> m(grep_out_type(foo, a));
  987. I restart;
  988. m.set_size(e.mark_count(), first, last);
  989. m.set_line(1, first);
  990. #ifdef RE_LOCALE_CPP
  991. const __JM_STD::locale& locale_inst = e.locale();
  992. #endif
  993. unsigned int clines = 1;
  994. unsigned int cmatches = 0;
  995. I last_line = first;
  996. I next_base;
  997. I base = first;
  998. bool need_init;
  999. flags |= match_init;
  1000. __priv_match_data<I, A2> pd(m);
  1001. const unsigned char* __map = e.get_map();
  1002. unsigned int type;
  1003. if(first == last)
  1004. {
  1005. // special case, only test if can_be_null,
  1006. // don't dereference any pointers!!
  1007. if(e.first()->can_be_null)
  1008. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1009. {
  1010. foo(m);
  1011. ++cmatches;
  1012. }
  1013. return cmatches;
  1014. }
  1015. // try one time whatever:
  1016. if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type() ) )
  1017. {
  1018. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1019. {
  1020. ++cmatches;
  1021. if(foo(m) == false)
  1022. return cmatches;
  1023. // update to end of what matched
  1024. // trying to match again with match_not_null set if this
  1025. // is a null match...
  1026. need_init = true;
  1027. if(first == m[0].second)
  1028. {
  1029. next_base = m[0].second;
  1030. pd.temp_match.init_fail(next_base, last);
  1031. m.init_fail(next_base, last);
  1032. if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
  1033. {
  1034. ++cmatches;
  1035. if(foo(m) == false)
  1036. return cmatches;
  1037. }
  1038. else
  1039. {
  1040. need_init = false;
  1041. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1042. if(restart != last)
  1043. ++restart;
  1044. __skip_and_inc(clines, last_line, first, restart);
  1045. }
  1046. }
  1047. if(need_init)
  1048. {
  1049. __skip_and_inc(clines, last_line, first, m[0].second);
  1050. next_base = m[0].second;
  1051. pd.temp_match.init_fail(next_base, last);
  1052. m.init_fail(next_base, last);
  1053. }
  1054. }
  1055. else
  1056. {
  1057. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1058. if(restart != last)
  1059. ++restart;
  1060. __skip_and_inc(clines, last_line, first, restart);
  1061. }
  1062. }
  1063. else
  1064. __inc_one(clines, last_line, first);
  1065. flags |= match_prev_avail | match_not_bob;
  1066. // depending on what the first record is we may be able to
  1067. // optimise the search:
  1068. type = (flags & match_continuous) ? regbase::restart_continue : e.restart_type();
  1069. if(type == regbase::restart_buf)
  1070. return cmatches;
  1071. switch(type)
  1072. {
  1073. case regbase::restart_lit:
  1074. case regbase::restart_fixed_lit:
  1075. {
  1076. const kmp_info<charT>* info = e.get_kmp();
  1077. int len = info->len;
  1078. const charT* x = info->pstr;
  1079. int j = 0;
  1080. bool icase = e.flags() & regbase::icase;
  1081. while (first != last)
  1082. {
  1083. while((j > -1) && (x[j] != traits::translate(*first, icase MAYBE_PASS_LOCALE(locale_inst))))
  1084. j = info->kmp_next[j];
  1085. __inc_one(clines, last_line, first);
  1086. ++j;
  1087. if(j >= len)
  1088. {
  1089. if(type == regbase::restart_fixed_lit)
  1090. {
  1091. __skip_and_dec(clines, last_line, first, base, j);
  1092. restart = first;
  1093. restart += len;
  1094. m.set_first(first);
  1095. m.set_second(restart);
  1096. m.set_line(clines, last_line);
  1097. ++cmatches;
  1098. if(foo(m) == false)
  1099. return cmatches;
  1100. __skip_and_inc(clines, last_line, first, restart);
  1101. next_base = m[0].second;
  1102. pd.temp_match.init_fail(next_base, last);
  1103. m.init_fail(next_base, last);
  1104. j = 0;
  1105. }
  1106. else
  1107. {
  1108. restart = first;
  1109. __skip_and_dec(clines, last_line, first, base, j);
  1110. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1111. {
  1112. m.set_line(clines, last_line);
  1113. ++cmatches;
  1114. if(foo(m) == false)
  1115. return cmatches;
  1116. // update to end of what matched
  1117. __skip_and_inc(clines, last_line, first, m[0].second);
  1118. next_base = m[0].second;
  1119. pd.temp_match.init_fail(next_base, last);
  1120. m.init_fail(next_base, last);
  1121. j = 0;
  1122. }
  1123. else
  1124. {
  1125. for(int k = 0; (restart != first) && (k < j); ++k, --restart);
  1126. if(restart != last)
  1127. ++restart;
  1128. __skip_and_inc(clines, last_line, first, restart);
  1129. j = 0; //we could do better than this...
  1130. }
  1131. }
  1132. }
  1133. }
  1134. break;
  1135. }
  1136. case regbase::restart_any:
  1137. {
  1138. while(first != last)
  1139. {
  1140. if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) )
  1141. {
  1142. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1143. {
  1144. m.set_line(clines, last_line);
  1145. ++cmatches;
  1146. if(foo(m) == false)
  1147. return cmatches;
  1148. // update to end of what matched
  1149. // trying to match again with match_not_null set if this
  1150. // is a null match...
  1151. need_init = true;
  1152. if(first == m[0].second)
  1153. {
  1154. next_base = m[0].second;
  1155. pd.temp_match.init_fail(next_base, last);
  1156. m.init_fail(next_base, last);
  1157. if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
  1158. {
  1159. m.set_line(clines, last_line);
  1160. ++cmatches;
  1161. if(foo(m) == false)
  1162. return cmatches;
  1163. }
  1164. else
  1165. {
  1166. need_init = false;
  1167. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1168. if(restart != last)
  1169. ++restart;
  1170. __skip_and_inc(clines, last_line, first, restart);
  1171. }
  1172. }
  1173. if(need_init)
  1174. {
  1175. __skip_and_inc(clines, last_line, first, m[0].second);
  1176. next_base = m[0].second;
  1177. pd.temp_match.init_fail(next_base, last);
  1178. m.init_fail(next_base, last);
  1179. }
  1180. continue;
  1181. }
  1182. else
  1183. {
  1184. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1185. if(restart != last)
  1186. ++restart;
  1187. __skip_and_inc(clines, last_line, first, restart);
  1188. }
  1189. }
  1190. else
  1191. __inc_one(clines, last_line, first);
  1192. }
  1193. }
  1194. break;
  1195. case regbase::restart_word:
  1196. {
  1197. // do search optimised for word starts:
  1198. while(first != last)
  1199. {
  1200. --first;
  1201. if(*first == '\n')
  1202. --clines;
  1203. // skip the word characters:
  1204. while((first != last) && traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)))
  1205. ++first;
  1206. // now skip the white space:
  1207. while((first != last) && (traits::is_class(*first, char_class_word MAYBE_PASS_LOCALE(locale_inst)) == false))
  1208. __inc_one(clines, last_line, first);
  1209. if(first == last)
  1210. break;
  1211. if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) )
  1212. {
  1213. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1214. {
  1215. m.set_line(clines, last_line);
  1216. ++cmatches;
  1217. if(foo(m) == false)
  1218. return cmatches;
  1219. // update to end of what matched
  1220. // trying to match again with match_not_null set if this
  1221. // is a null match...
  1222. need_init = true;
  1223. if(first == m[0].second)
  1224. {
  1225. next_base = m[0].second;
  1226. pd.temp_match.init_fail(next_base, last);
  1227. m.init_fail(next_base, last);
  1228. if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
  1229. {
  1230. m.set_line(clines, last_line);
  1231. ++cmatches;
  1232. if(foo(m) == false)
  1233. return cmatches;
  1234. }
  1235. else
  1236. {
  1237. need_init = false;
  1238. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1239. if(restart != last)
  1240. ++restart;
  1241. __skip_and_inc(clines, last_line, first, restart);
  1242. }
  1243. }
  1244. if(need_init)
  1245. {
  1246. __skip_and_inc(clines, last_line, first, m[0].second);
  1247. next_base = m[0].second;
  1248. pd.temp_match.init_fail(next_base, last);
  1249. m.init_fail(next_base, last);
  1250. }
  1251. }
  1252. else
  1253. {
  1254. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1255. if(restart != last)
  1256. ++restart;
  1257. __skip_and_inc(clines, last_line, first, restart);
  1258. }
  1259. }
  1260. else
  1261. __inc_one(clines, last_line, first);
  1262. }
  1263. }
  1264. break;
  1265. case regbase::restart_line:
  1266. {
  1267. // do search optimised for line starts:
  1268. while(first != last)
  1269. {
  1270. // find first charcter after a line break:
  1271. --first;
  1272. if(*first == '\n')
  1273. --clines;
  1274. while((first != last) && (*first != '\n'))
  1275. ++first;
  1276. if(first == last)
  1277. break;
  1278. ++first;
  1279. if(first == last)
  1280. break;
  1281. ++clines;
  1282. last_line = first;
  1283. if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) )
  1284. {
  1285. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1286. {
  1287. m.set_line(clines, last_line);
  1288. ++cmatches;
  1289. if(foo(m) == false)
  1290. return cmatches;
  1291. // update to end of what matched
  1292. // trying to match again with match_not_null set if this
  1293. // is a null match...
  1294. need_init = true;
  1295. if(first == m[0].second)
  1296. {
  1297. next_base = m[0].second;
  1298. pd.temp_match.init_fail(next_base, last);
  1299. m.init_fail(next_base, last);
  1300. if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
  1301. {
  1302. m.set_line(clines, last_line);
  1303. ++cmatches;
  1304. if(foo(m) == false)
  1305. return cmatches;
  1306. }
  1307. else
  1308. {
  1309. need_init = false;
  1310. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1311. if(restart != last)
  1312. ++restart;
  1313. __skip_and_inc(clines, last_line, first, restart);
  1314. }
  1315. }
  1316. if(need_init)
  1317. {
  1318. __skip_and_inc(clines, last_line, first, m[0].second);
  1319. next_base = m[0].second;
  1320. pd.temp_match.init_fail(next_base, last);
  1321. m.init_fail(next_base, last);
  1322. }
  1323. }
  1324. else
  1325. {
  1326. for(unsigned int i = 0; (restart != first) && (i < e.leading_length()); ++i, --restart);
  1327. if(restart != last)
  1328. ++restart;
  1329. __skip_and_inc(clines, last_line, first, restart);
  1330. }
  1331. }
  1332. else
  1333. __inc_one(clines, last_line, first);
  1334. }
  1335. }
  1336. break;
  1337. case regbase::restart_continue:
  1338. {
  1339. while(first != last)
  1340. {
  1341. if( reg_expression<charT, traits, A>::can_start(*first, __map, (unsigned char)mask_any, width_type()) )
  1342. {
  1343. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1344. {
  1345. m.set_line(clines, last_line);
  1346. ++cmatches;
  1347. if(foo(m) == false)
  1348. return cmatches;
  1349. // update to end of what matched
  1350. // trying to match again with match_not_null set if this
  1351. // is a null match...
  1352. if(first == m[0].second)
  1353. {
  1354. next_base = m[0].second;
  1355. pd.temp_match.init_fail(next_base, last);
  1356. m.init_fail(next_base, last);
  1357. if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
  1358. {
  1359. m.set_line(clines, last_line);
  1360. ++cmatches;
  1361. if(foo(m) == false)
  1362. return cmatches;
  1363. }
  1364. else
  1365. return cmatches; // can't continue from null match
  1366. }
  1367. __skip_and_inc(clines, last_line, first, m[0].second);
  1368. next_base = m[0].second;
  1369. pd.temp_match.init_fail(next_base, last);
  1370. m.init_fail(next_base, last);
  1371. continue;
  1372. }
  1373. }
  1374. return cmatches;
  1375. }
  1376. }
  1377. break;
  1378. }
  1379. // finally check trailing null string:
  1380. if(e.first()->can_be_null)
  1381. {
  1382. if(query_match_aux(first, last, m, e, flags, pd, &restart))
  1383. {
  1384. m.set_line(clines, last_line);
  1385. ++cmatches;
  1386. if(foo(m) == false)
  1387. return cmatches;
  1388. }
  1389. }
  1390. return cmatches;
  1391. }
  1392. #if defined(JM_NO_TEMPLATE_SWITCH_MERGE) && !defined(JM_NO_NAMESPACES)
  1393. } // namespace
  1394. #endif
  1395. template <class iterator, class Allocator, class charT, class traits, class Allocator2>
  1396. bool reg_search(iterator first, iterator last, reg_match<iterator, Allocator>& m, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default)
  1397. {
  1398. if(e.flags() & regbase::failbit)
  1399. return false;
  1400. typedef typename traits::size_type traits_size_type;
  1401. typedef typename traits::uchar_type traits_uchar_type;
  1402. // prepare m for failure:
  1403. if((flags & match_init) == 0)
  1404. {
  1405. m.set_size(e.mark_count(), first, last);
  1406. }
  1407. flags |= match_init;
  1408. return reg_grep2(grep_search_predicate<iterator, Allocator>(&m), first, last, e, flags, m.allocator());
  1409. }
  1410. //
  1411. // reg_search convenience interfaces:
  1412. #ifndef JM_NO_PARTIAL_FUNC_SPEC
  1413. //
  1414. // this isn't really a partial specialisation, but template function
  1415. // overloading - if the compiler doesn't support partial specialisation
  1416. // then it really won't support this either:
  1417. template <class charT, class Allocator, class traits, class Allocator2>
  1418. inline bool reg_search(const charT* str,
  1419. reg_match<const charT*, Allocator>& m,
  1420. const reg_expression<charT, traits, Allocator2>& e,
  1421. unsigned flags = match_default)
  1422. {
  1423. return reg_search(str, str + traits::length(str), m, e, flags);
  1424. }
  1425. #ifndef JM_NO_STRING_H
  1426. template <class ST, class SA, class Allocator, class charT, class traits, class Allocator2>
  1427. inline bool reg_search(const __JM_STD::basic_string<charT, ST, SA>& s,
  1428. reg_match<typename __JM_STD::basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
  1429. const reg_expression<charT, traits, Allocator2>& e,
  1430. unsigned flags = match_default)
  1431. {
  1432. return reg_search(s.begin(), s.end(), m, e, flags);
  1433. }
  1434. #endif
  1435. #else // partial specialisation
  1436. inline bool reg_search(const char* str,
  1437. cmatch& m,
  1438. const regex& e,
  1439. unsigned flags = match_default)
  1440. {
  1441. return reg_search(str, str + regex::traits_type::length(str), m, e, flags);
  1442. }
  1443. #ifndef JM_NO_WCSTRING
  1444. inline bool reg_search(const wchar_t* str,
  1445. wcmatch& m,
  1446. const wregex& e,
  1447. unsigned flags = match_default)
  1448. {
  1449. return reg_search(str, str + wregex::traits_type::length(str), m, e, flags);
  1450. }
  1451. #endif
  1452. #ifndef JM_NO_STRING_H
  1453. inline bool reg_search(const __JM_STD::string& s,
  1454. reg_match<__JM_STD::string::const_iterator, regex::alloc_type>& m,
  1455. const regex& e,
  1456. unsigned flags = match_default)
  1457. {
  1458. return reg_search(s.begin(), s.end(), m, e, flags);
  1459. }
  1460. #if !defined(JM_NO_STRING_DEF_ARGS) && !defined(JM_NO_WCSTRING)
  1461. inline bool reg_search(const __JM_STD::basic_string<wchar_t>& s,
  1462. reg_match<__JM_STD::basic_string<wchar_t>::const_iterator, wregex::alloc_type>& m,
  1463. const wregex& e,
  1464. unsigned flags = match_default)
  1465. {
  1466. return reg_search(s.begin(), s.end(), m, e, flags);
  1467. }
  1468. #endif
  1469. #endif
  1470. #endif
  1471. //
  1472. // reg_grep:
  1473. // find all non-overlapping matches within the sequence first last:
  1474. //
  1475. template <class Predicate, class iterator, class charT, class traits, class Allocator>
  1476. inline unsigned int reg_grep(Predicate foo, iterator first, iterator last, const reg_expression<charT, traits, Allocator>& e, unsigned flags = match_default)
  1477. {
  1478. return reg_grep2(foo, first, last, e, flags, e.allocator());
  1479. }
  1480. //
  1481. // reg_grep convenience interfaces:
  1482. #ifndef JM_NO_PARTIAL_FUNC_SPEC
  1483. //
  1484. // this isn't really a partial specialisation, but template function
  1485. // overloading - if the compiler doesn't support partial specialisation
  1486. // then it really won't support this either:
  1487. template <class Predicate, class charT, class Allocator, class traits>
  1488. inline bool reg_grep(Predicate foo, const charT* str,
  1489. const reg_expression<charT, traits, Allocator>& e,
  1490. unsigned flags = match_default)
  1491. {
  1492. return reg_grep(foo, str, str + traits::length(str), e, flags);
  1493. }
  1494. #ifndef JM_NO_STRING_H
  1495. template <class Predicate, class ST, class SA, class Allocator, class charT, class traits>
  1496. inline bool reg_grep(Predicate foo, const __JM_STD::basic_string<charT, ST, SA>& s,
  1497. const reg_expression<charT, traits, Allocator>& e,
  1498. unsigned flags = match_default)
  1499. {
  1500. return reg_grep(foo, s.begin(), s.end(), e, flags);
  1501. }
  1502. #endif
  1503. #else // partial specialisation
  1504. inline bool reg_grep(bool (*foo)(const cmatch&), const char* str,
  1505. const regex& e,
  1506. unsigned flags = match_default)
  1507. {
  1508. return reg_grep(foo, str, str + regex::traits_type::length(str), e, flags);
  1509. }
  1510. #ifndef JM_NO_WCSTRING
  1511. inline bool reg_grep(bool (*foo)(const wcmatch&), const wchar_t* str,
  1512. const wregex& e,
  1513. unsigned flags = match_default)
  1514. {
  1515. return reg_grep(foo, str, str + wregex::traits_type::length(str), e, flags);
  1516. }
  1517. #endif
  1518. #ifndef JM_NO_STRING_H
  1519. inline bool reg_grep(bool (*foo)(const reg_match<__JM_STD::string::const_iterator, regex::alloc_type>&), const __JM_STD::string& s,
  1520. const regex& e,
  1521. unsigned flags = match_default)
  1522. {
  1523. return reg_grep(foo, s.begin(), s.end(), e, flags);
  1524. }
  1525. #if !defined(JM_NO_STRING_DEF_ARGS) && !defined(JM_NO_WCSTRING)
  1526. inline bool reg_grep(bool (*foo)(const reg_match<__JM_STD::basic_string<wchar_t>::const_iterator, wregex::alloc_type>&),
  1527. const __JM_STD::basic_string<wchar_t>& s,
  1528. const wregex& e,
  1529. unsigned flags = match_default)
  1530. {
  1531. return reg_grep(foo, s.begin(), s.end(), e, flags);
  1532. }
  1533. #endif
  1534. #endif
  1535. #endif
  1536. //
  1537. // finally for compatablity with version 1.x of the library
  1538. // we need a form of reg_grep that takes an output iterator
  1539. // as its first argument:
  1540. //
  1541. //
  1542. // struct grep_match:
  1543. // stores what matched during a reg_grep,
  1544. // the output iterator type passed to reg_grep must have an
  1545. // operator*() that returns a type with an
  1546. // operator=(const grep_match<iterator, Allocator>&);
  1547. //
  1548. template <class iterator, class Allocator>
  1549. struct grep_match
  1550. {
  1551. unsigned int line;
  1552. iterator line_start;
  1553. reg_match<iterator, Allocator> what;
  1554. grep_match(Allocator a = Allocator()) : what(a) {}
  1555. grep_match(unsigned int l, iterator p1, const reg_match<iterator, Allocator>& m)
  1556. : what(m) { line = l; line_start = p1; }
  1557. bool operator == (const grep_match& )
  1558. { return false; }
  1559. bool operator < (const grep_match&)
  1560. { return false; }
  1561. };
  1562. template <class O, class I, class A>
  1563. struct grep_adaptor
  1564. {
  1565. O oi;
  1566. reg_match<I, A> m;
  1567. grep_adaptor(O i, A a) : m(a), oi(i) {}
  1568. bool operator()(const reg_match_base<I, A>& w)
  1569. {
  1570. m.what = w;
  1571. m.line = w.line();
  1572. m.line_start = w.line_start();
  1573. *oi = m;
  1574. ++oi;
  1575. return true;
  1576. }
  1577. };
  1578. template <class Out, class iterator, class charT, class traits, class Allocator>
  1579. inline unsigned int reg_grep_old(Out oi, iterator first, iterator last, const reg_expression<charT, traits, Allocator>& e, unsigned flags = match_default)
  1580. {
  1581. return reg_grep2(grep_adaptor<Out, iterator, Allocator>(oi, e.allocator()), first, last, e, flags, e.allocator());
  1582. }
  1583. JM_END_NAMESPACE // namespace regex
  1584. #endif // __REGMATCH_H