[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; nbTimeInit = 0;
return; return;
} }
etk::theme::uninit(); etk::theme::unInit();
TK_INFO("ETK system un-init (BEGIN)"); TK_INFO("ETK system un-init (BEGIN)");
ETK_MEM_SHOW_LOG(); ETK_MEM_SHOW_LOG();
TK_INFO("ETK system un-init (END)"); TK_INFO("ETK system un-init (END)");

View File

@ -4,7 +4,8 @@
* @license MPL v2.0 (see license file) * @license MPL v2.0 (see license file)
*/ */
#include <etk/fileSystem/Path.hpp> #include <etk/fileSystem/Path.hpp>
#include <etk/log.hpp> #include <etk/debug.hpp>
#include <etk/Exception.hpp>
#include <etk/typeInfo.hpp> #include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(etk::Path); 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_VERBOSE
#define TK_DBG_MODE TK_WARNING #define TK_DBG_MODE TK_WARNING
static etk::Pair<etk::fileSystem::Type, etk::String> parsePath(etk::String _path) {
// Reset ALL DATA : static etk::String simplifyPath(etk::String _input) {
m_data = ""; // step 1 : for windows change \ in /:
m_type = etk::fileSystem::Type::Unknow; TK_DEBUG("Simplify(1) : '" << _input << "'");
TK_DBG_MODE("1 : Set Name : \"" << _path << "\""); size_t currentPos = 0;
#ifdef __TARGET_OS__Windows if (_input.size() == 0) {
_path.replace("\\", "/"); return _input;
for (char iii='a' ; iii<='z' ; iii++) { }
char tmpVal[10]; while(currentPos < _input.size()) {
char tmpDest[10]; if (_input[currentPos] == '\\') {
sprintf(tmpVal, "%c:/", iii); _input[currentPos] = '/';
sprintf(tmpDest, "/%c/", iii);
if(etk::start_with(_path, tmpVal) == true) {
_path.replace(tmpVal, tmpDest);
break;
}
} }
for (char iii='A' ; iii<='Z' ; iii++) { currentPos++;
char tmpVal[10]; continue;
char tmpDest[10]; }
sprintf(tmpVal, "%c:/", iii); // step 2 : remove all '//'
sprintf(tmpDest, "/%c/", iii+'a'-'A'); TK_DBG_MODE("Simplify(2) : '" << _input << "'");
if(etk::start_with(_path, tmpVal) == true) { currentPos = 0;
_path.replace(tmpVal, tmpDest); if (_input.size() <= 1) {
break; 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 #endif
// generate destination name in case of the input error TK_DEBUG("Simplify(end) : '" << _input << "'");
if (_path.size() == 0) { return _input;
// 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);
} }
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) { etk::Path::Path(const etk::String& _value) {
m_type = m_data = parsePath(_value);
m_data =
}
etk::Path::Path(fileSystem::Type _type, const etk::String& _value) {
} }
etk::String etk::Path::getString() const { 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::getRelative() const {
// TODO : plouf ...
} return "todo";
etk::String etk::Path::getDecorated() const {
} }
etk::String etk::Path::getNative() const { 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 { bool etk::Path::operator== (const etk::Path &_obj) const {
return m_type == _obj.m_type return m_data == _obj.m_data;
&& m_data == _obj.m_data;
} }
bool etk::Path::operator!= (const etk::Path &_obj) const { bool etk::Path::operator!= (const etk::Path &_obj) const {
return m_type != _obj.m_type return m_data != _obj.m_data;
|| m_data != _obj.m_data;
} }
etk::Path etk::Path::operator/ (const etk::String & _element) const { 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; 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) { etk::Path& etk::Path::operator/= (const etk::String & _element) {
if (_element.size() == 0) { if (_element.size() == 0) {
return *this; 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; return *this;
} }
@ -216,6 +260,12 @@ etk::Path& etk::Path::operator+= (const etk::String & _element) {
return *this; return *this;
} }
m_data += _element; m_data += _element;
m_data = simplifyPath(m_data);
return *this; 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/types.hpp>
#include <etk/fileSystem/Type.hpp> #include <etk/fileSystem/Type.hpp>
#include <etk/String.hpp>
namespace etk { namespace etk {
/** /**
@ -15,7 +16,6 @@ namespace etk {
*/ */
class Path { class Path {
private: private:
fileSystem::Type m_type; //!< the Type of data requested by the User.
etk::String m_data; //!< Raw data of the path. etk::String m_data; //!< Raw data of the path.
public: public:
ETK_CONSTRUCTOR_MOVE_DEFAULT(Path); ETK_CONSTRUCTOR_MOVE_DEFAULT(Path);
@ -29,32 +29,47 @@ namespace etk {
* @param[in] _value Element basic path * @param[in] _value Element basic path
*/ */
Path(const etk::String& _value); 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 * @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; 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. * @brief Get the relative path.
* @return string like ../../aaa/bbb/*** * @return string like ../../aaa/bbb/###
*/ */
etk::String getRelative() const; etk::String getRelative() const;
/**
* @brief Get the Decorated path.
* @return string like DATA:aaa/bbb/***
*/
etk::String getDecorated() const;
/** /**
* @brief Get the absolute path * @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; 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. * @brief Check if the 2 Path are identical.
* @param[in] _obj Path to compare. * @param[in] _obj Path to compare.
@ -74,7 +89,11 @@ namespace etk {
*/ */
Path operator/ (const etk::String & _element) const; Path operator/ (const etk::String & _element) const;
//! @preivious //! @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. * @brief Add a subfolder on the current path.
* @param[in] _element sub folder or file to add. * @param[in] _element sub folder or file to add.
@ -83,8 +102,12 @@ namespace etk {
Path operator+ (const etk::String & _element) const; Path operator+ (const etk::String & _element) const;
//! @preivious //! @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);
}; };
//! @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/os/FSNodeRight.hpp>
#include <etk/stdTools.hpp> #include <etk/stdTools.hpp>
#include <etk/typeInfo.hpp> #include <etk/typeInfo.hpp>
#include <etk/fileSystem/Permissions.hpp>
#include <etk/typeInfo.hpp> #include <etk/typeInfo.hpp>
ETK_DECLARE_TYPE(etk::filesystem::Permissions); ETK_DECLARE_TYPE(etk::fileSystem::Permissions);
// Right Flags: // Right Flags:
@ -27,44 +28,42 @@ enum {
right_user_read = 1 << 8, 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) { m_rights(_newRight&0x01FF) {
} }
uint16_t etk::filesystem::Permissions::getRight() const { uint16_t etk::fileSystem::Permissions::getRightValue() const {
return m_rights; 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; m_rights = _obj.m_rights;
return *this; 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; m_rights = _newVal&0x01FF;
return *this; return *this;
} }
void etk::filesystem::Permissions::clear() { void etk::fileSystem::Permissions::clear() {
m_rights = 0; m_rights = 0;
} }
bool etk::filesystem::Permissions::isUserReadable() const { bool etk::fileSystem::Permissions::isUserReadable() const {
return ((m_rights&right_user_read)!=0)?true:false; 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; 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; 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_user_read); m_rights &= (0xFFFFFFFF - right_user_read);
if (_newStatus == true) { 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_user_write); m_rights &= (0xFFFFFFFF - right_user_write);
if (_newStatus == true) { 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_user_execute); m_rights &= (0xFFFFFFFF - right_user_execute);
if (_newStatus == true) { 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; 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; 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; 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_group_read); m_rights &= (0xFFFFFFFF - right_group_read);
if (true == _newStatus) { 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_group_write); m_rights &= (0xFFFFFFFF - right_group_write);
if (true == _newStatus) { 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_group_execute); m_rights &= (0xFFFFFFFF - right_group_execute);
if (true == _newStatus) { 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; 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; 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; 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: // reset the flag:
m_rights &= (0xFFFFFFFF - right_other_read); m_rights &= (0xFFFFFFFF - right_other_read);
if (_newStatus == true) { 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_other_write); m_rights &= (0xFFFFFFFF - right_other_write);
if (_newStatus == true) { 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 : // reset the flag :
m_rights &= (0xFFFFFFFF - right_other_execute); m_rights &= (0xFFFFFFFF - right_other_execute);
if (_newStatus == true) { 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; etk::String tmp;
if (isUserReadable() == true) { if (isUserReadable() == true) {
tmp += "r"; 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(); _os << _obj.getRight();
return _os; return _os;
}; };

View File

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

View File

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

View File

@ -4,7 +4,7 @@
* @license MPL v2.0 (see license file) * @license MPL v2.0 (see license file)
*/ */
#include <etk/fileSystem/fileSystem.hpp> #include <etk/fileSystem/fileSystem.hpp>
#include <etk/log.hpp> #include <etk/debug.hpp>
#ifdef __TARGET_OS__Windows #ifdef __TARGET_OS__Windows
#include <tchar.h> #include <tchar.h>
@ -17,47 +17,127 @@ extern "C" {
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
} }
namespace etk {
void etk::fileSystem::copy(const etk::Path& _path1, const etk::Path& _path2) { 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; struct stat st;
int32_t status = 0; int32_t status = 0;
if (stat(_path.get().c_str(), &st) != 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 etk::fileSystem::getPermission(const etk::Path& _path) {
etk::filesystem::Permissions permissions; etk::fileSystem::Permissions permissions;
// tmpStat Buffer : // tmpStat Buffer :
struct stat statProperty; struct stat statProperty;
if (-1 == stat(m_systemFileName.c_str(), &statProperty)) { if (-1 == stat(m_systemFileName.c_str(), &statProperty)) {

View File

@ -3,10 +3,12 @@
* @copyright 2018, Edouard DUPIN, all right reserved * @copyright 2018, Edouard DUPIN, all right reserved
* @license MPL v2.0 (see license file) * @license MPL v2.0 (see license file)
*/ */
#pragma once
#include <etk/types.hpp> #include <etk/types.hpp>
#pragma once #include <etk/fileSystem/Path.hpp>
#include <etk/fileSystem/Permissions.hpp>
namespace etk { namespace etk {
namespace fileSystem { namespace fileSystem {
@ -14,61 +16,86 @@ namespace etk {
* @brief Copy a path to an other (if possible...) * @brief Copy a path to an other (if possible...)
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @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...) * @brief Copy a FOLDER path to an other (if possible...)
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @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...) * @brief Copy a FILE path to an other (if possible...)
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @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...) * @brief Move a path to an other (if possible...)
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @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...) * @brief Move a FOLDER path to an other (if possible...)
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @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...) * @brief Move a FILE path to an other (if possible...)
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @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...) * @brief Remove a path (if possible...)
* @param[in] _path Path to remove. * @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...) * @brief Remove a FOLDER path (if possible...)
* @param[in] _path Path to remove. * @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...) * @brief Remove a FILE path (if possible...)
* @param[in] _path Path to remove. * @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 * @brief Check if the path exist
* @param[in] _path1 Path source. * @param[in] _path1 Path source.
* @param[in] _path2 Path destination. * @param[in] _path2 Path destination.
*/ */
bool exit(const etk::Path& _path); bool exist(const etk::Path& _path);
/** /**
* @brief Get the File size * @brief Get the File size
* @return the requested size * @return the requested size
@ -79,7 +106,7 @@ namespace etk {
bool isFile(const etk::Path& _path); bool isFile(const etk::Path& _path);
bool isSymLink(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 getRelativeString(const etk::Path& _path);
etk::String getDecoratedString(const etk::Path& _path); etk::String getDecoratedString(const etk::Path& _path);

View File

@ -11,10 +11,19 @@
etk::io::File::File() { etk::io::File::File() {
// nothing to do. // nothing to do.
} }
etk::io::File::File(const etk::Path& _path): etk::io::File::File(const etk::Path& _path):
m_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) { bool etk::io::File::open(etk::io::OpenMode _mode) {
if (m_pointer != null) { if (m_pointer != null) {
TK_CRITICAL("File Already open : " << *this); TK_CRITICAL("File Already open : " << *this);
@ -57,46 +66,6 @@ uint64_t etk::io::File::size() {
return etk::fileSystem::fileSize(m_path); 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) { bool etk::io::File::seek(uint64_t _offset, enum etk::io::SeekMode _origin) {
int originFS = 0; int originFS = 0;
switch(_origin) { 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) { 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) { 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/types.hpp>
#include <etk/io/Interface.hpp> #include <etk/io/Interface.hpp>
#include <etk/io/File.hpp>
namespace etk { namespace etk {
namespace io { namespace io {
@ -20,19 +21,16 @@ namespace etk {
public: public:
File(); File();
File(const etk::Path& _path); File(const etk::Path& _path);
~File();
ETK_CONSTRUCTOR_COPY_DELETE(File); ETK_CONSTRUCTOR_COPY_DELETE(File);
ETK_CONSTRUCTOR_MOVE_DEFAULT(File); ETK_CONSTRUCTOR_MOVE_DEFAULT(File);
public: public:
bool open() override; bool open(etk::io::OpenMode _mode) override;
bool isOpen() override; bool isOpen() override;
bool close() override; bool close() override;
uint64_t size() 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; bool seek(uint64_t _offset, enum etk::io::SeekMode _origin) override;
int64_t tell() override;
void flush() override; void flush() override;
int64_t read(void* _data, int64_t _blockSize, int64_t _nbBlock) 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; 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 { class Interface {
public: public:
virtual ~Interface();
/** /**
* @brief Open the file in Read mode * @brief Open the file in Read mode
* @param[in] _mode Mode to open the IO * @param[in] _mode Mode to open the IO
@ -40,39 +41,32 @@ namespace etk {
* @return the requested size * @return the requested size
*/ */
virtual uint64_t size() = 0; 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 * @brief Get a unique data in the file
* @return the next element 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 * @brief Get a compleate line in a text file
* @param[out] _output the next element in the file. * @param[out] _output the next element in the file.
* @return true The file is not ended. * @return true The file is not ended.
* @return false The file is 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 * @brief Write data on the file
* @param[in] _input data to write. * @param[in] _input data to write.
* @return true Write done corectly. * @return true Write done corectly.
* @return false ErrorOn write. * @return false ErrorOn write.
*/ */
virtual bool put(char _input) = 0; virtual bool put(char _input);
/** /**
* @brief Write data on the file * @brief Write data on the file
* @param[in] _input data to write. * @param[in] _input data to write.
* @return true Write done corectly. * @return true Write done corectly.
* @return false ErrorOn write. * @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 * @brief Move in the file Position
* @param[in] _offset Offset to apply at the file * @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) { TEST(TestPath, defaultContructor) {
etk::Path path; etk::Path path;
EXPECT_EQ(path.getType(), etk::fileSystem::Type::Unknow); EXPECT_EQ(path.getString(), "");
EXPECT_EQ(path.get(), ""); 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);
} }