AbstractFSProvider::status_t ZIPProvider::makeDirRecursive(const FileName & url) { if(isDir(url)) { return AbstractFSProvider::OK; } std::string archiveFileName; FileName file; decomposeURL(url, archiveFileName, file); const std::string path = file.getPath(); // Split path into directory components size_t pos = 0; while(pos != path.size()) { pos = path.find('/', pos); if(pos == std::string::npos) { break; } const std::string subPath = path.substr(0, pos + 1); ++pos; if(makeDir(FileName(archiveFileName + '$' + subPath)) != AbstractFSProvider::OK) { return AbstractFSProvider::FAILURE; } } return AbstractFSProvider::OK; }
AbstractFSProvider::status_t ZIPProvider::ZIPHandle::makeDir(const FileName & directory) { int index = zip_add_dir(handle, directory.getPath().c_str()); if (index == -1) { WARN(zip_strerror(handle)); return FAILURE; } dataWritten = true; return OK; }
size_t ZIPProvider::ZIPHandle::fileSize(const FileName & file) { struct zip_stat sb; zip_stat_init(&sb); if (zip_stat(handle, file.getPath().c_str(), 0, &sb) == -1) { WARN(zip_strerror(handle)); return 0; } return static_cast<size_t>(sb.size); }
bool ZIPProvider::ZIPHandle::isFile(const FileName & file) { struct zip_stat sb; zip_stat_init(&sb); if (zip_stat(handle, file.getPath().c_str(), 0, &sb) == -1) { return false; } std::string entry(sb.name); return (entry.back() != '/' && sb.size != 0); }
AbstractFSProvider::status_t ZIPProvider::ZIPHandle::writeFile(const FileName & file, const std::vector<uint8_t> & data, bool overwrite) { if (file.getFile().empty()) { return FAILURE; } bool replace = false; int index = zip_name_locate(handle, file.getPath().c_str(), 0); if (index != -1) { // File already exists. if (!overwrite) { return FAILURE; } else { replace = true; } } // Store data temporary because libzip writes data not until zip_close. tempStore.emplace_back(data); zip_source * source = zip_source_buffer(handle, tempStore.back().data(), static_cast<off_t>(tempStore.back().size()), 0); if (source == nullptr) { WARN(zip_strerror(handle)); zip_source_free(source); tempStore.pop_back(); return FAILURE; } int newIndex; if (replace) { newIndex = zip_replace(handle, index, source); } else { newIndex = zip_add(handle, file.getPath().c_str(), source); } if (newIndex == -1) { WARN(zip_strerror(handle)); zip_source_free(source); tempStore.pop_back(); return FAILURE; } dataWritten = true; return OK; }
AbstractFSProvider::status_t ZIPProvider::ZIPHandle::removeDir(const FileName & directory) { int index = zip_name_locate(handle, directory.getPath().c_str(), 0); if (index == -1) { WARN(zip_strerror(handle)); return FAILURE; } if (zip_delete(handle, index) == -1) { WARN(zip_strerror(handle)); return FAILURE; } dataWritten = true; return OK; }
vector<KeyFrame> ModelLoaderMD3::buildKeyFrame(Surface * surfaces, const FileName &fileName, const FileName &skinName, const Header &header, TextureFactory &textureFactory) { vector<KeyFrame> keyFrames; const FileName directory = fileName.getPath(); /* Only the first frame loads texture files. The other frames use a copy of the handles and that copy is stored in here. */ Material md3Material; // Take the all the surfaces and push each frame into the mesh manager for (int i=0; i<surfaces[0].header.numFrames; ++i) { string name = fileName.str() + "#" + itos(i); // Create a mesh from the surface Mesh *mesh = surfaces[0].getObject(i); // Load a material for the first mesh in the first model. // First model only! Ignored for subsequent models if (i==0) { if (header.numSurfaces > 0) { mesh->material.clear(); #if 0 if (surfaces[0].header.numShaders > 0) { const char *shaderName=(char*)surfaces[0].shaders[0].name; FileName skin = directory.append(FileName(shaderName)); mesh->material.setTexture(textureFactory.load(skin)); } else { mesh->material.setTexture(textureFactory.load(skinName)); } #else mesh->material.setTexture(textureFactory.load(skinName)); #endif // Keep a copy of the material to propagate to the subsequent frames md3Material = mesh->material; } } else { mesh->material = md3Material; // shallow copy } keyFrames.push_back(KeyFrame(mesh)); } return keyFrames; }
void ZIPProvider::decomposeURL(const FileName & url, std::string & archiveFileName, FileName & localPath) { const std::string path = url.getPath(); const std::size_t splitPos = path.find('$'); if (splitPos == std::string::npos) { archiveFileName = path; localPath = std::string(""); } else { archiveFileName = path.substr(0, splitPos); // Strip off './' at the beginning. if(path.compare(splitPos + 1, 2, "./") == 0) { localPath = path.substr(splitPos + 3); } else if(path.compare(splitPos + 1, 1, "/") == 0) { // strip beginning '/' localPath = path.substr(splitPos + 2); } else { localPath = path.substr(splitPos + 1); } } }
AbstractFSProvider::status_t ZIPProvider::ZIPHandle::readFile(const FileName & file, std::vector<uint8_t> & data) { if (file.getFile().empty()) { return FAILURE; } const size_t size = fileSize(file); if (size == 0) { return FAILURE; } zip_file * fileHandle = zip_fopen(handle, file.getPath().c_str(), 0); if (fileHandle == nullptr) { WARN(zip_strerror(handle)); return FAILURE; } data.resize(size); const int bytesRead = zip_fread(fileHandle, data.data(), data.size()); if (bytesRead == -1) { WARN(zip_strerror(handle)); zip_fclose(fileHandle); return FAILURE; } if (static_cast<size_t>(bytesRead) != size) { WARN("Sizes differ during read."); zip_fclose(fileHandle); return FAILURE; } if (zip_fclose(fileHandle) == -1) { WARN(zip_strerror(handle)); return FAILURE; } return OK; }