regex_format.hpp 33 KB

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