diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/cc4group.c | 85 | ||||
| -rw-r--r-- | src/cc4group.h | 8 | ||||
| -rw-r--r-- | src/cppc4group.cpp | 4 | ||||
| -rw-r--r-- | src/cppc4group.hpp | 3 |
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); |
