1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Add functions to get the substring found by regExpMatch().

For now this is only used in testing but there are places where it could be useful in the core code.

Even if that turns out not to be true, it doesn't seem worth implementing a new version in testing just to capture a few values that we already have.
This commit is contained in:
David Steele 2019-12-04 19:43:26 -05:00
parent 053af2f54d
commit b2d82bd248
3 changed files with 91 additions and 3 deletions

View File

@ -18,6 +18,8 @@ struct RegExp
{
MemContext *memContext;
regex_t regExp;
const char *matchPtr;
size_t matchSize;
};
OBJECT_DEFINE_FREE(REGEXP);
@ -73,7 +75,7 @@ regExpNew(const String *expression)
// Compile the regexp and process errors
int result = 0;
if ((result = regcomp(&this->regExp, strPtr(expression), REG_NOSUB | REG_EXTENDED)) != 0)
if ((result = regcomp(&this->regExp, strPtr(expression), REG_EXTENDED)) != 0)
{
memFree(this);
regExpError(result);
@ -102,14 +104,67 @@ regExpMatch(RegExp *this, const String *string)
ASSERT(string != NULL);
// Test for a match
int result = regexec(&this->regExp, strPtr(string), 0, NULL, 0);
regmatch_t matchPtr;
int result = regexec(&this->regExp, strPtr(string), 1, &matchPtr, 0);
// Check for an error
regExpError(result);
// Store match results
if (result == 0)
{
this->matchPtr = strPtr(string) + matchPtr.rm_so;
this->matchSize = (size_t)(matchPtr.rm_eo - matchPtr.rm_so);
}
// Else reset match results
else
{
this->matchPtr = NULL;
this->matchSize = 0;
}
FUNCTION_TEST_RETURN(result == 0);
}
/***********************************************************************************************************************************
Getters
***********************************************************************************************************************************/
const char *
regExpMatchPtr(RegExp *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(REGEXP, this);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN(this->matchPtr);
}
size_t
regExpMatchSize(RegExp *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(REGEXP, this);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN(this->matchSize);
}
String *
regExpMatchStr(RegExp *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(REGEXP, this);
FUNCTION_TEST_END();
ASSERT(this != NULL);
FUNCTION_TEST_RETURN(this->matchPtr == NULL ? NULL : strNewN(regExpMatchPtr(this), regExpMatchSize(this)));
}
/***********************************************************************************************************************************
Match a regular expression in one call for brevity
***********************************************************************************************************************************/

View File

@ -24,6 +24,18 @@ void regExpFree(RegExp *this);
bool regExpMatchOne(const String *expression, const String *string);
String *regExpPrefix(const String *expression);
/***********************************************************************************************************************************
Getters
***********************************************************************************************************************************/
// Get pointer to the last match. NULL if there was no match.
const char *regExpMatchPtr(RegExp *this);
// Get size of the last match. 0 if there was no match.
size_t regExpMatchSize(RegExp *this);
// Get the last match as a String. NULL if there was no match.
String *regExpMatchStr(RegExp *this);
/***********************************************************************************************************************************
Macros for function logging
***********************************************************************************************************************************/

View File

@ -24,10 +24,31 @@ testRun(void)
}
TRY_END();
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("new regexp");
RegExp *regExp = NULL;
TEST_ASSIGN(regExp, regExpNew(strNew("^abc")), "new regexp");
TEST_RESULT_BOOL(regExpMatch(regExp, strNew("abcdef")), true, "match regexp");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("regexp match");
const String *string = STRDEF("abcdef");
TEST_RESULT_BOOL(regExpMatch(regExp, string), true, "match regexp");
TEST_RESULT_PTR(regExpMatchPtr(regExp), strPtr(string), "check ptr");
TEST_RESULT_SIZE(regExpMatchSize(regExp), 3, "check size");
TEST_RESULT_STR_Z(regExpMatchStr(regExp), "abc", "check str");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("no regexp match");
TEST_RESULT_BOOL(regExpMatch(regExp, strNew("bcdef")), false, "no match regexp");
TEST_RESULT_PTR(regExpMatchPtr(regExp), NULL, "check ptr");
TEST_RESULT_SIZE(regExpMatchSize(regExp), 0, "check size");
TEST_RESULT_PTR(regExpMatchStr(regExp), NULL, "check str");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("free regexp");
TEST_RESULT_VOID(regExpFree(regExp), "free regexp");
}