protot/3rdparty/RuntimeCompiledCpp/RuntimeCompiler/FileSystemUtils.h

585 lines
13 KiB
C
Raw Normal View History

//
// Copyright (c) 2010-2011 Matthew Jack and Doug Binks
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
#pragma once
// we use std::string as there are many string types in the community
// and this can be easily swapped for your own implementation if desired
#include <string>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#ifdef _WIN32
#include <direct.h>
#include <sys/utime.h>
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#undef GetObject
#undef GetCurrentTime
#define FILESYSTEMUTILS_SEPERATORS "/\\"
#else
#include <utime.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#define FILESYSTEMUTILS_SEPERATORS "/"
#endif
namespace FileSystemUtils
{
#ifdef _WIN32
typedef __time64_t filetime_t;
#else
typedef time_t filetime_t;
#endif
class Path
{
public:
std::string m_string;
Path()
{
}
Path( const std::string& rhs_ )
: m_string( rhs_ )
{
}
Path( const char* rhs_ )
: m_string( rhs_ )
{
}
virtual ~Path() {} // for RCC++
const char* c_str() const;
Path& operator=( const std::string& rhs_ );
Path& operator=( const char* rhs_ );
bool Exists() const;
bool CreateDir() const;
bool Remove() const;
filetime_t GetLastWriteTime() const;
void SetLastWriteTime( filetime_t time_ ) const;
uint64_t GetFileSize() const;
bool HasExtension() const;
bool HasParentPath() const;
std::string Extension() const;
// returns filename - i.e. part after final seperator: ./dirone/hello.txt > hello.txt ; ./dirone/hello > hello ; ./dirone/ > [empty string]
Path Filename() const;
Path ParentPath() const;
Path DelimitersToOSDefault() const;
// returns a path cleaned of /../ by removing prior dir
Path GetCleanPath() const;
void ToOSCanonicalCase(); // lower case on Windows, preserve case on Linux
// replaces extension if one exists, or adds it if not
void ReplaceExtension( const std::string& ext );
#ifdef _WIN32
static const char seperator = '\\';
static const char altseperator = '/';
#else
static const char seperator = '/';
static const char altseperator = '\\';
#endif
};
inline void ToLowerInPlace( std::string& inout_str )
{
for( size_t i = 0; i < inout_str.size(); ++i )
{
if( inout_str[i] >= 'A' && inout_str[i] <= 'Z' )
{
//tolower
inout_str[i] -= 'A'-'a';
}
}
}
///////////////////////////////////////////////////////////////////
// Path function definitions
inline const char* Path::c_str() const
{
return m_string.c_str();
}
inline Path& Path::operator=( const std::string& rhs_ )
{
m_string = rhs_;
return *this;
}
inline Path& Path::operator=( const char* rhs_ )
{
m_string = rhs_;
return *this;
}
inline bool Path::Exists() const
{
int error = -1;
#ifdef _WIN32
struct _stat buffer;
error = _stat( m_string.c_str(), &buffer );
#else
struct stat buffer;
error = stat( m_string.c_str(), &buffer );
#endif
if( 0 == error )
{
return true;
}
return false;
}
inline bool Path::CreateDir() const
{
if( m_string.length() == 0 )
{
return false;
}
if( Exists() )
{
return false;
}
// we may need to create the parent path recursively
Path parentpath = ParentPath();
if( !parentpath.Exists() )
{
parentpath.CreateDir();
}
int error = -1;
#ifdef _WIN32
error = _mkdir( m_string.c_str() );
#else
error = mkdir( m_string.c_str(), 0777 );
#endif
if( 0 == error )
{
return true;
}
return false;
}
inline filetime_t Path::GetLastWriteTime() const
{
filetime_t lastwritetime = 0;
int error = -1;
#ifdef _WIN32
struct _stat64 buffer;
error = _stat64( c_str(), &buffer );
#else
struct stat buffer;
error = stat( c_str(), &buffer );
#endif
if( 0 == error )
{
lastwritetime = buffer.st_mtime;
}
return lastwritetime;
}
inline void Path::SetLastWriteTime( filetime_t time_ ) const
{
#ifdef _WIN32
__utimbuf64 modtime = { time_, time_ };
_utime64( c_str(), &modtime );
#else
utimbuf modtime = { time_, time_ };
utime( c_str(), &modtime );
#endif
}
inline filetime_t GetCurrentTime()
{
filetime_t timer;
#ifdef _WIN32
_time64(&timer);
#else
time(&timer);
#endif
return timer;
}
inline tm GetTimeStruct( filetime_t time )
{
tm ret;
#ifdef _WIN32
_gmtime64_s(&ret, &time);
#else
gmtime_r(&time, &ret);
#endif
return ret;
}
inline bool Path::Remove() const
{
int error = remove( c_str() );
if( !error )
{
return true;
}
return false;
}
inline uint64_t Path::GetFileSize() const
{
uint64_t filesize = 0;
int error = -1;
#ifdef _WIN32
struct _stat64 buffer;
error = _stat64( c_str(), &buffer );
#else
struct stat buffer;
error = stat( c_str(), &buffer );
#endif
if( 0 == error )
{
filesize = buffer.st_size;
}
return filesize;
}
inline bool Path::HasExtension() const
{
size_t posdot = m_string.find_last_of( '.' );
if( posdot != std::string::npos )
{
size_t posseperator = m_string.find_last_of( seperator );
if( posseperator != std::string::npos && posseperator > posdot )
{
return false; // the dot is for a directory such as ./ or ../ or the path is malformed
}
size_t posaltseperator = m_string.find_last_of( altseperator );
if( posaltseperator != std::string::npos && posaltseperator > posdot )
{
return false; // the dot is for a directory such as ./ or ../ or the path is malformed
}
return true;
}
return false;
}
inline bool Path::HasParentPath() const
{
size_t posseperator = m_string.find_last_of( seperator );
if( posseperator != std::string::npos && posseperator > 0 )
{
return true;
}
size_t posaltseperator = m_string.find_last_of( altseperator );
if( posaltseperator != std::string::npos && posaltseperator > 0 )
{
return true;
}
return false;
}
inline std::string Path::Extension() const
{
std::string ext;
if( HasExtension() )
{
size_t pos = m_string.find_last_of( '.' );
if( pos < m_string.length() )
{
ext = m_string.substr( pos );
}
}
return ext;
}
inline Path Path::Filename() const
{
Path filename;
size_t pos = m_string.find_last_of( seperator ) + 1;
if( pos <= m_string.length() )
{
filename = m_string.substr(pos);
}
return filename;
}
inline Path Path::ParentPath() const
{
Path parentpath = m_string;
if( parentpath.m_string.length() == 0 )
{
return parentpath;
}
//remove any trailing seperators
while( parentpath.m_string.find_last_of( FILESYSTEMUTILS_SEPERATORS ) == parentpath.m_string.length()-1 )
{
parentpath.m_string.erase(parentpath.m_string.length()-1, 1);
}
size_t pos = parentpath.m_string.find_last_of( FILESYSTEMUTILS_SEPERATORS );
if( pos < parentpath.m_string.length() )
{
parentpath = parentpath.m_string.substr(0, pos);
//remove any trailing seperators
while( parentpath.m_string.find_last_of( FILESYSTEMUTILS_SEPERATORS ) == parentpath.m_string.length()-1)
{
parentpath.m_string.erase(parentpath.m_string.length()-1, 1);
}
}
return parentpath;
}
inline Path Path::DelimitersToOSDefault() const
{
Path path = m_string;
for( size_t i = 0; i < path.m_string.size(); ++i )
{
if( path.m_string[i] == altseperator )
{
path.m_string[i] = seperator;
}
}
return path;
}
inline void Path::ReplaceExtension( const std::string& ext )
{
if( HasExtension() )
{
size_t pos = m_string.find_last_of( '.' );
if( pos < m_string.length() )
{
m_string.erase( m_string.begin() + pos, m_string.end() );
}
}
m_string += ext;
}
inline Path operator/( const Path& lhs_, const Path& rhs_ )
{
if( 0 == lhs_.m_string.length() )
{
return rhs_;
}
if( 0 == rhs_.m_string.length() )
{
return lhs_;
}
std::string strlhs = lhs_.m_string;
while( strlhs.length() && strlhs.find_last_of( FILESYSTEMUTILS_SEPERATORS ) == strlhs.length()-1 )
{
strlhs.erase(strlhs.length()-1, 1);
}
//note: should probably remove preceding seperators to rhs_, but this has not as yet occured
Path join = strlhs + Path::seperator + rhs_.m_string;
return join;
}
inline bool operator==( const Path& lhs_, const Path& rhs_ )
{
return lhs_.m_string == rhs_.m_string;
}
inline bool operator<( const Path& lhs_, const Path& rhs_ )
{
return lhs_.m_string < rhs_.m_string;
}
inline Path GetCurrentPath()
{
Path currPath;
#ifdef _WIN32
char currdir[MAX_PATH];
GetCurrentDirectoryA( sizeof( currdir ), currdir );
currPath = currdir;
#else
char* currdir = getcwd(0,0);
currPath = currdir;
free( currdir );
#endif
return currPath;
}
inline Path Path::GetCleanPath() const
{
Path path = m_string;
bool bFound = false;
do
{
bFound = false;
size_t pos = path.m_string.find( ".." );
if( pos != std::string::npos && pos+3 < path.m_string.length() && pos > 0 )
{
Path a = path.m_string.substr(0,pos-1); // pos-1 as we don't want delimiter
Path b = path.m_string.substr(pos+3,path.m_string.length()); // pos+3 as we don't want delimiter
a = a.ParentPath();
path = a / b;
bFound = true;
}
} while( bFound );
return path;
}
inline void Path::ToOSCanonicalCase()
{
#ifdef _WIN32
ToLowerInPlace( m_string );
#endif
}
class PathIterator
{
private:
Path m_dir;
Path m_path;
bool m_bIsValid;
#ifdef _WIN32
void ImpCtor()
{
Path test = m_dir / "*";
m_path = m_dir;
m_hFind = INVALID_HANDLE_VALUE;
m_hFind = FindFirstFileA(test.c_str(), &m_ffd);
m_bIsValid = INVALID_HANDLE_VALUE != m_hFind;
}
bool ImpNext()
{
if( m_bIsValid )
{
m_bIsValid = 0 != FindNextFileA( m_hFind, &m_ffd );
if( m_bIsValid )
{
m_path = m_dir / m_ffd.cFileName;
if( m_path.Filename() == ".." )
{
return ImpNext();
}
}
}
return m_bIsValid;
}
void ImpDtor()
{
FindClose( m_hFind );
}
HANDLE m_hFind;
WIN32_FIND_DATAA m_ffd;
#else
void ImpCtor()
{
Path test = m_dir / "*";
m_path = m_dir;
m_numFilesInList = scandir( m_path.c_str(), &m_paDirFileList, 0, alphasort);
m_bIsValid = m_numFilesInList > 0;
m_currFile = 0;
if( !m_bIsValid )
{
m_paDirFileList = 0;
}
}
bool ImpNext()
{
if( m_bIsValid )
{
++m_currFile;
m_bIsValid = m_currFile < m_numFilesInList;
if( m_bIsValid )
{
m_path = m_dir / m_paDirFileList[ m_currFile ]->d_name;
if( strcmp( m_paDirFileList[ m_currFile ]->d_name, "." ) == 0 ||
strcmp( m_paDirFileList[ m_currFile ]->d_name, ".." ) == 0 )
{
return ImpNext();
}
}
}
return m_bIsValid;
}
void ImpDtor()
{
free(m_paDirFileList);
}
struct dirent **m_paDirFileList;
int m_numFilesInList;
int m_currFile;
#endif
public:
PathIterator( const Path& path_ )
: m_dir( path_ )
{
ImpCtor();
}
~PathIterator()
{
ImpDtor();
}
bool operator++()
{
return ImpNext();
}
bool IsValid() const
{
return m_bIsValid;
}
const Path& GetPath() const
{
return m_path;
}
};
}
inline FileSystemUtils::Path operator/( const std::string& lhs_, const std::string& rhs_ )
{
//remove any trailing seperators
FileSystemUtils::Path pathlhs = lhs_;
FileSystemUtils::Path pathrhs = rhs_;
return pathlhs / pathrhs;
}