1
0
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:
David Steele 2017-11-26 18:23:11 -05:00
parent 1b3e8e0a5b
commit 4d8ad4ac18
8 changed files with 372 additions and 0 deletions

View File

@ -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>

View File

@ -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
View 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
View 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

View 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);
}

View 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

View File

@ -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,

View 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);
}
}