summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2019-03-16 15:57:50 +0100
committerMarkus Mittendrein <git@maxmitti.tk>2019-03-16 15:57:50 +0100
commit58bc74b6fdd58e870e2bbb1503148f79f0726306 (patch)
treeec51a3806d0709551c3933d2934a8a152351470b
parent673a447f292c07ad5399211f823ec45771bea07b (diff)
downloadcc4group-58bc74b6fdd58e870e2bbb1503148f79f0726306.tar.gz
cc4group-58bc74b6fdd58e870e2bbb1503148f79f0726306.zip
Add initCallback and deinitCallback for openWithReadCallback
-rw-r--r--src/cc4group.c85
-rw-r--r--src/cc4group.h8
-rw-r--r--src/cppc4group.cpp4
-rw-r--r--src/cppc4group.hpp3
4 files changed, 69 insertions, 31 deletions
diff --git a/src/cc4group.c b/src/cc4group.c
index e126984..48fa931 100644
--- a/src/cc4group.c
+++ b/src/cc4group.c
@@ -411,10 +411,10 @@ static bool cc4group_inflateFillOutput(z_stream* const strm, CC4Group_ReadCallba
return ret == Z_OK || (ret == Z_STREAM_END && strm->avail_in == 0 && eof);
}
-static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback const callback, void* const callbackArg, int const memoryManagement)
+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)
{
assert(this);
- assert(callback);
+ assert(readCallback);
assert(callbackArg);
// only if the group is still empty
@@ -428,6 +428,14 @@ static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback
CC4Group_CleanupJob tmpCleanup;
uint8_t* mappedTmpFile = NULL;
+ if(initCallback != NULL)
+ {
+ if(!initCallback(callbackArg))
+ {
+ SET_MESSAGE_ERROR("The initCallback failed");
+ return false;
+ }
+ }
size_t totalReadSize = 0;
@@ -447,13 +455,14 @@ static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback
readData = NULL;
readSize = 0;
- eof = callback((const void**)&readData, &readSize, callbackArg);
+ eof = readCallback((const void**)&readData, &readSize, callbackArg);
if(readSize == 0)
{
continue;
}
+ // TODO: check for success at every call of this
cc4group_applyMemoryManagementStart(memoryManagement, &readData, readSize);
size_t newTotalReadSize = totalReadSize + readSize;
@@ -527,7 +536,7 @@ static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback
strm.avail_in = totalReadSize - 2;
}
- if(!cc4group_inflateFillOutput(&strm, callback, callbackArg, memoryManagement, &eof, &readData, &ret))
+ if(!cc4group_inflateFillOutput(&strm, readCallback, callbackArg, memoryManagement, &eof, &readData, &ret))
{
if(eof && ret == Z_BUF_ERROR)
{
@@ -587,7 +596,7 @@ static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback
strm.next_out = (Bytef*)cores;
strm.avail_out = sizeof(C4GroupEntryCore) * header->Entries;
- if(!cc4group_inflateFillOutput(&strm, callback, callbackArg, memoryManagement, &eof, &readData, &ret))
+ if(!cc4group_inflateFillOutput(&strm, readCallback, callbackArg, memoryManagement, &eof, &readData, &ret))
{
if(eof && ret == Z_BUF_ERROR)
{
@@ -615,7 +624,7 @@ static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback
strm.next_out = data;
strm.avail_out = uncompressedSize;
- if(!cc4group_inflateFillOutput(&strm, callback, callbackArg, memoryManagement, &eof, &readData, &ret))
+ if(!cc4group_inflateFillOutput(&strm, readCallback, callbackArg, memoryManagement, &eof, &readData, &ret))
{
if(eof && ret == Z_BUF_ERROR)
{
@@ -628,6 +637,14 @@ static bool cc4group_uncompressGroup(CC4Group* const this, CC4Group_ReadCallback
goto ret;
}
+ if(deinitCallback != NULL)
+ {
+ if(!deinitCallback(callbackArg))
+ {
+ fprintf(stderr, "WARNING: cc4group_uncompressGroup: the deinitCallback failed\n");
+ }
+ }
+
if(strm.avail_in > 0 || ret != Z_STREAM_END)
{
SET_MALFORMED_MESSAGE_ERROR("The group contents are read completely but more data is left to read");
@@ -684,41 +701,55 @@ static bool cc4group_completeDataReadCallback(const void** const data, size_t* c
return true;
}
-static bool cc4group_readFdReadCallback(const void** const data, size_t* const size, void* callbackArg)
+typedef struct {
+ void* arg;
+ void* buffer;
+} ChunkedReadData;
+
+static bool cc4group_initChunkBufferCallback(void* callbackArg)
{
#define CHUNK_SIZE 1000*1000
- void* readData = malloc(CHUNK_SIZE);
- if(data == NULL)
+ void* buffer = malloc(CHUNK_SIZE);
+
+ if(buffer == NULL)
{
- return true;
+ return false;
}
- ssize_t count = read(*(int*)callbackArg, readData, CHUNK_SIZE);
+ ((ChunkedReadData*)callbackArg)->buffer = buffer;
+ return true;
+}
+
+static bool cc4group_deinitChunkBufferCallback(void* callbackArg)
+{
+ free(((ChunkedReadData*)callbackArg)->buffer);
+ return true;
+}
+
+static bool cc4group_readFdReadCallback(const void** const data, size_t* const size, void* callbackArg)
+{
+ ChunkedReadData* arg = callbackArg;
+ void* buffer = arg->buffer;
+ ssize_t count = read(*(int*)arg->arg, buffer, CHUNK_SIZE);
if(count > 0)
{
- *data = readData;
+ *data = buffer;
*size = count;
return false;
}
return true;
-#undef CHUNK_SIZE
}
static bool cc4group_readFilePointerReadCallback(const void** const data, size_t* const size, void* callbackArg)
{
-#define CHUNK_SIZE 1000*1000
- void* readData = malloc(CHUNK_SIZE);
- if(data == NULL)
- {
- return true;
- }
-
- size_t count = fread(readData, 1, CHUNK_SIZE, callbackArg);
+ ChunkedReadData* arg = callbackArg;
+ void* buffer = arg->buffer;
+ size_t count = fread(buffer, 1, CHUNK_SIZE, arg->arg);
if(count > 0)
{
- *data = readData;
+ *data = buffer;
*size = count;
return false;
}
@@ -733,7 +764,7 @@ static bool cc4group_openMemory(CC4Group* const this, const void* const compress
assert(size);
CompleteDataReadCallbackArg data = {.data = compressedData, .size = size};
- return cc4group_uncompressGroup(this, cc4group_completeDataReadCallback, &data, memoryManagement);
+ return cc4group_uncompressGroup(this, cc4group_completeDataReadCallback, &data, memoryManagement, NULL, NULL);
}
static bool cc4group_setSubRoot(CC4Group* const this, const char* const subPath)
@@ -832,7 +863,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);
+ success = cc4group_uncompressGroup(this, cc4group_completeDataReadCallback, &data, Reference, NULL, NULL);
ret:
if(mappedFile != MAP_FAILED)
@@ -1042,12 +1073,14 @@ static bool cc4group_create(CC4Group* const this)
static bool cc4group_openFd(CC4Group* const this, int fd)
{
- return cc4group_uncompressGroup(this, cc4group_readFdReadCallback, &fd, Take);
+ ChunkedReadData arg = {.arg = &fd};
+ return cc4group_uncompressGroup(this, cc4group_readFdReadCallback, &arg, Reference, cc4group_initChunkBufferCallback, cc4group_deinitChunkBufferCallback);
}
static bool cc4group_openFilePointer(CC4Group* const this, FILE* file)
{
- return cc4group_uncompressGroup(this, cc4group_readFilePointerReadCallback, file, Take);
+ ChunkedReadData arg = {.arg = file};
+ return cc4group_uncompressGroup(this, cc4group_readFilePointerReadCallback, &arg, Reference, cc4group_initChunkBufferCallback, cc4group_deinitChunkBufferCallback);
}
static bool cc4group_openExisting(CC4Group* const this, const char* const path)
diff --git a/src/cc4group.h b/src/cc4group.h
index cc04a4f..76a0970 100644
--- a/src/cc4group.h
+++ b/src/cc4group.h
@@ -37,6 +37,10 @@ typedef void* (*CC4Group_TmpMemoryStrategy)(CC4Group* const this, const size_t s
// the pointer passed in will be handled as specified with the corresponding MemoryManagement
typedef bool (*CC4Group_ReadCallback)(const void** const data, size_t* const size, void* const arg);
+// can be used as initialization before and deinitialization after all necessary calls to a read callback are made; for instance for buffer allocation and deletion
+// the callback should return true on success and false on failure
+typedef bool (*CC4Group_ReadSetupCallback)(void* const arg);
+
typedef struct {
CC4Group* (*new)(void);
bool (*create)(CC4Group* const this);
@@ -60,8 +64,8 @@ typedef struct {
// the file must have been opened with read access; also be aware that the file must be opened with binary mode on windows
bool (*openFilePointer)(CC4Group* const this, FILE* fd);
- // opens a group and calls the callback to get the group data
- bool (*openWithReadCallback)(CC4Group* const this, CC4Group_ReadCallback const callback, void* const callbackArg, int const memoryManagement);
+ // opens a group and calls the callback to get the group data; 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
+ bool (*openWithReadCallback)(CC4Group* const this, CC4Group_ReadCallback const readCallback, void* const callbackArg, int const memoryManagement, CC4Group_ReadSetupCallback const initCallback, CC4Group_ReadSetupCallback const deinitCallback);
bool (*save)(CC4Group* const this, const char* const path);
bool (*saveOverwrite)(CC4Group* const this, const char* const path);
diff --git a/src/cppc4group.cpp b/src/cppc4group.cpp
index b76e220..464dc88 100644
--- a/src/cppc4group.cpp
+++ b/src/cppc4group.cpp
@@ -91,9 +91,9 @@ bool CppC4Group::openMemory(const void* const data, const size_t size, const Mem
return cc4group.openMemory(p->g, data, size, convertMemoryManagement(management));
}
-bool CppC4Group::openWithReadCallback(const ReadCallback callback, void* const callbackArg, const MemoryManagement management)
+bool CppC4Group::openWithReadCallback(const ReadCallback callback, void* const callbackArg, const MemoryManagement management, SetupCallback initCallback, SetupCallback deinitCallback)
{
- return cc4group.openWithReadCallback(p->g, callback, callbackArg, convertMemoryManagement(management));
+ return cc4group.openWithReadCallback(p->g, callback, callbackArg, convertMemoryManagement(management), initCallback, deinitCallback);
}
bool CppC4Group::save(const std::string& path, const bool overwrite)
diff --git a/src/cppc4group.hpp b/src/cppc4group.hpp
index 0787c97..78370d9 100644
--- a/src/cppc4group.hpp
+++ b/src/cppc4group.hpp
@@ -32,6 +32,7 @@ public:
public:
using ReadCallback = bool(*)(const void** const data, size_t* const size, void* const arg);
+ using SetupCallback = bool(*)(void* const arg);
enum TmpMemoryStrategy {
Memory,
@@ -56,7 +57,7 @@ public:
bool openFd(const int fd);
bool openFilePointer(FILE* file);
bool openMemory(const void* const data, const size_t size, const MemoryManagement management = Reference);
- bool openWithReadCallback(const ReadCallback callback, void* const callbackArg, const MemoryManagement management = Take);
+ bool openWithReadCallback(const ReadCallback callback, void* const callbackArg, const MemoryManagement management = Take, SetupCallback initCallback = nullptr, SetupCallback deinitCallback = nullptr);
bool save(const std::string& path, const bool overwrite = false);
bool extractAll(const std::string& path);