diff --git a/etk/archive/Archive.cpp b/etk/archive/Archive.cpp index ae98859..544e109 100644 --- a/etk/archive/Archive.cpp +++ b/etk/archive/Archive.cpp @@ -186,5 +186,21 @@ etk::Vector etk::Archive::list(const etk::Path& _path) { } return out; } +etk::Vector etk::Archive::listRecursive(const etk::Path& _path) { + etk::Vector 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 diff --git a/etk/archive/Archive.hpp b/etk/archive/Archive.hpp index eb3338d..39be297 100644 --- a/etk/archive/Archive.hpp +++ b/etk/archive/Archive.hpp @@ -193,6 +193,12 @@ namespace etk { * @return the full list of path in the _path. */ etk::Vector list(const etk::Path& _path); + /** + * @brief List the content of a specific path. + * @param[in] Path to parse. + * @return the full list of path in the _path. + */ + etk::Vector listRecursive(const etk::Path& _path); }; } #endif diff --git a/etk/io/Interface.hpp b/etk/io/Interface.hpp index b92ff53..792efb9 100644 --- a/etk/io/Interface.hpp +++ b/etk/io/Interface.hpp @@ -138,7 +138,7 @@ namespace etk { * @param[in] _value String data to write in the File * @return true the file is fully correcty write */ - bool fileWriteAll(const etk::String& _value) { + bool writeAll(const etk::String& _value) { return int64_t(_value.size()) == write(static_cast(&(_value[0])), sizeof(char), _value.size()/sizeof(char)); } }; diff --git a/etk/path/Path.cpp b/etk/path/Path.cpp index 139df6d..f07ca46 100644 --- a/etk/path/Path.cpp +++ b/etk/path/Path.cpp @@ -277,16 +277,51 @@ etk::String etk::Path::getFileName() const { } etk::String etk::Path::getExtention() const { - etk::String fileName = getFileName(); - size_t pos = fileName.rfind('.'); + size_t pos = m_data.rfind('.'); + size_t posSlash = m_data.rfind('/'); if (pos == etk::String::npos) { return ""; } - if (pos == 0) { + if ( posSlash != etk::String::npos + && posSlash > pos) { + return ""; + } + if ( pos == 0 + || ( posSlash != etk::String::npos + && posSlash == pos-1 + ) + ) { // a simple name started with a . return ""; } - return fileName.extract(pos+1); + return m_data.extract(pos+1); +} + +void etk::Path::removeExtention() { + size_t pos = m_data.rfind('.'); + size_t posSlash = m_data.rfind('/'); + if (pos == etk::String::npos) { + return; + } + if ( posSlash != etk::String::npos + && posSlash > pos) { + return; + } + if ( pos == 0 + || ( posSlash != etk::String::npos + && posSlash == pos-1 + ) + ) { + // a simple name started with a . + return; + } + m_data = m_data.extract(0, pos); +} + +etk::Path etk::Path::getExtentionRemoved() const { + etk::Path tmp(*this); + tmp.removeExtention(); + return tmp; } void etk::Path::parent() { diff --git a/etk/path/Path.hpp b/etk/path/Path.hpp index 3ac30bd..280361f 100644 --- a/etk/path/Path.hpp +++ b/etk/path/Path.hpp @@ -111,6 +111,15 @@ namespace etk { * @return * extention of the file. */ etk::String getExtention() const; + /** + * @brief remove extention of the file (all after the last '.'). + */ + void removeExtention(); + /** + * @brief Get a copy with the extention of the file removed. + * @return a copy of the path without extention + */ + etk::Path getExtentionRemoved() const; /** * @brief remove the last child element of the path. */ diff --git a/etk/path/fileSystem.cpp b/etk/path/fileSystem.cpp index 27b98ca..f915d34 100644 --- a/etk/path/fileSystem.cpp +++ b/etk/path/fileSystem.cpp @@ -474,7 +474,54 @@ uint32_t etk::path::getIdGroup(const etk::Path& _path) { return statProperty.st_gid; } -etk::Vector etk::path::list(const etk::Path& _path) { +etk::Vector etk::path::list(const etk::Path& _path, uint32_t _flags) { + etk::Vector out; + if (etk::path::isDirectory(_path) == false) { + return out; + } + DIR *dir = null; + struct dirent *ent = null; + dir = opendir(_path.getNative().c_str()); + if (dir != null) { + // for each element in the drectory... + while ((ent = readdir(dir)) != null) { + if( strcmp(ent->d_name, ".") == 0 + || strcmp(ent->d_name, "..") == 0 + || strlen(ent->d_name) == 0) { + // do nothing ... + continue; + } + etk::Path tmpPath = _path / ent->d_name; + if (_flags == etk::path::LIST_ALL) { + out.pushBack(tmpPath); + continue; + } + // Hidden file + if ( ent->d_name[0] == '.' + || (_flags & etk::path::LIST_HIDDEN) == 0) { + continue; + } + // FOLDER + if (etk::path::isDirectory(tmpPath) == true) { + if ((_flags & etk::path::LIST_FOLDER) != 0) { + out.pushBack(tmpPath); + } + continue; + } + // OTHER ==> clasify as file ==> 99.9999% of usage + if ((_flags & etk::path::LIST_FILE) != 0) { + out.pushBack(tmpPath); + } + } + closedir(dir); + } else { + TK_ERROR("could not open directory : '" << _path << "'"); + } + return out; +} + + +etk::Vector etk::path::listRecursive(const etk::Path& _path, uint32_t _flags) { etk::Vector out; if (etk::path::isDirectory(_path) == false) { return out; @@ -490,7 +537,37 @@ etk::Vector etk::path::list(const etk::Path& _path) { // do nothing ... continue; } - out.pushBack(_path / ent->d_name); + etk::Path tmpPath = _path / ent->d_name; + if (_flags == etk::path::LIST_ALL) { + out.pushBack(tmpPath); + if (etk::path::isDirectory(tmpPath) == true) { + for (auto& it: etk::path::listRecursive(tmpPath, _flags)) { + out.pushBack(it); + } + } + continue; + } + // Hidden file + if ( ent->d_name[0] == '.' + || (_flags & etk::path::LIST_HIDDEN) == 0) { + continue; + } + // FOLDER + if (etk::path::isDirectory(tmpPath) == true) { + if ((_flags & etk::path::LIST_FOLDER) != 0) { + out.pushBack(tmpPath); + } + if (etk::path::isDirectory(tmpPath) == true) { + for (auto& it: etk::path::listRecursive(tmpPath, _flags)) { + out.pushBack(it); + } + } + continue; + } + // OTHER ==> clasify as file ==> 99.9999% of usage + if ((_flags & etk::path::LIST_FILE) != 0) { + out.pushBack(tmpPath); + } } closedir(dir); } else { diff --git a/etk/path/fileSystem.hpp b/etk/path/fileSystem.hpp index 25ae8f7..78663f7 100644 --- a/etk/path/fileSystem.hpp +++ b/etk/path/fileSystem.hpp @@ -36,7 +36,6 @@ namespace etk { * @return false Operation Failed. */ bool copyFile(const etk::Path& _path1, const etk::Path& _path2); - /** * @brief Move a path to an other (if possible...) * @param[in] _path1 Path source. @@ -259,12 +258,25 @@ namespace etk { * @return Generic permission class. */ etk::path::Permissions getPermission(const etk::Path& _path); + + enum { + LIST_HIDDEN = 1<<1, + LIST_FOLDER = 1<<2, + LIST_FILE = 1<<3, + LIST_ALL = LIST_HIDDEN|LIST_FOLDER|LIST_FILE, + }; /** * @brief List the content of a specific path. * @param[in] Path to parse. * @return the full list of path in the _path. */ - etk::Vector list(const etk::Path& _path); + etk::Vector list(const etk::Path& _path, uint32_t _flags=etk::path::LIST_ALL); + /** + * @brief List the content of a specific path (recursively). + * @param[in] Path to parse. + * @return the full list of path in the _path. + */ + etk::Vector listRecursive(const etk::Path& _path, uint32_t _flags=etk::path::LIST_ALL); } } diff --git a/etk/uri/Query.cpp b/etk/uri/Query.cpp index 666796d..7065345 100644 --- a/etk/uri/Query.cpp +++ b/etk/uri/Query.cpp @@ -122,7 +122,7 @@ void etk::uri::Query::set(const etk::String& _key, const etk::String& _value) { m_data.set(_key, _value); } -bool etk::uri::Query::exist(const etk::String& _key) { +bool etk::uri::Query::exist(const etk::String& _key) const { return m_data.exist(_key); } diff --git a/etk/uri/Query.hpp b/etk/uri/Query.hpp index 9d518d3..ce8b7a8 100644 --- a/etk/uri/Query.hpp +++ b/etk/uri/Query.hpp @@ -57,7 +57,7 @@ namespace etk { * @return true Key exist. * @return false Unknown key. */ - bool exist(const etk::String& _key); + bool exist(const etk::String& _key) const; /** * @brief erase a specific key. * @param[in] _key Key of the query. diff --git a/etk/uri/Uri.cpp b/etk/uri/Uri.cpp index 3644bc3..2577e14 100644 --- a/etk/uri/Uri.cpp +++ b/etk/uri/Uri.cpp @@ -274,6 +274,10 @@ const etk::uri::Query& etk::Uri::getQuery() const { return m_query; } +etk::uri::Query& etk::Uri::getQuery() { + return m_query; +} + void etk::Uri::setQuery(const etk::uri::Query& _value) { m_query = _value; } diff --git a/etk/uri/Uri.hpp b/etk/uri/Uri.hpp index f128d38..c76e1e3 100644 --- a/etk/uri/Uri.hpp +++ b/etk/uri/Uri.hpp @@ -129,6 +129,7 @@ namespace etk { * @return query data. */ const etk::uri::Query& getQuery() const; + etk::uri::Query& getQuery(); /** * @brief Set the new query. * @param[in] _value Data. diff --git a/etk/uri/provider/Interface.hpp b/etk/uri/provider/Interface.hpp index a926265..5df6856 100644 --- a/etk/uri/provider/Interface.hpp +++ b/etk/uri/provider/Interface.hpp @@ -25,6 +25,7 @@ namespace etk { virtual ememory::SharedPtr create(const etk::Uri& _uri) = 0; virtual bool exist(const etk::Uri& _uri) = 0; virtual etk::Vector list(const etk::Uri& _uri) = 0; + virtual etk::Vector listRecursive(const etk::Uri& _uri) = 0; virtual bool canMove() { return false; } virtual bool move(const etk::Uri& _uriSource, const etk::Uri& _uriDestination) { return false; } }; diff --git a/etk/uri/provider/ProviderFile.cpp b/etk/uri/provider/ProviderFile.cpp index f6fc563..7176ffa 100644 --- a/etk/uri/provider/ProviderFile.cpp +++ b/etk/uri/provider/ProviderFile.cpp @@ -54,6 +54,29 @@ etk::Vector etk::uri::provider::ProviderFile::list(const etk::Uri& _ur return out; } +etk::Vector etk::uri::provider::ProviderFile::listRecursive(const etk::Uri& _uri) { + etk::Vector tmp; + etk::Vector out; + if (m_offset.isEmpty() == true) { + tmp = etk::path::listRecursive(_uri.getPath()); + for (auto& elem: tmp) { + etk::Uri newUri = _uri; + newUri.setPath(elem); + out.pushBack(newUri); + } + return out; + } + TK_VERBOSE("list path: " << m_offset / _uri.getPath()); + tmp = etk::path::listRecursive(m_offset / _uri.getPath()); + int32_t offset = m_offset.getString().size()+1; + for (auto& elem: tmp) { + etk::Uri newUri = _uri; + newUri.setPath(elem.getString().extract(offset)); + out.pushBack(newUri); + } + return out; +} + bool etk::uri::provider::ProviderFile::canMove() { return true; } diff --git a/etk/uri/provider/ProviderFile.hpp b/etk/uri/provider/ProviderFile.hpp index b3970cf..d641c7e 100644 --- a/etk/uri/provider/ProviderFile.hpp +++ b/etk/uri/provider/ProviderFile.hpp @@ -21,6 +21,7 @@ namespace etk { ememory::SharedPtr create(const etk::Uri& _uri) override; bool exist(const etk::Uri& _uri) override; etk::Vector list(const etk::Uri& _uri) override; + etk::Vector listRecursive(const etk::Uri& _uri) override; virtual bool canMove() override; virtual bool move(const etk::Uri& _uriSource, const etk::Uri& _uriDestination) override; }; diff --git a/etk/uri/provider/ProviderFileZip.cpp b/etk/uri/provider/ProviderFileZip.cpp index 2cc9700..95af103 100644 --- a/etk/uri/provider/ProviderFileZip.cpp +++ b/etk/uri/provider/ProviderFileZip.cpp @@ -59,3 +59,25 @@ etk::Vector etk::uri::provider::ProviderFileZip::list(const etk::Uri& } return out; } + +etk::Vector etk::uri::provider::ProviderFileZip::listRecursive(const etk::Uri& _uri) { + etk::Vector tmp; + etk::Vector out; + if (m_offset.isEmpty() == true) { + tmp = m_archive->listRecursive(_uri.getPath()); + for (auto& elem: tmp) { + etk::Uri newUri = _uri; + newUri.setPath(elem); + out.pushBack(newUri); + } + return out; + } + tmp = m_archive->listRecursive(m_offset / _uri.getPath()); + int32_t offset = m_offset.getString().size()+1; + for (auto& elem: tmp) { + etk::Uri newUri = _uri; + newUri.setPath(elem.getString().extract(offset)); + out.pushBack(newUri); + } + return out; +} diff --git a/etk/uri/provider/ProviderFileZip.hpp b/etk/uri/provider/ProviderFileZip.hpp index 436fdf4..a147f75 100644 --- a/etk/uri/provider/ProviderFileZip.hpp +++ b/etk/uri/provider/ProviderFileZip.hpp @@ -26,6 +26,7 @@ namespace etk { ememory::SharedPtr create(const etk::Uri& _uri) override; bool exist(const etk::Uri& _uri) override; etk::Vector list(const etk::Uri& _uri) override; + etk::Vector listRecursive(const etk::Uri& _uri) override; }; } } diff --git a/etk/uri/uri.cpp b/etk/uri/uri.cpp index c67b820..bd263bd 100644 --- a/etk/uri/uri.cpp +++ b/etk/uri/uri.cpp @@ -40,6 +40,16 @@ etk::Vector etk::uri::list(const etk::Uri& _uri) { return etk::uri::provider::getProviders()[scheme]->list(_uri); } +etk::Vector etk::uri::listRecursive(const etk::Uri& _uri) { + etk::String scheme = _uri.getScheme(); + if (scheme.empty() == true) { + scheme = "RAW"; + } + if (etk::uri::provider::getProviders().exist(scheme) == false) { + return etk::Vector(); + } + return etk::uri::provider::getProviders()[scheme]->listRecursive(_uri); +} ememory::SharedPtr etk::uri::get(const etk::Uri& _uri) { etk::String scheme = _uri.getScheme(); if (scheme.empty() == true) { @@ -98,7 +108,23 @@ bool etk::uri::writeAll(const etk::Uri& _uri, const etk::String& _data) { TK_ERROR("Can not open (w) the file : " << _uri); return false; } - fileIo->fileWriteAll(_data); + fileIo->writeAll(_data); fileIo->close(); return true; -} \ No newline at end of file +} + +bool etk::uri::readAll(const etk::Uri& _uri, etk::String& _data) { + auto fileIo = etk::uri::get(_uri); + if (fileIo == null) { + TK_ERROR("Can not create the uri: " << _uri); + return false; + } + if (fileIo->open(etk::io::OpenMode::Read) == false) { + TK_ERROR("Can not open (w) the file : " << _uri); + return false; + } + _data = fileIo->readAllString(); + fileIo->close(); + return true; +} + diff --git a/etk/uri/uri.hpp b/etk/uri/uri.hpp index 5a5b714..3c91e87 100644 --- a/etk/uri/uri.hpp +++ b/etk/uri/uri.hpp @@ -28,6 +28,12 @@ namespace etk { * @return list of sub-uri */ etk::Vector list(const etk::Uri& _uri); + /** + * @brief Get the list of sub-element in the Uri reursively + * @param[in] _uri Uri requested as parent. + * @return list of sub-uri + */ + etk::Vector listRecursive(const etk::Uri& _uri); /** * @brief Get an IO interface with a specific URI * @param[in] _uri Data interface requested @@ -54,5 +60,12 @@ namespace etk { * @return true All data are write, false otherwise. */ bool writeAll(const etk::Uri& _uri, const etk::String& _data); + /** + * @brief Read all a string in a uri (if possible) + * @param[in] _uri Uri destination. + * @param[out] _data Data readed. + * @return true All data are read, false otherwise. + */ + bool readAll(const etk::Uri& _uri, etk::String& _data); } }