etk/etk/archive/Archive.cpp

225 lines
5.8 KiB
C++

/** @file
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#ifdef ETK_BUILD_MINIZIP
#include <etk/archive/Archive.hpp>
#include <etk/archive/Zip.hpp>
#include <etk/debug.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(etk::Archive);
etk::Path etk::Archive::getName(size_t _id) const {
ethread::UniqueLock lock(m_mutex);
size_t id = 0;
for (auto &it : m_content) {
if (id == _id) {
return it.first;
}
++id;
}
return "";
}
ememory::SharedPtr<etk::ArchiveContent> etk::Archive::getContent(size_t _id) const {
ethread::UniqueLock lock(m_mutex);
size_t id = 0;
for (auto &it : m_content) {
if (id == _id) {
return it.second;
}
++id;
}
return null;
}
ememory::SharedPtr<etk::ArchiveContent> etk::Archive::getContent(const etk::Path& _key) const {
ethread::UniqueLock lock(m_mutex);
auto it = m_content.find(_key);
if (it == m_content.end()) {
return null;
}
return it->second;
}
bool etk::Archive::exist(const etk::Path& _key) const {
ethread::UniqueLock lock(m_mutex);
if (m_content.find(_key) != m_content.end()) {
return true;
}
return isDirectory(_key);
}
bool etk::Archive::isDirectory(const etk::Path& _key) const {
etk::String base = _key.getString() + "/";
for (auto &it: m_content) {
if (it.first.getString().startWith(base) == true) {
return true;
}
}
return false;
}
bool etk::Archive::isFile(const etk::Path& _key) const {
ethread::UniqueLock lock(m_mutex);
return m_content.find(_key) != m_content.end();
}
void etk::Archive::display() {
ethread::UniqueLock lock(m_mutex);
for (auto &it : m_content) {
int32_t size = it.second->getTheoricSize();
int32_t sizeR = it.second->size();
TK_INFO(" element : " << it.first << " size=" << size << " allocated=" << sizeR);
}
}
ememory::SharedPtr<etk::Archive> etk::Archive::load(const etk::Path& _fileName) {
ememory::SharedPtr<etk::Archive> output;
etk::String extention = _fileName.getExtention().toLower();
// select the corect Loader :
if( extention == "zip"
|| extention == ".apk") {
output = ememory::makeShared<etk::archive::Zip>(_fileName);
if (output == null) {
TK_ERROR("An error occured when load archive : " << _fileName);
}
} else {
TK_ERROR("Extention not managed '" << _fileName << "' Supported extention : .zip");
}
return output;
}
ememory::SharedPtr<etk::Archive> etk::Archive::load(const etk::Uri& _uri) {
ememory::SharedPtr<etk::Archive> output;
etk::String extention = _uri.getPath().getExtention().toLower();
// select the corect Loader :
if( extention == "zip"
|| extention == ".apk") {
output = ememory::makeShared<etk::archive::Zip>(_uri);
if (output == null) {
TK_ERROR("An error occured when load archive : " << _uri);
}
} else {
TK_ERROR("Extention not managed '" << _uri << "' Supported extention : .zip");
}
return output;
}
ememory::SharedPtr<etk::Archive> etk::Archive::loadPackage(const etk::Path& _fileName) {
ememory::SharedPtr<etk::Archive> output;
FILE* file = fopen(_fileName.getNative().c_str(), "rb");
if (file == null) {
TK_ERROR("Can not open file : '" << _fileName);
return null;
}
// move to end - 16 bytes:
fseek(file, -8, SEEK_END);
// get the basic binary size
uint64_t position = 0;
fread(&position, 1, sizeof(uint64_t), file);
TK_ERROR("position = " << position);
// move to the position
fseek(file, position, SEEK_SET);
char plop[1024];
fread(plop, 1, 16, file);
plop[16] = '\0';
// check if we have the mark: "***START DATA***" ==> if not ==> error
if (etk::String(plop) != "***START DATA***") {
TK_ERROR("Error in the tag file : '" << plop << "'");
fclose(file);
return null;
}
fclose(file);
file = null;
output = ememory::makeShared<etk::archive::Zip>(_fileName, position);
if (output == null) {
TK_ERROR("An error occured when load archive : " << _fileName);
}
return output;
}
void etk::Archive::open(const etk::Path& _key) {
ethread::UniqueLock lock(m_mutex);
auto it = m_content.find(_key);
if (it == m_content.end()) {
TK_ERROR("Try open an unexistant file : '" << _key << "'");
return;
}
if (it->second->getNumberOfRef()==-1) {
loadFile(it);
it->second->increaseRef();
}
it->second->increaseRef();
}
void etk::Archive::close(const etk::Path& _key) {
ethread::UniqueLock lock(m_mutex);
auto it = m_content.find(_key);
if (it == m_content.end()) {
TK_ERROR("Try close an unexistant file : '" << _key << "'");
return;
}
if (it->second->getNumberOfRef()==0){
TK_ERROR("Try close one more time the file : '" << _key << "'");
} else {
it->second->decreaseRef();
}
}
etk::Vector<etk::Path> etk::Archive::list(const etk::Path& _path) {
etk::Vector<etk::Path> out;
etk::String base = _path.getString();
for (auto& it: m_content) {
etk::String name = it.first.getString();
if (name.size() < base.size()) {
continue;
}
if (etk::start_with(name, base) == true) {
// element or subElement...
if (it.first.getParent() == _path) {
out.pushBack(it.first);
continue;
}
etk::String back = name.extract(base.size());
if ( back.size() == 0
|| back[0] != '/') {
continue;
}
back.erase(back.begin());
size_t pos = back.find('/');
if (pos == etk::String::npos) {
continue;
}
etk::String value = back.extract(0, pos);
etk::Path tmpppp = etk::Path(base) / value;
if (etk::isIn(tmpppp, out) == false) {
out.pushBack(tmpppp);
}
}
}
return out;
}
etk::Vector<etk::Path> etk::Archive::listRecursive(const etk::Path& _path) {
etk::Vector<etk::Path> out;
etk::String base = _path.getString();
for (auto& it: m_content) {
etk::String name = it.first.getString();
if (name.size() < base.size()) {
continue;
}
if (etk::start_with(name, base) == true) {
// element or subElement...
out.pushBack(it.first);
}
}
return out;
}
#endif