regex_format.hpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158
  1. /*
  2. *
  3. * Copyright (c) 1998-2009 John Maddock
  4. * Copyright 2008 Eric Niebler.
  5. *
  6. * Use, modification and distribution are subject to the
  7. * Boost Software License, Version 1.0. (See accompanying file
  8. * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. *
  10. */
  11. /*
  12. * LOCATION: see http://www.boost.org for most recent version.
  13. * FILE regex_format.hpp
  14. * VERSION see <boost/version.hpp>
  15. * DESCRIPTION: Provides formatting output routines for search and replace
  16. * operations. Note this is an internal header file included
  17. * by regex.hpp, do not include on its own.
  18. */
  19. #ifndef BOOST_REGEX_FORMAT_HPP
  20. #define BOOST_REGEX_FORMAT_HPP
  21. #include <boost/type_traits/is_pointer.hpp>
  22. #include <boost/type_traits/is_function.hpp>
  23. #include <boost/type_traits/is_class.hpp>
  24. #include <boost/type_traits/is_same.hpp>
  25. #include <boost/type_traits/is_convertible.hpp>
  26. #include <boost/type_traits/remove_pointer.hpp>
  27. #include <boost/type_traits/remove_cv.hpp>
  28. #include <boost/mpl/if.hpp>
  29. #include <boost/mpl/and.hpp>
  30. #include <boost/mpl/not.hpp>
  31. #ifndef BOOST_NO_SFINAE
  32. #include <boost/mpl/has_xxx.hpp>
  33. #endif
  34. #include <boost/ref.hpp>
  35. namespace boost{
  36. #ifdef BOOST_MSVC
  37. #pragma warning(push)
  38. #pragma warning(disable: 4103)
  39. #endif
  40. #ifdef BOOST_HAS_ABI_HEADERS
  41. # include BOOST_ABI_PREFIX
  42. #endif
  43. #ifdef BOOST_MSVC
  44. #pragma warning(pop)
  45. #endif
  46. //
  47. // Forward declaration:
  48. //
  49. template <class BidiIterator, class Allocator = BOOST_DEDUCED_TYPENAME std::vector<sub_match<BidiIterator> >::allocator_type >
  50. class match_results;
  51. namespace BOOST_REGEX_DETAIL_NS{
  52. //
  53. // struct trivial_format_traits:
  54. // defines minimum localisation support for formatting
  55. // in the case that the actual regex traits is unavailable.
  56. //
  57. template <class charT>
  58. struct trivial_format_traits
  59. {
  60. typedef charT char_type;
  61. static std::ptrdiff_t length(const charT* p)
  62. {
  63. return global_length(p);
  64. }
  65. static charT tolower(charT c)
  66. {
  67. return ::boost::BOOST_REGEX_DETAIL_NS::global_lower(c);
  68. }
  69. static charT toupper(charT c)
  70. {
  71. return ::boost::BOOST_REGEX_DETAIL_NS::global_upper(c);
  72. }
  73. static int value(const charT c, int radix)
  74. {
  75. int result = global_value(c);
  76. return result >= radix ? -1 : result;
  77. }
  78. int toi(const charT*& p1, const charT* p2, int radix)const
  79. {
  80. return (int)global_toi(p1, p2, radix, *this);
  81. }
  82. };
  83. #ifdef BOOST_MSVC
  84. # pragma warning(push)
  85. #pragma warning(disable:26812)
  86. #endif
  87. template <class OutputIterator, class Results, class traits, class ForwardIter>
  88. class basic_regex_formatter
  89. {
  90. public:
  91. typedef typename traits::char_type char_type;
  92. basic_regex_formatter(OutputIterator o, const Results& r, const traits& t)
  93. : m_traits(t), m_results(r), m_out(o), m_position(), m_end(), m_flags(), m_state(output_copy), m_restore_state(output_copy), m_have_conditional(false) {}
  94. OutputIterator format(ForwardIter p1, ForwardIter p2, match_flag_type f);
  95. OutputIterator format(ForwardIter p1, match_flag_type f)
  96. {
  97. return format(p1, p1 + m_traits.length(p1), f);
  98. }
  99. private:
  100. typedef typename Results::value_type sub_match_type;
  101. enum output_state
  102. {
  103. output_copy,
  104. output_next_lower,
  105. output_next_upper,
  106. output_lower,
  107. output_upper,
  108. output_none
  109. };
  110. void put(char_type c);
  111. void put(const sub_match_type& sub);
  112. void format_all();
  113. void format_perl();
  114. void format_escape();
  115. void format_conditional();
  116. void format_until_scope_end();
  117. bool handle_perl_verb(bool have_brace);
  118. inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::false_&)
  119. {
  120. std::vector<char_type> v(i, j);
  121. return (i != j) ? this->m_results.named_subexpression(&v[0], &v[0] + v.size())
  122. : this->m_results.named_subexpression(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
  123. }
  124. inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const mpl::true_&)
  125. {
  126. return this->m_results.named_subexpression(i, j);
  127. }
  128. inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j)
  129. {
  130. typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
  131. return get_named_sub(i, j, tag_type());
  132. }
  133. inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::false_&)
  134. {
  135. std::vector<char_type> v(i, j);
  136. return (i != j) ? this->m_results.named_subexpression_index(&v[0], &v[0] + v.size())
  137. : this->m_results.named_subexpression_index(static_cast<const char_type*>(0), static_cast<const char_type*>(0));
  138. }
  139. inline int get_named_sub_index(ForwardIter i, ForwardIter j, const mpl::true_&)
  140. {
  141. return this->m_results.named_subexpression_index(i, j);
  142. }
  143. inline int get_named_sub_index(ForwardIter i, ForwardIter j)
  144. {
  145. typedef typename boost::is_convertible<ForwardIter, const char_type*>::type tag_type;
  146. return get_named_sub_index(i, j, tag_type());
  147. }
  148. #ifdef BOOST_MSVC
  149. // msvc-8.0 issues a spurious warning on the call to std::advance here:
  150. #pragma warning(push)
  151. #pragma warning(disable:4244)
  152. #endif
  153. inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::false_&)
  154. {
  155. if(i != j)
  156. {
  157. std::vector<char_type> v(i, j);
  158. const char_type* start = &v[0];
  159. const char_type* pos = start;
  160. int r = (int)m_traits.toi(pos, &v[0] + v.size(), base);
  161. std::advance(i, pos - start);
  162. return r;
  163. }
  164. return -1;
  165. }
  166. #ifdef BOOST_MSVC
  167. #pragma warning(pop)
  168. #endif
  169. inline int toi(ForwardIter& i, ForwardIter j, int base, const boost::mpl::true_&)
  170. {
  171. return m_traits.toi(i, j, base);
  172. }
  173. inline int toi(ForwardIter& i, ForwardIter j, int base)
  174. {
  175. #if defined(_MSC_VER) && defined(__INTEL_COMPILER) && ((__INTEL_COMPILER == 9999) || (__INTEL_COMPILER == 1210))
  176. // Workaround for Intel support issue #656654.
  177. // See also https://svn.boost.org/trac/boost/ticket/6359
  178. return toi(i, j, base, mpl::false_());
  179. #else
  180. typedef typename boost::is_convertible<ForwardIter, const char_type*&>::type tag_type;
  181. return toi(i, j, base, tag_type());
  182. #endif
  183. }
  184. const traits& m_traits; // the traits class for localised formatting operations
  185. const Results& m_results; // the match_results being used.
  186. OutputIterator m_out; // where to send output.
  187. ForwardIter m_position; // format string, current position
  188. ForwardIter m_end; // format string end
  189. match_flag_type m_flags; // format flags to use
  190. output_state m_state; // what to do with the next character
  191. output_state m_restore_state; // what state to restore to.
  192. bool m_have_conditional; // we are parsing a conditional
  193. private:
  194. basic_regex_formatter(const basic_regex_formatter&);
  195. basic_regex_formatter& operator=(const basic_regex_formatter&);
  196. };
  197. #ifdef BOOST_MSVC
  198. # pragma warning(pop)
  199. #endif
  200. template <class OutputIterator, class Results, class traits, class ForwardIter>
  201. OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format(ForwardIter p1, ForwardIter p2, match_flag_type f)
  202. {
  203. m_position = p1;
  204. m_end = p2;
  205. m_flags = f;
  206. format_all();
  207. return m_out;
  208. }
  209. template <class OutputIterator, class Results, class traits, class ForwardIter>
  210. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all()
  211. {
  212. // over and over:
  213. while(m_position != m_end)
  214. {
  215. switch(*m_position)
  216. {
  217. case '&':
  218. if(m_flags & ::boost::regex_constants::format_sed)
  219. {
  220. ++m_position;
  221. put(m_results[0]);
  222. break;
  223. }
  224. put(*m_position++);
  225. break;
  226. case '\\':
  227. format_escape();
  228. break;
  229. case '(':
  230. if(m_flags & boost::regex_constants::format_all)
  231. {
  232. ++m_position;
  233. bool have_conditional = m_have_conditional;
  234. m_have_conditional = false;
  235. format_until_scope_end();
  236. m_have_conditional = have_conditional;
  237. if(m_position == m_end)
  238. return;
  239. BOOST_REGEX_ASSERT(*m_position == static_cast<char_type>(')'));
  240. ++m_position; // skip the closing ')'
  241. break;
  242. }
  243. put(*m_position);
  244. ++m_position;
  245. break;
  246. case ')':
  247. if(m_flags & boost::regex_constants::format_all)
  248. {
  249. return;
  250. }
  251. put(*m_position);
  252. ++m_position;
  253. break;
  254. case ':':
  255. if((m_flags & boost::regex_constants::format_all) && m_have_conditional)
  256. {
  257. return;
  258. }
  259. put(*m_position);
  260. ++m_position;
  261. break;
  262. case '?':
  263. if(m_flags & boost::regex_constants::format_all)
  264. {
  265. ++m_position;
  266. format_conditional();
  267. break;
  268. }
  269. put(*m_position);
  270. ++m_position;
  271. break;
  272. case '$':
  273. if((m_flags & format_sed) == 0)
  274. {
  275. format_perl();
  276. break;
  277. }
  278. // not a special character:
  279. BOOST_FALLTHROUGH;
  280. default:
  281. put(*m_position);
  282. ++m_position;
  283. break;
  284. }
  285. }
  286. }
  287. template <class OutputIterator, class Results, class traits, class ForwardIter>
  288. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_perl()
  289. {
  290. //
  291. // On entry *m_position points to a '$' character
  292. // output the information that goes with it:
  293. //
  294. BOOST_REGEX_ASSERT(*m_position == '$');
  295. //
  296. // see if this is a trailing '$':
  297. //
  298. if(++m_position == m_end)
  299. {
  300. --m_position;
  301. put(*m_position);
  302. ++m_position;
  303. return;
  304. }
  305. //
  306. // OK find out what kind it is:
  307. //
  308. bool have_brace = false;
  309. ForwardIter save_position = m_position;
  310. switch(*m_position)
  311. {
  312. case '&':
  313. ++m_position;
  314. put(this->m_results[0]);
  315. break;
  316. case '`':
  317. ++m_position;
  318. put(this->m_results.prefix());
  319. break;
  320. case '\'':
  321. ++m_position;
  322. put(this->m_results.suffix());
  323. break;
  324. case '$':
  325. put(*m_position++);
  326. break;
  327. case '+':
  328. if((++m_position != m_end) && (*m_position == '{'))
  329. {
  330. ForwardIter base = ++m_position;
  331. while((m_position != m_end) && (*m_position != '}')) ++m_position;
  332. if(m_position != m_end)
  333. {
  334. // Named sub-expression:
  335. put(get_named_sub(base, m_position));
  336. ++m_position;
  337. break;
  338. }
  339. else
  340. {
  341. m_position = --base;
  342. }
  343. }
  344. put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]);
  345. break;
  346. case '{':
  347. have_brace = true;
  348. ++m_position;
  349. BOOST_FALLTHROUGH;
  350. default:
  351. // see if we have a number:
  352. {
  353. std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
  354. //len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
  355. int v = this->toi(m_position, m_position + len, 10);
  356. if((v < 0) || (have_brace && ((m_position == m_end) || (*m_position != '}'))))
  357. {
  358. // Look for a Perl-5.10 verb:
  359. if(!handle_perl_verb(have_brace))
  360. {
  361. // leave the $ as is, and carry on:
  362. m_position = --save_position;
  363. put(*m_position);
  364. ++m_position;
  365. }
  366. break;
  367. }
  368. // otherwise output sub v:
  369. put(this->m_results[v]);
  370. if(have_brace)
  371. ++m_position;
  372. }
  373. }
  374. }
  375. template <class OutputIterator, class Results, class traits, class ForwardIter>
  376. bool basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::handle_perl_verb(bool have_brace)
  377. {
  378. //
  379. // We may have a capitalised string containing a Perl action:
  380. //
  381. static const char_type MATCH[] = { 'M', 'A', 'T', 'C', 'H' };
  382. static const char_type PREMATCH[] = { 'P', 'R', 'E', 'M', 'A', 'T', 'C', 'H' };
  383. static const char_type POSTMATCH[] = { 'P', 'O', 'S', 'T', 'M', 'A', 'T', 'C', 'H' };
  384. static const char_type LAST_PAREN_MATCH[] = { 'L', 'A', 'S', 'T', '_', 'P', 'A', 'R', 'E', 'N', '_', 'M', 'A', 'T', 'C', 'H' };
  385. static const char_type LAST_SUBMATCH_RESULT[] = { 'L', 'A', 'S', 'T', '_', 'S', 'U', 'B', 'M', 'A', 'T', 'C', 'H', '_', 'R', 'E', 'S', 'U', 'L', 'T' };
  386. static const char_type LAST_SUBMATCH_RESULT_ALT[] = { '^', 'N' };
  387. if(m_position == m_end)
  388. return false;
  389. if(have_brace && (*m_position == '^'))
  390. ++m_position;
  391. std::ptrdiff_t max_len = m_end - m_position;
  392. if((max_len >= 5) && std::equal(m_position, m_position + 5, MATCH))
  393. {
  394. m_position += 5;
  395. if(have_brace)
  396. {
  397. if((m_position != m_end) && (*m_position == '}'))
  398. ++m_position;
  399. else
  400. {
  401. m_position -= 5;
  402. return false;
  403. }
  404. }
  405. put(this->m_results[0]);
  406. return true;
  407. }
  408. if((max_len >= 8) && std::equal(m_position, m_position + 8, PREMATCH))
  409. {
  410. m_position += 8;
  411. if(have_brace)
  412. {
  413. if((m_position != m_end) && (*m_position == '}'))
  414. ++m_position;
  415. else
  416. {
  417. m_position -= 8;
  418. return false;
  419. }
  420. }
  421. put(this->m_results.prefix());
  422. return true;
  423. }
  424. if((max_len >= 9) && std::equal(m_position, m_position + 9, POSTMATCH))
  425. {
  426. m_position += 9;
  427. if(have_brace)
  428. {
  429. if((m_position != m_end) && (*m_position == '}'))
  430. ++m_position;
  431. else
  432. {
  433. m_position -= 9;
  434. return false;
  435. }
  436. }
  437. put(this->m_results.suffix());
  438. return true;
  439. }
  440. if((max_len >= 16) && std::equal(m_position, m_position + 16, LAST_PAREN_MATCH))
  441. {
  442. m_position += 16;
  443. if(have_brace)
  444. {
  445. if((m_position != m_end) && (*m_position == '}'))
  446. ++m_position;
  447. else
  448. {
  449. m_position -= 16;
  450. return false;
  451. }
  452. }
  453. put((this->m_results)[this->m_results.size() > 1 ? static_cast<int>(this->m_results.size() - 1) : 1]);
  454. return true;
  455. }
  456. if((max_len >= 20) && std::equal(m_position, m_position + 20, LAST_SUBMATCH_RESULT))
  457. {
  458. m_position += 20;
  459. if(have_brace)
  460. {
  461. if((m_position != m_end) && (*m_position == '}'))
  462. ++m_position;
  463. else
  464. {
  465. m_position -= 20;
  466. return false;
  467. }
  468. }
  469. put(this->m_results.get_last_closed_paren());
  470. return true;
  471. }
  472. if((max_len >= 2) && std::equal(m_position, m_position + 2, LAST_SUBMATCH_RESULT_ALT))
  473. {
  474. m_position += 2;
  475. if(have_brace)
  476. {
  477. if((m_position != m_end) && (*m_position == '}'))
  478. ++m_position;
  479. else
  480. {
  481. m_position -= 2;
  482. return false;
  483. }
  484. }
  485. put(this->m_results.get_last_closed_paren());
  486. return true;
  487. }
  488. return false;
  489. }
  490. template <class OutputIterator, class Results, class traits, class ForwardIter>
  491. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_escape()
  492. {
  493. // skip the escape and check for trailing escape:
  494. if(++m_position == m_end)
  495. {
  496. put(static_cast<char_type>('\\'));
  497. return;
  498. }
  499. // now switch on the escape type:
  500. switch(*m_position)
  501. {
  502. case 'a':
  503. put(static_cast<char_type>('\a'));
  504. ++m_position;
  505. break;
  506. case 'f':
  507. put(static_cast<char_type>('\f'));
  508. ++m_position;
  509. break;
  510. case 'n':
  511. put(static_cast<char_type>('\n'));
  512. ++m_position;
  513. break;
  514. case 'r':
  515. put(static_cast<char_type>('\r'));
  516. ++m_position;
  517. break;
  518. case 't':
  519. put(static_cast<char_type>('\t'));
  520. ++m_position;
  521. break;
  522. case 'v':
  523. put(static_cast<char_type>('\v'));
  524. ++m_position;
  525. break;
  526. case 'x':
  527. if(++m_position == m_end)
  528. {
  529. put(static_cast<char_type>('x'));
  530. return;
  531. }
  532. // maybe have \x{ddd}
  533. if(*m_position == static_cast<char_type>('{'))
  534. {
  535. ++m_position;
  536. int val = this->toi(m_position, m_end, 16);
  537. if(val < 0)
  538. {
  539. // invalid value treat everything as literals:
  540. put(static_cast<char_type>('x'));
  541. put(static_cast<char_type>('{'));
  542. return;
  543. }
  544. if((m_position == m_end) || (*m_position != static_cast<char_type>('}')))
  545. {
  546. --m_position;
  547. while(*m_position != static_cast<char_type>('\\'))
  548. --m_position;
  549. ++m_position;
  550. put(*m_position++);
  551. return;
  552. }
  553. ++m_position;
  554. put(static_cast<char_type>(val));
  555. return;
  556. }
  557. else
  558. {
  559. std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
  560. len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
  561. int val = this->toi(m_position, m_position + len, 16);
  562. if(val < 0)
  563. {
  564. --m_position;
  565. put(*m_position++);
  566. return;
  567. }
  568. put(static_cast<char_type>(val));
  569. }
  570. break;
  571. case 'c':
  572. if(++m_position == m_end)
  573. {
  574. --m_position;
  575. put(*m_position++);
  576. return;
  577. }
  578. put(static_cast<char_type>(*m_position++ % 32));
  579. break;
  580. case 'e':
  581. put(static_cast<char_type>(27));
  582. ++m_position;
  583. break;
  584. default:
  585. // see if we have a perl specific escape:
  586. if((m_flags & boost::regex_constants::format_sed) == 0)
  587. {
  588. bool breakout = false;
  589. switch(*m_position)
  590. {
  591. case 'l':
  592. ++m_position;
  593. m_restore_state = m_state;
  594. m_state = output_next_lower;
  595. breakout = true;
  596. break;
  597. case 'L':
  598. ++m_position;
  599. m_state = output_lower;
  600. breakout = true;
  601. break;
  602. case 'u':
  603. ++m_position;
  604. m_restore_state = m_state;
  605. m_state = output_next_upper;
  606. breakout = true;
  607. break;
  608. case 'U':
  609. ++m_position;
  610. m_state = output_upper;
  611. breakout = true;
  612. break;
  613. case 'E':
  614. ++m_position;
  615. m_state = output_copy;
  616. breakout = true;
  617. break;
  618. }
  619. if(breakout)
  620. break;
  621. }
  622. // see if we have a \n sed style backreference:
  623. std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
  624. len = (std::min)(static_cast<std::ptrdiff_t>(1), len);
  625. int v = this->toi(m_position, m_position+len, 10);
  626. if((v > 0) || ((v == 0) && (m_flags & ::boost::regex_constants::format_sed)))
  627. {
  628. put(m_results[v]);
  629. break;
  630. }
  631. else if(v == 0)
  632. {
  633. // octal ecape sequence:
  634. --m_position;
  635. len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
  636. len = (std::min)(static_cast<std::ptrdiff_t>(4), len);
  637. v = this->toi(m_position, m_position + len, 8);
  638. BOOST_REGEX_ASSERT(v >= 0);
  639. put(static_cast<char_type>(v));
  640. break;
  641. }
  642. // Otherwise output the character "as is":
  643. put(*m_position++);
  644. break;
  645. }
  646. }
  647. template <class OutputIterator, class Results, class traits, class ForwardIter>
  648. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional()
  649. {
  650. if(m_position == m_end)
  651. {
  652. // oops trailing '?':
  653. put(static_cast<char_type>('?'));
  654. return;
  655. }
  656. int v;
  657. if(*m_position == '{')
  658. {
  659. ForwardIter base = m_position;
  660. ++m_position;
  661. v = this->toi(m_position, m_end, 10);
  662. if(v < 0)
  663. {
  664. // Try a named subexpression:
  665. while((m_position != m_end) && (*m_position != '}'))
  666. ++m_position;
  667. v = this->get_named_sub_index(base + 1, m_position);
  668. }
  669. if((v < 0) || (*m_position != '}'))
  670. {
  671. m_position = base;
  672. // oops trailing '?':
  673. put(static_cast<char_type>('?'));
  674. return;
  675. }
  676. // Skip trailing '}':
  677. ++m_position;
  678. }
  679. else
  680. {
  681. std::ptrdiff_t len = ::boost::BOOST_REGEX_DETAIL_NS::distance(m_position, m_end);
  682. len = (std::min)(static_cast<std::ptrdiff_t>(2), len);
  683. v = this->toi(m_position, m_position + len, 10);
  684. }
  685. if(v < 0)
  686. {
  687. // oops not a number:
  688. put(static_cast<char_type>('?'));
  689. return;
  690. }
  691. // output varies depending upon whether sub-expression v matched or not:
  692. if(m_results[v].matched)
  693. {
  694. m_have_conditional = true;
  695. format_all();
  696. m_have_conditional = false;
  697. if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
  698. {
  699. // skip the ':':
  700. ++m_position;
  701. // save output state, then turn it off:
  702. output_state saved_state = m_state;
  703. m_state = output_none;
  704. // format the rest of this scope:
  705. format_until_scope_end();
  706. // restore output state:
  707. m_state = saved_state;
  708. }
  709. }
  710. else
  711. {
  712. // save output state, then turn it off:
  713. output_state saved_state = m_state;
  714. m_state = output_none;
  715. // format until ':' or ')':
  716. m_have_conditional = true;
  717. format_all();
  718. m_have_conditional = false;
  719. // restore state:
  720. m_state = saved_state;
  721. if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
  722. {
  723. // skip the ':':
  724. ++m_position;
  725. // format the rest of this scope:
  726. format_until_scope_end();
  727. }
  728. }
  729. }
  730. template <class OutputIterator, class Results, class traits, class ForwardIter>
  731. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end()
  732. {
  733. do
  734. {
  735. format_all();
  736. if((m_position == m_end) || (*m_position == static_cast<char_type>(')')))
  737. return;
  738. put(*m_position++);
  739. }while(m_position != m_end);
  740. }
  741. template <class OutputIterator, class Results, class traits, class ForwardIter>
  742. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(char_type c)
  743. {
  744. // write a single character to output
  745. // according to which case translation mode we are in:
  746. switch(this->m_state)
  747. {
  748. case output_none:
  749. return;
  750. case output_next_lower:
  751. c = m_traits.tolower(c);
  752. this->m_state = m_restore_state;
  753. break;
  754. case output_next_upper:
  755. c = m_traits.toupper(c);
  756. this->m_state = m_restore_state;
  757. break;
  758. case output_lower:
  759. c = m_traits.tolower(c);
  760. break;
  761. case output_upper:
  762. c = m_traits.toupper(c);
  763. break;
  764. default:
  765. break;
  766. }
  767. *m_out = c;
  768. ++m_out;
  769. }
  770. template <class OutputIterator, class Results, class traits, class ForwardIter>
  771. void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::put(const sub_match_type& sub)
  772. {
  773. typedef typename sub_match_type::iterator iterator_type;
  774. iterator_type i = sub.first;
  775. while(i != sub.second)
  776. {
  777. put(*i);
  778. ++i;
  779. }
  780. }
  781. template <class S>
  782. class string_out_iterator
  783. {
  784. S* out;
  785. public:
  786. string_out_iterator(S& s) : out(&s) {}
  787. string_out_iterator& operator++() { return *this; }
  788. string_out_iterator& operator++(int) { return *this; }
  789. string_out_iterator& operator*() { return *this; }
  790. string_out_iterator& operator=(typename S::value_type v)
  791. {
  792. out->append(1, v);
  793. return *this;
  794. }
  795. typedef std::ptrdiff_t difference_type;
  796. typedef typename S::value_type value_type;
  797. typedef value_type* pointer;
  798. typedef value_type& reference;
  799. typedef std::output_iterator_tag iterator_category;
  800. };
  801. template <class OutputIterator, class Iterator, class Alloc, class ForwardIter, class traits>
  802. OutputIterator regex_format_imp(OutputIterator out,
  803. const match_results<Iterator, Alloc>& m,
  804. ForwardIter p1, ForwardIter p2,
  805. match_flag_type flags,
  806. const traits& t
  807. )
  808. {
  809. if(flags & regex_constants::format_literal)
  810. {
  811. return BOOST_REGEX_DETAIL_NS::copy(p1, p2, out);
  812. }
  813. BOOST_REGEX_DETAIL_NS::basic_regex_formatter<
  814. OutputIterator,
  815. match_results<Iterator, Alloc>,
  816. traits, ForwardIter> f(out, m, t);
  817. return f.format(p1, p2, flags);
  818. }
  819. #ifndef BOOST_NO_SFINAE
  820. BOOST_MPL_HAS_XXX_TRAIT_DEF(const_iterator)
  821. struct any_type
  822. {
  823. template <class T>
  824. any_type(const T&);
  825. template <class T, class U>
  826. any_type(const T&, const U&);
  827. template <class T, class U, class V>
  828. any_type(const T&, const U&, const V&);
  829. };
  830. typedef char no_type;
  831. typedef char (&unary_type)[2];
  832. typedef char (&binary_type)[3];
  833. typedef char (&ternary_type)[4];
  834. no_type check_is_formatter(unary_type, binary_type, ternary_type);
  835. template<typename T>
  836. unary_type check_is_formatter(T const &, binary_type, ternary_type);
  837. template<typename T>
  838. binary_type check_is_formatter(unary_type, T const &, ternary_type);
  839. template<typename T, typename U>
  840. binary_type check_is_formatter(T const &, U const &, ternary_type);
  841. template<typename T>
  842. ternary_type check_is_formatter(unary_type, binary_type, T const &);
  843. template<typename T, typename U>
  844. ternary_type check_is_formatter(T const &, binary_type, U const &);
  845. template<typename T, typename U>
  846. ternary_type check_is_formatter(unary_type, T const &, U const &);
  847. template<typename T, typename U, typename V>
  848. ternary_type check_is_formatter(T const &, U const &, V const &);
  849. struct unary_binary_ternary
  850. {
  851. typedef unary_type (*unary_fun)(any_type);
  852. typedef binary_type (*binary_fun)(any_type, any_type);
  853. typedef ternary_type (*ternary_fun)(any_type, any_type, any_type);
  854. operator unary_fun();
  855. operator binary_fun();
  856. operator ternary_fun();
  857. };
  858. template<typename Formatter, bool IsFunction = boost::is_function<Formatter>::value>
  859. struct formatter_wrapper
  860. : Formatter
  861. , unary_binary_ternary
  862. {
  863. formatter_wrapper(){}
  864. };
  865. template<typename Formatter>
  866. struct formatter_wrapper<Formatter, true>
  867. : unary_binary_ternary
  868. {
  869. operator Formatter *();
  870. };
  871. template<typename Formatter>
  872. struct formatter_wrapper<Formatter *, false>
  873. : unary_binary_ternary
  874. {
  875. operator Formatter *();
  876. };
  877. template <class F, class M, class O>
  878. struct format_traits_imp
  879. {
  880. private:
  881. //
  882. // F must be a pointer, a function, or a class with a function call operator:
  883. //
  884. BOOST_STATIC_ASSERT((::boost::is_pointer<F>::value || ::boost::is_function<F>::value || ::boost::is_class<F>::value));
  885. static formatter_wrapper<typename unwrap_reference<F>::type> f;
  886. static M m;
  887. static O out;
  888. static boost::regex_constants::match_flag_type flags;
  889. public:
  890. BOOST_STATIC_CONSTANT(int, value = sizeof(check_is_formatter(f(m), f(m, out), f(m, out, flags))));
  891. };
  892. template <class F, class M, class O>
  893. struct format_traits
  894. {
  895. public:
  896. //
  897. // Type is mpl::int_<N> where N is one of:
  898. //
  899. // 0 : F is a pointer to a presumably null-terminated string.
  900. // 1 : F is a character-container such as a std::string.
  901. // 2 : F is a Unary Functor.
  902. // 3 : F is a Binary Functor.
  903. // 4 : F is a Ternary Functor.
  904. //
  905. typedef typename boost::mpl::if_<
  906. boost::mpl::and_<boost::is_pointer<F>, boost::mpl::not_<boost::is_function<typename boost::remove_pointer<F>::type> > >,
  907. boost::mpl::int_<0>,
  908. typename boost::mpl::if_<
  909. has_const_iterator<F>,
  910. boost::mpl::int_<1>,
  911. boost::mpl::int_<format_traits_imp<F, M, O>::value>
  912. >::type
  913. >::type type;
  914. //
  915. // This static assertion will fail if the functor passed does not accept
  916. // the same type of arguments passed.
  917. //
  918. BOOST_STATIC_ASSERT( boost::is_class<F>::value && !has_const_iterator<F>::value ? (type::value > 1) : true);
  919. };
  920. #else // BOOST_NO_SFINAE
  921. template <class F, class M, class O>
  922. struct format_traits
  923. {
  924. public:
  925. //
  926. // Type is mpl::int_<N> where N is one of:
  927. //
  928. // 0 : F is a pointer to a presumably null-terminated string.
  929. // 1 : F is a character-container such as a std::string.
  930. //
  931. // Other options such as F being a Functor are not supported without
  932. // SFINAE support.
  933. //
  934. typedef typename boost::mpl::if_<
  935. boost::is_pointer<F>,
  936. boost::mpl::int_<0>,
  937. boost::mpl::int_<1>
  938. >::type type;
  939. };
  940. #endif // BOOST_NO_SFINAE
  941. template <class Base, class Match>
  942. struct format_functor3
  943. {
  944. format_functor3(Base b) : func(b) {}
  945. template <class OutputIter>
  946. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f)
  947. {
  948. return boost::unwrap_ref(func)(m, i, f);
  949. }
  950. template <class OutputIter, class Traits>
  951. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
  952. {
  953. return (*this)(m, i, f);
  954. }
  955. private:
  956. Base func;
  957. format_functor3(const format_functor3&);
  958. format_functor3& operator=(const format_functor3&);
  959. };
  960. template <class Base, class Match>
  961. struct format_functor2
  962. {
  963. format_functor2(Base b) : func(b) {}
  964. template <class OutputIter>
  965. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
  966. {
  967. return boost::unwrap_ref(func)(m, i);
  968. }
  969. template <class OutputIter, class Traits>
  970. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
  971. {
  972. return (*this)(m, i, f);
  973. }
  974. private:
  975. Base func;
  976. format_functor2(const format_functor2&);
  977. format_functor2& operator=(const format_functor2&);
  978. };
  979. template <class Base, class Match>
  980. struct format_functor1
  981. {
  982. format_functor1(Base b) : func(b) {}
  983. template <class S, class OutputIter>
  984. OutputIter do_format_string(const S& s, OutputIter i)
  985. {
  986. return BOOST_REGEX_DETAIL_NS::copy(s.begin(), s.end(), i);
  987. }
  988. template <class S, class OutputIter>
  989. inline OutputIter do_format_string(const S* s, OutputIter i)
  990. {
  991. while(s && *s)
  992. {
  993. *i = *s;
  994. ++i;
  995. ++s;
  996. }
  997. return i;
  998. }
  999. template <class OutputIter>
  1000. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type /*f*/)
  1001. {
  1002. return do_format_string(boost::unwrap_ref(func)(m), i);
  1003. }
  1004. template <class OutputIter, class Traits>
  1005. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits&)
  1006. {
  1007. return (*this)(m, i, f);
  1008. }
  1009. private:
  1010. Base func;
  1011. format_functor1(const format_functor1&);
  1012. format_functor1& operator=(const format_functor1&);
  1013. };
  1014. template <class charT, class Match, class Traits>
  1015. struct format_functor_c_string
  1016. {
  1017. format_functor_c_string(const charT* ps) : func(ps) {}
  1018. template <class OutputIter>
  1019. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
  1020. {
  1021. //typedef typename Match::char_type char_type;
  1022. const charT* end = func;
  1023. while(*end) ++end;
  1024. return regex_format_imp(i, m, func, end, f, t);
  1025. }
  1026. private:
  1027. const charT* func;
  1028. format_functor_c_string(const format_functor_c_string&);
  1029. format_functor_c_string& operator=(const format_functor_c_string&);
  1030. };
  1031. template <class Container, class Match, class Traits>
  1032. struct format_functor_container
  1033. {
  1034. format_functor_container(const Container& c) : func(c) {}
  1035. template <class OutputIter>
  1036. OutputIter operator()(const Match& m, OutputIter i, boost::regex_constants::match_flag_type f, const Traits& t = Traits())
  1037. {
  1038. //typedef typename Match::char_type char_type;
  1039. return BOOST_REGEX_DETAIL_NS::regex_format_imp(i, m, func.begin(), func.end(), f, t);
  1040. }
  1041. private:
  1042. const Container& func;
  1043. format_functor_container(const format_functor_container&);
  1044. format_functor_container& operator=(const format_functor_container&);
  1045. };
  1046. template <class Func, class Match, class OutputIterator, class Traits = BOOST_REGEX_DETAIL_NS::trivial_format_traits<typename Match::char_type> >
  1047. struct compute_functor_type
  1048. {
  1049. typedef typename format_traits<Func, Match, OutputIterator>::type tag;
  1050. typedef typename boost::remove_cv< typename boost::remove_pointer<Func>::type>::type maybe_char_type;
  1051. typedef typename mpl::if_<
  1052. ::boost::is_same<tag, mpl::int_<0> >, format_functor_c_string<maybe_char_type, Match, Traits>,
  1053. typename mpl::if_<
  1054. ::boost::is_same<tag, mpl::int_<1> >, format_functor_container<Func, Match, Traits>,
  1055. typename mpl::if_<
  1056. ::boost::is_same<tag, mpl::int_<2> >, format_functor1<Func, Match>,
  1057. typename mpl::if_<
  1058. ::boost::is_same<tag, mpl::int_<3> >, format_functor2<Func, Match>,
  1059. format_functor3<Func, Match>
  1060. >::type
  1061. >::type
  1062. >::type
  1063. >::type type;
  1064. };
  1065. } // namespace BOOST_REGEX_DETAIL_NS
  1066. template <class OutputIterator, class Iterator, class Allocator, class Functor>
  1067. inline OutputIterator regex_format(OutputIterator out,
  1068. const match_results<Iterator, Allocator>& m,
  1069. Functor fmt,
  1070. match_flag_type flags = format_all
  1071. )
  1072. {
  1073. return m.format(out, fmt, flags);
  1074. }
  1075. template <class Iterator, class Allocator, class Functor>
  1076. inline std::basic_string<typename match_results<Iterator, Allocator>::char_type> regex_format(const match_results<Iterator, Allocator>& m,
  1077. Functor fmt,
  1078. match_flag_type flags = format_all)
  1079. {
  1080. return m.format(fmt, flags);
  1081. }
  1082. #ifdef BOOST_MSVC
  1083. #pragma warning(push)
  1084. #pragma warning(disable: 4103)
  1085. #endif
  1086. #ifdef BOOST_HAS_ABI_HEADERS
  1087. # include BOOST_ABI_SUFFIX
  1088. #endif
  1089. #ifdef BOOST_MSVC
  1090. #pragma warning(pop)
  1091. #endif
  1092. } // namespace boost
  1093. #endif // BOOST_REGEX_FORMAT_HPP