-
Notifications
You must be signed in to change notification settings - Fork 6
Add google/re2 and abseil-cpp as external dependencies #336
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
49269bc
d625ab2
eee7191
1dd92dd
63e588c
907298c
e9d7ecc
5ce2030
a29ca14
89aae22
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,36 @@ | ||||||||
| #include "cucumber_cpp/library/cucumber_expression/Re2RegexStrategy.hpp" | ||||||||
| #include <re2/re2.h> | ||||||||
| #include <optional> | ||||||||
| #include <stdexcept> | ||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [MegaLinter] reported by reviewdog 🐶
Suggested change
|
||||||||
| #include <string> | ||||||||
| #include <string_view> | ||||||||
| #include <vector> | ||||||||
|
|
||||||||
| namespace cucumber_cpp::library::cucumber_expression | ||||||||
| { | ||||||||
| Re2RegexStrategy::Re2RegexStrategy(std::string_view pattern) | ||||||||
| : re2{ std::make_unique<re2::RE2>(pattern) } | ||||||||
| { | ||||||||
| if (!re2->ok()) | ||||||||
| throw std::invalid_argument(re2->error()); | ||||||||
| } | ||||||||
|
|
||||||||
| Re2RegexStrategy::~Re2RegexStrategy() = default; | ||||||||
|
|
||||||||
| std::optional<std::vector<std::string>> Re2RegexStrategy::Match(std::string_view text) const | ||||||||
| { | ||||||||
| const int nCaptures = re2->NumberOfCapturingGroups(); | ||||||||
| const int nSubmatch = nCaptures + 1; | ||||||||
| std::vector<absl::string_view> submatch(static_cast<std::size_t>(nSubmatch)); | ||||||||
|
|
||||||||
| if (!re2->Match(text, 0, static_cast<int>(text.size()), RE2::UNANCHORED, submatch.data(), nSubmatch)) | ||||||||
| return std::nullopt; | ||||||||
|
|
||||||||
| std::vector<std::string> result; | ||||||||
| result.reserve(static_cast<std::size_t>(nSubmatch)); | ||||||||
| for (const auto& piece : submatch) | ||||||||
| result.emplace_back(piece.data(), piece.size()); | ||||||||
|
|
||||||||
| return result; | ||||||||
| } | ||||||||
| } | ||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #ifndef CUCUMBER_EXPRESSION_RE2REGEXSTRATEGY_HPP | ||
| #define CUCUMBER_EXPRESSION_RE2REGEXSTRATEGY_HPP | ||
|
|
||
| #include "cucumber_cpp/library/cucumber_expression/RegexStrategy.hpp" | ||
| #include <memory> | ||
| #include <optional> | ||
| #include <string> | ||
| #include <string_view> | ||
| #include <vector> | ||
|
|
||
| namespace re2 | ||
| { | ||
| class RE2; | ||
| } | ||
|
|
||
| namespace cucumber_cpp::library::cucumber_expression | ||
| { | ||
| struct Re2RegexStrategy : RegexStrategy | ||
| { | ||
| explicit Re2RegexStrategy(std::string_view pattern); | ||
| ~Re2RegexStrategy() override; | ||
|
|
||
| [[nodiscard]] std::optional<std::vector<std::string>> Match(std::string_view text) const override; | ||
|
|
||
| private: | ||
| std::unique_ptr<re2::RE2> re2; | ||
| }; | ||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,2 @@ | ||||
| // This file has been superseded by StdRegexStrategy.cpp and Re2RegexStrategy.cpp. | ||||
|
|
||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [MegaLinter] reported by reviewdog 🐶
Suggested change
|
||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #ifndef CUCUMBER_EXPRESSION_REGEXSTRATEGY_HPP | ||
| #define CUCUMBER_EXPRESSION_REGEXSTRATEGY_HPP | ||
|
|
||
| #include <optional> | ||
| #include <string> | ||
| #include <string_view> | ||
| #include <vector> | ||
|
|
||
| namespace cucumber_cpp::library::cucumber_expression | ||
| { | ||
| struct RegexStrategy | ||
| { | ||
| RegexStrategy() = default; | ||
| RegexStrategy(const RegexStrategy&) = delete; | ||
| RegexStrategy& operator=(const RegexStrategy&) = delete; | ||
| RegexStrategy(RegexStrategy&&) = delete; | ||
| RegexStrategy& operator=(RegexStrategy&&) = delete; | ||
| virtual ~RegexStrategy() = default; | ||
|
|
||
| [[nodiscard]] virtual std::optional<std::vector<std::string>> Match(std::string_view text) const = 0; | ||
| }; | ||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| #include "cucumber_cpp/library/cucumber_expression/RegexStrategyFactory.hpp" | ||
| #include "cucumber_cpp/library/cucumber_expression/StdRegexStrategy.hpp" | ||
| #ifdef CCR_HAS_RE2 | ||
| #include "cucumber_cpp/library/cucumber_expression/Re2RegexStrategy.hpp" | ||
| #endif | ||
| #include <memory> | ||
| #include <string_view> | ||
|
|
||
| namespace cucumber_cpp::library::cucumber_expression | ||
| { | ||
| std::unique_ptr<RegexStrategy> CreateRegexStrategy(std::string_view pattern) | ||
| { | ||
| #ifdef CCR_HAS_RE2 | ||
| return std::make_unique<Re2RegexStrategy>(pattern); | ||
| #else | ||
| return std::make_unique<StdRegexStrategy>(pattern); | ||
| #endif | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #ifndef CUCUMBER_EXPRESSION_REGEXSTRATEGYFACTORY_HPP | ||
| #define CUCUMBER_EXPRESSION_REGEXSTRATEGYFACTORY_HPP | ||
|
|
||
| #include "cucumber_cpp/library/cucumber_expression/RegexStrategy.hpp" | ||
| #include <memory> | ||
| #include <string_view> | ||
|
|
||
| namespace cucumber_cpp::library::cucumber_expression | ||
| { | ||
| [[nodiscard]] std::unique_ptr<RegexStrategy> CreateRegexStrategy(std::string_view pattern); | ||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| #include "cucumber_cpp/library/cucumber_expression/StdRegexStrategy.hpp" | ||
| #include <optional> | ||
| #include <regex> | ||
| #include <string> | ||
| #include <string_view> | ||
| #include <vector> | ||
|
|
||
| namespace cucumber_cpp::library::cucumber_expression | ||
| { | ||
| StdRegexStrategy::StdRegexStrategy(std::string_view pattern) | ||
| : regex{ std::string(pattern) } | ||
| { | ||
| } | ||
|
|
||
| std::optional<std::vector<std::string>> StdRegexStrategy::Match(std::string_view text) const | ||
| { | ||
| std::smatch match; | ||
| const std::string textStr(text); | ||
| if (!std::regex_search(textStr, match, regex)) | ||
|
Check warning on line 19 in cucumber_cpp/library/cucumber_expression/StdRegexStrategy.cpp
|
||
| return std::nullopt; | ||
|
|
||
| std::vector<std::string> result; | ||
| result.reserve(match.size()); | ||
| for (const auto& m : match) | ||
| result.emplace_back(m.str()); | ||
|
|
||
| return result; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #ifndef CUCUMBER_EXPRESSION_STDREGEXSTRATEGY_HPP | ||
| #define CUCUMBER_EXPRESSION_STDREGEXSTRATEGY_HPP | ||
|
|
||
| #include "cucumber_cpp/library/cucumber_expression/RegexStrategy.hpp" | ||
| #include <optional> | ||
| #include <regex> | ||
| #include <string> | ||
| #include <string_view> | ||
| #include <vector> | ||
|
|
||
| namespace cucumber_cpp::library::cucumber_expression | ||
| { | ||
| struct StdRegexStrategy : RegexStrategy | ||
| { | ||
| explicit StdRegexStrategy(std::string_view pattern); | ||
|
|
||
| [[nodiscard]] std::optional<std::vector<std::string>> Match(std::string_view text) const override; | ||
|
|
||
| private: | ||
| std::regex regex; | ||
| }; | ||
| } | ||
|
|
||
| #endif |
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,83 @@ | ||||
| #include "cucumber_cpp/library/cucumber_expression/StdRegexStrategy.hpp" | ||||
| #ifdef CCR_HAS_RE2 | ||||
| #include "cucumber_cpp/library/cucumber_expression/Re2RegexStrategy.hpp" | ||||
| #endif | ||||
| #include <gmock/gmock.h> | ||||
| #include <gtest/gtest.h> | ||||
| #include <optional> | ||||
| #include <stdexcept> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|
|
||||
| namespace cucumber_cpp::library::cucumber_expression | ||||
| { | ||||
| template<typename T> | ||||
| struct TestRegexStrategy : testing::Test | ||||
| {}; | ||||
|
|
||||
| #ifdef CCR_HAS_RE2 | ||||
| using RegexStrategyTypes = testing::Types<StdRegexStrategy, Re2RegexStrategy>; | ||||
| #else | ||||
| using RegexStrategyTypes = testing::Types<StdRegexStrategy>; | ||||
| #endif | ||||
| TYPED_TEST_SUITE(TestRegexStrategy, RegexStrategyTypes); | ||||
|
|
||||
| TYPED_TEST(TestRegexStrategy, ReturnsNulloptWhenNoMatch) | ||||
| { | ||||
| TypeParam strategy{ R"__(hello)__" }; | ||||
|
|
||||
| EXPECT_THAT(strategy.Match("world"), testing::IsFalse()); | ||||
| } | ||||
|
|
||||
| TYPED_TEST(TestRegexStrategy, ReturnsVectorWhenPatternMatches) | ||||
| { | ||||
| TypeParam strategy{ R"__((\d+))__" }; | ||||
|
|
||||
| const auto result = strategy.Match("abc 42 def"); | ||||
|
|
||||
| ASSERT_THAT(result, testing::IsTrue()); | ||||
| EXPECT_THAT(result->at(0), testing::StrEq("42")); // whole match | ||||
| EXPECT_THAT(result->at(1), testing::StrEq("42")); // first capture group | ||||
| } | ||||
|
|
||||
| TYPED_TEST(TestRegexStrategy, WholeMatchIsAtIndexZero) | ||||
| { | ||||
| TypeParam strategy{ R"__((\w+)\s+(\w+))__" }; | ||||
|
|
||||
| const auto result = strategy.Match("hello world"); | ||||
|
|
||||
| ASSERT_THAT(result, testing::IsTrue()); | ||||
| ASSERT_THAT(result->size(), testing::Eq(3)); | ||||
| EXPECT_THAT(result->at(0), testing::StrEq("hello world")); // whole match | ||||
| EXPECT_THAT(result->at(1), testing::StrEq("hello")); // first capture group | ||||
| EXPECT_THAT(result->at(2), testing::StrEq("world")); // second capture group | ||||
| } | ||||
|
|
||||
| TYPED_TEST(TestRegexStrategy, MatchesNegativeInteger) | ||||
| { | ||||
| TypeParam strategy{ R"__((-?\d+))__" }; | ||||
|
|
||||
| const auto result = strategy.Match("-22"); | ||||
|
|
||||
| ASSERT_THAT(result, testing::IsTrue()); | ||||
| EXPECT_THAT(result->at(1), testing::StrEq("-22")); | ||||
| } | ||||
|
|
||||
| TYPED_TEST(TestRegexStrategy, MatchesEmptyCapture) | ||||
| { | ||||
| TypeParam strategy{ R"__(^The value equals "([^"]*)"$)__" }; | ||||
|
|
||||
| const auto result = strategy.Match(R"__(The value equals "")__"); | ||||
|
|
||||
| ASSERT_THAT(result, testing::IsTrue()); | ||||
| EXPECT_THAT(result->at(1), testing::StrEq("")); | ||||
| } | ||||
|
|
||||
| #ifdef CCR_HAS_RE2 | ||||
| TEST(Re2RegexStrategy, ThrowsOnInvalidPattern) | ||||
| { | ||||
| EXPECT_THROW(Re2RegexStrategy{ R"__([invalid)__" }, std::invalid_argument); | ||||
| } | ||||
| #endif | ||||
| } | ||||
|
|
||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [MegaLinter] reported by reviewdog 🐶
Suggested change
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[MegaLinter] reported by reviewdog 🐶