#pragma once #ifdef __cplusplus extern "C" { #define this this_ #define new new_ #define delete delete_ #endif #include #include #include #include typedef struct { const char* fileName; int32_t modified; const char* author; size_t size; size_t totalSize; bool executable; bool directory; bool official; } CC4Group_EntryInfo; typedef struct CC4Group_t CC4Group; typedef void(*CC4Group_CleanupFunc)(void* data); typedef struct { CC4Group_CleanupFunc func; void* data; } CC4Group_CleanupJob; typedef void* (*CC4Group_TmpMemoryStrategy)(CC4Group* const this, const size_t size, CC4Group_CleanupJob* cleanupJob); // the callback has to store a pointer to the newly read data in data, as well as the amount of read data in size // the callback must return true if the end of data is reached or any read error happens and false otherwise // 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); void (*delete)(CC4Group* const this); // opens a group on the filesystem; path may point to a directory inside a group // only open an existing group on a frehsly created group object bool (*openExisting)(CC4Group* const this, const char* const path); // opens a group that is stored entirely in memory // only open an in-memory group on a frehsly created group object // 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 bool (*openMemory)(CC4Group* const this, const void* const groupData, size_t const size, int const memoryManagement); // opens a group through a file descriptor // the file descriptor must have been opened with read access; also be aware that the file must be opened with binary mode on windows bool (*openFd)(CC4Group* const this, int fd); // opens a group through a FILE* // 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; 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); // extraction to disk bool (*extractAll)(CC4Group* const this, const char* const targetPath); bool (*extractSingle)(CC4Group* const this, const char* const entryPath, const char* const targetPath); // the group owns the data pointed to. the pointer is valid until the group destructor is called bool (*getEntryData)(CC4Group* const this, const char* const entryPath, const void** const data, size_t* const size); // all error information is only meaningfully defined after any error ocurred (indicated by any method returning false) and always describes the last error that ocurred // returns a human readable error message, including the "error causer", an interpretation of the error code, the internal method in which the error occured ("error method") and possibly also the error code // the returned error message pointer is valid until the next call to getErrorMessage is issued or the group is destructed // this method may return NULL if memory allocation for the formatted message fails; so NULL should be considered as out of memory const char* (*getErrorMessage)(CC4Group* const this); // returns the error code of the last error; interpretation of this code depends on the internally used function that caused the error int32_t (*getErrorCode)(const CC4Group* const this); // returns the internal method name in which the error ocurred const char* (*getErrorMethod)(const CC4Group* const this); // returns human readable information during which operation the error occured const char* (*getErrorCauser)(const CC4Group* const this); struct { CC4Group_TmpMemoryStrategy Memory; CC4Group_TmpMemoryStrategy File; CC4Group_TmpMemoryStrategy Auto; } const TmpMemoryStrategies; 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 } const MemoryManagement; void (*setTmpMemoryStrategy)(const CC4Group_TmpMemoryStrategy strategy); // group metadata handling bool (*setMaker)(CC4Group* const this, const char* const maker, const char* const path, bool const recursive); bool (*setCreation)(CC4Group* const this, int32_t const creation, const char* const path, bool const recursive); bool (*setOfficial)(CC4Group* const this, bool const official, const char* const path, bool const recursive); bool (*setExecutable)(CC4Group* const this, bool const executable, const char* const path); bool (*getEntryInfo)(CC4Group* const this, const char* const path, CC4Group_EntryInfo* const info); bool (*getEntryInfos)(CC4Group* const this, const char* const path, CC4Group_EntryInfo** const infos, size_t* const size); // modifying the group bool (*deleteEntry)(CC4Group* const this, const char* const path, bool const recursive); bool (*renameEntry)(CC4Group* const this, const char* const oldPath, const char* const newPath); bool (*createDirectory)(CC4Group* const this, const char* const path); bool (*createFile)(CC4Group* const this, const char* const path); // 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); } const CC4Group_API; #ifndef CC4GROUP_DYNAMIC_LOAD extern CC4Group_API cc4group; #endif #ifdef __cplusplus } #undef this #undef new #undef delete #endif