DSL
rwops.cpp
1 //@AUTOHEADER@BEGIN@
2 /***********************************************************************\
3 | Drift Standard Libraries v1.01 |
4 | Copyright 2010-2023 Drift Solutions / Indy Sams |
5 | Docs and more information available at https://www.driftsolutions.dev |
6 | This file released under the 3-clause BSD license, |
7 | see included DSL.LICENSE.TXT file for details. |
8 \***********************************************************************/
9 //@AUTOHEADER@END@
10 
11 #include <drift/dslcore.h>
12 #include <drift/rwops.h>
13 #include <drift/GenLib.h>
14 
15 int64 file_read(void * buf, int64 size, DSL_FILE * fp) {
16  return fread(buf,1,size,fp->fp);
17 }
18 
19 int64 file_write(void * buf, int64 size, DSL_FILE * fp) {
20  return fwrite(buf,1,size,fp->fp);
21 }
22 
23 bool file_seek(DSL_FILE * fp, int64 pos, int whence) {
24  return (fseek64(fp->fp, pos, whence) == 0);
25 }
26 
27 int64 file_tell(DSL_FILE * fp) {
28  return ftell64(fp->fp);
29 }
30 
31 bool file_flush(DSL_FILE * fp) {
32  return (fflush(fp->fp) == 0);
33 }
34 
35 bool file_eof(DSL_FILE * fp) {
36  return (feof(fp->fp) != 0);
37 }
38 
39 void file_close(DSL_FILE * fp) {
40  bool do_close = true;
41  if (fp->p_extra) {
42  TP_RWOPT * opt = (TP_RWOPT *)fp->p_extra;
43  do_close = opt->autoclose;
44  dsl_free(opt);
45  }
46  if (do_close) { fclose(fp->fp); }
47  dsl_free(fp);
48 }
49 
50 DSL_FILE * DSL_CC RW_OpenFile(const char * fn, const char * mode) {
51  FILE * fp = fopen(fn, mode);
52  if (fp == NULL) { return NULL; }
53 
54  DSL_FILE * ret = dsl_znew(DSL_FILE);
55 
56  ret->fp = fp;
57  ret->read = file_read;
58  ret->write = file_write;
59  ret->seek = file_seek;
60  ret->tell = file_tell;
61  ret->flush = file_flush;
62  ret->eof = file_eof;
63  ret->close = file_close;
64 
65  return ret;
66 };
67 
68 DSL_FILE * DSL_CC RW_ConvertFile(FILE * fp, bool autoclose) {
69  DSL_FILE * ret = dsl_znew(DSL_FILE);
70 
71  ret->fp = fp;
72  ret->read = file_read;
73  ret->write = file_write;
74  ret->seek = file_seek;
75  ret->tell = file_tell;
76  ret->flush = file_flush;
77  ret->eof = file_eof;
78  ret->close = file_close;
79 
80  TP_RWOPT * opt = dsl_znew(TP_RWOPT);
81  opt->autoclose = autoclose;
82  ret->p_extra = opt;
83 
84  return ret;
85 };
86 
87 struct TP_MEMHANDLE {
88  DSL_FILE _handle;
89  uint8 * mem;
90  bool bDelete;
91  int64 offset;
92  int64 size;
93 };
94 
95 int64 mem_read(void * buf, int64 size, DSL_FILE * fp) {
96  TP_MEMHANDLE * mem = (TP_MEMHANDLE *)fp;
97  if (size + mem->offset > mem->size) {
98  size = mem->size - mem->offset;
99  }
100  if (mem->offset >= mem->size || size <= 0) { return 0; }
101 
102  memcpy(buf, mem->mem + mem->offset, size);
103  mem->offset += size;
104 
105  return size;
106 }
107 
108 int64 mem_write(void * buf, int64 size, DSL_FILE * fp) {
109  TP_MEMHANDLE * mem = (TP_MEMHANDLE *)fp;
110 
111  if (size + mem->offset > mem->size) {
112  size = mem->size - mem->offset;
113  }
114  if (mem->offset >= mem->size || size <= 0) { return 0; }
115 
116  memcpy(mem->mem + mem->offset, buf, size);
117  mem->offset += size;
118  return size;
119 }
120 
121 bool mem_seek(DSL_FILE * fp, int64 pos, int mode) {
122  TP_MEMHANDLE * mem = (TP_MEMHANDLE *)fp;
123  switch(mode) {
124  case SEEK_SET:
125  mem->offset = pos;
126  break;
127  case SEEK_CUR:
128  mem->offset += pos;
129  break;
130  case SEEK_END:
131  mem->offset = mem->size + pos;
132  break;
133  default:
134  return false;
135  break;
136  }
137  if (mem->offset > mem->size) {
138  mem->offset = mem->size;
139  }
140  if (mem->offset < 0) {
141  mem->offset = 0;
142  }
143  return true;
144 }
145 
146 void mem_close(DSL_FILE * fp) {
147  TP_MEMHANDLE * mem = (TP_MEMHANDLE *)fp;
148  if (mem->bDelete) {
149  dsl_free(mem->mem);
150  }
151  dsl_free(fp);
152 }
153 
154 int64 mem_tell(DSL_FILE * fp) {
155  TP_MEMHANDLE * mem = (TP_MEMHANDLE *)fp;
156  return mem->offset;
157 }
158 
159 bool mem_eof(DSL_FILE * fp) {
160  TP_MEMHANDLE * mem = (TP_MEMHANDLE *)fp;
161  return (mem->offset >= mem->size);
162 }
163 
164 bool mem_flush(DSL_FILE * fp) {
165  return true;
166 }
167 
168 DSL_FILE * DSL_CC RW_OpenMemory(int64 size) {
170  DSL_FILE * ret = (DSL_FILE *)&mem->_handle;
171 
172  mem->mem = (uint8 *)dsl_malloc(size);
173  mem->bDelete = true;
174  memset(mem->mem,0,size);
175  mem->size = size;
176 
177  ret->read = mem_read;
178  ret->write = mem_write;
179  ret->seek = mem_seek;
180  ret->tell = mem_tell;
181  ret->eof = mem_eof;
182  ret->flush = mem_flush;
183  ret->close = mem_close;
184 
185  return ret;
186 }
187 
188 DSL_FILE * DSL_CC RW_ConvertMemory(uint8 * buf, int64 size) {
190  DSL_FILE * ret = (DSL_FILE *)&mem->_handle;
191 
192  mem->mem = buf;
193  mem->size = size;
194 
195  ret->read = mem_read;
196  ret->write = mem_write;
197  ret->seek = mem_seek;
198  ret->tell = mem_tell;
199  ret->eof = mem_eof;
200  ret->flush = mem_flush;
201  ret->close = mem_close;
202 
203  return ret;
204 }
205 
206 struct TP_BUFHANDLE {
207  DSL_FILE _handle;
208  DSL_BUFFER * buf;
209  bool bDelete;
210  int64 offset;
211 };
212 
213 int64 buf_read(void * buf, int64 size, DSL_FILE * fp) {
214  TP_BUFHANDLE * mem = (TP_BUFHANDLE *)fp;
215  if (size + mem->offset > mem->buf->len) {
216  size = mem->buf->len - mem->offset;
217  }
218  if (mem->offset >= mem->buf->len || size <= 0) { return 0; }
219 
220  memcpy(buf, mem->buf->udata + mem->offset, size);
221  mem->offset += size;
222 
223  return size;
224 }
225 
226 int64 buf_write(void * buf, int64 size, DSL_FILE * fp) {
227  TP_BUFHANDLE * mem = (TP_BUFHANDLE *)fp;
228 
229  if (size <= 0) { return 0; }
230 
231  int64 newoff = mem->offset + size;
232  if (newoff > mem->buf->len) {
233  buffer_resize(mem->buf, newoff);
234  }
235 
236  memcpy(mem->buf->udata + mem->offset, buf, size);
237  mem->offset = newoff;
238  return size;
239 }
240 
241 bool buf_seek(DSL_FILE * fp, int64 pos, int mode) {
242  TP_BUFHANDLE * mem = (TP_BUFHANDLE *)fp;
243  switch (mode) {
244  case SEEK_SET:
245  mem->offset = pos;
246  break;
247  case SEEK_CUR:
248  mem->offset += pos;
249  break;
250  case SEEK_END:
251  mem->offset = mem->buf->len + pos;
252  break;
253  default:
254  return false;
255  break;
256  }
257  if (mem->offset > mem->buf->len) {
258  mem->offset = mem->buf->len;
259  }
260  if (mem->offset < 0) {
261  mem->offset = 0;
262  }
263  return true;
264 }
265 
266 void buf_close(DSL_FILE * fp) {
267  TP_BUFHANDLE * mem = (TP_BUFHANDLE *)fp;
268  if (mem->bDelete) {
269  buffer_free(mem->buf);
270  dsl_free(mem->buf);
271  }
272  dsl_free(fp);
273 }
274 
275 int64 buf_tell(DSL_FILE * fp) {
276  TP_BUFHANDLE * mem = (TP_BUFHANDLE *)fp;
277  return mem->offset;
278 }
279 
280 bool buf_eof(DSL_FILE * fp) {
281  TP_BUFHANDLE * mem = (TP_BUFHANDLE *)fp;
282  return (mem->offset >= mem->buf->len);
283 }
284 
285 bool buf_flush(DSL_FILE * fp) {
286  return true;
287 }
288 
289 DSL_FILE * DSL_CC RW_OpenBuffer(DSL_BUFFER ** pbuf) {
291  DSL_FILE * ret = (DSL_FILE *)&mem->_handle;
292 
293  DSL_BUFFER * buf = dsl_znew(DSL_BUFFER);
294  buffer_init(buf);
295 
296  mem->buf = buf;
297  if (pbuf != NULL) {
298  *pbuf = buf;
299  }
300  mem->bDelete = true;
301 
302  ret->read = buf_read;
303  ret->write = buf_write;
304  ret->seek = buf_seek;
305  ret->tell = buf_tell;
306  ret->eof = buf_eof;
307  ret->flush = buf_flush;
308  ret->close = buf_close;
309 
310  return ret;
311 }
312 
313 DSL_FILE * DSL_CC RW_ConvertBuffer(DSL_BUFFER * buf, int64 offset) {
315  DSL_FILE * ret = (DSL_FILE *)&mem->_handle;
316 
317  mem->buf = buf;
318  if (offset < 0) {
319  mem->offset = buf->len;
320  } else {
321  mem->offset = offset;
322  }
323 
324  ret->read = buf_read;
325  ret->write = buf_write;
326  ret->seek = buf_seek;
327  ret->tell = buf_tell;
328  ret->eof = buf_eof;
329  ret->flush = buf_flush;
330  ret->close = buf_close;
331 
332  return ret;
333 }
334 
DSL_API void DSL_CC buffer_init(DSL_BUFFER *buf, bool useMutex=false)
Initialize the buffer, optionally with a mutex protecting it. If you don't use the mutex you need to ...
Definition: Buffer.cpp:123
DSL_API void DSL_CC buffer_free(DSL_BUFFER *buf)
Free the buffer when you are done with it.
Definition: Buffer.cpp:128
DSL_API void DSL_CC buffer_resize(DSL_BUFFER *buf, int64 len)
Resize the buffer, if the length is longer then the existing data the added byte values are undefined...
Definition: Buffer.cpp:160
DSL_API void DSL_CC dsl_free(void *ptr)
Definition: dsl.cpp:345
#define dsl_znew(x)
Definition: dslcore.h:152
DSL_API int64 DSL_CC ftell64(FILE *fp)
Cross-platform 64-bit ftell.
Definition: GenLib.cpp:527
DSL_API int64 DSL_CC fseek64(FILE *fp, int64 offset, int whence)
Cross-platform 64-bit fseek.
Definition: GenLib.cpp:519
DSL_FILE *DSL_CC RW_ConvertBuffer(DSL_BUFFER *buf, int64 offset)
Definition: rwops.cpp:313
DSL_FILE *DSL_CC RW_ConvertFile(FILE *fp, bool autoclose)
Definition: rwops.cpp:68
DSL_FILE *DSL_CC RW_OpenFile(const char *fn, const char *mode)
Definition: rwops.cpp:50
DSL_FILE *DSL_CC RW_OpenBuffer(DSL_BUFFER **pbuf)
Definition: rwops.cpp:289
DSL_FILE *DSL_CC RW_ConvertMemory(uint8 *buf, int64 size)
Definition: rwops.cpp:188
DSL_FILE *DSL_CC RW_OpenMemory(int64 size)
Definition: rwops.cpp:168
Definition: rwops.h:24
int64(* write)(void *buf, int64 size, DSL_FILE *fp)
Definition: rwops.h:41
void(* close)(DSL_FILE *fp)
Definition: rwops.h:54
bool(* seek)(DSL_FILE *fp, int64 pos, int mode)
Definition: rwops.h:31
int64(* read)(void *buf, int64 size, DSL_FILE *fp)
Definition: rwops.h:36
bool(* eof)(DSL_FILE *fp)
Definition: rwops.h:50
int64(* tell)(DSL_FILE *fp)
Definition: rwops.h:45