Use wide-string APIs on Windows.
SGPath and simgear::Dir use ‘w’ versions of POSIX APIs on Windows, and convert UTF-8 SGPath to wide-strings as part of this. Includes improved unit-tests for this code, with some very basic tests of creating and iterating files with Unicode characters in their names. No user-visible changes should result from this, on any platform; in particular wide-string support is still incomplete so FlightGear will not yet work with arbitrary Unicode paths on Windows.
This commit is contained in:
@@ -9,20 +9,10 @@ using std::cout;
|
||||
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()
|
||||
{
|
||||
@@ -81,6 +71,69 @@ SGPath::Permissions validateWrite(const SGPath&)
|
||||
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;
|
||||
@@ -197,6 +250,8 @@ int main(int argc, char* argv[])
|
||||
|
||||
test_dir();
|
||||
|
||||
test_path_dir();
|
||||
|
||||
cout << "all tests passed OK" << endl;
|
||||
return 0; // passed
|
||||
}
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
//
|
||||
// $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>
|
||||
@@ -41,6 +40,7 @@
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
@@ -85,11 +85,10 @@ void Dir::setRemoveOnDestroy()
|
||||
_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
|
||||
@@ -124,8 +123,15 @@ Dir Dir::tempDir(const std::string& templ)
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -147,16 +153,16 @@ PathList Dir::children(int types, const std::string& nameFilter) const
|
||||
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) {
|
||||
@@ -167,16 +173,17 @@ PathList Dir::children(int types, const std::string& nameFilter) const
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -192,7 +199,7 @@ PathList Dir::children(int types, const std::string& nameFilter) const
|
||||
continue;
|
||||
}
|
||||
|
||||
result.push_back(file(fData.cFileName));
|
||||
result.push_back(file(utf8File));
|
||||
}
|
||||
|
||||
FindClose(find);
|
||||
@@ -272,10 +279,11 @@ PathList Dir::children(int types, const std::string& nameFilter) const
|
||||
|
||||
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;
|
||||
|
||||
@@ -301,12 +309,6 @@ SGPath Dir::file(const std::string& name) const
|
||||
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()) {
|
||||
@@ -323,8 +325,13 @@ bool Dir::create(mode_t mode)
|
||||
}
|
||||
|
||||
// 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) );
|
||||
}
|
||||
@@ -367,10 +374,11 @@ bool Dir::remove(bool recursive)
|
||||
}
|
||||
} // 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) {
|
||||
|
||||
@@ -68,22 +68,22 @@ static const char sgSearchPathSep = ':';
|
||||
|
||||
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;
|
||||
@@ -101,16 +101,7 @@ static SGPath pathForKnownFolder(REFKNOWNFOLDERID folderId, const SGPath& 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));
|
||||
|
||||
@@ -213,6 +204,18 @@ SGPath::SGPath( const std::string& p, PermissionChecker validator )
|
||||
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,
|
||||
@@ -463,12 +466,12 @@ void SGPath::validate() const
|
||||
#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;
|
||||
@@ -549,11 +552,6 @@ bool SGPath::isFile() const
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
# define sgMkDir(d,m) _mkdir(d)
|
||||
#else
|
||||
# define sgMkDir(d,m) mkdir(d,m)
|
||||
#endif
|
||||
|
||||
int SGPath::create_dir(mode_t mode)
|
||||
{
|
||||
@@ -565,49 +563,57 @@ 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;
|
||||
}
|
||||
|
||||
@@ -704,8 +710,13 @@ bool SGPath::remove()
|
||||
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 << ") "
|
||||
@@ -759,10 +770,17 @@ bool SGPath::rename(const SGPath& newName)
|
||||
}
|
||||
}
|
||||
#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 <<
|
||||
@@ -851,9 +869,16 @@ SGPath SGPath::standardLocation(StandardLocation type, const SGPath& def)
|
||||
//------------------------------------------------------------------------------
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -862,18 +887,21 @@ SGPath SGPath::fromEnv(const char* name, const SGPath& 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
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -929,9 +957,10 @@ SGPath SGPath::documents(const SGPath& def)
|
||||
//------------------------------------------------------------------------------
|
||||
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);
|
||||
@@ -956,9 +985,15 @@ SGPath SGPath::realpath() const
|
||||
}
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -981,24 +1016,5 @@ std::string SGPath::join(const std::vector<SGPath>& paths, const std::string& jo
|
||||
//------------------------------------------------------------------------------
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,8 @@ public:
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -185,8 +185,7 @@ sg_gzofstream::sg_gzofstream( int fd, ios_openmode io_mode )
|
||||
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
|
||||
@@ -198,24 +197,40 @@ sg_gzofstream::attach( int fd, ios_openmode io_mode )
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
#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;
|
||||
@@ -363,12 +368,9 @@ namespace simgear {
|
||||
}
|
||||
|
||||
#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(),
|
||||
@@ -376,32 +378,45 @@ static WCharVec convertMultiByteToWString(DWORD encoding, const std::string& a)
|
||||
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)
|
||||
{
|
||||
return convertMultiByteToWString(CP_UTF8, a);
|
||||
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
|
||||
@@ -410,19 +425,7 @@ std::string convertWindowsLocal8BitToUtf8(const std::string& a)
|
||||
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
|
||||
|
||||
@@ -176,10 +176,8 @@ namespace simgear {
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -22,10 +22,14 @@
|
||||
// $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"
|
||||
|
||||
@@ -110,7 +114,14 @@ gzfilebuf::open( const char *name, ios_openmode io_mode )
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user