#include "cppc4group.hpp" #include "cc4group.h" CppC4Group::Data::Data() : data{nullptr}, size{0} { } CppC4Group::Data::Data(const void* const data, const size_t size) : data{data}, size{size} { } CppC4Group::TmpMemory::TmpMemory(void* const memory, const TmpMemoryCleanupCallback& cleanup, void *const arg) : memory(memory), cleanup(cleanup), arg(arg) { } struct CppC4Group::Private { CC4Group* g; Private() : g{cc4group.new_()} { if(g == nullptr) { throw std::bad_alloc(); } } Private(CC4Group* g) : g{g} { } ~Private() { cc4group.delete_(g); } }; namespace { CC4Group_TmpMemoryStrategy convertTmpMemoryStrategy(const CppC4Group::TmpMemoryStrategy strategy) { switch(strategy) { case CppC4Group::Auto: return cc4group.TmpMemoryStrategies.Auto; case CppC4Group::File: return cc4group.TmpMemoryStrategies.File; case CppC4Group::Memory: return cc4group.TmpMemoryStrategies.Memory; } return cc4group.TmpMemoryStrategies.Auto; } int convertMemoryManagement(const CppC4Group::MemoryManagement management) { switch(management) { case CppC4Group::Take: return cc4group.MemoryManagement.Take; case CppC4Group::Copy: return cc4group.MemoryManagement.Copy; case CppC4Group::Reference: return cc4group.MemoryManagement.Reference; } return cc4group.MemoryManagement.Copy; } } CppC4Group::CppC4Group() : p{new CppC4Group::Private{}} { } CppC4Group::CppC4Group(CppC4Group&& other) : p{std::move(other.p)} { } CppC4Group::CppC4Group(std::unique_ptr&& p) : p{std::move(p)} { } CppC4Group::~CppC4Group() { } bool CppC4Group::create() { return cc4group.create(p->g); } bool CppC4Group::openExisting(const std::string& path) { return cc4group.openExisting(p->g, path.c_str()); } bool CppC4Group::openFd(const int fd) { return cc4group.openFd(p->g, fd); } bool CppC4Group::openFilePointer(FILE* file) { return cc4group.openFilePointer(p->g, file); } bool CppC4Group::openMemory(const void* const data, const size_t size, const MemoryManagement management) { return cc4group.openMemory(p->g, data, size, convertMemoryManagement(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), initCallback, deinitCallback); } bool CppC4Group::save(const std::string& path, const bool overwrite) { return (overwrite ? cc4group.saveOverwrite : cc4group.save)(p->g, path.c_str()); } bool CppC4Group::saveToFd(const int fd) { return cc4group.saveToFd(p->g, fd); } bool CppC4Group::saveToFilePointer(FILE* file) { return cc4group.saveToFilePointer(p->g, file); } bool CppC4Group::saveWithWriteCallback(const CppC4Group::WriteCallback callback, void *const arg, size_t bufferSize) { return cc4group.saveWithWriteCallback(p->g, callback, arg, bufferSize); } bool CppC4Group::extractAll(const std::string& path) { return cc4group.extractAll(p->g, path.c_str()); } bool CppC4Group::extractSingle(const std::string& entryPath, const std::string& targetPath) { return cc4group.extractSingle(p->g, entryPath.c_str(), targetPath.c_str()); } std::optional CppC4Group::getEntryData(const std::string& path) { const void* data; size_t size; if(cc4group.getEntryData(p->g, path.c_str(), &data, &size)) { return std::make_optional(data, size); } else { return {}; } } std::string CppC4Group::getErrorMessage() { return cc4group.getErrorMessage(p->g); } int32_t CppC4Group::getErrorCode() { return cc4group.getErrorCode(p->g); } std::string CppC4Group::getErrorMethod() { return cc4group.getErrorMethod(p->g); } std::string CppC4Group::getErrorCauser() { return cc4group.getErrorCauser(p->g); } void CppC4Group::setTmpMemoryStrategy(const TmpMemoryStrategy strategy) { cc4group.setTmpMemoryStrategy(convertTmpMemoryStrategy(strategy)); } namespace { static CppC4Group::TmpMemoryCallback tmpMemoryCallback = nullptr; void* customTmpMemoryStrategy(CC4Group* const, size_t size, CC4Group_CleanupJob* cleanup) { if(const auto& tmpMemory = tmpMemoryCallback(size)) { auto tmpMemorySettings = new CppC4Group::TmpMemory(*tmpMemory); *cleanup = CC4Group_CleanupJob{[](void* arg){ auto tmpMemory = reinterpret_cast(arg); tmpMemory->cleanup(tmpMemory->memory, tmpMemory->arg); delete tmpMemory; }, static_cast(tmpMemorySettings)}; return tmpMemorySettings->memory; } return nullptr; } } void CppC4Group::setTmpMemoryStrategy(const TmpMemoryCallback callback) { tmpMemoryCallback = callback; cc4group.setTmpMemoryStrategy(customTmpMemoryStrategy); } bool CppC4Group::setMaker(const std::string& maker, const std::string& path, const bool recursive) { return cc4group.setMaker(p->g, maker.c_str(), path.c_str(), recursive); } bool CppC4Group::setCreation(const int32_t creation, const std::string& path, const bool recursive) { return cc4group.setCreation(p->g, creation, path.c_str(), recursive); } bool CppC4Group::setOfficial(const bool official, const std::string& path, const bool recursive) { return cc4group.setOfficial(p->g, official, path.c_str(), recursive); } bool CppC4Group::setExecutable(const bool executable, const std::string& path) { return cc4group.setExecutable(p->g, executable, path.c_str()); } namespace { CppC4Group::EntryInfo& fillEntryInfo(CppC4Group::EntryInfo& info, const CC4Group_EntryInfo& entryInfo) { info.fileName = entryInfo.fileName; info.modified = entryInfo.modified; info.author = entryInfo.author; info.size = entryInfo.size; info.totalSize = entryInfo.totalSize; info.executable = entryInfo.executable; info.directory = entryInfo.directory; info.official = entryInfo.official; return info; } }; std::optional CppC4Group::getEntryInfo(const std::string& path) { CC4Group_EntryInfo info; if(cc4group.getEntryInfo(p->g, path.c_str(), &info)) { auto entryInfo = std::make_optional(); fillEntryInfo(*entryInfo, info); return entryInfo; } else { return {}; } } std::optional> CppC4Group::getEntryInfos(const std::string& path) { CC4Group_EntryInfo* infos; size_t infoCount; if(cc4group.getEntryInfos(p->g, path.c_str(), &infos, &infoCount)) { auto entryInfos = std::make_optional>(infoCount); for(size_t i = 0; i < infoCount; ++i) { fillEntryInfo((*entryInfos)[i], infos[i]); } free(infos); return entryInfos; } else { return {}; } } bool CppC4Group::deleteEntry(const std::string& path, const bool recursive) { return cc4group.deleteEntry(p->g, path.c_str(), recursive); } bool CppC4Group::renameEntry(const std::string& oldPath, const std::string& newPath) { return cc4group.renameEntry(p->g, oldPath.c_str(), newPath.c_str()); } bool CppC4Group::createDirectory(const std::string& path) { return cc4group.createDirectory(p->g, path.c_str()); } bool CppC4Group::createFile(const std::string& path) { return cc4group.createFile(p->g, path.c_str()); } bool CppC4Group::setEntryData(const std::string& path, const void*const data, const size_t size, const MemoryManagement management) { return cc4group.setEntryData(p->g, path.c_str(), data, size, convertMemoryManagement(management)); } std::optional CppC4Group::openAsChild(const std::string& path) { auto g = cc4group.openAsChild(p->g, path.c_str()); if(g == nullptr) { return {}; } else { return {{std::make_unique(g)}}; } }