source: cpp/common/virtfile/virtfile.h @ 584

Last change on this file since 584 was 523, checked in by Maciej Komosinski, 8 years ago

No more overloading of fopen/fclose/... functions for the VirtFILE class. #define VIRTFILE_OVERLOADING to enable overloading only when necessary.

  • Property svn:eol-style set to native
File size: 6.0 KB
Line 
1// This file is a part of Framsticks SDK.  http://www.framsticks.com/
2// Copyright (C) 1999-2015  Maciej Komosinski and Szymon Ulatowski.
3// See LICENSE.txt for details.
4
5#ifndef _VIRTFILE_H_
6#define _VIRTFILE_H_
7
8#include <stdio.h>
9#include <stdarg.h>
10#include <common/nonstd_dir.h>
11#include <string>
12#include <set>
13using std::string;
14
15#ifdef DLLEXPORTACTIVE  //defined in the project that makes the DLL
16#define DLLEXP __declspec(dllexport)
17#else
18#ifdef __BORLANDC__ //assuming that all executables produced by borland use the DLL
19#define DLLEXP __declspec(dllimport) //without dllimport, fields in objects would have separate instances in DLL and in EXE
20#else
21#define DLLEXP
22#endif
23#endif
24
25class DLLEXP VirtFileSystem;
26
27class DLLEXP VirtFILE
28{
29protected:
30        string path;
31public:
32        virtual size_t Vread(void *ptr, size_t size, size_t nmemb) = 0;
33        virtual size_t Vwrite(const void *ptr, size_t size, size_t nmemb) = 0;
34        virtual int Veof() = 0;
35        virtual int Vputc(int c) { unsigned char data = (unsigned char)c; return (Vwrite(&data, 1, 1) == 1) ? data : EOF; }
36        virtual int Vputs(const char *s) = 0;
37        virtual int Vgetc() { unsigned char data; if (Vread(&data, 1, 1) == 1) return data; else return EOF; }
38        virtual int Vseek(long offset, int whence) = 0;
39        virtual long Vtell() = 0;
40        virtual void Vrewind() { Vseek(0, SEEK_SET); }
41        virtual int Vflush() = 0;
42        virtual char *Vgets(char *s, int size) = 0;
43        virtual int Vprintf(const char *format, va_list args);
44        int printf(const char *format, ...);
45        virtual const char *VgetPath() { return path.c_str(); }
46        virtual int getSize();
47        VirtFILE(const char* _path) :path(_path) {}
48        virtual ~VirtFILE();
49        static VirtFILE *Vstdin, *Vstdout, *Vstderr;
50        static void setVstdin(VirtFILE *);
51        static void setVstdout(VirtFILE *);
52        static void setVstderr(VirtFILE *);
53        static VirtFILE* getVstdin();
54        static VirtFILE* getVstdout();
55        static VirtFILE* getVstderr();
56        static VirtFileSystem *vfs;
57        static void selectFileSystem(VirtFileSystem *s);
58};
59
60/** can be used directly or as a base class for implementations delegating VirtFILE calls to another VirtFILE object */
61class DLLEXP DelegatedFILE : public VirtFILE
62{
63        VirtFILE *delegate;
64public:
65        size_t Vread(void *ptr, size_t size, size_t nmemb) { return delegate->Vread(ptr, size, nmemb); }
66        size_t Vwrite(const void *ptr, size_t size, size_t nmemb) { return delegate->Vwrite(ptr, size, nmemb); }
67        int Veof() { return delegate->Veof(); }
68        int Vputc(int c) { return delegate->Vputc(c); }
69        int Vputs(const char *s) { return delegate->Vputs(s); }
70        int Vgetc() { return delegate->Vgetc(); }
71        int Vseek(long offset, int whence) { return delegate->Vseek(offset, whence); }
72        long Vtell() { return delegate->Vtell(); }
73        void Vrewind() { delegate->Vrewind(); }
74        int Vflush() { return delegate->Vflush(); }
75        char *Vgets(char *s, int size) { return delegate->Vgets(s, size); }
76        int Vprintf(const char *format, va_list args) { return delegate->Vprintf(format, args); }
77        int getSize() { return delegate->getSize(); }
78        // not overriden: VgetPath()
79
80        DelegatedFILE(const char* _path, VirtFILE *_delegate) :VirtFILE(_path), delegate(_delegate) {}
81        virtual ~DelegatedFILE() { if (delegate) delete delegate; delegate = NULL; }
82};
83
84class DLLEXP VirtDIR
85{
86public:
87        virtual ~VirtDIR() {}
88        virtual dirent* Vreaddir() { return NULL; }
89};
90
91class DLLEXP VirtFileSystem
92{
93public:
94        virtual VirtFILE *Vfopen(const char* path, const char*mode);
95        virtual bool Vfexists(const char* path);
96        virtual VirtDIR *Vopendir(const char* path);
97        virtual bool Vmkdir(const char* path);
98        virtual bool Vmkdirs(const char* path);
99        virtual bool Vdirexists(const char* path, bool is_writable);
100};
101
102/// base class for chained filesystems - redirect unimplemented calls -> chain
103class DLLEXP ChainFileSystem : public VirtFileSystem
104{
105public:
106        VirtFileSystem *chain;
107        ChainFileSystem(VirtFileSystem *_chain = NULL);
108        VirtFILE *Vfopen(const char* path, const char*mode);
109        bool Vfexists(const char* path);
110        VirtDIR *Vopendir(const char* path);
111        virtual VirtDIR *internalopendir(const char* path) {return NULL;}
112        bool Vmkdir(const char* path);
113        bool Vmkdirs(const char* path);
114        bool Vdirexists(const char* path, bool is_writable);
115
116        class Dir: public VirtDIR
117        {
118        ChainFileSystem *first;
119        VirtFileSystem *second;
120        string path;
121        std::set<string> duplicates;
122        VirtDIR *dir;
123          public:
124        Dir(string _path,ChainFileSystem *_first,VirtFileSystem *_second):first(_first),second(_second),path(_path),dir(NULL) {}
125        ~Dir();
126        dirent* Vreaddir();
127        };
128};
129
130
131DLLEXP VirtFILE *Vfopen(const char* path, const char*mode);
132DLLEXP VirtDIR *Vopendir(const char* path);
133DLLEXP bool Vfexists(const char* path);
134DLLEXP bool Vmkdir(const char* path);
135DLLEXP bool Vmkdirs(const char* path);
136DLLEXP bool Vdirexists(const char* path, bool is_writable);
137
138#ifdef VIRTFILE_OVERLOADING
139//may be needed for redefine... or if someone simply prefers overloading ;-)
140
141DLLEXP int fread(void *ptr, size_t size, size_t nmemb, VirtFILE* f);
142DLLEXP int fwrite(const void *ptr, size_t size, size_t nmemb, VirtFILE* f);
143
144//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.cpp
145#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
146#pragma push_macro("feof")
147#undef feof
148#endif
149#if defined __BORLANDC__ //does not support #pragma push_macro/pop_macro
150#undef feof
151#endif
152
153DLLEXP int feof(VirtFILE* f);// {return f->Veof();}
154
155//...and then restore the original macro:
156#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
157#pragma pop_macro("feof")
158#endif
159#if defined __BORLANDC__
160#define feof(__f)     ((__f)->flags & _F_EOF)
161#endif
162
163
164DLLEXP int fputc(int c, VirtFILE* f);
165DLLEXP int fputs(const char *s, VirtFILE* f);
166DLLEXP int fgetc(VirtFILE* f);
167DLLEXP int fseek(VirtFILE* f, long offset, int whence);
168DLLEXP int ftell(VirtFILE* f);
169DLLEXP void rewind(VirtFILE* f);
170DLLEXP int fflush(VirtFILE* f);
171DLLEXP char *fgets(char *s, int size, VirtFILE* f);
172DLLEXP int fprintf(VirtFILE* f, const char *format, ...);
173DLLEXP int fclose(VirtFILE* f);
174
175DLLEXP dirent* readdir(VirtDIR* d);
176DLLEXP int closedir(VirtDIR* d);
177
178#endif //VIRTFILE_OVERLOADING
179
180#endif
Note: See TracBrowser for help on using the repository browser.