[DEV] path and filesystem start to be good

This commit is contained in:
Edouard DUPIN 2018-09-03 00:39:49 +02:00
parent 5a1160fb89
commit f6ffdb9b25
16 changed files with 854 additions and 438 deletions

View File

@ -28,7 +28,7 @@ void etk::unInit() {
nbTimeInit = 0;
return;
}
etk::theme::uninit();
etk::theme::unInit();
TK_INFO("ETK system un-init (BEGIN)");
ETK_MEM_SHOW_LOG();
TK_INFO("ETK system un-init (END)");

View File

@ -4,7 +4,8 @@
* @license MPL v2.0 (see license file)
*/
#include <etk/fileSystem/Path.hpp>
#include <etk/log.hpp>
#include <etk/debug.hpp>
#include <etk/Exception.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(etk::Path);
@ -12,183 +13,204 @@ ETK_DECLARE_TYPE(etk::Path);
//#define TK_DBG_MODE TK_VERBOSE
#define TK_DBG_MODE TK_WARNING
static etk::Pair<etk::fileSystem::Type, etk::String> parsePath(etk::String _path) {
// Reset ALL DATA :
m_data = "";
m_type = etk::fileSystem::Type::Unknow;
TK_DBG_MODE("1 : Set Name : \"" << _path << "\"");
#ifdef __TARGET_OS__Windows
_path.replace("\\", "/");
for (char iii='a' ; iii<='z' ; iii++) {
char tmpVal[10];
char tmpDest[10];
sprintf(tmpVal, "%c:/", iii);
sprintf(tmpDest, "/%c/", iii);
if(etk::start_with(_path, tmpVal) == true) {
_path.replace(tmpVal, tmpDest);
break;
}
static etk::String simplifyPath(etk::String _input) {
// step 1 : for windows change \ in /:
TK_DEBUG("Simplify(1) : '" << _input << "'");
size_t currentPos = 0;
if (_input.size() == 0) {
return _input;
}
while(currentPos < _input.size()) {
if (_input[currentPos] == '\\') {
_input[currentPos] = '/';
}
for (char iii='A' ; iii<='Z' ; iii++) {
char tmpVal[10];
char tmpDest[10];
sprintf(tmpVal, "%c:/", iii);
sprintf(tmpDest, "/%c/", iii+'a'-'A');
if(etk::start_with(_path, tmpVal) == true) {
_path.replace(tmpVal, tmpDest);
break;
currentPos++;
continue;
}
// step 2 : remove all '//'
TK_DBG_MODE("Simplify(2) : '" << _input << "'");
currentPos = 0;
if (_input.size() <= 1) {
return _input;
}
while(currentPos < _input.size()-1) {
if ( _input[currentPos] != '/'
|| _input[currentPos+1] != '/') {
currentPos++;
continue;
}
_input.erase(currentPos, 1);
}
// step 3 : remove all '/./'
TK_DBG_MODE("Simplify(3) : '" << _input << "'");
currentPos = 0;
if (_input.size() <= 1) {
return _input;
}
while( currentPos < _input.size()-2
&& _input.size() > 2) {
if ( _input[currentPos] != '/'
|| _input[currentPos+1] != '.'
|| _input[currentPos+2] != '/') {
currentPos++;
continue;
}
_input.erase(currentPos, 2);
}
if (end_with(_input, "/.") == true) {
_input.erase(_input.size()-1, 1);
}
// step 4 remove xxx/..
TK_DBG_MODE("Simplify(4) : '" << _input << "'");
size_t lastSlashPos = etk::String::npos;
currentPos = 0;
while( currentPos < _input.size()-2
&& _input.size() > 2) {
if ( _input[currentPos] != '/'
|| _input[currentPos+1] != '.'
|| _input[currentPos+2] != '.') {
if (_input[currentPos] == '/') {
lastSlashPos = currentPos;
}
currentPos++;
continue;
}
if (lastSlashPos == etk::String::npos) {
currentPos++;
continue;
}
_input.erase(lastSlashPos, currentPos+2-lastSlashPos+1);
TK_DEBUG("update : '" << _input << "'");
lastSlashPos = etk::String::npos;
currentPos = 0;
}
TK_DBG_MODE("Simplify(5) : '" << _input << "'");
if (_input.size() == 0) {
_input = "/";
}
#ifdef __TARGET_OS__Windows
etk::String base;
base += _input[0];
base += ":";
if ( _input == base + "/../"
|| _input == base + "/.."
|| _input == base + "/./"
|| _input == base + "/."
|| _input == "/") {
_input = base + "/";
}
#else
if ( _input == "/../"
|| _input == "/.."
|| _input == "/./"
|| _input == "/.") {
_input = "/";
}
#endif
// generate destination name in case of the input error
if (_path.size() == 0) {
// if no name ==> go to the root Folder
_path = "ROOT:";
}
if (_path[0] == '/') {
TK_DBG_MODE(" ==> detect root");
_path.erase(0, 1);
m_type = etk::fileSystem::Type::Direct;
} else if (start_with(_path, "ROOT:", false) == true) {
TK_DBG_MODE(" ==> detect root 2 ");
_path.erase(0, 5);
m_type = etk::fileSystem::Type::Direct;
if(start_with(_path, "~") == true) {
_path.erase(0, 1);
m_type = etk::fileSystem::Type::Home;
}
} else if (start_with(_path, "DIRECT:", false) == true) {
TK_DBG_MODE(" ==> detect direct");
_path.erase(0, 7);
m_type = etk::fileSystem::Type::Direct;
if(start_with(_path, "~") == true) {
_path.erase(0, 1);
m_type = etk::fileSystem::Type::Home;
}
} else if (start_with(_path, "DATA:", false) == true) {
TK_DBG_MODE(" ==> detect data");
_path.erase(0, 5);
m_type = etk::fileSystem::Type::Data;
} else if (start_with(_path, "USERDATA:", false) == true) {
TK_DBG_MODE(" ==> detect User-data");
_path.erase(0, 9);
m_type = etk::fileSystem::Type::UserData;
} else if (start_with(_path, "CACHE:", false) == true) {
TK_DBG_MODE(" ==> detect Cache");
_path.erase(0, 6);
m_type = etk::fileSystem::Type::Cache;
} else if (start_with(_path, "THEME:", false) == true) {
TK_DBG_MODE(" ==> detect theme");
_path.erase(0, 6);
m_type = etk::fileSystem::Type::Theme;
} else if (start_with(_path, "./") == true) {
TK_DBG_MODE(" ==> detect relatif 1");
_path.erase(0, 2);
while (_path.size()>0 && _path[0] == '/') {
_path.erase(0, 1);
}
m_type = etk::FSNType_relatif;
} else if (start_with(_path, "REL:", false) == true) {
TK_DBG_MODE(" ==> detect relatif 2");
_path.erase(0, 4);
while (_path.size()>0 && _path[0] == '/') {
_path.erase(0, 1);
}
m_type = etk::FSNType_relatif;
} else if (start_with(_path, baseRunPath) == true) {
TK_DBG_MODE(" ==> detect relatif 3 (run path=" << baseRunPath << ")");
_path.erase(0, baseRunPath.size());
while (_path.size()>0 && _path[0] == '/') {
_path.erase(0, 1);
}
m_type = etk::FSNType_relatif;
} else if (( baseRunPath != baseRunPathInHome
&& ( start_with(_path, "~" + baseRunPathInHome) == true
|| start_with(_path, "HOME:" + baseRunPathInHome, false) == true ) ) ) {
TK_DBG_MODE(" ==> detect relatif 4");
if (start_with(_path, "~" + baseRunPathInHome) == true) {
_path.erase(0, 1);
} else {
_path.erase(0, 5);
}
_path.erase(0, baseRunPathInHome.size());
while (_path.size()>0 && _path[0] == '/') {
_path.erase(0, 1);
}
m_type = etk::FSNType_relatif;
} else if (start_with(_path, "~")) {
TK_DBG_MODE(" ==> detect home 2");
_path.erase(0, 1);
m_type = etk::fileSystem::Type::Home;
} else if (start_with(_path, "HOME:", false) == true ) {
TK_DBG_MODE(" ==> detect home 3");
_path.erase(0, 5);
m_type = etk::fileSystem::Type::Home;
if(start_with(_path, "~") == true) {
_path.erase(0, 1);
}
} else if (start_with(_path, baseFolderHome) == true) {
TK_DBG_MODE(" ==> detect home");
_path.erase(0, baseFolderHome.size());
m_type = etk::fileSystem::Type::Home;
} else {
TK_DBG_MODE(" ==> detect other");
// nothing to remove
//Other type is Relative :
m_type = etk::FSNType_relatif;
}
m_data = _path;
TK_DBG_MODE("3 : parse done : [" << m_type << "]->\"" << m_data << "\"");
// Now we reduce the path with all un-needed ../ and other thinks ...
// TODO : Do it whith link and the other sub thinks ...
m_userFileName = simplifyPath(m_userFileName);
TK_DBG_MODE("4 : Path simplification : [" << m_type << "]->\"" << m_userFileName << "\"");
// Now we generate the real FS path:
generateFileSystemPath();
TK_DBG_MODE("5 : file System Real name : \"" << m_systemFileName << "\"");
// now we get all the right if the file existed:
updateFileSystemProperty();
TK_DBG_MODE("6 : type : [" << m_typeNode << "] right :" << m_rights);
TK_DEBUG("Simplify(end) : '" << _input << "'");
return _input;
}
static etk::String parsePath(etk::String _path) {
etk::String out = _path;
TK_DBG_MODE("1 : Set Name : '" << out << "'");
// Replace all time to prevent Windows user error when port on Unix
out.replace("\\", "/");
if ( out.size() > 3
&& out[1] == ':'
&& out[2] == '/') {
#ifndef __TARGET_OS__Windows
TK_WARNING("Path name have a windows form: '" << _path << "' c:/ but not a windwos platform");
#endif
if ( out[0] >= 'A'
&& out[0] <= 'Z') {
out[1] = out[0] + 'a' - 'A';
} else {
out[1] = out[0];
}
out[0] = '/';
}
out = simplifyPath(out);
TK_DBG_MODE("3 : parse done : '" << _path << "' ==>\"" << out << "\"");
return out;
}
etk::Path::Path(const etk::String& _value) {
m_type =
m_data =
}
etk::Path::Path(fileSystem::Type _type, const etk::String& _value) {
m_data = parsePath(_value);
}
etk::String etk::Path::getString() const {
return m_data;
}
etk::String etk::Path::getStringWindows() const {
etk::String out = m_data;
out.replace("/", "\\");
if ( out.size() > 3
&& out[0] == '/'
&& out[2] == '/') {
out[0] = out[1];
out[0] = ':';
}
return out;
}
etk::String etk::Path::getRelative() const {
}
etk::String etk::Path::getDecorated() const {
// TODO : plouf ...
return "todo";
}
etk::String etk::Path::getNative() const {
#ifdef __TARGET_OS__Windows
return getStringWindows();
#else
return getString();
#endif
}
bool etk::Path::isRelative() const {
if ( m_data.size() >= 1
&& m_data[0] != '/') {
return true;
}
return false;
}
bool etk::Path::isAbsolute() const {
if ( m_data.size() >= 1
&& m_data[0] == '/') {
return true;
}
return false;
}
void etk::Path::parent() {
size_t pos = m_data.rfind('/');
if (pos == etk::String::npos) {
return;
}
if (pos == 0) {
// Last root element ==> do nothing.
return;
}
m_data = m_data.extract(0, pos);
}
etk::Path etk::Path::getParent() const {
etk::Path out = *this;
out.parent();
return out;
}
bool etk::Path::operator== (const etk::Path &_obj) const {
return m_type == _obj.m_type
&& m_data == _obj.m_data;
return m_data == _obj.m_data;
}
bool etk::Path::operator!= (const etk::Path &_obj) const {
return m_type != _obj.m_type
|| m_data != _obj.m_data;
return m_data != _obj.m_data;
}
etk::Path etk::Path::operator/ (const etk::String & _element) const {
@ -197,11 +219,33 @@ etk::Path etk::Path::operator/ (const etk::String & _element) const {
return tmp;
}
etk::Path etk::Path::operator/ (const etk::Path & _path) const {
etk::Path tmp = *this;
tmp /= _path;
return tmp;
}
etk::Path& etk::Path::operator/= (const etk::String & _element) {
if (_element.size() == 0) {
return *this;
}
m_data += "/" + _element;
if (_element[0] == '/') {
ETK_THROW_EXCEPTION(etk::exception::InvalidArgument("add path that is absolute"));
}
m_data += '/' + _element;
m_data = simplifyPath(m_data);
return *this;
}
etk::Path& etk::Path::operator/= (const etk::Path & _path) {
if (_path.m_data.size() == 0) {
return *this;
}
if (_path.m_data[0] == '/') {
ETK_THROW_EXCEPTION(etk::exception::InvalidArgument("add path that is absolute"));
}
m_data += '/' + _path.m_data;
m_data = simplifyPath(m_data);
return *this;
}
@ -216,6 +260,12 @@ etk::Path& etk::Path::operator+= (const etk::String & _element) {
return *this;
}
m_data += _element;
m_data = simplifyPath(m_data);
return *this;
}
etk::Stream& etk::operator <<(etk::Stream &_os, const etk::Path &_obj) {
_os << _obj.getString();
return _os;
}

View File

@ -7,6 +7,7 @@
#include <etk/types.hpp>
#include <etk/fileSystem/Type.hpp>
#include <etk/String.hpp>
namespace etk {
/**
@ -15,7 +16,6 @@ namespace etk {
*/
class Path {
private:
fileSystem::Type m_type; //!< the Type of data requested by the User.
etk::String m_data; //!< Raw data of the path.
public:
ETK_CONSTRUCTOR_MOVE_DEFAULT(Path);
@ -29,32 +29,47 @@ namespace etk {
* @param[in] _value Element basic path
*/
Path(const etk::String& _value);
/**
* @brief Contructor with basic path.
* @param[in] _type type of path
* @param[in] _value offset in the path
*/
Path(fileSystem::Type _type, const etk::String& _value);
/**
* @brief Get the absolute path
* @return string like /home/userXXX/aaa/bbb/*** or /c/userXXX/aaa/bbb/***
* @return string like /home/userXXX/aaa/bbb/### or /c/userXXX/aaa/bbb/###
*/
etk::String getString() const;
/**
* @brief Get the absolute path
* @return string like /home/userXXX/aaa/bbb/### or /c/userXXX/aaa/bbb/###
*/
etk::String getStringWindows() const;
/**
* @brief Get the relative path.
* @return string like ../../aaa/bbb/***
* @return string like ../../aaa/bbb/###
*/
etk::String getRelative() const;
/**
* @brief Get the Decorated path.
* @return string like DATA:aaa/bbb/***
*/
etk::String getDecorated() const;
/**
* @brief Get the absolute path
* @return string like /home/userXXX/aaa/bbb/*** or c:\userXXX\aaa\bbb\***
* @return string like /home/userXXX/aaa/bbb/### or c:\userXXX\aaa\bbb\###
*/
etk::String getNative() const;
/**
* @brief Check if the path is relative or not.
* @return true The path is relative.
* @return false The path is not relative.
*/
bool isRelative() const;
/**
* @brief Check if the path is absolute or not.
* @return true The path is absolute.
* @return false The path is not absolute.
*/
bool isAbsolute() const;
/**
* @brief remove the last child element of the path.
*/
void parent();
/**
* @brief Get the path of the parent.
* @return Parent path.
*/
etk::Path getParent() const;
/**
* @brief Check if the 2 Path are identical.
* @param[in] _obj Path to compare.
@ -74,7 +89,11 @@ namespace etk {
*/
Path operator/ (const etk::String & _element) const;
//! @preivious
Path& operator=/ (const etk::String & _element);
Path& operator/= (const etk::String & _element);
//! @preivious
Path operator/ (const etk::Path & _element) const;
//! @preivious
Path& operator/= (const etk::Path & _element);
/**
* @brief Add a subfolder on the current path.
* @param[in] _element sub folder or file to add.
@ -83,8 +102,12 @@ namespace etk {
Path operator+ (const etk::String & _element) const;
//! @preivious
Path& operator+= (const etk::String & _element);
//! @preivious
Path operator+ (const etk::Path & _element) const;
//! @preivious
Path& operator+= (const etk::Path & _element);
};
//! @not_in_doc
etk::Stream& operator <<(etk::Stream &_os, const etk::Path &_obj);
}

View File

@ -8,10 +8,11 @@
#include <etk/os/FSNodeRight.hpp>
#include <etk/stdTools.hpp>
#include <etk/typeInfo.hpp>
#include <etk/fileSystem/Permissions.hpp>
#include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(etk::filesystem::Permissions);
ETK_DECLARE_TYPE(etk::fileSystem::Permissions);
// Right Flags:
@ -27,44 +28,42 @@ enum {
right_user_read = 1 << 8,
};
ETK_DECLARE_TYPE(etk::filesystem::Permissions);
etk::filesystem::Permissions::Permissions(uint16_t _newRight) :
etk::fileSystem::Permissions::Permissions(uint16_t _newRight) :
m_rights(_newRight&0x01FF) {
}
uint16_t etk::filesystem::Permissions::getRight() const {
uint16_t etk::fileSystem::Permissions::getRightValue() const {
return m_rights;
}
etk::filesystem::Permissions& etk::filesystem::Permissions::operator= (const etk::filesystem::Permissions &_obj ) {
etk::fileSystem::Permissions& etk::fileSystem::Permissions::operator= (const etk::fileSystem::Permissions &_obj ) {
m_rights = _obj.m_rights;
return *this;
}
etk::filesystem::Permissions& etk::filesystem::Permissions::operator= (const uint32_t _newVal) {
etk::fileSystem::Permissions& etk::fileSystem::Permissions::operator= (const uint32_t _newVal) {
m_rights = _newVal&0x01FF;
return *this;
}
void etk::filesystem::Permissions::clear() {
void etk::fileSystem::Permissions::clear() {
m_rights = 0;
}
bool etk::filesystem::Permissions::isUserReadable() const {
bool etk::fileSystem::Permissions::isUserReadable() const {
return ((m_rights&right_user_read)!=0)?true:false;
}
bool etk::filesystem::Permissions::isUserWritable() const {
bool etk::fileSystem::Permissions::isUserWritable() const {
return ((m_rights&right_user_write)!=0)?true:false;
}
bool etk::filesystem::Permissions::isUserRunable() const {
bool etk::fileSystem::Permissions::isUserRunable() const {
return ((m_rights&right_user_execute)!=0)?true:false;
}
void etk::filesystem::Permissions::setUserReadable(bool _newStatus) {
void etk::fileSystem::Permissions::setUserReadable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_user_read);
if (_newStatus == true) {
@ -72,7 +71,7 @@ void etk::filesystem::Permissions::setUserReadable(bool _newStatus) {
}
}
void etk::filesystem::Permissions::setUserWritable(bool _newStatus) {
void etk::fileSystem::Permissions::setUserWritable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_user_write);
if (_newStatus == true) {
@ -80,7 +79,7 @@ void etk::filesystem::Permissions::setUserWritable(bool _newStatus) {
}
}
void etk::filesystem::Permissions::setUserRunable(bool _newStatus) {
void etk::fileSystem::Permissions::setUserRunable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_user_execute);
if (_newStatus == true) {
@ -88,19 +87,19 @@ void etk::filesystem::Permissions::setUserRunable(bool _newStatus) {
}
}
bool etk::filesystem::Permissions::isGroupReadable() const {
bool etk::fileSystem::Permissions::isGroupReadable() const {
return ((m_rights&right_group_read)!=0)?true:false;
}
bool etk::filesystem::Permissions::isGroupWritable() const {
bool etk::fileSystem::Permissions::isGroupWritable() const {
return ((m_rights&right_group_write)!=0)?true:false;
}
bool etk::filesystem::Permissions::isGroupRunable() const {
bool etk::fileSystem::Permissions::isGroupRunable() const {
return ((m_rights&right_group_execute)!=0)?true:false;
}
void etk::filesystem::Permissions::setGroupReadable(bool _newStatus) {
void etk::fileSystem::Permissions::setGroupReadable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_group_read);
if (true == _newStatus) {
@ -108,7 +107,7 @@ void etk::filesystem::Permissions::setGroupReadable(bool _newStatus) {
}
}
void etk::filesystem::Permissions::setGroupWritable(bool _newStatus) {
void etk::fileSystem::Permissions::setGroupWritable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_group_write);
if (true == _newStatus) {
@ -116,7 +115,7 @@ void etk::filesystem::Permissions::setGroupWritable(bool _newStatus) {
}
}
void etk::filesystem::Permissions::setGroupRunable(bool _newStatus) {
void etk::fileSystem::Permissions::setGroupRunable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_group_execute);
if (true == _newStatus) {
@ -124,19 +123,19 @@ void etk::filesystem::Permissions::setGroupRunable(bool _newStatus) {
}
}
bool etk::filesystem::Permissions::isOtherReadable() const {
bool etk::fileSystem::Permissions::isOtherReadable() const {
return ((m_rights&right_other_read) != 0)?true:false;
}
bool etk::filesystem::Permissions::isOtherWritable() const {
bool etk::fileSystem::Permissions::isOtherWritable() const {
return ((m_rights&right_other_write) != 0)?true:false;
}
bool etk::filesystem::Permissions::isOtherRunable() const {
bool etk::fileSystem::Permissions::isOtherRunable() const {
return ((m_rights&right_other_execute) != 0)?true:false;
}
void etk::filesystem::Permissions::setOtherReadable(bool _newStatus) {
void etk::fileSystem::Permissions::setOtherReadable(bool _newStatus) {
// reset the flag:
m_rights &= (0xFFFFFFFF - right_other_read);
if (_newStatus == true) {
@ -144,7 +143,7 @@ void etk::filesystem::Permissions::setOtherReadable(bool _newStatus) {
}
}
void etk::filesystem::Permissions::setOtherWritable(bool _newStatus) {
void etk::fileSystem::Permissions::setOtherWritable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_other_write);
if (_newStatus == true) {
@ -152,7 +151,7 @@ void etk::filesystem::Permissions::setOtherWritable(bool _newStatus) {
}
}
void etk::filesystem::Permissions::setOtherRunable(bool _newStatus) {
void etk::fileSystem::Permissions::setOtherRunable(bool _newStatus) {
// reset the flag :
m_rights &= (0xFFFFFFFF - right_other_execute);
if (_newStatus == true) {
@ -160,7 +159,7 @@ void etk::filesystem::Permissions::setOtherRunable(bool _newStatus) {
}
}
etk::String etk::filesystem::Permissions::getRight() const {
etk::String etk::fileSystem::Permissions::getRight() const {
etk::String tmp;
if (isUserReadable() == true) {
tmp += "r";
@ -211,7 +210,7 @@ etk::String etk::filesystem::Permissions::getRight() const {
}
etk::Stream& etk::operator <<(etk::Stream &_os, const etk::filesystem::Permissions &_obj) {
etk::Stream& etk::operator <<(etk::Stream &_os, const etk::fileSystem::Permissions &_obj) {
_os << _obj.getRight();
return _os;
};

View File

@ -11,146 +11,148 @@
#include <etk/String.hpp>
namespace etk {
/**
* @brief File System Right management
*/
class Permissions {
private:
uint16_t m_rights; //!< right manage in a bit field
public:
/**
* @brief Right contructor.
* @param[in] _newRight Right to set by default
*/
Permissions(uint16_t _newRight = 0);
/**
* @brief Get Raw right
* @return the internal value.
*/
uint16_t getRight() const;
/**
* @brief Copy asignement operator (operator=)
* @param[in] _obj Object to copy
* @return Local reference on the object
*/
etk::filesystem::Permissions& operator= (const etk::filesystem::Permissions &_obj);
/**
* @brief Asignement operator (operator=)
* @param[in] _newVal Value to set on the right
* @return Local reference on the object
*/
etk::filesystem::Permissions& operator= (const uint32_t _newVal );
/**
* @brief Clear right (set the value at 0 ==> cant not be read/write/execute
*/
void clear();
/**
* @brief Get the "Read status" for the "User"
* @return true The file/folder/... is readable
* @return false The file/folder/... is NOT readable
*/
bool isUserReadable() const;
/**
* @brief Get the "Write status" for the "User"
* @return true The file/folder/... is writable
* @return false The file/folder/... is NOT writable
*/
bool isUserWritable() const;
/**
* @brief Get the "execute status" for the "User"
* @return true The file/folder/... is executable
* @return false The file/folder/... is NOT executable
*/
bool isUserRunable() const;
/**
* @brief Set the "Read status" for the "User"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setUserReadable(bool _newStatus);
/**
* @brief Set the "Write status" for the "User"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setUserWritable(bool _newStatus);
/**
* @brief Set the "execute status" for the "User"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setUserRunable(bool _newStatus);
/**
* @brief Get the "Read status" for the "Group"
* @return true The file/folder/... is readable
* @return false The file/folder/... is NOT readable
*/
bool isGroupReadable() const;
/**
* @brief Get the "Write status" for the "Group"
* @return true The file/folder/... is writable
* @return false The file/folder/... is NOT writable
*/
bool isGroupWritable() const;
/**
* @brief Get the "execute status" for the "Group"
* @return true The file/folder/... is executable
* @return false The file/folder/... is NOT executable
*/
bool isGroupRunable() const;
/**
* @brief Set the "Read status" for the "Group"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setGroupReadable(bool _newStatus);
/**
* @brief Set the "Write status" for the "Group"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setGroupWritable(bool _newStatus);
/**
* @brief Set the "Execute status" for the "Group"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setGroupRunable(bool _newStatus);
/**
* @brief Get the "Read status" for the "Other"
* @return true The file/folder/... is readable
* @return false The file/folder/... is NOT readable
*/
bool isOtherReadable() const;
/**
* @brief Get the "Write status" for the "Other"
* @return true The file/folder/... is writable
* @return false The file/folder/... is NOT writable
*/
bool isOtherWritable() const;
/**
* @brief Get the "execute status" for the "Other"
* @return true The file/folder/... is executable
* @return false The file/folder/... is NOT executable
*/
bool isOtherRunable() const;
/**
* @brief Set the "Read status" for the "Other"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setOtherReadable(bool _newStatus);
/**
* @brief Set the "Write status" for the "Other"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setOtherWritable(bool _newStatus);
/**
* @brief Set the "Execute status" for the "Other"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setOtherRunable(bool _newStatus);
/**
* @brief Get the write written in a string mode (like in linux rw-r-----)
* @return String with the right in string
*/
etk::String getRight() const;
};
namespace fileSystem {
/**
* @brief File System Right management
*/
class Permissions {
private:
uint16_t m_rights; //!< right manage in a bit field
public:
/**
* @brief Right contructor.
* @param[in] _newRight Right to set by default
*/
Permissions(uint16_t _newRight = 0);
/**
* @brief Get Raw right
* @return the internal value.
*/
uint16_t getRightValue() const;
/**
* @brief Copy asignement operator (operator=)
* @param[in] _obj Object to copy
* @return Local reference on the object
*/
Permissions& operator= (const Permissions &_obj);
/**
* @brief Asignement operator (operator=)
* @param[in] _newVal Value to set on the right
* @return Local reference on the object
*/
Permissions& operator= (const uint32_t _newVal );
/**
* @brief Clear right (set the value at 0 ==> cant not be read/write/execute
*/
void clear();
/**
* @brief Get the "Read status" for the "User"
* @return true The file/folder/... is readable
* @return false The file/folder/... is NOT readable
*/
bool isUserReadable() const;
/**
* @brief Get the "Write status" for the "User"
* @return true The file/folder/... is writable
* @return false The file/folder/... is NOT writable
*/
bool isUserWritable() const;
/**
* @brief Get the "execute status" for the "User"
* @return true The file/folder/... is executable
* @return false The file/folder/... is NOT executable
*/
bool isUserRunable() const;
/**
* @brief Set the "Read status" for the "User"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setUserReadable(bool _newStatus);
/**
* @brief Set the "Write status" for the "User"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setUserWritable(bool _newStatus);
/**
* @brief Set the "execute status" for the "User"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setUserRunable(bool _newStatus);
/**
* @brief Get the "Read status" for the "Group"
* @return true The file/folder/... is readable
* @return false The file/folder/... is NOT readable
*/
bool isGroupReadable() const;
/**
* @brief Get the "Write status" for the "Group"
* @return true The file/folder/... is writable
* @return false The file/folder/... is NOT writable
*/
bool isGroupWritable() const;
/**
* @brief Get the "execute status" for the "Group"
* @return true The file/folder/... is executable
* @return false The file/folder/... is NOT executable
*/
bool isGroupRunable() const;
/**
* @brief Set the "Read status" for the "Group"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setGroupReadable(bool _newStatus);
/**
* @brief Set the "Write status" for the "Group"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setGroupWritable(bool _newStatus);
/**
* @brief Set the "Execute status" for the "Group"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setGroupRunable(bool _newStatus);
/**
* @brief Get the "Read status" for the "Other"
* @return true The file/folder/... is readable
* @return false The file/folder/... is NOT readable
*/
bool isOtherReadable() const;
/**
* @brief Get the "Write status" for the "Other"
* @return true The file/folder/... is writable
* @return false The file/folder/... is NOT writable
*/
bool isOtherWritable() const;
/**
* @brief Get the "execute status" for the "Other"
* @return true The file/folder/... is executable
* @return false The file/folder/... is NOT executable
*/
bool isOtherRunable() const;
/**
* @brief Set the "Read status" for the "Other"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setOtherReadable(bool _newStatus);
/**
* @brief Set the "Write status" for the "Other"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setOtherWritable(bool _newStatus);
/**
* @brief Set the "Execute status" for the "Other"
* @param[in] _newStatus New value to set on the file/folder/...
*/
void setOtherRunable(bool _newStatus);
/**
* @brief Get the write written in a string mode (like in linux rw-r-----)
* @return String with the right in string
*/
etk::String getRight() const;
};
}
//! @not_in_doc
etk::Stream& operator <<(etk::Stream &_os, const etk::filesystem::Permissions &_obj);
etk::Stream& operator <<(etk::Stream &_os, const etk::fileSystem::Permissions &_obj);
}

View File

@ -4,7 +4,7 @@
* @license MPL v2.0 (see license file)
*/
#include <etk/types.hpp>
#include <etk/filesystem/Type.hpp>
#include <etk/fileSystem/Type.hpp>
etk::Stream& etk::operator <<(etk::Stream &_os, const enum etk::fileSystem::Type &_obj) {
switch (_obj) {

View File

@ -5,6 +5,7 @@
*/
#include <etk/types.hpp>
#include <etk/Stream.hpp>
#pragma once

View File

@ -4,7 +4,7 @@
* @license MPL v2.0 (see license file)
*/
#include <etk/fileSystem/fileSystem.hpp>
#include <etk/log.hpp>
#include <etk/debug.hpp>
#ifdef __TARGET_OS__Windows
#include <tchar.h>
@ -17,47 +17,127 @@ extern "C" {
#include <sys/stat.h>
#include <errno.h>
}
void etk::fileSystem::copy(const etk::Path& _path1, const etk::Path& _path2) {
namespace etk {
static int32_t mkdir(const char* _path, mode_t _mode) {
struct stat st;
int32_t status = 0;
if (stat(_path, &st) != 0) {
/* Directory does not exist. EEXIST for race condition */
#ifdef __TARGET_OS__Windows
if(0!=::mkdir(_path)
#else
if(0!=::mkdir(_path, _mode)
#endif
&& errno != EEXIST) {
status = -1;
}
} else if (!S_ISDIR(st.st_mode)) {
errno = ENOTDIR;
status = -1;
}
return(status);
}
static int32_t mkPath(const char* _path, mode_t _mode) {
char *pp;
char *sp;
int status;
char *copypath = strdup(_path);
if (copypath == null) {
return -1;
}
status = 0;
pp = copypath;
while (status == 0 && (sp = strchr(pp, '/')) != 0) {
if (sp != pp) {
/* Neither root nor double slash in path */
*sp = '\0';
status = etk::mkdir(copypath, _mode);
*sp = '/';
}
pp = sp + 1;
}
if (status == 0) {
status = etk::mkdir(_path, _mode);
}
free(copypath);
return (status);
}
}
void etk::fileSystem::copyDirectory(const etk::Path& _path1, const etk::Path& _path2, bool _recursive) {
bool etk::fileSystem::copy(const etk::Path& _path1, const etk::Path& _path2) {
return false;
}
void etk::fileSystem::copyFile(const etk::Path& _path1, const etk::Path& _path2) {
bool etk::fileSystem::copyDirectory(const etk::Path& _path1, const etk::Path& _path2, bool _recursive) {
return false;
}
bool etk::fileSystem::copyFile(const etk::Path& _path1, const etk::Path& _path2) {
return false;
}
void etk::fileSystem::move(const etk::Path& _path1, const etk::Path& _path2) {
bool etk::fileSystem::move(const etk::Path& _path1, const etk::Path& _path2) {
if (etk::fileSystem::exist(_path2) == true) {
remove(_path2);
}
TK_DEBUG("Move : \"" << _path1 << "\" ==> \"" << _path2 << "\"");
// create path to be sure it exist ...
TK_VERBOSE("create path: '" << _path2.getParent() << "'");
etk::mkPath(_path2.getParent().getString().c_str() , 0755);
int32_t res = ::rename(_path1.getString().c_str(), _path2.getString().c_str());
if (res!=0) {
TK_ERROR("Can not move the file: '" << _path1 << "' ==> '" << _path2 << "'");
return false;
}
return true;
}
void etk::fileSystem::moveDirectory(const etk::Path& _path1, const etk::Path& _path2) {
bool etk::fileSystem::moveDirectory(const etk::Path& _path1, const etk::Path& _path2) {
return false;
}
void etk::fileSystem::moveFile(const etk::Path& _path1, const etk::Path& _path2) {
bool etk::fileSystem::moveFile(const etk::Path& _path1, const etk::Path& _path2) {
return false;
}
void etk::fileSystem::remove(const etk::Path& _path) {
bool etk::fileSystem::remove(const etk::Path& _path) {
if (etk::fileSystem::isDirectory(_path) == true) {
return etk::fileSystem::removeDirectory(_path);
}
return etk::fileSystem::removeFile(_path);
}
void etk::fileSystem::removeDirectory(const etk::Path& _path) {
bool etk::fileSystem::removeDirectory(const etk::Path& _path) {
if( 0 != ::rmdir(_path1.getString().c_str()) ) {
if (ENOTEMPTY == errno) {
TK_ERROR("The Directory is not empty...");
}
return false;
}
return true;
}
void etk::fileSystem::removeFile(const etk::Path& _path) {
bool etk::fileSystem::removeFile(const etk::Path& _path) {
if (0 != unlink(_path1.getString().c_str()) ) {
return false;
}
return true;
}
bool etk::fileSystem::touch(const etk::Path& _path) {
TK_DEBUG("Touch FILE : " << _path);
//just open in write an close ==> this will update the time
etk::io::File file{_path};
if (file.open(etk::io::OpenMode::Append) == false) {
return false;
}
return file.close();
}
bool etk::fileSystem::exit(const etk::Path& _path) {
bool etk::fileSystem::exist(const etk::Path& _path) {
struct stat st;
int32_t status = 0;
if (stat(_path.get().c_str(), &st) != 0) {
@ -116,8 +196,8 @@ bool etk::fileSystem::isSymLink(const etk::Path& _path) {
}
etk::filesystem::Permissions etk::fileSystem::getPermission(const etk::Path& _path) {
etk::filesystem::Permissions permissions;
etk::fileSystem::Permissions etk::fileSystem::getPermission(const etk::Path& _path) {
etk::fileSystem::Permissions permissions;
// tmpStat Buffer :
struct stat statProperty;
if (-1 == stat(m_systemFileName.c_str(), &statProperty)) {

View File

@ -3,10 +3,12 @@
* @copyright 2018, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#pragma once
#include <etk/fileSystem/Path.hpp>
#include <etk/fileSystem/Permissions.hpp>
namespace etk {
namespace fileSystem {
@ -14,61 +16,86 @@ namespace etk {
* @brief Copy a path to an other (if possible...)
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void copy(const etk::Path& _path1, const etk::Path& _path2);
bool copy(const etk::Path& _path1, const etk::Path& _path2);
/**
* @brief Copy a FOLDER path to an other (if possible...)
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void copyDirectory(const etk::Path& _path1, const etk::Path& _path2, bool _recursive = true);
bool copyDirectory(const etk::Path& _path1, const etk::Path& _path2, bool _recursive = true);
/**
* @brief Copy a FILE path to an other (if possible...)
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void copyFile(const etk::Path& _path1, const etk::Path& _path2);
bool copyFile(const etk::Path& _path1, const etk::Path& _path2);
/**
* @brief Move a path to an other (if possible...)
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void move(const etk::Path& _path1, const etk::Path& _path2);
bool move(const etk::Path& _path1, const etk::Path& _path2);
/**
* @brief Move a FOLDER path to an other (if possible...)
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void moveDirectory(const etk::Path& _path1, const etk::Path& _path2);
bool moveDirectory(const etk::Path& _path1, const etk::Path& _path2);
/**
* @brief Move a FILE path to an other (if possible...)
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void moveFile(const etk::Path& _path1, const etk::Path& _path2);
bool moveFile(const etk::Path& _path1, const etk::Path& _path2);
/**
* @brief Remove a path (if possible...)
* @param[in] _path Path to remove.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void remove(const etk::Path& _path);
bool remove(const etk::Path& _path);
/**
* @brief Remove a FOLDER path (if possible...)
* @param[in] _path Path to remove.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void removeDirectory(const etk::Path& _path);
bool removeDirectory(const etk::Path& _path);
/**
* @brief Remove a FILE path (if possible...)
* @param[in] _path Path to remove.
* @return true Operation succeed.
* @return false Operation Failed.
*/
void removeFile(const etk::Path& _path);
bool removeFile(const etk::Path& _path);
/**
* @brief update the Time of the file with the current time
* @param[in] _path Path to touch.
* @return true : action done
* @return false : action not done
*/
bool touch(const etk::Path& _path);
/**
* @brief Check if the path exist
* @param[in] _path1 Path source.
* @param[in] _path2 Path destination.
*/
bool exit(const etk::Path& _path);
bool exist(const etk::Path& _path);
/**
* @brief Get the File size
* @return the requested size
@ -79,7 +106,7 @@ namespace etk {
bool isFile(const etk::Path& _path);
bool isSymLink(const etk::Path& _path);
etk::filesystem::Permissions getPermission(const etk::Path& _path);
etk::fileSystem::Permissions getPermission(const etk::Path& _path);
etk::String getRelativeString(const etk::Path& _path);
etk::String getDecoratedString(const etk::Path& _path);

View File

@ -11,10 +11,19 @@
etk::io::File::File() {
// nothing to do.
}
etk::io::File::File(const etk::Path& _path):
m_path(_path) {
}
etk::io::File::File() {
if (m_pointer != null) {
TK_ERROR("Missing to close the file : \"" << *this << "\"");
close();
}
}
bool etk::io::File::open(etk::io::OpenMode _mode) {
if (m_pointer != null) {
TK_CRITICAL("File Already open : " << *this);
@ -57,46 +66,6 @@ uint64_t etk::io::File::size() {
return etk::fileSystem::fileSize(m_path);
}
char* etk::io::File::gets(char* _elementLine, int64_t _maxData) {
return fgets(_elementLine, _maxData, m_pointer);
}
char etk::io::File::get() {
char data='\0';
if (read(&data, 1, 1)!=1) {
return '\0';
}
return data;
}
bool etk::io::File::gets(etk::String& _output) {
_output.clear();
char tmp = get();
while ( tmp != '\0'
&& tmp != '\n') {
_output += tmp;
tmp = get();
}
if (tmp == '\0') {
return false;
}
return true;
}
bool etk::io::File::put(char _input) {
if (fileWrite(&_input, 1, 1) == 1) {
return true;
}
return false;
}
bool etk::io::File::puts(const etk::String& _input) {
if (fileWrite((void*)_input.c_str(), 1, _input.size()) == (int64_t)_input.size()) {
return true;
}
return false;
}
bool etk::io::File::seek(uint64_t _offset, enum etk::io::SeekMode _origin) {
int originFS = 0;
switch(_origin) {
@ -123,10 +92,11 @@ void etk::io::File::flush() {
}
}
void etk::io::File::tell() {
int64_t etk::io::File::tell() {
if (m_pointer != null) {
ftell(m_pointer);
return ftell(m_pointer);
}
return 0;
}
int64_t etk::io::File::read(void* _data, int64_t _blockSize, int64_t _nbBlock) {

View File

@ -7,6 +7,7 @@
#include <etk/types.hpp>
#include <etk/io/Interface.hpp>
#include <etk/io/File.hpp>
namespace etk {
namespace io {
@ -20,19 +21,16 @@ namespace etk {
public:
File();
File(const etk::Path& _path);
~File();
ETK_CONSTRUCTOR_COPY_DELETE(File);
ETK_CONSTRUCTOR_MOVE_DEFAULT(File);
public:
bool open() override;
bool open(etk::io::OpenMode _mode) override;
bool isOpen() override;
bool close() override;
uint64_t size() override;
char* gets(char* _elementLine, int64_t _maxData) override;
char get() override;
bool gets(etk::String& _output) override;
bool put(char _input) override;
bool puts(const etk::String& _input) override;
bool seek(uint64_t _offset, enum etk::io::SeekMode _origin) override;
int64_t tell() override;
void flush() override;
int64_t read(void* _data, int64_t _blockSize, int64_t _nbBlock) override;
int64_t write(const void* _data, int64_t _blockSize, int64_t _nbBlock) override;

View File

@ -0,0 +1,46 @@
/**
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/io/Interface.hpp>
char etk::io::Interface::get() {
char data='\0';
if (read(&data, 1, 1)!=1) {
return '\0';
}
return data;
}
bool etk::io::Interface::gets(etk::String& _output) {
_output.clear();
char tmp = get();
while ( tmp != '\0'
&& tmp != '\n') {
_output += tmp;
tmp = get();
}
if (tmp == '\0') {
return false;
}
return true;
}
bool etk::io::Interface::put(char _input) {
if (fileWrite(&_input, 1, 1) == 1) {
return true;
}
return false;
}
bool etk::io::Interface::puts(const etk::String& _input) {
if (fileWrite((void*)_input.c_str(), 1, _input.size()) == (int64_t)_input.size()) {
return true;
}
return false;
}

View File

@ -16,6 +16,7 @@ namespace etk {
*/
class Interface {
public:
virtual ~Interface();
/**
* @brief Open the file in Read mode
* @param[in] _mode Mode to open the IO
@ -40,39 +41,32 @@ namespace etk {
* @return the requested size
*/
virtual uint64_t size() = 0;
/**
* @brief Get the pointer on the start line and the next line (or null)
* @param[in,out] _elementLine Pointer to an array of chars where the string read is copied.
* @param[in] _maxData Maximum number of characters to be copied into str (including the terminating null-character).
* @return the pointer on the end of the cuurent line.
*/
virtual char* gets(char* _elementLine, int64_t _maxData) = 0;
/**
* @brief Get a unique data in the file
* @return the next element in the file.
*/
virtual char get() = 0;
virtual char get();
/**
* @brief Get a compleate line in a text file
* @param[out] _output the next element in the file.
* @return true The file is not ended.
* @return false The file is ended.
*/
virtual bool gets(etk::String& _output) = 0;
virtual bool gets(etk::String& _output);
/**
* @brief Write data on the file
* @param[in] _input data to write.
* @return true Write done corectly.
* @return false ErrorOn write.
*/
virtual bool put(char _input) = 0;
virtual bool put(char _input);
/**
* @brief Write data on the file
* @param[in] _input data to write.
* @return true Write done corectly.
* @return false ErrorOn write.
*/
virtual bool puts(const etk::String& _input) = 0;
virtual bool puts(const etk::String& _input);
/**
* @brief Move in the file Position
* @param[in] _offset Offset to apply at the file

View File

@ -0,0 +1,132 @@
/**
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/io/Interface.hpp>
#include <etk/io/ZipFile.hpp>
etk::io::ZipFile::ZipFile(ememory::SharedPtr<etk::Archive> _archive):
m_archive(_archive) {
// nothing to do.
}
etk::io::ZipFile::ZipFile(const etk::Path& _path, ememory::SharedPtr<etk::Archive> _archive):
m_path(_path),
m_archive(_archive) {
}
bool etk::io::ZipFile::open(etk::io::OpenMode _mode) {
if (m_content != null) {
TK_CRITICAL("File Already open : " << *this);
return true;
}
if (m_archive == null) {
return false;
}
TK_VERBOSE(" Read file : " << m_path);
switch (_mode) {
case etk::io::OpenMode::Read:
if (m_archive->exist(m_path) == false) {
return false;
}
m_content = m_archive->getContent(m_path);
if (m_content != null) {
return true;
}
m_archive->open(m_path);
return false;
case etk::io::OpenMode::Write:
return false;
case etk::io::OpenMode::Append:
return false;
}
return false;
}
bool etk::io::ZipFile::isOpen() {
if (m_content != null) {
return true;
}
return false;
}
bool etk::io::ZipFile::close() {
if (m_content == null) {
TK_CRITICAL("File Already closed : " << *this);
return false;
}
m_archive->close(m_path);
m_content = null;
m_offset = 0;
return true;
}
uint64_t etk::io::ZipFile::size() {
if (m_content == null) {
TK_CRITICAL("Can not access to the size: " << *this);
return false;
}
return m_content->getTheoricSize()
}
bool etk::io::ZipFile::seek(uint64_t _offset, enum etk::io::SeekMode _origin) {
if (null == m_content) {
return false;
}
int32_t positionEnd = 0;
switch(_origin) {
case etk::seekNode_end:
positionEnd = m_content->size();
break;
case etk::seekNode_current:
positionEnd = m_offset;
break;
default:
positionEnd = 0;
break;
}
positionEnd += _offset;
if (positionEnd < 0) {
positionEnd = 0;
} else if (positionEnd > m_content->size()) {
positionEnd = m_content->size();
}
m_offset = positionEnd;
return true;
}
void etk::io::ZipFile::flush() {
// nothing to do.
}
int64_t etk::io::ZipFile::tell() {
if (null == m_content) {
return 0;
}
return m_offset;
}
int64_t etk::io::ZipFile::read(void* _data, int64_t _blockSize, int64_t _nbBlock) {
if (m_content == null) {
((char*)_data)[0] = '\0';
return 0;
}
int32_t dataToRead = _blockSize * _nbBlock;
if (dataToRead + m_offset > m_content->size()) {
_nbBlock = ((m_content->size() - m_offset) / _blockSize);
dataToRead = _blockSize * _nbBlock;
}
memcpy(_data, &((char*)m_content->data())[m_offset], dataToRead);
m_offset += dataToRead;
return _nbBlock;
}
int64_t etk::io::ZipFile::write(const void* _data, int64_t _blockSize, int64_t _nbBlock) {
TK_CRITICAL("Can not write on data inside APK : " << *this);
return 0;
}

View File

@ -0,0 +1,40 @@
/**
* @author Edouard DUPIN
* @copyright 2011, Edouard DUPIN, all right reserved
* @license MPL-2 (see license file)
*/
#pragma once
#include <etk/types.hpp>
#include <etk/io/Interface.hpp>
namespace etk {
namespace io {
/**
* @brief System file interface.
*/
class ZipFile: public etk::io::Interface {
private:
etk::Path m_path; //!< Path to access in this interface
ememory::SharedPtr<etk::Archive> m_archive; //!< Archive interface
ememory::SharedPtr<etk::ArchiveContent> m_content; //!< Data in the archive file
int32_t m_offset;
public:
ZipFile(ememory::SharedPtr<etk::Archive> _archive);
ZipFile(const etk::Path& _path, ememory::SharedPtr<etk::Archive> _archive);
ETK_CONSTRUCTOR_COPY_DELETE(File);
ETK_CONSTRUCTOR_MOVE_DEFAULT(File);
public:
bool open(etk::io::OpenMode _mode) override;
bool isOpen() override;
bool close() override;
uint64_t size() override;
char* gets(char* _elementLine, int64_t _maxData) override;
bool seek(uint64_t _offset, enum etk::io::SeekMode _origin) override;
int64_t tell() override;
void flush() override;
int64_t read(void* _data, int64_t _blockSize, int64_t _nbBlock) override;
int64_t write(const void* _data, int64_t _blockSize, int64_t _nbBlock) override;
};
}
}

View File

@ -12,6 +12,60 @@
TEST(TestPath, defaultContructor) {
etk::Path path;
EXPECT_EQ(path.getType(), etk::fileSystem::Type::Unknow);
EXPECT_EQ(path.get(), "");
EXPECT_EQ(path.getString(), "");
EXPECT_EQ(path.isRelative(), true);
EXPECT_EQ(path.isAbsolute(), false);
}
TEST(TestPath, basic_relatif) {
etk::Path path("hello");
EXPECT_EQ(path.getSring(), "hello");
EXPECT_EQ(path.isRelative(), true);
EXPECT_EQ(path.isAbsolute(), false);
}
TEST(TestPath, basic_relatif_2) {
etk::Path path("hello/plouf");
EXPECT_EQ(path.getSring(), "hello/plouf");
EXPECT_EQ(path.isRelative(), true);
EXPECT_EQ(path.isAbsolute(), false);
}
TEST(TestPath, basic_relatif_2_windows) {
etk::Path path("hello\\plouf");
EXPECT_EQ(path.getSring(), "hello/plouf");
EXPECT_EQ(path.isRelative(), true);
EXPECT_EQ(path.isAbsolute(), false);
}
TEST(TestPath, basic_absolute) {
etk::Path path("/");
EXPECT_EQ(path.getSring(), "/");
EXPECT_EQ(path.getSringWindows(), "\\");
EXPECT_EQ(path.isRelative(), false);
EXPECT_EQ(path.isAbsolute(), true);
}
TEST(TestPath, basic_absolute_windows) {
etk::Path path("k:\\");
EXPECT_EQ(path.getSring(), "/k/");
EXPECT_EQ(path.getSringWindows(), "k:\\");
EXPECT_EQ(path.isRelative(), false);
EXPECT_EQ(path.isAbsolute(), true);
}
TEST(TestPath, basic_absolute_2) {
etk::Path path("/home/heero/hello/plouf");
EXPECT_EQ(path.getSring(), "/home/heero/hello/plouf");
EXPECT_EQ(path.getSringWindows(), "\\home\\heero\\hello\\plouf");
EXPECT_EQ(path.isRelative(), false);
EXPECT_EQ(path.isAbsolute(), true);
}
TEST(TestPath, basic_absolute_2_windows) {
etk::Path path("G:\\hello\\plouf");
EXPECT_EQ(path.getSring(), "/g/hello/plouf");
EXPECT_EQ(path.getSringWindows(), "g:\\hello\\plouf");
EXPECT_EQ(path.isRelative(), false);
EXPECT_EQ(path.isAbsolute(), true);
}