diff --git a/Libraries/LibRegex/C/Regex.cpp b/Libraries/LibRegex/C/Regex.cpp index 7bb36204fb..d914d2760c 100644 --- a/Libraries/LibRegex/C/Regex.cpp +++ b/Libraries/LibRegex/C/Regex.cpp @@ -79,7 +79,7 @@ int regcomp(regex_t* reg, const char* pattern, int cflags) preg->cflags = cflags; String pattern_str(pattern); - preg->re = make>(pattern_str, PosixOptions {} | (PosixFlags)cflags); + preg->re = make>(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(); diff --git a/Libraries/LibRegex/Forward.h b/Libraries/LibRegex/Forward.h index b35a0f3476..10203513a4 100644 --- a/Libraries/LibRegex/Forward.h +++ b/Libraries/LibRegex/Forward.h @@ -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; diff --git a/Libraries/LibRegex/RegexByteCode.cpp b/Libraries/LibRegex/RegexByteCode.cpp index 27bd16002e..0b0191905e 100644 --- a/Libraries/LibRegex/RegexByteCode.cpp +++ b/Libraries/LibRegex/RegexByteCode.cpp @@ -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,26 +392,30 @@ 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) { - auto str_view1 = StringView(str, length); - auto str_view2 = StringView(&input.view[state.string_position], length); - String str1, str2; - if (input.regex_options & AllFlags::Insensitive) { - str1 = str_view1.to_string().to_lowercase(); - str2 = str_view2.to_string().to_lowercase(); - str_view1 = str1.view(); - str_view2 = str2.view(); + if (input.view.is_u8_view()) { + auto str_view1 = StringView(str, 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(); + str2 = str_view2.to_string().to_lowercase(); + str_view1 = str1.view(); + str_view2 = str2.view(); + } + + if (str_view1 == str_view2) { + state.string_position += length; + return true; + } } - if (str_view1 == str_view2) { - state.string_position += length; - return true; - } else - return false; + 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 OpCode_Compare::variable_arguments_to_string(Optional 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 OpCode_Compare::variable_arguments_to_string(Optionalat(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(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; diff --git a/Libraries/LibRegex/RegexByteCode.h b/Libraries/LibRegex/RegexByteCode.h index d3ffdcef67..fce3b52b20 100644 --- a/Libraries/LibRegex/RegexByteCode.h +++ b/Libraries/LibRegex/RegexByteCode.h @@ -407,7 +407,6 @@ protected: Optional m_state; }; - class OpCode_Exit final : public OpCode { public: OpCode_Exit(ByteCode& bytecode) @@ -567,10 +566,10 @@ public: const Vector variable_arguments_to_string(Optional 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 diff --git a/Libraries/LibRegex/RegexMatch.h b/Libraries/LibRegex/RegexMatch.h index 8b41424079..9ae8b5ae7e 100644 --- a/Libraries/LibRegex/RegexMatch.h +++ b/Libraries/LibRegex/RegexMatch.h @@ -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 lines() const + { + if (is_u8_view()) { + auto views = u8view().lines(false); + Vector new_views; + for (auto& view : views) + new_views.append(move(view)); + return new_views; + } + + // FIXME: line splitting for Utf32View needed + Vector 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 m_u8view; + Optional m_u32view; +}; + class Match final { private: Optional 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; diff --git a/Libraries/LibRegex/RegexMatcher.cpp b/Libraries/LibRegex/RegexMatcher.cpp index 9a636d9cb1..d410c62543 100644 --- a/Libraries/LibRegex/RegexMatcher.cpp +++ b/Libraries/LibRegex/RegexMatcher.cpp @@ -66,10 +66,22 @@ String Regex::error_string(Optional message) const } template -RegexResult Matcher::match(const StringView& view, Optional::OptionsType> regex_options) const +RegexResult Matcher::match(const RegexStringView& view, Optional::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 views; + views.append(view); + return match(views, regex_options); +} + +template +RegexResult Matcher::match(const Vector views, Optional::OptionsType> regex_options) const { size_t match_count { 0 }; - Vector views { view }; MatchInput input; MatchState state; @@ -78,9 +90,6 @@ RegexResult Matcher::match(const StringView& view, Optional::match(const StringView& view, Optional 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::match(const StringView& view, Optional Matcher::execute_low_prio_forks(const Match original_state.string_position = 0; return false; -}; +} template class Matcher; template class Regex; diff --git a/Libraries/LibRegex/RegexMatcher.h b/Libraries/LibRegex/RegexMatcher.h index b98873c81f..5d28c2b8d0 100644 --- a/Libraries/LibRegex/RegexMatcher.h +++ b/Libraries/LibRegex/RegexMatcher.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -50,7 +51,9 @@ struct RegexResult final { Vector matches; Vector> capture_group_matches; Vector> 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 @@ -67,7 +70,8 @@ public: } ~Matcher() = default; - RegexResult match(const StringView&, Optional::OptionsType> = {}) const; + RegexResult match(const RegexStringView&, Optional::OptionsType> = {}) const; + RegexResult match(const Vector, Optional::OptionsType> = {}) const; private: Optional 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 { nullptr }; - Regex(StringView pattern, typename ParserTraits::OptionsType regex_options = {}); + explicit Regex(StringView pattern, typename ParserTraits::OptionsType regex_options = {}); ~Regex() = default; void print_bytecode(FILE* f = stdout) const; String error_string(Optional message = {}) const; - RegexResult match(StringView view, Optional::OptionsType> regex_options = {}) const + RegexResult match(const RegexStringView view, Optional::OptionsType> regex_options = {}) const { if (!matcher || parser_result.error != Error::NoError) return {}; return matcher->match(view, regex_options); } - RegexResult search(StringView view, Optional::OptionsType> regex_options = {}) const + RegexResult match(const Vector views, Optional::OptionsType> regex_options = {}) const + { + if (!matcher || parser_result.error != Error::NoError) + return {}; + return matcher->match(views, regex_options); + } + + RegexResult search(const RegexStringView view, Optional::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::OptionsType> regex_options = {}) const + RegexResult search(const Vector views, Optional::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::OptionsType> regex_options = {}) const + { + m = match(view, regex_options); return m.success; } - bool search(StringView view, RegexResult& m, Optional::OptionsType> regex_options = {}) const + bool match(const Vector views, RegexResult& m, Optional::OptionsType> regex_options = {}) const + { + m = match(views, regex_options); + return m.success; + } + + bool search(const RegexStringView view, RegexResult& m, Optional::OptionsType> regex_options = {}) const { m = search(view, regex_options); return m.success; } - bool has_match(const StringView view, Optional::OptionsType> regex_options = {}) const + bool search(const Vector views, RegexResult& m, Optional::OptionsType> regex_options = {}) const + { + m = search(views, regex_options); + return m.success; + } + + bool has_match(const RegexStringView view, Optional::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 views, Optional::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 -RegexResult match(const StringView view, Regex& pattern, Optional::OptionsType> regex_options = {}) +RegexResult match(const RegexStringView view, Regex& pattern, Optional::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 -bool match(const StringView view, Regex& pattern, RegexResult& res, Optional::OptionsType> regex_options = {}) +RegexResult match(const Vector view, Regex& pattern, Optional::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 -RegexResult search(const StringView view, Regex& pattern, Optional::OptionsType> regex_options = {}) +bool match(const RegexStringView view, Regex& pattern, RegexResult& res, Optional::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 -bool search(const StringView view, Regex& pattern, RegexResult& res, Optional::OptionsType> regex_options = {}) +bool match(const Vector view, Regex& pattern, RegexResult& res, Optional::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 -bool has_match(const StringView view, Regex& pattern, Optional::OptionsType> regex_options = {}) +RegexResult search(const RegexStringView view, Regex& pattern, Optional::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 +RegexResult search(const Vector views, Regex& pattern, Optional::OptionsType> regex_options = {}) +{ + return pattern.search(views, regex_options); +} + + +template +bool search(const RegexStringView view, Regex& pattern, RegexResult& res, Optional::OptionsType> regex_options = {}) +{ + return pattern.search(view, regex_options); +} + +template +bool search(const Vector views, Regex& pattern, RegexResult& res, Optional::OptionsType> regex_options = {}) +{ + return pattern.search(views, regex_options); +} + +template +bool has_match(const RegexStringView view, Regex& pattern, Optional::OptionsType> regex_options = {}) +{ + return pattern.has_match(view, regex_options); +} + +template +bool has_match(const Vector views, Regex& pattern, Optional::OptionsType> regex_options = {}) +{ + return pattern.has_match(views, regex_options); +} } using regex::has_match; diff --git a/Libraries/LibRegex/RegexOptions.h b/Libraries/LibRegex/RegexOptions.h index 36cc0ce40a..cbebe82ea7 100644 --- a/Libraries/LibRegex/RegexOptions.h +++ b/Libraries/LibRegex/RegexOptions.h @@ -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, }; diff --git a/Libraries/LibRegex/Tests/Benchmark.cpp b/Libraries/LibRegex/Tests/Benchmark.cpp index fa90c2f80f..0a25ee1847 100644 --- a/Libraries/LibRegex/Tests/Benchmark.cpp +++ b/Libraries/LibRegex/Tests/Benchmark.cpp @@ -42,6 +42,12 @@ # include # 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 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 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 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 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 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 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 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 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 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 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 re("regex*"); @@ -356,10 +362,10 @@ BENCHMARK_CASE(char_qualifier_asterisk_benchmark) EXPECT_EQ(re.search("#include ", 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 ", m, re), false); } } -#endif +# endif -#if defined(REGEX_BENCHMARK_OUR) +# if defined(REGEX_BENCHMARK_OUR) BENCHMARK_CASE(parens_qualifier_questionmark_benchmark) { Regex 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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) diff --git a/Libraries/LibRegex/Tests/Regex.cpp b/Libraries/LibRegex/Tests/Regex.cpp index 8a5cb904b1..9c73b54914 100644 --- a/Libraries/LibRegex/Tests/Regex.cpp +++ b/Libraries/LibRegex/Tests/Regex.cpp @@ -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 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 re("[[:alpha:]]*=(?[[:digit:]]*)"); diff --git a/Libraries/LibRegex/Tests/RegexLibC.cpp b/Libraries/LibRegex/Tests/RegexLibC.cpp index 40e0303159..031ed13b2c 100644 --- a/Libraries/LibRegex/Tests/RegexLibC.cpp +++ b/Libraries/LibRegex/Tests/RegexLibC.cpp @@ -30,13 +30,6 @@ #include #include -#define BENCHMARK_LOOP_ITERATIONS 100000 -#define DISABLE_REGEX_BENCHMARK - -//#if not(defined(REGEX_DEBUG) || defined(REGEX_MATCH_STATUS) || defined(DISABLE_REGEX_BENCHMARK)) -# include -//#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)