source: cpp/common/nonstd_stdio.cpp @ 282

Last change on this file since 282 was 281, checked in by Maciej Komosinski, 10 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
Line 
1// This file is a part of the Framsticks GDK.
2// Copyright (C) 1999-2014  Maciej Komosinski and Szymon Ulatowski.  See LICENSE.txt for details.
3// Refer to http://www.framsticks.com/ for further information.
4
5#include "nonstd_stdio.h"
6#include "nonstd.h"
7#include "Convert.h" //utf8ToUtf16()
8#include <common/stl-util.h>
9
10#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>
16#endif
17
18bool fileExists(const char* path)
19{
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;
29}
30
31bool directoryExists(const char* path)
32{
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);
40}
41
42bool makeDirectory(const char* path)
43{
44#ifdef _WIN32
45        return _wmkdir(Convert::utf8ToUtf16(path).c_str()) == 0;
46#else
47        return mkdir(path,0777) == 0;
48#endif
49}
50
51bool makeDirectories(const char* path)
52{
53        if (directoryExists(path)) return true;
54        string parentdir = getFileDir(path);
55        if (!makeDirectories(parentdir.c_str())) return false;
56        return makeDirectory(path);
57}
58
59int getFileSize(const char* path)
60{
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;
71}
72
73int getFileSize(MFILE *f)
74{
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;
80}
81
82bool removeFile(const char* path)
83{
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
89}
90
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
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
96#else
97        return fname[0] == PATH_SEPARATOR_CHAR;
98#endif
99}
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__
198#include "framsg.h"
199#include "nonstd.h"
200#include "nonstd_stl.h"
201MFILE *mfopen(const char *path, const char *mode)
202{
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
207        FILE *rwfile=NULL;
208        if (strstr(path,respath.c_str())==path) //opening resource! so we use a dedicated way to read from assets
209        {
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);
215                if (rfile==NULL) return NULL;
216        } else //a "normal" access (HOME)
217        {
218                rwfile=fopen(path,mode);
219                //printFM("Opened HOME file as %p",rwfile);
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)
241                return NvFRead(ptr, size, count, f->rfile); //nvidia introduced my corrections in SDK v10.14, so a fix is no longer needed here
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)
249                return 0; //write not supported in assets using nvidia functions
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)
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        }
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)
286                return NvFSeek(f->rfile, position, type); //nvidia introduced my corrections in SDK v10.14, so a fix is no longer needed here
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.