mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Refactor List, StringList, and VariantList for performance.
Introduce a standard pattern for exposing public struct members (as documented in CODING.md) and use it to inline lstSize() which should improve the performance of iterating large lists. Since many functions in these modules are just thin wrappers of other functions, inline where appropriate. Remove strLstExistsZ() and strLstInsertZ() since they were only used in tests, where the String version of the function is sufficient. Move strLstNewSplitSizeZ() to command/help/help.c and remove strLstNewSplitSize(). This function has only ever been used by help and does not seem widely applicable.
This commit is contained in:
parent
904738a5f1
commit
79a2d02c9c
30
CODING.md
30
CODING.md
@ -205,6 +205,36 @@ Don't use a macro when a function could be used instead. Macros make it hard to
|
||||
|
||||
Object-oriented programming is used extensively. The object pointer is always referred to as `this`.
|
||||
|
||||
An object can expose internal struct members by defining a public struct that contains the members to be exposed and using inline functions to get/set the members.
|
||||
|
||||
The header file:
|
||||
```c
|
||||
/***********************************************************************************************************************************
|
||||
Getters/setters
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct ListPub
|
||||
{
|
||||
unsigned int listSize; // List size
|
||||
} ListPub;
|
||||
|
||||
// List size
|
||||
__attribute__((always_inline)) static inline unsigned int
|
||||
lstSize(const List *this)
|
||||
{
|
||||
ASSERT_INLINE(this != NULL);
|
||||
return ((const ListPub *)this)->listSize;
|
||||
}
|
||||
```
|
||||
And the C file:
|
||||
```c
|
||||
struct List
|
||||
{
|
||||
ListPub pub; // Publicly accessible variables
|
||||
...
|
||||
};
|
||||
```
|
||||
The public struct must be the first member of the private struct. The naming convention for the public struct is to add `Pub` to the end of the private struct name.
|
||||
|
||||
### Variadic Functions
|
||||
|
||||
Variadic functions can take a variable number of parameters. While the `printf()` pattern is variadic, it is not very flexible in terms of optional parameters given in any order.
|
||||
|
@ -266,6 +266,40 @@ switch (int)
|
||||
<title>Objects</title>
|
||||
|
||||
<p>Object-oriented programming is used extensively. The object pointer is always referred to as <id>this</id>.</p>
|
||||
|
||||
<p>An object can expose internal struct members by defining a public struct that contains the members to be exposed and using inline functions to get/set the members.</p>
|
||||
|
||||
<p>The header file:</p>
|
||||
|
||||
<code-block type="c">
|
||||
/***********************************************************************************************************************************
|
||||
Getters/setters
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct ListPub
|
||||
{
|
||||
unsigned int listSize; // List size
|
||||
} ListPub;
|
||||
|
||||
// List size
|
||||
__attribute__((always_inline)) static inline unsigned int
|
||||
lstSize(const List *this)
|
||||
{
|
||||
ASSERT_INLINE(this != NULL);
|
||||
return ((const ListPub *)this)->listSize;
|
||||
}
|
||||
</code-block>
|
||||
|
||||
<p>And the C file:</p>
|
||||
|
||||
<code-block type="c">
|
||||
struct List
|
||||
{
|
||||
ListPub pub; // Publicly accessible variables
|
||||
...
|
||||
};
|
||||
</code-block>
|
||||
|
||||
<p>The public struct must be the first member of the private struct. The naming convention for the public struct is to add <id>Pub</id> to the end of the private struct name.</p>
|
||||
</section>
|
||||
|
||||
<section id="variadic-functions">
|
||||
|
@ -26,6 +26,75 @@ Define the console width - use a fixed with of 80 since this should be safe on v
|
||||
***********************************************************************************************************************************/
|
||||
#define CONSOLE_WIDTH 80
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function to 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 text on spaces, for
|
||||
example.
|
||||
***********************************************************************************************************************************/
|
||||
static StringList *
|
||||
helpRenderSplitSize(const String *string, const char *delimiter, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, delimiter);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(string != NULL);
|
||||
ASSERT(delimiter != NULL);
|
||||
ASSERT(size > 0);
|
||||
|
||||
// Create the list
|
||||
StringList *this = strLstNew();
|
||||
|
||||
// Base points to the beginning of the string that is being searched
|
||||
const char *stringBase = strZ(string);
|
||||
|
||||
// Match points to the next delimiter match that has been found
|
||||
const char *stringMatchLast = NULL;
|
||||
const char *stringMatch = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||
{
|
||||
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, (size_t)(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, (size_t)((stringMatchLast - strlen(delimiter)) - stringBase)));
|
||||
stringBase = stringMatchLast;
|
||||
}
|
||||
|
||||
strLstAdd(this, strNew(stringBase));
|
||||
}
|
||||
}
|
||||
while (stringMatch != NULL);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function for helpRender() to make output look good on a console
|
||||
***********************************************************************************************************************************/
|
||||
@ -55,7 +124,7 @@ helpRenderText(const String *text, size_t indent, bool indentFirst, size_t lengt
|
||||
strCat(result, LF_STR);
|
||||
|
||||
// Split the paragraph into lines that don't exceed the line length
|
||||
StringList *partList = strLstNewSplitSizeZ(strLstGet(lineList, lineIdx), " ", length - indent);
|
||||
StringList *partList = helpRenderSplitSize(strLstGet(lineList, lineIdx), " ", length - indent);
|
||||
|
||||
for (unsigned int partIdx = 0; partIdx < strLstSize(partList); partIdx++)
|
||||
{
|
||||
|
@ -17,9 +17,9 @@ Object type
|
||||
***********************************************************************************************************************************/
|
||||
struct List
|
||||
{
|
||||
ListPub pub; // Publicly accessible variables
|
||||
MemContext *memContext;
|
||||
size_t itemSize;
|
||||
unsigned int listSize;
|
||||
unsigned int listSizeMax;
|
||||
SortOrder sortOrder;
|
||||
unsigned char *listAlloc; // Pointer to memory allocated for the list
|
||||
@ -59,21 +59,6 @@ lstNew(size_t itemSize, ListParam param)
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void *
|
||||
lstAdd(List *this, const void *item)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_PARAM_P(VOID, item);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(item != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstInsert(this, lstSize(this), item));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
List *
|
||||
lstClear(List *this)
|
||||
@ -92,7 +77,7 @@ lstClear(List *this)
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
this->listSize = 0;
|
||||
this->pub.listSize = 0;
|
||||
this->listSizeMax = 0;
|
||||
}
|
||||
|
||||
@ -137,8 +122,8 @@ lstGet(const List *this, unsigned int listIdx)
|
||||
ASSERT(this != NULL);
|
||||
|
||||
// Ensure list index is in range
|
||||
if (listIdx >= this->listSize)
|
||||
THROW_FMT(AssertError, "cannot get index %u from list with %u value(s)", listIdx, this->listSize);
|
||||
if (listIdx >= lstSize(this))
|
||||
THROW_FMT(AssertError, "cannot get index %u from list with %u value(s)", listIdx, lstSize(this));
|
||||
|
||||
// Return pointer to list item
|
||||
FUNCTION_TEST_RETURN(this->list + (listIdx * this->itemSize));
|
||||
@ -154,26 +139,11 @@ lstGetLast(const List *this)
|
||||
ASSERT(this != NULL);
|
||||
|
||||
// Ensure there are items in the list
|
||||
if (this->listSize == 0)
|
||||
if (lstSize(this) == 0)
|
||||
THROW(AssertError, "cannot get last from list with no values");
|
||||
|
||||
// Return pointer to list item
|
||||
FUNCTION_TEST_RETURN(lstGet(this, this->listSize - 1));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
bool
|
||||
lstExists(const List *this, const void *item)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_PARAM_P(VOID, item);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(item != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstFind(this, item) != NULL);
|
||||
FUNCTION_TEST_RETURN(lstGet(this, lstSize(this) - 1));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
@ -190,13 +160,13 @@ lstFind(const List *this, const void *item)
|
||||
ASSERT(item != NULL);
|
||||
|
||||
if (this->sortOrder == sortOrderAsc)
|
||||
FUNCTION_TEST_RETURN(bsearch(item, this->list, this->listSize, this->itemSize, this->comparator));
|
||||
FUNCTION_TEST_RETURN(bsearch(item, this->list, lstSize(this), this->itemSize, this->comparator));
|
||||
else if (this->sortOrder == sortOrderDesc)
|
||||
{
|
||||
// Assign the list for the descending comparator to use
|
||||
comparatorDescList = this;
|
||||
|
||||
FUNCTION_TEST_RETURN(bsearch(item, this->list, this->listSize, this->itemSize, lstComparatorDesc));
|
||||
FUNCTION_TEST_RETURN(bsearch(item, this->list, lstSize(this), this->itemSize, lstComparatorDesc));
|
||||
}
|
||||
|
||||
// Fall back on an iterative search
|
||||
@ -260,7 +230,7 @@ lstIdx(const List *this, const void *item)
|
||||
size_t result = (size_t)((unsigned char * const)item - this->list) / this->itemSize;
|
||||
|
||||
// Item pointers should always be in range
|
||||
ASSERT(result < this->listSize);
|
||||
ASSERT(result < lstSize(this));
|
||||
|
||||
FUNCTION_TEST_RETURN((unsigned int)result);
|
||||
}
|
||||
@ -279,7 +249,7 @@ lstInsert(List *this, unsigned int listIdx, const void *item)
|
||||
ASSERT(item != NULL);
|
||||
|
||||
// If list size = max then allocate more space
|
||||
if (this->listSize == this->listSizeMax)
|
||||
if (lstSize(this) == this->listSizeMax)
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
{
|
||||
@ -303,9 +273,9 @@ lstInsert(List *this, unsigned int listIdx, const void *item)
|
||||
// Else if there is space before the beginning of the list then move the list down
|
||||
else if (
|
||||
(this->list != this->listAlloc) &&
|
||||
(this->listSize + ((uintptr_t)(this->list - this->listAlloc) / this->itemSize) == this->listSizeMax))
|
||||
(lstSize(this) + ((uintptr_t)(this->list - this->listAlloc) / this->itemSize) == this->listSizeMax))
|
||||
{
|
||||
memmove(this->listAlloc, this->list, this->listSize * this->itemSize);
|
||||
memmove(this->listAlloc, this->list, lstSize(this) * this->itemSize);
|
||||
this->list = this->listAlloc;
|
||||
}
|
||||
|
||||
@ -319,7 +289,7 @@ lstInsert(List *this, unsigned int listIdx, const void *item)
|
||||
// Copy item into the list
|
||||
this->sortOrder = sortOrderNone;
|
||||
memcpy(itemPtr, item, this->itemSize);
|
||||
this->listSize++;
|
||||
this->pub.listSize++;
|
||||
|
||||
FUNCTION_TEST_RETURN(itemPtr);
|
||||
}
|
||||
@ -337,7 +307,7 @@ lstRemoveIdx(List *this, unsigned int listIdx)
|
||||
ASSERT(listIdx <= lstSize(this));
|
||||
|
||||
// Decrement the list size
|
||||
this->listSize--;
|
||||
this->pub.listSize--;
|
||||
|
||||
// If this is the first item then move the list pointer up to avoid moving all the items
|
||||
if (listIdx == 0)
|
||||
@ -386,10 +356,10 @@ lstRemoveLast(List *this)
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
if (this->listSize == 0)
|
||||
if (lstSize(this) == 0)
|
||||
THROW(AssertError, "cannot remove last from list with no values");
|
||||
|
||||
FUNCTION_TEST_RETURN(lstRemoveIdx(this, this->listSize - 1));
|
||||
FUNCTION_TEST_RETURN(lstRemoveIdx(this, lstSize(this) - 1));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
@ -405,19 +375,6 @@ lstMemContext(const List *this)
|
||||
FUNCTION_TEST_RETURN(this->memContext);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
unsigned int
|
||||
lstSize(const List *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(this->listSize);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
List *
|
||||
lstSort(List *this, SortOrder sortOrder)
|
||||
@ -433,7 +390,7 @@ lstSort(List *this, SortOrder sortOrder)
|
||||
switch (sortOrder)
|
||||
{
|
||||
case sortOrderAsc:
|
||||
qsort(this->list, this->listSize, this->itemSize, this->comparator);
|
||||
qsort(this->list, lstSize(this), this->itemSize, this->comparator);
|
||||
break;
|
||||
|
||||
case sortOrderDesc:
|
||||
@ -441,7 +398,7 @@ lstSort(List *this, SortOrder sortOrder)
|
||||
// Assign the list that will be sorted for the comparator function to use
|
||||
comparatorDescList = this;
|
||||
|
||||
qsort(this->list, this->listSize, this->itemSize, lstComparatorDesc);
|
||||
qsort(this->list, lstSize(this), this->itemSize, lstComparatorDesc);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -475,5 +432,5 @@ lstComparatorSet(List *this, ListComparator *comparator)
|
||||
String *
|
||||
lstToLog(const List *this)
|
||||
{
|
||||
return strNewFmt("{size: %u}", this->listSize);
|
||||
return strNewFmt("{size: %u}", lstSize(this));
|
||||
}
|
||||
|
@ -63,12 +63,35 @@ typedef struct ListParam
|
||||
|
||||
List *lstNew(size_t itemSize, ListParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters/Setters
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct ListPub
|
||||
{
|
||||
unsigned int listSize; // List size
|
||||
} ListPub;
|
||||
|
||||
// Set a new comparator
|
||||
List *lstComparatorSet(List *this, ListComparator *comparator);
|
||||
|
||||
// List size
|
||||
__attribute__((always_inline)) static inline unsigned int
|
||||
lstSize(const List *this)
|
||||
{
|
||||
ASSERT_INLINE(this != NULL);
|
||||
return ((const ListPub *)this)->listSize;
|
||||
}
|
||||
|
||||
// Is the list empty?
|
||||
__attribute__((always_inline)) static inline bool
|
||||
lstEmpty(const List *this)
|
||||
{
|
||||
return lstSize(this) == 0;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
// Add an item to the end of the list
|
||||
void *lstAdd(List *this, const void *item);
|
||||
|
||||
// Clear items from a list
|
||||
List *lstClear(List *this);
|
||||
|
||||
@ -76,20 +99,31 @@ List *lstClear(List *this);
|
||||
void *lstGet(const List *this, unsigned int listIdx);
|
||||
void *lstGetLast(const List *this);
|
||||
|
||||
// Does an item exist in the list?
|
||||
bool lstExists(const List *this, const void *item);
|
||||
|
||||
// Find an item in the list
|
||||
void *lstFind(const List *this, const void *item);
|
||||
void *lstFindDefault(const List *this, const void *item, void *itemDefault);
|
||||
unsigned int lstFindIdx(const List *this, const void *item);
|
||||
|
||||
// Does an item exist in the list?
|
||||
__attribute__((always_inline)) static inline bool
|
||||
lstExists(const List *this, const void *item)
|
||||
{
|
||||
return lstFind(this, item) != NULL;
|
||||
}
|
||||
|
||||
// Get the index of a list item
|
||||
unsigned int lstIdx(const List *this, const void *item);
|
||||
|
||||
// Insert an item into the list
|
||||
void *lstInsert(List *this, unsigned int listIdx, const void *item);
|
||||
|
||||
// Add an item to the end of the list
|
||||
__attribute__((always_inline)) static inline void *
|
||||
lstAdd(List *this, const void *item)
|
||||
{
|
||||
return lstInsert(this, lstSize(this), item);
|
||||
}
|
||||
|
||||
// Memory context for this list
|
||||
MemContext *lstMemContext(const List *this);
|
||||
|
||||
@ -101,25 +135,9 @@ bool lstRemove(List *this, const void *item);
|
||||
List *lstRemoveIdx(List *this, unsigned int listIdx);
|
||||
List *lstRemoveLast(List *this);
|
||||
|
||||
// Return list size
|
||||
unsigned int lstSize(const List *this);
|
||||
|
||||
// Is the list empty?
|
||||
__attribute__((always_inline)) static inline bool
|
||||
lstEmpty(const List *this)
|
||||
{
|
||||
return lstSize(this) == 0;
|
||||
}
|
||||
|
||||
// List sort
|
||||
List *lstSort(List *this, SortOrder sortOrder);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters/Setters
|
||||
***********************************************************************************************************************************/
|
||||
// Set a new comparator
|
||||
List *lstComparatorSet(List *this, ListComparator *comparator);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
***********************************************************************************************************************************/
|
||||
|
@ -12,64 +12,25 @@ String List Handler
|
||||
#include "common/memContext.h"
|
||||
#include "common/type/stringList.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Wrapper for lstNew*()
|
||||
***********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstNew(void)
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RETURN((StringList *)lstNewP(sizeof(String *), .comparator = lstComparatorStr));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Internal add -- the string must have been created in the list's mem context before being passed
|
||||
***********************************************************************************************************************************/
|
||||
static String *
|
||||
__attribute__((always_inline)) static inline String *
|
||||
strLstAddInternal(StringList *this, String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(*(String **)lstAdd((List *)this, &string));
|
||||
return *(String **)lstAdd((List *)this, &string);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Internal insert -- the string must have been created in the list's mem context before being passed
|
||||
***********************************************************************************************************************************/
|
||||
static String *
|
||||
__attribute__((always_inline)) static inline String *
|
||||
strLstInsertInternal(StringList *this, unsigned int listIdx, String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(*(String **)lstInsert((List *)this, listIdx, &string));
|
||||
return *(String **)lstInsert((List *)this, listIdx, &string);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstNewSplit(const String *string, const String *delimiter)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRING, delimiter);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(string != NULL);
|
||||
ASSERT(delimiter != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(strLstNewSplitZ(string, strZ(delimiter)));
|
||||
}
|
||||
|
||||
StringList *
|
||||
strLstNewSplitZ(const String *string, const char *delimiter)
|
||||
{
|
||||
@ -114,85 +75,6 @@ strLstNewSplitZ(const String *string, const char *delimiter)
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstNewSplitSize(const String *string, const String *delimiter, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRING, delimiter);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(string != NULL);
|
||||
ASSERT(delimiter != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(strLstNewSplitSizeZ(string, strZ(delimiter), size));
|
||||
}
|
||||
|
||||
StringList *
|
||||
strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, delimiter);
|
||||
FUNCTION_TEST_PARAM(SIZE, size);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(string != NULL);
|
||||
ASSERT(delimiter != NULL);
|
||||
|
||||
// Create the list
|
||||
StringList *this = strLstNew();
|
||||
|
||||
// Base points to the beginning of the string that is being searched
|
||||
const char *stringBase = strZ(string);
|
||||
|
||||
// Match points to the next delimiter match that has been found
|
||||
const char *stringMatchLast = NULL;
|
||||
const char *stringMatch = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||
{
|
||||
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);
|
||||
|
||||
strLstAddInternal(this, strNewN(stringBase, (size_t)(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)
|
||||
{
|
||||
strLstAddInternal(this, strNewN(stringBase, (size_t)((stringMatchLast - strlen(delimiter)) - stringBase)));
|
||||
stringBase = stringMatchLast;
|
||||
}
|
||||
|
||||
strLstAddInternal(this, strNew(stringBase));
|
||||
}
|
||||
}
|
||||
while (stringMatch != NULL);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstNewVarLst(const VariantList *sourceList)
|
||||
@ -247,35 +129,6 @@ strLstDup(const StringList *sourceList)
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
bool
|
||||
strLstExists(const StringList *this, const String *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING, string);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstExists((List *)this, &string));
|
||||
}
|
||||
|
||||
bool
|
||||
strLstExistsZ(const StringList *this, const char *cstring)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, cstring);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
const String *string = cstring == NULL ? NULL : STR(cstring);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstExists((List *)this, &string));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strLstAdd(StringList *this, const String *string)
|
||||
@ -337,20 +190,6 @@ strLstAddZ(StringList *this, const char *string)
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strLstGet(const StringList *this, unsigned int listIdx)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(*(String **)lstGet((List *)this, listIdx));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strLstInsert(StringList *this, unsigned int listIdx, const String *string)
|
||||
@ -374,43 +213,6 @@ strLstInsert(StringList *this, unsigned int listIdx, const String *string)
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
String *
|
||||
strLstInsertZ(StringList *this, unsigned int listIdx, const char *string)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, string);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||
{
|
||||
result = strLstInsertInternal(this, listIdx, strNew(string));
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strLstJoin(const StringList *this, const char *separator)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRINGZ, separator);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(separator != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(strLstJoinQuote(this, separator, ""));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strLstJoinQuote(const StringList *this, const char *separator, const char *quote)
|
||||
@ -502,22 +304,6 @@ strLstMergeAnti(const StringList *this, const StringList *anti)
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstMove(StringList *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(parentNew != NULL);
|
||||
|
||||
lstMove((List *)this, parentNew);
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
const char **
|
||||
strLstPtr(const StringList *this)
|
||||
@ -543,93 +329,9 @@ strLstPtr(const StringList *this)
|
||||
FUNCTION_TEST_RETURN(list);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
bool
|
||||
strLstRemove(StringList *this, const String *item)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(STRING, item);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(item != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstRemove((List *)this, &item));
|
||||
}
|
||||
|
||||
StringList *
|
||||
strLstRemoveIdx(StringList *this, unsigned int listIdx)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN((StringList *)lstRemoveIdx((List *)this, listIdx));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
unsigned int
|
||||
strLstSize(const StringList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstSize((List *)this));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstSort(StringList *this, SortOrder sortOrder)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(ENUM, sortOrder);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
lstSort((List *)this, sortOrder);
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
StringList *
|
||||
strLstComparatorSet(StringList *this, ListComparator *comparator)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_PARAM(FUNCTIONP, comparator);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
lstComparatorSet((List *)this, comparator);
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
String *
|
||||
strLstToLog(const StringList *this)
|
||||
{
|
||||
return strNewFmt("{[%s]}", strZ(strLstJoinQuote(this, ", ", "\"")));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
strLstFree(StringList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING_LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
lstFree((List *)this);
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
@ -17,16 +17,21 @@ typedef struct StringList StringList;
|
||||
/***********************************************************************************************************************************
|
||||
Constructors
|
||||
***********************************************************************************************************************************/
|
||||
StringList *strLstNew(void);
|
||||
// Create empty StringList
|
||||
__attribute__((always_inline)) static inline StringList *
|
||||
strLstNew(void)
|
||||
{
|
||||
return (StringList *)lstNewP(sizeof(String *), .comparator = lstComparatorStr);
|
||||
}
|
||||
|
||||
// Split a string into a string list based on a delimiter
|
||||
StringList *strLstNewSplit(const String *string, const String *delimiter);
|
||||
StringList *strLstNewSplitZ(const String *string, const char *delimiter);
|
||||
|
||||
// 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 text on spaces, for example.
|
||||
StringList *strLstNewSplitSize(const String *string, const String *delimiter, size_t size);
|
||||
StringList *strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size);
|
||||
__attribute__((always_inline)) static inline StringList *
|
||||
strLstNewSplit(const String *string, const String *delimiter)
|
||||
{
|
||||
return strLstNewSplitZ(string, strZ(delimiter));
|
||||
}
|
||||
|
||||
// New string list from a variant list -- all variants in the list must be type string
|
||||
StringList *strLstNewVarLst(const VariantList *sourceList);
|
||||
@ -34,6 +39,30 @@ StringList *strLstNewVarLst(const VariantList *sourceList);
|
||||
// Duplicate a string list
|
||||
StringList *strLstDup(const StringList *sourceList);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters/Setters
|
||||
***********************************************************************************************************************************/
|
||||
// Set a new comparator
|
||||
__attribute__((always_inline)) static inline StringList *
|
||||
strLstComparatorSet(StringList *this, ListComparator *comparator)
|
||||
{
|
||||
return (StringList *)lstComparatorSet((List *)this, comparator);
|
||||
}
|
||||
|
||||
// List size
|
||||
__attribute__((always_inline)) static inline unsigned int
|
||||
strLstSize(const StringList *this)
|
||||
{
|
||||
return lstSize((List *)this);
|
||||
}
|
||||
|
||||
// Is the list empty?
|
||||
__attribute__((always_inline)) static inline bool
|
||||
strLstEmpty(const StringList *this)
|
||||
{
|
||||
return strLstSize(this) == 0;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
@ -43,60 +72,75 @@ String *strLstAddZ(StringList *this, const char *string);
|
||||
String *strLstAddIfMissing(StringList *this, const String *string);
|
||||
|
||||
// Does the specified string exist in the list?
|
||||
bool strLstExists(const StringList *this, const String *string);
|
||||
bool strLstExistsZ(const StringList *this, const char *cstring);
|
||||
__attribute__((always_inline)) static inline bool
|
||||
strLstExists(const StringList *this, const String *string)
|
||||
{
|
||||
return lstExists((List *)this, &string);
|
||||
}
|
||||
|
||||
// Insert into the list
|
||||
String *strLstInsert(StringList *this, unsigned int listIdx, const String *string);
|
||||
String *strLstInsertZ(StringList *this, unsigned int listIdx, const char *string);
|
||||
|
||||
// Get a string by index
|
||||
String *strLstGet(const StringList *this, unsigned int listIdx);
|
||||
|
||||
// Join a list of strings into a single string using the specified separator
|
||||
String *strLstJoin(const StringList *this, const char *separator);
|
||||
__attribute__((always_inline)) static inline String *
|
||||
strLstGet(const StringList *this, unsigned int listIdx)
|
||||
{
|
||||
return *(String **)lstGet((List *)this, listIdx);
|
||||
}
|
||||
|
||||
// Join a list of strings into a single string using the specified separator and quote with specified quote character
|
||||
String *strLstJoinQuote(const StringList *this, const char *separator, const char *quote);
|
||||
|
||||
// Join a list of strings into a single string using the specified separator
|
||||
__attribute__((always_inline)) static inline String *
|
||||
strLstJoin(const StringList *this, const char *separator)
|
||||
{
|
||||
return strLstJoinQuote(this, separator, "");
|
||||
}
|
||||
|
||||
// Return all items in this list which are not in the anti list. The input lists must *both* be sorted ascending or the results will
|
||||
// be undefined.
|
||||
StringList *strLstMergeAnti(const StringList *this, const StringList *anti);
|
||||
|
||||
// Move to a new parent mem context
|
||||
StringList *strLstMove(StringList *this, MemContext *parentNew);
|
||||
__attribute__((always_inline)) static inline StringList *
|
||||
strLstMove(StringList *this, MemContext *parentNew)
|
||||
{
|
||||
return (StringList *)lstMove((List *)this, parentNew);
|
||||
}
|
||||
|
||||
// Return a null-terminated array of pointers to the zero-terminated strings in this list. DO NOT override const and modify any of
|
||||
// the strings in this array, though it is OK to modify the array itself.
|
||||
const char **strLstPtr(const StringList *this);
|
||||
|
||||
// Remove an item from the list
|
||||
bool strLstRemove(StringList *this, const String *item);
|
||||
StringList *strLstRemoveIdx(StringList *this, unsigned int listIdx);
|
||||
|
||||
// List size
|
||||
unsigned int strLstSize(const StringList *this);
|
||||
|
||||
// Is the list empty?
|
||||
__attribute__((always_inline)) static inline bool
|
||||
strLstEmpty(const StringList *this)
|
||||
strLstRemove(StringList *this, const String *item)
|
||||
{
|
||||
return strLstSize(this) == 0;
|
||||
return lstRemove((List *)this, &item);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline StringList *
|
||||
strLstRemoveIdx(StringList *this, unsigned int listIdx)
|
||||
{
|
||||
return (StringList *)lstRemoveIdx((List *)this, listIdx);
|
||||
}
|
||||
|
||||
// List sort
|
||||
StringList *strLstSort(StringList *this, SortOrder sortOrder);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters/Setters
|
||||
***********************************************************************************************************************************/
|
||||
// Set a new comparator
|
||||
StringList *strLstComparatorSet(StringList *this, ListComparator *comparator);
|
||||
__attribute__((always_inline)) static inline StringList *
|
||||
strLstSort(StringList *this, SortOrder sortOrder)
|
||||
{
|
||||
return (StringList *)lstSort((List *)this, sortOrder);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void strLstFree(StringList *this);
|
||||
__attribute__((always_inline)) static inline void
|
||||
strLstFree(StringList *this)
|
||||
{
|
||||
lstFree((List *)this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
|
@ -12,16 +12,6 @@ Variant List Handler
|
||||
#include "common/type/list.h"
|
||||
#include "common/type/variantList.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Wrapper for lstNewP()
|
||||
***********************************************************************************************************************************/
|
||||
VariantList *
|
||||
varLstNew(void)
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
FUNCTION_TEST_RETURN((VariantList *)lstNewP(sizeof(Variant *)));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
VariantList *
|
||||
varLstNewStrLst(const StringList *stringList)
|
||||
@ -63,75 +53,3 @@ varLstDup(const VariantList *source)
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
VariantList *
|
||||
varLstAdd(VariantList *this, Variant *data)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_PARAM(VARIANT, data);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
lstAdd((List *)this, &data);
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
Variant *
|
||||
varLstGet(const VariantList *this, unsigned int listIdx)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_PARAM(UINT, listIdx);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(*(Variant **)lstGet((List *)this, listIdx));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
unsigned int
|
||||
varLstSize(const VariantList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(lstSize((List *)this));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
VariantList *
|
||||
varLstMove(VariantList *this, MemContext *parentNew)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, parentNew);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(parentNew != NULL);
|
||||
|
||||
lstMove((List *)this, parentNew);
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
varLstFree(VariantList *this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(VARIANT_LIST, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
lstFree((List *)this);
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
@ -15,7 +15,12 @@ typedef struct VariantList VariantList;
|
||||
/***********************************************************************************************************************************
|
||||
Constructors
|
||||
***********************************************************************************************************************************/
|
||||
VariantList *varLstNew(void);
|
||||
// Create empty VariantList
|
||||
__attribute__((always_inline)) static inline VariantList *
|
||||
varLstNew(void)
|
||||
{
|
||||
return (VariantList *)lstNewP(sizeof(Variant *));
|
||||
}
|
||||
|
||||
// Create VariantList from StringList
|
||||
VariantList *varLstNewStrLst(const StringList *stringList);
|
||||
@ -24,19 +29,14 @@ VariantList *varLstNewStrLst(const StringList *stringList);
|
||||
VariantList *varLstDup(const VariantList *source);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
Getters/Setters
|
||||
***********************************************************************************************************************************/
|
||||
// Add to list
|
||||
VariantList *varLstAdd(VariantList *this, Variant *data);
|
||||
|
||||
// Get by index
|
||||
Variant *varLstGet(const VariantList *this, unsigned int listIdx);
|
||||
|
||||
// Move to new parent mem context
|
||||
VariantList *varLstMove(VariantList *this, MemContext *parentNew);
|
||||
|
||||
// List size
|
||||
unsigned int varLstSize(const VariantList *this);
|
||||
__attribute__((always_inline)) static inline unsigned int
|
||||
varLstSize(const VariantList *this)
|
||||
{
|
||||
return lstSize((List *)this);
|
||||
}
|
||||
|
||||
// Is the list empty?
|
||||
__attribute__((always_inline)) static inline bool
|
||||
@ -45,10 +45,39 @@ varLstEmpty(const VariantList *this)
|
||||
return varLstSize(this) == 0;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
// Add to list
|
||||
__attribute__((always_inline)) static inline VariantList *
|
||||
varLstAdd(VariantList *this, Variant *data)
|
||||
{
|
||||
lstAdd((List *)this, &data);
|
||||
return this;
|
||||
}
|
||||
|
||||
// Get by index
|
||||
__attribute__((always_inline)) static inline Variant *
|
||||
varLstGet(const VariantList *this, const unsigned int listIdx)
|
||||
{
|
||||
return *(Variant **)lstGet((List *)this, listIdx);
|
||||
}
|
||||
|
||||
// Move to new parent mem context
|
||||
__attribute__((always_inline)) static inline VariantList *
|
||||
varLstMove(VariantList *this, MemContext *parentNew)
|
||||
{
|
||||
return (VariantList *)lstMove((List *)this, parentNew);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void varLstFree(VariantList *this);
|
||||
__attribute__((always_inline)) static inline void
|
||||
varLstFree(VariantList *this)
|
||||
{
|
||||
lstFree((List *)this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
|
@ -122,7 +122,7 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: type-string
|
||||
total: 26
|
||||
total: 25
|
||||
feature: string
|
||||
|
||||
coverage:
|
||||
@ -730,7 +730,7 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: help
|
||||
total: 4
|
||||
total: 5
|
||||
|
||||
coverage:
|
||||
- command/help/help
|
||||
|
@ -72,7 +72,7 @@ harnessCfgLoadRole(ConfigCommand commandId, ConfigCommandRole commandRoleId, con
|
||||
|
||||
// Set job retry to 0 if it is valid
|
||||
if (cfgParseOptionValid(commandId, commandRoleId, cfgOptJobRetry))
|
||||
strLstInsertZ(argList, 0, "--" CFGOPT_JOB_RETRY "=0");
|
||||
strLstInsert(argList, 0, STRDEF("--" CFGOPT_JOB_RETRY "=0"));
|
||||
|
||||
// Set log path if valid
|
||||
if (cfgParseOptionValid(commandId, commandRoleId, cfgOptLogPath))
|
||||
|
@ -192,7 +192,8 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_VOID(expireBackup(infoBackup, full1, 0), "expire backup with both manifest files");
|
||||
TEST_RESULT_BOOL(
|
||||
(strLstSize(storageListP(storageTest, full1Path)) && strLstExistsZ(storageListP(storageTest, full1Path), "bogus")),
|
||||
(strLstSize(storageListP(storageTest, full1Path)) &&
|
||||
strLstExists(storageListP(storageTest, full1Path), STRDEF("bogus"))),
|
||||
true, "full1 - only manifest files removed");
|
||||
|
||||
TEST_RESULT_VOID(expireBackup(infoBackup, full2, 0), "expire backup with no manifest - does not error");
|
||||
|
@ -47,6 +47,23 @@ testRun(void)
|
||||
"Use 'pgbackrest help [command]' for more information.\n",
|
||||
helpVersion));
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("helpRenderSplitSize()"))
|
||||
{
|
||||
TEST_RESULT_STR_Z(strLstJoin(helpRenderSplitSize(STRDEF("abc def"), " ", 3), "-"), "abc-def", "two items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(helpRenderSplitSize(STRDEF("abc def"), " ", 4), "-"), "abc-def", "one items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(helpRenderSplitSize(STRDEF("abc def ghi"), " ", 4), "-"), "abc-def-ghi", "three items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(helpRenderSplitSize(STRDEF("abc def ghi"), " ", 8), "-"), "abc def-ghi", "three items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(helpRenderSplitSize(STRDEF("abc def "), " ", 4), "-"), "abc-def ", "two items");
|
||||
|
||||
TEST_RESULT_STR_Z(
|
||||
strLstJoin(helpRenderSplitSize(STRDEF("this is a short sentence"), " ", 10), "\n"),
|
||||
"this is a\n"
|
||||
"short\n"
|
||||
"sentence",
|
||||
"empty list");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("helpRenderText()"))
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ testRun(void)
|
||||
List *list = lstNewP(sizeof(void *));
|
||||
|
||||
TEST_RESULT_UINT(list->itemSize, sizeof(void *), "item size");
|
||||
TEST_RESULT_UINT(list->listSize, 0, "list size");
|
||||
TEST_RESULT_UINT(list->pub.listSize, 0, "list size");
|
||||
TEST_RESULT_UINT(list->listSizeMax, 0, "list size max");
|
||||
TEST_RESULT_PTR(lstMemContext(list), list->memContext, "list mem context");
|
||||
TEST_RESULT_VOID(lstClear(list), "clear list");
|
||||
@ -130,7 +130,7 @@ testRun(void)
|
||||
TEST_RESULT_VOID(lstAdd(list, &item), "add item %d", item);
|
||||
}
|
||||
|
||||
TEST_RESULT_INT(list->listSize, list->listSizeMax, "size equals max size");
|
||||
TEST_RESULT_UINT(lstSize(list), list->listSizeMax, "size equals max size");
|
||||
|
||||
// Remove last item
|
||||
TEST_RESULT_VOID(lstRemoveLast(list), "remove last item");
|
||||
|
@ -341,8 +341,8 @@ testRun(void)
|
||||
TEST_ASSIGN(list, strLstNew(), "new list");
|
||||
TEST_RESULT_VOID(strLstAddIfMissing(list, STRDEF("item1")), "add item 1");
|
||||
TEST_RESULT_UINT(strLstSize(list), 1, "check size");
|
||||
TEST_RESULT_BOOL(strLstExistsZ(list, "item1"), true, "check exists");
|
||||
TEST_RESULT_BOOL(strLstExistsZ(list, NULL), false, "check null exists");
|
||||
TEST_RESULT_BOOL(strLstExists(list, STRDEF("item1")), true, "check exists");
|
||||
TEST_RESULT_BOOL(strLstExists(list, NULL), false, "check null exists");
|
||||
TEST_RESULT_VOID(strLstAddIfMissing(list, STRDEF("item1")), "add item 1 again");
|
||||
TEST_RESULT_UINT(strLstSize(list), 1, "check size");
|
||||
TEST_RESULT_BOOL(strLstEmpty(list), false, " not empty");
|
||||
@ -361,24 +361,6 @@ testRun(void)
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplit(STRDEF("item1, item2"), STRDEF(", ")), ", "), "item1, item2", "two items");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strLstNewSplitSize()"))
|
||||
{
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplitSize(STRDEF(""), STRDEF(" "), 0), ", "), "", "empty list");
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def"), " ", 3), "-"), "abc-def", "two items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def"), " ", 4), "-"), "abc-def", "one items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def ghi"), " ", 4), "-"), "abc-def-ghi", "three items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def ghi"), " ", 8), "-"), "abc def-ghi", "three items");
|
||||
TEST_RESULT_STR_Z(strLstJoin(strLstNewSplitSizeZ(STRDEF("abc def "), " ", 4), "-"), "abc-def ", "two items");
|
||||
|
||||
TEST_RESULT_STR_Z(
|
||||
strLstJoin(strLstNewSplitSize(STRDEF("this is a short sentence"), STRDEF(" "), 10), "\n"),
|
||||
"this is a\n"
|
||||
"short\n"
|
||||
"sentence",
|
||||
"empty list");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strLstNewVarLst()"))
|
||||
{
|
||||
@ -430,7 +412,7 @@ testRun(void)
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("strLstExists() and strLstExistsZ()"))
|
||||
if (testBegin("strLstExists()"))
|
||||
{
|
||||
StringList *list = strLstNew();
|
||||
strLstAddZ(list, "A");
|
||||
@ -438,8 +420,6 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_BOOL(strLstExists(list, STRDEF("B")), false, "string does not exist");
|
||||
TEST_RESULT_BOOL(strLstExists(list, STRDEF("C")), true, "string exists");
|
||||
TEST_RESULT_BOOL(strLstExistsZ(list, "B"), false, "string does not exist");
|
||||
TEST_RESULT_BOOL(strLstExistsZ(list, "C"), true, "string exists");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
@ -531,11 +511,11 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_STR_Z(strLstToLog(list), "{[]}", "format empty list");
|
||||
|
||||
strLstInsertZ(list, 0, "item3");
|
||||
strLstInsert(list, 0, STRDEF("item3"));
|
||||
TEST_RESULT_STR_Z(strLstToLog(list), "{[\"item3\"]}", "format 1 item list");
|
||||
|
||||
strLstInsert(list, 0, STRDEF("item1"));
|
||||
strLstInsertZ(list, 1, "item2");
|
||||
strLstInsert(list, 1, STRDEF("item2"));
|
||||
TEST_RESULT_STR_Z(strLstToLog(list), "{[\"item1\", \"item2\", \"item3\"]}", "format 3 item list");
|
||||
}
|
||||
|
||||
|
@ -174,8 +174,9 @@ testRun(void)
|
||||
TEST_RESULT_UINT(backupDataPtr->backupInfoSizeDelta, 163866, " backup delta");
|
||||
TEST_RESULT_STR_Z(backupDataPtr->backupPrior, "20161219-212741F", " backup prior exists");
|
||||
TEST_RESULT_BOOL(
|
||||
(strLstSize(backupDataPtr->backupReference) == 1 && strLstExistsZ(backupDataPtr->backupReference, "20161219-212741F")), true,
|
||||
" backup reference exists");
|
||||
(strLstSize(backupDataPtr->backupReference) == 1 &&
|
||||
strLstExists(backupDataPtr->backupReference, STRDEF("20161219-212741F"))),
|
||||
true, " backup reference exists");
|
||||
TEST_RESULT_PTR(infoBackupDataByLabel(infoBackup, STRDEF("20161219-12345")), NULL, " backup label does not exist");
|
||||
|
||||
backupData = infoBackupData(infoBackup, 2);
|
||||
@ -185,8 +186,9 @@ testRun(void)
|
||||
TEST_RESULT_STR_Z(backupData.backupType, "incr", " backup type incr");
|
||||
TEST_RESULT_STR_Z(backupData.backupPrior, "20161219-212741F", " backup prior exists");
|
||||
TEST_RESULT_BOOL(
|
||||
(strLstSize(backupData.backupReference) == 2 && strLstExistsZ(backupData.backupReference, "20161219-212741F") &&
|
||||
strLstExistsZ(backupData.backupReference, "20161219-212741F_20161219-212803D")), true, " backup reference exists");
|
||||
(strLstSize(backupData.backupReference) == 2 && strLstExists(backupData.backupReference, STRDEF("20161219-212741F")) &&
|
||||
strLstExists(backupData.backupReference, STRDEF("20161219-212741F_20161219-212803D"))),
|
||||
true, " backup reference exists");
|
||||
TEST_RESULT_BOOL(backupData.optionArchiveCheck, true, " option archive check");
|
||||
TEST_RESULT_BOOL(backupData.optionArchiveCopy, false, " option archive copy");
|
||||
TEST_RESULT_BOOL(backupData.optionBackupStandby, false, " option backup standby");
|
||||
|
Loading…
Reference in New Issue
Block a user