Subversion Repositories spk

Rev

Rev 211 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "DirIO.h"

#include <sys/types.h>  // For stat().
#include <sys/stat.h>   // For stat().
#include <fcntl.h>
#include "File.h"
#include "File_IO.h"

#ifdef _WIN32
#include <windows.h>
#include <io.h>
#include <direct.h>
#define ACCESS _waccess
#else
#include <dirent.h>
#define ACCESS waccess
#endif

#pragma warning(disable:4244)
std::string TOSTRING(const std::wstring& s) { return std::string(s.begin(), s.end()); }
#pragma warning(default:4244)

/////////////////////////////////////////
// STATIC FUNCTIONS
bool CDirIO::Exists(const Utils::WString &dir)
{
        return CDirIO(dir).exists();
}

bool CDirIO::IsEmptyDir(const Utils::WStringList& dirList)
{
        // not found any files, most likly empty
        if (dirList.empty())
                return true;
        // check for any valid files

        for (auto itr = dirList.begin(); itr != dirList.end(); itr++)
        {
                Utils::WString d = (*itr)->str;
                if (d == L"." || d == L"..")
                        continue;

                // found something
                return false;
        }

        return true;
}


////////////////////////////////////////
// Ctor/Dtor

CDirIO::CDirIO()
{
}

CDirIO::~CDirIO()
{
}

CDirIO::CDirIO(const Utils::WString &dir)
{
        setDir(dir);
}

CDirIO::CDirIO(CFileIO *file)
{
        setDir(file->dir());
}

/////////////////////////////////////////////////////////
//

void CDirIO::setDir(const Utils::WString& dir)
{
        m_sCurrentDir = dir;
        m_sCurrentDir.toFilename();
}

bool CDirIO::exists() const
{
        Utils::WString dir = m_sCurrentDir;

        if (dir.empty())
                return false;

        //std::wifstream f(dir.c_str());
        //if (f.good())
                //return true;

        if (ACCESS(dir.c_str(), 0) == 0)
                return true;

        return false;
}

bool CDirIO::exists(const Utils::WString &dir) const
{
        Utils::WString d = _parseDir(dir);

        if (d.empty())
                return false;

        //std::wifstream f(d.c_str());
        //if (f.good())
                //return true;

        if (ACCESS(d.c_str(), 0) == 0)
                return true;

        return false;
}

Utils::WString CDirIO::_parseDir(const Utils::WString &dir) const
{
        Utils::WString sDir = dir.asFilename();
        if ( !m_sCurrentDir.empty() && !sDir.contains(L":") )
        {
                if ( sDir.empty() )
                        sDir = m_sCurrentDir;
                else
                        sDir = m_sCurrentDir + L"/" + sDir;
        }

        return sDir.asFilename();
}

bool CDirIO::isDir(const Utils::WString &sDir) const
{
        Utils::WString dir = _parseDir(sDir);
        if (ACCESS(dir.c_str(), 0) != -1)
        {
#ifdef _WIN32
                struct _stat64i32 status;
                _wstat(dir.c_str(), &status);

                if (status.st_mode & S_IFDIR)
                        return true;
#else
                struct stat status;
                stat(TOSTRING(dir).c_str(), &status);

                if (status.st_mode & S_IFDIR)
                        return true;
#endif
        }
        else {
                return !dir.token(L"/", -1).contains(L".");
        }

        return false;
}

bool CDirIO::isDir() const
{
        return isDir(m_sCurrentDir);
}

bool CDirIO::isFile() const
{
        return isFile(m_sCurrentDir);
}
bool CDirIO::isFile(const Utils::WString &sDir) const
{
        Utils::WString dir = _parseDir(sDir);
        if (ACCESS(dir.c_str(), 0) != -1)
        {
#ifdef _WIN32
                struct _stat64i32 status;
                _wstat(dir.c_str(), &status);

                if (status.st_mode & S_IFDIR)
                        return false;
#else
                struct stat status;
                stat(TOSTRING(dir).c_str(), &status);

                if (status.st_mode & S_IFDIR)
                        return false;
#endif
                return true;
        }
        else {
                return dir.token(L"/", -1).contains(L".");
        }

        return false;
}


bool CDirIO::create() const
{
        return create(Utils::WString::Null());
}
bool CDirIO::create(const Utils::WString &sDir) const
{
        Utils::WString dir = sDir;
        if ( dir.empty() )
                dir = m_sCurrentDir;
        dir = _parseDir(dir);

        // split up directorys
        std::vector<Utils::WString> dirs;
        if(dir.findReplace(L"/", L"\\").findReplace(L"\\\\", L"\\").tokenise(L"\\", dirs))
        {
                // check if full dir, or relative
                size_t start = 1;
                Utils::WString curDir = dirs.front();

                if (!curDir.contains(L":"))
                {
                        curDir = m_sCurrentDir;
                        start = 0;
                }

                // process each dir
                for (size_t i = start; i < dirs.size(); i++)
                {
                        if (!curDir.empty())
                                curDir += L"/";
                        curDir += dirs.at(i);

                        // check if the directory exists
                        if (!exists(curDir))
                        {
#ifdef _WIN32
                                std::string str = TOSTRING(curDir);
                                if (_wmkdir(curDir.c_str()))
#else
                                if (mkdir(TOSTRING(curDir).c_str(), 0755))
#endif
                                        return false;
                        }
                }
        }

        return true;
}

bool CDirIO::move(const Utils::WString &sTo)
{
        Utils::WString to = _parseDir(sTo);

        if (exists(to))
                return false;

        if (!CFileIO::Rename(m_sCurrentDir, to))
        {
                m_sCurrentDir = to;
                return true;
        }

        return false;
}


bool CDirIO::move(const Utils::WString &sFrom, const Utils::WString &sTo)
{
        Utils::WString from = _parseDir(sFrom);
        Utils::WString to = _parseDir(sTo);

        if ( !exists(to) )
        {
                if ( !create(to) )
                        return false;
        }

        if(CFileIO::Rename(from, to))
                return true;

        return false;
}

bool CDirIO::checkEmptyDir(const Utils::WStringList &dirList) const
{
        // not found any files, most likly empty
        if (dirList.empty())
                return true;
        // check for any valid files

        for(auto itr = dirList.begin(); itr != dirList.end(); itr++)
        {
                Utils::WString d = (*itr)->str;
                if (d == L"." || d == L"..")
                        continue;

                // found something
                return false;
        }

        return true;
}

bool CDirIO::removeDir(const Utils::WString& dir, bool doFiles, bool recursive, Utils::WStringList* errors)
{
        // check if the dir is empty
        Utils::WStringList list;
        if (dirList(list, dir))
        {
                if (CDirIO::IsEmptyDir(list))
                {
                        Utils::WString remDir = _parseDir(dir);
#ifdef _WIN32
                        if (_wrmdir(remDir.c_str()) == 0)
#else
                        if (rmdir(TOSTRING(remDir).c_str()) == 0)
#endif
                        {
                                if (errors)
                                        errors->pushBack(remDir);
                        }
                        return true;
                }

                // not empty
                if (doFiles || recursive)
                {
                        for (auto itr = list.begin(); itr != list.end(); itr++)
                        {
                                Utils::WString d = (*itr)->str;
                                if (d == L"." || d == L"..")
                                        continue;

                                // if its a file
                                Utils::WString fullFile = dir + "\\" + d;
                                if (doFiles && isFile(fullFile))
                                {
                                        Utils::WString remFile = _parseDir(fullFile);
                                        if (!CFileIO::Remove(remFile))
                                        {
                                                if (errors)
                                                        errors->pushBack(remFile);
                                        }
                                }
                                else if (recursive && isDir(fullFile))
                                        removeDir(fullFile, doFiles, recursive, errors);
                        }
                }
        }
        list.clear();
        // now check if its empty
        if(dirList(list, dir))
        {
                if (CDirIO::IsEmptyDir(list))
                {
                        Utils::WString remDir = _parseDir(dir);
#ifdef _WIN32
                        if (_wrmdir(remDir.c_str()) == 0)
#else
                        if (rmdir(TOSTRING(remDir).c_str()) == 0)
#endif
                        {
                                if (errors)
                                        errors->pushBack(remDir);
                        }
                        return true;
                }
        }
        return false;
}

bool CDirIO::dirList(Utils::WStringList& files, const Utils::WString &sDir, const Utils::WString &filePattern) const
{
        Utils::WString dir = _parseDir(sDir);
        if (dir.empty())
                return false;

        dir = dir.findReplace(L"\\", L"/");
        if (filePattern.empty())
                dir += L"/*";
        else
        {
                dir += L"/";
                dir += filePattern;
        }
        dir = dir.findReplace(L"//", L"/");

#ifdef _WIN32
        dir = dir.findReplace(L"/", L"\\");

        WIN32_FIND_DATA data;
        HANDLE h = FindFirstFile(dir.c_str(), &data);
        if (h != INVALID_HANDLE_VALUE)
        {
                Utils::WString checkFile(data.cFileName);
                if (!checkFile.Compare(L".") && !checkFile.Compare(L".."))
                        files.pushBack(checkFile);

                while (FindNextFile(h, &data))
                {
                        Utils::WString checkFile(data.cFileName);
                        if (checkFile != L"." && checkFile != L"..")
                                files.pushBack(checkFile);
                }

                FindClose(h);
                return true;
        }
        return false;
#else
        DIR* dir;
        struct dirent* ent;
        if ((dir = opendir(dir.c_str())) != NULL) {
                while ((ent = readdir(dir)) != NULL) {
                        Utils::WString checkFile(ent->d_name);
                        if (checkFile != L"." && checkFile != L"..")
                                files.pushBack(checkFile);
                }
                closedir(dir);
        }
        return true;
#endif//_WIN32

}

Utils::WString CDirIO::file(const Utils::WString &filename) const
{
        if (m_sCurrentDir.empty())
                return filename;

        return m_sCurrentDir + L"/" + filename;
}

Utils::WString CDirIO::dir(const Utils::WString &sDir) const
{
        return _parseDir(sDir);
}

const Utils::WString &CDirIO::dir() const
{
        return m_sCurrentDir;
}

bool CDirIO::cd(const Utils::WString &sDir)
{
        if ( m_sCurrentDir.empty() )
                m_sCurrentDir = sDir;
        else
                m_sCurrentDir = m_sCurrentDir + L"/" + sDir;
        m_sCurrentDir = m_sCurrentDir.asFilename();

        return exists();
}

bool CDirIO::createAndChange(const Utils::WString &dir)
{
        if ( create(dir) )
                return cd(dir);
        return false;
}


Utils::WString CDirIO::topDir() const
{
        if ( m_sCurrentDir.empty() )
                return Utils::WString(L"");

        return m_sCurrentDir.token(L"/", -1);
}

const Utils::WString &CDirIO::moveBack()
{
        m_sCurrentDir = m_sCurrentDir.tokens(L"/", 1, -2);
        return m_sCurrentDir;
}
Utils::WString CDirIO::back() const
{
        return m_sCurrentDir.tokens(L"/", 1, -2);
}