initial import
[dosrtxon] / libs / mikmod / mmio / mmio.c
1 /*      MikMod sound library
2         (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS for
3         complete list.
4
5         This library is free software; you can redistribute it and/or modify
6         it under the terms of the GNU Library General Public License as
7         published by the Free Software Foundation; either version 2 of
8         the License, or (at your option) any later version.
9
10         This program is distributed in the hope that it will be useful,
11         but WITHOUT ANY WARRANTY; without even the implied warranty of
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13         GNU Library General Public License for more details.
14
15         You should have received a copy of the GNU Library General Public
16         License along with this library; if not, write to the Free Software
17         Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18         02111-1307, USA.
19 */
20
21 /*==============================================================================
22
23   $Id$
24
25   Portable file I/O routines
26
27 ==============================================================================*/
28
29 /*
30
31         The way this module works:
32
33         - _mm_fopen will call the errorhandler [see mmerror.c] in addition to
34           setting _mm_errno on exit.
35         - _mm_iobase is for internal use.  It is used by Player_LoadFP to
36           ensure that it works properly with wad files.
37         - _mm_read_I_* and _mm_read_M_* differ : the first is for reading data
38           written by a little endian (intel) machine, and the second is for reading
39           big endian (Mac, RISC, Alpha) machine data.
40         - _mm_write functions work the same as the _mm_read functions.
41         - _mm_read_string is for reading binary strings.  It is basically the same
42           as an fread of bytes.
43
44 */
45
46 #ifdef HAVE_CONFIG_H
47 #include "config.h"
48 #endif
49
50 #ifdef HAVE_UNISTD_H
51 #include <unistd.h>
52 #endif
53
54 #ifdef HAVE_LIMITS_H
55 #include <limits.h>
56 #endif
57
58 #include <stdio.h>
59 #include <string.h>
60
61 #include "mikmod_internals.h"
62
63 #ifdef SUNOS
64 extern int fclose(FILE *);
65 extern int fgetc(FILE *);
66 extern int fputc(int, FILE *);
67 extern size_t fread(void *, size_t, size_t, FILE *);
68 extern int fseek(FILE *, long, int);
69 extern size_t fwrite(const void *, size_t, size_t, FILE *);
70 #endif
71
72 #define COPY_BUFSIZE  1024
73
74 /* some prototypes */
75 static BOOL _mm_MemReader_Eof(MREADER* reader);
76 static BOOL _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size);
77 static int _mm_MemReader_Get(MREADER* reader);
78 static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence);
79 static long _mm_MemReader_Tell(MREADER* reader);
80
81 /*static long _mm_iobase = 0, temp_iobase = 0;*/
82
83 FILE* _mm_fopen(const CHAR* fname, const CHAR* attrib)
84 {
85         FILE *fp;
86
87         if(!(fp=fopen(fname,attrib))) {
88                 _mm_errno = MMERR_OPENING_FILE;
89                 if(_mm_errorhandler) _mm_errorhandler();
90         }
91         return fp;
92 }
93
94 BOOL _mm_FileExists(const CHAR* fname)
95 {
96         FILE *fp;
97
98         if(!(fp=fopen(fname,"r"))) return 0;
99         fclose(fp);
100
101         return 1;
102 }
103
104 int _mm_fclose(FILE *fp)
105 {
106         return fclose(fp);
107 }
108
109 /* Sets the current file-position as the new iobase */
110 void _mm_iobase_setcur(MREADER* reader)
111 {
112         reader->prev_iobase=reader->iobase;  /* store old value in case of revert */
113         reader->iobase=reader->Tell(reader);
114 }
115
116 /* Reverts to the last known iobase value. */
117 void _mm_iobase_revert(MREADER* reader)
118 {
119         reader->iobase=reader->prev_iobase;
120 }
121
122 /*========== File Reader */
123
124 typedef struct MFILEREADER {
125         MREADER core;
126         FILE*   file;
127 } MFILEREADER;
128
129 static BOOL _mm_FileReader_Eof(MREADER* reader)
130 {
131         return feof(((MFILEREADER*)reader)->file);
132 }
133
134 static BOOL _mm_FileReader_Read(MREADER* reader,void* ptr,size_t size)
135 {
136         return !!fread(ptr,size,1,((MFILEREADER*)reader)->file);
137 }
138
139 static int _mm_FileReader_Get(MREADER* reader)
140 {
141         return fgetc(((MFILEREADER*)reader)->file);
142 }
143
144 static int _mm_FileReader_Seek(MREADER* reader,long offset,int whence)
145 {
146         return fseek(((MFILEREADER*)reader)->file,
147                                  (whence==SEEK_SET)?offset+reader->iobase:offset,whence);
148 }
149
150 static long _mm_FileReader_Tell(MREADER* reader)
151 {
152         return ftell(((MFILEREADER*)reader)->file)-reader->iobase;
153 }
154
155 MREADER *_mm_new_file_reader(FILE* fp)
156 {
157         MFILEREADER* reader=(MFILEREADER*)MikMod_calloc(1,sizeof(MFILEREADER));
158         if (reader) {
159                 reader->core.Eof =&_mm_FileReader_Eof;
160                 reader->core.Read=&_mm_FileReader_Read;
161                 reader->core.Get =&_mm_FileReader_Get;
162                 reader->core.Seek=&_mm_FileReader_Seek;
163                 reader->core.Tell=&_mm_FileReader_Tell;
164                 reader->file=fp;
165         }
166         return (MREADER*)reader;
167 }
168
169 void _mm_delete_file_reader (MREADER* reader)
170 {
171         MikMod_free(reader);
172 }
173
174 /*========== File Writer */
175
176 typedef struct MFILEWRITER {
177         MWRITER core;
178         FILE*   file;
179 } MFILEWRITER;
180
181 static int _mm_FileWriter_Seek(MWRITER* writer,long offset,int whence)
182 {
183         return fseek(((MFILEWRITER*)writer)->file,offset,whence);
184 }
185
186 static long _mm_FileWriter_Tell(MWRITER* writer)
187 {
188         return ftell(((MFILEWRITER*)writer)->file);
189 }
190
191 static BOOL _mm_FileWriter_Write(MWRITER* writer, const void* ptr, size_t size)
192 {
193         return (fwrite(ptr,size,1,((MFILEWRITER*)writer)->file)==size);
194 }
195
196 static int _mm_FileWriter_Put(MWRITER* writer,int value)
197 {
198         return fputc(value,((MFILEWRITER*)writer)->file);
199 }
200
201 MWRITER *_mm_new_file_writer(FILE* fp)
202 {
203         MFILEWRITER* writer=(MFILEWRITER*)MikMod_calloc(1,sizeof(MFILEWRITER));
204         if (writer) {
205                 writer->core.Seek =&_mm_FileWriter_Seek;
206                 writer->core.Tell =&_mm_FileWriter_Tell;
207                 writer->core.Write=&_mm_FileWriter_Write;
208                 writer->core.Put  =&_mm_FileWriter_Put;
209                 writer->file=fp;
210         }
211         return (MWRITER*) writer;
212 }
213
214 void _mm_delete_file_writer (MWRITER* writer)
215 {
216         MikMod_free (writer);
217 }
218
219 /*========== Memory Reader */
220
221 typedef struct MMEMREADER {
222         MREADER core;
223         const void *buffer;
224         long len;
225         long pos;
226 } MMEMREADER;
227
228 void _mm_delete_mem_reader(MREADER* reader)
229 {
230         MikMod_free(reader);
231 }
232
233 MREADER *_mm_new_mem_reader(const void *buffer, long len)
234 {
235         MMEMREADER* reader=(MMEMREADER*)MikMod_calloc(1,sizeof(MMEMREADER));
236         if (reader)
237         {
238                 reader->core.Eof =&_mm_MemReader_Eof;
239                 reader->core.Read=&_mm_MemReader_Read;
240                 reader->core.Get =&_mm_MemReader_Get;
241                 reader->core.Seek=&_mm_MemReader_Seek;
242                 reader->core.Tell=&_mm_MemReader_Tell;
243                 reader->buffer = buffer;
244                 reader->len = len;
245                 reader->pos = 0;
246         }
247         return (MREADER*)reader;
248 }
249
250 static BOOL _mm_MemReader_Eof(MREADER* reader)
251 {
252         MMEMREADER* mr = (MMEMREADER*) reader;
253         if (!mr) return 1;
254         if (mr->pos >= mr->len) return 1;
255         return 0;
256 }
257
258 static BOOL _mm_MemReader_Read(MREADER* reader,void* ptr,size_t size)
259 {
260         unsigned char *d;
261         const unsigned char *s;
262         MMEMREADER* mr;
263         long siz;
264         BOOL ret;
265
266         if (!reader || !size || (size > (size_t) LONG_MAX))
267                 return 0;
268
269         mr = (MMEMREADER*) reader;
270         siz = (long) size;
271         if (mr->pos >= mr->len) return 0;       /* @ eof */
272         if (mr->pos + siz > mr->len) {
273                 siz = mr->len - mr->pos;
274                 ret = 0; /* not enough remaining bytes */
275         }
276         else {
277                 ret = 1;
278         }
279
280         s = (const unsigned char *) mr->buffer;
281         s += mr->pos;
282         mr->pos += siz;
283         d = (unsigned char *) ptr;
284
285         while (siz) {
286                 *d++ = *s++;
287                 siz--;
288         }
289
290         return ret;
291 }
292
293 static int _mm_MemReader_Get(MREADER* reader)
294 {
295         MMEMREADER* mr;
296         int c;
297
298         mr = (MMEMREADER*) reader;
299         if (mr->pos >= mr->len) return EOF;
300         c = ((const unsigned char*) mr->buffer)[mr->pos];
301         mr->pos++;
302
303         return c;
304 }
305
306 static int _mm_MemReader_Seek(MREADER* reader,long offset,int whence)
307 {
308         MMEMREADER* mr;
309
310         if (!reader) return -1;
311         mr = (MMEMREADER*) reader;
312         switch(whence)
313         {
314         case SEEK_CUR:
315                 mr->pos += offset;
316                 break;
317         case SEEK_SET:
318                 mr->pos = reader->iobase + offset;
319                 break;
320         case SEEK_END:
321                 mr->pos = mr->len + offset;
322                 break;
323         }
324         if (mr->pos < reader->iobase) {
325                 mr->pos = mr->core.iobase;
326                 return -1;
327         }
328         if (mr->pos > mr->len) {
329                 mr->pos = mr->len;
330         }
331         return 0;
332 }
333
334 static long _mm_MemReader_Tell(MREADER* reader)
335 {
336         if (reader) {
337                 return ((MMEMREADER*)reader)->pos - reader->iobase;
338         }
339         return 0;
340 }
341
342 /*========== Write functions */
343
344 void _mm_write_string(const CHAR* data,MWRITER* writer)
345 {
346         if(data)
347                 _mm_write_UBYTES(data,strlen(data),writer);
348 }
349
350 void _mm_write_M_UWORD(UWORD data,MWRITER* writer)
351 {
352         _mm_write_UBYTE(data>>8,writer);
353         _mm_write_UBYTE(data&0xff,writer);
354 }
355
356 void _mm_write_I_UWORD(UWORD data,MWRITER* writer)
357 {
358         _mm_write_UBYTE(data&0xff,writer);
359         _mm_write_UBYTE(data>>8,writer);
360 }
361
362 void _mm_write_M_ULONG(ULONG data,MWRITER* writer)
363 {
364         _mm_write_M_UWORD(data>>16,writer);
365         _mm_write_M_UWORD(data&0xffff,writer);
366 }
367
368 void _mm_write_I_ULONG(ULONG data,MWRITER* writer)
369 {
370         _mm_write_I_UWORD(data&0xffff,writer);
371         _mm_write_I_UWORD(data>>16,writer);
372 }
373
374 void _mm_write_M_SWORD(SWORD data,MWRITER* writer)
375 {
376         _mm_write_M_UWORD((UWORD)data,writer);
377 }
378
379 void _mm_write_I_SWORD(SWORD data,MWRITER* writer)
380 {
381         _mm_write_I_UWORD((UWORD)data,writer);
382 }
383
384 void _mm_write_M_SLONG(SLONG data,MWRITER* writer)
385 {
386         _mm_write_M_ULONG((ULONG)data,writer);
387 }
388
389 void _mm_write_I_SLONG(SLONG data,MWRITER* writer)
390 {
391         _mm_write_I_ULONG((ULONG)data,writer);
392 }
393
394 void _mm_write_M_SWORDS(SWORD *buffer,int cnt,MWRITER* writer)
395 {
396         while(cnt-- > 0) _mm_write_M_SWORD(*(buffer++),writer);
397 }
398
399 void _mm_write_M_UWORDS(UWORD *buffer,int cnt,MWRITER* writer)
400 {
401         while(cnt-- > 0) _mm_write_M_UWORD(*(buffer++),writer);
402 }
403
404 void _mm_write_I_SWORDS(SWORD *buffer,int cnt,MWRITER* writer)
405 {
406         while(cnt-- > 0) _mm_write_I_SWORD(*(buffer++),writer);
407 }
408
409 void _mm_write_I_UWORDS(UWORD *buffer,int cnt,MWRITER* writer)
410 {
411         while(cnt-- > 0) _mm_write_I_UWORD(*(buffer++),writer);
412 }
413
414 void _mm_write_M_SLONGS(SLONG *buffer,int cnt,MWRITER* writer)
415 {
416         while(cnt-- > 0) _mm_write_M_SLONG(*(buffer++),writer);
417 }
418
419 void _mm_write_M_ULONGS(ULONG *buffer,int cnt,MWRITER* writer)
420 {
421         while(cnt-- > 0) _mm_write_M_ULONG(*(buffer++),writer);
422 }
423
424 void _mm_write_I_SLONGS(SLONG *buffer,int cnt,MWRITER* writer)
425 {
426         while(cnt-- > 0) _mm_write_I_SLONG(*(buffer++),writer);
427 }
428
429 void _mm_write_I_ULONGS(ULONG *buffer,int cnt,MWRITER* writer)
430 {
431         while(cnt-- > 0) _mm_write_I_ULONG(*(buffer++),writer);
432 }
433
434 /*========== Read functions */
435
436 BOOL _mm_read_string(CHAR* buffer,int cnt,MREADER* reader)
437 {
438         return reader->Read(reader,buffer,cnt);
439 }
440
441 UWORD _mm_read_M_UWORD(MREADER* reader)
442 {
443         UWORD result=((UWORD)_mm_read_UBYTE(reader))<<8;
444         result|=_mm_read_UBYTE(reader);
445         return result;
446 }
447
448 UWORD _mm_read_I_UWORD(MREADER* reader)
449 {
450         UWORD result=_mm_read_UBYTE(reader);
451         result|=((UWORD)_mm_read_UBYTE(reader))<<8;
452         return result;
453 }
454
455 ULONG _mm_read_M_ULONG(MREADER* reader)
456 {
457         ULONG result=((ULONG)_mm_read_M_UWORD(reader))<<16;
458         result|=_mm_read_M_UWORD(reader);
459         return result;
460 }
461
462 ULONG _mm_read_I_ULONG(MREADER* reader)
463 {
464         ULONG result=_mm_read_I_UWORD(reader);
465         result|=((ULONG)_mm_read_I_UWORD(reader))<<16;
466         return result;
467 }
468
469 SWORD _mm_read_M_SWORD(MREADER* reader)
470 {
471         return((SWORD)_mm_read_M_UWORD(reader));
472 }
473
474 SWORD _mm_read_I_SWORD(MREADER* reader)
475 {
476         return((SWORD)_mm_read_I_UWORD(reader));
477 }
478
479 SLONG _mm_read_M_SLONG(MREADER* reader)
480 {
481         return((SLONG)_mm_read_M_ULONG(reader));
482 }
483
484 SLONG _mm_read_I_SLONG(MREADER* reader)
485 {
486         return((SLONG)_mm_read_I_ULONG(reader));
487 }
488
489 BOOL _mm_read_M_SWORDS(SWORD *buffer,int cnt,MREADER* reader)
490 {
491         while(cnt-- > 0) *(buffer++)=_mm_read_M_SWORD(reader);
492         return !reader->Eof(reader);
493 }
494
495 BOOL _mm_read_M_UWORDS(UWORD *buffer,int cnt,MREADER* reader)
496 {
497         while(cnt-- > 0) *(buffer++)=_mm_read_M_UWORD(reader);
498         return !reader->Eof(reader);
499 }
500
501 BOOL _mm_read_I_SWORDS(SWORD *buffer,int cnt,MREADER* reader)
502 {
503         while(cnt-- > 0) *(buffer++)=_mm_read_I_SWORD(reader);
504         return !reader->Eof(reader);
505 }
506
507 BOOL _mm_read_I_UWORDS(UWORD *buffer,int cnt,MREADER* reader)
508 {
509         while(cnt-- > 0) *(buffer++)=_mm_read_I_UWORD(reader);
510         return !reader->Eof(reader);
511 }
512
513 BOOL _mm_read_M_SLONGS(SLONG *buffer,int cnt,MREADER* reader)
514 {
515         while(cnt-- > 0) *(buffer++)=_mm_read_M_SLONG(reader);
516         return !reader->Eof(reader);
517 }
518
519 BOOL _mm_read_M_ULONGS(ULONG *buffer,int cnt,MREADER* reader)
520 {
521         while(cnt-- > 0) *(buffer++)=_mm_read_M_ULONG(reader);
522         return !reader->Eof(reader);
523 }
524
525 BOOL _mm_read_I_SLONGS(SLONG *buffer,int cnt,MREADER* reader)
526 {
527         while(cnt-- > 0) *(buffer++)=_mm_read_I_SLONG(reader);
528         return !reader->Eof(reader);
529 }
530
531 BOOL _mm_read_I_ULONGS(ULONG *buffer,int cnt,MREADER* reader)
532 {
533         while(cnt-- > 0) *(buffer++)=_mm_read_I_ULONG(reader);
534         return !reader->Eof(reader);
535 }
536
537 /* ex:set ts=4: */