]> git.mxchange.org Git - simgear.git/commitdiff
Use wide-string APIs on Windows.
authorJames Turner <zakalawe@mac.com>
Mon, 4 Jul 2016 16:23:42 +0000 (17:23 +0100)
committerRoland Haeder <roland@mxchange.org>
Sat, 13 Aug 2016 08:21:16 +0000 (10:21 +0200)
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.

simgear/misc/path_test.cxx
simgear/misc/sg_dir.cxx
simgear/misc/sg_path.cxx
simgear/misc/sg_path.hxx
simgear/misc/sgstream.cxx
simgear/misc/strutils.cxx
simgear/misc/strutils.hxx
simgear/misc/zfstream.cxx

index bfe8754612e3ba47815f8e45ad6ccf3ea24d7336..a640389e66d8c469d94a30981c81b774849d1c25 100644 (file)
@@ -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
 }
index 18f14b19021a4897af69d1e648d487b6899bc4d6..208a05ede923466f8a00303fc3232c40a1ef8e77 100644 (file)
@@ -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) {
index ffc2641a26c9a08c4ba702e21de06721c7df55f8..2ff8f40b9727a7050a5968797ef29992e4716344 100644 (file)
@@ -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);
 }
index f30b6a4b0c0d18e8313eebec39548beebc9716cc..a35c64e41eca7dc80283a9355c67bd9a0870a849 100644 (file)
@@ -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
index 41289a632750776db8a01685dc7c758b7e727740..8f289c4083ee13c7c5341685522a98267879a441 100644 (file)
@@ -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);
 }
index ff18ec7216f40977e48b9d677af8932c7fde640c..48d8fea8441fc9c2f920c9e2276e829acbe4cb91 100644 (file)
 #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)
+{
+       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
index baad38cb870bb9319a33e3c485ad0861e1297a5d..dd78863c373bffc8e14ebf67ae1d7f86ac5cdc2a 100644 (file)
@@ -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.
index eae24f78b16d88ecb7d4332f0f55a539db3fc0d7..f1a07d072e7c8194feb2fa557ffffa8a324db5ba 100644 (file)
 // $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;