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> |
---|
13 | using 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 | |
---|
25 | class DLLEXP VirtFileSystem; |
---|
26 | |
---|
27 | class DLLEXP VirtFILE |
---|
28 | { |
---|
29 | protected: |
---|
30 | string path; |
---|
31 | public: |
---|
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 */ |
---|
61 | class DLLEXP DelegatedFILE : public VirtFILE |
---|
62 | { |
---|
63 | VirtFILE *delegate; |
---|
64 | public: |
---|
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 | |
---|
84 | class DLLEXP VirtDIR |
---|
85 | { |
---|
86 | public: |
---|
87 | virtual ~VirtDIR() {} |
---|
88 | virtual dirent* Vreaddir() { return NULL; } |
---|
89 | }; |
---|
90 | |
---|
91 | class DLLEXP VirtFileSystem |
---|
92 | { |
---|
93 | public: |
---|
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 |
---|
103 | class DLLEXP ChainFileSystem : public VirtFileSystem |
---|
104 | { |
---|
105 | public: |
---|
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 | |
---|
131 | DLLEXP VirtFILE *Vfopen(const char* path, const char*mode); |
---|
132 | DLLEXP VirtDIR *Vopendir(const char* path); |
---|
133 | DLLEXP bool Vfexists(const char* path); |
---|
134 | DLLEXP bool Vmkdir(const char* path); |
---|
135 | DLLEXP bool Vmkdirs(const char* path); |
---|
136 | DLLEXP bool Vdirexists(const char* path, bool is_writable); |
---|
137 | |
---|
138 | DLLEXP int fread(void *ptr, size_t size, size_t nmemb, VirtFILE* f); |
---|
139 | DLLEXP int fwrite(const void *ptr, size_t size, size_t nmemb, VirtFILE* f); |
---|
140 | |
---|
141 | |
---|
142 | //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 |
---|
143 | #if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__ |
---|
144 | #pragma push_macro("feof") |
---|
145 | #undef feof |
---|
146 | #endif |
---|
147 | #if defined __BORLANDC__ //does not support #pragma push_macro/pop_macro |
---|
148 | #undef feof |
---|
149 | #endif |
---|
150 | |
---|
151 | DLLEXP int feof(VirtFILE* f);// {return f->Veof();} |
---|
152 | |
---|
153 | //...and then restore the original macro: |
---|
154 | #if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__ |
---|
155 | #pragma pop_macro("feof") |
---|
156 | #endif |
---|
157 | #if defined __BORLANDC__ |
---|
158 | #define feof(__f) ((__f)->flags & _F_EOF) |
---|
159 | #endif |
---|
160 | |
---|
161 | |
---|
162 | DLLEXP int fputc(int c, VirtFILE* f); |
---|
163 | DLLEXP int fputs(const char *s, VirtFILE* f); |
---|
164 | DLLEXP int fgetc(VirtFILE* f); |
---|
165 | DLLEXP int fseek(VirtFILE* f, long offset, int whence); |
---|
166 | DLLEXP int ftell(VirtFILE* f); |
---|
167 | DLLEXP void rewind(VirtFILE* f); |
---|
168 | DLLEXP int fflush(VirtFILE* f); |
---|
169 | DLLEXP char *fgets(char *s, int size, VirtFILE* f); |
---|
170 | DLLEXP int fprintf(VirtFILE* f, const char *format, ...); |
---|
171 | DLLEXP int fclose(VirtFILE* f); |
---|
172 | |
---|
173 | DLLEXP dirent* readdir(VirtDIR* d); |
---|
174 | DLLEXP int closedir(VirtDIR* d); |
---|
175 | |
---|
176 | #endif |
---|
177 | |
---|