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:
parent
d992851456
commit
83ddd75d82
@ -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);
|
||||
|
@ -4,6 +4,8 @@ Buffer Handler
|
||||
#ifndef COMMON_TYPE_BUFFER_H
|
||||
#define COMMON_TYPE_BUFFER_H
|
||||
|
||||
#include "common/type.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Buffer object
|
||||
***********************************************************************************************************************************/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -143,7 +143,7 @@ my $oTestDef =
|
||||
},
|
||||
{
|
||||
&TESTDEF_NAME => 'type-string',
|
||||
&TESTDEF_TOTAL => 5,
|
||||
&TESTDEF_TOTAL => 8,
|
||||
&TESTDEF_C => true,
|
||||
|
||||
&TESTDEF_COVERAGE =>
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
|
Loading…
x
Reference in New Issue
Block a user