Subversion Repositories spk

Rev

Rev 1 | 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 _access
#else
#define ACCESS access
#endif

CDirIO::CDirIO()
{
}

CDirIO::~CDirIO()
{
}

CDirIO::CDirIO(CyString dir)
{
        SetDir(dir);
}

CDirIO::CDirIO ( CFileIO *file )
{
        SetDir(file->GetDir());
}


void CDirIO::SetDir(CyString dir)
{
        m_sCurrentDir = dir;
        m_sCurrentDir = m_sCurrentDir.FindReplace("\\", "/");
}


bool CDirIO::Exists(CyString dir)
{
        dir = ParseDir(dir);

        if ( dir.Empty() )
                return false;

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

        return false;
}

CyString CDirIO::ParseDir(CyString dir)
{
        dir = dir.FindReplace("\\", "/");
        if ( !m_sCurrentDir.Empty() && !dir.IsIn(":") )
        {
                if ( dir.Empty() )
                        dir = m_sCurrentDir;
                else
                        dir = m_sCurrentDir + "/" + dir;
        }

        dir = dir.FindReplace("//", "/");
        return dir;
}

bool CDirIO::IsDir(CyString dir)
{
        dir = ParseDir(dir);
        if ( ACCESS( dir.c_str(), 0 ) == 0 )
        {
                struct stat status;
                stat( dir.c_str(), &status );

                if ( status.st_mode & S_IFDIR )
                        return true;
        }

        return false;
}

bool CDirIO::IsFile(CyString dir)
{
        dir = ParseDir(dir);
        if ( ACCESS( dir.c_str(), 0 ) == 0 )
        {
                struct stat status;
                stat( dir.c_str(), &status );

                if ( status.st_mode & S_IFDIR )
                        return false;
                else
                        return true;
        }

        return false;
}

bool CDirIO::Create(CyString dir)
{
        if ( dir.Empty() )
                dir = m_sCurrentDir;
        dir = ParseDir(dir);

        // split up directorys
        int max = 0;
        CyString *dirs = dir.FindReplace ( "/", "\\" ).FindReplace ( "\\\\", "\\" ).SplitToken ( '\\', &max );

        // check if full dir, or relative
        int start = 1;
        CyString curDir;
        
        if ( dirs && max )
                curDir = dirs[0];

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

        // process each dir
        for ( int i = start; i < max; i++ )
        {
                if ( !curDir.Empty() )
                        curDir += "/";
                curDir += dirs[i];

                // check if the directory exists
                if ( !Exists(curDir) )
                {
#ifdef _WIN32
                        if ( _mkdir(curDir.c_str()) )
#else
                        if ( mkdir(curDir.c_str(), 0755) )
#endif
                        {
                                CLEANSPLIT(dirs, max);
                                return false;
                        }
                }
        }

        CLEANSPLIT(dirs, max);

        return true;
}

bool CDirIO::Move(CyString from, CyString to)
{
        from = ParseDir(from);
        to = ParseDir(to);

        if ( !Exists(to) )
        {
                if ( !Create(to) )
                        return false;
        }

        if ( !rename(from.c_str(), to.c_str()) )
                return true;

        return false;
}

bool CDirIO::CheckEmptyDir(CyStringList *dirList)
{
        // no pointer, most likly empty
        if ( !dirList )
                return true;
        // not found any files, most likly empty
        if ( !dirList->Count() )
                return true;
        // check for any valid files

        for ( SStringList *str = dirList->Head(); str; str = str->next )
        {
                CyString d = str->str;
                if ( d == "." || d == ".." )
                        continue;

                // found something
                return false;
        }

        return true;
}

bool CDirIO::RemoveDir(CyString dir, bool doFiles, bool recursive, CyStringList *errors)
{
        // check if the dir is empty
        CyStringList *dirList = DirList(dir);
        if ( CheckEmptyDir(dirList) )
        {
                CyString remDir = ParseDir(dir);
                #ifdef _WIN32
                if ( _rmdir(remDir.c_str()) == 0 )
                #else
                if ( rmdir(remDir.c_str()) == 0 )
                #endif
                {
                        if ( errors )
                                errors->PushBack(remDir);
                }
                return true;
        }

        // not empty
        if ( doFiles || recursive )
        {
                for ( SStringList *str = dirList->Head(); str; str = str->next )
                {
                        CyString d = str->str;
                        if ( d == "." || d == ".." )
                                continue;

                        // if its a file
                        CyString fullFile = dir + "\\" + d;
                        if ( doFiles && IsFile(fullFile) )
                        {
                                CyString remFile = ParseDir(fullFile);
                                if ( remove(remFile.c_str()) == 0 )
                                {
                                        if ( errors )
                                                errors->PushBack(remFile);
                                }
                        }
                        else if ( recursive && IsDir(fullFile) )
                                RemoveDir(fullFile, doFiles, recursive, errors);
                }
        }

        // now check if its empty
        delete dirList;
        dirList = DirList(dir);
        if ( CheckEmptyDir(dirList) )
        {
                CyString remDir = ParseDir(dir);
                #ifdef _WIN32
                if ( _rmdir(remDir.c_str()) == 0 )
                #else
                if ( rmdir(remDir.c_str()) == 0 )
                #endif
                {
                        if ( errors )
                                errors->PushBack(remDir);
                }
                return true;
        }

        return false;
}

CyStringList *CDirIO::DirList(CyString dir, CyString filepattern)
{
        dir = ParseDir(dir);
        if ( dir.Empty() )
                return 0;

        CyStringList *files = new CyStringList;

#ifdef _WIN32
        dir = dir.FindReplace("/", "\\");
        if ( filepattern.Empty() )
                dir += "\\*";
        else
        {
                dir += "\\";
                dir += filepattern;
        }
        dir = dir.FindReplace("\\\\", "\\");

        WIN32_FIND_DATA data;
        TCHAR buf[5000];
        wsprintf(buf, L"%hs", dir.c_str());

        HANDLE h = FindFirstFile(buf, &data);
        if ( h != INVALID_HANDLE_VALUE)
        {
                CyString checkFile(data.cFileName);
                if ( !checkFile.Compare(".") && !checkFile.Compare("..") )
                        files->PushBack(checkFile);
                while ( FindNextFile(h, &data) )
                {
                        CyString checkFile(data.cFileName);
                        if ( checkFile != "." && checkFile != ".." )
                                files->PushBack(checkFile);
                }

                FindClose(h);
        }
#else

#endif//_WIN32

        return files;
}

CyString CDirIO::File(CyString filename)
{
        if ( m_sCurrentDir.Empty() )
                return filename;

        return m_sCurrentDir + "/" + filename;
}

CyString CDirIO::Dir(CyString dir)
{
        return ParseDir(dir);
}

bool CDirIO::cd(CyString dir)
{
        if ( m_sCurrentDir.Empty() )
                m_sCurrentDir = dir;
        else
                m_sCurrentDir = m_sCurrentDir + "/" + dir;
        m_sCurrentDir.FindReplace("\\", "/");
        m_sCurrentDir.FindReplace("//", "/");

        return Exists();
}

bool CDirIO::CreateAndChange(CyString dir)
{
        if ( Create(dir) )
                return cd(dir);
        return false;
}


CyString CDirIO::TopDir()
{
        if ( m_sCurrentDir.Empty() )
                return NullString;

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

CyString CDirIO::Back()
{
        m_sCurrentDir = m_sCurrentDir.GetToken("/", 0, -1);
        return m_sCurrentDir;
}