source: cpp/common/virtfile/virtfile.cpp @ 1328

Last change on this file since 1328 was 1328, checked in by Maciej Komosinski, 2 days ago

Added Vstat(), Vdelete(), Vsettime() to VirtFILE

  • Property svn:eol-style set to native
File size: 7.3 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2024  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#include "virtfile.h"
6#include <common/util-string.h>
7
8VirtFILE *VirtFILE::Vstdin = NULL;
9VirtFILE *VirtFILE::Vstdout = NULL;
10VirtFILE *VirtFILE::Vstderr = NULL;
11
12VirtFileSystem *VirtFILE::vfs = NULL;
13
14//#define DEBUG_VIRTFILE
15
16VirtFILE *Vfopen(const char* path, const char* mode)
17{
18#ifdef DEBUG_VIRTFILE
19        printf("VirtFILE::Vfopen %s %s (vfs=%p)\n",path,mode,VirtFILE::vfs);
20#endif
21        return VirtFILE::vfs ? VirtFILE::vfs->Vfopen(path, mode) : NULL;
22}
23
24VirtDIR *Vopendir(const char* path)
25{
26#ifdef DEBUG_VIRTFILE
27        printf("VirtFILE::Vfopendir %s (vfs=%p)\n",path,VirtFILE::vfs);
28#endif
29        return VirtFILE::vfs ? VirtFILE::vfs->Vopendir(path) : NULL;
30}
31
32bool Vfexists(const char* path)
33{
34        return VirtFILE::vfs ? VirtFILE::vfs->Vfexists(path) : false;
35}
36
37bool Vdirexists(const char* path, bool is_writable)
38{
39        return VirtFILE::vfs ? VirtFILE::vfs->Vdirexists(path, is_writable) : false;
40}
41
42bool Vmkdir(const char* path)
43{
44        return VirtFILE::vfs ? VirtFILE::vfs->Vmkdir(path) : false;
45}
46
47bool Vmkdirs(const char* path)
48{
49        return VirtFILE::vfs ? VirtFILE::vfs->Vmkdirs(path) : false;
50}
51
52bool Vdelete(const char* path)
53{
54        return VirtFILE::vfs ? VirtFILE::vfs->Vdelete(path) : false;
55}
56
57bool Vstat(const char* path, struct VirtFileSystem::Stat *stat)
58{
59        return VirtFILE::vfs ? VirtFILE::vfs->Vstat(path, stat) : false;
60}
61
62bool Vsettime(const char* path, double timestamp)
63{
64        return VirtFILE::vfs ? VirtFILE::vfs->Vsettime(path, timestamp) : false;
65}
66VirtFILE::~VirtFILE()
67{}
68
69void VirtFILE::selectFileSystem(VirtFileSystem *s)
70{
71        vfs = s;
72#ifdef DEBUG_VIRTFILE
73        ::printf("VirtFILE::selectFileSystem: %p := %p\n",vfs,s);
74#endif
75}
76
77int VirtFILE::Vprintf(const char *format, va_list args)
78{
79        string s = ssprintf_va(format, args);
80        return (int)Vwrite(s.c_str(), 1, s.size());
81}
82
83int VirtFILE::printf(const char *format, ...)
84{
85        int ret; va_list argptr;
86        va_start(argptr, format);
87        ret = Vprintf(format, argptr);
88        va_end(argptr);
89        return ret;
90}
91
92int VirtFILE::getSize()
93{
94        auto saved_pos = Vtell();
95        Vseek(0, SEEK_END);
96        int size = (int)Vtell();
97        Vseek(saved_pos, SEEK_SET);
98        return size;
99}
100
101void VirtFILE::setVstdin(VirtFILE *f) { Vstdin = f; }
102void VirtFILE::setVstdout(VirtFILE *f) { Vstdout = f; }
103void VirtFILE::setVstderr(VirtFILE *f) { Vstderr = f; }
104VirtFILE* VirtFILE::getVstdin() { return Vstdin; }
105VirtFILE* VirtFILE::getVstdout() { return Vstdout; }
106VirtFILE* VirtFILE::getVstderr() { return Vstderr; }
107//////////////////////////////////////////////////////////////////////////
108
109// base class only returns NULL/false/not supported - implementations perform the actual work
110VirtFILE* VirtFileSystem::Vfopen(const char* path, const char* mode) { return NULL; }
111bool VirtFileSystem::Vfexists(const char* path) { return false; }
112VirtDIR* VirtFileSystem::Vopendir(const char* path) { return NULL; }
113bool VirtFileSystem::Vmkdir(const char* path) { return false; }
114bool VirtFileSystem::Vdirexists(const char* path, bool is_writable) { return false; }
115bool VirtFileSystem::Vdelete(const char* path) { return false; }
116bool VirtFileSystem::Vstat(const char* path, Stat* stat) { return false; }
117bool VirtFileSystem::Vsettime(const char* path, double timestamp) { return false; }
118
119//////////////////////////////////////////////////////////////////////////
120
121
122
123size_t fread(void *ptr, size_t size, size_t nmemb, VirtFILE* f) { return f->Vread(ptr, size, nmemb); }
124size_t fwrite(const void *ptr, size_t size, size_t nmemb, VirtFILE* f) { return f->Vwrite(ptr, size, nmemb); }
125
126
127//since we want our own feof(VirtFILE*) function and some systems unfortunately define feof as a macro, we need to #undef it. Same as in virtfile.h
128#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
129#pragma push_macro("feof")
130#undef feof
131#endif
132#if defined __BORLANDC__ //does not support #pragma push_macro/pop_macro
133#undef feof
134#endif
135
136int feof(VirtFILE* f) { return f->Veof(); }
137
138//...and then restore the original macro:
139#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
140#pragma pop_macro("feof")
141#endif
142#if defined __BORLANDC__
143#define feof(__f)     ((__f)->flags & _F_EOF)
144#endif
145
146
147int fputc(int c, VirtFILE* f) { return f->Vputc(c); }
148int fputs(const char *s, VirtFILE* f) { return f->Vputs(s); }
149int fgetc(VirtFILE* f) { return f->Vgetc(); }
150int fseek(VirtFILE* f, long offset, int whence) { return f->Vseek(offset, whence); }
151int ftell(VirtFILE* f) { return (int)f->Vtell(); }
152void rewind(VirtFILE* f) { f->Vrewind(); }
153int fflush(VirtFILE* f) { return f->Vflush(); }
154char *fgets(char *s, int size, VirtFILE* f) { return f->Vgets(s, size); }
155int fprintf(VirtFILE* f, const char *format, ...)
156{
157        int ret; va_list argptr;
158        va_start(argptr, format);
159        ret = f->Vprintf(format, argptr);
160        va_end(argptr);
161        return ret;
162}
163int fclose(VirtFILE* f) { delete f; return 0; }
164
165int closedir(VirtDIR* d) { delete d; return 0; }
166dirent* readdir(VirtDIR* d) { return d->Vreaddir(); }
167
168/////////
169
170bool VirtFileSystem::Vmkdirs(const char* path)
171{
172        if (Vdirexists(path, true)) return true;
173        string parentdir = getFileDir(path);
174        if (!Vmkdirs(parentdir.c_str())) return false;
175        return Vmkdir(path);
176}
177
178//////////
179
180
181ChainFileSystem::ChainFileSystem(VirtFileSystem *_chain)
182{
183        chain = _chain;
184#ifdef DEBUG_VIRTFILE
185        printf("ChainFileSystem constructor: %p := %p\n",chain,_chain);
186#endif
187}
188
189
190VirtFILE *ChainFileSystem::Vfopen(const char* path, const char* mode)
191{
192#ifdef DEBUG_VIRTFILE
193        printf("ChainFileSystem::Vfopen %s %s (chain=%p)\n",path,mode,chain);
194#endif
195        return (chain != NULL) ? chain->Vfopen(path, mode) : NULL;
196}
197
198bool ChainFileSystem::Vfexists(const char* path)
199{
200        return (chain != NULL) ? chain->Vfexists(path) : false;
201}
202
203VirtDIR *ChainFileSystem::Vopendir(const char* path)
204{
205#ifdef DEBUG_VIRTFILE
206        printf("ChainFileSystem::Vfopendir %s (chain=%p)\n",path,chain);
207#endif
208        if (chain==NULL) return internalopendir(path);
209        return new Dir(string(path),this,chain);
210}
211
212bool ChainFileSystem::Vmkdir(const char* path)
213{
214        return (chain != NULL) ? chain->Vmkdir(path) : false;
215}
216
217bool ChainFileSystem::Vmkdirs(const char* path)
218{
219        return (chain != NULL) ? chain->Vmkdirs(path) : false;
220}
221
222bool ChainFileSystem::Vdirexists(const char* path, bool is_writable)
223{
224        return (chain != NULL) ? chain->Vdirexists(path, is_writable) : false;
225}
226
227bool ChainFileSystem::Vdelete(const char* path)
228{
229        return (chain != NULL) ? chain->Vdelete(path) : false;
230}
231
232bool ChainFileSystem::Vstat(const char* path, Stat* stat)
233{
234        return (chain != NULL) ? chain->Vstat(path, stat) : false;
235}
236
237bool ChainFileSystem::Vsettime(const char* path, double timestamp)
238{
239        return (chain != NULL) ? chain->Vsettime(path, timestamp) : false;
240}
241
242ChainFileSystem::Dir::~Dir()
243{
244if (dir) delete dir;
245}
246
247dirent* ChainFileSystem::Dir::Vreaddir()
248{
249dirent *de;
250  retry:
251if (!dir)
252        {
253        if (first)
254                {
255                dir=first->internalopendir(path.c_str());
256                first=NULL;
257                }
258        else if (second)
259                {
260                dir=second->Vopendir(path.c_str());
261                second=NULL;
262                }
263        else
264                return NULL;
265        }
266de=dir ? dir->Vreaddir() : NULL;
267if (de==NULL)
268        {if (dir) delete dir; dir=NULL; goto retry;}
269
270// no need to check for duplicates if no names are saved and scanning the last location (most common case)
271if (! (duplicates.empty() && (first==NULL) && (second==NULL)) )
272{
273string s(de->d_name);
274if (duplicates.find(s)==duplicates.end())
275        duplicates.insert(s);
276else
277        goto retry;
278}
279
280return de;
281}
Note: See TracBrowser for help on using the repository browser.