Skip to content

Commit

Permalink
Merge pull request #1835 from Expensify/main
Browse files Browse the repository at this point in the history
Update expensify_prod branch
  • Loading branch information
iwiznia authored Jul 31, 2024
2 parents c6f025a + 3db7538 commit 7f5a91d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 4 deletions.
22 changes: 19 additions & 3 deletions libstuff/libstuff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2805,7 +2805,7 @@ bool SIsValidSQLiteDateModifier(const string& modifier) {
return true;
}

bool SREMatch(const string& regExp, const string& input, bool caseSensitive, bool partialMatch, vector<string>* matches) {
bool SREMatch(const string& regExp, const string& input, bool caseSensitive, bool partialMatch, vector<string>* matches, size_t startOffset, size_t* matchOffset) {
int errornumber = 0;
PCRE2_SIZE erroroffset = 0;
uint32_t matchFlags = 0;
Expand All @@ -2824,7 +2824,7 @@ bool SREMatch(const string& regExp, const string& input, bool caseSensitive, boo
pcre2_set_depth_limit(matchContext, 1000);
pcre2_match_data* matchData = pcre2_match_data_create_from_pattern(re, 0);

int result = pcre2_match(re, (PCRE2_SPTR8)input.c_str(), input.size(), 0, matchFlags, matchData, matchContext);
int result = pcre2_match(re, (PCRE2_SPTR8)input.c_str() + startOffset, input.size() - startOffset, 0, matchFlags, matchData, matchContext);

// Clear out existing matches.
if (matches) {
Expand All @@ -2841,7 +2841,10 @@ bool SREMatch(const string& regExp, const string& input, bool caseSensitive, boo
if (start == PCRE2_UNSET || end == PCRE2_UNSET) {
continue;
}
matches->push_back(input.substr(start, end - start));
matches->push_back(input.substr(startOffset + start, end - start));
if (i == 0 && matchOffset) {
*matchOffset = startOffset + start;
}
}
}

Expand All @@ -2852,6 +2855,19 @@ bool SREMatch(const string& regExp, const string& input, bool caseSensitive, boo
return result > 0;
}

vector<vector <string>> SREMatchAll(const string& regExp, const string& input, bool caseSensitive) {
vector<vector<string>> returnValue;
vector<string> matches;
size_t startOffset = 0;
size_t matchOffset = 0;
while(SREMatch(regExp, input, caseSensitive, true, &matches, startOffset, &matchOffset)) {
returnValue.push_back(matches);
startOffset = matchOffset + matches[0].size();
}

return returnValue;
}

string SREReplace(const string& regExp, const string& input, const string& replacement, bool caseSensitive) {
char* output = nullptr;
size_t outSize = 0;
Expand Down
16 changes: 15 additions & 1 deletion libstuff/libstuff.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,21 @@ bool SConstantTimeEquals(const string& secret, const string& userInput);
bool SConstantTimeIEquals(const string& secret, const string& userInput);

// Unless `partialMatch` is specified, perform a full regex match (the '^' and '$' symbols are implicit).
bool SREMatch(const string& regExp, const string& input, bool caseSensitive = true, bool partialMatch = false, vector<string>* matches = nullptr);
//
// If `matches` is supplied it will be cleared, and any matches to the expression will fill it. The first entry in matches will be the entire matched portion of the string,
// and any following entries will be matched parenthesized subgroups.
//
// startOffset can be supplied to ignore the first part of the input string.
//
// If matchOffset is supplied, and a match is found, it will be set to the offset of the first character of the matched substring.
// To find the end of the matched substring, you can do something like matchOffset + matches[0].size().
bool SREMatch(const string& regExp, const string& input, bool caseSensitive = true, bool partialMatch = false, vector<string>* matches = nullptr, size_t startOffset = 0, size_t* matchOffset = nullptr);

// Matches every instance of regExp in the input string. Returns a vector of vectors or strings.
// The outer vector has one entry for each match found. The inner vectors contain first the entire matched substring, and following that, each match group
vector<vector <string>> SREMatchAll(const string& regExp, const string& input, bool caseSensitive = true);

// Replaces all instances of the matched `regExp` with `replacement` in `input`.
string SREReplace(const string& regExp, const string& input, const string& replacement, bool caseSensitive = true);

// Redact values that should not be logged.
Expand Down
8 changes: 8 additions & 0 deletions test/tests/LibStuffTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,14 @@ struct LibStuff : tpunit::TestFixture {
ASSERT_EQUAL(matches[1], "this");
ASSERT_EQUAL(matches[2], "contains");
ASSERT_EQUAL(matches[3], "cat");

// Let's do multiple matches.
string catNames = "kitty Whiskers, kitty Mittens, kitty Snowball";
auto matchList = SREMatchAll(R"(kitty\s+(\w+))", catNames);
ASSERT_EQUAL(matchList.size(), 3);
ASSERT_EQUAL(matchList[0][1], "Whiskers");
ASSERT_EQUAL(matchList[1][1], "Mittens");
ASSERT_EQUAL(matchList[2][1], "Snowball");
}

void SREReplaceTest() {
Expand Down

0 comments on commit 7f5a91d

Please sign in to comment.