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

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

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

  • Property svn:eol-style set to native
File size: 7.3 KB
RevLine 
[286]1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
[1328]2// Copyright (C) 1999-2024  Maciej Komosinski and Szymon Ulatowski.
[286]3// See LICENSE.txt for details.
[109]4
5#include "virtfile.h"
[841]6#include <common/util-string.h>
[109]7
[298]8VirtFILE *VirtFILE::Vstdin = NULL;
9VirtFILE *VirtFILE::Vstdout = NULL;
10VirtFILE *VirtFILE::Vstderr = NULL;
[109]11
[298]12VirtFileSystem *VirtFILE::vfs = NULL;
[109]13
[302]14//#define DEBUG_VIRTFILE
[301]15
[302]16VirtFILE *Vfopen(const char* path, const char* mode)
[109]17{
[302]18#ifdef DEBUG_VIRTFILE
19        printf("VirtFILE::Vfopen %s %s (vfs=%p)\n",path,mode,VirtFILE::vfs);
[301]20#endif
[302]21        return VirtFILE::vfs ? VirtFILE::vfs->Vfopen(path, mode) : NULL;
[109]22}
23
24VirtDIR *Vopendir(const char* path)
25{
[302]26#ifdef DEBUG_VIRTFILE
27        printf("VirtFILE::Vfopendir %s (vfs=%p)\n",path,VirtFILE::vfs);
[301]28#endif
[302]29        return VirtFILE::vfs ? VirtFILE::vfs->Vopendir(path) : NULL;
[109]30}
31
[295]32bool Vfexists(const char* path)
[109]33{
[302]34        return VirtFILE::vfs ? VirtFILE::vfs->Vfexists(path) : false;
[109]35}
36
[302]37bool Vdirexists(const char* path, bool is_writable)
[295]38{
[302]39        return VirtFILE::vfs ? VirtFILE::vfs->Vdirexists(path, is_writable) : false;
[295]40}
41
42bool Vmkdir(const char* path)
43{
[302]44        return VirtFILE::vfs ? VirtFILE::vfs->Vmkdir(path) : false;
[295]45}
46
47bool Vmkdirs(const char* path)
48{
[302]49        return VirtFILE::vfs ? VirtFILE::vfs->Vmkdirs(path) : false;
[295]50}
51
[1328]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}
[109]66VirtFILE::~VirtFILE()
67{}
68
[301]69void VirtFILE::selectFileSystem(VirtFileSystem *s)
70{
[302]71        vfs = s;
72#ifdef DEBUG_VIRTFILE
73        ::printf("VirtFILE::selectFileSystem: %p := %p\n",vfs,s);
[301]74#endif
75}
[109]76
[206]77int VirtFILE::Vprintf(const char *format, va_list args)
78{
[302]79        string s = ssprintf_va(format, args);
[888]80        return (int)Vwrite(s.c_str(), 1, s.size());
[206]81}
82
[109]83int VirtFILE::printf(const char *format, ...)
84{
[302]85        int ret; va_list argptr;
86        va_start(argptr, format);
87        ret = Vprintf(format, argptr);
88        va_end(argptr);
89        return ret;
[109]90}
91
[247]92int VirtFILE::getSize()
93{
[888]94        auto saved_pos = Vtell();
[302]95        Vseek(0, SEEK_END);
[888]96        int size = (int)Vtell();
[302]97        Vseek(saved_pos, SEEK_SET);
98        return size;
[247]99}
100
[302]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; }
[109]107//////////////////////////////////////////////////////////////////////////
108
[298]109// base class only returns NULL/false/not supported - implementations perform the actual work
[302]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; }
[1328]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; }
[109]118
119//////////////////////////////////////////////////////////////////////////
120
121
122
[888]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); }
[123]125
[131]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
[225]128#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
[302]129#pragma push_macro("feof")
130#undef feof
[123]131#endif
[131]132#if defined __BORLANDC__ //does not support #pragma push_macro/pop_macro
[302]133#undef feof
[131]134#endif
[123]135
[302]136int feof(VirtFILE* f) { return f->Veof(); }
[123]137
138//...and then restore the original macro:
[225]139#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
[302]140#pragma pop_macro("feof")
[131]141#endif
[225]142#if defined __BORLANDC__
[302]143#define feof(__f)     ((__f)->flags & _F_EOF)
[109]144#endif
145
[123]146
[302]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); }
[888]151int ftell(VirtFILE* f) { return (int)f->Vtell(); }
[302]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{
[109]157        int ret; va_list argptr;
[302]158        va_start(argptr, format);
159        ret = f->Vprintf(format, argptr);
[109]160        va_end(argptr);
161        return ret;
[302]162}
163int fclose(VirtFILE* f) { delete f; return 0; }
[109]164
[302]165int closedir(VirtDIR* d) { delete d; return 0; }
166dirent* readdir(VirtDIR* d) { return d->Vreaddir(); }
[123]167
[295]168/////////
169
170bool VirtFileSystem::Vmkdirs(const char* path)
171{
[302]172        if (Vdirexists(path, true)) return true;
173        string parentdir = getFileDir(path);
174        if (!Vmkdirs(parentdir.c_str())) return false;
175        return Vmkdir(path);
[295]176}
177
178//////////
179
[301]180
181ChainFileSystem::ChainFileSystem(VirtFileSystem *_chain)
[295]182{
[302]183        chain = _chain;
184#ifdef DEBUG_VIRTFILE
185        printf("ChainFileSystem constructor: %p := %p\n",chain,_chain);
[301]186#endif
187}
188
189
190VirtFILE *ChainFileSystem::Vfopen(const char* path, const char* mode)
191{
[302]192#ifdef DEBUG_VIRTFILE
193        printf("ChainFileSystem::Vfopen %s %s (chain=%p)\n",path,mode,chain);
[301]194#endif
[295]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{
[302]205#ifdef DEBUG_VIRTFILE
206        printf("ChainFileSystem::Vfopendir %s (chain=%p)\n",path,chain);
[301]207#endif
[410]208        if (chain==NULL) return internalopendir(path);
209        return new Dir(string(path),this,chain);
[295]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
[302]222bool ChainFileSystem::Vdirexists(const char* path, bool is_writable)
[295]223{
[302]224        return (chain != NULL) ? chain->Vdirexists(path, is_writable) : false;
[295]225}
[410]226
[1328]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
[410]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.