regex_format.hpp 33 KB

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