source: cpp/common/nonstd_stdio.cpp @ 281

Last change on this file since 281 was 281, checked in by Maciej Komosinski, 9 years ago

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

  • Property svn:eol-style set to native
File size: 6.9 KB
RevLine 
[122]1// This file is a part of the Framsticks GDK.
[197]2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
[122]3// Refer to http://www.framsticks.com/ for further information.
4
[109]5#include "nonstd_stdio.h"
[201]6#include "nonstd.h"
[281]7#include "Convert.h" //utf8ToUtf16()
[247]8#include <common/stl-util.h>
[201]9
[109]10#if defined _WIN32 && !defined SHP
[281]11//<unistd.h> not needed for unlink()
12#include "Shlwapi.h" //PathIsRelative()
13#include <sys/stat.h> //_stat
[109]14#else
[281]15#include <unistd.h>
[109]16#endif
17
18bool fileExists(const char* path)
19{
[281]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;
[109]29}
30
[247]31bool directoryExists(const char* path)
32{
[281]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);
[247]40}
41
42bool makeDirectory(const char* path)
43{
44#ifdef _WIN32
[281]45        return _wmkdir(Convert::utf8ToUtf16(path).c_str()) == 0;
[247]46#else
[281]47        return mkdir(path,0777) == 0;
[247]48#endif
49}
50
51bool makeDirectories(const char* path)
52{
[281]53        if (directoryExists(path)) return true;
54        string parentdir = getFileDir(path);
55        if (!makeDirectories(parentdir.c_str())) return false;
56        return makeDirectory(path);
[247]57}
58
59int getFileSize(const char* path)
60{
[281]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;
[247]71}
72
73int getFileSize(MFILE *f)
74{
[281]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;
[247]80}
81
[109]82bool removeFile(const char* path)
83{
[281]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
[109]89}
90
[201]91bool isAbsolutePath(const char* fname)
92{
93        if (fname == NULL) return false; //SplitFileSystem never passes NULL but this function is public so we never know
[281]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
[201]96#else
97        return fname[0] == PATH_SEPARATOR_CHAR;
98#endif
99}
[109]100
101#if defined SHP && defined BADA_API_1
102
103MFILE *mfopen(const char *path, const char *mode)
104{
105        Osp::Io::File *f = new Osp::Io::File();
106        result r = f->Construct(path, mode);
107        if (IsFailed(r))
108        {
109                delete f;
110                f = NULL;
111        }
112        return f;
113}
114
115void mfclose(MFILE *f)
116{
117        delete f;
118}
119
120int mfread(void *ptr, int size, int count, MFILE *f)
121{
122        int bytes = size * count;
123        int przeczytane = f->Read(ptr, bytes);
124        return przeczytane != bytes ? przeczytane / size : count;
125}
126
127int mfwrite(const void *ptr, int size, int count, MFILE *f)
128{
129        result r = f->Write(ptr, size * count);
130        if (IsFailed(r))
131                return 0; //nie mozemy wykryc jesli udalo sie zapisac czêœæ
132        else
133                return count;
134}
135
136int mfputs(const char *txt, MFILE *f)
137{
138        int len = strlen(txt);
139        int res = mfwrite(txt, len, 1, f);
140        return res == 1 ? 1 : EOF;
141}
142
143char* mfgets(char *str, int num, MFILE *f)
144{
145        bool err = false;
146        int przeczytane = 0;
147        num--; //zeby zawsze zostalo miejsce na wpisanie koncz¹cego NULL
148        do
149        {
150                err = f->Read(str, 1) != 1;
151                if (!err)
152                {
153                        str++;
154                        przeczytane++;
155                }
156        } while (!err && przeczytane<num && *str != '\n');
157        if (*str == '\n' && przeczytane<num)
158                *(str + 1) = 0;
159        return przeczytane == 0 ? NULL : str;
160}
161
162int mfeof(MFILE *f)
163{
164        //brzydkie obejscie zeby w bada wykryc czy FILE jest w stanie EOF
165        static char buf[1];
166        int pos = f->Tell();
167        int przeczytane = f->Read(&buf, 1);
168        f->Seek(Osp::Io::FILESEEKPOSITION_BEGIN,pos);
169        return przeczytane == 1 ? 0 : 1;
170}
171
172int mfseek(MFILE *f, long position, int type)
173{
174        result r;
175        if (type == SEEK_SET)
176                r = f->Seek(Osp::Io::FILESEEKPOSITION_BEGIN, position);
177        else if (type == SEEK_CUR)
178                r = f->Seek(Osp::Io::FILESEEKPOSITION_CURRENT, position);
179        else if (type == SEEK_END)
180                r = f->Seek(Osp::Io::FILESEEKPOSITION_END, position);
181        else
182                return 1;
183        return IsFailed(r) ? 1 : 0;
184}
185
186long mftell(MFILE *f)
187{
188        return f->Tell();
189}
190
191#endif
192
193
194
195
196
197#ifdef __ANDROID__
[227]198#include "framsg.h"
[109]199#include "nonstd.h"
[227]200#include "nonstd_stl.h"
[109]201MFILE *mfopen(const char *path, const char *mode)
202{
[227]203        string respath=GET_APP_RESOURCES; //the macro can be char* or std::string, we don't know (nonstd.h, INITIAL_DIR_IS_RES, cwd.cpp) so we convert it to std::string
204        //printFM("Opening '%s', mode='%s'",path,mode);
205        //printFM("GET_APP_RESOURCES='%s'",respath.c_str());
206        NvFile *rfile=NULL; //can only read
[109]207        FILE *rwfile=NULL;
[227]208        if (strstr(path,respath.c_str())==path) //opening resource! so we use a dedicated way to read from assets
[109]209        {
[227]210                path+=respath.length(); //strip the prefix, we need a relative path in assets
211                if (strstr(mode,"w"))
212                        printFM("Warning: attempt to open a read-only resource '%s' in writable mode '%s'",path,mode);
213                rfile=NvFOpen(path); //"mode" not supported! can only read
214                //printFM("Opened RES file as %p",rfile);
[109]215                if (rfile==NULL) return NULL;
[227]216        } else //a "normal" access (HOME)
[109]217        {
218                rwfile=fopen(path,mode);
[227]219                //printFM("Opened HOME file as %p",rwfile);
[109]220                if (rwfile==NULL) return NULL;
221        }
222        MFILE *mfile=new MFILE;
223        mfile->rfile=rfile;
224        mfile->rwfile=rwfile;
225        return mfile;
226}
227
228void mfclose(MFILE *f)
229{
230        if (f->rfile)
231                NvFClose(f->rfile);
232        else
233                fclose(f->rwfile);
234
235        delete f;
236}
237
238int mfread(void *ptr, int size, int count, MFILE *f)
239{
240        if (f->rfile)
[227]241                return NvFRead(ptr, size, count, f->rfile); //nvidia introduced my corrections in SDK v10.14, so a fix is no longer needed here
[109]242        else
243                return fread(ptr, size, count, f->rwfile);
244}
245
246int mfwrite(const void *ptr, int size, int count, MFILE *f)
247{
248        if (f->rfile)
[227]249                return 0; //write not supported in assets using nvidia functions
[109]250        else
251                return fwrite(ptr, size, count, f->rwfile);
252}
253
254int mfputs(const char *txt, MFILE *f)
255{
256        int len = strlen(txt);
257        int res = mfwrite(txt, len, 1, f);
258        return res == 1 ? 1 : EOF;
259}
260
261char* mfgets(char *str, int num, MFILE *f)
262{
263        if (f->rfile)
[227]264        {
265                char *ret=NvFGets(str, num, f->rfile);
266                //fixing nvidia inconsistency... their function never returns NULL (fix submitted)
267                if (ret!=NULL && *ret==0 && num>0) //nothing has been read, must have been eof
268                        return NULL;
269                return ret;
270        }
[109]271        else
272                return fgets(str,num,f->rwfile);
273}
274
275int mfeof(MFILE *f)
276{
277        if (f->rfile)
278                return NvFEOF(f->rfile);
279        else
280                return feof(f->rwfile);
281}
282
283int mfseek(MFILE *f, long position, int type)
284{
285        if (f->rfile)
[227]286                return NvFSeek(f->rfile, position, type); //nvidia introduced my corrections in SDK v10.14, so a fix is no longer needed here
[109]287        else
288                return fseek(f->rwfile, position, type);
289}
290
291long mftell(MFILE *f)
292{
293        if (f->rfile)
294                return NvFTell(f->rfile);
295        else
296                return ftell(f->rwfile);
297}
298#endif
Note: See TracBrowser for help on using the repository browser.