Skip to content

Commit b34a5c2

Browse files
committed
Optimization: Check for implicit anchor
Improves code generation for cases where .* can be treated as an anchor
1 parent eeada60 commit b34a5c2

File tree

5 files changed

+204
-3
lines changed

5 files changed

+204
-3
lines changed

include/ctre/evaluation.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "atoms.hpp"
66
#include "atoms_unicode.hpp"
77
#include "starts_with_anchor.hpp"
8+
#include "has_implicit_anchor.hpp"
89
#include "utility.hpp"
910
#include "return_type.hpp"
1011
#include "find_captures.hpp"

include/ctre/has_implicit_anchor.hpp

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#ifndef CTRE__HAS_IMPLICIT_ANCHOR__HPP
2+
#define CTRE__HAS_IMPLICIT_ANCHOR__HPP
3+
4+
#include "atoms.hpp"
5+
#include "atoms_unicode.hpp"
6+
7+
namespace ctre {
8+
9+
template<typename... Content>
10+
constexpr bool has_implicit_anchor(ctll::list<repeat<0, 0, any>, Content...>) noexcept {
11+
return true;
12+
}
13+
template<typename... Content>
14+
constexpr bool has_implicit_anchor(ctll::list<repeat<1, 0, any>, Content...>) noexcept {
15+
return true;
16+
}
17+
18+
template<typename... Content>
19+
constexpr bool has_implicit_anchor(ctll::list<possessive_repeat<0, 0, any>, Content...>) noexcept {
20+
return true;
21+
}
22+
23+
template<typename... Content>
24+
constexpr bool has_implicit_anchor(ctll::list<possessive_repeat<1, 0, any>, Content...>) noexcept {
25+
return true;
26+
}
27+
28+
template<typename... Content>
29+
constexpr bool has_implicit_anchor(ctll::list<lazy_repeat<0, 0, any>, Content...>) noexcept {
30+
return true;
31+
}
32+
33+
template<typename... Content>
34+
constexpr bool has_implicit_anchor(ctll::list<lazy_repeat<1, 0, any>, Content...>) noexcept {
35+
return true;
36+
}
37+
38+
template<typename... Content, typename... Tail>
39+
constexpr bool has_implicit_anchor(ctll::list<sequence<Content...>, Tail...>) noexcept {
40+
return has_implicit_anchor(ctll::list<Content..., Tail...>{});
41+
}
42+
43+
//TODO: we may check captures as implicit anchors*, but they must not be backreferenced because for example "(.+)X\1" will not work properly with "1234X2345"
44+
/*
45+
template<size_t Id, typename... Content, typename... Tail>
46+
constexpr bool has_implicit_anchor(ctll::list<capture<Id, Content...>, Tail...>) noexcept {
47+
//Id must not be backreferenced
48+
return !id_backreference(Id) && has_implicit_anchor(ctll::list<Content..., Tail...>{});
49+
}
50+
51+
template<size_t Id, typename Name, typename... Content, typename... Tail>
52+
constexpr bool has_implicit_anchor(ctll::list<capture_with_name<Id, Name, Content...>, Tail...>) noexcept {
53+
//Id must not be backreferenced
54+
return !id_backreference(Id) && has_implicit_anchor(ctll::list<Content..., Tail...>{});
55+
}
56+
*/
57+
58+
template<typename... Opts, typename... Tail>
59+
constexpr bool has_implicit_anchor(ctll::list<select<Opts...>, Tail...>) noexcept {
60+
return (has_implicit_anchor(ctll::list<Opts, Tail...>{}) && ...);
61+
}
62+
63+
constexpr bool has_implicit_anchor(...) noexcept {
64+
return false;
65+
}
66+
}
67+
68+
#endif

include/ctre/wrapper.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct search_method {
6262
template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept {
6363
using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
6464

65-
constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{});
65+
constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{}) || has_implicit_anchor(ctll::list<RE>{});
6666

6767
auto it = begin;
6868

single-header/ctre-unicode.hpp

+67-1
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,72 @@ constexpr bool starts_with_anchor(const flags & f, ctll::list<capture_with_name<
27202720

27212721
#endif
27222722

2723+
#ifndef CTRE__HAS_IMPLICIT_ANCHOR__HPP
2724+
#define CTRE__HAS_IMPLICIT_ANCHOR__HPP
2725+
2726+
namespace ctre {
2727+
2728+
template<typename... Content>
2729+
constexpr bool has_implicit_anchor(ctll::list<repeat<0, 0, any>, Content...>) noexcept {
2730+
return true;
2731+
}
2732+
template<typename... Content>
2733+
constexpr bool has_implicit_anchor(ctll::list<repeat<1, 0, any>, Content...>) noexcept {
2734+
return true;
2735+
}
2736+
2737+
template<typename... Content>
2738+
constexpr bool has_implicit_anchor(ctll::list<possessive_repeat<0, 0, any>, Content...>) noexcept {
2739+
return true;
2740+
}
2741+
2742+
template<typename... Content>
2743+
constexpr bool has_implicit_anchor(ctll::list<possessive_repeat<1, 0, any>, Content...>) noexcept {
2744+
return true;
2745+
}
2746+
2747+
template<typename... Content>
2748+
constexpr bool has_implicit_anchor(ctll::list<lazy_repeat<0, 0, any>, Content...>) noexcept {
2749+
return true;
2750+
}
2751+
2752+
template<typename... Content>
2753+
constexpr bool has_implicit_anchor(ctll::list<lazy_repeat<1, 0, any>, Content...>) noexcept {
2754+
return true;
2755+
}
2756+
2757+
template<typename... Content, typename... Tail>
2758+
constexpr bool has_implicit_anchor(ctll::list<sequence<Content...>, Tail...>) noexcept {
2759+
return has_implicit_anchor(ctll::list<Content..., Tail...>{});
2760+
}
2761+
2762+
//TODO: we may check captures as implicit anchors*, but they must not be backreferenced because for example "(.+)X\1" will not work properly with "1234X2345"
2763+
/*
2764+
template<size_t Id, typename... Content, typename... Tail>
2765+
constexpr bool has_implicit_anchor(ctll::list<capture<Id, Content...>, Tail...>) noexcept {
2766+
//Id must not be backreferenced
2767+
return !id_backreference(Id) && has_implicit_anchor(ctll::list<Content..., Tail...>{});
2768+
}
2769+
2770+
template<size_t Id, typename Name, typename... Content, typename... Tail>
2771+
constexpr bool has_implicit_anchor(ctll::list<capture_with_name<Id, Name, Content...>, Tail...>) noexcept {
2772+
//Id must not be backreferenced
2773+
return !id_backreference(Id) && has_implicit_anchor(ctll::list<Content..., Tail...>{});
2774+
}
2775+
*/
2776+
2777+
template<typename... Opts, typename... Tail>
2778+
constexpr bool has_implicit_anchor(ctll::list<select<Opts...>, Tail...>) noexcept {
2779+
return (has_implicit_anchor(ctll::list<Opts, Tail...>{}) && ...);
2780+
}
2781+
2782+
constexpr bool has_implicit_anchor(...) noexcept {
2783+
return false;
2784+
}
2785+
}
2786+
2787+
#endif
2788+
27232789
#ifndef CTRE__RETURN_TYPE__HPP
27242790
#define CTRE__RETURN_TYPE__HPP
27252791

@@ -4878,7 +4944,7 @@ struct search_method {
48784944
template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept {
48794945
using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
48804946

4881-
constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{});
4947+
constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{}) || has_implicit_anchor(ctll::list<RE>{});
48824948

48834949
auto it = begin;
48844950

single-header/ctre.hpp

+67-1
Original file line numberDiff line numberDiff line change
@@ -2717,6 +2717,72 @@ constexpr bool starts_with_anchor(const flags & f, ctll::list<capture_with_name<
27172717

27182718
#endif
27192719

2720+
#ifndef CTRE__HAS_IMPLICIT_ANCHOR__HPP
2721+
#define CTRE__HAS_IMPLICIT_ANCHOR__HPP
2722+
2723+
namespace ctre {
2724+
2725+
template<typename... Content>
2726+
constexpr bool has_implicit_anchor(ctll::list<repeat<0, 0, any>, Content...>) noexcept {
2727+
return true;
2728+
}
2729+
template<typename... Content>
2730+
constexpr bool has_implicit_anchor(ctll::list<repeat<1, 0, any>, Content...>) noexcept {
2731+
return true;
2732+
}
2733+
2734+
template<typename... Content>
2735+
constexpr bool has_implicit_anchor(ctll::list<possessive_repeat<0, 0, any>, Content...>) noexcept {
2736+
return true;
2737+
}
2738+
2739+
template<typename... Content>
2740+
constexpr bool has_implicit_anchor(ctll::list<possessive_repeat<1, 0, any>, Content...>) noexcept {
2741+
return true;
2742+
}
2743+
2744+
template<typename... Content>
2745+
constexpr bool has_implicit_anchor(ctll::list<lazy_repeat<0, 0, any>, Content...>) noexcept {
2746+
return true;
2747+
}
2748+
2749+
template<typename... Content>
2750+
constexpr bool has_implicit_anchor(ctll::list<lazy_repeat<1, 0, any>, Content...>) noexcept {
2751+
return true;
2752+
}
2753+
2754+
template<typename... Content, typename... Tail>
2755+
constexpr bool has_implicit_anchor(ctll::list<sequence<Content...>, Tail...>) noexcept {
2756+
return has_implicit_anchor(ctll::list<Content..., Tail...>{});
2757+
}
2758+
2759+
//TODO: we may check captures as implicit anchors*, but they must not be backreferenced because for example "(.+)X\1" will not work properly with "1234X2345"
2760+
/*
2761+
template<size_t Id, typename... Content, typename... Tail>
2762+
constexpr bool has_implicit_anchor(ctll::list<capture<Id, Content...>, Tail...>) noexcept {
2763+
//Id must not be backreferenced
2764+
return !id_backreference(Id) && has_implicit_anchor(ctll::list<Content..., Tail...>{});
2765+
}
2766+
2767+
template<size_t Id, typename Name, typename... Content, typename... Tail>
2768+
constexpr bool has_implicit_anchor(ctll::list<capture_with_name<Id, Name, Content...>, Tail...>) noexcept {
2769+
//Id must not be backreferenced
2770+
return !id_backreference(Id) && has_implicit_anchor(ctll::list<Content..., Tail...>{});
2771+
}
2772+
*/
2773+
2774+
template<typename... Opts, typename... Tail>
2775+
constexpr bool has_implicit_anchor(ctll::list<select<Opts...>, Tail...>) noexcept {
2776+
return (has_implicit_anchor(ctll::list<Opts, Tail...>{}) && ...);
2777+
}
2778+
2779+
constexpr bool has_implicit_anchor(...) noexcept {
2780+
return false;
2781+
}
2782+
}
2783+
2784+
#endif
2785+
27202786
#ifndef CTRE__RETURN_TYPE__HPP
27212787
#define CTRE__RETURN_TYPE__HPP
27222788

@@ -4875,7 +4941,7 @@ struct search_method {
48754941
template <typename Modifier = singleline, typename ResultIterator = void, typename RE, typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto exec(IteratorBegin orig_begin, IteratorBegin begin, IteratorEnd end, RE) noexcept {
48764942
using result_iterator = std::conditional_t<std::is_same_v<ResultIterator, void>, IteratorBegin, ResultIterator>;
48774943

4878-
constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{});
4944+
constexpr bool fixed = starts_with_anchor(Modifier{}, ctll::list<RE>{}) || has_implicit_anchor(ctll::list<RE>{});
48794945

48804946
auto it = begin;
48814947

0 commit comments

Comments
 (0)