Skip to content

Commit

Permalink
Improve String, StringList, and List objects.
Browse files Browse the repository at this point in the history
* Add strCmp*() and strFirst*() to String.
* Add strLstSort() and strLstNewSplitSize() to StringList.
* Add strLstNewSplitZ() to StringList a update calls to strLstNewSplit() as needed.
* Add lstSort to List.
  • Loading branch information
dwsteele committed Jan 23, 2018
1 parent 47c048b commit 2afb73d
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 24 deletions.
2 changes: 1 addition & 1 deletion src/common/ini.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ iniParse(Ini *this, const String *content)
String *section = NULL;

// Split the content into lines and loop
StringList *lines = strLstNewSplit(content, strNew("\n"));
StringList *lines = strLstNewSplitZ(content, "\n");

for (unsigned int lineIdx = 0; lineIdx < strLstSize(lines); lineIdx++)
{
Expand Down
11 changes: 11 additions & 0 deletions src/common/type/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,17 @@ lstSize(const List *this)
return this->listSize;
}

/***********************************************************************************************************************************
List sort
***********************************************************************************************************************************/
List *
lstSort(List *this, int (*comparator)(const void *, const void*))
{
qsort(this->list, this->listSize, this->itemSize, comparator);

return this;
}

/***********************************************************************************************************************************
Free the string
***********************************************************************************************************************************/
Expand Down
1 change: 1 addition & 0 deletions src/common/type/list.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ List *lstNew(size_t itemSize);
List *lstAdd(List *this, const void *item);
void *lstGet(const List *this, unsigned int listIdx);
unsigned int lstSize(const List *this);
List *lstSort(List *this, int (*comparator)(const void *, const void*));
void lstFree(List *this);

#endif
40 changes: 40 additions & 0 deletions src/common/type/string.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/***********************************************************************************************************************************
String Handler
***********************************************************************************************************************************/
#include <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -194,6 +195,21 @@ strCatFmt(String *this, const char *format, ...)
return this;
}

/***********************************************************************************************************************************
C-style string compare
***********************************************************************************************************************************/
int
strCmp(const String *this, const String *compare)
{
return strcmp(strPtr(this), strPtr(compare));
}

int
strCmpZ(const String *this, const char *compare)
{
return strcmp(strPtr(this), compare);
}

/***********************************************************************************************************************************
Duplicate a string from an existing string
***********************************************************************************************************************************/
Expand Down Expand Up @@ -252,6 +268,30 @@ strEqZ(const String *this, const char *compare)
return strcmp(strPtr(this), compare) == 0;
}

/***********************************************************************************************************************************
Upper-case the first letter
***********************************************************************************************************************************/
String *
strFirstUpper(String *this)
{
if (this->size > 0)
this->buffer[0] = toupper(this->buffer[0]);

return this;
}

/***********************************************************************************************************************************
Lower-case the first letter
***********************************************************************************************************************************/
String *
strFirstLower(String *this)
{
if (this->size > 0)
this->buffer[0] = tolower(this->buffer[0]);

return this;
}

/***********************************************************************************************************************************
Return string ptr
***********************************************************************************************************************************/
Expand Down
4 changes: 4 additions & 0 deletions src/common/type/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ 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, ...) __attribute__((format(printf, 2, 3)));
int strCmp(const String *this, const String *compare);
int strCmpZ(const String *this, const char *compare);
String *strDup(const String *this);
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);
String *strFirstUpper(String *this);
String *strFirstLower(String *this);
const char *strPtr(const String *this);
size_t strSize(const String *this);
String *strTrim(String *this);
Expand Down
107 changes: 105 additions & 2 deletions src/common/type/stringList.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ Split a string into a string list based on a delimiter
***********************************************************************************************************************************/
StringList *
strLstNewSplit(const String *string, const String *delimiter)
{
return strLstNewSplitZ(string, strPtr(delimiter));
}

StringList *
strLstNewSplitZ(const String *string, const char *delimiter)
{
// Create the list
StringList *this = strLstNew();
Expand All @@ -36,13 +42,13 @@ strLstNewSplit(const String *string, const String *delimiter)
do
{
// Find a delimiter match
stringMatch = strstr(stringBase, strPtr(delimiter));
stringMatch = strstr(stringBase, delimiter);

// If a match was found then add the string
if (stringMatch != NULL)
{
strLstAdd(this, strNewN(stringBase, stringMatch - stringBase));
stringBase = stringMatch + strSize(delimiter);
stringBase = stringMatch + strlen(delimiter);
}
// Else make whatever is left the last string
else
Expand All @@ -53,6 +59,68 @@ strLstNewSplit(const String *string, const String *delimiter)
return this;
}

/***********************************************************************************************************************************
Split a string into a string list based on a delimiter and max size per item
In other words each item in the list will be no longer than size even if multiple delimiters are skipped. This is useful for
breaking up test on spaces, for example.
***********************************************************************************************************************************/
StringList *
strLstNewSplitSize(const String *string, const String *delimiter, size_t size)
{
return strLstNewSplitSizeZ(string, strPtr(delimiter), size);
}

StringList *
strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
{
// Create the list
StringList *this = strLstNew();

// Base points to the beginning of the string that is being searched
const char *stringBase = strPtr(string);

// Match points to the next delimiter match that has been found
const char *stringMatchLast = NULL;
const char *stringMatch = NULL;

do
{
// Find a delimiter match
stringMatch = strstr(stringMatchLast == NULL ? stringBase : stringMatchLast, delimiter);

// If a match was found then add the string
if (stringMatch != NULL)
{
if ((size_t)(stringMatch - stringBase) >= size)
{
if (stringMatchLast != NULL)
stringMatch = stringMatchLast - strlen(delimiter);

strLstAdd(this, strNewN(stringBase, stringMatch - stringBase));
stringBase = stringMatch + strlen(delimiter);
stringMatchLast = NULL;
}
else
stringMatchLast = stringMatch + strlen(delimiter);
}
// Else make whatever is left the last string
else
{
if (stringMatchLast != NULL && strlen(stringBase) - strlen(delimiter) >= size)
{
strLstAdd(this, strNewN(stringBase, (stringMatchLast - strlen(delimiter)) - stringBase));
stringBase = stringMatchLast;
}

strLstAdd(this, strNew(stringBase));
}
}
while(stringMatch != NULL);

return this;
}

/***********************************************************************************************************************************
New string list from a variant list -- all variants in the list must be type string
***********************************************************************************************************************************/
Expand Down Expand Up @@ -164,6 +232,41 @@ strLstSize(const StringList *this)
return lstSize((List *)this);
}

/***********************************************************************************************************************************
Sort strings in alphabetical order
***********************************************************************************************************************************/
static int
sortAscComparator(const void *item1, const void *item2)
{
return strCmp(*(String **)item1, *(String **)item2);
}

static int
sortDescComparator(const void *item1, const void *item2)
{
return strCmp(*(String **)item2, *(String **)item1);
}

StringList *
strLstSort(StringList *this, SortOrder sortOrder)
{
switch (sortOrder)
{
case sortOrderAsc:
{
lstSort((List *)this, sortAscComparator);
break;
}

case sortOrderDesc:
{
lstSort((List *)this, sortDescComparator);
break;
}
}
return this;
}

/***********************************************************************************************************************************
Wrapper for lstFree()
***********************************************************************************************************************************/
Expand Down
14 changes: 14 additions & 0 deletions src/common/type/stringList.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ String List Handler

#include "common/type/string.h"

/***********************************************************************************************************************************
Sort orders
***********************************************************************************************************************************/
typedef enum
{
sortOrderAsc,
sortOrderDesc,
} SortOrder;

/***********************************************************************************************************************************
String list type
***********************************************************************************************************************************/
Expand All @@ -18,6 +27,9 @@ Functions

StringList *strLstNew();
StringList *strLstNewSplit(const String *string, const String *delimiter);
StringList *strLstNewSplitZ(const String *string, const char *delimiter);
StringList *strLstNewSplitSize(const String *string, const String *delimiter, size_t size);
StringList *strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size);
StringList *strLstNewVarLst(const VariantList *sourceList);
StringList *strLstDup(const StringList *sourceList);

Expand All @@ -27,6 +39,8 @@ String *strLstGet(const StringList *this, unsigned int listIdx);
String *strLstJoin(const StringList *this, const char *separator);
const char **strLstPtr(const StringList *this);
unsigned int strLstSize(const StringList *this);
StringList *strLstSort(StringList *this, SortOrder sortOrder);

void strLstFree(StringList *this);

#endif
6 changes: 3 additions & 3 deletions test/lib/pgBackRestTest/Common/DefineTest.pm
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ my $oTestDef =
},
{
&TESTDEF_NAME => 'type-list',
&TESTDEF_TOTAL => 2,
&TESTDEF_TOTAL => 3,
&TESTDEF_C => true,

&TESTDEF_COVERAGE =>
Expand All @@ -184,7 +184,7 @@ my $oTestDef =
},
{
&TESTDEF_NAME => 'type-string',
&TESTDEF_TOTAL => 8,
&TESTDEF_TOTAL => 9,
&TESTDEF_C => true,

&TESTDEF_COVERAGE =>
Expand All @@ -194,7 +194,7 @@ my $oTestDef =
},
{
&TESTDEF_NAME => 'type-string-list',
&TESTDEF_TOTAL => 5,
&TESTDEF_TOTAL => 7,
&TESTDEF_C => true,

&TESTDEF_COVERAGE =>
Expand Down
37 changes: 37 additions & 0 deletions test/src/module/common/typeListTest.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@
Test Lists
***********************************************************************************************************************************/

/***********************************************************************************************************************************
Test sort comparator
***********************************************************************************************************************************/
static int
testComparator(const void *item1, const void *item2)
{
int int1 = *(int *)item1;
int int2 = *(int *)item2;

if (int1 < int2)
return -1;

if (int1 > int2)
return 1;

return 0;
}

/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
Expand Down Expand Up @@ -42,4 +60,23 @@ void testRun()

TEST_ERROR(lstGet(list, lstSize(list)), AssertError, "cannot get index 9 from list with 9 value(s)");
}

// *****************************************************************************************************************************
if (testBegin("lstSort"))
{
List *list = lstNew(sizeof(int));
int value;

value = 3; lstAdd(list, &value);
value = 5; lstAdd(list, &value);
value = 3; lstAdd(list, &value);
value = 2; lstAdd(list, &value);

TEST_RESULT_PTR(lstSort(list, testComparator), list, "list sort");

TEST_RESULT_INT(*((int *)lstGet(list, 0)), 2, "sort value 0");
TEST_RESULT_INT(*((int *)lstGet(list, 1)), 3, "sort value 1");
TEST_RESULT_INT(*((int *)lstGet(list, 2)), 3, "sort value 2");
TEST_RESULT_INT(*((int *)lstGet(list, 3)), 5, "sort value 3");
}
}
Loading

0 comments on commit 2afb73d

Please sign in to comment.