You've already forked pgbackrest
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:
@@ -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>
|
<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>
|
||||||
|
|
||||||
|
<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>
|
<release-item>
|
||||||
<p>Improve branch coverage in C code.</p>
|
<p>Improve branch coverage in C code.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|||||||
+1
-3
@@ -110,8 +110,6 @@ iniSectionKeyList(const Ini *this, const String *section)
|
|||||||
// Get the section
|
// Get the section
|
||||||
KeyValue *sectionKv = varKv(kvGet(this->store, varNewStr(section)));
|
KeyValue *sectionKv = varKv(kvGet(this->store, varNewStr(section)));
|
||||||
|
|
||||||
memContextSwitch(MEM_CONTEXT_OLD());
|
|
||||||
|
|
||||||
// Return key list of the section exists
|
// Return key list of the section exists
|
||||||
if (sectionKv != NULL)
|
if (sectionKv != NULL)
|
||||||
result = strLstNewVarLst(kvKeyList(sectionKv));
|
result = strLstNewVarLst(kvKeyList(sectionKv));
|
||||||
@@ -119,7 +117,7 @@ iniSectionKeyList(const Ini *this, const String *section)
|
|||||||
else
|
else
|
||||||
result = strLstNew();
|
result = strLstNew();
|
||||||
|
|
||||||
memContextSwitch(MEM_CONTEXT_TEMP());
|
strLstMove(result, MEM_CONTEXT_OLD());
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_TEMP_END();
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
|
||||||
|
|||||||
+91
-37
@@ -4,6 +4,7 @@ Memory Context Manager
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/memContext.h"
|
#include "common/memContext.h"
|
||||||
|
|
||||||
@@ -113,6 +114,55 @@ memFreeInternal(void *buffer)
|
|||||||
free(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
|
Create a new memory context
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@@ -123,43 +173,8 @@ memContextNew(const char *name)
|
|||||||
if (strlen(name) == 0 || strlen(name) > MEM_CONTEXT_NAME_SIZE)
|
if (strlen(name) == 0 || strlen(name) > MEM_CONTEXT_NAME_SIZE)
|
||||||
THROW(AssertError, "context name length must be > 0 and <= %d", 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
|
// Find space for the new context
|
||||||
unsigned int contextIdx;
|
unsigned int contextIdx = memContextNewIndex(memContextCurrent(), true);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the context has not been allocated yet
|
// If the context has not been allocated yet
|
||||||
if (!memContextCurrent()->contextChildList[contextIdx])
|
if (!memContextCurrent()->contextChildList[contextIdx])
|
||||||
@@ -330,6 +345,45 @@ memFree(void *buffer)
|
|||||||
alloc->active = false;
|
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
|
Switch to the specified context and return the old context
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ TRY_END();
|
|||||||
Use the MEM_CONTEXT*() macros when possible rather than implement error-handling for every memory context block.
|
Use the MEM_CONTEXT*() macros when possible rather than implement error-handling for every memory context block.
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
MemContext *memContextNew(const char *name);
|
MemContext *memContextNew(const char *name);
|
||||||
|
void memContextMove(MemContext *this, MemContext *parentNew);
|
||||||
void memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *callbackArgument);
|
void memContextCallback(MemContext *this, void (*callbackFunction)(void *), void *callbackArgument);
|
||||||
MemContext *memContextSwitch(MemContext *this);
|
MemContext *memContextSwitch(MemContext *this);
|
||||||
void memContextFree(MemContext *this);
|
void memContextFree(MemContext *this);
|
||||||
|
|||||||
+21
-13
@@ -3,7 +3,6 @@ String Handler
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "common/memContext.h"
|
|
||||||
#include "common/type/buffer.h"
|
#include "common/type/buffer.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@@ -21,15 +20,21 @@ Create a new buffer
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
Buffer *
|
Buffer *
|
||||||
bufNew(size_t size)
|
bufNew(size_t size)
|
||||||
|
{
|
||||||
|
Buffer *this = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_NEW_BEGIN("Buffer")
|
||||||
{
|
{
|
||||||
// Create object
|
// Create object
|
||||||
Buffer *this = memNew(sizeof(Buffer));
|
this = memNew(sizeof(Buffer));
|
||||||
this->memContext = memContextCurrent();
|
this->memContext = MEM_CONTEXT_NEW();
|
||||||
this->size = size;
|
this->size = size;
|
||||||
|
|
||||||
// Allocate buffer
|
// Allocate buffer
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
this->buffer = memNewRaw(this->size);
|
this->buffer = memNewRaw(this->size);
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_NEW_END();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -49,6 +54,18 @@ bufNewStr(const String *string)
|
|||||||
return this;
|
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
|
Return buffer ptr
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@@ -113,14 +130,5 @@ void
|
|||||||
bufFree(Buffer *this)
|
bufFree(Buffer *this)
|
||||||
{
|
{
|
||||||
if (this != NULL)
|
if (this != NULL)
|
||||||
{
|
memContextFree(this->memContext);
|
||||||
MEM_CONTEXT_BEGIN(this->memContext)
|
|
||||||
{
|
|
||||||
if (this->buffer != NULL)
|
|
||||||
memFree(this->buffer);
|
|
||||||
|
|
||||||
memFree(this);
|
|
||||||
}
|
|
||||||
MEM_CONTEXT_END();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,20 +4,20 @@ Buffer Handler
|
|||||||
#ifndef COMMON_TYPE_BUFFER_H
|
#ifndef COMMON_TYPE_BUFFER_H
|
||||||
#define COMMON_TYPE_BUFFER_H
|
#define COMMON_TYPE_BUFFER_H
|
||||||
|
|
||||||
#include "common/typec.h"
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Buffer object
|
Buffer object
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef struct Buffer Buffer;
|
typedef struct Buffer Buffer;
|
||||||
|
|
||||||
|
#include "common/memContext.h"
|
||||||
|
#include "common/type/string.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#include "common/type/string.h"
|
|
||||||
|
|
||||||
Buffer *bufNew(size_t size);
|
Buffer *bufNew(size_t size);
|
||||||
Buffer *bufNewStr(const String *string);
|
Buffer *bufNewStr(const String *string);
|
||||||
|
Buffer *bufMove(Buffer *this, MemContext *parentNew);
|
||||||
Buffer *bufResize(Buffer *this, size_t size);
|
Buffer *bufResize(Buffer *this, size_t size);
|
||||||
size_t bufSize(const Buffer *this);
|
size_t bufSize(const Buffer *this);
|
||||||
unsigned char *bufPtr(const Buffer *this);
|
unsigned char *bufPtr(const Buffer *this);
|
||||||
|
|||||||
+36
-6
@@ -5,7 +5,6 @@ List Handler
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "common/memContext.h"
|
|
||||||
#include "common/type/list.h"
|
#include "common/type/list.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@@ -13,6 +12,7 @@ Contains information about the list
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct List
|
struct List
|
||||||
{
|
{
|
||||||
|
MemContext *memContext;
|
||||||
size_t itemSize;
|
size_t itemSize;
|
||||||
unsigned int listSize;
|
unsigned int listSize;
|
||||||
unsigned int listSizeMax;
|
unsigned int listSizeMax;
|
||||||
@@ -24,10 +24,17 @@ Create a new list
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
List *
|
List *
|
||||||
lstNew(size_t itemSize)
|
lstNew(size_t itemSize)
|
||||||
|
{
|
||||||
|
List *this = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_NEW_BEGIN("List")
|
||||||
{
|
{
|
||||||
// Create object
|
// Create object
|
||||||
List *this = memNew(sizeof(List));
|
this = memNew(sizeof(List));
|
||||||
|
this->memContext = MEM_CONTEXT_NEW();
|
||||||
this->itemSize = itemSize;
|
this->itemSize = itemSize;
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_NEW_END();
|
||||||
|
|
||||||
// Return buffer
|
// Return buffer
|
||||||
return this;
|
return this;
|
||||||
@@ -41,6 +48,8 @@ lstAdd(List *this, const void *item)
|
|||||||
{
|
{
|
||||||
// If list size = max then allocate more space
|
// If list size = max then allocate more space
|
||||||
if (this->listSize == this->listSizeMax)
|
if (this->listSize == this->listSizeMax)
|
||||||
|
{
|
||||||
|
MEM_CONTEXT_BEGIN(this->memContext)
|
||||||
{
|
{
|
||||||
// If nothing has been allocated yet
|
// If nothing has been allocated yet
|
||||||
if (this->listSizeMax == 0)
|
if (this->listSizeMax == 0)
|
||||||
@@ -55,6 +64,8 @@ lstAdd(List *this, const void *item)
|
|||||||
this->list = memGrowRaw(this->list, this->listSizeMax * this->itemSize);
|
this->list = memGrowRaw(this->list, this->listSizeMax * this->itemSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MEM_CONTEXT_END();
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(this->list + (this->listSize * this->itemSize), item, this->itemSize);
|
memcpy(this->list + (this->listSize * this->itemSize), item, this->itemSize);
|
||||||
this->listSize++;
|
this->listSize++;
|
||||||
@@ -77,6 +88,27 @@ lstGet(const List *this, unsigned int listIdx)
|
|||||||
return this->list + (listIdx * this->itemSize);
|
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
|
Return list size
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@@ -103,8 +135,6 @@ Free the string
|
|||||||
void
|
void
|
||||||
lstFree(List *this)
|
lstFree(List *this)
|
||||||
{
|
{
|
||||||
if (this->list != NULL)
|
if (this != NULL)
|
||||||
memFree(this->list);
|
memContextFree(this->memContext);
|
||||||
|
|
||||||
memFree(this);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ List Handler
|
|||||||
#ifndef COMMON_TYPE_LIST_H
|
#ifndef COMMON_TYPE_LIST_H
|
||||||
#define COMMON_TYPE_LIST_H
|
#define COMMON_TYPE_LIST_H
|
||||||
|
|
||||||
|
#include "common/memContext.h"
|
||||||
#include "common/type/string.h"
|
#include "common/type/string.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@@ -22,6 +23,8 @@ Functions
|
|||||||
List *lstNew(size_t itemSize);
|
List *lstNew(size_t itemSize);
|
||||||
List *lstAdd(List *this, const void *item);
|
List *lstAdd(List *this, const void *item);
|
||||||
void *lstGet(const List *this, unsigned int listIdx);
|
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);
|
unsigned int lstSize(const List *this);
|
||||||
List *lstSort(List *this, int (*comparator)(const void *, const void*));
|
List *lstSort(List *this, int (*comparator)(const void *, const void*));
|
||||||
void lstFree(List *this);
|
void lstFree(List *this);
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ strLstNew()
|
|||||||
return (StringList *)lstNew(sizeof(String *));
|
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
|
Split a string into a string list based on a delimiter
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@@ -39,6 +48,8 @@ strLstNewSplitZ(const String *string, const char *delimiter)
|
|||||||
// Match points to the next delimiter match that has been found
|
// Match points to the next delimiter match that has been found
|
||||||
const char *stringMatch = NULL;
|
const char *stringMatch = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Find a delimiter match
|
// Find a delimiter match
|
||||||
@@ -47,14 +58,16 @@ strLstNewSplitZ(const String *string, const char *delimiter)
|
|||||||
// If a match was found then add the string
|
// If a match was found then add the string
|
||||||
if (stringMatch != NULL)
|
if (stringMatch != NULL)
|
||||||
{
|
{
|
||||||
strLstAdd(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
|
strLstAddInternal(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
|
||||||
stringBase = stringMatch + strlen(delimiter);
|
stringBase = stringMatch + strlen(delimiter);
|
||||||
}
|
}
|
||||||
// Else make whatever is left the last string
|
// Else make whatever is left the last string
|
||||||
else
|
else
|
||||||
strLstAdd(this, strNew(stringBase));
|
strLstAddInternal(this, strNew(stringBase));
|
||||||
}
|
}
|
||||||
while(stringMatch != NULL);
|
while(stringMatch != NULL);
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_END();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -84,6 +97,8 @@ strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
|
|||||||
const char *stringMatchLast = NULL;
|
const char *stringMatchLast = NULL;
|
||||||
const char *stringMatch = NULL;
|
const char *stringMatch = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||||
|
{
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Find a delimiter match
|
// Find a delimiter match
|
||||||
@@ -97,7 +112,7 @@ strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
|
|||||||
if (stringMatchLast != NULL)
|
if (stringMatchLast != NULL)
|
||||||
stringMatch = stringMatchLast - strlen(delimiter);
|
stringMatch = stringMatchLast - strlen(delimiter);
|
||||||
|
|
||||||
strLstAdd(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
|
strLstAddInternal(this, strNewN(stringBase, (size_t)(stringMatch - stringBase)));
|
||||||
stringBase = stringMatch + strlen(delimiter);
|
stringBase = stringMatch + strlen(delimiter);
|
||||||
stringMatchLast = NULL;
|
stringMatchLast = NULL;
|
||||||
}
|
}
|
||||||
@@ -109,14 +124,16 @@ strLstNewSplitSizeZ(const String *string, const char *delimiter, size_t size)
|
|||||||
{
|
{
|
||||||
if (stringMatchLast != NULL && strlen(stringBase) - strlen(delimiter) >= size)
|
if (stringMatchLast != NULL && strlen(stringBase) - strlen(delimiter) >= size)
|
||||||
{
|
{
|
||||||
strLstAdd(this, strNewN(stringBase, (size_t)((stringMatchLast - strlen(delimiter)) - stringBase)));
|
strLstAddInternal(this, strNewN(stringBase, (size_t)((stringMatchLast - strlen(delimiter)) - stringBase)));
|
||||||
stringBase = stringMatchLast;
|
stringBase = stringMatchLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
strLstAdd(this, strNew(stringBase));
|
strLstAddInternal(this, strNew(stringBase));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(stringMatch != NULL);
|
while(stringMatch != NULL);
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_END();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -131,8 +148,12 @@ strLstNewVarLst(const VariantList *sourceList)
|
|||||||
StringList *this = strLstNew();
|
StringList *this = strLstNew();
|
||||||
|
|
||||||
// Copy variants
|
// Copy variants
|
||||||
|
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||||
|
{
|
||||||
for (unsigned int listIdx = 0; listIdx < varLstSize(sourceList); listIdx++)
|
for (unsigned int listIdx = 0; listIdx < varLstSize(sourceList); listIdx++)
|
||||||
strLstAdd(this, varStr(varLstGet(sourceList, listIdx)));
|
strLstAddInternal(this, strDup(varStr(varLstGet(sourceList, listIdx))));
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_END();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -146,9 +167,13 @@ strLstDup(const StringList *sourceList)
|
|||||||
// Create the list
|
// Create the list
|
||||||
StringList *this = strLstNew();
|
StringList *this = strLstNew();
|
||||||
|
|
||||||
// Copy variants
|
// Copy strings
|
||||||
|
MEM_CONTEXT_BEGIN(lstMemContext((List *)this))
|
||||||
|
{
|
||||||
for (unsigned int listIdx = 0; listIdx < strLstSize(sourceList); listIdx++)
|
for (unsigned int listIdx = 0; listIdx < strLstSize(sourceList); listIdx++)
|
||||||
strLstAdd(this, strLstGet(sourceList, listIdx));
|
strLstAddInternal(this, strDup(strLstGet(sourceList, listIdx)));
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_END();
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -159,8 +184,15 @@ Wrapper for lstAdd()
|
|||||||
StringList *
|
StringList *
|
||||||
strLstAdd(StringList *this, const String *string)
|
strLstAdd(StringList *this, const String *string)
|
||||||
{
|
{
|
||||||
String *stringCopy = strDup(string);
|
StringList *result = NULL;
|
||||||
return (StringList *)lstAdd((List *)this, &stringCopy);
|
|
||||||
|
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 *
|
StringList *
|
||||||
strLstAddZ(StringList *this, const char *string)
|
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;
|
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
|
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.
|
this array, though it is OK to modify the array itself.
|
||||||
@@ -273,6 +323,5 @@ Wrapper for lstFree()
|
|||||||
void
|
void
|
||||||
strLstFree(StringList *this)
|
strLstFree(StringList *this)
|
||||||
{
|
{
|
||||||
if (this != NULL)
|
|
||||||
lstFree((List *)this);
|
lstFree((List *)this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ String List Handler
|
|||||||
#ifndef COMMON_TYPE_STRINGLIST_H
|
#ifndef COMMON_TYPE_STRINGLIST_H
|
||||||
#define COMMON_TYPE_STRINGLIST_H
|
#define COMMON_TYPE_STRINGLIST_H
|
||||||
|
|
||||||
#include "common/type/string.h"
|
/***********************************************************************************************************************************
|
||||||
|
String list type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct StringList StringList;
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Sort orders
|
Sort orders
|
||||||
@@ -15,16 +18,13 @@ typedef enum
|
|||||||
sortOrderDesc,
|
sortOrderDesc,
|
||||||
} SortOrder;
|
} SortOrder;
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
#include "common/memContext.h"
|
||||||
String list type
|
#include "common/type/string.h"
|
||||||
***********************************************************************************************************************************/
|
#include "common/type/variantList.h"
|
||||||
typedef struct StringList StringList;
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#include "common/type/variantList.h"
|
|
||||||
|
|
||||||
StringList *strLstNew();
|
StringList *strLstNew();
|
||||||
StringList *strLstNewSplit(const String *string, const String *delimiter);
|
StringList *strLstNewSplit(const String *string, const String *delimiter);
|
||||||
StringList *strLstNewSplitZ(const String *string, const char *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);
|
StringList *strLstAddZ(StringList *this, const char *string);
|
||||||
String *strLstGet(const StringList *this, unsigned int listIdx);
|
String *strLstGet(const StringList *this, unsigned int listIdx);
|
||||||
String *strLstJoin(const StringList *this, const char *separator);
|
String *strLstJoin(const StringList *this, const char *separator);
|
||||||
|
StringList * strLstMove(StringList *this, MemContext *parentNew);
|
||||||
const char **strLstPtr(const StringList *this);
|
const char **strLstPtr(const StringList *this);
|
||||||
unsigned int strLstSize(const StringList *this);
|
unsigned int strLstSize(const StringList *this);
|
||||||
StringList *strLstSort(StringList *this, SortOrder sortOrder);
|
StringList *strLstSort(StringList *this, SortOrder sortOrder);
|
||||||
|
|||||||
+24
-33
@@ -54,28 +54,28 @@ Read from storage into a buffer
|
|||||||
Buffer *
|
Buffer *
|
||||||
storageDriverPosixGet(const StorageFile *file)
|
storageDriverPosixGet(const StorageFile *file)
|
||||||
{
|
{
|
||||||
Buffer volatile *result = NULL;
|
Buffer *result = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
{
|
||||||
TRY_BEGIN()
|
TRY_BEGIN()
|
||||||
{
|
{
|
||||||
|
size_t bufferSize = storageBufferSize(storageFileStorage(file));
|
||||||
|
result = bufNew(bufferSize);
|
||||||
|
|
||||||
// Create result buffer with buffer size
|
// Create result buffer with buffer size
|
||||||
ssize_t actualBytes = 0;
|
ssize_t actualBytes = 0;
|
||||||
size_t totalBytes = 0;
|
size_t totalBytes = 0;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
size_t bufferSize = storageBufferSize(storageFileStorage(file));
|
|
||||||
|
|
||||||
// Allocate the buffer before first read
|
|
||||||
if (result == NULL)
|
|
||||||
result = bufNew(bufferSize);
|
|
||||||
// Grow the buffer on subsequent reads
|
// Grow the buffer on subsequent reads
|
||||||
else
|
if (totalBytes != 0)
|
||||||
bufResize((Buffer *)result, bufSize((Buffer *)result) + bufferSize);
|
bufResize(result, bufSize(result) + bufferSize);
|
||||||
|
|
||||||
// Read and handle errors
|
// Read and handle errors
|
||||||
actualBytes = read(
|
actualBytes = read(
|
||||||
STORAGE_DATA(file)->handle, bufPtr((Buffer *)result) + totalBytes, bufferSize);
|
STORAGE_DATA(file)->handle, bufPtr(result) + totalBytes, bufferSize);
|
||||||
|
|
||||||
// Error occurred during write
|
// Error occurred during write
|
||||||
if (actualBytes == -1)
|
if (actualBytes == -1)
|
||||||
@@ -87,14 +87,7 @@ storageDriverPosixGet(const StorageFile *file)
|
|||||||
while (actualBytes != 0);
|
while (actualBytes != 0);
|
||||||
|
|
||||||
// Resize buffer to total bytes read
|
// Resize buffer to total bytes read
|
||||||
bufResize((Buffer *)result, totalBytes);
|
bufResize(result, totalBytes);
|
||||||
}
|
|
||||||
CATCH_ANY()
|
|
||||||
{
|
|
||||||
// Free buffer on error if it was allocated
|
|
||||||
bufFree((Buffer *)result);
|
|
||||||
|
|
||||||
RETHROW();
|
|
||||||
}
|
}
|
||||||
FINALLY()
|
FINALLY()
|
||||||
{
|
{
|
||||||
@@ -103,7 +96,11 @@ storageDriverPosixGet(const StorageFile *file)
|
|||||||
}
|
}
|
||||||
TRY_END();
|
TRY_END();
|
||||||
|
|
||||||
return (Buffer *)result;
|
bufMove(result, MEM_CONTEXT_OLD());
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@@ -113,9 +110,7 @@ StringList *
|
|||||||
storageDriverPosixList(const String *path, bool errorOnMissing, const String *expression)
|
storageDriverPosixList(const String *path, bool errorOnMissing, const String *expression)
|
||||||
{
|
{
|
||||||
StringList *result = NULL;
|
StringList *result = NULL;
|
||||||
|
|
||||||
DIR *dir = NULL;
|
DIR *dir = NULL;
|
||||||
RegExp *regExp = NULL;
|
|
||||||
|
|
||||||
TRY_BEGIN()
|
TRY_BEGIN()
|
||||||
{
|
{
|
||||||
@@ -129,10 +124,11 @@ storageDriverPosixList(const String *path, bool errorOnMissing, const String *ex
|
|||||||
THROW_SYS_ERROR(PathOpenError, "unable to open directory '%s' for read", strPtr(path));
|
THROW_SYS_ERROR(PathOpenError, "unable to open directory '%s' for read", strPtr(path));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
{
|
{
|
||||||
// Prepare regexp if an expression was passed
|
// Prepare regexp if an expression was passed
|
||||||
if (expression != NULL)
|
RegExp *regExp = (expression == NULL) ? NULL : regExpNew(expression);
|
||||||
regExp = regExpNew(expression);
|
|
||||||
|
|
||||||
// Create the string list now that we know the directory is valid
|
// Create the string list now that we know the directory is valid
|
||||||
result = strLstNew();
|
result = strLstNew();
|
||||||
@@ -147,27 +143,22 @@ storageDriverPosixList(const String *path, bool errorOnMissing, const String *ex
|
|||||||
// Exclude current/parent directory and apply the expression if specified
|
// Exclude current/parent directory and apply the expression if specified
|
||||||
if (!strEqZ(entry, ".") && !strEqZ(entry, "..") && (regExp == NULL || regExpMatch(regExp, entry)))
|
if (!strEqZ(entry, ".") && !strEqZ(entry, "..") && (regExp == NULL || regExpMatch(regExp, entry)))
|
||||||
strLstAdd(result, entry);
|
strLstAdd(result, entry);
|
||||||
else
|
|
||||||
strFree(entry);
|
strFree(entry);
|
||||||
|
|
||||||
dirEntry = readdir(dir);
|
dirEntry = readdir(dir);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
CATCH_ANY()
|
|
||||||
{
|
|
||||||
// Free list on error
|
|
||||||
strLstFree(result);
|
|
||||||
|
|
||||||
RETHROW();
|
// Move finished list up to the old context
|
||||||
|
strLstMove(result, MEM_CONTEXT_OLD());
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FINALLY()
|
FINALLY()
|
||||||
{
|
{
|
||||||
if (dir != NULL)
|
if (dir != NULL)
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
|
|
||||||
if (regExp != NULL)
|
|
||||||
regExpFree(regExp);
|
|
||||||
}
|
}
|
||||||
TRY_END();
|
TRY_END();
|
||||||
|
|
||||||
|
|||||||
+8
-20
@@ -123,21 +123,15 @@ storageList(const Storage *this, const String *pathExp, StorageListParam param)
|
|||||||
{
|
{
|
||||||
StringList *result = NULL;
|
StringList *result = NULL;
|
||||||
|
|
||||||
String *path = NULL;
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
|
||||||
TRY_BEGIN()
|
|
||||||
{
|
{
|
||||||
// Build the path
|
// Build the path
|
||||||
path = storagePathNP(this, pathExp);
|
String *path = storagePathNP(this, pathExp);
|
||||||
|
|
||||||
// Call driver function
|
// Move list up to the old context
|
||||||
result = storageDriverPosixList(path, param.errorOnMissing, param.expression);
|
result = strLstMove(storageDriverPosixList(path, param.errorOnMissing, param.expression), MEM_CONTEXT_OLD());
|
||||||
}
|
}
|
||||||
FINALLY()
|
MEM_CONTEXT_TEMP_END();
|
||||||
{
|
|
||||||
strFree(path);
|
|
||||||
}
|
|
||||||
TRY_END();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -151,7 +145,7 @@ storageOpenRead(const Storage *this, const String *fileExp, StorageOpenReadParam
|
|||||||
{
|
{
|
||||||
StorageFile *result = NULL;
|
StorageFile *result = NULL;
|
||||||
|
|
||||||
MEM_CONTEXT_NEW_BEGIN("StorageFileRead")
|
MEM_CONTEXT_NEW_BEGIN("StorageFile")
|
||||||
{
|
{
|
||||||
String *fileName = storagePathNP(this, fileExp);
|
String *fileName = storagePathNP(this, fileExp);
|
||||||
|
|
||||||
@@ -159,13 +153,7 @@ storageOpenRead(const Storage *this, const String *fileExp, StorageOpenReadParam
|
|||||||
void *data = storageDriverPosixOpenRead(fileName, param.ignoreMissing);
|
void *data = storageDriverPosixOpenRead(fileName, param.ignoreMissing);
|
||||||
|
|
||||||
// Free mem contexts if missing files are ignored
|
// Free mem contexts if missing files are ignored
|
||||||
if (data == NULL)
|
if (data != NULL)
|
||||||
{
|
|
||||||
memContextSwitch(MEM_CONTEXT_OLD());
|
|
||||||
memContextFree(MEM_CONTEXT_NEW());
|
|
||||||
}
|
|
||||||
// Else create the storage file
|
|
||||||
else
|
|
||||||
result = storageFileNew(this, fileName, storageFileTypeRead, data);
|
result = storageFileNew(this, fileName, storageFileTypeRead, data);
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_NEW_END();
|
MEM_CONTEXT_NEW_END();
|
||||||
@@ -183,7 +171,7 @@ storageOpenWrite(const Storage *this, const String *fileExp, StorageOpenWritePar
|
|||||||
|
|
||||||
StorageFile *result = NULL;
|
StorageFile *result = NULL;
|
||||||
|
|
||||||
MEM_CONTEXT_NEW_BEGIN("StorageFileWrite")
|
MEM_CONTEXT_NEW_BEGIN("StorageFile")
|
||||||
{
|
{
|
||||||
String *fileName = storagePathNP(this, fileExp);
|
String *fileName = storagePathNP(this, fileExp);
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ my $oTestDef =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
&TESTDEF_NAME => 'mem-context',
|
&TESTDEF_NAME => 'mem-context',
|
||||||
&TESTDEF_TOTAL => 6,
|
&TESTDEF_TOTAL => 7,
|
||||||
&TESTDEF_C => true,
|
&TESTDEF_C => true,
|
||||||
&TESTDEF_CDEF => '-DNO_MEM_CONTEXT -DNO_LOG',
|
&TESTDEF_CDEF => '-DNO_MEM_CONTEXT -DNO_LOG',
|
||||||
|
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ testRun()
|
|||||||
TEST_RESULT_INT(memContextTop()->contextChildListSize, 0, "top context should init with zero children");
|
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_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
|
// Current context should equal top context
|
||||||
TEST_RESULT_PTR(memContextCurrent(), memContextTop(), "top context == current context");
|
TEST_RESULT_PTR(memContextCurrent(), memContextTop(), "top context == current context");
|
||||||
|
|
||||||
@@ -156,6 +154,11 @@ testRun()
|
|||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
memContextFree(memContextTop()->contextChildList[MEM_CONTEXT_INITIAL_SIZE]),
|
memContextFree(memContextTop()->contextChildList[MEM_CONTEXT_INITIAL_SIZE]),
|
||||||
AssertError, "cannot free inactive context");
|
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");
|
TEST_RESULT_INT(expectedTotal, sizeof(size_t), "all bytes are 0xFE in original portion");
|
||||||
|
|
||||||
// Free memory
|
// 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(NULL), AssertError, "unable to find null allocation");
|
||||||
TEST_ERROR(memFree((void *)0x01), AssertError, "unable to find allocation");
|
TEST_ERROR(memFree((void *)0x01), AssertError, "unable to find allocation");
|
||||||
memFree(buffer);
|
memFree(buffer);
|
||||||
@@ -298,5 +306,46 @@ testRun()
|
|||||||
TEST_RESULT_BOOL(memContext->state == memContextStateFree, true, "new mem context is not active");
|
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());
|
memContextFree(memContextTop());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,17 @@ void
|
|||||||
testRun()
|
testRun()
|
||||||
{
|
{
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
if (testBegin("bufNew(), bufNewStr(), bufSize(), bufPtr(), and bufFree()"))
|
if (testBegin("bufNew(), bufNewStr(), bufMove(), bufSize(), bufPtr(), and bufFree()"))
|
||||||
{
|
{
|
||||||
Buffer *buffer = NULL;
|
Buffer *buffer = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
{
|
||||||
TEST_ASSIGN(buffer, bufNew(256), "new buffer");
|
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_PTR(bufPtr(buffer), buffer->buffer, "buffer pointer");
|
||||||
TEST_RESULT_INT(bufSize(buffer), 256, "buffer size");
|
TEST_RESULT_INT(bufSize(buffer), 256, "buffer size");
|
||||||
|
|
||||||
@@ -23,6 +29,8 @@ testRun()
|
|||||||
TEST_RESULT_VOID(bufFree(buffer), "free buffer");
|
TEST_RESULT_VOID(bufFree(buffer), "free buffer");
|
||||||
TEST_RESULT_VOID(bufFree(bufNew(0)), "free empty buffer");
|
TEST_RESULT_VOID(bufFree(bufNew(0)), "free empty buffer");
|
||||||
TEST_RESULT_VOID(bufFree(NULL), "free null buffer");
|
TEST_RESULT_VOID(bufFree(NULL), "free null buffer");
|
||||||
|
|
||||||
|
TEST_RESULT_VOID(bufMove(NULL, NULL), "move null buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
|
|||||||
@@ -27,30 +27,40 @@ void
|
|||||||
testRun()
|
testRun()
|
||||||
{
|
{
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
if (testBegin("lstNew() and lstFree()"))
|
if (testBegin("lstNew(), lstMemContext(), and lstFree()"))
|
||||||
{
|
{
|
||||||
List *list = lstNew(sizeof(void *));
|
List *list = lstNew(sizeof(void *));
|
||||||
|
|
||||||
TEST_RESULT_INT(list->itemSize, sizeof(void *), "item size");
|
TEST_RESULT_INT(list->itemSize, sizeof(void *), "item size");
|
||||||
TEST_RESULT_INT(list->listSize, 0, "list size");
|
TEST_RESULT_INT(list->listSize, 0, "list size");
|
||||||
TEST_RESULT_INT(list->listSizeMax, 0, "list size max");
|
TEST_RESULT_INT(list->listSizeMax, 0, "list size max");
|
||||||
|
TEST_RESULT_PTR(lstMemContext(list), list->memContext, "list mem context");
|
||||||
|
|
||||||
void *ptr = NULL;
|
void *ptr = NULL;
|
||||||
TEST_RESULT_PTR(lstAdd(list, &ptr), list, "add item");
|
TEST_RESULT_PTR(lstAdd(list, &ptr), list, "add item");
|
||||||
|
|
||||||
TEST_RESULT_VOID(lstFree(list), "free list");
|
TEST_RESULT_VOID(lstFree(list), "free list");
|
||||||
TEST_RESULT_VOID(lstFree(lstNew(1)), "free empty 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;
|
||||||
|
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
{
|
||||||
|
list = lstNew(sizeof(int));
|
||||||
|
|
||||||
// Add ints to the list
|
// Add ints to the list
|
||||||
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
|
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
|
||||||
TEST_RESULT_PTR(lstAdd(list, &listIdx), list, "add item %d", 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");
|
TEST_RESULT_INT(lstSize(list), 9, "list size");
|
||||||
|
|
||||||
// Read them back and check values
|
// Read them back and check values
|
||||||
@@ -61,6 +71,7 @@ testRun()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_ERROR(lstGet(list, lstSize(list)), AssertError, "cannot get index 9 from list with 9 value(s)");
|
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
|
|||||||
@@ -9,12 +9,16 @@ void
|
|||||||
testRun()
|
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
|
// Add strings to the list
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
StringList *list = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
{
|
||||||
|
list = strLstNew();
|
||||||
|
|
||||||
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
|
for (int listIdx = 0; listIdx <= LIST_INITIAL_SIZE; listIdx++)
|
||||||
{
|
{
|
||||||
if (listIdx == 0)
|
if (listIdx == 0)
|
||||||
@@ -25,6 +29,10 @@ testRun()
|
|||||||
TEST_RESULT_PTR(strLstAdd(list, strNewFmt("STR%02d", listIdx)), list, "add item %d", listIdx);
|
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");
|
TEST_RESULT_INT(strLstSize(list), 9, "list size");
|
||||||
|
|
||||||
// Read them back and check values
|
// Read them back and check values
|
||||||
|
|||||||
Reference in New Issue
Block a user