You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-09-16 09:06:18 +02:00
Add List and StringList objects to simplify list handling.
This commit is contained in:
@@ -26,6 +26,10 @@
|
|||||||
<release-item>
|
<release-item>
|
||||||
<p>Add <code>String</code> object to simplify string handling.</p>
|
<p>Add <code>String</code> object to simplify string handling.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<p>Add <code>List</code> and <code>StringList</code> objects to simplify list handling.</p>
|
||||||
|
</release-item>
|
||||||
</release-development-list>
|
</release-development-list>
|
||||||
</release-core-list>
|
</release-core-list>
|
||||||
|
|
||||||
|
@@ -32,6 +32,8 @@ typedef int64_t int64;
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Include all header files in type directory for convenience
|
Include all header files in type directory for convenience
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
#include "common/type/list.h"
|
||||||
#include "common/type/string.h"
|
#include "common/type/string.h"
|
||||||
|
#include "common/type/stringList.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
99
src/common/type/list.c
Normal file
99
src/common/type/list.c
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
List Handler
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common/memContext.h"
|
||||||
|
#include "common/type/list.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Contains information about the list
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
struct List
|
||||||
|
{
|
||||||
|
size_t itemSize;
|
||||||
|
unsigned int listSize;
|
||||||
|
unsigned int listSizeMax;
|
||||||
|
unsigned char *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Create a new list
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
List *
|
||||||
|
lstNew(size_t itemSize)
|
||||||
|
{
|
||||||
|
// Create object
|
||||||
|
List *this = memNew(sizeof(List));
|
||||||
|
this->itemSize = itemSize;
|
||||||
|
|
||||||
|
// Return buffer
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Add an item to the end of the list
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
List *
|
||||||
|
lstAdd(List *this, const void *item)
|
||||||
|
{
|
||||||
|
// If list size = max then allocate more space
|
||||||
|
if (this->listSize == this->listSizeMax)
|
||||||
|
{
|
||||||
|
// If nothing has been allocated yet
|
||||||
|
if (this->listSizeMax == 0)
|
||||||
|
{
|
||||||
|
this->listSizeMax = LIST_INITIAL_SIZE;
|
||||||
|
this->list = memNewRaw(this->listSizeMax * this->itemSize);
|
||||||
|
}
|
||||||
|
// Else the list needs to be extended
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->listSizeMax *= 2;
|
||||||
|
this->list = memGrowRaw(this->list, this->listSize * this->itemSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(this->list + (this->listSize * this->itemSize), item, this->itemSize);
|
||||||
|
this->listSize++;
|
||||||
|
|
||||||
|
// Return list
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Get an item from the list
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void *
|
||||||
|
lstGet(const List *this, unsigned int listIdx)
|
||||||
|
{
|
||||||
|
// Ensure list index is in range
|
||||||
|
if (listIdx >= this->listSize)
|
||||||
|
THROW(AssertError, "cannot get index %d from list with %d value(s)", listIdx, this->listSize);
|
||||||
|
|
||||||
|
// Return pointer to list item
|
||||||
|
return this->list + (listIdx * this->itemSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Return list size
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
unsigned int
|
||||||
|
lstSize(const List *this)
|
||||||
|
{
|
||||||
|
return this->listSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Free the string
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
lstFree(List *this)
|
||||||
|
{
|
||||||
|
if (this->list != NULL)
|
||||||
|
memFree(this->list);
|
||||||
|
|
||||||
|
memFree(this);
|
||||||
|
}
|
28
src/common/type/list.h
Normal file
28
src/common/type/list.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
List Handler
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#ifndef COMMON_TYPE_LIST_H
|
||||||
|
#define COMMON_TYPE_LIST_H
|
||||||
|
|
||||||
|
#include "common/type/string.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Define initial size of a list
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define LIST_INITIAL_SIZE 8
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
List type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct List List;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Functions
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
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);
|
||||||
|
void lstFree(List *this);
|
||||||
|
|
||||||
|
#endif
|
95
src/common/type/stringList.c
Normal file
95
src/common/type/stringList.c
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
String List Handler
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common/memContext.h"
|
||||||
|
#include "common/type/list.h"
|
||||||
|
#include "common/type/stringList.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Wrapper for lstNew()
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
StringList *
|
||||||
|
strLstNew()
|
||||||
|
{
|
||||||
|
return (StringList *)lstNew(sizeof(String *));
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Wrapper for lstAdd()
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
StringList *
|
||||||
|
strLstAdd(StringList *this, String *string)
|
||||||
|
{
|
||||||
|
return (StringList *)lstAdd((List *)this, &string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Wrapper for lstGet()
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
String *
|
||||||
|
strLstGet(const StringList *this, unsigned int listIdx)
|
||||||
|
{
|
||||||
|
return *(String **)lstGet((List *)this, listIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Concatenate a list of strings into a single string using the specified separator
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
String *strLstCat(StringList *this, const char *separator)
|
||||||
|
{
|
||||||
|
String *join = strNew("");
|
||||||
|
|
||||||
|
for (unsigned int listIdx = 0; listIdx < strLstSize(this); listIdx++)
|
||||||
|
{
|
||||||
|
if (listIdx != 0)
|
||||||
|
strCat(join, separator);
|
||||||
|
|
||||||
|
if (strLstGet(this, listIdx) == NULL)
|
||||||
|
strCat(join, "[NULL]");
|
||||||
|
else
|
||||||
|
strCat(join, strPtr(strLstGet(this, listIdx)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return join;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Return an 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)
|
||||||
|
{
|
||||||
|
const char **list = memNew(strLstSize(this) * sizeof(char *));
|
||||||
|
|
||||||
|
for (unsigned int listIdx = 0; listIdx < strLstSize(this); listIdx++)
|
||||||
|
{
|
||||||
|
if (strLstGet(this, listIdx) == NULL)
|
||||||
|
list[listIdx] = NULL;
|
||||||
|
else
|
||||||
|
list[listIdx] = strPtr(strLstGet(this, listIdx));
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Wrapper for lstSize()
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
unsigned int
|
||||||
|
strLstSize(const StringList *this)
|
||||||
|
{
|
||||||
|
return lstSize((List *)this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Wrapper for lstFree()
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void strLstFree(StringList *this)
|
||||||
|
{
|
||||||
|
lstFree((List *)this);
|
||||||
|
}
|
25
src/common/type/stringList.h
Normal file
25
src/common/type/stringList.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
String List Handler
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#ifndef COMMON_TYPE_STRING_LIST_H
|
||||||
|
#define COMMON_TYPE_STRING_LIST_H
|
||||||
|
|
||||||
|
#include "common/type/string.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
String list type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct StringList StringList;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Functions
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
StringList *strLstNew();
|
||||||
|
StringList *strLstAdd(StringList *this, String *string);
|
||||||
|
String *strLstGet(const StringList *this, unsigned int listIdx);
|
||||||
|
String *strLstCat(StringList *this, const char *separator);
|
||||||
|
const char **strLstPtr(const StringList *this);
|
||||||
|
unsigned int strLstSize(const StringList *this);
|
||||||
|
void strLstFree(StringList *this);
|
||||||
|
|
||||||
|
#endif
|
@@ -125,6 +125,17 @@ my $oTestDef =
|
|||||||
'common/memContext' => TESTDEF_COVERAGE_FULL,
|
'common/memContext' => TESTDEF_COVERAGE_FULL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
&TESTDEF_NAME => 'type-list',
|
||||||
|
&TESTDEF_TOTAL => 3,
|
||||||
|
&TESTDEF_C => true,
|
||||||
|
|
||||||
|
&TESTDEF_COVERAGE =>
|
||||||
|
{
|
||||||
|
'common/type/list' => TESTDEF_COVERAGE_FULL,
|
||||||
|
'common/type/stringList' => TESTDEF_COVERAGE_FULL,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
&TESTDEF_NAME => 'type-string',
|
&TESTDEF_NAME => 'type-string',
|
||||||
&TESTDEF_TOTAL => 2,
|
&TESTDEF_TOTAL => 2,
|
||||||
|
108
test/src/module/common/typeListTest.c
Normal file
108
test/src/module/common/typeListTest.c
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Test Lists
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Test Run
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void testRun()
|
||||||
|
{
|
||||||
|
// *****************************************************************************************************************************
|
||||||
|
if (testBegin("lstNew() and lstFree()"))
|
||||||
|
{
|
||||||
|
List *list = lstNew(sizeof(void *));
|
||||||
|
|
||||||
|
TEST_RESULT_INT(list->itemSize, sizeof(void *), "item size");
|
||||||
|
TEST_RESULT_INT(list->listSize, 0, "list size");
|
||||||
|
TEST_RESULT_INT(list->listSizeMax, 0, "list size max");
|
||||||
|
|
||||||
|
void *ptr = NULL;
|
||||||
|
TEST_RESULT_PTR(lstAdd(list, &ptr), list, "add item");
|
||||||
|
|
||||||
|
lstFree(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// *****************************************************************************************************************************
|
||||||
|
if (testBegin("lstAdd() and lstSize()"))
|
||||||
|
{
|
||||||
|
List *list = lstNew(sizeof(int));
|
||||||
|
|
||||||
|
// Add ints to the list
|
||||||
|
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
|
||||||
|
TEST_RESULT_PTR(lstAdd(list, &listIdx), list, "add item %d", listIdx);
|
||||||
|
|
||||||
|
TEST_RESULT_INT(lstSize(list), 9, "list size");
|
||||||
|
|
||||||
|
// Read them back and check values
|
||||||
|
for (unsigned int listIdx = 0; listIdx < lstSize(list); listIdx++)
|
||||||
|
{
|
||||||
|
int *item = lstGet(list, listIdx);
|
||||||
|
TEST_RESULT_INT(*item, listIdx, "check item %d", listIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_ERROR(lstGet(list, lstSize(list)), AssertError, "cannot get index 9 from list with 9 value(s)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// *****************************************************************************************************************************
|
||||||
|
if (testBegin("StringList"))
|
||||||
|
{
|
||||||
|
StringList *list = strLstNew();
|
||||||
|
|
||||||
|
// Add strings to the list
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
|
||||||
|
{
|
||||||
|
if (listIdx == 0)
|
||||||
|
{
|
||||||
|
TEST_RESULT_PTR(strLstAdd(list, NULL), list, "add null item");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TEST_RESULT_PTR(strLstAdd(list, strNewFmt("STR%02d", listIdx)), list, "add item %d", listIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_RESULT_INT(strLstSize(list), 9, "list size");
|
||||||
|
|
||||||
|
// Read them back and check values
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
for (unsigned int listIdx = 0; listIdx < strLstSize(list); listIdx++)
|
||||||
|
{
|
||||||
|
if (listIdx == 0)
|
||||||
|
{
|
||||||
|
TEST_RESULT_PTR(strLstGet(list, listIdx), NULL, "check null item");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TEST_RESULT_STR(strPtr(strLstGet(list, listIdx)), strPtr(strNewFmt("STR%02d", listIdx)), "check item %d", listIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check pointer
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
const char **szList = strLstPtr(list);
|
||||||
|
|
||||||
|
for (unsigned int listIdx = 0; listIdx < strLstSize(list); listIdx++)
|
||||||
|
{
|
||||||
|
if (listIdx == 0)
|
||||||
|
{
|
||||||
|
TEST_RESULT_PTR(szList[listIdx], NULL, "check null item");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TEST_RESULT_STR(szList[listIdx], strPtr(strNewFmt("STR%02d", listIdx)), "check item %d", listIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// strLstCat()
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
list = strLstNew();
|
||||||
|
|
||||||
|
TEST_RESULT_STR(strPtr(strLstCat(list, ", ")), "", "empty list");
|
||||||
|
|
||||||
|
strLstAdd(list, strNew("item1"));
|
||||||
|
strLstAdd(list, strNew("item2"));
|
||||||
|
|
||||||
|
TEST_RESULT_STR(strPtr(strLstCat(list, ", ")), "item1, item2", "empty list");
|
||||||
|
|
||||||
|
strLstAdd(list, NULL);
|
||||||
|
|
||||||
|
TEST_RESULT_STR(strPtr(strLstCat(list, ", ")), "item1, item2, [NULL]", "empty list");
|
||||||
|
|
||||||
|
strLstFree(list);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user