1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2026-05-22 10:15:16 +02:00

Allow MemContext objects to be copied to a new parent.

This makes it easier to create objects and then copy them to another context when they are complete without having to worry about freeing them on error. Update List, StringList, and Buffer to allow moves. Update Ini and Storage to take advantage of moves.
This commit is contained in:
David Steele
2018-04-06 17:04:52 -04:00
parent b9f636cab4
commit f3b56cf8f3
17 changed files with 443 additions and 240 deletions
+4
View File
@@ -39,6 +39,10 @@
<p>Storage object improvements. Convert all functions to variadic functions. Enforce read-only storage. Add <code>storageLocalWrite()</code> helper function. Add <code>storageExists()</code>, <code>storagePathCreate()</code>, and <code>storageRemove()</code>. Add <code>StorageFile</code> object and <code>storageOpenRead()</code>/<code>storageOpenWrite()</code>. Abstract Posix driver code into a separate module.</p>
</release-item>
<release-item>
<p>Allow <code>MemContext</code> objects to be copied to a new parent. This makes it easier to create objects and then copy them to another context when they are complete without having to worry about freeing them on error. Update <code>List</code>, <code>StringList</code>, and <code>Buffer</code> to allow moves. Update <code>Ini</code> and <code>Storage</code> to take advantage of moves.</p>
</release-item>
<release-item>
<p>Improve branch coverage in C code.</p>
</release-item>
+1 -3
View File
@@ -110,8 +110,6 @@ iniSectionKeyList(const Ini *this, const String *section)
// Get the section
KeyValue *sectionKv = varKv(kvGet(this->store, varNewStr(section)));
memContextSwitch(MEM_CONTEXT_OLD());
// Return key list of the section exists
if (sectionKv != NULL)
result = strLstNewVarLst(kvKeyList(sectionKv));
@@ -119,7 +117,7 @@ iniSectionKeyList(const Ini *this, const String *section)
else
result = strLstNew();
memContextSwitch(MEM_CONTEXT_TEMP());
strLstMove(result, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
+91 -37
View File
@@ -4,6 +4,7 @@ Memory Context Manager
#include <stdlib.h>
#include <string.h>
#include "common/debug.h"
#include "common/error.h"
#include "common/memContext.h"
@@ -113,6 +114,55 @@ memFreeInternal(void *buffer)
free(buffer);
}
/***********************************************************************************************************************************
Find space for a new mem context
***********************************************************************************************************************************/
static unsigned int
memContextNewIndex(MemContext *memContext, bool allowFree)
{
// Try to find space for the new context
unsigned int contextIdx;
for (contextIdx = 0; contextIdx < memContext->contextChildListSize; contextIdx++)
{
if (!memContext->contextChildList[contextIdx] ||
(allowFree && memContext->contextChildList[contextIdx]->state == memContextStateFree))
{
break;
}
}
// If no space was found then allocate more
if (contextIdx == memContext->contextChildListSize)
{
// If no space has been allocated to the list
if (memContext->contextChildListSize == 0)
{
// Allocate memory before modifying anything else in case there is an error
memContext->contextChildList = memAllocInternal(sizeof(MemContext *) * MEM_CONTEXT_INITIAL_SIZE, true);
// Set new list size
memContext->contextChildListSize = MEM_CONTEXT_INITIAL_SIZE;
}
// Else grow the list
else
{
// Calculate new list size
unsigned int contextChildListSizeNew = memContext->contextChildListSize * 2;
// ReAllocate memory before modifying anything else in case there is an error
memContext->contextChildList = memReAllocInternal(
memContext->contextChildList, sizeof(MemContext *) * memContext->contextChildListSize,
sizeof(MemContext *) * contextChildListSizeNew, true);
// Set new list size
memContext->contextChildListSize = contextChildListSizeNew;
}
}
return contextIdx;
}
/***********************************************************************************************************************************
Create a new memory context
***********************************************************************************************************************************/
@@ -123,43 +173,8 @@ memContextNew(const char *name)
if (strlen(name) == 0 || strlen(name) > MEM_CONTEXT_NAME_SIZE)
THROW(AssertError, "context name length must be > 0 and <= %d", MEM_CONTEXT_NAME_SIZE);
// Try to find space for the new context
unsigned int contextIdx;
for (contextIdx = 0; contextIdx < memContextCurrent()->contextChildListSize; contextIdx++)
if (!memContextCurrent()->contextChildList[contextIdx] ||
memContextCurrent()->contextChildList[contextIdx]->state == memContextStateFree)
{
break;
}
// If no space was found then allocate more
if (contextIdx == memContextCurrent()->contextChildListSize)
{
// If no space has been allocated to the list
if (memContextCurrent()->contextChildListSize == 0)
{
// Allocate memory before modifying anything else in case there is an error
memContextCurrent()->contextChildList = memAllocInternal(sizeof(MemContext *) * MEM_CONTEXT_INITIAL_SIZE, true);
// Set new list size
memContextCurrent()->contextChildListSize = MEM_CONTEXT_INITIAL_SIZE;
}
// Else grow the list
else
{
// Calculate new list size
unsigned int contextChildListSizeNew = memContextCurrent()->contextChildListSize * 2;
// ReAllocate memory before modifying anything else in case there is an error
memContextCurrent()->contextChildList = memReAllocInternal(
memContextCurrent()->contextChildList, sizeof(MemContext *) * memContextCurrent()->contextChildListSize,
sizeof(MemContext *) * contextChildListSizeNew, true);
// Set new list size
memContextCurrent()->contextChildListSize = contextChildListSizeNew;
}
}
// Find space for the new context
unsigned int contextIdx = memContextNewIndex(memContextCurrent(), true);
// If the context has not been allocated yet
if (!memContextCurrent()->contextChildList[contextIdx])
@@ -330,6 +345,45 @@ memFree(void *buffer)
alloc->active = false;
}
/***********************************************************************************************************************************
Move a context to a new parent context
This is generally used to move objects to a new context once they have been successfully created.
***********************************************************************************************************************************/
void
memContextMove(MemContext *this, MemContext *parentNew)
{
// Only move if a valid mem context is provided
if (this != NULL)
{
// Find context in the old parent and NULL it out
MemContext *parentOld = this->contextParent;
unsigned int contextIdx;
for (contextIdx = 0; contextIdx < parentOld->contextChildListSize; contextIdx++)
{
if (parentOld->contextChildList[contextIdx] == this)
{
parentOld->contextChildList[contextIdx] = NULL;
break;
}
}
// The memory must be found
if (contextIdx == parentOld->contextChildListSize)
THROW(AssertError, "unable to find mem context in old parent");
// Find a place in the new parent context and assign it. The child list may be moved while finding a new index so store the
// index and use it with (what might be) the new pointer.
contextIdx = memContextNewIndex(parentNew, false);
ASSERT_DEBUG(parentNew->contextChildList[contextIdx] == NULL);
parentNew->contextChildList[contextIdx] = this;
// Assign new parent
this->contextParent = parentNew;
}
}
/***********************************************************************************************************************************
Switch to the specified context and return the old context
***********************************************************************************************************************************/
+1
View File
@@ -63,6 +63,7 @@ TRY_END();
Use the MEM_CONTEXT*() macros when possible rather than implement error-handling for every memory context block.
***********************************************************************************************************************************/
MemContext *memContextNew(const char *name);
void memContextMove(MemContext *this, MemContext *parentNew);
void memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *callbackArgument);
MemContext *memContextSwitch(MemContext *this);
void memContextFree(MemContext *this);
+26 -18
View File
@@ -3,7 +3,6 @@ String Handler
***********************************************************************************************************************************/
#include <string.h>
#include "common/memContext.h"
#include "common/type/buffer.h"
/***********************************************************************************************************************************
@@ -22,14 +21,20 @@ Create a new buffer
Buffer *
bufNew(size_t size)
{
// Create object
Buffer *this = memNew(sizeof(Buffer));
this->memContext = memContextCurrent();
this->size = size;
Buffer *this = NULL;
// Allocate buffer
if (size > 0)
this->buffer = memNewRaw(this->size);
MEM_CONTEXT_NEW_BEGIN("Buffer")
{
// Create object
this = memNew(sizeof(Buffer));
this->memContext = MEM_CONTEXT_NEW();
this->size = size;
// Allocate buffer
if (size > 0)
this->buffer = memNewRaw(this->size);
}
MEM_CONTEXT_NEW_END();
return this;
}
@@ -49,6 +54,18 @@ bufNewStr(const String *string)
return this;
}
/***********************************************************************************************************************************
Move buffer to a new mem context
***********************************************************************************************************************************/
Buffer *
bufMove(Buffer *this, MemContext *parentNew)
{
if (this != NULL)
memContextMove(this->memContext, parentNew);
return this;
}
/***********************************************************************************************************************************
Return buffer ptr
***********************************************************************************************************************************/
@@ -113,14 +130,5 @@ void
bufFree(Buffer *this)
{
if (this != NULL)
{
MEM_CONTEXT_BEGIN(this->memContext)
{
if (this->buffer != NULL)
memFree(this->buffer);
memFree(this);
}
MEM_CONTEXT_END();
}
memContextFree(this->memContext);
}
+4 -4
View File
@@ -4,20 +4,20 @@ Buffer Handler
#ifndef COMMON_TYPE_BUFFER_H
#define COMMON_TYPE_BUFFER_H
#include "common/typec.h"
/***********************************************************************************************************************************
Buffer object
***********************************************************************************************************************************/
typedef struct Buffer Buffer;
#include "common/memContext.h"
#include "common/type/string.h"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
#include "common/type/string.h"
Buffer *bufNew(size_t size);
Buffer *bufNewStr(const String *string);
Buffer *bufMove(Buffer *this, MemContext *parentNew);
Buffer *bufResize(Buffer *this, size_t size);
size_t bufSize(const Buffer *this);
unsigned char *bufPtr(const Buffer *this);
+48 -18
View File
@@ -5,7 +5,6 @@ List Handler
#include <stdlib.h>
#include <string.h>
#include "common/memContext.h"
#include "common/type/list.h"
/***********************************************************************************************************************************
@@ -13,6 +12,7 @@ Contains information about the list
***********************************************************************************************************************************/
struct List
{
MemContext *memContext;
size_t itemSize;
unsigned int listSize;
unsigned int listSizeMax;
@@ -25,9 +25,16 @@ Create a new list
List *
lstNew(size_t itemSize)
{
// Create object
List *this = memNew(sizeof(List));
this->itemSize = itemSize;
List *this = NULL;
MEM_CONTEXT_NEW_BEGIN("List")
{
// Create object
this = memNew(sizeof(List));
this->memContext = MEM_CONTEXT_NEW();
this->itemSize = itemSize;
}
MEM_CONTEXT_NEW_END();
// Return buffer
return this;
@@ -42,18 +49,22 @@ 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)
MEM_CONTEXT_BEGIN(this->memContext)
{
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->listSizeMax * this->itemSize);
// 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->listSizeMax * this->itemSize);
}
}
MEM_CONTEXT_END();
}
memcpy(this->list + (this->listSize * this->itemSize), item, this->itemSize);
@@ -77,6 +88,27 @@ lstGet(const List *this, unsigned int listIdx)
return this->list + (listIdx * this->itemSize);
}
/***********************************************************************************************************************************
Return the memory context for this list
***********************************************************************************************************************************/
MemContext *
lstMemContext(const List *this)
{
return this->memContext;
}
/***********************************************************************************************************************************
Move the string list
***********************************************************************************************************************************/
List *
lstMove(List *this, MemContext *parentNew)
{
if (this != NULL)
memContextMove(this->memContext, parentNew);
return this;
}
/***********************************************************************************************************************************
Return list size
***********************************************************************************************************************************/
@@ -103,8 +135,6 @@ Free the string
void
lstFree(List *this)
{
if (this->list != NULL)
memFree(this->list);
memFree(this);
if (this != NULL)
memContextFree(this->memContext);
}
+3
View File
@@ -4,6 +4,7 @@ List Handler
#ifndef COMMON_TYPE_LIST_H
#define COMMON_TYPE_LIST_H
#include "common/memContext.h"
#include "common/type/string.h"
/***********************************************************************************************************************************
@@ -22,6 +23,8 @@ Functions
List *lstNew(size_t itemSize);
List *lstAdd(List *this, const void *item);
void *lstGet(const List *this, unsigned int listIdx);
MemContext *lstMemContext(const List *this);
List *lstMove(List *this, MemContext *parentNew);
unsigned int lstSize(const List *this);
List *lstSort(List *this, int (*comparator)(const void *, const void*));
void lstFree(List *this);
+95 -46
View File
@@ -18,6 +18,15 @@ strLstNew()
return (StringList *)lstNew(sizeof(String *));
}
/***********************************************************************************************************************************
Internal add -- the string must have been created in the list's mem context before being passed
***********************************************************************************************************************************/
static StringList *
strLstAddInternal(StringList *this, String *string)
{
return (StringList *)lstAdd((List *)this, &string);
}
/***********************************************************************************************************************************
Split a string into a string list based on a delimiter
***********************************************************************************************************************************/
@@ -39,22 +48,26 @@ strLstNewSplitZ(const String *string, const char *delimiter)
// Match points to the next delimiter match that has been found
const char *stringMatch = NULL;
do
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
{
// Find a delimiter match
stringMatch = strstr(stringBase, delimiter);
// If a match was found then add the string
if (stringMatch != NULL)
do
{
strLstAdd(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
stringBase = stringMatch + strlen(delimiter);
// Find a delimiter match
stringMatch = strstr(stringBase, delimiter);
// If a match was found then add the string
if (stringMatch != NULL)
{
strLstAddInternal(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
stringBase = stringMatch + strlen(delimiter);
}
// Else make whatever is left the last string
else
strLstAddInternal(this, strNew(stringBase));
}
// Else make whatever is left the last string
else
strLstAdd(this, strNew(stringBase));
while(stringMatch != NULL);
}
while(stringMatch != NULL);
MEM_CONTEXT_END();
return this;
}
@@ -84,39 +97,43 @@ strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
const char *stringMatchLast = NULL;
const char *stringMatch = NULL;
do
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
{
// Find a delimiter match
stringMatch = strstr(stringMatchLast == NULL ? stringBase : stringMatchLast, delimiter);
// If a match was found then add the string
if (stringMatch != NULL)
do
{
if ((size_t)(stringMatch - stringBase) >= size)
{
if (stringMatchLast != NULL)
stringMatch = stringMatchLast - strlen(delimiter);
// Find a delimiter match
stringMatch = strstr(stringMatchLast == NULL ? stringBase : stringMatchLast, delimiter);
strLstAdd(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
stringBase = stringMatch + strlen(delimiter);
stringMatchLast = NULL;
// 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
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;
}
if (stringMatchLast != NULL && strlen(stringBase) - strlen(delimiter) >= size)
{
strLstAddInternal(this, strNewN(stringBase, (size_t)((stringMatchLast - strlen(delimiter)) - stringBase)));
stringBase = stringMatchLast;
}
strLstAdd(this, strNew(stringBase));
strLstAddInternal(this, strNew(stringBase));
}
}
while(stringMatch != NULL);
}
while(stringMatch != NULL);
MEM_CONTEXT_END();
return this;
}
@@ -131,8 +148,12 @@ strLstNewVarLst(const VariantList *sourceList)
StringList *this = strLstNew();
// Copy variants
for (unsigned int listIdx = 0; listIdx < varLstSize(sourceList); listIdx++)
strLstAdd(this, varStr(varLstGet(sourceList, listIdx)));
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
{
for (unsigned int listIdx = 0; listIdx < varLstSize(sourceList); listIdx++)
strLstAddInternal(this, strDup(varStr(varLstGet(sourceList, listIdx))));
}
MEM_CONTEXT_END();
return this;
}
@@ -146,9 +167,13 @@ strLstDup(const StringList *sourceList)
// Create the list
StringList *this = strLstNew();
// Copy variants
for (unsigned int listIdx = 0; listIdx < strLstSize(sourceList); listIdx++)
strLstAdd(this, strLstGet(sourceList, listIdx));
// Copy strings
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
{
for (unsigned int listIdx = 0; listIdx < strLstSize(sourceList); listIdx++)
strLstAddInternal(this, strDup(strLstGet(sourceList, listIdx)));
}
MEM_CONTEXT_END();
return this;
}
@@ -159,8 +184,15 @@ Wrapper for lstAdd()
StringList *
strLstAdd(StringList *this, const String *string)
{
String *stringCopy = strDup(string);
return (StringList *)lstAdd((List *)this, &stringCopy);
StringList *result = NULL;
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
{
result = strLstAddInternal(this, strDup(string));
}
MEM_CONTEXT_END();
return result;
}
/***********************************************************************************************************************************
@@ -169,7 +201,15 @@ Add a zero-terminated string to the list
StringList *
strLstAddZ(StringList *this, const char *string)
{
return strLstAdd(this, strNew(string));
StringList *result = NULL;
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
{
result = strLstAddInternal(this, strNew(string));
}
MEM_CONTEXT_END();
return result;
}
/***********************************************************************************************************************************
@@ -203,6 +243,16 @@ strLstJoin(const StringList *this, const char *separator)
return join;
}
/***********************************************************************************************************************************
Move the string list
***********************************************************************************************************************************/
StringList *
strLstMove(StringList *this, MemContext *parentNew)
{
lstMove((List *)this, parentNew);
return this;
}
/***********************************************************************************************************************************
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.
@@ -273,6 +323,5 @@ Wrapper for lstFree()
void
strLstFree(StringList *this)
{
if (this != NULL)
lstFree((List *)this);
lstFree((List *)this);
}
+8 -7
View File
@@ -4,7 +4,10 @@ String List Handler
#ifndef COMMON_TYPE_STRINGLIST_H
#define COMMON_TYPE_STRINGLIST_H
#include "common/type/string.h"
/***********************************************************************************************************************************
String list type
***********************************************************************************************************************************/
typedef struct StringList StringList;
/***********************************************************************************************************************************
Sort orders
@@ -15,16 +18,13 @@ typedef enum
sortOrderDesc,
} SortOrder;
/***********************************************************************************************************************************
String list type
***********************************************************************************************************************************/
typedef struct StringList StringList;
#include "common/memContext.h"
#include "common/type/string.h"
#include "common/type/variantList.h"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
#include "common/type/variantList.h"
StringList *strLstNew();
StringList *strLstNewSplit(const String *string, const String *delimiter);
StringList *strLstNewSplitZ(const String *string, const char *delimiter);
@@ -37,6 +37,7 @@ StringList *strLstAdd(StringList *this, const String *string);
StringList *strLstAddZ(StringList *this, const char *string);
String *strLstGet(const StringList *this, unsigned int listIdx);
String *strLstJoin(const StringList *this, const char *separator);
StringList * strLstMove(StringList *this, MemContext *parentNew);
const char **strLstPtr(const StringList *this);
unsigned int strLstSize(const StringList *this);
StringList *strLstSort(StringList *this, SortOrder sortOrder);
+59 -68
View File
@@ -54,56 +54,53 @@ Read from storage into a buffer
Buffer *
storageDriverPosixGet(const StorageFile *file)
{
Buffer volatile *result = NULL;
Buffer *result = NULL;
TRY_BEGIN()
MEM_CONTEXT_TEMP_BEGIN()
{
// Create result buffer with buffer size
ssize_t actualBytes = 0;
size_t totalBytes = 0;
do
TRY_BEGIN()
{
size_t bufferSize = storageBufferSize(storageFileStorage(file));
result = bufNew(bufferSize);
// Allocate the buffer before first read
if (result == NULL)
result = bufNew(bufferSize);
// Grow the buffer on subsequent reads
else
bufResize((Buffer *)result, bufSize((Buffer *)result) + bufferSize);
// Create result buffer with buffer size
ssize_t actualBytes = 0;
size_t totalBytes = 0;
// Read and handle errors
actualBytes = read(
STORAGE_DATA(file)->handle, bufPtr((Buffer *)result) + totalBytes, bufferSize);
do
{
// Grow the buffer on subsequent reads
if (totalBytes != 0)
bufResize(result, bufSize(result) + bufferSize);
// Error occurred during write
if (actualBytes == -1)
THROW_SYS_ERROR(FileReadError, "unable to read '%s'", strPtr(storageFileName(file)));
// Read and handle errors
actualBytes = read(
STORAGE_DATA(file)->handle, bufPtr(result) + totalBytes, bufferSize);
// Track total bytes read
totalBytes += (size_t)actualBytes;
// Error occurred during write
if (actualBytes == -1)
THROW_SYS_ERROR(FileReadError, "unable to read '%s'", strPtr(storageFileName(file)));
// Track total bytes read
totalBytes += (size_t)actualBytes;
}
while (actualBytes != 0);
// Resize buffer to total bytes read
bufResize(result, totalBytes);
}
while (actualBytes != 0);
FINALLY()
{
close(STORAGE_DATA(file)->handle);
storageFileFree(file);
}
TRY_END();
// Resize buffer to total bytes read
bufResize((Buffer *)result, totalBytes);
bufMove(result, MEM_CONTEXT_OLD());
}
CATCH_ANY()
{
// Free buffer on error if it was allocated
bufFree((Buffer *)result);
MEM_CONTEXT_TEMP_END();
RETHROW();
}
FINALLY()
{
close(STORAGE_DATA(file)->handle);
storageFileFree(file);
}
TRY_END();
return (Buffer *)result;
return result;
}
/***********************************************************************************************************************************
@@ -113,9 +110,7 @@ StringList *
storageDriverPosixList(const String *path, bool errorOnMissing, const String *expression)
{
StringList *result = NULL;
DIR *dir = NULL;
RegExp *regExp = NULL;
TRY_BEGIN()
{
@@ -130,44 +125,40 @@ storageDriverPosixList(const String *path, bool errorOnMissing, const String *ex
}
else
{
// Prepare regexp if an expression was passed
if (expression != NULL)
regExp = regExpNew(expression);
// Create the string list now that we know the directory is valid
result = strLstNew();
// Read the directory entries
struct dirent *dirEntry = readdir(dir);
while (dirEntry != NULL)
MEM_CONTEXT_TEMP_BEGIN()
{
String *entry = strNew(dirEntry->d_name);
// Prepare regexp if an expression was passed
RegExp *regExp = (expression == NULL) ? NULL : regExpNew(expression);
// Create the string list now that we know the directory is valid
result = strLstNew();
// Read the directory entries
struct dirent *dirEntry = readdir(dir);
while (dirEntry != NULL)
{
String *entry = strNew(dirEntry->d_name);
// Exclude current/parent directory and apply the expression if specified
if (!strEqZ(entry, ".") && !strEqZ(entry, "..") && (regExp == NULL || regExpMatch(regExp, entry)))
strLstAdd(result, entry);
// Exclude current/parent directory and apply the expression if specified
if (!strEqZ(entry, ".") && !strEqZ(entry, "..") && (regExp == NULL || regExpMatch(regExp, entry)))
strLstAdd(result, entry);
else
strFree(entry);
dirEntry = readdir(dir);
}
}
}
CATCH_ANY()
{
// Free list on error
strLstFree(result);
dirEntry = readdir(dir);
}
RETHROW();
// Move finished list up to the old context
strLstMove(result, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
}
}
FINALLY()
{
if (dir != NULL)
closedir(dir);
if (regExp != NULL)
regExpFree(regExp);
}
TRY_END();
+8 -20
View File
@@ -123,21 +123,15 @@ storageList(const Storage *this, const String *pathExp, StorageListParam param)
{
StringList *result = NULL;
String *path = NULL;
TRY_BEGIN()
MEM_CONTEXT_TEMP_BEGIN()
{
// Build the path
path = storagePathNP(this, pathExp);
String *path = storagePathNP(this, pathExp);
// Call driver function
result = storageDriverPosixList(path, param.errorOnMissing, param.expression);
// Move list up to the old context
result = strLstMove(storageDriverPosixList(path, param.errorOnMissing, param.expression), MEM_CONTEXT_OLD());
}
FINALLY()
{
strFree(path);
}
TRY_END();
MEM_CONTEXT_TEMP_END();
return result;
}
@@ -151,7 +145,7 @@ storageOpenRead(const Storage *this, const String *fileExp, StorageOpenReadParam
{
StorageFile *result = NULL;
MEM_CONTEXT_NEW_BEGIN("StorageFileRead")
MEM_CONTEXT_NEW_BEGIN("StorageFile")
{
String *fileName = storagePathNP(this, fileExp);
@@ -159,13 +153,7 @@ storageOpenRead(const Storage *this, const String *fileExp, StorageOpenReadParam
void *data = storageDriverPosixOpenRead(fileName, param.ignoreMissing);
// Free mem contexts if missing files are ignored
if (data == NULL)
{
memContextSwitch(MEM_CONTEXT_OLD());
memContextFree(MEM_CONTEXT_NEW());
}
// Else create the storage file
else
if (data != NULL)
result = storageFileNew(this, fileName, storageFileTypeRead, data);
}
MEM_CONTEXT_NEW_END();
@@ -183,7 +171,7 @@ storageOpenWrite(const Storage *this, const String *fileExp, StorageOpenWritePar
StorageFile *result = NULL;
MEM_CONTEXT_NEW_BEGIN("StorageFileWrite")
MEM_CONTEXT_NEW_BEGIN("StorageFile")
{
String *fileName = storagePathNP(this, fileExp);
+1 -1
View File
@@ -135,7 +135,7 @@ my $oTestDef =
},
{
&TESTDEF_NAME => 'mem-context',
&TESTDEF_TOTAL => 6,
&TESTDEF_TOTAL => 7,
&TESTDEF_C => true,
&TESTDEF_CDEF => '-DNO_MEM_CONTEXT -DNO_LOG',
+51 -2
View File
@@ -91,8 +91,6 @@ testRun()
TEST_RESULT_INT(memContextTop()->contextChildListSize, 0, "top context should init with zero children");
TEST_RESULT_PTR(memContextTop()->contextChildList, NULL, "top context child list empty");
// TEST_ERROR(memContextFree(memContextTop()), AssertError, "cannot free top context");
// Current context should equal top context
TEST_RESULT_PTR(memContextCurrent(), memContextTop(), "top context == current context");
@@ -156,6 +154,11 @@ testRun()
TEST_ERROR(
memContextFree(memContextTop()->contextChildList[MEM_CONTEXT_INITIAL_SIZE]),
AssertError, "cannot free inactive context");
MemContext *noAllocation = memContextNew("empty");
noAllocation->allocListSize = 0;
free(noAllocation->allocList);
TEST_RESULT_VOID(memContextFree(noAllocation), "free context with no allocations");
}
// -----------------------------------------------------------------------------------------------------------------------------
@@ -201,6 +204,11 @@ testRun()
TEST_RESULT_INT(expectedTotal, sizeof(size_t), "all bytes are 0xFE in original portion");
// Free memory
TEST_RESULT_VOID(memFree(memContextCurrent()->allocList[MEM_CONTEXT_ALLOC_INITIAL_SIZE].buffer), "free allocation");
TEST_ERROR(
memFree(memContextCurrent()->allocList[MEM_CONTEXT_ALLOC_INITIAL_SIZE].buffer), AssertError,
"unable to find allocation");
TEST_ERROR(memFree(NULL), AssertError, "unable to find null allocation");
TEST_ERROR(memFree((void *)0x01), AssertError, "unable to find allocation");
memFree(buffer);
@@ -298,5 +306,46 @@ testRun()
TEST_RESULT_BOOL(memContext->state == memContextStateFree, true, "new mem context is not active");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("memContextMove()"))
{
TEST_RESULT_VOID(memContextMove(NULL, NULL), "move NULL context");
// -------------------------------------------------------------------------------------------------------------------------
MemContext *memContext = NULL;
void *mem = NULL;
MEM_CONTEXT_NEW_BEGIN("outer")
{
MEM_CONTEXT_TEMP_BEGIN()
{
memContextNew("not-to-be-moved");
MEM_CONTEXT_NEW_BEGIN("inner")
{
memContext = MEM_CONTEXT_NEW();
mem = memNew(sizeof(int));
}
MEM_CONTEXT_NEW_END();
TEST_RESULT_PTR(memContext->allocList[0].buffer, mem, "check memory allocation");
TEST_RESULT_PTR(memContextCurrent()->contextChildList[1], memContext, "check memory context");
// Null out the mem context in the parent so the move will fail
memContextCurrent()->contextChildList[1] = NULL;
TEST_ERROR(memContextMove(memContext, MEM_CONTEXT_OLD()), AssertError, "unable to find mem context in old parent");
// Set it back so the move will fail
memContextCurrent()->contextChildList[1] = memContext;
TEST_RESULT_VOID(memContextMove(memContext, MEM_CONTEXT_OLD()), "move context");
}
MEM_CONTEXT_TEMP_END();
TEST_RESULT_PTR(memContext->allocList[0].buffer, mem, "check memory allocation");
TEST_RESULT_PTR(memContextCurrent()->contextChildList[1], memContext, "check memory context");
}
MEM_CONTEXT_NEW_END();
}
memContextFree(memContextTop());
}
+10 -2
View File
@@ -9,11 +9,17 @@ void
testRun()
{
// *****************************************************************************************************************************
if (testBegin("bufNew(), bufNewStr(), bufSize(), bufPtr(), and bufFree()"))
if (testBegin("bufNew(), bufNewStr(), bufMove(), bufSize(), bufPtr(), and bufFree()"))
{
Buffer *buffer = NULL;
TEST_ASSIGN(buffer, bufNew(256), "new buffer");
MEM_CONTEXT_TEMP_BEGIN()
{
TEST_ASSIGN(buffer, bufNew(256), "new buffer");
bufMove(buffer, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
TEST_RESULT_PTR(bufPtr(buffer), buffer->buffer, "buffer pointer");
TEST_RESULT_INT(bufSize(buffer), 256, "buffer size");
@@ -23,6 +29,8 @@ testRun()
TEST_RESULT_VOID(bufFree(buffer), "free buffer");
TEST_RESULT_VOID(bufFree(bufNew(0)), "free empty buffer");
TEST_RESULT_VOID(bufFree(NULL), "free null buffer");
TEST_RESULT_VOID(bufMove(NULL, NULL), "move null buffer");
}
// *****************************************************************************************************************************
+17 -6
View File
@@ -27,29 +27,39 @@ void
testRun()
{
// *****************************************************************************************************************************
if (testBegin("lstNew() and lstFree()"))
if (testBegin("lstNew(), lstMemContext(), 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");
TEST_RESULT_PTR(lstMemContext(list), list->memContext, "list mem context");
void *ptr = NULL;
TEST_RESULT_PTR(lstAdd(list, &ptr), list, "add item");
TEST_RESULT_VOID(lstFree(list), "free list");
TEST_RESULT_VOID(lstFree(lstNew(1)), "free empty list");
TEST_RESULT_VOID(lstFree(NULL), "free null list");
}
// *****************************************************************************************************************************
if (testBegin("lstAdd() and lstSize()"))
if (testBegin("lstAdd(), lstMove(), and lstSize()"))
{
List *list = lstNew(sizeof(int));
List *list = NULL;
// 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);
MEM_CONTEXT_TEMP_BEGIN()
{
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);
lstMove(list, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
TEST_RESULT_INT(lstSize(list), 9, "list size");
@@ -61,6 +71,7 @@ testRun()
}
TEST_ERROR(lstGet(list, lstSize(list)), AssertError, "cannot get index 9 from list with 9 value(s)");
TEST_RESULT_VOID(lstMove(NULL, NULL), "move null list");
}
// *****************************************************************************************************************************
+16 -8
View File
@@ -9,21 +9,29 @@ void
testRun()
{
// *****************************************************************************************************************************
if (testBegin("strLstNew(), strLstAdd, strLstGet(), strLstSize(), and strLstFree()"))
if (testBegin("strLstNew(), strLstAdd, strLstGet(), strLstMove(), strLstSize(), and strLstFree()"))
{
StringList *list = strLstNew();
// Add strings to the list
// -------------------------------------------------------------------------------------------------------------------------
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
StringList *list = NULL;
MEM_CONTEXT_TEMP_BEGIN()
{
if (listIdx == 0)
list = strLstNew();
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
{
TEST_RESULT_PTR(strLstAdd(list, NULL), list, "add null item");
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);
}
else
TEST_RESULT_PTR(strLstAdd(list, strNewFmt("STR%02d", listIdx)), list, "add item %d", listIdx);
strLstMove(list, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
TEST_RESULT_INT(strLstSize(list), 9, "list size");