Skip to content

Commit 4c97c59

Browse files
author
Hana Dusíková
committed
Partial fix for #95, adding function starts_with, analyzing subtree for ^ in all paths could be costly, but I will think about it.
1 parent fd55485 commit 4c97c59

File tree

6 files changed

+120
-2
lines changed

6 files changed

+120
-2
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ ctre::match<"REGEX">(subject); // C++20
1616
```
1717

1818
* Matching
19-
* Searching
19+
* Searching (`search` or `starts_with`)
2020
* Capturing content (named captures are supported too)
2121
* Back-Reference (\g{N} syntax, and \1...\9 syntax too)
2222

include/ctre/evaluation.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ constexpr inline auto match_re(const Iterator begin, const EndIterator end, Patt
4343
return evaluate(begin, begin, end, return_type{}, ctll::list<start_mark, Pattern, assert_end, end_mark, accept>());
4444
}
4545

46+
template <typename Iterator, typename EndIterator, typename Pattern>
47+
constexpr inline auto starts_with_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
48+
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
49+
return evaluate(begin, begin, end, return_type{}, ctll::list<start_mark, Pattern, end_mark, accept>());
50+
}
51+
4652
template <typename Iterator, typename EndIterator, typename Pattern>
4753
constexpr inline auto search_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
4854
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));

include/ctre/functions.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,16 @@ template <typename RE> struct regex_search_t {
6666
}
6767
};
6868

69+
template <typename RE> struct regex_starts_with_t {
70+
template <typename... Args> CTRE_FORCE_INLINE constexpr auto operator()(Args && ... args) const noexcept {
71+
auto re_obj = ctre::regular_expression<RE>();
72+
return re_obj.starts_with(std::forward<Args>(args)...);
73+
}
74+
template <typename... Args> CTRE_FORCE_INLINE constexpr auto try_extract(Args && ... args) const noexcept {
75+
return operator()(std::forward<Args>(args)...);
76+
}
77+
};
78+
6979
#if (__cpp_nontype_template_parameter_class || (__cpp_nontype_template_args >= 201911L))
7080

7181
template <auto input> struct regex_builder {
@@ -79,6 +89,8 @@ template <ctll::fixed_string input> static constexpr inline auto match = regex_m
7989

8090
template <ctll::fixed_string input> static constexpr inline auto search = regex_search_t<typename regex_builder<input>::type>();
8191

92+
template <ctll::fixed_string input> static constexpr inline auto starts_with = regex_starts_with_t<typename regex_builder<input>::type>();
93+
8294
#else
8395

8496
template <auto & input> struct regex_builder {
@@ -91,6 +103,9 @@ template <auto & input> static constexpr inline auto match = regex_match_t<typen
91103

92104
template <auto & input> static constexpr inline auto search = regex_search_t<typename regex_builder<input>::type>();
93105

106+
template <auto & input> static constexpr inline auto starts_with = regex_starts_with_t<typename regex_builder<input>::type>();
107+
108+
94109
#endif
95110

96111

include/ctre/wrapper.hpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ template <typename RE> struct regular_expression {
3838
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto search_2(IteratorBegin begin, IteratorEnd end) noexcept {
3939
return search_re(begin, end, RE());
4040
}
41+
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto starts_with_2(IteratorBegin begin, IteratorEnd end) noexcept {
42+
return starts_with(begin, end, RE());
43+
}
4144
constexpr CTRE_FORCE_INLINE regular_expression() noexcept { }
4245
constexpr CTRE_FORCE_INLINE regular_expression(RE) noexcept { }
4346
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto match(Iterator begin, Iterator end) noexcept {
@@ -70,6 +73,7 @@ template <typename RE> struct regular_expression {
7073
template <typename Range, typename = typename std::enable_if<RangeLikeType<Range>::value>::type> static constexpr CTRE_FORCE_INLINE auto match(Range && range) noexcept {
7174
return match(std::begin(range), std::end(range));
7275
}
76+
7377
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto search(Iterator begin, Iterator end) noexcept {
7478
return search_re(begin, end, RE());
7579
}
@@ -100,6 +104,37 @@ template <typename RE> struct regular_expression {
100104
template <typename Range> static constexpr CTRE_FORCE_INLINE auto search(Range && range) noexcept {
101105
return search(std::begin(range), std::end(range));
102106
}
107+
108+
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto starts_with(Iterator begin, Iterator end) noexcept {
109+
return starts_with_re(begin, end, RE());
110+
}
111+
constexpr CTRE_FORCE_INLINE static auto starts_with(const char * s) noexcept {
112+
return starts_with_2(s, zero_terminated_string_end_iterator());
113+
}
114+
static constexpr CTRE_FORCE_INLINE auto starts_with(const wchar_t * s) noexcept {
115+
return starts_with_2(s, zero_terminated_string_end_iterator());
116+
}
117+
static constexpr CTRE_FORCE_INLINE auto starts_with(const std::string & s) noexcept {
118+
return starts_with_2(s.c_str(), zero_terminated_string_end_iterator());
119+
}
120+
static constexpr CTRE_FORCE_INLINE auto starts_with(const std::wstring & s) noexcept {
121+
return starts_with_2(s.c_str(), zero_terminated_string_end_iterator());
122+
}
123+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::string_view sv) noexcept {
124+
return starts_with(sv.begin(), sv.end());
125+
}
126+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::wstring_view sv) noexcept {
127+
return starts_with(sv.begin(), sv.end());
128+
}
129+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::u16string_view sv) noexcept {
130+
return starts_with(sv.begin(), sv.end());
131+
}
132+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::u32string_view sv) noexcept {
133+
return starts_with(sv.begin(), sv.end());
134+
}
135+
template <typename Range> static constexpr CTRE_FORCE_INLINE auto starts_with(Range && range) noexcept {
136+
return starts_with(std::begin(range), std::end(range));
137+
}
103138
};
104139

105140
template <typename RE> regular_expression(RE) -> regular_expression<RE>;

single-header/ctre.hpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3229,6 +3229,12 @@ constexpr inline auto match_re(const Iterator begin, const EndIterator end, Patt
32293229
return evaluate(begin, begin, end, return_type{}, ctll::list<start_mark, Pattern, assert_end, end_mark, accept>());
32303230
}
32313231

3232+
template <typename Iterator, typename EndIterator, typename Pattern>
3233+
constexpr inline auto starts_with_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
3234+
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
3235+
return evaluate(begin, begin, end, return_type{}, ctll::list<start_mark, Pattern, end_mark, accept>());
3236+
}
3237+
32323238
template <typename Iterator, typename EndIterator, typename Pattern>
32333239
constexpr inline auto search_re(const Iterator begin, const EndIterator end, Pattern pattern) noexcept {
32343240
using return_type = decltype(regex_results(std::declval<Iterator>(), find_captures(pattern)));
@@ -3687,6 +3693,9 @@ template <typename RE> struct regular_expression {
36873693
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto search_2(IteratorBegin begin, IteratorEnd end) noexcept {
36883694
return search_re(begin, end, RE());
36893695
}
3696+
template <typename IteratorBegin, typename IteratorEnd> constexpr CTRE_FORCE_INLINE static auto starts_with_2(IteratorBegin begin, IteratorEnd end) noexcept {
3697+
return starts_with(begin, end, RE());
3698+
}
36903699
constexpr CTRE_FORCE_INLINE regular_expression() noexcept { }
36913700
constexpr CTRE_FORCE_INLINE regular_expression(RE) noexcept { }
36923701
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto match(Iterator begin, Iterator end) noexcept {
@@ -3719,6 +3728,7 @@ template <typename RE> struct regular_expression {
37193728
template <typename Range, typename = typename std::enable_if<RangeLikeType<Range>::value>::type> static constexpr CTRE_FORCE_INLINE auto match(Range && range) noexcept {
37203729
return match(std::begin(range), std::end(range));
37213730
}
3731+
37223732
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto search(Iterator begin, Iterator end) noexcept {
37233733
return search_re(begin, end, RE());
37243734
}
@@ -3749,6 +3759,37 @@ template <typename RE> struct regular_expression {
37493759
template <typename Range> static constexpr CTRE_FORCE_INLINE auto search(Range && range) noexcept {
37503760
return search(std::begin(range), std::end(range));
37513761
}
3762+
3763+
template <typename Iterator> constexpr CTRE_FORCE_INLINE static auto starts_with(Iterator begin, Iterator end) noexcept {
3764+
return starts_with_re(begin, end, RE());
3765+
}
3766+
constexpr CTRE_FORCE_INLINE static auto starts_with(const char * s) noexcept {
3767+
return starts_with_2(s, zero_terminated_string_end_iterator());
3768+
}
3769+
static constexpr CTRE_FORCE_INLINE auto starts_with(const wchar_t * s) noexcept {
3770+
return starts_with_2(s, zero_terminated_string_end_iterator());
3771+
}
3772+
static constexpr CTRE_FORCE_INLINE auto starts_with(const std::string & s) noexcept {
3773+
return starts_with_2(s.c_str(), zero_terminated_string_end_iterator());
3774+
}
3775+
static constexpr CTRE_FORCE_INLINE auto starts_with(const std::wstring & s) noexcept {
3776+
return starts_with_2(s.c_str(), zero_terminated_string_end_iterator());
3777+
}
3778+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::string_view sv) noexcept {
3779+
return starts_with(sv.begin(), sv.end());
3780+
}
3781+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::wstring_view sv) noexcept {
3782+
return starts_with(sv.begin(), sv.end());
3783+
}
3784+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::u16string_view sv) noexcept {
3785+
return starts_with(sv.begin(), sv.end());
3786+
}
3787+
static constexpr CTRE_FORCE_INLINE auto starts_with(std::u32string_view sv) noexcept {
3788+
return starts_with(sv.begin(), sv.end());
3789+
}
3790+
template <typename Range> static constexpr CTRE_FORCE_INLINE auto starts_with(Range && range) noexcept {
3791+
return starts_with(std::begin(range), std::end(range));
3792+
}
37523793
};
37533794

37543795
template <typename RE> regular_expression(RE) -> regular_expression<RE>;
@@ -3930,6 +3971,16 @@ template <typename RE> struct regex_search_t {
39303971
}
39313972
};
39323973

3974+
template <typename RE> struct regex_starts_with_t {
3975+
template <typename... Args> CTRE_FORCE_INLINE constexpr auto operator()(Args && ... args) const noexcept {
3976+
auto re_obj = ctre::regular_expression<RE>();
3977+
return re_obj.starts_with(std::forward<Args>(args)...);
3978+
}
3979+
template <typename... Args> CTRE_FORCE_INLINE constexpr auto try_extract(Args && ... args) const noexcept {
3980+
return operator()(std::forward<Args>(args)...);
3981+
}
3982+
};
3983+
39333984
#if (__cpp_nontype_template_parameter_class || (__cpp_nontype_template_args >= 201911L))
39343985

39353986
template <auto input> struct regex_builder {
@@ -3943,6 +3994,8 @@ template <ctll::fixed_string input> static constexpr inline auto match = regex_m
39433994

39443995
template <ctll::fixed_string input> static constexpr inline auto search = regex_search_t<typename regex_builder<input>::type>();
39453996

3997+
template <ctll::fixed_string input> static constexpr inline auto starts_with = regex_starts_with_t<typename regex_builder<input>::type>();
3998+
39463999
#else
39474000

39484001
template <auto & input> struct regex_builder {
@@ -3955,6 +4008,8 @@ template <auto & input> static constexpr inline auto match = regex_match_t<typen
39554008

39564009
template <auto & input> static constexpr inline auto search = regex_search_t<typename regex_builder<input>::type>();
39574010

4011+
template <auto & input> static constexpr inline auto starts_with = regex_starts_with_t<typename regex_builder<input>::type>();
4012+
39584013
#endif
39594014

39604015
}

tests/matching.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,17 @@ template <typename Pattern> constexpr bool search(std::string_view input, Patter
1111
return bool(ctre::search_re(input.begin(), input.end(), pattern));
1212
}
1313

14+
template <typename Pattern> constexpr bool starts_with(std::string_view input, Pattern pattern) {
15+
return bool(ctre::starts_with_re(input.begin(), input.end(), pattern));
16+
}
17+
1418
using namespace std::string_view_literals;
1519

1620
static_assert(match("a"sv, ctre::character<'a'>()));
17-
static_assert(search("abc"sv, ctre::character<'a'>())); // only match from start
21+
static_assert(search("abc"sv, ctre::character<'a'>()));
22+
static_assert(search("abc"sv, ctre::character<'b'>()));
23+
static_assert(starts_with("abc"sv, ctre::character<'a'>()));
24+
static_assert(!starts_with("abc"sv, ctre::character<'b'>()));
1825
static_assert(!match("abc"sv, ctre::character<'b'>()));
1926
static_assert(!match("a"sv, ctre::character<'b'>()));
2027
static_assert(match("a"sv, ctre::any()));

0 commit comments

Comments
 (0)