added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / libs / lib3ds / io.c
1 /*
2  * The 3D Studio File Format Library
3  * Copyright (C) 1996-2001 by J.E. Hoffmann <je-h@gmx.net>
4  * All rights reserved.
5  *
6  * This program is  free  software;  you can redistribute it and/or modify it
7  * under the terms of the  GNU Lesser General Public License  as published by 
8  * the  Free Software Foundation;  either version 2.1 of the License,  or (at 
9  * your option) any later version.
10  *
11  * This  program  is  distributed in  the  hope that it will  be useful,  but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  * or  FITNESS FOR A  PARTICULAR PURPOSE.  See the  GNU Lesser General Public  
14  * License for more details.
15  *
16  * You should  have received  a copy of the GNU Lesser General Public License
17  * along with  this program;  if not, write to the  Free Software Foundation,
18  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  *
20  * $Id: io.c,v 1.3 2001/07/11 13:47:35 jeh Exp $
21  */
22 #define LIB3DS_EXPORT
23 #include <lib3ds/io.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27
28 /*!
29  * \defgroup io Binary Input/Ouput Abstraction Layer
30  *
31  * \author J.E. Hoffmann <je-h@gmx.net>
32  */
33
34
35 struct _Lib3dsIo {
36   void *self;
37   Lib3dsIoErrorFunc error_func;
38   Lib3dsIoSeekFunc seek_func;
39   Lib3dsIoTellFunc tell_func;
40   Lib3dsIoReadFunc read_func;
41   Lib3dsIoWriteFunc write_func;
42 };
43
44
45 Lib3dsIo* 
46 lib3ds_io_new(void *self, Lib3dsIoErrorFunc error_func, Lib3dsIoSeekFunc seek_func,
47   Lib3dsIoTellFunc tell_func, Lib3dsIoReadFunc read_func, Lib3dsIoWriteFunc write_func)
48 {
49   Lib3dsIo *io = calloc(sizeof(Lib3dsIo),1);
50   ASSERT(io);
51   if (!io) {
52     return 0;
53   }
54
55   io->self = self;
56   io->error_func = error_func;
57   io->seek_func = seek_func;
58   io->tell_func = tell_func;
59   io->read_func = read_func;
60   io->write_func = write_func;
61
62   return io;
63 }
64
65
66 void 
67 lib3ds_io_free(Lib3dsIo *io)
68 {
69   ASSERT(io);
70   if (!io) {
71     return;
72   }
73   free(io);
74 }
75
76
77 Lib3dsBool
78 lib3ds_io_error(Lib3dsIo *io)
79 {
80   ASSERT(io);
81   if (!io || !io->error_func) {
82     return 0;
83   }
84   return (*io->error_func)(io->self);
85 }
86
87
88 long 
89 lib3ds_io_seek(Lib3dsIo *io, long offset, Lib3dsIoSeek origin)
90 {
91   ASSERT(io);
92   if (!io || !io->seek_func) {
93     return 0;
94   }
95   return (*io->seek_func)(io->self, offset, origin);
96 }
97
98
99 long 
100 lib3ds_io_tell(Lib3dsIo *io)
101 {
102   ASSERT(io);
103   if (!io || !io->tell_func) {
104     return 0;
105   }
106   return (*io->tell_func)(io->self);
107 }
108
109
110 int 
111 lib3ds_io_read(Lib3dsIo *io, Lib3dsByte *buffer, int size)
112 {
113   ASSERT(io);
114   if (!io || !io->read_func) {
115     return 0;
116   }
117   return (*io->read_func)(io->self, buffer, size);
118 }
119
120
121 int 
122 lib3ds_io_write(Lib3dsIo *io, const Lib3dsByte *buffer, int size)
123 {
124   ASSERT(io);
125   if (!io || !io->write_func) {
126     return 0;
127   }
128   return (*io->write_func)(io->self, buffer, size);
129 }
130
131
132 /*!
133  * \ingroup io
134  *
135  * Read a byte from a file stream.  
136  */
137 Lib3dsByte
138 lib3ds_io_read_byte(Lib3dsIo *io)
139 {
140   Lib3dsByte b;
141
142   ASSERT(io);
143   lib3ds_io_read(io, &b, 1);
144   return(b);
145 }
146
147
148 /**
149  * Read a word from a file stream in little endian format.   
150  */
151 Lib3dsWord
152 lib3ds_io_read_word(Lib3dsIo *io)
153 {
154   Lib3dsByte b[2];
155   Lib3dsWord w;
156
157   ASSERT(io);
158   lib3ds_io_read(io, b, 2);
159   w=((Lib3dsWord)b[1] << 8) |
160     ((Lib3dsWord)b[0]);
161   return(w);
162 }
163
164
165 /*!
166  * \ingroup io
167  *
168  * Read a dword from file a stream in little endian format.   
169  */
170 Lib3dsDword
171 lib3ds_io_read_dword(Lib3dsIo *io)
172 {
173   Lib3dsByte b[4];
174   Lib3dsDword d;        
175                          
176   ASSERT(io);
177   lib3ds_io_read(io, b, 4);
178   d=((Lib3dsDword)b[3] << 24) |
179     ((Lib3dsDword)b[2] << 16) |
180     ((Lib3dsDword)b[1] << 8) |
181     ((Lib3dsDword)b[0]);
182   return(d);
183 }
184
185
186 /*!
187  * \ingroup io
188  *
189  * Read a signed byte from a file stream.   
190  */
191 Lib3dsIntb
192 lib3ds_io_read_intb(Lib3dsIo *io)
193 {
194   Lib3dsIntb b;
195
196   ASSERT(io);
197   lib3ds_io_read(io, (Lib3dsByte*)&b, 1);
198   return(b);
199 }
200
201
202 /*!
203  * \ingroup io
204  *
205  * Read a signed word from a file stream in little endian format.   
206  */
207 Lib3dsIntw
208 lib3ds_io_read_intw(Lib3dsIo *io)
209 {
210   Lib3dsByte b[2];
211   Lib3dsWord w;
212
213   ASSERT(io);
214   lib3ds_io_read(io, b, 2);
215   w=((Lib3dsWord)b[1] << 8) |
216     ((Lib3dsWord)b[0]);
217   return((Lib3dsIntw)w);
218 }
219
220
221 /*!
222  * \ingroup io
223  *
224  * Read a signed dword a from file stream in little endian format.   
225  */
226 Lib3dsIntd
227 lib3ds_io_read_intd(Lib3dsIo *io)
228 {
229   Lib3dsByte b[4];
230   Lib3dsDword d;        
231                          
232   ASSERT(io);
233   lib3ds_io_read(io, b, 4);
234   d=((Lib3dsDword)b[3] << 24) |
235     ((Lib3dsDword)b[2] << 16) |
236     ((Lib3dsDword)b[1] << 8) |
237     ((Lib3dsDword)b[0]);
238   return((Lib3dsIntd)d);
239 }
240
241
242 /*!
243  * \ingroup io
244  *
245  * Read a float from a file stream in little endian format.   
246  */
247 Lib3dsFloat
248 lib3ds_io_read_float(Lib3dsIo *io)
249 {
250   Lib3dsByte b[4];
251   Lib3dsDword d;
252
253   ASSERT(io);
254   lib3ds_io_read(io, b, 4);
255   d=((Lib3dsDword)b[3] << 24) |
256     ((Lib3dsDword)b[2] << 16) |
257     ((Lib3dsDword)b[1] << 8) |
258     ((Lib3dsDword)b[0]);
259   return(*((Lib3dsFloat*)&d));
260 }
261
262
263 /*!
264  * \ingroup io
265  * \ingroup vector
266  *
267  * Read a vector from a file stream in little endian format.   
268  *
269  * \param io IO input handle. 
270  * \param v  The vector to store the data. 
271  */
272 Lib3dsBool
273 lib3ds_io_read_vector(Lib3dsIo *io, Lib3dsVector v)
274 {
275   ASSERT(io);
276   
277   v[0]=lib3ds_io_read_float(io);
278   v[1]=lib3ds_io_read_float(io);
279   v[2]=lib3ds_io_read_float(io);
280
281   return(!lib3ds_io_error(io));
282 }
283
284
285 /*!
286  * \ingroup io
287  */
288 Lib3dsBool
289 lib3ds_io_read_rgb(Lib3dsIo *io, Lib3dsRgb rgb)
290 {
291   ASSERT(io);
292
293   rgb[0]=lib3ds_io_read_float(io);
294   rgb[1]=lib3ds_io_read_float(io);
295   rgb[2]=lib3ds_io_read_float(io);
296
297   return(!lib3ds_io_error(io));
298 }
299
300
301 /*!
302  * \ingroup io
303  *
304  * Read a zero-terminated string from a file stream.
305  *
306  * \param io      IO input handle. 
307  * \param s       The buffer to store the read string.
308  * \param buflen  Buffer length.
309  *
310  * \return        True on success, False otherwise.
311  */
312 Lib3dsBool
313 lib3ds_io_read_string(Lib3dsIo *io, char *s, int buflen)
314 {
315   char c;
316   int k=0;
317
318   ASSERT(io);
319   for (;;) {
320     if (lib3ds_io_read(io, (Lib3dsByte*)&c, 1)!=1) {
321       return LIB3DS_FALSE;
322     }
323     *s++ = c;
324     if (!c) {
325       break;
326     }
327     ++k;
328     if (k>=buflen) {
329       return(LIB3DS_FALSE);
330     }
331   }
332
333   return(!lib3ds_io_error(io));
334 }
335
336
337 /*!
338  * \ingroup io
339  *
340  * Writes a byte into a file stream.
341  */
342 Lib3dsBool
343 lib3ds_io_write_byte(Lib3dsIo *io, Lib3dsByte b)
344 {
345   ASSERT(io);
346   if (lib3ds_io_write(io, &b, 1)!=1) {
347     return(LIB3DS_FALSE);
348   }
349   return(LIB3DS_TRUE);
350 }
351
352
353 /*!
354  * \ingroup io
355  *
356  * Writes a word into a little endian file stream.
357  */
358 Lib3dsBool
359 lib3ds_io_write_word(Lib3dsIo *io, Lib3dsWord w)
360 {
361   Lib3dsByte b[2];
362
363   ASSERT(io);
364   b[1]=((Lib3dsWord)w & 0xFF00) >> 8;
365   b[0]=((Lib3dsWord)w & 0x00FF);
366   if (lib3ds_io_write(io, b, 2)!=2) {
367     return(LIB3DS_FALSE);
368   }
369   return(LIB3DS_TRUE);
370 }
371
372
373 /*!
374  * \ingroup io
375  *
376  * Writes a dword into a little endian file stream.
377  */
378 Lib3dsBool
379 lib3ds_io_write_dword(Lib3dsIo *io, Lib3dsDword d)
380 {
381   Lib3dsByte b[4];
382
383   ASSERT(io);
384   b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24);
385   b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16);
386   b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8);
387   b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF));
388   if (lib3ds_io_write(io, b, 4)!=4) {
389     return(LIB3DS_FALSE);
390   }
391   return(LIB3DS_TRUE);
392 }
393
394
395 /*!
396  * \ingroup io
397  *
398  * Writes a signed byte in a file stream.
399  */
400 Lib3dsBool
401 lib3ds_io_write_intb(Lib3dsIo *io, Lib3dsIntb b)
402 {
403   ASSERT(io);
404   if (lib3ds_io_write(io, (Lib3dsByte*)&b, 1)!=1) {
405     return(LIB3DS_FALSE);
406   }
407   return(LIB3DS_TRUE);
408 }
409
410
411 /*!
412  * \ingroup io
413  *
414  * Writes a signed word into a little endian file stream.
415  */
416 Lib3dsBool
417 lib3ds_io_write_intw(Lib3dsIo *io, Lib3dsIntw w)
418 {
419   Lib3dsByte b[2];
420
421   ASSERT(io);
422   b[1]=((Lib3dsWord)w & 0xFF00) >> 8;
423   b[0]=((Lib3dsWord)w & 0x00FF);
424   if (lib3ds_io_write(io, b, 2)!=2) {
425     return(LIB3DS_FALSE);
426   }
427   return(LIB3DS_TRUE);
428 }
429
430
431 /*!
432  * \ingroup io
433  *
434  * Writes a signed dword into a little endian file stream.
435  */
436 Lib3dsBool
437 lib3ds_io_write_intd(Lib3dsIo *io, Lib3dsIntd d)
438 {
439   Lib3dsByte b[4];
440
441   ASSERT(io);
442   b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24);
443   b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16);
444   b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8);
445   b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF));
446   if (lib3ds_io_write(io, b, 4)!=4) {
447     return(LIB3DS_FALSE);
448   }
449   return(LIB3DS_TRUE);
450 }
451
452
453 /*!
454  * \ingroup io
455  *
456  * Writes a float into a little endian file stream.
457  */
458 Lib3dsBool
459 lib3ds_io_write_float(Lib3dsIo *io, Lib3dsFloat l)
460 {
461   Lib3dsByte b[4];
462   Lib3dsDword d;
463
464   ASSERT(io);
465   d=*((Lib3dsDword*)&l);
466   b[3]=(Lib3dsByte)(((Lib3dsDword)d & 0xFF000000) >> 24);
467   b[2]=(Lib3dsByte)(((Lib3dsDword)d & 0x00FF0000) >> 16);
468   b[1]=(Lib3dsByte)(((Lib3dsDword)d & 0x0000FF00) >> 8);
469   b[0]=(Lib3dsByte)(((Lib3dsDword)d & 0x000000FF));
470   if (lib3ds_io_write(io, b, 4)!=4) {
471     return(LIB3DS_FALSE);
472   }
473   return(LIB3DS_TRUE);
474 }
475
476
477 /*!
478  * \ingroup io
479  * \ingroup vector
480  *
481  * Writes a vector into a file stream in little endian format.   
482  */
483 Lib3dsBool
484 lib3ds_io_write_vector(Lib3dsIo *io, Lib3dsVector v)
485 {
486   int i;
487   for (i=0; i<3; ++i) {
488     if (!lib3ds_io_write_float(io, v[i])) {
489       return(LIB3DS_FALSE);
490     }
491   }
492   return(LIB3DS_TRUE);
493 }
494
495
496 /*!
497  * \ingroup io
498  */
499 Lib3dsBool
500 lib3ds_io_write_rgb(Lib3dsIo *io, Lib3dsRgb rgb)
501 {
502   int i;
503   for (i=0; i<3; ++i) {
504     if (!lib3ds_io_write_float(io, rgb[i])) {
505       return(LIB3DS_FALSE);
506     }
507   }
508   return(LIB3DS_TRUE);
509 }
510
511
512 /*!
513  * \ingroup io
514  *
515  * Writes a zero-terminated string into a file stream.
516  */
517 Lib3dsBool
518 lib3ds_io_write_string(Lib3dsIo *io, const char *s)
519 {
520   ASSERT(s);
521   ASSERT(io);
522   lib3ds_io_write(io, (const Lib3dsByte*)s, strlen(s)+1);
523   return(!lib3ds_io_error(io));
524 }