mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 12:32:43 +00:00 
			
		
		
		
	LibRegex: Add RegexStringView wrapper to support utf8 and utf32 views
This commit is contained in:
		
							parent
							
								
									12dd40a2a5
								
							
						
					
					
						commit
						4a630d4b63
					
				
					 11 changed files with 596 additions and 304 deletions
				
			
		|  | @ -79,7 +79,7 @@ int regcomp(regex_t* reg, const char* pattern, int cflags) | |||
|     preg->cflags = cflags; | ||||
| 
 | ||||
|     String pattern_str(pattern); | ||||
|     preg->re = make<Regex<PosixExtended>>(pattern_str, PosixOptions {} | (PosixFlags)cflags); | ||||
|     preg->re = make<Regex<PosixExtended>>(pattern_str, PosixOptions {} | (PosixFlags)cflags | PosixFlags::SkipTrimEmptyMatches); | ||||
| 
 | ||||
|     auto parser_result = preg->re->parser_result; | ||||
|     if (parser_result.error != regex::Error::NoError) { | ||||
|  | @ -109,9 +109,9 @@ int regexec(const regex_t* reg, const char* string, size_t nmatch, regmatch_t pm | |||
| 
 | ||||
|     RegexResult result; | ||||
|     if (eflags & REG_SEARCH) | ||||
|         result = preg->re->search({ string }, PosixOptions {} | (PosixFlags)eflags); | ||||
|         result = preg->re->search(string, PosixOptions {} | (PosixFlags)eflags); | ||||
|     else | ||||
|         result = preg->re->match({ string }, PosixOptions {} | (PosixFlags)eflags); | ||||
|         result = preg->re->match(string, PosixOptions {} | (PosixFlags)eflags); | ||||
| 
 | ||||
|     if (result.success) { | ||||
|         auto size = result.matches.size(); | ||||
|  |  | |||
|  | @ -47,8 +47,10 @@ class OpCode_SaveLeftNamedCaptureGroup; | |||
| class OpCode_SaveNamedLeftCaptureGroup; | ||||
| class OpCode_SaveRightNamedCaptureGroup; | ||||
| class OpCode_Compare; | ||||
| class RegexStringView; | ||||
| } | ||||
| 
 | ||||
| using regex::Error; | ||||
| using regex::Lexer; | ||||
| using regex::PosixExtendedParser; | ||||
| using regex::RegexStringView; | ||||
|  |  | |||
|  | @ -346,7 +346,7 @@ ALWAYS_INLINE ExecutionResult OpCode_Compare::execute(const MatchInput& input, M | |||
|                 return ExecutionResult::Failed_ExecuteLowPrioForks; | ||||
| 
 | ||||
|             auto character_class = (CharClass)m_bytecode->at(offset++); | ||||
|             auto& ch = input.view[state.string_position]; | ||||
|             auto ch = input.view[state.string_position]; | ||||
| 
 | ||||
|             compare_character_class(input, state, character_class, ch, inverse, inverse_matched); | ||||
| 
 | ||||
|  | @ -375,10 +375,9 @@ ALWAYS_INLINE ExecutionResult OpCode_Compare::execute(const MatchInput& input, M | |||
|     return ExecutionResult::Continue; | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE void OpCode_Compare::compare_char(const MatchInput& input, MatchState& state, char& ch, bool inverse, bool& inverse_matched) const | ||||
| ALWAYS_INLINE void OpCode_Compare::compare_char(const MatchInput& input, MatchState& state, u32 ch1, bool inverse, bool& inverse_matched) | ||||
| { | ||||
|     auto ch1 = ch; | ||||
|     auto ch2 = input.view[state.string_position]; | ||||
|     u32 ch2 = input.view[state.string_position]; | ||||
| 
 | ||||
|     if (input.regex_options & AllFlags::Insensitive) { | ||||
|         ch1 = tolower(ch1); | ||||
|  | @ -393,10 +392,12 @@ ALWAYS_INLINE void OpCode_Compare::compare_char(const MatchInput& input, MatchSt | |||
|     } | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE bool OpCode_Compare::compare_string(const MatchInput& input, MatchState& state, const char* str, size_t length) const | ||||
| ALWAYS_INLINE bool OpCode_Compare::compare_string(const MatchInput& input, MatchState& state, const char* str, size_t length) | ||||
| { | ||||
|     if (input.view.is_u8_view()) { | ||||
|         auto str_view1 = StringView(str, length); | ||||
|     auto str_view2 = StringView(&input.view[state.string_position], length); | ||||
|         auto str_view2 = StringView(&input.view.u8view()[state.string_position], length); | ||||
| 
 | ||||
|         String str1, str2; | ||||
|         if (input.regex_options & AllFlags::Insensitive) { | ||||
|             str1 = str_view1.to_string().to_lowercase(); | ||||
|  | @ -408,11 +409,13 @@ ALWAYS_INLINE bool OpCode_Compare::compare_string(const MatchInput& input, Match | |||
|         if (str_view1 == str_view2) { | ||||
|             state.string_position += length; | ||||
|             return true; | ||||
|     } else | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE void OpCode_Compare::compare_character_class(const MatchInput& input, MatchState& state, CharClass character_class, char ch, bool inverse, bool& inverse_matched) const | ||||
| ALWAYS_INLINE void OpCode_Compare::compare_character_class(const MatchInput& input, MatchState& state, CharClass character_class, char ch, bool inverse, bool& inverse_matched) | ||||
| { | ||||
|     switch (character_class) { | ||||
|     case CharClass::Alnum: | ||||
|  | @ -510,7 +513,7 @@ ALWAYS_INLINE void OpCode_Compare::compare_character_class(const MatchInput& inp | |||
|     } | ||||
| } | ||||
| 
 | ||||
| ALWAYS_INLINE void OpCode_Compare::compare_character_range(const MatchInput& input, MatchState& state, char from, char to, char ch, bool inverse, bool& inverse_matched) const | ||||
| ALWAYS_INLINE void OpCode_Compare::compare_character_range(const MatchInput& input, MatchState& state, char from, char to, char ch, bool inverse, bool& inverse_matched) | ||||
| { | ||||
|     if (input.regex_options & AllFlags::Insensitive) { | ||||
|         from = tolower(from); | ||||
|  | @ -536,9 +539,7 @@ const Vector<String> OpCode_Compare::variable_arguments_to_string(Optional<Match | |||
|     Vector<String> result; | ||||
| 
 | ||||
|     size_t offset { state().instruction_position + 3 }; | ||||
|     StringView view; | ||||
|     if (input.has_value()) | ||||
|         view = input.value().view; | ||||
|     RegexStringView view = ((input.has_value()) ? input.value().view : nullptr); | ||||
| 
 | ||||
|     for (size_t i = 0; i < arguments_count(); ++i) { | ||||
|         auto compare_type = (CharacterCompareType)m_bytecode->at(offset++); | ||||
|  | @ -548,23 +549,23 @@ const Vector<String> OpCode_Compare::variable_arguments_to_string(Optional<Match | |||
|             char ch = m_bytecode->at(offset++); | ||||
|             result.empend(String::format("value='%c'", ch)); | ||||
|             if (!view.is_null()) | ||||
|                 result.empend(String::format("compare against: '%s'", String { view.substring_view(state().string_position, state().string_position + 1 > view.length() ? 0 : 1) }.characters())); | ||||
|                 result.empend(String::format("compare against: '%s'", view.substring_view(state().string_position, state().string_position + 1 > view.length() ? 0 : 1).to_string().characters())); | ||||
|         } else if (compare_type == CharacterCompareType::String) { | ||||
|             char* str = reinterpret_cast<char*>(m_bytecode->at(offset++)); | ||||
|             auto& length = m_bytecode->at(offset++); | ||||
|             result.empend(String::format("value=\"%s\"", String { str, length }.characters())); | ||||
|             if (!view.is_null()) | ||||
|                 result.empend(String::format("compare against: \"%s\"", String { input.value().view.substring_view(state().string_position, state().string_position + length > view.length() ? 0 : length) }.characters())); | ||||
|                 result.empend(String::format("compare against: \"%s\"", input.value().view.substring_view(state().string_position, state().string_position + length > view.length() ? 0 : length).to_string().characters())); | ||||
|         } else if (compare_type == CharacterCompareType::CharClass) { | ||||
|             auto character_class = (CharClass)m_bytecode->at(offset++); | ||||
|             result.empend(String::format("ch_class=%lu [%s]", (size_t)character_class, character_class_name(character_class))); | ||||
|             if (!view.is_null()) | ||||
|                 result.empend(String::format("compare against: '%s'", String { input.value().view.substring_view(state().string_position, state().string_position + 1 > view.length() ? 0 : 1) }.characters())); | ||||
|                 result.empend(String::format("compare against: '%s'", input.value().view.substring_view(state().string_position, state().string_position + 1 > view.length() ? 0 : 1).to_string().characters())); | ||||
|         } else if (compare_type == CharacterCompareType::CharRange) { | ||||
|             auto value = (CharRange)m_bytecode->at(offset++); | ||||
|             result.empend(String::format("ch_range='%c'-'%c'", value.from, value.to)); | ||||
|             if (!view.is_null()) | ||||
|                 result.empend(String::format("compare against: '%s'", String { input.value().view.substring_view(state().string_position, state().string_position + 1 > view.length() ? 0 : 1) }.characters())); | ||||
|                 result.empend(String::format("compare against: '%s'",  input.value().view.substring_view(state().string_position, state().string_position + 1 > view.length() ? 0 : 1).to_string().characters())); | ||||
|         } | ||||
|     } | ||||
|     return result; | ||||
|  |  | |||
|  | @ -407,7 +407,6 @@ protected: | |||
|     Optional<MatchState*> m_state; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| class OpCode_Exit final : public OpCode { | ||||
| public: | ||||
|     OpCode_Exit(ByteCode& bytecode) | ||||
|  | @ -567,10 +566,10 @@ public: | |||
|     const Vector<String> variable_arguments_to_string(Optional<MatchInput> input = {}) const; | ||||
| 
 | ||||
| private: | ||||
|     ALWAYS_INLINE void compare_char(const MatchInput& input, MatchState& state, char& ch, bool inverse, bool& inverse_matched) const; | ||||
|     ALWAYS_INLINE bool compare_string(const MatchInput& input, MatchState& state, const char* str, size_t length) const; | ||||
|     ALWAYS_INLINE void compare_character_class(const MatchInput& input, MatchState& state, CharClass character_class, char ch, bool inverse, bool& inverse_matched) const; | ||||
|     ALWAYS_INLINE void compare_character_range(const MatchInput& input, MatchState& state, char from, char to, char ch, bool inverse, bool& inverse_matched) const; | ||||
|     ALWAYS_INLINE static void compare_char(const MatchInput& input, MatchState& state, u32 ch1, bool inverse, bool& inverse_matched); | ||||
|     ALWAYS_INLINE static bool compare_string(const MatchInput& input, MatchState& state, const char* str, size_t length); | ||||
|     ALWAYS_INLINE static void compare_character_class(const MatchInput& input, MatchState& state, CharClass character_class, char ch, bool inverse, bool& inverse_matched); | ||||
|     ALWAYS_INLINE static void compare_character_range(const MatchInput& input, MatchState& state, char from, char to, char ch, bool inverse, bool& inverse_matched); | ||||
| }; | ||||
| 
 | ||||
| template<typename T> | ||||
|  |  | |||
|  | @ -31,11 +31,196 @@ | |||
| #include "AK/FlyString.h" | ||||
| #include "AK/HashMap.h" | ||||
| #include "AK/String.h" | ||||
| #include "AK/StringBuilder.h" | ||||
| #include "AK/StringView.h" | ||||
| #include "AK/Utf32View.h" | ||||
| #include "AK/Vector.h" | ||||
| 
 | ||||
| namespace regex { | ||||
| 
 | ||||
| class RegexStringView { | ||||
| public: | ||||
|     RegexStringView(const char* chars) | ||||
|         : m_u8view(chars) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     RegexStringView(const String& string) | ||||
|         : m_u8view(string) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     RegexStringView(const StringView view) | ||||
|         : m_u8view(view) | ||||
|     { | ||||
|     } | ||||
|     RegexStringView(const Utf32View view) | ||||
|         : m_u32view(view) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     bool is_u8_view() const { return m_u8view.has_value(); } | ||||
|     bool is_u32_view() const { return m_u32view.has_value(); } | ||||
| 
 | ||||
|     const StringView& u8view() const | ||||
|     { | ||||
|         ASSERT(m_u8view.has_value()); | ||||
|         return m_u8view.value(); | ||||
|     }; | ||||
| 
 | ||||
|     const Utf32View& u32view() const | ||||
|     { | ||||
|         ASSERT(m_u32view.has_value()); | ||||
|         return m_u32view.value(); | ||||
|     }; | ||||
| 
 | ||||
|     bool is_empty() const | ||||
|     { | ||||
|         if (is_u8_view()) | ||||
|             return m_u8view.value().is_empty(); | ||||
|         else | ||||
|             return m_u32view.value().is_empty(); | ||||
|     } | ||||
| 
 | ||||
|     bool is_null() const | ||||
|     { | ||||
|         if (is_u8_view()) | ||||
|             return m_u8view.value().is_null(); | ||||
|         else | ||||
|             return m_u32view.value().code_points() == nullptr; | ||||
|     } | ||||
| 
 | ||||
|     size_t length() const | ||||
|     { | ||||
|         if (is_u8_view()) | ||||
|             return m_u8view.value().length(); | ||||
|         else | ||||
|             return m_u32view.value().length(); | ||||
|     } | ||||
| 
 | ||||
|     Vector<RegexStringView> lines() const | ||||
|     { | ||||
|         if (is_u8_view()) { | ||||
|             auto views = u8view().lines(false); | ||||
|             Vector<RegexStringView> new_views; | ||||
|             for (auto& view : views) | ||||
|                 new_views.append(move(view)); | ||||
|             return new_views; | ||||
|         } | ||||
| 
 | ||||
|         // FIXME: line splitting for Utf32View needed
 | ||||
|         Vector<RegexStringView> views; | ||||
|         views.append(m_u32view.value()); | ||||
|         return views; | ||||
|     } | ||||
| 
 | ||||
|     RegexStringView substring_view(size_t offset, size_t length) const | ||||
|     { | ||||
|         if (is_u8_view()) { | ||||
|             return u8view().substring_view(offset, length); | ||||
|         } | ||||
|         return u32view().substring_view(offset, length); | ||||
|     } | ||||
| 
 | ||||
|     String to_string() const | ||||
|     { | ||||
|         if (is_u8_view()) { | ||||
|             return u8view().to_string(); | ||||
|         } | ||||
| 
 | ||||
|         StringBuilder builder; | ||||
|         builder.append(u32view()); | ||||
|         return builder.to_string(); | ||||
|     } | ||||
| 
 | ||||
|     u32 operator[](size_t index) const | ||||
|     { | ||||
|         if (is_u8_view()) { | ||||
|             return u8view()[index]; | ||||
|         } | ||||
|         return u32view().code_points()[index]; | ||||
|     } | ||||
| 
 | ||||
|     bool operator==(const char* cstring) const | ||||
|     { | ||||
|         if (is_u8_view()) | ||||
|             return u8view() == cstring; | ||||
| 
 | ||||
|         return to_string() == cstring; | ||||
|     } | ||||
| 
 | ||||
|     bool operator!=(const char* cstring) const | ||||
|     { | ||||
|         return !(*this == cstring); | ||||
|     } | ||||
| 
 | ||||
|     bool operator==(const String& string) const | ||||
|     { | ||||
|         if (is_u8_view()) | ||||
|             return u8view() == string; | ||||
| 
 | ||||
|         return to_string() == string; | ||||
|     } | ||||
| 
 | ||||
|     bool operator==(const StringView& other) const | ||||
|     { | ||||
|         if (is_u8_view()) | ||||
|             return u8view() == other; | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     bool operator!=(const StringView& other) const | ||||
|     { | ||||
|         return !(*this == other); | ||||
|     } | ||||
| 
 | ||||
|     bool operator==(const Utf32View& other) const | ||||
|     { | ||||
|         if (is_u32_view()) { | ||||
|             StringBuilder builder; | ||||
|             builder.append(other); | ||||
|             return to_string() == builder.to_string(); | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     bool operator!=(const Utf32View& other) const | ||||
|     { | ||||
|         return !(*this == other); | ||||
|     } | ||||
| 
 | ||||
|     const char* characters_without_null_termination() const | ||||
|     { | ||||
|         if(is_u8_view()) | ||||
|             return u8view().characters_without_null_termination(); | ||||
| 
 | ||||
|         return to_string().characters(); // FIXME: it contains the null termination, does that actually matter?
 | ||||
|     } | ||||
| 
 | ||||
|     bool starts_with(const StringView& str) const | ||||
|     { | ||||
|         if(is_u32_view()) | ||||
|             return false; | ||||
|         return u8view().starts_with(str); | ||||
|     } | ||||
| 
 | ||||
|     bool starts_with(const Utf32View& str) const | ||||
|     { | ||||
|         if(is_u8_view()) | ||||
|             return false; | ||||
| 
 | ||||
|         StringBuilder builder; | ||||
|         builder.append(str); | ||||
|         return to_string().starts_with(builder.to_string()); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     Optional<StringView> m_u8view; | ||||
|     Optional<Utf32View> m_u32view; | ||||
| }; | ||||
| 
 | ||||
| class Match final { | ||||
| private: | ||||
|     Optional<FlyString> string; | ||||
|  | @ -44,7 +229,7 @@ public: | |||
|     Match() = default; | ||||
|     ~Match() = default; | ||||
| 
 | ||||
|     Match(const StringView view_, const size_t line_, const size_t column_, const size_t global_offset_) | ||||
|     Match(const RegexStringView view_, const size_t line_, const size_t column_, const size_t global_offset_) | ||||
|         : view(view_) | ||||
|         , line(line_) | ||||
|         , column(column_) | ||||
|  | @ -63,7 +248,7 @@ public: | |||
|     { | ||||
|     } | ||||
| 
 | ||||
|     StringView view { nullptr }; | ||||
|     RegexStringView view { nullptr }; | ||||
|     size_t line { 0 }; | ||||
|     size_t column { 0 }; | ||||
|     size_t global_offset { 0 }; | ||||
|  | @ -74,14 +259,14 @@ public: | |||
| }; | ||||
| 
 | ||||
| struct MatchInput { | ||||
|     StringView view { nullptr }; | ||||
|     RegexStringView view { nullptr }; | ||||
|     AllOptions regex_options {}; | ||||
| 
 | ||||
|     size_t match_index { 0 }; | ||||
|     size_t line { 0 }; | ||||
|     size_t column { 0 }; | ||||
| 
 | ||||
|     size_t global_offset { 0 }; // For multiline matching, knowning the offset from start could be important
 | ||||
|     size_t global_offset { 0 }; // For multiline matching, knowing the offset from start could be important
 | ||||
| }; | ||||
| 
 | ||||
| struct MatchState { | ||||
|  | @ -98,3 +283,5 @@ struct MatchOutput { | |||
| }; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| using regex::RegexStringView; | ||||
|  |  | |||
|  | @ -66,10 +66,22 @@ String Regex<Parser>::error_string(Optional<String> message) const | |||
| } | ||||
| 
 | ||||
| template<typename Parser> | ||||
| RegexResult Matcher<Parser>::match(const StringView& view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options) const | ||||
| RegexResult Matcher<Parser>::match(const RegexStringView& view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options) const | ||||
| { | ||||
|     AllOptions options = m_regex_options | regex_options.value_or({}).value(); | ||||
| 
 | ||||
|     if (options.has_flag_set(AllFlags::Multiline)) | ||||
|         return match(view.lines(), regex_options); // FIXME: how do we know, which line ending a line has (1char or 2char)? This is needed to get the correct match offsets from start of string...
 | ||||
| 
 | ||||
|     Vector<RegexStringView> views; | ||||
|     views.append(view); | ||||
|     return match(views, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<typename Parser> | ||||
| RegexResult Matcher<Parser>::match(const Vector<RegexStringView> views, Optional<typename ParserTraits<Parser>::OptionsType> regex_options) const | ||||
| { | ||||
|     size_t match_count { 0 }; | ||||
|     Vector<StringView> views { view }; | ||||
| 
 | ||||
|     MatchInput input; | ||||
|     MatchState state; | ||||
|  | @ -78,9 +90,6 @@ RegexResult Matcher<Parser>::match(const StringView& view, Optional<typename Par | |||
|     input.regex_options = m_regex_options | regex_options.value_or({}).value(); | ||||
|     output.operations = 0; | ||||
| 
 | ||||
|     if (input.regex_options & AllFlags::Multiline) | ||||
|         views = view.lines(false); // FIXME: how do we know, which line ending a line has (1char or 2char)? This is needed to get the correct match offsets from start of string...
 | ||||
| 
 | ||||
|     if (c_match_preallocation_count) { | ||||
|         output.matches.ensure_capacity(c_match_preallocation_count); | ||||
|         output.capture_group_matches.ensure_capacity(c_match_preallocation_count); | ||||
|  | @ -192,7 +201,16 @@ RegexResult Matcher<Parser>::match(const StringView& view, Optional<typename Par | |||
|     if (match_count) { | ||||
|         auto capture_groups_count = min(output.capture_group_matches.size(), output.matches.size()); | ||||
|         for (size_t i = 0; i < capture_groups_count; ++i) { | ||||
|             if(input.regex_options & AllFlags::SkipTrimEmptyMatches) { | ||||
|                 output_copy.capture_group_matches.append(output.capture_group_matches.at(i)); | ||||
|             } else { | ||||
|                 Vector<Match> capture_group_matches; | ||||
|                 for (size_t j = 0; j < output.capture_group_matches.at(i).size(); ++j) { | ||||
|                     if (!output.capture_group_matches.at(i).at(j).view.is_null()) | ||||
|                         capture_group_matches.append(output.capture_group_matches.at(i).at(j)); | ||||
|                 } | ||||
|                 output_copy.capture_group_matches.append(capture_group_matches); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         auto named_capture_groups_count = min(output.named_capture_group_matches.size(), output.matches.size()); | ||||
|  | @ -216,6 +234,8 @@ RegexResult Matcher<Parser>::match(const StringView& view, Optional<typename Par | |||
|         move(output_copy.capture_group_matches), | ||||
|         move(output_copy.named_capture_group_matches), | ||||
|         output.operations, | ||||
|         m_pattern.parser_result.capture_groups_count, | ||||
|         m_pattern.parser_result.named_capture_groups_count, | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
|  | @ -306,7 +326,7 @@ ALWAYS_INLINE Optional<bool> Matcher<Parser>::execute_low_prio_forks(const Match | |||
| 
 | ||||
|     original_state.string_position = 0; | ||||
|     return false; | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| template class Matcher<PosixExtendedParser>; | ||||
| template class Regex<PosixExtendedParser>; | ||||
|  |  | |||
|  | @ -35,6 +35,7 @@ | |||
| #include <AK/HashMap.h> | ||||
| #include <AK/NonnullOwnPtrVector.h> | ||||
| #include <AK/Types.h> | ||||
| #include <AK/Utf32View.h> | ||||
| #include <AK/Vector.h> | ||||
| 
 | ||||
| #include <stdio.h> | ||||
|  | @ -50,7 +51,9 @@ struct RegexResult final { | |||
|     Vector<Match> matches; | ||||
|     Vector<Vector<Match>> capture_group_matches; | ||||
|     Vector<HashMap<String, Match>> named_capture_group_matches; | ||||
|     size_t operations { 0 }; | ||||
|     size_t n_operations { 0 }; | ||||
|     size_t n_capture_groups { 0 }; | ||||
|     size_t n_named_capture_groups { 0 }; | ||||
| }; | ||||
| 
 | ||||
| template<class Parser> | ||||
|  | @ -67,7 +70,8 @@ public: | |||
|     } | ||||
|     ~Matcher() = default; | ||||
| 
 | ||||
|     RegexResult match(const StringView&, Optional<typename ParserTraits<Parser>::OptionsType> = {}) const; | ||||
|     RegexResult match(const RegexStringView&, Optional<typename ParserTraits<Parser>::OptionsType> = {}) const; | ||||
|     RegexResult match(const Vector<RegexStringView>, Optional<typename ParserTraits<Parser>::OptionsType> = {}) const; | ||||
| 
 | ||||
| private: | ||||
|     Optional<bool> execute(const MatchInput& input, MatchState& state, MatchOutput& output, size_t recursion_level) const; | ||||
|  | @ -84,20 +88,27 @@ public: | |||
|     regex::Parser::Result parser_result; | ||||
|     OwnPtr<Matcher<Parser>> matcher { nullptr }; | ||||
| 
 | ||||
|     Regex(StringView pattern, typename ParserTraits<Parser>::OptionsType regex_options = {}); | ||||
|     explicit Regex(StringView pattern, typename ParserTraits<Parser>::OptionsType regex_options = {}); | ||||
|     ~Regex() = default; | ||||
| 
 | ||||
|     void print_bytecode(FILE* f = stdout) const; | ||||
|     String error_string(Optional<String> message = {}) const; | ||||
| 
 | ||||
|     RegexResult match(StringView view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     RegexResult match(const RegexStringView view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         if (!matcher || parser_result.error != Error::NoError) | ||||
|             return {}; | ||||
|         return matcher->match(view, regex_options); | ||||
|     } | ||||
| 
 | ||||
|     RegexResult search(StringView view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     RegexResult match(const Vector<RegexStringView> views, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         if (!matcher || parser_result.error != Error::NoError) | ||||
|             return {}; | ||||
|         return matcher->match(views, regex_options); | ||||
|     } | ||||
| 
 | ||||
|     RegexResult search(const RegexStringView view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         if (!matcher || parser_result.error != Error::NoError) | ||||
|             return {}; | ||||
|  | @ -112,72 +123,123 @@ public: | |||
|         return matcher->match(view, options); | ||||
|     } | ||||
| 
 | ||||
|     bool match(StringView view, RegexResult& m, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     RegexResult search(const Vector<RegexStringView> views, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         if (!matcher || parser_result.error != Error::NoError) | ||||
|             return {}; | ||||
|         m = matcher->match(view, regex_options); | ||||
| 
 | ||||
|         AllOptions options = (AllOptions)regex_options.value_or({}); | ||||
|         if ((options & AllFlags::MatchNotBeginOfLine) && (options & AllFlags::MatchNotEndOfLine)) { | ||||
|             options.reset_flag(AllFlags::MatchNotEndOfLine); | ||||
|             options.reset_flag(AllFlags::MatchNotBeginOfLine); | ||||
|         } | ||||
|         options |= AllFlags::Global; | ||||
| 
 | ||||
|         return matcher->match(views, options); | ||||
|     } | ||||
| 
 | ||||
|     bool match(const RegexStringView view, RegexResult& m, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         m = match(view, regex_options); | ||||
|         return m.success; | ||||
|     } | ||||
| 
 | ||||
|     bool search(StringView view, RegexResult& m, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     bool match(const Vector<RegexStringView> views, RegexResult& m, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         m = match(views, regex_options); | ||||
|         return m.success; | ||||
|     } | ||||
| 
 | ||||
|     bool search(const RegexStringView view, RegexResult& m, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         m = search(view, regex_options); | ||||
|         return m.success; | ||||
|     } | ||||
| 
 | ||||
|     bool has_match(const StringView view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     bool search(const Vector<RegexStringView> views, RegexResult& m, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         m = search(views, regex_options); | ||||
|         return m.success; | ||||
|     } | ||||
| 
 | ||||
|     bool has_match(const RegexStringView view, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         if (!matcher || parser_result.error != Error::NoError) | ||||
|             return false; | ||||
|         RegexResult result = matcher->match(view, AllOptions { regex_options.value_or({}) } | AllFlags::SkipSubExprResults); | ||||
|         return result.success; | ||||
|     } | ||||
| 
 | ||||
|     bool has_match(const Vector<RegexStringView> views, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) const | ||||
|     { | ||||
|         if (!matcher || parser_result.error != Error::NoError) | ||||
|             return false; | ||||
|         RegexResult result = matcher->match(views, AllOptions { regex_options.value_or({}) } | AllFlags::SkipSubExprResults); | ||||
|         return result.success; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| // free standing functions for match, search and has_match
 | ||||
| template<class Parser> | ||||
| RegexResult match(const StringView view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| RegexResult match(const RegexStringView view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     if (!pattern.matcher || pattern.parser_result.error != Error::NoError) | ||||
|         return {}; | ||||
|     return pattern.matcher->match(view, regex_options); | ||||
|     return pattern.match(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool match(const StringView view, Regex<Parser>& pattern, RegexResult& res, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| RegexResult match(const Vector<RegexStringView> view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     if (!pattern.matcher || pattern.parser_result.error != Error::NoError) | ||||
|         return {}; | ||||
|     res = pattern.matcher->match(view, regex_options); | ||||
|     return res.success; | ||||
|     return pattern.match(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| RegexResult search(const StringView view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| bool match(const RegexStringView view, Regex<Parser>& pattern, RegexResult& res, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     if (!pattern.matcher || pattern.parser_result.error != Error::NoError) | ||||
|         return {}; | ||||
|     return pattern.matcher->search(view, regex_options); | ||||
|     return pattern.match(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool search(const StringView view, Regex<Parser>& pattern, RegexResult& res, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| bool match(const Vector<RegexStringView> view, Regex<Parser>& pattern, RegexResult& res, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     if (!pattern.matcher || pattern.parser_result.error != Error::NoError) | ||||
|         return {}; | ||||
|     res = pattern.matcher->search(view, regex_options); | ||||
|     return res.success; | ||||
|     return pattern.match(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool has_match(const StringView view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| RegexResult search(const RegexStringView view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     if (pattern.matcher == nullptr) | ||||
|         return {}; | ||||
|     RegexResult result = pattern.matcher->match(view, AllOptions { regex_options.value_or({}) } | AllFlags::SkipSubExprResults); | ||||
|     return result.success; | ||||
|     return pattern.search(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| RegexResult search(const Vector<RegexStringView> views, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     return pattern.search(views, regex_options); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool search(const RegexStringView view, Regex<Parser>& pattern, RegexResult& res, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     return pattern.search(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool search(const Vector<RegexStringView> views, Regex<Parser>& pattern, RegexResult& res, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     return pattern.search(views, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool has_match(const RegexStringView view, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     return pattern.has_match(view, regex_options); | ||||
| } | ||||
| 
 | ||||
| template<class Parser> | ||||
| bool has_match(const Vector<RegexStringView> views, Regex<Parser>& pattern, Optional<typename ParserTraits<Parser>::OptionsType> regex_options = {}) | ||||
| { | ||||
|     return pattern.has_match(views, regex_options); | ||||
| } | ||||
| } | ||||
| 
 | ||||
| using regex::has_match; | ||||
|  |  | |||
|  | @ -66,6 +66,7 @@ enum class PosixFlags : FlagsUnderlyingType { | |||
|     MatchNotBeginOfLine = (FlagsUnderlyingType)AllFlags::MatchNotBeginOfLine, | ||||
|     MatchNotEndOfLine = (FlagsUnderlyingType)AllFlags::MatchNotEndOfLine, | ||||
|     SkipSubExprResults = (FlagsUnderlyingType)AllFlags::SkipSubExprResults, | ||||
|     SkipTrimEmptyMatches = (FlagsUnderlyingType)AllFlags::SkipTrimEmptyMatches, | ||||
|     Multiline = (FlagsUnderlyingType)AllFlags::Multiline, | ||||
|     StringCopyMatches = (FlagsUnderlyingType)AllFlags::StringCopyMatches, | ||||
| }; | ||||
|  |  | |||
|  | @ -42,6 +42,12 @@ | |||
| #        include <regex> | ||||
| #    endif | ||||
| 
 | ||||
| #    if not(defined(REGEX_BENCHMARK_OUR) && defined(REGEX_BENCHMARK_OUR)) | ||||
| BENCHMARK_CASE(dummy_benchmark) | ||||
| { | ||||
| } | ||||
| #    endif | ||||
| 
 | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(catch_all_benchmark) | ||||
| { | ||||
|  | @ -51,10 +57,10 @@ BENCHMARK_CASE(catch_all_benchmark) | |||
|         EXPECT(re.match("Hello World", m)); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(catch_all_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(catch_all_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("^.*$"); | ||||
|     std::cmatch m; | ||||
|  | @ -62,9 +68,9 @@ BENCHMARK_CASE(catch_all_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("Hello World", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_start_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("^hello friends"); | ||||
|  | @ -75,10 +81,10 @@ BENCHMARK_CASE(simple_start_benchmark) | |||
|         EXPECT_EQ(re.match("Well, hello friends", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_start_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_start_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("^hello friends"); | ||||
|     std::cmatch m; | ||||
|  | @ -88,9 +94,9 @@ BENCHMARK_CASE(simple_start_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("Well, hello friends", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_end_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re(".*hello\\.\\.\\. there$"); | ||||
|  | @ -102,10 +108,10 @@ BENCHMARK_CASE(simple_end_benchmark) | |||
|         EXPECT_EQ(re.match("hello.. there", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_end_benchmark_reference_stdcpp_regex_search) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_end_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re(".*hello\\.\\.\\. there$"); | ||||
|     std::cmatch m; | ||||
|  | @ -116,9 +122,9 @@ BENCHMARK_CASE(simple_end_benchmark_reference_stdcpp_regex_search) | |||
|         EXPECT_EQ(std::regex_search("hello.. there", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_period_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("hello."); | ||||
|  | @ -130,10 +136,10 @@ BENCHMARK_CASE(simple_period_benchmark) | |||
|         EXPECT_EQ(re.match("hello?", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_period_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_period_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("hello."); | ||||
|     std::cmatch m; | ||||
|  | @ -144,9 +150,9 @@ BENCHMARK_CASE(simple_period_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("hello?", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_period_end_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("hello.$"); | ||||
|  | @ -158,10 +164,10 @@ BENCHMARK_CASE(simple_period_end_benchmark) | |||
|         EXPECT_EQ(re.search("hello?", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_period_end_benchmark_reference_stdcpp_regex_search) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_period_end_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("hello.$"); | ||||
|     std::cmatch m; | ||||
|  | @ -172,9 +178,9 @@ BENCHMARK_CASE(simple_period_end_benchmark_reference_stdcpp_regex_search) | |||
|         EXPECT_EQ(std::regex_search("hello?", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_escaped_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("hello\\."); | ||||
|  | @ -184,10 +190,10 @@ BENCHMARK_CASE(simple_escaped_benchmark) | |||
|         EXPECT_EQ(re.match("hello.", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_escaped_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_escaped_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("hello\\."); | ||||
|     std::cmatch m; | ||||
|  | @ -196,9 +202,9 @@ BENCHMARK_CASE(simple_escaped_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("hello.", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_period2_end_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re(".*hi... there$"); | ||||
|  | @ -211,10 +217,10 @@ BENCHMARK_CASE(simple_period2_end_benchmark) | |||
|         EXPECT_EQ(re.search("I said fyhihi there", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_period2_end_benchmark_reference_stdcpp_regex_search) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_period2_end_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re(".*hi... there$"); | ||||
|     std::cmatch m; | ||||
|  | @ -226,9 +232,9 @@ BENCHMARK_CASE(simple_period2_end_benchmark_reference_stdcpp_regex_search) | |||
|         EXPECT_EQ(std::regex_search("I said fyhihi there", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_plus_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("a+"); | ||||
|  | @ -240,10 +246,10 @@ BENCHMARK_CASE(simple_plus_benchmark) | |||
|         EXPECT_EQ(re.search("aaaaaaaaaaa", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_plus_benchmark_reference_stdcpp_regex_search) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_plus_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("a+"); | ||||
|     std::cmatch m; | ||||
|  | @ -254,9 +260,9 @@ BENCHMARK_CASE(simple_plus_benchmark_reference_stdcpp_regex_search) | |||
|         EXPECT_EQ(std::regex_search("aaaaaaaaaaa", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_questionmark_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("da?d"); | ||||
|  | @ -271,10 +277,10 @@ BENCHMARK_CASE(simple_questionmark_benchmark) | |||
|         EXPECT_EQ(re.search("adadaa", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_questionmark_benchmark_reference_stdcpp_regex_search) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_questionmark_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("da?d"); | ||||
|     std::cmatch m; | ||||
|  | @ -288,9 +294,9 @@ BENCHMARK_CASE(simple_questionmark_benchmark_reference_stdcpp_regex_search) | |||
|         EXPECT_EQ(std::regex_search("adadaa", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(character_class_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("[[:alpha:]]"); | ||||
|  | @ -302,10 +308,10 @@ BENCHMARK_CASE(character_class_benchmark) | |||
|         EXPECT_EQ(re.search(haystack.characters(), m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(character_class_benchmark_reference_stdcpp_regex_search) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(character_class_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("[[:alpha:]]"); | ||||
|     std::cmatch m; | ||||
|  | @ -316,9 +322,9 @@ BENCHMARK_CASE(character_class_benchmark_reference_stdcpp_regex_search) | |||
|         EXPECT_EQ(std::regex_search(haystack.characters(), m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(escaped_char_questionmark_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("This\\.?And\\.?That"); | ||||
|  | @ -330,10 +336,10 @@ BENCHMARK_CASE(escaped_char_questionmark_benchmark) | |||
|         EXPECT_EQ(re.match("This..And..That", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(escaped_char_questionmark_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(escaped_char_questionmark_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("This\\.?And\\.?That"); | ||||
|     std::cmatch m; | ||||
|  | @ -344,9 +350,9 @@ BENCHMARK_CASE(escaped_char_questionmark_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("This..And..That", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(char_qualifier_asterisk_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("regex*"); | ||||
|  | @ -356,10 +362,10 @@ BENCHMARK_CASE(char_qualifier_asterisk_benchmark) | |||
|         EXPECT_EQ(re.search("#include <stdio.h>", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(char_qualifier_asterisk_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(char_qualifier_asterisk_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("regex*"); | ||||
|     std::cmatch m; | ||||
|  | @ -368,9 +374,9 @@ BENCHMARK_CASE(char_qualifier_asterisk_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_search("#include <stdio.h>", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(parens_qualifier_questionmark_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("test(hello)?test"); | ||||
|  | @ -381,10 +387,10 @@ BENCHMARK_CASE(parens_qualifier_questionmark_benchmark) | |||
|         EXPECT_EQ(re.match("testasfdtest", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_questionmark_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_questionmark_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("test(hello)?test"); | ||||
|     std::cmatch m; | ||||
|  | @ -394,9 +400,9 @@ BENCHMARK_CASE(parens_qualifier_questionmark_benchmark_reference_stdcpp_regex_ma | |||
|         EXPECT_EQ(std::regex_match("testasfdtest", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(parens_qualifier_asterisk_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("test(hello)*test"); | ||||
|  | @ -408,10 +414,10 @@ BENCHMARK_CASE(parens_qualifier_asterisk_benchmark) | |||
|         EXPECT_EQ(re.match("aaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbb", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_asterisk_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_asterisk_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("test(hello)*test"); | ||||
|     std::cmatch m; | ||||
|  | @ -422,9 +428,9 @@ BENCHMARK_CASE(parens_qualifier_asterisk_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("aaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbb", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(parens_qualifier_asterisk_2_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("test(.*)test"); | ||||
|  | @ -436,10 +442,10 @@ BENCHMARK_CASE(parens_qualifier_asterisk_2_benchmark) | |||
|         EXPECT_EQ(re.match("aaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbb", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_asterisk_2_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_asterisk_2_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("test(.*)test"); | ||||
|     std::cmatch m; | ||||
|  | @ -450,9 +456,9 @@ BENCHMARK_CASE(parens_qualifier_asterisk_2_benchmark_reference_stdcpp_regex_matc | |||
|         EXPECT_EQ(std::regex_match("aaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbb", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(multi_parens_qualifier_questionmark_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("test(a)?(b)?(c)?test"); | ||||
|  | @ -466,10 +472,10 @@ BENCHMARK_CASE(multi_parens_qualifier_questionmark_benchmark) | |||
|         EXPECT_EQ(re.match("whaaaaat", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(multi_parens_qualifier_questionmark_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(multi_parens_qualifier_questionmark_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("test(a)?(b)?(c)?test"); | ||||
|     std::cmatch m; | ||||
|  | @ -482,9 +488,9 @@ BENCHMARK_CASE(multi_parens_qualifier_questionmark_benchmark_reference_stdcpp_re | |||
|         EXPECT_EQ(std::regex_match("whaaaaat", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_alternative_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("test|hello|friends"); | ||||
|  | @ -496,10 +502,10 @@ BENCHMARK_CASE(simple_alternative_benchmark) | |||
|         EXPECT_EQ(re.match("whaaaaat", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_alternative_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_alternative_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("test|hello|friends"); | ||||
|     std::cmatch m; | ||||
|  | @ -510,9 +516,9 @@ BENCHMARK_CASE(simple_alternative_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("whaaaaat", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(alternative_match_groups_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("test(a)?(b)?|hello ?(dear|my)? friends"); | ||||
|  | @ -528,10 +534,10 @@ BENCHMARK_CASE(alternative_match_groups_benchmark) | |||
|         EXPECT_EQ(re.match("hello test friends", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(alternative_match_groups_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(alternative_match_groups_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("test(a)?(b)?|hello ?(dear|my)? friends"); | ||||
|     std::cmatch m; | ||||
|  | @ -546,9 +552,9 @@ BENCHMARK_CASE(alternative_match_groups_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("hello test friends", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(parens_qualifier_exact_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("(hello){3}"); | ||||
|  | @ -560,10 +566,10 @@ BENCHMARK_CASE(parens_qualifier_exact_benchmark) | |||
|         EXPECT_EQ(re.search("test hellohellohello", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_exact_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_exact_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("(hello){3}"); | ||||
|     std::cmatch m; | ||||
|  | @ -574,9 +580,9 @@ BENCHMARK_CASE(parens_qualifier_exact_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_search("test hellohellohello", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(parens_qualifier_minimum_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("(hello){3,}"); | ||||
|  | @ -589,10 +595,10 @@ BENCHMARK_CASE(parens_qualifier_minimum_benchmark) | |||
|         EXPECT_EQ(re.search("test hellohellohellohello", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_minimum_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_minimum_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("(hello){3,}"); | ||||
|     std::cmatch m; | ||||
|  | @ -604,9 +610,9 @@ BENCHMARK_CASE(parens_qualifier_minimum_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_search("test hellohellohellohello", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(parens_qualifier_maximum_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("(hello){2,3}"); | ||||
|  | @ -621,10 +627,10 @@ BENCHMARK_CASE(parens_qualifier_maximum_benchmark) | |||
|         EXPECT_EQ(re.search("test hellohellohellohello", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_maximum_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(parens_qualifier_maximum_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("(hello){2,3}"); | ||||
|     std::cmatch m; | ||||
|  | @ -638,9 +644,9 @@ BENCHMARK_CASE(parens_qualifier_maximum_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_search("test hellohellohellohello", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(char_qualifier_min_max_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("c{3,30}"); | ||||
|  | @ -654,10 +660,10 @@ BENCHMARK_CASE(char_qualifier_min_max_benchmark) | |||
|         EXPECT_EQ(re.match("cccccccccccccccccccccccccccccccc", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(char_qualifier_min_max_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(char_qualifier_min_max_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("c{3,30}"); | ||||
|     std::cmatch m; | ||||
|  | @ -670,9 +676,9 @@ BENCHMARK_CASE(char_qualifier_min_max_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("cccccccccccccccccccccccccccccccc", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_bracket_chars_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("[abc]"); | ||||
|  | @ -685,10 +691,10 @@ BENCHMARK_CASE(simple_bracket_chars_benchmark) | |||
|         EXPECT_EQ(re.match("e", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("[abc]"); | ||||
|     std::cmatch m; | ||||
|  | @ -700,9 +706,9 @@ BENCHMARK_CASE(simple_bracket_chars_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("e", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_bracket_chars_inverse_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("[^abc]"); | ||||
|  | @ -715,10 +721,10 @@ BENCHMARK_CASE(simple_bracket_chars_inverse_benchmark) | |||
|         EXPECT_EQ(re.match("e", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_inverse_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_inverse_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("[^abc]"); | ||||
|     std::cmatch m; | ||||
|  | @ -730,9 +736,9 @@ BENCHMARK_CASE(simple_bracket_chars_inverse_benchmark_reference_stdcpp_regex_mat | |||
|         EXPECT_EQ(std::regex_match("e", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_bracket_chars_range_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("[a-d]"); | ||||
|  | @ -745,10 +751,10 @@ BENCHMARK_CASE(simple_bracket_chars_range_benchmark) | |||
|         EXPECT_EQ(re.match("e", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_range_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_range_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("[a-d]"); | ||||
|     std::cmatch m; | ||||
|  | @ -760,9 +766,9 @@ BENCHMARK_CASE(simple_bracket_chars_range_benchmark_reference_stdcpp_regex_match | |||
|         EXPECT_EQ(std::regex_match("e", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_bracket_chars_range_inverse_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("[^a-df-z]"); | ||||
|  | @ -777,10 +783,10 @@ BENCHMARK_CASE(simple_bracket_chars_range_inverse_benchmark) | |||
|         EXPECT_EQ(re.match("z", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_range_inverse_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_chars_range_inverse_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("[^a-df-z]"); | ||||
|     std::cmatch m; | ||||
|  | @ -794,9 +800,9 @@ BENCHMARK_CASE(simple_bracket_chars_range_inverse_benchmark_reference_stdcpp_reg | |||
|         EXPECT_EQ(std::regex_match("z", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(bracket_character_class_uuid_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("^([[:xdigit:]]{8})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{12})$"); | ||||
|  | @ -806,10 +812,10 @@ BENCHMARK_CASE(bracket_character_class_uuid_benchmark) | |||
|         EXPECT_EQ(re.match("fb9b62a2", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(bracket_character_class_uuid_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(bracket_character_class_uuid_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("^([[:xdigit:]]{8})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{4})-([[:xdigit:]]{12})$"); | ||||
|     std::cmatch m; | ||||
|  | @ -818,9 +824,9 @@ BENCHMARK_CASE(bracket_character_class_uuid_benchmark_reference_stdcpp_regex_mat | |||
|         EXPECT_EQ(std::regex_match("fb9b62a2", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_bracket_character_class_inverse_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("[^[:digit:]]"); | ||||
|  | @ -833,10 +839,10 @@ BENCHMARK_CASE(simple_bracket_character_class_inverse_benchmark) | |||
|         EXPECT_EQ(re.match("e", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_character_class_inverse_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_bracket_character_class_inverse_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("[^[:digit:]]"); | ||||
|     std::cmatch m; | ||||
|  | @ -848,9 +854,9 @@ BENCHMARK_CASE(simple_bracket_character_class_inverse_benchmark_reference_stdcpp | |||
|         EXPECT_EQ(std::regex_match("e", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(email_address_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("^[A-Z0-9a-z._%+-]{1,64}@(?:[A-Za-z0-9-]{1,63}\\.){1,125}[A-Za-z]{2,63}$"); | ||||
|  | @ -860,10 +866,10 @@ BENCHMARK_CASE(email_address_benchmark) | |||
|         EXPECT_EQ(re.match("this.is.a.very_long_email_address@world.wide.web", m), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(email_address_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(email_address_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("^[A-Z0-9a-z._%+-]{1,64}@(?:[A-Za-z0-9-]{1,63}\\.){1,125}[A-Za-z]{2,63}$"); | ||||
|     std::cmatch m; | ||||
|  | @ -872,9 +878,9 @@ BENCHMARK_CASE(email_address_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_match("this.is.a.very_long_email_address@world.wide.web", m, re), true); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OUR) | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_ignorecase_benchmark) | ||||
| { | ||||
|     Regex<PosixExtended> re("^hello friends", PosixFlags::Insensitive); | ||||
|  | @ -890,10 +896,10 @@ BENCHMARK_CASE(simple_ignorecase_benchmark) | |||
|         EXPECT_EQ(re.search("hell Friends", m), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_ignorecase_benchmark_reference_stdcpp_regex_match) | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_ignorecase_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re("^hello friends", std::regex_constants::icase); | ||||
|     std::cmatch m; | ||||
|  | @ -908,7 +914,78 @@ BENCHMARK_CASE(simple_ignorecase_benchmark_reference_stdcpp_regex_match) | |||
|         EXPECT_EQ(std::regex_search("hell Friends", m, re), false); | ||||
|     } | ||||
| } | ||||
| #endif | ||||
| #    endif | ||||
| 
 | ||||
| #    if defined(REGEX_BENCHMARK_OUR) | ||||
| BENCHMARK_CASE(simple_notbol_noteol_benchmark) | ||||
| { | ||||
|     String pattern = "^hello friends$"; | ||||
|     String pattern2 = "hello friends"; | ||||
|     regex_t regex, regex2; | ||||
| 
 | ||||
|     EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR); | ||||
|     EXPECT_EQ(regcomp(®ex2, pattern2.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR); | ||||
| 
 | ||||
|     for (size_t i = 0; i < BENCHMARK_LOOP_ITERATIONS; ++i) { | ||||
| 
 | ||||
|         EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH); | ||||
| 
 | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR); | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR); | ||||
| 
 | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOERR); | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOMATCH); | ||||
| 
 | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL | REG_SEARCH), REG_NOMATCH); | ||||
| 
 | ||||
|         EXPECT_EQ(regexec(®ex2, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|         EXPECT_EQ(regexec(®ex2, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
|     } | ||||
| 
 | ||||
|     regfree(®ex); | ||||
| } | ||||
| #    endif | ||||
| 
 | ||||
| #    if defined(REGEX_BENCHMARK_OTHER) | ||||
| BENCHMARK_CASE(simple_notbol_noteol_benchmark_reference_stdcpp) | ||||
| { | ||||
|     std::regex re1("^hello friends$", std::regex_constants::match_not_bol); | ||||
|     std::regex re2("^hello friends$", std::regex_constants::match_not_eol); | ||||
|     std::regex re3("^hello friends$", std::regex_constants::match_not_bol | std::regex_constants::match_not_eol); | ||||
|     std::regex re4("hello friends", std::regex_constants::match_not_bol); | ||||
|     std::regex re5("hello friends", std::regex_constants::match_not_eol); | ||||
|     std::cmatch m; | ||||
|     for (size_t i = 0; i < BENCHMARK_LOOP_ITERATIONS; ++i) { | ||||
|         EXPECT_EQ(std::regex_match("hello friends", m, re1), false); | ||||
|         EXPECT_EQ(std::regex_match("hello friends", m, re2), false); | ||||
|         EXPECT_EQ(std::regex_match("hello friends", m, re3), false); | ||||
| 
 | ||||
|         EXPECT_EQ(std::regex_match("a hello friends b", m, re1), false); | ||||
|         EXPECT_EQ(std::regex_match("a hello friends", m, re1), false); | ||||
|         EXPECT_EQ(std::regex_search("a hello friends", m, re1), true); | ||||
|         EXPECT_EQ(std::regex_search("a hello friends b", m, re1), true); | ||||
| 
 | ||||
|         EXPECT_EQ(std::regex_match("a hello friends b", m, re2), false); | ||||
|         EXPECT_EQ(std::regex_match("hello friends b", m, re2), false); | ||||
|         EXPECT_EQ(std::regex_search("hello friends b", m, re2), true); | ||||
|         EXPECT_EQ(std::regex_search("a hello friends b", m, re2), false); | ||||
| 
 | ||||
|         EXPECT_EQ(std::regex_match("a hello friends b", m, re3), false); | ||||
|         EXPECT_EQ(std::regex_search("a hello friends b", m, re3), false); | ||||
| 
 | ||||
|         EXPECT_EQ(std::regex_match("hello friends", m, re4), false); | ||||
|         EXPECT_EQ(std::regex_match("hello friends", m, re5), false); | ||||
|     } | ||||
| } | ||||
| #    endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| TEST_MAIN(Regex) | ||||
|  |  | |||
|  | @ -383,7 +383,7 @@ TEST_CASE(ini_file_entries) | |||
| #endif | ||||
| 
 | ||||
|     EXPECT_EQ(result.matches.at(0).view, "[Window]"); | ||||
|     EXPECT_EQ(result.capture_group_matches.at(0).at(1).view, "Window"); | ||||
|     EXPECT_EQ(result.capture_group_matches.at(0).at(0).view, "Window"); | ||||
|     EXPECT_EQ(result.matches.at(1).view, "Opacity=255"); | ||||
|     EXPECT_EQ(result.matches.at(1).line, 1u); | ||||
|     EXPECT_EQ(result.matches.at(1).column, 0u); | ||||
|  | @ -396,6 +396,20 @@ TEST_CASE(ini_file_entries) | |||
|     EXPECT_EQ(result.capture_group_matches.at(2).at(0).column, 12u); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE(ini_file_entries2) | ||||
| { | ||||
|     Regex<PosixExtended> re("[[:alpha:]]*=([[:digit:]]*)"); | ||||
|     RegexResult result; | ||||
| 
 | ||||
|     String haystack = "ViewMode=Icon"; | ||||
| 
 | ||||
|     EXPECT_EQ(re.match(haystack.view(), result), false); | ||||
|     EXPECT_EQ(result.count, 0u); | ||||
| 
 | ||||
|     EXPECT_EQ(re.search(haystack.view(), result), true); | ||||
|     EXPECT_EQ(result.count, 1u); | ||||
| } | ||||
| 
 | ||||
| TEST_CASE(named_capture_group) | ||||
| { | ||||
|     Regex<PosixExtended> re("[[:alpha:]]*=(?<Test>[[:digit:]]*)"); | ||||
|  |  | |||
|  | @ -30,13 +30,6 @@ | |||
| #include <LibC/regex.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #define BENCHMARK_LOOP_ITERATIONS 100000 | ||||
| #define DISABLE_REGEX_BENCHMARK | ||||
| 
 | ||||
| //#if not(defined(REGEX_DEBUG) || defined(REGEX_MATCH_STATUS) || defined(DISABLE_REGEX_BENCHMARK))
 | ||||
| #    include <regex> | ||||
| //#endif
 | ||||
| 
 | ||||
| TEST_CASE(catch_all) | ||||
| { | ||||
|     String pattern = "^.*$"; | ||||
|  | @ -1115,9 +1108,11 @@ TEST_CASE(simple_ignorecase) | |||
| TEST_CASE(simple_notbol_noteol) | ||||
| { | ||||
|     String pattern = "^hello friends$"; | ||||
|     regex_t regex; | ||||
|     String pattern2 = "hello friends"; | ||||
|     regex_t regex, regex2; | ||||
| 
 | ||||
|     EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR); | ||||
|     EXPECT_EQ(regcomp(®ex2, pattern2.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR); | ||||
| 
 | ||||
|     EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|     EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
|  | @ -1136,76 +1131,10 @@ TEST_CASE(simple_notbol_noteol) | |||
|     EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH); | ||||
|     EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL | REG_SEARCH), REG_NOMATCH); | ||||
| 
 | ||||
|     pattern = "hello friends"; | ||||
|     EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR); | ||||
| 
 | ||||
|     EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|     EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
|     EXPECT_EQ(regexec(®ex2, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH); | ||||
|     EXPECT_EQ(regexec(®ex2, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH); | ||||
| 
 | ||||
|     regfree(®ex); | ||||
| } | ||||
| 
 | ||||
| //#if not(defined(REGEX_DEBUG) || defined(REGEX_MATCH_STATUS) || defined(DISABLE_REGEX_BENCHMARK))
 | ||||
| //BENCHMARK_CASE(simple_notbol_noteol_benchmark)
 | ||||
| //{
 | ||||
| //    String pattern = "^hello friends$";
 | ||||
| //    regex_t regex;
 | ||||
| 
 | ||||
| //    EXPECT_EQ(regcomp(®ex, pattern.characters(), REG_EXTENDED | REG_NOSUB | REG_ICASE), REG_NOERR);
 | ||||
| 
 | ||||
| //    for (size_t i = 0; i < BENCHMARK_LOOP_ITERATIONS; ++i) {
 | ||||
| 
 | ||||
| //        EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTEOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "hello friends", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
 | ||||
| 
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends", 0, NULL, REG_NOTBOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOERR);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_SEARCH), REG_NOMATCH);
 | ||||
| 
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "hello friends b", 0, NULL, REG_NOTEOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOERR);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTEOL | REG_SEARCH), REG_NOMATCH);
 | ||||
| 
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL), REG_NOMATCH);
 | ||||
| //        EXPECT_EQ(regexec(®ex, "a hello friends b", 0, NULL, REG_NOTBOL | REG_NOTEOL | REG_SEARCH), REG_NOERR);
 | ||||
| //    }
 | ||||
| 
 | ||||
| //    regfree(®ex);
 | ||||
| //}
 | ||||
| 
 | ||||
| BENCHMARK_CASE(simple_notbol_noteol_benchmark_reference_stdcpp_regex_match) | ||||
| { | ||||
|     std::regex re1("^hello friends$", std::regex_constants::match_not_bol); | ||||
|     std::regex re2("^hello friends$", std::regex_constants::match_not_eol); | ||||
|     std::regex re3("^hello friends$", std::regex_constants::match_not_bol | std::regex_constants::match_not_eol); | ||||
|     std::regex re4("hello friends", std::regex_constants::match_not_bol); | ||||
|     std::regex re5("hello friends", std::regex_constants::match_not_eol); | ||||
|     std::cmatch m; | ||||
|     //for (size_t i = 0; i < BENCHMARK_LOOP_ITERATIONS; ++i) {
 | ||||
|     EXPECT_EQ(std::regex_match("hello friends", m, re1), false); | ||||
|     EXPECT_EQ(std::regex_match("hello friends", m, re2), false); | ||||
|     EXPECT_EQ(std::regex_match("hello friends", m, re3), false); | ||||
| 
 | ||||
|     EXPECT_EQ(std::regex_match("a hello friends b", m, re1), false); | ||||
|     EXPECT_EQ(std::regex_match("a hello friends", m, re1), false); | ||||
|     EXPECT_EQ(std::regex_search("a hello friends", m, re1), true); | ||||
|     EXPECT_EQ(std::regex_search("a hello friends b", m, re1), true); | ||||
| 
 | ||||
|     EXPECT_EQ(std::regex_match("a hello friends b", m, re2), false); | ||||
|     EXPECT_EQ(std::regex_match("hello friends b", m, re2), false); | ||||
|     EXPECT_EQ(std::regex_search("hello friends b", m, re2), true); | ||||
|     EXPECT_EQ(std::regex_search("a hello friends b", m, re2), false); | ||||
| 
 | ||||
|     EXPECT_EQ(std::regex_match("a hello friends b", m, re3), false); | ||||
|     EXPECT_EQ(std::regex_search("a hello friends b", m, re3), false); | ||||
| 
 | ||||
|     EXPECT_EQ(std::regex_match("hello friends", m, re4), false); | ||||
|     EXPECT_EQ(std::regex_match("hello friends", m, re5), false); | ||||
|     //}
 | ||||
| } | ||||
| //#endif
 | ||||
| 
 | ||||
| TEST_MAIN(Regex) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Emanuel Sprung
						Emanuel Sprung