Skip to content

Commit ec4bd97

Browse files
author
Hana Dusíková
committed
added detection for pattern which starts with anchor so we can remove the for cycle in search (full solution to #95)
1 parent 4c97c59 commit ec4bd97

File tree

3 files changed

+156
-4
lines changed

3 files changed

+156
-4
lines changed

include/ctre/evaluation.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "atoms.hpp"
55
#include "atoms_characters.hpp"
66
#include "atoms_unicode.hpp"
7+
#include "starts_with_anchor.hpp"
78
#include "utility.hpp"
89
#include "return_type.hpp"
910
#include "find_captures.hpp"
@@ -53,14 +54,16 @@ template <typename Iterator, typename EndIterator, typename Pattern>
5354
constexpr inline auto search_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
5455
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
5556

57+
[[maybe_unused]] constexpr bool fixed = starts_with_anchor(ctll::list<Pattern>{});
58+
5659
auto it = begin;
57-
for (; end != it; ++it) {
60+
for (; end != it && !fixed; ++it) {
5861
if (auto out = evaluate(begin, it, end, return_type{}, ctll::list<start_mark, Pattern, end_mark, accept>())) {
5962
return out;
6063
}
6164
}
6265

63-
// in case the RE is empty
66+
// in case the RE is empty or fixed
6467
return evaluate(begin, it, end, return_type{}, ctll::list<start_mark, Pattern, end_mark, accept>());
6568
}
6669

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#ifndef CTRE__STARTS_WITH_ANCHOR__HPP
2+
#define CTRE__STARTS_WITH_ANCHOR__HPP
3+
4+
namespace ctre {
5+
6+
template <typename... Content>
7+
constexpr bool starts_with_anchor(ctll::list<Content...>) noexcept {
8+
return false;
9+
}
10+
11+
template <typename... Content>
12+
constexpr bool starts_with_anchor(ctll::list<assert_begin, Content...>) noexcept {
13+
// yes! start anchor is here
14+
return true;
15+
}
16+
17+
template <typename... Options, typename... Content>
18+
constexpr bool starts_with_anchor(ctll::list<select<Options...>, Content...>) noexcept {
19+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
20+
return (starts_with_anchor(ctll::list<Options, Content...>{}) && ... && true);
21+
}
22+
23+
template <typename... Optional, typename... Content>
24+
constexpr bool starts_with_anchor(ctll::list<optional<Optional...>, Content...>) noexcept {
25+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
26+
return starts_with_anchor(ctll::list<Optional..., Content...>{}) && starts_with_anchor(ctll::list<Content...>{});
27+
}
28+
29+
template <typename... Optional, typename... Content>
30+
constexpr bool starts_with_anchor(ctll::list<lazy_optional<Optional...>, Content...>) noexcept {
31+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
32+
return starts_with_anchor(ctll::list<Optional..., Content...>{}) && starts_with_anchor(ctll::list<Content...>{});
33+
}
34+
35+
template <typename... Seq, typename... Content>
36+
constexpr bool starts_with_anchor(ctll::list<sequence<Seq...>, Content...>) noexcept {
37+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
38+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
39+
}
40+
41+
template <size_t A, size_t B, typename... Seq, typename... Content>
42+
constexpr bool starts_with_anchor(ctll::list<repeat<A, B, Seq...>, Content...>) noexcept {
43+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
44+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
45+
}
46+
47+
template <size_t A, size_t B, typename... Seq, typename... Content>
48+
constexpr bool starts_with_anchor(ctll::list<lazy_repeat<A, B, Seq...>, Content...>) noexcept {
49+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
50+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
51+
}
52+
53+
template <size_t A, size_t B, typename... Seq, typename... Content>
54+
constexpr bool starts_with_anchor(ctll::list<possessive_repeat<A, B, Seq...>, Content...>) noexcept {
55+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
56+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
57+
}
58+
59+
template <size_t Index, typename... Seq, typename... Content>
60+
constexpr bool starts_with_anchor(ctll::list<capture<Index, Seq...>, Content...>) noexcept {
61+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
62+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
63+
}
64+
65+
template <size_t Index, typename... Seq, typename... Content>
66+
constexpr bool starts_with_anchor(ctll::list<capture_with_name<Index, Seq...>, Content...>) noexcept {
67+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
68+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
69+
}
70+
71+
}
72+
73+
#endif

single-header/ctre.hpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2264,6 +2264,80 @@ template <auto V, auto... Value, auto... Name, typename... Ts, typename Paramete
22642264
#ifndef CTRE__EVALUATION__HPP
22652265
#define CTRE__EVALUATION__HPP
22662266

2267+
#ifndef CTRE__STARTS_WITH_ANCHOR__HPP
2268+
#define CTRE__STARTS_WITH_ANCHOR__HPP
2269+
2270+
namespace ctre {
2271+
2272+
template <typename... Content>
2273+
constexpr bool starts_with_anchor(ctll::list<Content...>) noexcept {
2274+
return false;
2275+
}
2276+
2277+
template <typename... Content>
2278+
constexpr bool starts_with_anchor(ctll::list<assert_begin, Content...>) noexcept {
2279+
// yes! start anchor is here
2280+
return true;
2281+
}
2282+
2283+
template <typename... Options, typename... Content>
2284+
constexpr bool starts_with_anchor(ctll::list<select<Options...>, Content...>) noexcept {
2285+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2286+
return (starts_with_anchor(ctll::list<Options, Content...>{}) && ... && true);
2287+
}
2288+
2289+
template <typename... Optional, typename... Content>
2290+
constexpr bool starts_with_anchor(ctll::list<optional<Optional...>, Content...>) noexcept {
2291+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2292+
return starts_with_anchor(ctll::list<Optional..., Content...>{}) && starts_with_anchor(ctll::list<Content...>{});
2293+
}
2294+
2295+
template <typename... Optional, typename... Content>
2296+
constexpr bool starts_with_anchor(ctll::list<lazy_optional<Optional...>, Content...>) noexcept {
2297+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2298+
return starts_with_anchor(ctll::list<Optional..., Content...>{}) && starts_with_anchor(ctll::list<Content...>{});
2299+
}
2300+
2301+
template <typename... Seq, typename... Content>
2302+
constexpr bool starts_with_anchor(ctll::list<sequence<Seq...>, Content...>) noexcept {
2303+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2304+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
2305+
}
2306+
2307+
template <size_t A, size_t B, typename... Seq, typename... Content>
2308+
constexpr bool starts_with_anchor(ctll::list<repeat<A, B, Seq...>, Content...>) noexcept {
2309+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2310+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
2311+
}
2312+
2313+
template <size_t A, size_t B, typename... Seq, typename... Content>
2314+
constexpr bool starts_with_anchor(ctll::list<lazy_repeat<A, B, Seq...>, Content...>) noexcept {
2315+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2316+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
2317+
}
2318+
2319+
template <size_t A, size_t B, typename... Seq, typename... Content>
2320+
constexpr bool starts_with_anchor(ctll::list<possessive_repeat<A, B, Seq...>, Content...>) noexcept {
2321+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2322+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
2323+
}
2324+
2325+
template <size_t Index, typename... Seq, typename... Content>
2326+
constexpr bool starts_with_anchor(ctll::list<capture<Index, Seq...>, Content...>) noexcept {
2327+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2328+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
2329+
}
2330+
2331+
template <size_t Index, typename... Seq, typename... Content>
2332+
constexpr bool starts_with_anchor(ctll::list<capture_with_name<Index, Seq...>, Content...>) noexcept {
2333+
// check if all options starts with anchor or if they are empty, there is an anchor behind them
2334+
return starts_with_anchor(ctll::list<Seq..., Content...>{});
2335+
}
2336+
2337+
}
2338+
2339+
#endif
2340+
22672341
#ifndef CTRE__RETURN_TYPE__HPP
22682342
#define CTRE__RETURN_TYPE__HPP
22692343

@@ -3239,14 +3313,16 @@ template <typename Iterator, typename EndIterator, typename Pattern>
32393313
constexpr inline auto search_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
32403314
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
32413315

3316+
[[maybe_unused]] constexpr bool fixed = starts_with_anchor(ctll::list<Pattern>{});
3317+
32423318
auto it = begin;
3243-
for (; end != it; ++it) {
3319+
for (; end != it && !fixed; ++it) {
32443320
if (auto out = evaluate(begin, it, end, return_type{}, ctll::list<start_mark, Pattern, end_mark, accept>())) {
32453321
return out;
32463322
}
32473323
}
32483324

3249-
// in case the RE is empty
3325+
// in case the RE is empty or fixed
32503326
return evaluate(begin, it, end, return_type{}, ctll::list<start_mark, Pattern, end_mark, accept>());
32513327
}
32523328

0 commit comments

Comments
 (0)