~jazzva/fakenes/ubuntu

« back to all changes in this revision

Viewing changes to src/shared/bufferfile.cpp

  • Committer: Sasa Bodiroza
  • Date: 2007-08-15 05:37:49 UTC
  • Revision ID: jazzva@gmail.com-20070815053749-76l0xj66tzgt290p
Upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FakeNES - A free, portable, Open Source NES emulator.
 
2
 
 
3
   Copyright (c) 2001-2006, FakeNES Team.
 
4
   This is free software.  See 'LICENSE' for details.
 
5
   You must read and accept the license prior to use.
 
6
 
 
7
   bufferfile.cpp: "Buffer file" I/O routines by randilyn. */
 
8
 
 
9
#include <allegro.h>        
 
10
#include <vector>
 
11
#include "../include/common.h"
 
12
#include "bufferfile.h"
 
13
 
 
14
class BufferFile {
 
15
public:
 
16
   std::vector<uint8> data;
 
17
   long pos, size, max;
 
18
};
 
19
 
 
20
#define CHUNK_SIZE   4096
 
21
                     
 
22
static const PACKFILE_VTABLE *get_packfile_vtable (void);
 
23
 
 
24
PACKFILE *BufferFile_open (void)
 
25
{
 
26
   BufferFile *bufferFile = new BufferFile;
 
27
   if (!bufferFile)
 
28
   {
 
29
      WARN("Out of memory");
 
30
      return (null);
 
31
 
 
32
   }
 
33
 
 
34
   bufferFile->pos = 0;
 
35
   bufferFile->size = 0;
 
36
   bufferFile->max = 0;
 
37
 
 
38
   PACKFILE *pf = pack_fopen_vtable (get_packfile_vtable (), bufferFile);
 
39
   if (!pf)
 
40
   {
 
41
      WARN("Call to pack_fopen_vtable() failed");
 
42
      delete bufferFile;
 
43
      return (null);
 
44
   }
 
45
 
 
46
   return (pf);
 
47
}
 
48
 
 
49
void BufferFile_get_buffer (PACKFILE *pf, uint8 **buffer, long *size)
 
50
{
 
51
   RT_ASSERT(pf);
 
52
   RT_ASSERT(buffer);
 
53
   RT_ASSERT(size);
 
54
 
 
55
   BufferFile *bufferFile = (BufferFile *)pf->userdata;
 
56
 
 
57
   *buffer = &bufferFile->data[0];
 
58
   *size = bufferFile->size;
 
59
}
 
60
 
 
61
// Internal functions follow.
 
62
 
 
63
static int BufferFile_fclose (void *userdata)
 
64
{
 
65
   RT_ASSERT(userdata);
 
66
 
 
67
   BufferFile *bufferFile = (BufferFile *)userdata;
 
68
 
 
69
   // Clean up.
 
70
   bufferFile->data.clear ();
 
71
 
 
72
   delete bufferFile;
 
73
 
 
74
   return (0);
 
75
}
 
76
 
 
77
static int BufferFile_getc (void *userdata)
 
78
{
 
79
   RT_ASSERT(userdata);
 
80
 
 
81
   BufferFile *bufferFile = (BufferFile *)userdata;
 
82
 
 
83
   if (bufferFile->pos >= bufferFile->size)
 
84
   {
 
85
      // EOF
 
86
      return (0);
 
87
   }
 
88
 
 
89
   return (bufferFile->data[bufferFile->pos++]);
 
90
}                  
 
91
 
 
92
static int BufferFile_ungetc (int c, void *userdata)
 
93
{
 
94
   RT_ASSERT(userdata);
 
95
 
 
96
   // Not supported.
 
97
   return (EOF);
 
98
}
 
99
 
 
100
static long BufferFile_fread (void *p, long n, void *userdata)
 
101
{
 
102
   RT_ASSERT(p);
 
103
   RT_ASSERT(userdata);
 
104
 
 
105
   BufferFile *bufferFile = (BufferFile *)userdata;
 
106
 
 
107
   if (bufferFile->pos >= bufferFile->size)
 
108
   {
 
109
      // EOF
 
110
      return (0);
 
111
   }
 
112
 
 
113
   long size = (bufferFile->size - bufferFile->pos);
 
114
   if (n > size)
 
115
      n = size;
 
116
 
 
117
   memcpy (p, (&bufferFile->data[0] + bufferFile->pos), n);
 
118
   bufferFile->pos += n;
 
119
 
 
120
   return (n);
 
121
}
 
122
 
 
123
static int BufferFile_putc (int c, void *userdata)
 
124
{
 
125
   RT_ASSERT(userdata);
 
126
 
 
127
   BufferFile *bufferFile = (BufferFile *)userdata;
 
128
 
 
129
   if (bufferFile->pos >= bufferFile->size)
 
130
   {
 
131
      // EOF
 
132
 
 
133
      if (bufferFile->pos >= (bufferFile->size + 1))
 
134
      {
 
135
         // Out of bounds
 
136
         return (0);
 
137
      }
 
138
 
 
139
      bufferFile->size++;
 
140
      if (bufferFile->size > bufferFile->max)
 
141
      {
 
142
         bufferFile->max = (bufferFile->size + CHUNK_SIZE);
 
143
         bufferFile->data.reserve (bufferFile->max);
 
144
      }
 
145
 
 
146
      bufferFile->data.resize (bufferFile->size);
 
147
   }
 
148
 
 
149
   bufferFile->data[bufferFile->pos++] = c;
 
150
 
 
151
   return (c);
 
152
}
 
153
                                                               
 
154
static long BufferFile_fwrite (const void *p, long n, void *userdata)
 
155
{
 
156
   RT_ASSERT(p);
 
157
   RT_ASSERT(userdata);
 
158
 
 
159
   BufferFile *bufferFile = (BufferFile *)userdata;
 
160
 
 
161
   if (bufferFile->pos >= bufferFile->size)
 
162
   {
 
163
      if (bufferFile->pos >= (bufferFile->size + 1))
 
164
         return (0);
 
165
 
 
166
      bufferFile->size += n;
 
167
      if (bufferFile->size > bufferFile->max)
 
168
      {
 
169
         bufferFile->max = (bufferFile->size + CHUNK_SIZE);
 
170
         bufferFile->data.reserve (bufferFile->max);
 
171
      }                               
 
172
 
 
173
      bufferFile->data.resize (bufferFile->size);
 
174
   }
 
175
 
 
176
   memcpy ((&bufferFile->data[0] + bufferFile->pos), p, n);
 
177
   bufferFile->pos += n;
 
178
 
 
179
   return (n);
 
180
}
 
181
 
 
182
static int BufferFile_fseek (void *userdata, int offset)
 
183
{
 
184
   RT_ASSERT(userdata);
 
185
 
 
186
   BufferFile *bufferFile = (BufferFile *)userdata;
 
187
 
 
188
   if ((offset < 0) || (offset > bufferFile->size))
 
189
   {
 
190
      // Out of bounds.
 
191
      return (-1);
 
192
   }
 
193
 
 
194
   bufferFile->pos = offset;
 
195
 
 
196
   return (0);
 
197
}
 
198
 
 
199
static int BufferFile_feof (void *userdata)
 
200
{
 
201
   RT_ASSERT(userdata);
 
202
 
 
203
   BufferFile *bufferFile = (BufferFile *)userdata;
 
204
 
 
205
   if (bufferFile->pos >= bufferFile->size)
 
206
      return (true);
 
207
 
 
208
   return (false);
 
209
}
 
210
 
 
211
static int BufferFile_ferror (void *userdata)
 
212
{
 
213
   RT_ASSERT(userdata);
 
214
 
 
215
   // Not supported.
 
216
   return (0);
 
217
}
 
218
 
 
219
static PACKFILE_VTABLE packfile_vtable;
 
220
 
 
221
static const PACKFILE_VTABLE *get_packfile_vtable (void)
 
222
{
 
223
   PACKFILE_VTABLE *vtable = &packfile_vtable;
 
224
 
 
225
   memset (vtable, 0, sizeof(PACKFILE_VTABLE));
 
226
 
 
227
   vtable->pf_fclose = BufferFile_fclose;
 
228
   vtable->pf_getc   = BufferFile_getc;
 
229
   vtable->pf_ungetc = BufferFile_ungetc;
 
230
   vtable->pf_fread  = BufferFile_fread;
 
231
   vtable->pf_putc   = BufferFile_putc;
 
232
   vtable->pf_fwrite = BufferFile_fwrite;
 
233
   vtable->pf_fseek  = BufferFile_fseek;
 
234
   vtable->pf_feof   = BufferFile_feof;
 
235
   vtable->pf_ferror = BufferFile_ferror;
 
236
 
 
237
   return (vtable);
 
238
}