summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cc4group.c102
-rw-r--r--src/cc4group.h24
-rw-r--r--src/cppc4group.cpp2
3 files changed, 90 insertions, 38 deletions
diff --git a/src/cc4group.c b/src/cc4group.c
index f040f23..4f9839b 100644
--- a/src/cc4group.c
+++ b/src/cc4group.c
@@ -49,12 +49,6 @@ static bool cc4group_getEntryData(CC4Group* const this, const char* const entryP
#define CC4GROUP_UNEXPECTED_EOD -100
#define CC4GROUP_MEM_ERROR -101
-typedef enum {
- Take,
- Copy,
- Reference
-} CC4Group_MemoryManagement;
-
struct list_GroupEntryList;
typedef struct C4GroupEntryData_t {
C4GroupEntryCore core;
@@ -115,25 +109,18 @@ typedef struct {
static bool cc4group_applyMemoryManagementStart(CC4Group_MemoryManagement const management, const uint8_t** data, size_t size)
{
- if(management == Copy)
+ void* newData = management->start((void*)*data, size);
+ if(newData == NULL)
{
- uint8_t* copy = malloc(size);
- if(copy == NULL)
- {
- return false;
- }
- memcpy(copy, *data, size);
- *data = copy;
+ return false;
}
+ *data = newData;
return true;
}
static void cc4group_applyMemoryManagementEnd(CC4Group_MemoryManagement const management, const uint8_t* data)
{
- if(management == Copy || management == Take)
- {
- free((void*)data);
- }
+ management->end((void*)data);
}
static const uint8_t* cc4group_getOnlyEntryData(CC4Group* const this, const C4GroupEntryData* entry);
@@ -254,7 +241,7 @@ static bool buildChildren(CC4Group* const this, C4GroupEntryData* const entry, s
return false;
}
- C4GroupEntryData* childEntry = &GroupEntryListAppend(entry->children, (C4GroupEntryData){.core = *core, .data = childData + core->Offset, .memoryManagement = Reference, .children = NULL, .parent = entry})->value;
+ C4GroupEntryData* childEntry = &GroupEntryListAppend(entry->children, (C4GroupEntryData){.core = *core, .data = childData + core->Offset, .memoryManagement = cc4group.MemoryManagement.Reference, .children = NULL, .parent = entry})->value;
if(core->Directory)
{
@@ -513,7 +500,7 @@ static bool cc4group_inflateFillOutput(z_stream* const strm, CC4Group_ReadCallba
return false;
}
-static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback const readCallback, void* const callbackArg, int const memoryManagement, CC4Group_ReadSetupCallback const initCallback, CC4Group_ReadSetupCallback const deinitCallback)
+static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback const readCallback, void* const callbackArg, CC4Group_MemoryManagement const memoryManagement, CC4Group_ReadSetupCallback const initCallback, CC4Group_ReadSetupCallback const deinitCallback)
{
assert(this);
assert(readCallback);
@@ -852,7 +839,7 @@ static bool cc4group_readFilePointerReadCallback(const void** const data, size_t
#undef CHUNK_SIZE
}
-static bool cc4group_openMemory(CC4Group* const this, const void* const compressedData, size_t const size, int const memoryManagement)
+static bool cc4group_openMemory(CC4Group* const this, const void* const compressedData, size_t const size, CC4Group_MemoryManagement const memoryManagement)
{
assert(this);
assert(compressedData);
@@ -957,7 +944,7 @@ static bool cc4group_uncompressGroupFromFile(CC4Group* const this, const char* c
}
CompleteDataReadCallbackArg data = {.data = mappedFile, .size = size};
- success = cc4group_uncompressGroup(this, cc4group_completeDataReadCallback, &data, Reference, NULL, NULL);
+ success = cc4group_uncompressGroup(this, cc4group_completeDataReadCallback, &data, cc4group.MemoryManagement.Reference, NULL, NULL);
ret:
if(mappedFile != MAP_FAILED)
@@ -989,7 +976,7 @@ static void cc4group_init(CC4Group* const this)
this->uncompressedSize = 0;
this->root.data = NULL;
- this->root.memoryManagement = Reference;
+ this->root.memoryManagement = cc4group.MemoryManagement.Reference;
this->root.parent = NULL;
this->root.children = NULL;
this->root.core.Directory = true;
@@ -1152,7 +1139,7 @@ static bool cc4group_openFd(CC4Group* const this, int fd)
// assert is in cc4group_uncompressGroup
ChunkedReadData arg = {.arg = &fd};
- return cc4group_uncompressGroup(this, cc4group_readFdReadCallback, &arg, Reference, cc4group_initChunkBufferCallback, cc4group_deinitChunkBufferCallback);
+ return cc4group_uncompressGroup(this, cc4group_readFdReadCallback, &arg, cc4group.MemoryManagement.Reference, cc4group_initChunkBufferCallback, cc4group_deinitChunkBufferCallback);
}
static bool cc4group_openFilePointer(CC4Group* const this, FILE* file)
@@ -1161,7 +1148,7 @@ static bool cc4group_openFilePointer(CC4Group* const this, FILE* file)
assert(file);
ChunkedReadData arg = {.arg = file};
- return cc4group_uncompressGroup(this, cc4group_readFilePointerReadCallback, &arg, Reference, cc4group_initChunkBufferCallback, cc4group_deinitChunkBufferCallback);
+ return cc4group_uncompressGroup(this, cc4group_readFilePointerReadCallback, &arg, cc4group.MemoryManagement.Reference, cc4group_initChunkBufferCallback, cc4group_deinitChunkBufferCallback);
}
static bool cc4group_openExisting(CC4Group* const this, const char* const path)
@@ -2156,7 +2143,7 @@ static C4GroupEntryData* cc4group_createEntry(CC4Group* const this, const char*
C4GroupEntryData entry;
entry.data = NULL;
- entry.memoryManagement = Reference;
+ entry.memoryManagement = cc4group.MemoryManagement.Reference;
entry.children = GroupEntryListNew();
C4GroupEntryCore_init(&entry.core);
@@ -2212,7 +2199,7 @@ static bool cc4group_createFile(CC4Group* const this, const char* const path)
return true;
}
-static bool cc4group_setEntryData(CC4Group* const this, const char* const entryPath, const void* const data, size_t const size, int const memoryManagement)
+static bool cc4group_setEntryData(CC4Group* const this, const char* const entryPath, const void* const data, size_t const size, CC4Group_MemoryManagement const memoryManagement)
{
assert(this);
assert(entryPath);
@@ -2229,7 +2216,7 @@ static bool cc4group_setEntryData(CC4Group* const this, const char* const entryP
entry->data = NULL;
entry->core.Size = 0;
- entry->memoryManagement = Reference;
+ entry->memoryManagement = cc4group.MemoryManagement.Reference;
}
if(data != NULL && size != 0)
@@ -2300,11 +2287,64 @@ static CC4Group* cc4group_openAsChild(CC4Group* const this, const char* const pa
return child;
}
+static void* cc4group_memoryManagementTakeStart(void* const data, size_t const size)
+{
+ (void)size;
+ return data;
+}
+
+static void cc4group_memoryManagementTakeEnd(void* const data)
+{
+ free(data);
+}
+
+static void* cc4group_memoryManagementCopyStart(void* const data, size_t const size)
+{
+ uint8_t* copy = malloc(size);
+ if(copy == NULL)
+ {
+ return NULL;
+ }
+ memcpy(copy, data, size);
+ return copy;
+}
+
+static void cc4group_memoryManagementCopyEnd(void* const data)
+{
+ free(data);
+}
+
+static void* cc4group_memoryManagementReferenceStart(void* const data, size_t const size)
+{
+ (void)size;
+ return data;
+}
+
+static void cc4group_memoryManagementReferenceEnd(void* const data)
+{
+ (void)data;
+}
+
+static CC4Group_MemoryManagement_t takeMemoryManagement = {
+ .start = cc4group_memoryManagementTakeStart,
+ .end = cc4group_memoryManagementTakeEnd,
+};
+
+static CC4Group_MemoryManagement_t copyMemoryManagement = {
+ .start = cc4group_memoryManagementCopyStart,
+ .end = cc4group_memoryManagementCopyEnd,
+};
+
+static CC4Group_MemoryManagement_t referenceMemoryManagement = {
+ .start = cc4group_memoryManagementReferenceStart,
+ .end = cc4group_memoryManagementReferenceEnd,
+};
+
CC4Group_API cc4group = {
.MemoryManagement = {
- .Take = Take,
- .Copy = Copy,
- .Reference = Reference
+ .Take = &takeMemoryManagement,
+ .Copy = &copyMemoryManagement,
+ .Reference = &referenceMemoryManagement
},
diff --git a/src/cc4group.h b/src/cc4group.h
index e575a7e..0a3ceb4 100644
--- a/src/cc4group.h
+++ b/src/cc4group.h
@@ -136,6 +136,18 @@ typedef struct {
typedef void* (*CC4Group_TmpMemoryStrategy)(CC4Group* const this, const size_t size, CC4Group_CleanupJob* cleanupJob);
+// a memory management strategy
+// actually, a memory management strategy is a pointer to an instance of this struct
+// it consists of a start function (like allocating some memory and making a copy)
+// and of an end function, which does the actual cleanup
+// additionally to the predefined memory management strategies, custom strategies may be used
+typedef struct {
+ void* (*start)(void* const data, const size_t size);
+ void (*end)(void* const data);
+} const CC4Group_MemoryManagement_t;
+typedef CC4Group_MemoryManagement_t* CC4Group_MemoryManagement;
+
+
// callback types for openWithReadCallback
// the callback has to store a pointer to the newly read data in data, as well as the amount of read data in size
@@ -161,9 +173,9 @@ typedef bool (*CC4Group_WriteCallback)(const void* const data, size_t const size
// it contains all available methods and constants
typedef struct {
struct {
- int Take; // cc4group will free the data when its not needed anymore; e.g. in the destructor or when setting the file's data again
- int Copy; // cc4group will copy the data to use it; the original data is untouched and needs to be freed by the caller whenever desired
- int Reference; // cc4group will use the data as is (i.e. store the pointer and use it); the caller must guarantee it's validity throughout the groups lifetime (or until the file's data is set to a new pointer) and needs to take care of freeing it afterwards
+ CC4Group_MemoryManagement Take; // cc4group will free the data when its not needed anymore; e.g. in the destructor or when setting the file's data again
+ CC4Group_MemoryManagement Copy; // cc4group will copy the data to use it; the original data is untouched and needs to be freed by the caller whenever desired
+ CC4Group_MemoryManagement Reference; // cc4group will use the data as is (i.e. store the pointer and use it); the caller must guarantee it's validity throughout the groups lifetime (or until the file's data is set to a new pointer) and needs to take care of freeing it afterwards
} const MemoryManagement;
@@ -211,7 +223,7 @@ typedef struct {
// see the description of MemoryManagement to know if and when data has to be freed by the caller
// if the lazy mode is not used, the data can be freed immediately after this function returns
// HINT: the lazy mode is actually not implemented yet, but at least I can't forget to mention it here anymore when it's actually done
- bool (*openMemory)(CC4Group* const this, const void* const groupData, size_t const size, int const memoryManagement);
+ bool (*openMemory)(CC4Group* const this, const void* const groupData, size_t const size, CC4Group_MemoryManagement const memoryManagement);
// opens a group through a file descriptor
// the file descriptor must have been opened with read access and must be in blocking mode (should be default if O_NONBLOCK is not specified)
@@ -226,7 +238,7 @@ typedef struct {
// initCallback is called before readCallback is called and deinitCallback is called after all read operations are done
// initCallback and deinitCallback may be NULL if they should not be used
// even when using the Reference memory management, the buffer returned by the readCallback may be reused across callback calls
- bool (*openWithReadCallback)(CC4Group* const this, CC4Group_ReadCallback const readCallback, void* const callbackArg, int const memoryManagement, CC4Group_ReadSetupCallback const initCallback, CC4Group_ReadSetupCallback const deinitCallback);
+ bool (*openWithReadCallback)(CC4Group* const this, CC4Group_ReadCallback const readCallback, void* const callbackArg, CC4Group_MemoryManagement const memoryManagement, CC4Group_ReadSetupCallback const initCallback, CC4Group_ReadSetupCallback const deinitCallback);
// saves the current in-memory state of the group as a compressed c4group to disk
@@ -287,7 +299,7 @@ typedef struct {
// overwrites the data of the file denoted by entryPath with data indicated by data and size
// see the description of MemoryManagement to know if and when data has to be freed by the caller
- bool (*setEntryData)(CC4Group* const this, const char* const entryPath, const void* const data, size_t const size, int const memoryManagementMode);
+ bool (*setEntryData)(CC4Group* const this, const char* const entryPath, const void* const data, size_t const size, CC4Group_MemoryManagement const memoryManagementMode);
// group metadata handling
diff --git a/src/cppc4group.cpp b/src/cppc4group.cpp
index 8e2fe70..2d85537 100644
--- a/src/cppc4group.cpp
+++ b/src/cppc4group.cpp
@@ -54,7 +54,7 @@ namespace {
return cc4group.TmpMemoryStrategies.Auto;
}
- int convertMemoryManagement(const CppC4Group::MemoryManagement management)
+ CC4Group_MemoryManagement convertMemoryManagement(const CppC4Group::MemoryManagement management)
{
switch(management)
{