File: FileInterface.hpp

package info (click to toggle)
psemu-drive-cdrmooby 2.8%2Bo-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 356 kB
  • ctags: 899
  • sloc: cpp: 3,286; ansic: 2,069; makefile: 46
file content (342 lines) | stat: -rw-r--r-- 10,525 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/************************************************************************

Copyright mooby 2002

CDRMooby2 FileInterface.hpp
http://mooby.psxfanatics.com

  This file is protected by the GNU GPL which should be included with
  the source code distribution.

************************************************************************/


#ifndef FILEINTERFACE_HPP
#define FILEINTERFACE_HPP

#include "CDTime.hpp"
#include "TimeCache.hpp"
#include "Frame.hpp"

#include <vector>
#include <fstream>

// the constants for the number of frames in compressed files as well as
// how large the required buffers are
const unsigned long BZIndexBufferFrames = 10;
const unsigned long BZIndexBufferBytes = BZIndexBufferFrames * bytesPerFrame;
const unsigned long ZTableBufferFrames = 1;
const unsigned long ZTableBufferBytes = ZTableBufferFrames * bytesPerFrame;
const unsigned long UncompressedBufferFrames = 10;
const unsigned long UncompressedBufferBytes = UncompressedBufferFrames * bytesPerFrame;

// a virtual interface to any CD image type
class FileInterface
{
public:
      // bufferFrames is the number of frames you want
      // available at any time.
   virtual ~FileInterface() 
   { 
      if (bufferFrames != 0) 
      {
      if (fileBuffer) 
         delete[] fileBuffer;
      } 
   }

		// opens the file
   virtual void openFile(const std::string& str)
      throw(Exception);

		// seeks to the time cdt in the file and sets the buffer pointer
   inline void seek(const CDTime& cdt)
      throw(Exception);

		// returns the pointer to the last frame seeked.
   inline unsigned char* getBuffer() const 
   {
      if (cacheMode == oldMode)
         return bufferPointer;
      else if (cacheMode == newMode)
         return *holdout;
   }

		// returns the length of the CD
   inline CDTime getCDLength() {return CDLength;}

      // sets up stuffs for pregap
   FileInterface& setPregap(const CDTime& gapLength, const CDTime& gapTime);

      // returns the last seeked time
   inline CDTime getSeekTime() {return seekTime;}

      // returns the name of the file
   inline std::string getFileName() const {return fileName;}

   enum CacheMode
   {
      oldMode,
      newMode
   };

   inline FileInterface& setCacheMode(const CacheMode m)
   { cacheMode = m; return *this; }

protected:
		// when seek(CDTime) seeks to a frame out of the buffer, this
		// function buffers more data and sets the bufferPointer to
      // the requested time
   virtual void seekUnbuffered(const CDTime& cdt)
      throw(std::exception, Exception) = 0;

		// the cd image
   std::ifstream file;
		// the number of frames buffered (0 for RAR)
   unsigned long bufferFrames;
		// the buffer to the cached data
   unsigned char* fileBuffer;
		// pointer to the last seeked frame
   unsigned char* bufferPointer;
		// the length of the CD
   CDTime CDLength;
		// the start position of the file buffer
   CDTime bufferPos;
		// the end position of the file buffer
   CDTime bufferEnd;
      // the last seeked time of this CD
   CDTime seekTime;
		// the name of the cd image
   std::string fileName;
	  // time of the pregap
   CDTime pregapTime;
      // length of the pregap
   CDTime pregapLength;

   CacheMode cacheMode;

      // the extra cache =)
   TimeCache<Frame> cache;
   Frame holdout;

protected:
		// this ensures that the buffer is at least as big as it's required (i.e. .BZ files
		// need at least 10 frames buffered).
		// for RAR, requiredFrames = 0
   FileInterface(const unsigned long requestedFrames, 
      const unsigned long requiredFrames);
};

// virtual interface to compressed files with index files (like .bz.index or .Z.table)
class CompressedFileInterface : public FileInterface
{
public:
   CompressedFileInterface(const unsigned long bf, const unsigned long pf)
      : FileInterface(bf, pf), compressedFrames(pf)
   { 
      compressedDataBuffer = 
         new unsigned char[(pf + 1) * bytesPerFrame];
   }

   virtual ~CompressedFileInterface() 
      {delete [] compressedDataBuffer;}

   virtual unsigned char* getCompressedBuffer() {return compressedDataBuffer;}

   virtual void compressData(char* uncompressedData,
                             char* compressedData,
                             unsigned int inputLen,
                             unsigned int& outputLen)
      throw(Exception) = 0;
   virtual void decompressData(char* uncompressedData,
                               char* compressedData,
                               unsigned int inputLen,
                               unsigned int& outputLen)
      throw(Exception) = 0;

   virtual std::string toTable(const std::vector<unsigned long>& table,
                               const std::vector<unsigned long>& sizes) = 0;

   unsigned long getCompressedFrames() {return compressedFrames;}

protected:
   virtual void seekUnbuffered(const CDTime& cdt)
      throw(std::exception, Exception);
   
   unsigned char* compressedDataBuffer;
   std::vector<unsigned long> lookupTable;
   unsigned long compressedFrames;

private:
   CompressedFileInterface();
};

// interface to the ZTable type files
class ZTableFileInterface : public CompressedFileInterface
{
public:
   ZTableFileInterface(const unsigned long bf)
      : CompressedFileInterface(bf, ZTableBufferFrames) {}
   virtual ~ZTableFileInterface() {}
   virtual void openFile(const std::string& str)
      throw(Exception);
   
   virtual void compressData(char* uncompressedData,
                             char* compressedData,
                             unsigned int inputLen,
                             unsigned int& outputLen)
      throw(Exception);
   virtual void decompressData(char* uncompressedData,
                               char* compressedData,
                               unsigned int inputLen,
                               unsigned int& outputLen)
      throw(Exception);

   virtual std::string toTable(const std::vector<unsigned long>& table,
                               const std::vector<unsigned long>& sizes);
protected:

private:
   ZTableFileInterface();
};

// interface to the BZIndex type of files
class BZIndexFileInterface : public CompressedFileInterface
{
public:
   BZIndexFileInterface(const unsigned long bf)
      : CompressedFileInterface(bf, BZIndexBufferFrames) {}
   virtual ~BZIndexFileInterface() {}
   virtual void openFile(const std::string& str)
      throw(Exception);
   
   virtual void compressData(char* uncompressedData,
                             char* compressedData,
                             unsigned int inputLen,
                             unsigned int& outputLen)
      throw(Exception);

   virtual void decompressData(char* uncompressedData,
                               char* compressedData,
                               unsigned int inputLen,
                               unsigned int& outputLen)
      throw(Exception);

   virtual std::string toTable(const std::vector<unsigned long>& table,
                               const std::vector<unsigned long>& sizes);
protected:

private:
   BZIndexFileInterface();
};

// interface to uncompressed files
class UncompressedFileInterface : public FileInterface
{
public:
   UncompressedFileInterface(const unsigned long bf)
      : FileInterface(bf, UncompressedBufferFrames) 
   {}
   
   virtual ~UncompressedFileInterface() {}

protected:
   virtual void seekUnbuffered(const CDTime& cdt)
      throw(std::exception, Exception);

private:
   UncompressedFileInterface();
};


// interface to RAR files.  All the data members are static so it doesn't
// decompress the file twice for normal data and CDDA data
class RARFileInterface : public FileInterface
{
public:
   RARFileInterface(const unsigned long bf)
      : FileInterface(bf, 0)
   {
         // dont use the LRU cache (the data is already in memory)
      cacheMode = oldMode;
   }

   virtual void openFile(const std::string& str)
      throw(Exception);
   virtual ~RARFileInterface() {toastStaticVars(); fileBuffer = NULL;}
protected:
   
   virtual void seekUnbuffered(const CDTime& cdt)
      throw(std::exception, Exception) {}
private:
   static void toastStaticVars() 
      {alreadyUncompressed = false; free(theFile); theFile = NULL; length = 0;}
   static void setUncompressed(const unsigned long len) 
      {alreadyUncompressed = true; length = len;}


   RARFileInterface();
		// whether or not it's already decompressed
   static bool alreadyUncompressed;
		// the file data uncompressed in memory
   static unsigned char* theFile;
		// the length of the file
   static unsigned long length;
};

// i optimized this function so the CDTimes don't need to use the timeConvert() function
// with all the + operations.  If the data is buffered, it should return very quickly.
// This only ensures that one frame is available at bufferPointer, but that should be
// enough for most things...
inline void FileInterface::seek(const CDTime& cdt)
   throw(Exception)
{
	using namespace std;
   seekTime = cdt;
   if (seekTime >= pregapTime)
      seekTime -= pregapLength;


   if (seekTime < CDLength)
   {
      if (cacheMode == newMode)
      {
            // check in the global cache first
         if (cache.find(seekTime, holdout))
         {
            return;
         }
      }

         // see if its in the file cache.
         // in both of these cases, bufferPointer should point to the data
         // requested
      if ( (seekTime >= bufferPos) &&
         ( (seekTime.getAbsoluteFrame() + 1) <= (bufferEnd.getAbsoluteFrame()) ) )
      {
         bufferPointer =
            fileBuffer + (seekTime.getAbsoluteByte() - bufferPos.getAbsoluteByte());
      }
      else
      {
         seekUnbuffered(seekTime);
      }
         // insert the new data into the cache
      if (cacheMode == newMode)
      {
         holdout = bufferPointer;
         cache.insert(seekTime, holdout);
      }
   }
   else
   {
      Exception e("Seek past end of disc");
      THROW(e);
   }
}

  // the factory method for creating a FileInterface based only on the filename
FileInterface* FileInterfaceFactory(const std::string& filename,
                                    std::string& extension);

#endif