1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-03 14:52:21 +02:00

Improvements to String object.

* Add strBeginsWith(), strEndsWith(), strEq(), and strBase().
* Enable compiler type checking for strNewFmt() and strCatFmt().
* Rename strNewSzN() to strNewN().
This commit is contained in:
David Steele 2018-01-16 12:47:08 -05:00
parent d992851456
commit 83ddd75d82
8 changed files with 130 additions and 20 deletions

View File

@ -165,7 +165,7 @@ iniParse(Ini *this, const String *content)
THROW(FormatError, "ini section should end with ] at line %d: %s", lineIdx + 1, linePtr);
// Assign section
section = strNewSzN(linePtr + 1, strSize(line) - 2);
section = strNewN(linePtr + 1, strSize(line) - 2);
}
// Else it should be a key/value
else
@ -180,7 +180,7 @@ iniParse(Ini *this, const String *content)
THROW(FormatError, "missing '=' in key/value at line %d: %s", lineIdx + 1, linePtr);
// Extract the key
String *key = strTrim(strNewSzN(linePtr, lineEqual - linePtr));
String *key = strTrim(strNewN(linePtr, lineEqual - linePtr));
if (strSize(key) == 0)
THROW(FormatError, "key is zero-length at line %d: %s", lineIdx++, linePtr);

View File

@ -4,6 +4,8 @@ Buffer Handler
#ifndef COMMON_TYPE_BUFFER_H
#define COMMON_TYPE_BUFFER_H
#include "common/type.h"
/***********************************************************************************************************************************
Buffer object
***********************************************************************************************************************************/

View File

@ -92,7 +92,7 @@ Create a new string from a string with a specific length
The string may or may not be zero-terminated but we'll use that nomeclature since we're not concerned about the end of the string.
***********************************************************************************************************************************/
String *
strNewSzN(const char *string, size_t size)
strNewN(const char *string, size_t size)
{
// Create object
String *this = memNew(sizeof(String));
@ -108,6 +108,41 @@ strNewSzN(const char *string, size_t size)
return this;
}
/***********************************************************************************************************************************
Return the file part of a string (i.e. everthing after the last / or the entire string if there is no /)
***********************************************************************************************************************************/
String *
strBase(const String *this)
{
const char *end = this->buffer + this->size;
while (end > this->buffer && *(end - 1) != '/')
end--;
return strNew(end);
}
/***********************************************************************************************************************************
Does the string begin with the specified string?
***********************************************************************************************************************************/
bool
strBeginsWith(const String *this, const String *beginsWith)
{
return strBeginsWithZ(this, strPtr(beginsWith));
}
bool
strBeginsWithZ(const String *this, const char *beginsWith)
{
bool result = false;
unsigned int beginsWithSize = (unsigned int)strlen(beginsWith);
if (this->size >= beginsWithSize)
result = strncmp(strPtr(this), beginsWith, beginsWithSize) == 0;
return result;
}
/***********************************************************************************************************************************
Append a string
***********************************************************************************************************************************/
@ -174,26 +209,61 @@ strDup(const String *this)
}
/***********************************************************************************************************************************
Are two strings equal?
Does the string end with the specified string?
***********************************************************************************************************************************/
bool
strEq(const String *this1, const String *this2)
strEndsWith(const String *this, const String *endsWith)
{
return strEndsWithZ(this, strPtr(endsWith));
}
bool
strEndsWithZ(const String *this, const char *endsWith)
{
bool result = false;
unsigned int endsWithSize = (unsigned int)strlen(endsWith);
if (this->size >= endsWithSize)
result = strcmp(strPtr(this) + (this->size - endsWithSize), endsWith) == 0;
return result;
}
/***********************************************************************************************************************************
Are two strings equal?
There are two separate implementations because string objects can get the size very efficiently whereas the zero-terminated strings
would need a call to strlen().
***********************************************************************************************************************************/
bool
strEq(const String *this, const String *compare)
{
bool result = false;
if (this1->size == this2->size)
result = strcmp(strPtr(this1), strPtr(this2)) == 0;
if (this->size == compare->size)
result = strcmp(strPtr(this), strPtr(compare)) == 0;
return result;
}
bool
strEqZ(const String *this, const char *compare)
{
return strcmp(strPtr(this), compare) == 0;
}
/***********************************************************************************************************************************
Return string ptr
***********************************************************************************************************************************/
const char *
strPtr(const String *this)
{
return (const char *)this->buffer;
const char *result = NULL;
if (this != NULL)
result = (const char *)this->buffer;
return result;
}
/***********************************************************************************************************************************

View File

@ -16,13 +16,19 @@ Functions
String *strNew(const char *string);
String *strNewBuf(const Buffer *buffer);
String *strNewFmt(const char *format, ...);
String *strNewSzN(const char *string, size_t size);
String *strNewFmt(const char *format, ...) __attribute__((format(printf, 1, 2)));
String *strNewN(const char *string, size_t size);
String *strBase(const String *this);
bool strBeginsWith(const String *this, const String *beginsWith);
bool strBeginsWithZ(const String *this, const char *beginsWith);
String *strCat(String *this, const char *cat);
String *strCatFmt(String *this, const char *format, ...);
String *strCatFmt(String *this, const char *format, ...) __attribute__((format(printf, 2, 3)));
String *strDup(const String *this);
bool strEq(const String *this1, const String *this2);
bool strEndsWith(const String *this, const String *endsWith);
bool strEndsWithZ(const String *this, const char *endsWith);
bool strEq(const String *this, const String *compare);
bool strEqZ(const String *this, const char *compare);
const char *strPtr(const String *this);
size_t strSize(const String *this);
String *strTrim(String *this);

View File

@ -41,7 +41,7 @@ strLstNewSplit(const String *string, const String *delimiter)
// If a match was found then add the string
if (stringMatch != NULL)
{
strLstAdd(this, strNewSzN(stringBase, stringMatch - stringBase));
strLstAdd(this, strNewN(stringBase, stringMatch - stringBase));
stringBase = stringMatch + strSize(delimiter);
}
// Else make whatever is left the last string
@ -169,5 +169,6 @@ Wrapper for lstFree()
***********************************************************************************************************************************/
void strLstFree(StringList *this)
{
lstFree((List *)this);
if (this != NULL)
lstFree((List *)this);
}

View File

@ -513,7 +513,7 @@ configParse(int argListSize, const char *argList[])
strPtr(strLstGet(parseOption->valueList, listIdx)), cfgOptionName(optionId));
}
kvPut(keyValue, varNewStr(strNewSzN(pair, equal - pair)), varNewStr(strNew(equal + 1)));
kvPut(keyValue, varNewStr(strNewN(pair, equal - pair)), varNewStr(strNew(equal + 1)));
}
cfgOptionSet(optionId, parseOption->source, value);

View File

@ -143,7 +143,7 @@ my $oTestDef =
},
{
&TESTDEF_NAME => 'type-string',
&TESTDEF_TOTAL => 5,
&TESTDEF_TOTAL => 8,
&TESTDEF_C => true,
&TESTDEF_COVERAGE =>

View File

@ -9,7 +9,7 @@ Test Run
void testRun()
{
// *****************************************************************************************************************************
if (testBegin("strNew(), strNewBuf(), strNewSzN(), and strFree()"))
if (testBegin("strNew(), strNewBuf(), strNewN(), and strFree()"))
{
String *string = strNew("static string");
TEST_RESULT_STR(strPtr(string), "static string", "new with static string");
@ -20,7 +20,7 @@ void testRun()
TEST_RESULT_VOID(strFree(string), "free string");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(strPtr(strNewSzN("testmorestring", 4)), "test", "new string with size limit");
TEST_RESULT_STR(strPtr(strNewN("testmorestring", 4)), "test", "new string with size limit");
// -------------------------------------------------------------------------------------------------------------------------
Buffer *buffer = bufNew(8);
@ -36,7 +36,16 @@ void testRun()
}
// *****************************************************************************************************************************
if (testBegin("strCat and strCatFmt()"))
if (testBegin("strBase()"))
{
TEST_RESULT_STR(strPtr(strBase(strNew(""))), "", "empty string");
TEST_RESULT_STR(strPtr(strBase(strNew("/"))), "", "/ only");
TEST_RESULT_STR(strPtr(strBase(strNew("/file"))), "file", "root file");
TEST_RESULT_STR(strPtr(strBase(strNew("/dir1/dir2/file"))), "file", "subdirectory file");
}
// *****************************************************************************************************************************
if (testBegin("strCat() and strCatFmt()"))
{
String *string = strNew("XXXX");
String *string2 = strNew("ZZZZ");
@ -62,11 +71,33 @@ void testRun()
}
// *****************************************************************************************************************************
if (testBegin("strEq()"))
if (testBegin("strBeginsWith() and strBeginsWithZ()"))
{
TEST_RESULT_BOOL(strBeginsWith(strNew(""), strNew("aaa")), false, "empty string");
TEST_RESULT_BOOL(strBeginsWith(strNew("astring"), strNew("")), true, "empty begins with");
TEST_RESULT_BOOL(strBeginsWithZ(strNew("astring"), "astr"), true, "partial begins with");
TEST_RESULT_BOOL(strBeginsWithZ(strNew("astring"), "astring"), true, "equal strings");
}
// *****************************************************************************************************************************
if (testBegin("strEndsWith() and strEndsWithZ()"))
{
TEST_RESULT_BOOL(strEndsWith(strNew(""), strNew(".doc")), false, "empty string");
TEST_RESULT_BOOL(strEndsWith(strNew("astring"), strNew("")), true, "empty ends with");
TEST_RESULT_BOOL(strEndsWithZ(strNew("astring"), "ing"), true, "partial ends with");
TEST_RESULT_BOOL(strEndsWithZ(strNew("astring"), "astring"), true, "equal strings");
}
// *****************************************************************************************************************************
if (testBegin("strEq() and strEqZ()"))
{
TEST_RESULT_BOOL(strEq(strNew("equalstring"), strNew("equalstring")), true, "strings equal");
TEST_RESULT_BOOL(strEq(strNew("astring"), strNew("anotherstring")), false, "strings not equal");
TEST_RESULT_BOOL(strEq(strNew("astring"), strNew("bstring")), false, "equal length strings not equal");
TEST_RESULT_BOOL(strEqZ(strNew("equalstring"), "equalstring"), true, "strings equal");
TEST_RESULT_BOOL(strEqZ(strNew("astring"), "anotherstring"), false, "strings not equal");
TEST_RESULT_BOOL(strEqZ(strNew("astring"), "bstring"), false, "equal length strings not equal");
}
// *****************************************************************************************************************************