testsuite_regex.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. // -*- C++ -*-
  2. // regex utils for the C++ library testsuite.
  3. //
  4. // Copyright (C) 2012-2022 Free Software Foundation, Inc.
  5. //
  6. // This file is part of the GNU ISO C++ Library. This library is free
  7. // software; you can redistribute it and/or modify it under the
  8. // terms of the GNU General Public License as published by the
  9. // Free Software Foundation; either version 3, or (at your option)
  10. // any later version.
  11. //
  12. // This library is distributed in the hope that it will be useful,
  13. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. // GNU General Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public License along
  18. // with this library; see the file COPYING3. If not see
  19. // <http://www.gnu.org/licenses/>.
  20. //
  21. #ifndef _TESTSUITE_REGEX_H
  22. #define _TESTSUITE_REGEX_H 1
  23. #include <regex>
  24. #include <stdexcept>
  25. #include <iostream>
  26. namespace __gnu_test
  27. {
  28. // Test on a compilation of simple expressions, throw regex_error on error.
  29. typedef std::regex regex_type;
  30. typedef regex_type::flag_type flag_type;
  31. typedef std::regex_constants::match_flag_type match_flag_type;
  32. typedef std::regex_constants::error_type error_type;
  33. typedef std::size_t size_type;
  34. typedef std::string string_type;
  35. using std::basic_regex;
  36. using std::match_results;
  37. // Utilities
  38. struct regex_expected_fail { };
  39. const error_type regex_error_internal(static_cast<error_type>(-1));
  40. // Stringify error codes for text logging.
  41. const char* regex_error_codes[] =
  42. {
  43. "error_collate",
  44. "error_ctype",
  45. "error_escape",
  46. "error_backref",
  47. "error_brack",
  48. "error_paren",
  49. "error_brace",
  50. "error_badbrace",
  51. "error_range",
  52. "error_space",
  53. "error_badrepeat",
  54. "error_complexity",
  55. "error_stack"
  56. };
  57. void
  58. show_regex_error_codes()
  59. {
  60. using namespace std;
  61. using namespace std::regex_constants;
  62. const char tab('\t');
  63. cout << "error_collate = " << tab << error_collate << endl;
  64. cout << "error_ctype = " << tab << error_ctype << endl;
  65. cout << "error_escape = " << tab << error_escape << endl;
  66. cout << "error_backref = " << tab << error_backref << endl;
  67. cout << "error_brack = " << tab << error_brack << endl;
  68. cout << "error_paren = " << tab << error_paren << endl;
  69. cout << "error_brace = " << tab << error_brace << endl;
  70. cout << "error_badbrace = " << tab << error_badbrace << endl;
  71. cout << "error_range = " << tab << error_range << endl;
  72. cout << "error_space = " << tab << error_space << endl;
  73. cout << "error_badrepeat = " << tab << error_badrepeat << endl;
  74. cout << "error_complexity =" << tab << error_complexity << endl;
  75. cout << "error_stack = " << tab << error_stack << endl;
  76. }
  77. // Arguments
  78. // string __res: the regular expression string
  79. // flag_type __f: flag
  80. // __error: expected error, if any
  81. void
  82. regex_sanity_check(const string_type& __res,
  83. flag_type __f = regex_type::basic,
  84. error_type __error = regex_error_internal)
  85. {
  86. using namespace std;
  87. try
  88. {
  89. regex_type reo(__res, __f);
  90. auto n = reo.mark_count();
  91. cout << "regex_type::mark_count " << n << endl;
  92. }
  93. catch (const regex_error& e)
  94. {
  95. cout << "regex_sanity_check: " << __res << endl;
  96. cout << "regex_error::what " << e.what() << endl;
  97. show_regex_error_codes();
  98. cout << "regex_error::code " << regex_error_codes[e.code()] << endl;
  99. if (__error != regex_error_internal)
  100. {
  101. // Then expected error_type is __error. Check.
  102. if (__error != e.code())
  103. {
  104. throw regex_expected_fail();
  105. }
  106. }
  107. throw;
  108. }
  109. catch (const logic_error& e)
  110. {
  111. cout << "logic_error::what " << e.what() << endl;
  112. throw;
  113. }
  114. catch (const std::exception& e)
  115. {
  116. cout << "exception: " << endl;
  117. throw;
  118. }
  119. }
  120. // regex_match_debug behaves like regex_match, but will run *two* executors
  121. // (if there's no back-reference) and check if their results agree. If not,
  122. // an exception is thrown. The arguments are the same as for regex_match.
  123. template<typename _Bi_iter, typename _Alloc,
  124. typename _Ch_type, typename _Rx_traits>
  125. bool
  126. regex_match_debug(_Bi_iter __s,
  127. _Bi_iter __e,
  128. match_results<_Bi_iter, _Alloc>& __m,
  129. const basic_regex<_Ch_type, _Rx_traits>& __re,
  130. match_flag_type __flags
  131. = std::regex_constants::match_default)
  132. {
  133. using namespace std::__detail;
  134. auto __res1 = __regex_algo_impl(__s, __e, __m, __re, __flags,
  135. _RegexExecutorPolicy::_S_auto,
  136. true);
  137. match_results<_Bi_iter, _Alloc> __mm;
  138. auto __res2 = __regex_algo_impl(__s, __e, __mm, __re, __flags,
  139. _RegexExecutorPolicy::_S_alternate,
  140. true);
  141. if (__res1 == __res2 && __m == __mm)
  142. return __res1;
  143. throw std::exception();
  144. }
  145. // No match_results version
  146. template<typename _Bi_iter, typename _Ch_type, typename _Rx_traits>
  147. inline bool
  148. regex_match_debug(_Bi_iter __first,
  149. _Bi_iter __last,
  150. const basic_regex<_Ch_type, _Rx_traits>& __re,
  151. match_flag_type __flags
  152. = std::regex_constants::match_default)
  153. {
  154. match_results<_Bi_iter> __what;
  155. return regex_match_debug(__first, __last, __what, __re, __flags);
  156. }
  157. // C-string version
  158. template<typename _Ch_type, typename _Alloc, typename _Rx_traits>
  159. inline bool
  160. regex_match_debug(const _Ch_type* __s,
  161. match_results<const _Ch_type*, _Alloc>& __m,
  162. const basic_regex<_Ch_type, _Rx_traits>& __re,
  163. match_flag_type __f
  164. = std::regex_constants::match_default)
  165. { return regex_match_debug(__s, __s + _Rx_traits::length(__s),
  166. __m, __re, __f); }
  167. // C-string version without match_results
  168. template<typename _Ch_type, class _Rx_traits>
  169. inline bool
  170. regex_match_debug(const _Ch_type* __s,
  171. const basic_regex<_Ch_type, _Rx_traits>& __re,
  172. match_flag_type __f
  173. = std::regex_constants::match_default)
  174. { return regex_match_debug(__s, __s + _Rx_traits::length(__s),
  175. __re, __f); }
  176. // std::basic_string version
  177. template<typename _Ch_traits, typename _Ch_alloc,
  178. typename _Alloc, typename _Ch_type, typename _Rx_traits>
  179. inline bool
  180. regex_match_debug(const std::basic_string<_Ch_type, _Ch_traits,
  181. _Ch_alloc>& __s,
  182. match_results<typename std::basic_string<_Ch_type,
  183. _Ch_traits, _Ch_alloc>::const_iterator,
  184. _Alloc>& __m,
  185. const basic_regex<_Ch_type, _Rx_traits>& __re,
  186. match_flag_type __flags
  187. = std::regex_constants::match_default)
  188. { return regex_match_debug(__s.begin(), __s.end(),
  189. __m, __re, __flags); }
  190. // std::basic_string version without match_results
  191. template<typename _Ch_traits, typename _Str_allocator,
  192. typename _Ch_type, typename _Rx_traits>
  193. inline bool
  194. regex_match_debug(const std::basic_string<_Ch_type, _Ch_traits,
  195. _Str_allocator>& __s,
  196. const basic_regex<_Ch_type, _Rx_traits>& __re,
  197. match_flag_type __flags
  198. = std::regex_constants::match_default)
  199. { return regex_match_debug(__s.begin(), __s.end(), __re, __flags); }
  200. // regex_match_debug behaves like regex_match, but will run *two* executors
  201. // (if there's no back-reference) and check if their results agree. If not,
  202. // an exception throws. One can use them just in the way of using regex_match.
  203. template<typename _Bi_iter, typename _Alloc,
  204. typename _Ch_type, typename _Rx_traits>
  205. bool
  206. regex_search_debug(_Bi_iter __s,
  207. _Bi_iter __e,
  208. match_results<_Bi_iter, _Alloc>& __m,
  209. const basic_regex<_Ch_type, _Rx_traits>& __re,
  210. match_flag_type __flags
  211. = std::regex_constants::match_default)
  212. {
  213. using namespace std::__detail;
  214. auto __res1 = __regex_algo_impl(__s, __e, __m, __re, __flags,
  215. _RegexExecutorPolicy::_S_auto,
  216. false);
  217. match_results<_Bi_iter, _Alloc> __mm;
  218. auto __res2 = __regex_algo_impl(__s, __e, __mm, __re, __flags,
  219. _RegexExecutorPolicy::_S_alternate,
  220. false);
  221. if (__res1 == __res2 && __m == __mm)
  222. return __res1;
  223. throw(std::exception()); // Let test fail. Give it a name.
  224. }
  225. // No match_results version
  226. template<typename _Bi_iter, typename _Ch_type, typename _Rx_traits>
  227. inline bool
  228. regex_search_debug(_Bi_iter __first,
  229. _Bi_iter __last,
  230. const basic_regex<_Ch_type, _Rx_traits>& __re,
  231. match_flag_type __flags
  232. = std::regex_constants::match_default)
  233. {
  234. match_results<_Bi_iter> __what;
  235. return regex_search_debug(__first, __last, __what, __re, __flags);
  236. }
  237. // C-string version
  238. template<typename _Ch_type, class _Alloc, class _Rx_traits>
  239. inline bool
  240. regex_search_debug(const _Ch_type* __s,
  241. match_results<const _Ch_type*, _Alloc>& __m,
  242. const basic_regex<_Ch_type, _Rx_traits>& __e,
  243. match_flag_type __f
  244. = std::regex_constants::match_default)
  245. { return regex_search_debug(__s, __s + _Rx_traits::length(__s),
  246. __m, __e, __f); }
  247. // C-string version without match_results
  248. template<typename _Ch_type, typename _Rx_traits>
  249. inline bool
  250. regex_search_debug(const _Ch_type* __s,
  251. const basic_regex<_Ch_type, _Rx_traits>& __e,
  252. match_flag_type __f
  253. = std::regex_constants::match_default)
  254. { return regex_search_debug(__s, __s + _Rx_traits::length(__s),
  255. __e, __f); }
  256. // std::basic_string version
  257. template<typename _Ch_traits, typename _Ch_alloc,
  258. typename _Alloc, typename _Ch_type,
  259. typename _Rx_traits>
  260. inline bool
  261. regex_search_debug(const std::basic_string<_Ch_type, _Ch_traits,
  262. _Ch_alloc>& __s,
  263. match_results<typename std::basic_string<_Ch_type,
  264. _Ch_traits, _Ch_alloc>::const_iterator, _Alloc>&
  265. __m,
  266. const basic_regex<_Ch_type, _Rx_traits>& __e,
  267. match_flag_type __f
  268. = std::regex_constants::match_default)
  269. { return regex_search_debug(__s.begin(), __s.end(), __m, __e, __f); }
  270. // std::basic_string version without match_results
  271. template<typename _Ch_traits, typename _String_allocator,
  272. typename _Ch_type, typename _Rx_traits>
  273. inline bool
  274. regex_search_debug(const std::basic_string<_Ch_type, _Ch_traits,
  275. _String_allocator>& __s,
  276. const basic_regex<_Ch_type, _Rx_traits>& __e,
  277. match_flag_type __f
  278. = std::regex_constants::match_default)
  279. { return regex_search_debug(__s.begin(), __s.end(), __e, __f); }
  280. } // namespace __gnu_test
  281. #endif