Changeset 281


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
Files:
7 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)
  • cpp/frams/virtfile/stdiofile.cpp

    r227 r281  
    77#include <common/nonstd_stdio.h>
    88#include <common/framsg.h>
     9#include <common/Convert.h>
    910
    10 VirtFILE* StdioFileSystem::Vfopen(const char* path,const char*mode)
     11VirtFILE* StdioFileSystem::Vfopen(const char *path, const char *mode)
    1112{
    1213        //printFM("Vfopen %s %s",path,mode);
    1314#ifdef USE_MFILE
    14         MFILE *f=mfopen(path,mode);
     15        MFILE *f = mfopen(path, mode);
    1516#else
    16         FILE *f=fopen(path,mode);
     17#ifdef _WIN32
     18        FILE *f = _wfopen(Convert::utf8ToUtf16(path).c_str(), Convert::strTOwstr(mode).c_str());
     19#else
     20        FILE *f = fopen(path, mode);
     21#endif
    1722#endif
    1823        //printFM("%p",f);
    19         if (f) return new StdioFILE(f,path); else return 0;
     24        if (f) return new StdioFILE(f, path); else return 0;
    2025}
    2126
     
    2328{
    2429        //printFM("Vopendir %s",path);
    25         DIR *d=opendir(path);
     30#ifdef _WIN32
     31        DIRTYPE *d = wopendir(Convert::utf8ToUtf16(path).c_str());
     32#else
     33        DIR *d = opendir(path);
     34#endif
    2635        //printFM("%p",d);
    2736        if (d) return new StdioDIR(d); else return 0;
     
    4857{
    4958        //printFM("Vreaddir %s",dir);
     59#ifdef _WIN32
     60        wdirent *wde=wreaddir(dir);
     61        if (wde==NULL) return NULL;
     62        strcpy(de.d_name, Convert::wstrToUtf8(wde->d_name).c_str());
     63        return &de;
     64#else
    5065        return readdir(dir);
     66#endif
    5167}
  • cpp/frams/virtfile/stdiofile.h

    r247 r281  
    1515#include <common/nonstd_dir.h>
    1616
    17 class StdioFileSystem: public VirtFileSystem
     17class StdioFileSystem : public VirtFileSystem
    1818{
    1919public:
    20 VirtFILE *Vfopen(const char* path,const char*mode);
    21 int Vfexists(const char* path);
    22 VirtDIR *Vopendir(const char* path);
     20        VirtFILE *Vfopen(const char *path, const char *mode);
     21        int Vfexists(const char* path);
     22        VirtDIR *Vopendir(const char* path);
    2323};
    2424
    2525#ifdef USE_MFILE
    26 class StdioFILE: public VirtFILE
     26class StdioFILE : public VirtFILE
    2727{
    28   protected:
    29 MFILE *file;
    30 SString path;
    31   public:
    32 StdioFILE(MFILE *f) {file=f;}
    33 StdioFILE(MFILE *f,const SString& p) {file=f;path=p;}
    34 static void setStdio();
    35 size_t Vread(void *ptr, size_t size, size_t nmemb) {return mfread(ptr,size,nmemb,file);}
    36 size_t Vwrite(const void *ptr, size_t size, size_t nmemb) {return mfwrite(ptr,size,nmemb,file);}
    37 int Veof() {return mfeof(file);}
    38 int Vputs(const char *s) {return mfputs(s,file);}
    39 char *Vgets(char *s, int size) {return mfgets(s,size,file);}
    40 int Vseek(long offset, int whence) {return mfseek(file,offset,whence);}
    41 long Vtell() {return mftell(file);}
    42 int Vflush() {return 0;/*NOT IMPLEMENTED!*/;}
    43 const char* VgetPath() {return path;}
     28protected:
     29        MFILE *file;
     30        SString path;
     31public:
     32        StdioFILE(MFILE *f) { file = f; }
     33        StdioFILE(MFILE *f, const SString& p) { file = f; path = p; }
     34        static void setStdio();
     35        size_t Vread(void *ptr, size_t size, size_t nmemb) { return mfread(ptr, size, nmemb, file); }
     36        size_t Vwrite(const void *ptr, size_t size, size_t nmemb) { return mfwrite(ptr, size, nmemb, file); }
     37        int Veof() { return mfeof(file); }
     38        int Vputs(const char *s) { return mfputs(s, file); }
     39        char *Vgets(char *s, int size) { return mfgets(s, size, file); }
     40        int Vseek(long offset, int whence) { return mfseek(file, offset, whence); }
     41        long Vtell() { return mftell(file); }
     42        int Vflush() { return 0; /*NOT IMPLEMENTED!*/ }
     43        const char* VgetPath() { return path; }
    4444
    45 ~StdioFILE() {if (file) mfclose(file);}
     45        ~StdioFILE() { if (file) mfclose(file); }
    4646};
    4747#else
    48 class StdioFILE: public VirtFILE
     48class StdioFILE : public VirtFILE
    4949{
    50   protected:
    51 FILE *file;
    52 SString path;
    53   public:
    54 StdioFILE(FILE *f) {file=f;}
    55 StdioFILE(FILE *f,const SString& p) {file=f;path=p;}
    56 static void setStdio();
    57 size_t Vread(void *ptr, size_t size, size_t nmemb) {return fread(ptr,size,nmemb,file);}
    58 size_t Vwrite(const void *ptr, size_t size, size_t nmemb) {return fwrite(ptr,size,nmemb,file);}
    59 int Veof() {return feof(file);}
    60 int Vputc(int c) {return fputc(c,file);}
    61 int Vputs(const char *s) {return fputs(s,file);}
    62 int Vgetc() {return fgetc(file);}
    63 char *Vgets(char *s, int size) {return fgets(s,size,file);}
    64 int Vprintf(const char *format, va_list args) { return vfprintf(file,format,args); }
    65 int Vseek(long offset, int whence) {return fseek(file,offset,whence);}
    66 long Vtell() {return ftell(file);}
    67 void Vrewind() {rewind(file);}
    68 int Vflush() {return fflush(file);}
    69 const char* VgetPath() {return path;}
     50protected:
     51        FILE *file;
     52        SString path;
     53public:
     54        StdioFILE(FILE *f) { file = f; }
     55        StdioFILE(FILE *f, const SString& p) { file = f; path = p; }
     56        static void setStdio();
     57        size_t Vread(void *ptr, size_t size, size_t nmemb) { return fread(ptr, size, nmemb, file); }
     58        size_t Vwrite(const void *ptr, size_t size, size_t nmemb) { return fwrite(ptr, size, nmemb, file); }
     59        int Veof() { return feof(file); }
     60        int Vputc(int c) { return fputc(c, file); }
     61        int Vputs(const char *s) { return fputs(s, file); }
     62        int Vgetc() { return fgetc(file); }
     63        char *Vgets(char *s, int size) { return fgets(s, size, file); }
     64        int Vprintf(const char *format, va_list args) { return vfprintf(file, format, args); }
     65        int Vseek(long offset, int whence) { return fseek(file, offset, whence); }
     66        long Vtell() { return ftell(file); }
     67        void Vrewind() { rewind(file); }
     68        int Vflush() { return fflush(file); }
     69        const char* VgetPath() { return path; }
    7070
    71 ~StdioFILE() {if (file) fclose(file);}
     71        ~StdioFILE() { if (file) fclose(file); }
    7272};
    7373#endif
    7474
    75 class StdioDIR: public VirtDIR
     75
     76#ifdef _WIN32
     77#ifdef __BORLANDC__
     78 typedef wDIR DIRTYPE;
     79#else
     80 typedef WDIR DIRTYPE;
     81#endif
     82#else
     83 typedef DIR DIRTYPE;
     84#endif
     85
     86class StdioDIR : public VirtDIR
    7687{
    77 DIR *dir;
    78   public:
    79 StdioDIR(DIR* d):dir(d) {}
    80 ~StdioDIR() {if (dir) closedir(dir);}
    81 dirent* Vreaddir();
     88        DIRTYPE *dir;
     89#ifdef _WIN32
     90        dirent de; //only used to convert wide string names (wdirent) to utf8 (dirent)
     91#endif
     92public:
     93        StdioDIR(DIRTYPE *d) : dir(d) {}
     94        ~StdioDIR()
     95        {
     96#ifdef _WIN32
     97                if (dir) wclosedir(dir);
     98#else
     99                if (dir) closedir(dir);
     100#endif
     101        }
     102        dirent* Vreaddir();
    82103};
    83104
    84 class StdioFILEDontClose: public StdioFILE
     105class StdioFILEDontClose : public StdioFILE
    85106{
    86   public:
     107public:
    87108#ifdef USE_MFILE
    88 StdioFILEDontClose(MFILE *f):StdioFILE(f) {}
     109        StdioFILEDontClose(MFILE *f) : StdioFILE(f) {}
    89110#else
    90 StdioFILEDontClose(FILE *f):StdioFILE(f) {}
     111        StdioFILEDontClose(FILE *f) : StdioFILE(f) {}
    91112#endif
    92 ~StdioFILEDontClose() {file=0;}
     113        ~StdioFILEDontClose() { file = 0; }
    93114};
    94115
    95116#endif
     117
Note: See TracChangeset for help on using the changeset viewer.