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

Last change on this file since 523 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
RevLine 
[286]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.
[109]4
5#ifndef _VIRTFILE_H_
6#define _VIRTFILE_H_
7
8#include <stdio.h>
9#include <stdarg.h>
10#include <common/nonstd_dir.h>
[295]11#include <string>
[410]12#include <set>
[295]13using std::string;
[109]14
[301]15#ifdef DLLEXPORTACTIVE  //defined in the project that makes the DLL
[109]16#define DLLEXP __declspec(dllexport)
17#else
[301]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
[109]21#define DLLEXP
22#endif
[301]23#endif
[109]24
25class DLLEXP VirtFileSystem;
26
27class DLLEXP VirtFILE
28{
[302]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);
[109]58};
59
[295]60/** can be used directly or as a base class for implementations delegating VirtFILE calls to another VirtFILE object */
[302]61class DLLEXP DelegatedFILE : public VirtFILE
[295]62{
[302]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()
[295]79
[302]80        DelegatedFILE(const char* _path, VirtFILE *_delegate) :VirtFILE(_path), delegate(_delegate) {}
81        virtual ~DelegatedFILE() { if (delegate) delete delegate; delegate = NULL; }
[295]82};
83
[109]84class DLLEXP VirtDIR
85{
[302]86public:
87        virtual ~VirtDIR() {}
[427]88        virtual dirent* Vreaddir() { return NULL; }
[109]89};
90
91class DLLEXP VirtFileSystem
92{
93public:
[302]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);
[109]100};
101
[295]102/// base class for chained filesystems - redirect unimplemented calls -> chain
103class DLLEXP ChainFileSystem : public VirtFileSystem
104{
105public:
106        VirtFileSystem *chain;
[301]107        ChainFileSystem(VirtFileSystem *_chain = NULL);
[295]108        VirtFILE *Vfopen(const char* path, const char*mode);
109        bool Vfexists(const char* path);
110        VirtDIR *Vopendir(const char* path);
[410]111        virtual VirtDIR *internalopendir(const char* path) {return NULL;}
[295]112        bool Vmkdir(const char* path);
113        bool Vmkdirs(const char* path);
[302]114        bool Vdirexists(const char* path, bool is_writable);
[410]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        };
[295]128};
129
130
[302]131DLLEXP VirtFILE *Vfopen(const char* path, const char*mode);
[109]132DLLEXP VirtDIR *Vopendir(const char* path);
[295]133DLLEXP bool Vfexists(const char* path);
134DLLEXP bool Vmkdir(const char* path);
135DLLEXP bool Vmkdirs(const char* path);
[302]136DLLEXP bool Vdirexists(const char* path, bool is_writable);
[109]137
[523]138#ifdef VIRTFILE_OVERLOADING
139//may be needed for redefine... or if someone simply prefers overloading ;-)
140
[109]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);
[123]143
[131]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
[225]145#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
[302]146#pragma push_macro("feof")
147#undef feof
[123]148#endif
[131]149#if defined __BORLANDC__ //does not support #pragma push_macro/pop_macro
[302]150#undef feof
[131]151#endif
[302]152
[123]153DLLEXP int feof(VirtFILE* f);// {return f->Veof();}
154
155//...and then restore the original macro:
[225]156#if defined _MSC_VER || defined __CYGWIN__ || defined SHP || defined __ANDROID__
[302]157#pragma pop_macro("feof")
[131]158#endif
[225]159#if defined __BORLANDC__
[302]160#define feof(__f)     ((__f)->flags & _F_EOF)
[109]161#endif
162
[123]163
[302]164DLLEXP int fputc(int c, VirtFILE* f);
165DLLEXP int fputs(const char *s, VirtFILE* f);
[109]166DLLEXP int fgetc(VirtFILE* f);
[302]167DLLEXP int fseek(VirtFILE* f, long offset, int whence);
[109]168DLLEXP int ftell(VirtFILE* f);
169DLLEXP void rewind(VirtFILE* f);
170DLLEXP int fflush(VirtFILE* f);
171DLLEXP char *fgets(char *s, int size, VirtFILE* f);
[302]172DLLEXP int fprintf(VirtFILE* f, const char *format, ...);
[109]173DLLEXP int fclose(VirtFILE* f);
174
175DLLEXP dirent* readdir(VirtDIR* d);
176DLLEXP int closedir(VirtDIR* d);
177
[523]178#endif //VIRTFILE_OVERLOADING
179
[109]180#endif
Note: See TracBrowser for help on using the repository browser.