Changeset 281 for cpp/common


Ignore:
Timestamp:
12/27/14 01:01:43 (9 years ago)
Author:
Maciej Komosinski
Message:

Support for wide char (unicode) names of files and directories under Windows, internally encoded as char* utf-8

Location:
cpp/common
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • cpp/common/Convert.cpp

    r257 r281  
    128128        return string(ret, 24); //24 znaki z pominieciem ostatniego \n
    129129}
     130
     131string Convert::wstrToUtf8(const wchar_t *str)
     132{
     133        if (str == NULL) return "";
     134        string res;
     135        wchar_t *wcp = (wchar_t*)str;
     136        while (*wcp != 0)
     137        {
     138                int c = *wcp;
     139                if (c < 0x80) res += c;
     140                else if (c < 0x800) { res += 192 + c / 64; res += 128 + c % 64; }
     141                else if (c - 0xd800u < 0x800) res += "<ERROR-CHAR>";
     142                else if (c < 0x10000) { res += 224 + c / 4096; res += 128 + c / 64 % 64; res += 128 + c % 64; }
     143                else if (c < 0x110000) { res += 240 + c / 262144; res += 128 + c / 4096 % 64; res += 128 + c / 64 % 64; res += 128 + c % 64; }
     144                else res += "<ERROR-CHAR>";
     145                wcp++;
     146        }
     147        return res;
     148}
     149
     150#ifdef _WIN32
     151wstring Convert::utf8ToUtf16(const char *str)
     152{
     153        wstring wstr;
     154        int nOffset = 0;
     155        int nDataLen = strlen(str) + 1; //including ending \0
     156        int nLenWide = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(str + nOffset),
     157                (int)(nDataLen - nOffset), NULL, 0);
     158        wstr.resize(nLenWide);
     159        if (MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)(str + nOffset),
     160                (int)(nDataLen - nOffset),
     161                &wstr[0], nLenWide) != nLenWide)
     162        {
     163                //ASSERT(false); //some conversion error
     164                return wstr;
     165        }
     166        return wstr;
     167}
     168#endif
  • cpp/common/Convert.h

    r247 r281  
    7272        }
    7373
    74         static string wstrTOutf8(const wchar_t *s)
    75         {
    76                 if (s == NULL) return "";
    77                 string res;
    78                 wchar_t *wcp = (wchar_t*)s;
    79                 while (*wcp != 0)
    80                 {
    81                         int c = *wcp;
    82                         if (c < 0x80) res += c;
    83                         else if (c < 0x800) { res += 192 + c / 64; res += 128 + c % 64; }
    84                         else if (c - 0xd800u < 0x800) res += "<ERR-CHAR>";
    85                         else if (c < 0x10000) { res += 224 + c / 4096; res += 128 + c / 64 % 64; res += 128 + c % 64; }
    86                         else if (c < 0x110000) { res += 240 + c / 262144; res += 128 + c / 4096 % 64; res += 128 + c / 64 % 64; res += 128 + c % 64; }
    87                         else res += "<ERR-CHAR>";
    88                         wcp++;
    89                 }
    90                 return res;
    91         }
    92         //#endif
     74        static string wstrToUtf8(const wchar_t *str);
     75#ifdef _WIN32
     76        static wstring utf8ToUtf16(const char *str);
     77#endif
    9378};
    9479
  • cpp/common/nonstd_stdio.cpp

    r247 r281  
    55#include "nonstd_stdio.h"
    66#include "nonstd.h"
    7 #include "Convert.h" //strTOwstr()
     7#include "Convert.h" //utf8ToUtf16()
    88#include <common/stl-util.h>
    99
    1010#if defined _WIN32 && !defined SHP
    11  //<unistd.h> not needed for unlink()
    12  #include "Shlwapi.h" //PathIsRelative()
    13  #include <sys/stat.h> //_stat
    14 #else
    15  #include <unistd.h>
     11//<unistd.h> not needed for unlink()
     12#include "Shlwapi.h" //PathIsRelative()
     13#include <sys/stat.h> //_stat
     14#else
     15#include <unistd.h>
    1616#endif
    1717
    1818bool fileExists(const char* path)
    1919{
    20 //lepiej gdyby uzywalo stat bo mfopen mogloby cos niepotrzebnie wczytywac przy otwarciu pliku ale mfopen wiadomo ze zadziala wszedzie tak samo
    21 MFILE *f=mfopen(path,FOPEN_READ_BINARY);
    22 if (f==NULL) return false;
    23 mfclose(f);
    24 return true;
     20        //lepiej gdyby uzywalo stat bo mfopen mogloby cos niepotrzebnie wczytywac przy otwarciu pliku ale mfopen wiadomo ze zadziala wszedzie tak samo
     21#ifdef _WIN32
     22        MFILE *f = mfopen(Convert::utf8ToUtf16(path).c_str(), Convert::strTOwstr(FOPEN_READ_BINARY).c_str());
     23#else
     24        MFILE *f = mfopen(path, FOPEN_READ_BINARY);
     25#endif
     26        if (f == NULL) return false;
     27        mfclose(f);
     28        return true;
    2529}
    2630
    2731bool directoryExists(const char* path)
    2832{
    29 struct _stat s;
    30 if (_stat(path,&s)!=0) return false;
    31 return S_ISDIR(s.st_mode);
     33        struct _stat s;
     34#ifdef _WIN32
     35        if (_wstat(Convert::utf8ToUtf16(path).c_str(), &s) != 0) return false;
     36#else
     37        if (_stat(path, &s) != 0) return false;
     38#endif
     39        return S_ISDIR(s.st_mode);
    3240}
    3341
     
    3543{
    3644#ifdef _WIN32
    37 return mkdir(path)==0;
    38 #else
    39 return mkdir(path,0777)==0;
     45        return _wmkdir(Convert::utf8ToUtf16(path).c_str()) == 0;
     46#else
     47        return mkdir(path,0777) == 0;
    4048#endif
    4149}
     
    4351bool makeDirectories(const char* path)
    4452{
    45 if (directoryExists(path)) return true;
    46 string parentdir=getFileDir(path);
    47 if (!makeDirectories(parentdir.c_str())) return false;
    48 return makeDirectory(path);
     53        if (directoryExists(path)) return true;
     54        string parentdir = getFileDir(path);
     55        if (!makeDirectories(parentdir.c_str())) return false;
     56        return makeDirectory(path);
    4957}
    5058
    5159int getFileSize(const char* path)
    5260{
    53 int size;
    54 MFILE *f=mfopen(path,FOPEN_READ_BINARY);
    55 if (f==NULL) return -1;
    56 size=getFileSize(f);
    57 mfclose(f);
    58 return size;
     61        int size;
     62#ifdef _WIN32
     63        MFILE *f = mfopen(Convert::utf8ToUtf16(path).c_str(), Convert::strTOwstr(FOPEN_READ_BINARY).c_str());
     64#else
     65        MFILE *f = mfopen(path, FOPEN_READ_BINARY);
     66#endif
     67        if (f == NULL) return -1;
     68        size = getFileSize(f);
     69        mfclose(f);
     70        return size;
    5971}
    6072
    6173int getFileSize(MFILE *f)
    6274{
    63   int saved_pos = mftell(f);
    64   mfseek(f, 0, SEEK_END);
    65   int size = mftell(f);
    66   mfseek(f, saved_pos, SEEK_SET);
    67   return size;
     75        int saved_pos = mftell(f);
     76        mfseek(f, 0, SEEK_END);
     77        int size = mftell(f);
     78        mfseek(f, saved_pos, SEEK_SET);
     79        return size;
    6880}
    6981
    7082bool removeFile(const char* path)
    7183{
    72   return _unlink(path)==0; //VS: "The POSIX name is deprecated. Instead, use the ISO C++ conformant name: _unlink"
     84#ifdef _WIN32
     85        return _wunlink(Convert::utf8ToUtf16(path).c_str()) == 0;
     86#else
     87        return _unlink(path) == 0; //VS: "The POSIX name is deprecated. Instead, use the ISO C++ conformant name: _unlink"
     88#endif
    7389}
    7490
     
    7692{
    7793        if (fname == NULL) return false; //SplitFileSystem never passes NULL but this function is public so we never know
    78 #if defined _WIN32 && !defined SHP
    79  #ifdef __BORLANDC__
    80         return PathIsRelative(fname) == FALSE; //no wide char for old borland compiler
    81  #else
    82         return PathIsRelative(Convert::strTOwstr(fname).c_str()) == FALSE; //http://msdn.microsoft.com/en-us/library/bb773660%28v=vs.85%29.aspx
    83  #endif
     94#if defined _WIN32
     95        return PathIsRelativeW(Convert::utf8ToUtf16(fname).c_str()) == FALSE; //http://msdn.microsoft.com/en-us/library/bb773660%28v=vs.85%29.aspx
    8496#else
    8597        return fname[0] == PATH_SEPARATOR_CHAR;
  • cpp/common/nonstd_stdio.h

    r247 r281  
    2020 #include <dir.h>
    2121#else
    22  #ifndef MOBILE2D
    2322 #include <direct.h>
    24  #endif
    2523 #define mkdir _mkdir
     24 #define S_ISDIR(m)     (((m)&S_IFDIR)==S_IFDIR)
    2625#endif
    2726
    28 #ifndef MOBILE2D
    29  #include <io.h> //borland compiler: include <io.h> before <dir.h> causes the SimWorld class in "simul.h" be unrecognized, for unknown reason :O moreover, this problem is only pertinent to the CLI project, not GUI. Maybe this is caused by global defines like NOVCL, NO_STRICT etc.?
     27#include <io.h> //borland compiler: include <io.h> before <dir.h> causes the SimWorld class in "simul.h" be unrecognized, for unknown reason :O moreover, this problem is only pertinent to the CLI project, not GUI. Maybe this is caused by global defines like NOVCL, NO_STRICT etc.?
    3028// #define makeDirectory(name) mkdir(name)
    31 #endif
    32 
    33  #define S_ISDIR(x) ((x & _S_IFDIR)==_S_IFDIR)
    3429
    3530#else
    3631
    37  #include <unistd.h>
    38  #include <sys/stat.h>
     32#include <unistd.h>
     33#include <sys/stat.h>
    3934// #define makeDirectory(name) mkdir(name,0777)
    40  #define _unlink unlink //_unlink jest ISO-conformant, unlink jest POSIX-deprecated
    41  #define _stat stat
     35#define _unlink unlink //_unlink jest ISO-conformant, unlink jest POSIX-deprecated
     36#define _stat stat
    4237#endif
    4338
     
    4944#ifdef __ANDROID__
    5045#include <nv_file/nv_file.h>
    51  struct rwFILE //jedno z dwoch pol jest zainicjowane w zaleznosci od tego gdzie jest plik
    52  { //nvidia uses a similar trick in nv_file.h (STD_FILE and APK_FILE), maybe doing a similar thing here is redundant? but their trick uses some trial-and-error code (see NvFOpen())
     46struct rwFILE //jedno z dwoch pol jest zainicjowane w zaleznosci od tego gdzie jest plik
     47{ //nvidia uses a similar trick in nv_file.h (STD_FILE and APK_FILE), maybe doing a similar thing here is redundant? but their trick uses some trial-and-error code (see NvFOpen())
    5348        NvFile *rfile; //can only read
    5449        FILE *rwfile;
    5550        rwFILE() {rfile=rwfile=NULL;}
    56  };
    57  typedef rwFILE MFILE;
     51};
     52typedef rwFILE MFILE;
    5853#else //SHP:
    59  //z <stdio.h> wzielismy sprintfy i inne ktore dzia³aj¹...
    60  #include <FIo.h>
    61  // wklejone z sailora w ramach integracji frams+engine
    62  // ale to nie sprawia ze framsy korzystaja z mfile - potrzebna jest implementacja virtfile dla bady! (patrz: stdiofile.h)
    63  // i wtedy bedzie mozna mfile wywalic tez z sailora
    64  typedef Osp::Io::File MFILE;
     54//z <stdio.h> wzielismy sprintfy i inne ktore dzia³aj¹...
     55#include <FIo.h>
     56// wklejone z sailora w ramach integracji frams+engine
     57// ale to nie sprawia ze framsy korzystaja z mfile - potrzebna jest implementacja virtfile dla bady! (patrz: stdiofile.h)
     58// i wtedy bedzie mozna mfile wywalic tez z sailora
     59typedef Osp::Io::File MFILE;
    6560#endif
    6661
     
    8277
    8378#else
    84  typedef FILE MFILE;
     79typedef FILE MFILE;
     80#ifdef _WIN32
     81 #define mfopen _wfopen
     82#else
    8583 #define mfopen fopen
    86  #define mfclose fclose
    87  #define mfread fread
    88  #define mfwrite fwrite
    89  #define mfputs fputs
    90  #define mfgets fgets
    91  #define mfeof feof
    92  #define mfseek fseek
    93  #define mftell ftell
     84#endif
     85#define mfclose fclose
     86#define mfread fread
     87#define mfwrite fwrite
     88#define mfputs fputs
     89#define mfgets fgets
     90#define mfeof feof
     91#define mfseek fseek
     92#define mftell ftell
    9493#endif
    9594
  • cpp/common/stl-util.cpp

    r257 r281  
    77#include <stdlib.h>
    88#include "nonstd_stdio.h"
     9#include "Convert.h"
    910#include "nonstd.h"
    1011#include "framsg.h"
     
    9192#endif
    9293        {
     94#ifdef _WIN32
     95                MFILE *f = mfopen(Convert::utf8ToUtf16(filename).c_str(), Convert::strTOwstr(FOPEN_READ_BINARY).c_str());
     96#else
    9397                MFILE *f = mfopen(filename, FOPEN_READ_BINARY);
     98#endif
    9499                if (f)
    95100                {
     
    119124bool writeCompleteFile(const char* filename, const string& text, bool warn_on_fail)
    120125{
     126#ifdef _WIN32
     127        MFILE *f = mfopen(Convert::utf8ToUtf16(filename).c_str(), Convert::strTOwstr(FOPEN_WRITE_BINARY).c_str());
     128#else
    121129        MFILE *f = mfopen(filename, FOPEN_WRITE_BINARY);
     130#endif
    122131        bool ok = f != NULL;
    123132        if (f)
Note: See TracChangeset for help on using the changeset viewer.