using std::cerr;
using std::endl;
-#define COMPARE(a, b) \
- if ((a) != (b)) { \
- cerr << "failed:" << #a << " != " << #b << endl; \
- exit(1); \
- }
-
-#define VERIFY(a) \
- if (!(a)) { \
- cerr << "failed:" << #a << endl; \
- exit(1); \
- }
-
+#include <simgear/misc/test_macros.hxx>
#include <simgear/misc/sg_path.hxx>
#include <simgear/misc/sg_dir.hxx>
+#include <simgear/misc/sgstream.hxx>
void test_dir()
{
return p;
}
+void test_path_dir()
+{
+ SGPath p(simgear::Dir::current().path());
+ p.append("path_dir");
+ simgear::Dir(p).remove(true);
+
+ VERIFY(p.isAbsolute());
+ COMPARE(p.create_dir(0755), 0);
+
+ SGPath sub = p / "subA" / "subB";
+ VERIFY(!sub.exists());
+
+ SGPath subFile = sub / "fileABC.txt";
+ COMPARE(subFile.create_dir(0755), 0);
+ VERIFY(!subFile.exists());
+
+ sub.set_cached(false);
+ VERIFY(sub.exists());
+ VERIFY(sub.isDir());
+
+ SGPath sub2 = p / "subA" / "fileA";
+ {
+ sg_ofstream os(sub2);
+ VERIFY(os.is_open());
+ for (int i = 0; i < 50; ++i) {
+ os << "ABCD" << endl;
+ }
+ }
+ VERIFY(sub2.isFile());
+ COMPARE(sub2.sizeInBytes(), 250);
+
+ SGPath sub3 = p / "subß" / "file𝕽";
+ sub3.create_dir(0755);
+
+ {
+ sg_ofstream os(sub3);
+ VERIFY(os.is_open());
+ for (int i = 0; i < 20; ++i) {
+ os << "EFGH" << endl;
+ }
+ }
+
+ sub3.set_cached(false);
+ VERIFY(sub3.exists());
+ COMPARE(sub3.sizeInBytes(), 100);
+ COMPARE(sub3.file(), "file𝕽");
+
+ simgear::Dir subD(p / "subA");
+ simgear::PathList dirChildren = subD.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT);
+ COMPARE(dirChildren.size(), 1);
+ COMPARE(dirChildren[0], subD.path() / "subB");
+
+ simgear::PathList fileChildren = subD.children(simgear::Dir::TYPE_FILE | simgear::Dir::NO_DOT_OR_DOTDOT);
+ COMPARE(fileChildren.size(), 1);
+ COMPARE(fileChildren[0], subD.path() / "fileA");
+
+ simgear::Dir subS(sub3.dirPath());
+ fileChildren = subS.children(simgear::Dir::TYPE_FILE | simgear::Dir::NO_DOT_OR_DOTDOT);
+ COMPARE(fileChildren.size(), 1);
+ COMPARE(fileChildren[0], subS.path() / "file𝕽");
+
+}
+
int main(int argc, char* argv[])
{
SGPath pa;
test_dir();
+ test_path_dir();
+
cout << "all tests passed OK" << endl;
return 0; // passed
}
//
// $Id$
-#ifdef HAVE_CONFIG_H
-# include <simgear_config.h>
-#endif
+#include <simgear_config.h>
+#include <simgear/compiler.h>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/structure/exception.hxx>
# include <errno.h>
#endif
+#include <simgear/misc/strutils.hxx>
#include <simgear/debug/logstream.hxx>
#include <boost/foreach.hpp>
_removeOnDestroy = true;
}
-#include <stdio.h>
Dir Dir::current()
{
-#ifdef _WIN32
- char* buf = _getcwd(NULL, 0);
+#if defined(SG_WINDOWS)
+ wchar_t* buf = _wgetcwd(NULL, 0);
#else
char *buf = ::getcwd(NULL, 0);
#endif
}
return Dir(SGPath(buf));
+#else
+#if defined(SG_WINDOWS)
+ std::wstring wideTemplate = simgear::strutils::convertUtf8ToWString(templ);
+ wchar_t* buf = _wtempnam(0, wideTemplate.c_str());
+ SGPath p(buf);
+ free(buf); // unlike tempnam(), _wtempnam mallocs its result buffer
#else
SGPath p(tempnam(0, templ.c_str()));
+#endif
Dir t(p);
if (!t.create(0700)) {
SG_LOG(SG_IO, SG_WARN, "failed to create temporary directory at " << p);
types = TYPE_FILE | TYPE_DIR | NO_DOT_OR_DOTDOT;
}
-#ifdef _WIN32
- std::string search(_path.local8BitStr());
+#if defined(SG_WINDOWS)
+ std::wstring search(_path.wstr());
if (nameFilter.empty()) {
- search += "\\*"; // everything
+ search += simgear::strutils::convertUtf8ToWString("\\*"); // everything
} else {
- search += "\\*" + nameFilter;
+ search += simgear::strutils::convertUtf8ToWString("\\*" + nameFilter);
}
- WIN32_FIND_DATA fData;
- HANDLE find = FindFirstFile(search.c_str(), &fData);
+ WIN32_FIND_DATAW fData;
+ HANDLE find = FindFirstFileW(search.c_str(), &fData);
if (find == INVALID_HANDLE_VALUE) {
int err = GetLastError();
if (err != ERROR_FILE_NOT_FOUND) {
}
bool done = false;
- for (bool done = false; !done; done = (FindNextFile(find, &fData) == 0)) {
+ for (bool done = false; !done; done = (FindNextFileW(find, &fData) == 0)) {
if (fData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
if (!(types & INCLUDE_HIDDEN)) {
continue;
}
}
+ std::string utf8File = simgear::strutils::convertWStringToUtf8(fData.cFileName);
if (fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if (types & NO_DOT_OR_DOTDOT) {
- if (!strcmp(fData.cFileName,".") || !strcmp(fData.cFileName,"..")) {
+ if ((utf8File == ".") || (utf8File == "..")) {
continue;
}
}
continue;
}
- result.push_back(file(fData.cFileName));
+ result.push_back(file(utf8File));
}
FindClose(find);
bool Dir::isEmpty() const
{
- std::string ps = _path.local8BitStr();
-#ifdef _WIN32
- return PathIsDirectoryEmpty( ps.c_str() );
+#if defined(SG_WINDOWS)
+ std::wstring ps = _path.wstr();
+ return PathIsDirectoryEmptyW( ps.c_str() );
#else
+ std::string ps = _path.local8BitStr();
DIR* dp = opendir( ps.c_str() );
if (!dp) return true;
return childPath;
}
-#ifdef _WIN32
-# define sgMkDir(d,m) _mkdir(d)
-#else
-# define sgMkDir(d,m) mkdir(d,m)
-#endif
-
bool Dir::create(mode_t mode)
{
if (exists()) {
}
// finally, create ourselves
+#if defined(SG_WINDOWS)
+ std::wstring ps = _path.wstr();
+ int err = _wmkdir(ps.c_str());
+#else
std::string ps = _path.local8BitStr();
- int err = sgMkDir(ps.c_str(), mode);
+ int err = mkdir(ps.c_str(), mode);
+#endif
if (err) {
SG_LOG(SG_IO, SG_WARN, "directory creation failed: (" << _path << ") " << strerror(errno) );
}
}
} // of recursive deletion
- std::string ps = _path.local8BitStr();
-#ifdef _WIN32
- int err = _rmdir(ps.c_str());
+#if defined(SG_WINDOWS)
+ std::wstring ps = _path.wstr();
+ int err = _wrmdir(ps.c_str());
#else
+ std::string ps = _path.local8BitStr();
int err = rmdir(ps.c_str());
#endif
if (err) {
static SGPath pathForCSIDL(int csidl, const SGPath& def)
{
- typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPSTR, int, BOOL);
+ typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, PWSTR, int, BOOL);
static GetSpecialFolderPath SHGetSpecialFolderPath = NULL;
// lazy open+resolve of shell32
if (!SHGetSpecialFolderPath) {
HINSTANCE shellDll = ::LoadLibrary("shell32");
- SHGetSpecialFolderPath = (GetSpecialFolderPath) GetProcAddress(shellDll, "SHGetSpecialFolderPathA");
+ SHGetSpecialFolderPath = (GetSpecialFolderPath) GetProcAddress(shellDll, "SHGetSpecialFolderPathW");
}
if (!SHGetSpecialFolderPath){
return def;
}
- char path[MAX_PATH];
+ wchar_t path[MAX_PATH];
if (SHGetSpecialFolderPath(0, path, csidl, false)) {
- return SGPath(path, def.getPermissionChecker());
+ return SGPath(std::wstring(path), def.getPermissionChecker());
}
return def;
wchar_t* localFolder = 0;
if (pSHGetKnownFolderPath(folderId, KF_FLAG_DEFAULT_PATH, NULL, &localFolder) == S_OK) {
- // copy into local memory
- char path[MAX_PATH];
- size_t len;
- if (wcstombs_s(&len, path, localFolder, MAX_PATH) != S_OK) {
- path[0] = '\0';
- SG_LOG(SG_GENERAL, SG_WARN, "WCS to MBS failed");
- }
-
- SGPath folder_path = SGPath(path, def.getPermissionChecker());
-
+ SGPath folder_path = SGPath(localFolder, def.getPermissionChecker());
// release dynamic memory
CoTaskMemFree(static_cast<void*>(localFolder));
fix();
}
+// create a path based on "path"
+SGPath::SGPath(const std::wstring& p, PermissionChecker validator) :
+ _permission_checker(validator),
+ _cached(false),
+ _rwCached(false),
+ _cacheEnabled(true)
+{
+ path = simgear::strutils::convertWStringToUtf8(p);
+ fix();
+}
+
+
// create a path based on "path" and a "subpath"
SGPath::SGPath( const SGPath& p,
const std::string& r,
#ifdef _WIN32
struct _stat buf ;
bool remove_trailing = false;
- string statPath(local8BitStr());
+ std::wstring statPath(wstr());
if ((path.length() > 1) && (path.back() == '/')) {
statPath.pop_back();
}
- if (_stat(statPath.c_str(), &buf ) < 0) {
+ if (_wstat(statPath.c_str(), &buf ) < 0) {
_exists = false;
} else {
_exists = true;
}
//------------------------------------------------------------------------------
-#ifdef _WIN32
-# define sgMkDir(d,m) _mkdir(d)
-#else
-# define sgMkDir(d,m) mkdir(d,m)
-#endif
int SGPath::create_dir(mode_t mode)
{
return -3;
}
- string_list dirlist = sgPathSplit(dir());
- if ( dirlist.empty() )
+ SGPath dirP = dirPath();
+ if (dirP.isNull() )
return -1;
- string path = dirlist[0];
- string_list path_elements = sgPathBranchSplit(path);
- bool absolute = !path.empty() && path[0] == sgDirPathSep;
-
+ string_list path_elements = sgPathBranchSplit(dirP.utf8Str());
+ bool absolute = dirP.isAbsolute();
unsigned int i = 1;
- SGPath dir(absolute ? string( 1, sgDirPathSep ) : "", _permission_checker);
- dir.concat( path_elements[0] );
- std::string ds = dir.local8BitStr();
-#ifdef _WIN32
- if ( ds.find(':') != string::npos && path_elements.size() >= 2 ) {
- dir.append( path_elements[1] );
- i = 2;
- ds = dir.local8BitStr();
- }
+
+#if defined(SG_WINDOWS)
+ SGPath dir(path_elements.front(), _permission_checker);
+ // exists() does not work for drive letter paths, eg 'C:\'.
+ // Detect this case and skip to the next element immediately
+ if (absolute && path_elements.size() >= 2) {
+ dir.append(path_elements[i++]);
+ }
+#else
+ SGPath dir((absolute ? "/" : "") + path_elements.front(), _permission_checker);
#endif
- struct stat info;
- int r;
- for(; (r = stat(dir.c_str(), &info)) == 0 && i < path_elements.size(); ++i) {
- dir.append(path_elements[i]);
-}
- if( r == 0 )
- return 0; // Directory already exists
+ while (dir.exists() && (i < path_elements.size())) {
+ dir.append(path_elements[i++]);
+ }
+
+ // already exists
+ if (dir.exists() && (i == path_elements.size())) {
+ return 0;
+ }
for(;;)
{
- if( sgMkDir(dir.c_str(), mode) )
+#if defined (SG_WINDOWS)
+ std::wstring ds = dir.wstr();
+ if (_wmkdir(ds.c_str()))
+#else
+ std::string ds = dir.utf8Str();
+ if( mkdir(ds.c_str(), mode) )
+#endif
{
- SG_LOG( SG_IO,
- SG_ALERT, "Error creating directory: (" << dir << ")" );
- return -2;
+ SG_LOG( SG_IO, SG_ALERT, "Error creating directory: (" << dir << "):"
+ << simgear::strutils::error_string(errno) );
+ return errno;
}
else
SG_LOG(SG_IO, SG_DEBUG, "Directory created: " << dir);
- if( i >= path_elements.size() )
- return 0;
+ if (i >= path_elements.size()) {
+ break;
+ }
dir.append(path_elements[i++]);
}
+ _cached = false; // re-stat on next query
return 0;
}
return false;
}
+#if defined(SG_WINDOWS)
+ std::wstring ps = wstr();
+ int err = _wunlink(ps.c_str());
+#else
std::string ps = local8BitStr();
int err = ::unlink(ps.c_str());
+#endif
if( err )
{
SG_LOG( SG_IO, SG_WARN, "file remove failed: (" << *this << ") "
}
}
#endif
+
+#if defined(SG_WINDOWS)
+ std::wstring p = wstr();
+ std::wstring np = newName.wstr();
+ if (_wrename(p.c_str(), np.c_str()) != 0)
+#else
std::string p = local8BitStr();
std::string np = newName.local8BitStr();
+ if( ::rename(p.c_str(), np.c_str()) != 0 )
+#endif
- if( ::rename(p.c_str(), np.c_str()) != 0 )
{
SG_LOG( SG_IO, SG_WARN, "rename failed: from " << *this <<
" to " << newName <<
//------------------------------------------------------------------------------
SGPath SGPath::fromEnv(const char* name, const SGPath& def)
{
+#if defined(SG_WINDOWS)
+ std::wstring wname = simgear::strutils::convertUtf8ToWString(name);
+ const wchar_t* val = _wgetenv(wname.c_str());
+ if (val && val[0])
+ return SGPath(val, def._permission_checker);
+#else
const char* val = getenv(name);
if( val && val[0] )
return SGPath(val, def._permission_checker);
+#endif
return def;
}
std::vector<SGPath> SGPath::pathsFromEnv(const char *name)
{
std::vector<SGPath> r;
- const char* val = getenv(name);
- if (!val) {
- return r;
- }
-
- string_list items = sgPathSplit(val);
- string_list_iterator it;
- for (it = items.begin(); it != items.end(); ++it) {
- r.push_back(SGPath::fromLocal8Bit(it->c_str()));
- }
-
- return r;
+#if defined(SG_WINDOWS)
+ std::wstring wname = simgear::strutils::convertUtf8ToWString(name);
+ const wchar_t* val = _wgetenv(wname.c_str());
+#else
+ const char* val = getenv(name);
+#endif
+ if (!val) {
+ return r;
+ }
+
+#if defined(SG_WINDOWS)
+ return pathsFromUtf8(simgear::strutils::convertWStringToUtf8(val));
+#else
+ return pathsFromUtf8(val);
+#endif
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
SGPath SGPath::realpath() const
{
-#if defined(_MSC_VER) /*for MS compilers */ || defined(_WIN32) /*needed for non MS windows compilers like MingW*/
+#if defined(SG_WINDOWS)
// with absPath NULL, will allocate, and ignore length
- char *buf = _fullpath( NULL, path.c_str(), _MAX_PATH );
+ std::wstring ws = wstr();
+ wchar_t *buf = _wfullpath( NULL, ws.c_str(), _MAX_PATH );
#else
// POSIX
char* buf = ::realpath(path.c_str(), NULL);
}
return SGPath(this_dir).realpath() / file();
}
- SGPath p(SGPath::fromLocal8Bit(buf));
+
+#if defined(SG_WINDOWS)
+ SGPath p = SGPath(std::wstring(buf), NULL);
+#else
+ SGPath p(SGPath::fromLocal8Bit(buf));
+#endif
free(buf);
return p;
+
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
std::wstring SGPath::wstr() const
{
-#ifdef SG_WINDOWS
- simgear::strutils::WCharVec ws = simgear::strutils::convertUtf8ToWString(path);
- return std::wstring(ws.data(), ws.size());
-#else
- const size_t buflen = mbstowcs(NULL, path.c_str(), 0)+1;
- wchar_t* wideBuf = (wchar_t*)malloc(buflen * sizeof(wchar_t));
- if (wideBuf) {
- size_t count = mbstowcs(wideBuf, path.c_str(), buflen);
- if (count == (size_t)-1) {
- return std::wstring();
- }
-
- std::wstring rv(wideBuf, count);
- free(wideBuf);
- return rv;
- } else {
- SG_LOG( SG_GENERAL, SG_ALERT, "SGPath::wstr: unable to allocate enough memory for " << *this );
- }
-#endif
- return std::wstring();
+ return simgear::strutils::convertUtf8ToWString(path);
}
*/
SGPath( const std::string& p, PermissionChecker validator = NULL );
+ explicit SGPath(const std::wstring& p, PermissionChecker validator = NULL);
+
/**
* Construct a path based on the starting path provided and a relative subpath
* @param p initial path
void
sg_gzofstream::open( const SGPath& name, ios_openmode io_mode )
{
- std::string ps = name.local8BitStr();
- gzbuf.open( ps.c_str(), io_mode );
+ gzbuf.open( name.c_str(), io_mode );
}
void
sg_ifstream::sg_ifstream(const SGPath& path, ios_openmode io_mode)
{
+#if defined(SG_WINDOWS)
+ std::wstring ps = path.wstr();
+#else
std::string ps = path.local8BitStr();
- std::ifstream::open(ps.c_str(), io_mode);
+#endif
+ std::ifstream::open(ps.c_str(), io_mode);
}
void sg_ifstream::open( const SGPath& name, ios_openmode io_mode )
{
- std::string ps = name.local8BitStr();
+#if defined(SG_WINDOWS)
+ std::wstring ps = name.wstr();
+#else
+ std::string ps = name.local8BitStr();
+#endif
std::ifstream::open(ps.c_str(), io_mode);
}
sg_ofstream::sg_ofstream(const SGPath& path, ios_openmode io_mode)
{
- std::string ps = path.local8BitStr();
+#if defined(SG_WINDOWS)
+ std::wstring ps = path.wstr();
+#else
+ std::string ps = path.local8BitStr();
+#endif
std::ofstream::open(ps.c_str(), io_mode);
}
void sg_ofstream::open( const SGPath& name, ios_openmode io_mode )
{
- std::string ps = name.local8BitStr();
+#if defined(SG_WINDOWS)
+ std::wstring ps = name.wstr();
+#else
+ std::string ps = name.local8BitStr();
+#endif
std::ofstream::open(ps.c_str(), io_mode);
}
#include <simgear/compiler.h> // SG_WINDOWS
#include <simgear/structure/exception.hxx>
+
+#if defined(SG_WINDOWS)
+ #include <windows.h>
+#endif
+
using std::string;
using std::vector;
using std::stringstream;
}
#if defined(SG_WINDOWS)
-
-#include <windows.h>
-
-static WCharVec convertMultiByteToWString(DWORD encoding, const std::string& a)
+static std::wstring convertMultiByteToWString(DWORD encoding, const std::string& a)
{
- WCharVec result;
+ std::vector<wchar_t> result;
DWORD flags = 0;
int requiredWideChars = MultiByteToWideChar(encoding, flags,
a.c_str(), a.size(),
result.resize(requiredWideChars);
MultiByteToWideChar(encoding, flags, a.c_str(), a.size(),
result.data(), result.size());
- return result;
+ return std::wstring(result.data(), result.size());
}
-WCharVec convertUtf8ToWString(const std::string& a)
+static std::string convertWStringToMultiByte(DWORD encoding, const std::wstring& w)
+{
+ std::vector<char> result;
+ DWORD flags = 0;
+ int requiredMBChars = WideCharToMultiByte(encoding, flags,
+ w.data(), w.size(),
+ NULL, 0, NULL, NULL);
+ result.resize(requiredMBChars);
+ WideCharToMultiByte(encoding, flags,
+ w.data(), w.size(),
+ result.data(), result.size(), NULL, NULL);
+ return std::string(result.data(), result.size());
+}
+#endif
+
+std::wstring convertUtf8ToWString(const std::string& a)
{
+#ifdef SG_WINDOWS
return convertMultiByteToWString(CP_UTF8, a);
+#else
+#endif
}
+std::string convertWStringToUtf8(const std::wstring& w)
+{
+#ifdef SG_WINDOWS
+ return convertWStringToMultiByte(CP_UTF8, w);
+#else
+
#endif
+}
std::string convertWindowsLocal8BitToUtf8(const std::string& a)
{
#ifdef SG_WINDOWS
- DWORD flags = 0;
- WCharVec wideString = convertMultiByteToWString(CP_ACP, a);
-
- // convert down to UTF-8
- std::vector<char> result;
- int requiredUTF8Chars = WideCharToMultiByte(CP_UTF8, flags,
- wideString.data(), wideString.size(),
- NULL, 0, NULL, NULL);
- result.resize(requiredUTF8Chars);
- WideCharToMultiByte(CP_UTF8, flags,
- wideString.data(), wideString.size(),
- result.data(), result.size(), NULL, NULL);
- return std::string(result.data(), result.size());
+ return convertWStringToMultiByte(CP_UTF8, convertMultiByteToWString(CP_ACP, a));
#else
return a;
#endif
std::string convertUtf8ToWindowsLocal8Bit(const std::string& a)
{
#ifdef SG_WINDOWS
- DWORD flags = 0;
- WCharVec wideString = convertMultiByteToWString(CP_UTF8, a);
-
- // convert down to local multi-byte
- std::vector<char> result;
- int requiredChars = WideCharToMultiByte(CP_ACP, flags,
- wideString.data(), wideString.size(),
- NULL, 0, NULL, NULL);
- result.resize(requiredChars);
- WideCharToMultiByte(CP_ACP, flags,
- wideString.data(), wideString.size(),
- result.data(), result.size(), NULL, NULL);
- return std::string(result.data(), result.size());
+ return convertWStringToMultiByte(CP_ACP, convertMultiByteToWString(CP_UTF8, a));
#else
return a;
#endif
*/
std::string convertUtf8ToWindowsLocal8Bit(const std::string& a);
-#if defined(SG_WINDOWS)
- typedef std::vector<wchar_t> WCharVec;
- WCharVec convertUtf8ToWString(const std::string& a);
-#endif
+ std::wstring convertUtf8ToWString(const std::string& a);
+ std::string convertWStringToUtf8(const std::wstring& w);
/**
* Get md5 hash of raw data.
// $Id$
#include <simgear/compiler.h>
+#include <simgear_config.h>
#include <cerrno>
#include <memory.h>
#include <stdio.h>
+#include <fcntl.h>
+
+#include <simgear/misc/strutils.hxx>
#include "zfstream.hxx"
char char_mode[10];
cvt_iomode( char_mode, io_mode );
+
+#if defined(SG_WINDOWS)
+ std::wstring ws = simgear::strutils::convertUtf8ToWString(std::string(name));
+ if ( (file = gzopen_w(ws.c_str(), char_mode)) == NULL ) {
+
+#else
if ( (file = gzopen(name, char_mode)) == NULL ) {
+#endif
// perror( "gzfilebuf::open(): " );
errno = 0;
return NULL;