#pragma once // this is the main and only include file for cppc4group, the C++-wrapper for cc4group // because cc4group is already object-oriented, this is just a simple wrapper and almost all methods work exactly the same, just with C++-types // although, when dealing with raw memory (because cc4group can't know the type of the stored data) also users of this wrapper have to deal with some void* // because most methods behave exactly the same, please look at cc4group.h for their description (they are named exactly the same with a few exceptions) // in case their are real differences, they will be noted in this header also // until now, all except one example only use cc4group's C-API, but as a C++-programmer you should have no problems reading them anyway // one general difference to the C-API that is not mentioned at the individual methods is that functions actually returning data return an std::optional instead of a bool... // ...the optional will be populated normally and empty in error cases #include #include #include #include #include class CppC4Group { // all C-related stuff is hidden from this header so it doesn't land in the precious C++-only code this might be used in... // ...and pollute the root-namespace with various types that are better contained in this class instead struct Private; std::unique_ptr p; // this is only needed for internal purposes CppC4Group(std::unique_ptr&& p); public: // this struct is used for the getEntryData-method to return them in a uniform way (instead of using reference- or pointer-arguments) struct Data { // this will contain the information cc4group.getEntryData stores in its data argument const void* data; // and the same for size size_t size; // there should be no reason to construct one of these as API user, but it is needed internally Data(); Data(const void* const data, const size_t size); }; // this struct contains the same things as the CC4Group_EntryInfo struct of the C-version // member descriptions also apply equally here struct EntryInfo { std::string fileName; int32_t modified; std::string author; size_t size; size_t totalSize; bool executable; bool directory; bool official; }; // this struct is used in custom tmp memory strategies // instead of using additional pointer arguments to return the cleanup stuff everything is returned in a single one of this by the tmp memory strategy function struct TmpMemory { using TmpMemoryCleanupCallback = std::function; // memory needs to hold the readily allocated memory // it corresponds to the pointer that needs to be returned by C tmp memory strategies void* memory; // cleanup is a fancy std::function that will be called when the memory is not needed anymore // it receives the memory pointer stored above and the custom argument stored right below as arguments TmpMemoryCleanupCallback cleanup; // this can be set to arbitrary data needed by the cleanup callback to properly cleanup all used resources void* arg; // this is just a plain constructor setting each member accordingly TmpMemory(void* const memory, const TmpMemoryCleanupCallback& cleanup, void* const arg); }; public: // the C++ custom tmp memory strategy only receives the needed size as argument and must return an optional containing the information described above (TmpMemory) // or an empty optional on failure using TmpMemoryCallback = std::optional(*)(size_t size); // these are equivalent to their C counterparts using ReadCallback = bool(*)(const void** const data, size_t* const size, void* const arg); using SetupCallback = bool(*)(void* const arg); using WriteCallback = bool(*)(const void* const data, size_t const size, void* const arg); // these enums are just mapped to their C-counterparts internally enum TmpMemoryStrategy { Memory, File, Auto }; enum MemoryManagement { Take, Copy, Reference }; // use this to set one of the predefined strategies static void setTmpMemoryStrategy(const TmpMemoryStrategy strategy); // and this for your own custom strategy static void setTmpMemoryStrategy(const TmpMemoryCallback callback); public: // the constructor will automatically construct an internal CC4Group, so no new-equivalent method is needed // may throw std::bad_alloc if the allocation and construction of the internal CC4Group object fails CppC4Group(); // the move constructor is needed to move the returned group out of the optional from openAsChild CppC4Group(CppC4Group&& other); // the destructor will automatically delete the internal CC4Group, so also no extra method needed ~CppC4Group(); void create(); bool openExisting(const std::string& path); 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, SetupCallback initCallback = nullptr, SetupCallback deinitCallback = nullptr); // save actually maps to both cc4group.save and cc4group.saveOverwrite, thanks to default arguments (yes, thats the reason why they are separate in the C-API) bool save(const std::string& path, const bool overwrite = false); bool saveToFd(const int fd); bool saveToFilePointer(FILE* file); bool saveWithWriteCallback(const WriteCallback callback, void* const arg = nullptr, size_t bufferSize = 0); bool extractAll(const std::string& path); bool extractSingle(const std::string& entryPath, const std::string& targetPath); std::optional getEntryData(const std::string& path); std::string getErrorMessage(); int32_t getErrorCode(); std::string getErrorMethod(); std::string getErrorCauser(); bool setMaker(const std::string& maker, const std::string& path = "", const bool recursive = false); bool setCreation(const int32_t creation, const std::string& path = "", const bool recursive = false); bool setOfficial(const bool official, const std::string& path = "", const bool recursive = false); bool setExecutable(const bool executable, const std::string& path); std::optional getEntryInfo(const std::string& path = ""); std::optional> getEntryInfos(const std::string& path = ""); bool deleteEntry(const std::string& path, const bool recursive = false); bool renameEntry(const std::string& oldPath, const std::string& newPath); bool createDirectory(const std::string& path); bool createFile(const std::string& path); bool setEntryData(const std::string& path, const void* const data = nullptr, const size_t size = 0, const MemoryManagement management = Copy); // to get the child group out of the optional in case of success, construct a new CppC4Group with the move constructor: CppC4Group child{std::move(*optionalChild)}; std::optional openAsChild(const std::string& path); };