RegexLibC.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  1. /*
  2. * Copyright (c) 2020, Emanuel Sprung <emanuel.sprung@gmail.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright notice, this
  9. * list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  21. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  23. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include <AK/TestSuite.h>
  27. #include <AK/StringBuilder.h>
  28. #include <LibC/regex.h>
  29. #include <stdio.h>
  30. TEST_CASE(catch_all)
  31. {
  32. String pattern = "^.*$";
  33. regex_t regex;
  34. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  35. EXPECT_EQ(regexec(&regex, "Hello World", 0, NULL, 0), REG_NOERR);
  36. regfree(&regex);
  37. }
  38. TEST_CASE(simple_start)
  39. {
  40. String pattern = "^hello friends";
  41. regex_t regex;
  42. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  43. EXPECT_EQ(regexec(&regex, "Hello!", 0, NULL, 0), REG_NOMATCH);
  44. EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, 0), REG_NOERR);
  45. EXPECT_EQ(regexec(&regex, "Well, hello friends", 0, NULL, 0), REG_NOMATCH);
  46. regfree(&regex);
  47. }
  48. TEST_CASE(simple_end)
  49. {
  50. String pattern = ".*hello\\.\\.\\. there$";
  51. regex_t regex;
  52. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  53. EXPECT_EQ(regexec(&regex, "Hallo", 0, NULL, 0), REG_NOMATCH);
  54. EXPECT_EQ(regexec(&regex, "I said fyhello... there", 0, NULL, 0), REG_NOERR);
  55. EXPECT_EQ(regexec(&regex, "ahello... therea", 0, NULL, 0), REG_NOMATCH);
  56. EXPECT_EQ(regexec(&regex, "hello.. there", 0, NULL, 0), REG_NOMATCH);
  57. regfree(&regex);
  58. }
  59. TEST_CASE(simple_period)
  60. {
  61. String pattern = "hello.";
  62. regex_t regex;
  63. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  64. EXPECT_EQ(regexec(&regex, "Hello1", 0, NULL, 0), REG_NOMATCH);
  65. EXPECT_EQ(regexec(&regex, "hello1", 0, NULL, 0), REG_NOERR);
  66. EXPECT_EQ(regexec(&regex, "hello2", 0, NULL, 0), REG_NOERR);
  67. EXPECT_EQ(regexec(&regex, "hello?", 0, NULL, 0), REG_NOERR);
  68. regfree(&regex);
  69. }
  70. TEST_CASE(simple_period_end)
  71. {
  72. String pattern = "hello.$";
  73. regex_t regex;
  74. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB), REG_NOERR);
  75. EXPECT_EQ(regexec(&regex, "Hello1", 0, NULL, REG_NOSUB), REG_NOMATCH);
  76. EXPECT_EQ(regexec(&regex, "hello1hello1", 0, NULL, REG_GLOBAL), REG_NOERR);
  77. EXPECT_EQ(regexec(&regex, "hello2hell", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  78. EXPECT_EQ(regexec(&regex, "hello?", 0, NULL, REG_NOSUB), REG_NOERR);
  79. regfree(&regex);
  80. }
  81. TEST_CASE(simple_escaped)
  82. {
  83. String pattern = "hello\\.";
  84. regex_t regex;
  85. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  86. EXPECT_EQ(regexec(&regex, "hello", 0, NULL, 0), REG_NOMATCH);
  87. EXPECT_EQ(regexec(&regex, "hello.", 0, NULL, 0), REG_NOERR);
  88. regfree(&regex);
  89. }
  90. TEST_CASE(simple_period2_end)
  91. {
  92. String pattern = ".*hi... there$";
  93. regex_t regex;
  94. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  95. EXPECT_EQ(regexec(&regex, "Hello there", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  96. EXPECT_EQ(regexec(&regex, "I said fyhi... there", 0, NULL, REG_GLOBAL), REG_NOERR);
  97. EXPECT_EQ(regexec(&regex, "....hi... ", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  98. EXPECT_EQ(regexec(&regex, "I said fyhihii there", 0, NULL, REG_GLOBAL), REG_NOERR);
  99. EXPECT_EQ(regexec(&regex, "I said fyhihi there", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  100. regfree(&regex);
  101. }
  102. TEST_CASE(simple_plus)
  103. {
  104. String pattern = "a+";
  105. regex_t regex;
  106. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB), REG_NOERR);
  107. EXPECT_EQ(regexec(&regex, "b", 0, NULL, REG_NOSUB), REG_NOMATCH);
  108. EXPECT_EQ(regexec(&regex, "a", 0, NULL, REG_NOSUB), REG_NOERR);
  109. EXPECT_EQ(regexec(&regex, "aaaaaabbbbb", 0, NULL, REG_GLOBAL), REG_NOERR);
  110. EXPECT_EQ(regexec(&regex, "aaaaaaaaaaa", 0, NULL, REG_GLOBAL), REG_NOERR);
  111. regfree(&regex);
  112. }
  113. TEST_CASE(simple_questionmark)
  114. {
  115. String pattern = "da?d";
  116. regex_t regex;
  117. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  118. EXPECT_EQ(regexec(&regex, "a", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  119. EXPECT_EQ(regexec(&regex, "daa", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  120. EXPECT_EQ(regexec(&regex, "ddddd", 0, NULL, REG_GLOBAL), REG_NOERR);
  121. EXPECT_EQ(regexec(&regex, "dd", 0, NULL, REG_GLOBAL), REG_NOERR);
  122. EXPECT_EQ(regexec(&regex, "dad", 0, NULL, REG_GLOBAL), REG_NOERR);
  123. EXPECT_EQ(regexec(&regex, "dada", 0, NULL, REG_GLOBAL), REG_NOERR);
  124. EXPECT_EQ(regexec(&regex, "adadaa", 0, NULL, REG_GLOBAL), REG_NOERR);
  125. regfree(&regex);
  126. }
  127. TEST_CASE(simple_questionmark_matchall)
  128. {
  129. String pattern = "da?d";
  130. regex_t regex;
  131. static constexpr int num_matches { 5 };
  132. regmatch_t matches[num_matches];
  133. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  134. EXPECT_EQ(regexec(&regex, "a", num_matches, matches, REG_GLOBAL), REG_NOMATCH);
  135. EXPECT_EQ(matches[0].rm_cnt, 0u);
  136. EXPECT_EQ(regexec(&regex, "daa", num_matches, matches, REG_GLOBAL), REG_NOMATCH);
  137. EXPECT_EQ(matches[0].rm_cnt, 0u);
  138. EXPECT_EQ(regexec(&regex, "ddddd", num_matches, matches, REG_GLOBAL), REG_NOERR);
  139. EXPECT_EQ(matches[0].rm_cnt, 2u);
  140. EXPECT_EQ(matches[0].rm_so, 0u);
  141. EXPECT_EQ(matches[0].rm_eo, 2u);
  142. EXPECT_EQ(matches[1].rm_so, 2u);
  143. EXPECT_EQ(matches[1].rm_eo, 4u);
  144. EXPECT_EQ(regexec(&regex, "dd", num_matches, matches, REG_GLOBAL), REG_NOERR);
  145. EXPECT_EQ(matches[0].rm_cnt, 1u);
  146. EXPECT_EQ(regexec(&regex, "dad", num_matches, matches, REG_GLOBAL), REG_NOERR);
  147. EXPECT_EQ(matches[0].rm_cnt, 1u);
  148. EXPECT_EQ(regexec(&regex, "dada", num_matches, matches, REG_GLOBAL), REG_NOERR);
  149. EXPECT_EQ(matches[0].rm_cnt, 1u);
  150. EXPECT_EQ(regexec(&regex, "adadaa", num_matches, matches, REG_GLOBAL), REG_NOERR);
  151. EXPECT_EQ(matches[0].rm_cnt, 1u);
  152. regfree(&regex);
  153. }
  154. TEST_CASE(character_class)
  155. {
  156. String pattern = "[[:alpha:]]";
  157. regex_t regex;
  158. static constexpr int num_matches { 5 };
  159. regmatch_t matches[num_matches];
  160. String haystack = "[Window]\nOpacity=255\nAudibleBeep=0\n";
  161. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  162. EXPECT_EQ(regexec(&regex, haystack.characters(), num_matches, matches, 0), REG_NOMATCH);
  163. EXPECT_EQ(matches[0].rm_cnt, 0u);
  164. EXPECT_EQ(regexec(&regex, haystack.characters(), num_matches, matches, REG_GLOBAL), REG_NOERR);
  165. EXPECT_EQ(matches[0].rm_cnt, 24u);
  166. EXPECT_EQ(haystack.substring_view(matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so), "W");
  167. EXPECT_EQ(haystack.substring_view(matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so), "i");
  168. regfree(&regex);
  169. }
  170. TEST_CASE(character_class2)
  171. {
  172. String pattern = "[[:alpha:]]*=([[:digit:]]*)|\\[(.*)\\]";
  173. regex_t regex;
  174. static constexpr int num_matches { 9 };
  175. regmatch_t matches[num_matches];
  176. String haystack = "[Window]\nOpacity=255\nAudibleBeep=0\n";
  177. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NEWLINE), REG_NOERR);
  178. EXPECT_EQ(regexec(&regex, haystack.characters(), num_matches, matches, 0), REG_NOERR);
  179. EXPECT_EQ(matches[0].rm_cnt, 3u);
  180. #if 0
  181. for (int i = 0; i < num_matches; ++i) {
  182. fprintf(stderr, "Matches[%i].rm_so: %li, .rm_eo: %li .rm_cnt: %li: ", i, matches[i].rm_so, matches[i].rm_eo, matches[i].rm_cnt);
  183. fprintf(stderr, "haystack length: %lu\n", haystack.length());
  184. if (matches[i].rm_so != -1)
  185. fprintf(stderr, "%s\n", haystack.substring_view(matches[i].rm_so, matches[i].rm_eo - matches[i].rm_so).to_string().characters());
  186. }
  187. #endif
  188. EXPECT_EQ(haystack.substring_view(matches[0].rm_so, matches[0].rm_eo - matches[0].rm_so), "[Window]");
  189. EXPECT_EQ(matches[1].rm_so, -1);
  190. EXPECT_EQ(matches[1].rm_eo, -1);
  191. EXPECT_EQ(matches[1].rm_cnt, 0);
  192. EXPECT_EQ(haystack.substring_view(matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so), "Window");
  193. EXPECT_EQ(haystack.substring_view(matches[3].rm_so, matches[3].rm_eo - matches[3].rm_so), "Opacity=255");
  194. EXPECT_EQ(haystack.substring_view(matches[4].rm_so, matches[4].rm_eo - matches[4].rm_so), "255");
  195. EXPECT_EQ(matches[5].rm_so, -1);
  196. EXPECT_EQ(matches[5].rm_eo, -1);
  197. EXPECT_EQ(matches[5].rm_cnt, 0);
  198. EXPECT_EQ(haystack.substring_view(matches[6].rm_so, matches[6].rm_eo - matches[6].rm_so), "AudibleBeep=0");
  199. EXPECT_EQ(haystack.substring_view(matches[7].rm_so, matches[7].rm_eo - matches[7].rm_so), "0");
  200. EXPECT_EQ(matches[8].rm_so, -1);
  201. EXPECT_EQ(matches[8].rm_eo, -1);
  202. EXPECT_EQ(matches[8].rm_cnt, 0);
  203. regfree(&regex);
  204. }
  205. TEST_CASE(escaped_char_questionmark)
  206. {
  207. String pattern = "This\\.?And\\.?That";
  208. regex_t regex;
  209. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  210. EXPECT_EQ(regexec(&regex, "ThisAndThat", 0, NULL, 0), REG_NOERR);
  211. EXPECT_EQ(regexec(&regex, "This.And.That", 0, NULL, 0), REG_NOERR);
  212. EXPECT_EQ(regexec(&regex, "This And That", 0, NULL, 0), REG_NOMATCH);
  213. EXPECT_EQ(regexec(&regex, "This..And..That", 0, NULL, 0), REG_NOMATCH);
  214. regfree(&regex);
  215. }
  216. TEST_CASE(char_qualifier_asterisk)
  217. {
  218. String pattern = "regex*";
  219. regex_t regex;
  220. static constexpr int num_matches { 5 };
  221. regmatch_t matches[num_matches];
  222. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  223. EXPECT_EQ(regexec(&regex, "#include <regex.h>", num_matches, matches, REG_GLOBAL), REG_NOERR);
  224. EXPECT_EQ(matches[0].rm_cnt, 1u);
  225. regfree(&regex);
  226. }
  227. TEST_CASE(char_utf8)
  228. {
  229. String pattern = "😀";
  230. regex_t regex;
  231. static constexpr int num_matches { 5 };
  232. regmatch_t matches[num_matches];
  233. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  234. EXPECT_EQ(regexec(&regex, "Привет, мир! 😀 γειά σου κόσμος 😀 こんにちは世界", num_matches, matches, REG_GLOBAL), REG_NOERR);
  235. EXPECT_EQ(matches[0].rm_cnt, 2u);
  236. regfree(&regex);
  237. }
  238. TEST_CASE(parens)
  239. {
  240. String pattern = "test(hello)test";
  241. regex_t regex;
  242. static constexpr int num_matches { 5 };
  243. regmatch_t matches[num_matches];
  244. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  245. EXPECT_EQ(regexec(&regex, "testhellotest", num_matches, matches, 0), REG_NOERR);
  246. EXPECT_EQ(matches[0].rm_cnt, 1u);
  247. EXPECT_EQ(matches[0].rm_so, 0u);
  248. EXPECT_EQ(matches[0].rm_eo, 13u);
  249. EXPECT_EQ(matches[1].rm_so, 4u);
  250. EXPECT_EQ(matches[1].rm_eo, 9u);
  251. regfree(&regex);
  252. }
  253. TEST_CASE(parser_error_parens)
  254. {
  255. String pattern = "test()test";
  256. regex_t regex;
  257. static constexpr int num_matches { 5 };
  258. regmatch_t matches[num_matches];
  259. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
  260. EXPECT_EQ(regexec(&regex, "testhellotest", num_matches, matches, 0), REG_EMPTY_EXPR);
  261. regfree(&regex);
  262. }
  263. TEST_CASE(parser_error_special_characters_used_at_wrong_place)
  264. {
  265. String pattern;
  266. regex_t regex;
  267. static constexpr int num_matches { 5 };
  268. regmatch_t matches[num_matches];
  269. Vector<char, 4> chars = { '*', '+', '?', '}' };
  270. StringBuilder b;
  271. for (auto& ch : chars) {
  272. auto error_code_to_check = ch == '}' ? REG_EBRACE : REG_BADRPT;
  273. // First in ere
  274. b.clear();
  275. b.append(ch);
  276. pattern = b.build();
  277. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
  278. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
  279. // After vertical line
  280. b.clear();
  281. b.append("a|");
  282. b.append(ch);
  283. pattern = b.build();
  284. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
  285. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
  286. // After circumflex
  287. b.clear();
  288. b.append("^");
  289. b.append(ch);
  290. pattern = b.build();
  291. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
  292. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
  293. // After dollar
  294. b.clear();
  295. b.append("$");
  296. b.append(ch);
  297. pattern = b.build();
  298. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
  299. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
  300. // After left parens
  301. b.clear();
  302. b.append("(");
  303. b.append(ch);
  304. b.append(")");
  305. pattern = b.build();
  306. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), error_code_to_check);
  307. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), error_code_to_check);
  308. }
  309. regfree(&regex);
  310. }
  311. TEST_CASE(parser_error_vertical_line_used_at_wrong_place)
  312. {
  313. String pattern;
  314. regex_t regex;
  315. static constexpr int num_matches { 5 };
  316. regmatch_t matches[num_matches];
  317. // First in ere
  318. pattern = "|asdf";
  319. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
  320. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
  321. // Last in ere
  322. pattern = "asdf|";
  323. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
  324. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
  325. // After left parens
  326. pattern = "(|asdf)";
  327. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
  328. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
  329. // Proceed right parens
  330. pattern = "(asdf)|";
  331. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EMPTY_EXPR);
  332. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_EMPTY_EXPR);
  333. regfree(&regex);
  334. }
  335. TEST_CASE(parens_qualifier_questionmark)
  336. {
  337. String pattern = "test(hello)?test";
  338. regex_t regex;
  339. static constexpr int num_matches { 5 };
  340. regmatch_t matches[num_matches];
  341. const char* match_str;
  342. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  343. match_str = "testtest";
  344. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  345. EXPECT_EQ(matches[0].rm_cnt, 1u);
  346. EXPECT_EQ(matches[0].rm_so, 0u);
  347. EXPECT_EQ(matches[0].rm_eo, 8u);
  348. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
  349. match_str = "testhellotest";
  350. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  351. EXPECT_EQ(matches[0].rm_cnt, 1u);
  352. EXPECT_EQ(matches[0].rm_so, 0u);
  353. EXPECT_EQ(matches[0].rm_eo, 13u);
  354. EXPECT_EQ(matches[1].rm_so, 4u);
  355. EXPECT_EQ(matches[1].rm_eo, 9u);
  356. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellotest");
  357. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  358. regfree(&regex);
  359. }
  360. TEST_CASE(parens_qualifier_asterisk)
  361. {
  362. String pattern = "test(hello)*test";
  363. regex_t regex;
  364. static constexpr int num_matches { 6 };
  365. regmatch_t matches[num_matches];
  366. const char* match_str;
  367. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  368. match_str = "testtest";
  369. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  370. EXPECT_EQ(matches[0].rm_cnt, 1u);
  371. EXPECT_EQ(matches[0].rm_so, 0u);
  372. EXPECT_EQ(matches[0].rm_eo, 8u);
  373. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
  374. match_str = "testhellohellotest";
  375. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  376. EXPECT_EQ(matches[0].rm_cnt, 1u);
  377. EXPECT_EQ(matches[0].rm_so, 0u);
  378. EXPECT_EQ(matches[0].rm_eo, 18u);
  379. EXPECT_EQ(matches[1].rm_so, 9u);
  380. EXPECT_EQ(matches[1].rm_eo, 14u);
  381. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellohellotest");
  382. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  383. match_str = "testhellohellotest, testhellotest";
  384. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  385. EXPECT_EQ(matches[0].rm_cnt, 2u);
  386. EXPECT_EQ(matches[0].rm_so, 0u);
  387. EXPECT_EQ(matches[0].rm_eo, 18u);
  388. EXPECT_EQ(matches[1].rm_so, 9u);
  389. EXPECT_EQ(matches[1].rm_eo, 14u);
  390. EXPECT_EQ(matches[2].rm_so, 20u);
  391. EXPECT_EQ(matches[2].rm_eo, 33u);
  392. EXPECT_EQ(matches[3].rm_so, 24u);
  393. EXPECT_EQ(matches[3].rm_eo, 29u);
  394. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testhellohellotest");
  395. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  396. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "testhellotest");
  397. EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "hello");
  398. regfree(&regex);
  399. }
  400. TEST_CASE(parens_qualifier_asterisk_2)
  401. {
  402. String pattern = "test(.*)test";
  403. regex_t regex;
  404. static constexpr int num_matches { 6 };
  405. regmatch_t matches[num_matches];
  406. const char* match_str;
  407. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  408. match_str = "testasdftest";
  409. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  410. EXPECT_EQ(matches[0].rm_cnt, 1u);
  411. EXPECT_EQ(matches[0].rm_so, 0u);
  412. EXPECT_EQ(matches[0].rm_eo, 12u);
  413. EXPECT_EQ(matches[1].rm_so, 4u);
  414. EXPECT_EQ(matches[1].rm_eo, 8u);
  415. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testasdftest");
  416. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "asdf");
  417. match_str = "testasdfasdftest";
  418. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  419. EXPECT_EQ(matches[0].rm_cnt, 1u);
  420. EXPECT_EQ(matches[0].rm_so, 0u);
  421. EXPECT_EQ(matches[0].rm_eo, 16u);
  422. EXPECT_EQ(matches[1].rm_so, 4u);
  423. EXPECT_EQ(matches[1].rm_eo, 12u);
  424. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testasdfasdftest");
  425. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "asdfasdf");
  426. match_str = "testaaaatest, testbbbtest, testtest";
  427. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  428. EXPECT_EQ(matches[0].rm_cnt, 1u);
  429. EXPECT_EQ(matches[0].rm_so, 0u);
  430. EXPECT_EQ(matches[0].rm_eo, 35u);
  431. EXPECT_EQ(matches[1].rm_so, 4u);
  432. EXPECT_EQ(matches[1].rm_eo, 31u);
  433. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testaaaatest, testbbbtest, testtest");
  434. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "aaaatest, testbbbtest, test");
  435. regfree(&regex);
  436. }
  437. TEST_CASE(mulit_parens_qualifier_too_less_result_values)
  438. {
  439. String pattern = "test(a)?(b)?(c)?test";
  440. regex_t regex;
  441. static constexpr int num_matches { 4 };
  442. regmatch_t matches[num_matches];
  443. const char* match_str;
  444. matches[3] = { -2, -2, 100 };
  445. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  446. match_str = "testabtest";
  447. EXPECT_EQ(regexec(&regex, match_str, num_matches - 1, matches, 0), REG_NOERR);
  448. EXPECT_EQ(matches[0].rm_cnt, 1u);
  449. EXPECT_EQ(matches[0].rm_so, 0u);
  450. EXPECT_EQ(matches[0].rm_eo, 10u);
  451. EXPECT_EQ(matches[1].rm_so, 4u);
  452. EXPECT_EQ(matches[1].rm_eo, 5u);
  453. EXPECT_EQ(matches[2].rm_so, 5u);
  454. EXPECT_EQ(matches[2].rm_eo, 6u);
  455. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabtest");
  456. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
  457. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
  458. EXPECT_EQ(matches[3].rm_so, -2);
  459. EXPECT_EQ(matches[3].rm_eo, -2);
  460. EXPECT_EQ(matches[3].rm_cnt, 100u);
  461. match_str = "testabctest";
  462. EXPECT_EQ(regexec(&regex, match_str, num_matches - 1, matches, 0), REG_NOERR);
  463. EXPECT_EQ(matches[0].rm_cnt, 1u);
  464. EXPECT_EQ(matches[0].rm_so, 0u);
  465. EXPECT_EQ(matches[0].rm_eo, 11u);
  466. EXPECT_EQ(matches[1].rm_so, 4u);
  467. EXPECT_EQ(matches[1].rm_eo, 5u);
  468. EXPECT_EQ(matches[2].rm_so, 5u);
  469. EXPECT_EQ(matches[2].rm_eo, 6u);
  470. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
  471. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
  472. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
  473. EXPECT_EQ(matches[3].rm_so, -2);
  474. EXPECT_EQ(matches[3].rm_eo, -2);
  475. EXPECT_EQ(matches[3].rm_cnt, 100u);
  476. match_str = "testabctest, testabctest";
  477. EXPECT_EQ(regexec(&regex, match_str, num_matches - 1, matches, REG_GLOBAL), REG_NOERR);
  478. EXPECT_EQ(matches[0].rm_cnt, 2u);
  479. EXPECT_EQ(matches[0].rm_so, 0u);
  480. EXPECT_EQ(matches[0].rm_eo, 11u);
  481. EXPECT_EQ(matches[1].rm_so, 4u);
  482. EXPECT_EQ(matches[1].rm_eo, 5u);
  483. EXPECT_EQ(matches[2].rm_so, 5u);
  484. EXPECT_EQ(matches[2].rm_eo, 6u);
  485. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
  486. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
  487. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
  488. EXPECT_EQ(matches[3].rm_so, -2);
  489. EXPECT_EQ(matches[3].rm_eo, -2);
  490. EXPECT_EQ(matches[3].rm_cnt, 100u);
  491. regfree(&regex);
  492. }
  493. TEST_CASE(multi_parens_qualifier_questionmark)
  494. {
  495. String pattern = "test(a)?(b)?(c)?test";
  496. regex_t regex;
  497. static constexpr int num_matches { 8 };
  498. regmatch_t matches[num_matches];
  499. const char* match_str;
  500. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  501. match_str = "testtest";
  502. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  503. EXPECT_EQ(matches[0].rm_cnt, 1u);
  504. EXPECT_EQ(matches[0].rm_so, 0u);
  505. EXPECT_EQ(matches[0].rm_eo, 8u);
  506. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testtest");
  507. match_str = "testabctest";
  508. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  509. EXPECT_EQ(matches[0].rm_cnt, 1u);
  510. EXPECT_EQ(matches[0].rm_so, 0u);
  511. EXPECT_EQ(matches[0].rm_eo, 11u);
  512. EXPECT_EQ(matches[1].rm_so, 4u);
  513. EXPECT_EQ(matches[1].rm_eo, 5u);
  514. EXPECT_EQ(matches[2].rm_so, 5u);
  515. EXPECT_EQ(matches[2].rm_eo, 6u);
  516. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
  517. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
  518. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
  519. match_str = "testabctest, testactest";
  520. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  521. EXPECT_EQ(matches[0].rm_cnt, 2u);
  522. EXPECT_EQ(matches[0].rm_so, 0u);
  523. EXPECT_EQ(matches[0].rm_eo, 11u);
  524. EXPECT_EQ(matches[1].rm_so, 4u);
  525. EXPECT_EQ(matches[1].rm_eo, 5u);
  526. EXPECT_EQ(matches[2].rm_so, 5u);
  527. EXPECT_EQ(matches[2].rm_eo, 6u);
  528. EXPECT_EQ(matches[3].rm_so, 6u);
  529. EXPECT_EQ(matches[3].rm_eo, 7u);
  530. EXPECT_EQ(matches[4].rm_so, 13u);
  531. EXPECT_EQ(matches[4].rm_eo, 23u);
  532. EXPECT_EQ(matches[5].rm_so, 17u);
  533. EXPECT_EQ(matches[5].rm_eo, 18u);
  534. EXPECT_EQ(matches[6].rm_so, -1);
  535. EXPECT_EQ(matches[6].rm_eo, -1);
  536. EXPECT_EQ(matches[7].rm_so, 18u);
  537. EXPECT_EQ(matches[7].rm_eo, 19u);
  538. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testabctest");
  539. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
  540. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
  541. EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "c");
  542. EXPECT_EQ(StringView(&match_str[matches[4].rm_so], matches[4].rm_eo - matches[4].rm_so), "testactest");
  543. EXPECT_EQ(StringView(&match_str[matches[5].rm_so], matches[5].rm_eo - matches[5].rm_so), "a");
  544. EXPECT_EQ(StringView(&match_str[matches[6].rm_so], matches[6].rm_eo - matches[6].rm_so), "");
  545. EXPECT_EQ(StringView(&match_str[matches[7].rm_so], matches[7].rm_eo - matches[7].rm_so), "c");
  546. regfree(&regex);
  547. }
  548. TEST_CASE(simple_alternative)
  549. {
  550. String pattern = "test|hello|friends";
  551. regex_t regex;
  552. static constexpr int num_matches { 1 };
  553. regmatch_t matches[num_matches];
  554. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  555. EXPECT_EQ(regexec(&regex, "test", num_matches, matches, 0), REG_NOERR);
  556. EXPECT_EQ(matches[0].rm_cnt, 1u);
  557. EXPECT_EQ(matches[0].rm_so, 0u);
  558. EXPECT_EQ(matches[0].rm_eo, 4u);
  559. EXPECT_EQ(regexec(&regex, "hello", num_matches, matches, 0), REG_NOERR);
  560. EXPECT_EQ(matches[0].rm_cnt, 1u);
  561. EXPECT_EQ(matches[0].rm_so, 0u);
  562. EXPECT_EQ(matches[0].rm_eo, 5u);
  563. EXPECT_EQ(regexec(&regex, "friends", num_matches, matches, 0), REG_NOERR);
  564. EXPECT_EQ(matches[0].rm_cnt, 1u);
  565. EXPECT_EQ(matches[0].rm_so, 0u);
  566. EXPECT_EQ(matches[0].rm_eo, 7u);
  567. regfree(&regex);
  568. }
  569. TEST_CASE(alternative_match_groups)
  570. {
  571. String pattern = "test(a)?(b)?|hello ?(dear|my)? friends";
  572. regex_t regex;
  573. static constexpr int num_matches { 8 };
  574. regmatch_t matches[num_matches];
  575. const char* match_str;
  576. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  577. match_str = "test";
  578. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  579. EXPECT_EQ(matches[0].rm_cnt, 1u);
  580. EXPECT_EQ(matches[0].rm_so, 0);
  581. EXPECT_EQ(matches[0].rm_eo, 4);
  582. EXPECT_EQ(matches[1].rm_so, -1);
  583. EXPECT_EQ(matches[1].rm_eo, -1);
  584. EXPECT_EQ(matches[2].rm_so, -1);
  585. EXPECT_EQ(matches[2].rm_eo, -1);
  586. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "test");
  587. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
  588. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
  589. match_str = "testa";
  590. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  591. EXPECT_EQ(matches[0].rm_cnt, 1u);
  592. EXPECT_EQ(matches[0].rm_so, 0u);
  593. EXPECT_EQ(matches[0].rm_eo, 5u);
  594. EXPECT_EQ(matches[1].rm_so, 4u);
  595. EXPECT_EQ(matches[1].rm_eo, 5u);
  596. EXPECT_EQ(matches[2].rm_so, -1);
  597. EXPECT_EQ(matches[2].rm_eo, -1);
  598. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testa");
  599. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "a");
  600. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
  601. match_str = "testb";
  602. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  603. EXPECT_EQ(matches[0].rm_cnt, 1u);
  604. EXPECT_EQ(matches[0].rm_so, 0u);
  605. EXPECT_EQ(matches[0].rm_eo, 5u);
  606. EXPECT_EQ(matches[1].rm_so, -1);
  607. EXPECT_EQ(matches[1].rm_eo, -1);
  608. EXPECT_EQ(matches[2].rm_so, 4u);
  609. EXPECT_EQ(matches[2].rm_eo, 5u);
  610. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "testb");
  611. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
  612. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "b");
  613. match_str = "hello friends";
  614. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  615. EXPECT_EQ(matches[0].rm_cnt, 1u);
  616. EXPECT_EQ(matches[0].rm_so, 0u);
  617. EXPECT_EQ(matches[0].rm_eo, 13u);
  618. EXPECT_EQ(matches[1].rm_so, -1);
  619. EXPECT_EQ(matches[1].rm_eo, -1);
  620. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello friends");
  621. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
  622. match_str = "hello dear friends";
  623. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  624. EXPECT_EQ(matches[0].rm_cnt, 1u);
  625. EXPECT_EQ(matches[0].rm_so, 0u);
  626. EXPECT_EQ(matches[0].rm_eo, 18u);
  627. EXPECT_EQ(matches[1].rm_so, -1);
  628. EXPECT_EQ(matches[1].rm_eo, -1);
  629. EXPECT_EQ(matches[2].rm_so, -1);
  630. EXPECT_EQ(matches[2].rm_eo, -1);
  631. EXPECT_EQ(matches[3].rm_so, 6);
  632. EXPECT_EQ(matches[3].rm_eo, 10);
  633. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello dear friends");
  634. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
  635. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
  636. EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "dear");
  637. match_str = "hello my friends";
  638. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  639. EXPECT_EQ(matches[0].rm_cnt, 1u);
  640. EXPECT_EQ(matches[0].rm_so, 0u);
  641. EXPECT_EQ(matches[0].rm_eo, 16u);
  642. EXPECT_EQ(matches[1].rm_so, -1);
  643. EXPECT_EQ(matches[1].rm_eo, -1);
  644. EXPECT_EQ(matches[2].rm_so, -1);
  645. EXPECT_EQ(matches[2].rm_eo, -1);
  646. EXPECT_EQ(matches[3].rm_so, 6);
  647. EXPECT_EQ(matches[3].rm_eo, 8);
  648. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hello my friends");
  649. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "");
  650. EXPECT_EQ(StringView(&match_str[matches[2].rm_so], matches[2].rm_eo - matches[2].rm_so), "");
  651. EXPECT_EQ(StringView(&match_str[matches[3].rm_so], matches[3].rm_eo - matches[3].rm_so), "my");
  652. match_str = "testabc";
  653. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
  654. EXPECT_EQ(matches[0].rm_cnt, 0u);
  655. EXPECT_EQ(matches[0].rm_so, -1);
  656. EXPECT_EQ(matches[0].rm_eo, -1);
  657. match_str = "hello test friends";
  658. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
  659. EXPECT_EQ(matches[0].rm_cnt, 0u);
  660. EXPECT_EQ(matches[0].rm_so, -1);
  661. EXPECT_EQ(matches[0].rm_eo, -1);
  662. regfree(&regex);
  663. }
  664. TEST_CASE(parens_qualifier_exact)
  665. {
  666. String pattern = "(hello){3}";
  667. regex_t regex;
  668. static constexpr int num_matches { 5 };
  669. regmatch_t matches[num_matches];
  670. const char* match_str;
  671. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  672. match_str = "hello";
  673. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
  674. EXPECT_EQ(matches[0].rm_cnt, 0u);
  675. match_str = "hellohellohello";
  676. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  677. EXPECT_EQ(matches[0].rm_cnt, 1u);
  678. EXPECT_EQ(matches[0].rm_so, 0u);
  679. EXPECT_EQ(matches[0].rm_eo, 15u);
  680. EXPECT_EQ(matches[1].rm_so, 10u);
  681. EXPECT_EQ(matches[1].rm_eo, 15u);
  682. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  683. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  684. match_str = "hellohellohellohello";
  685. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  686. EXPECT_EQ(matches[0].rm_cnt, 1u);
  687. EXPECT_EQ(matches[0].rm_so, 0u);
  688. EXPECT_EQ(matches[0].rm_eo, 15u);
  689. EXPECT_EQ(matches[1].rm_so, 10u);
  690. EXPECT_EQ(matches[1].rm_eo, 15u);
  691. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  692. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  693. match_str = "test hellohellohello";
  694. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  695. EXPECT_EQ(matches[0].rm_cnt, 1u);
  696. EXPECT_EQ(matches[0].rm_so, 5u);
  697. EXPECT_EQ(matches[0].rm_eo, 20u);
  698. EXPECT_EQ(matches[1].rm_so, 15u);
  699. EXPECT_EQ(matches[1].rm_eo, 20u);
  700. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  701. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  702. regfree(&regex);
  703. }
  704. TEST_CASE(parens_qualifier_minimum)
  705. {
  706. String pattern = "(hello){3,}";
  707. regex_t regex;
  708. static constexpr int num_matches { 5 };
  709. regmatch_t matches[num_matches];
  710. const char* match_str;
  711. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  712. match_str = "hello";
  713. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
  714. EXPECT_EQ(matches[0].rm_cnt, 0u);
  715. match_str = "hellohellohello";
  716. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  717. EXPECT_EQ(matches[0].rm_cnt, 1u);
  718. EXPECT_EQ(matches[0].rm_so, 0u);
  719. EXPECT_EQ(matches[0].rm_eo, 15u);
  720. EXPECT_EQ(matches[1].rm_so, 10u);
  721. EXPECT_EQ(matches[1].rm_eo, 15u);
  722. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  723. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  724. match_str = "hellohellohellohello";
  725. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_SEARCH), REG_NOERR);
  726. EXPECT_EQ(matches[0].rm_cnt, 1u);
  727. EXPECT_EQ(matches[0].rm_so, 0u);
  728. EXPECT_EQ(matches[0].rm_eo, 20u);
  729. EXPECT_EQ(matches[1].rm_so, 15u);
  730. EXPECT_EQ(matches[1].rm_eo, 20u);
  731. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohellohello");
  732. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  733. match_str = "test hellohellohello";
  734. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  735. EXPECT_EQ(matches[0].rm_cnt, 1u);
  736. EXPECT_EQ(matches[0].rm_so, 5u);
  737. EXPECT_EQ(matches[0].rm_eo, 20u);
  738. EXPECT_EQ(matches[1].rm_so, 15u);
  739. EXPECT_EQ(matches[1].rm_eo, 20u);
  740. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  741. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  742. match_str = "test hellohellohellohello";
  743. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  744. EXPECT_EQ(matches[0].rm_cnt, 1u);
  745. EXPECT_EQ(matches[0].rm_so, 5u);
  746. EXPECT_EQ(matches[0].rm_eo, 25u);
  747. EXPECT_EQ(matches[1].rm_so, 20u);
  748. EXPECT_EQ(matches[1].rm_eo, 25u);
  749. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohellohello");
  750. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  751. regfree(&regex);
  752. }
  753. TEST_CASE(parens_qualifier_maximum)
  754. {
  755. String pattern = "(hello){2,3}";
  756. regex_t regex;
  757. static constexpr int num_matches { 5 };
  758. regmatch_t matches[num_matches];
  759. const char* match_str;
  760. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  761. match_str = "hello";
  762. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOMATCH);
  763. EXPECT_EQ(matches[0].rm_cnt, 0u);
  764. match_str = "hellohellohello";
  765. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, 0), REG_NOERR);
  766. EXPECT_EQ(matches[0].rm_cnt, 1u);
  767. EXPECT_EQ(matches[0].rm_so, 0u);
  768. EXPECT_EQ(matches[0].rm_eo, 15u);
  769. EXPECT_EQ(matches[1].rm_so, 10u);
  770. EXPECT_EQ(matches[1].rm_eo, 15u);
  771. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  772. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  773. match_str = "hellohellohellohello";
  774. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  775. EXPECT_EQ(matches[0].rm_cnt, 1u);
  776. EXPECT_EQ(matches[0].rm_so, 0u);
  777. EXPECT_EQ(matches[0].rm_eo, 15u);
  778. EXPECT_EQ(matches[1].rm_so, 10u);
  779. EXPECT_EQ(matches[1].rm_eo, 15u);
  780. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  781. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  782. match_str = "test hellohellohello";
  783. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  784. EXPECT_EQ(matches[0].rm_cnt, 1u);
  785. EXPECT_EQ(matches[0].rm_so, 5u);
  786. EXPECT_EQ(matches[0].rm_eo, 20u);
  787. EXPECT_EQ(matches[1].rm_so, 15u);
  788. EXPECT_EQ(matches[1].rm_eo, 20u);
  789. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  790. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  791. match_str = "test hellohellohellohello";
  792. EXPECT_EQ(regexec(&regex, match_str, num_matches, matches, REG_GLOBAL), REG_NOERR);
  793. EXPECT_EQ(matches[0].rm_cnt, 1u);
  794. EXPECT_EQ(matches[0].rm_so, 5u);
  795. EXPECT_EQ(matches[0].rm_eo, 20u);
  796. EXPECT_EQ(matches[1].rm_so, 15u);
  797. EXPECT_EQ(matches[1].rm_eo, 20u);
  798. EXPECT_EQ(StringView(&match_str[matches[0].rm_so], matches[0].rm_eo - matches[0].rm_so), "hellohellohello");
  799. EXPECT_EQ(StringView(&match_str[matches[1].rm_so], matches[1].rm_eo - matches[1].rm_so), "hello");
  800. regfree(&regex);
  801. }
  802. TEST_CASE(char_qualifier_min_max)
  803. {
  804. String pattern = "c{3,30}";
  805. regex_t regex;
  806. static constexpr int num_matches { 5 };
  807. regmatch_t matches[num_matches];
  808. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  809. EXPECT_EQ(regexec(&regex, "cc", num_matches, matches, 0), REG_NOMATCH);
  810. EXPECT_EQ(regexec(&regex, "ccc", num_matches, matches, 0), REG_NOERR);
  811. EXPECT_EQ(regexec(&regex, "cccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOERR);
  812. EXPECT_EQ(matches[0].rm_cnt, 1u);
  813. EXPECT_EQ(regexec(&regex, "ccccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOMATCH);
  814. EXPECT_EQ(regexec(&regex, "ccccccccccccccccccccccccccccccc", num_matches, matches, REG_GLOBAL), REG_NOERR);
  815. EXPECT_EQ(regexec(&regex, "cccccccccccccccccccccccccccccccc", num_matches, matches, 0), REG_NOMATCH);
  816. regfree(&regex);
  817. }
  818. TEST_CASE(simple_bracket_chars)
  819. {
  820. String pattern = "[abc]";
  821. regex_t regex;
  822. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  823. EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOERR);
  824. EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOERR);
  825. EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOERR);
  826. EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOMATCH);
  827. EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOMATCH);
  828. }
  829. TEST_CASE(simple_bracket_chars_inverse)
  830. {
  831. String pattern = "[^abc]";
  832. regex_t regex;
  833. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  834. EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOMATCH);
  835. EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOMATCH);
  836. EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOMATCH);
  837. EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOERR);
  838. EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOERR);
  839. }
  840. TEST_CASE(simple_bracket_chars_range)
  841. {
  842. String pattern = "[a-d]";
  843. regex_t regex;
  844. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  845. EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOERR);
  846. EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOERR);
  847. EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOERR);
  848. EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOERR);
  849. EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOMATCH);
  850. }
  851. TEST_CASE(simple_bracket_chars_range_inverse)
  852. {
  853. String pattern = "[^a-df-z]";
  854. regex_t regex;
  855. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  856. EXPECT_EQ(regexec(&regex, "a", 0, NULL, 0), REG_NOMATCH);
  857. EXPECT_EQ(regexec(&regex, "b", 0, NULL, 0), REG_NOMATCH);
  858. EXPECT_EQ(regexec(&regex, "c", 0, NULL, 0), REG_NOMATCH);
  859. EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOMATCH);
  860. EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOERR);
  861. EXPECT_EQ(regexec(&regex, "k", 0, NULL, 0), REG_NOMATCH);
  862. EXPECT_EQ(regexec(&regex, "z", 0, NULL, 0), REG_NOMATCH);
  863. }
  864. TEST_CASE(bracket_character_class_uuid)
  865. {
  866. String pattern = "^([[:xdigit:]]{8})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{12})$";
  867. regex_t regex;
  868. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  869. EXPECT_EQ(regexec(&regex, "fb9b62a2-1579-4e3a-afba-76239ccb6583", 0, NULL, 0), REG_NOERR);
  870. EXPECT_EQ(regexec(&regex, "fb9b62a2", 0, NULL, 0), REG_NOMATCH);
  871. regfree(&regex);
  872. }
  873. TEST_CASE(simple_bracket_character_class_inverse)
  874. {
  875. String pattern = "[^[:digit:]]";
  876. regex_t regex;
  877. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  878. EXPECT_EQ(regexec(&regex, "1", 0, NULL, 0), REG_NOMATCH);
  879. EXPECT_EQ(regexec(&regex, "2", 0, NULL, 0), REG_NOMATCH);
  880. EXPECT_EQ(regexec(&regex, "3", 0, NULL, 0), REG_NOMATCH);
  881. EXPECT_EQ(regexec(&regex, "d", 0, NULL, 0), REG_NOERR);
  882. EXPECT_EQ(regexec(&regex, "e", 0, NULL, 0), REG_NOERR);
  883. }
  884. TEST_CASE(email_address)
  885. {
  886. String pattern = "^[A-Z0-9a-z._%+-]{1,64}@(?:[A-Za-z0-9-]{1,63}\\.){1,125}[A-Za-z]{2,63}$";
  887. regex_t regex;
  888. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_NOERR);
  889. EXPECT_EQ(regexec(&regex, "emanuel.sprung@gmail.com", 0, NULL, 0), REG_NOERR);
  890. EXPECT_EQ(regexec(&regex, "kling@serenityos.org", 0, NULL, 0), REG_NOERR);
  891. regfree(&regex);
  892. }
  893. TEST_CASE(error_message)
  894. {
  895. String pattern = "^[A-Z0-9[a-z._%+-]{1,64}@[A-Za-z0-9-]{1,63}\\.{1,125}[A-Za-z]{2,63}$";
  896. regex_t regex;
  897. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED), REG_EBRACK);
  898. EXPECT_EQ(regexec(&regex, "asdf@asdf.com", 0, NULL, 0), REG_EBRACK);
  899. char buf[1024];
  900. size_t buflen = 1024;
  901. auto len = regerror(0, &regex, buf, buflen);
  902. String expected = "Error during parsing of regular expression:\n ^[A-Z0-9[a-z._%+-]{1,64}@[A-Za-z0-9-]{1,63}\\.{1,125}[A-Za-z]{2,63}$\n ^---- [ ] imbalance.";
  903. for (size_t i = 0; i < len; ++i) {
  904. EXPECT_EQ(buf[i], expected[i]);
  905. }
  906. regfree(&regex);
  907. }
  908. TEST_CASE(simple_ignorecase)
  909. {
  910. String pattern = "^hello friends";
  911. regex_t regex;
  912. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
  913. EXPECT_EQ(regexec(&regex, "Hello Friends", 0, NULL, 0), REG_NOERR);
  914. EXPECT_EQ(regexec(&regex, "hello Friends", 0, NULL, 0), REG_NOERR);
  915. EXPECT_EQ(regexec(&regex, "hello Friends!", 0, NULL, 0), REG_NOMATCH);
  916. EXPECT_EQ(regexec(&regex, "hello Friends!", 0, NULL, REG_GLOBAL), REG_NOERR);
  917. EXPECT_EQ(regexec(&regex, "hell Friends", 0, NULL, 0), REG_NOMATCH);
  918. EXPECT_EQ(regexec(&regex, "hell Friends", 0, NULL, REG_GLOBAL), REG_NOMATCH);
  919. regfree(&regex);
  920. }
  921. TEST_CASE(simple_notbol_noteol)
  922. {
  923. String pattern = "^hello friends$";
  924. String pattern2 = "hello friends";
  925. regex_t regex, regex2;
  926. EXPECT_EQ(regcomp(&regex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
  927. EXPECT_EQ(regcomp(&regex2, pattern2.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
  928. EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
  929. EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
  930. EXPECT_EQ(regexec(&regex, "hello friends", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
  931. EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL), REG_NOMATCH);
  932. EXPECT_EQ(regexec(&regex, "a hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
  933. EXPECT_EQ(regexec(&regex, "a hello friends", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
  934. EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
  935. EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
  936. EXPECT_EQ(regexec(&regex, "hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
  937. EXPECT_EQ(regexec(&regex, "hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOERR);
  938. EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
  939. EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
  940. EXPECT_EQ(regexec(&regex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
  941. EXPECT_EQ(regexec(&regex2, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
  942. EXPECT_EQ(regexec(&regex2, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
  943. regfree(&regex);
  944. }
  945. TEST_MAIN(Regex)