mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-12 10:04:14 +02:00
Add List and StringList objects to simplify list handling.
This commit is contained in:
parent
1b3e8e0a5b
commit
4d8ad4ac18
@ -26,6 +26,10 @@
|
||||
<release-item>
|
||||
<p>Add <code>String</code> object to simplify string handling.</p>
|
||||
</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-core-list>
|
||||
|
||||
|
@ -32,6 +32,8 @@ typedef int64_t int64;
|
||||
/***********************************************************************************************************************************
|
||||
Include all header files in type directory for convenience
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/type/list.h"
|
||||
#include "common/type/string.h"
|
||||
#include "common/type/stringList.h"
|
||||
|
||||
#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,
|
||||
},
|
||||
},
|
||||
{
|
||||
&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_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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user