]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/picomodel/lwo/lwio.c
Merge commit 'b017c473e86330d5908858b8add1b16674b0a1a8' into garux-merge
[xonotic/netradiant.git] / libs / picomodel / lwo / lwio.c
1 /*
2    ======================================================================
3    lwio.c
4
5    Functions for reading basic LWO2 data types.
6
7    Ernie Wright  17 Sep 00
8    ====================================================================== */
9
10 #include "../picointernal.h"
11 #include "lwo2.h"
12 #include <limits.h>
13 #include "globaldefs.h"
14
15
16 /*
17    ======================================================================
18    flen
19
20    This accumulates a count of the number of bytes read.  Callers can set
21    it at the beginning of a sequence of reads and then retrieve it to get
22    the number of bytes actually read.  If one of the I/O functions fails,
23    flen is set to an error code, after which the I/O functions ignore
24    read requests until flen is reset.
25    ====================================================================== */
26
27 const int FLEN_ERROR = INT_MIN;
28
29 static int flen;
30
31 void set_flen( int i ) { flen = i; }
32
33 int get_flen( void ) { return flen; }
34
35
36 #if !GDEF_ARCH_ENDIAN_BIG
37 /*
38    =====================================================================
39    revbytes()
40
41    Reverses byte order in place.
42
43    INPUTS
44    bp       bytes to reverse
45    elsize   size of the underlying data type
46    elcount  number of elements to swap
47
48    RESULTS
49    Reverses the byte order in each of elcount elements.
50
51    This only needs to be defined on little-endian platforms, most
52    notably Windows.  lwo2.h replaces this with a #define on big-endian
53    platforms.
54    ===================================================================== */
55
56 void revbytes( void *bp, int elsize, int elcount ){
57         register unsigned char *p, *q;
58
59         p = ( unsigned char * ) bp;
60
61         if ( elsize == 2 ) {
62                 q = p + 1;
63                 while ( elcount-- ) {
64                         *p ^= *q;
65                         *q ^= *p;
66                         *p ^= *q;
67                         p += 2;
68                         q += 2;
69                 }
70                 return;
71         }
72
73         while ( elcount-- ) {
74                 q = p + elsize - 1;
75                 while ( p < q ) {
76                         *p ^= *q;
77                         *q ^= *p;
78                         *p ^= *q;
79                         ++p;
80                         --q;
81                 }
82                 p += elsize >> 1;
83         }
84 }
85 #endif
86
87
88 void *getbytes( picoMemStream_t *fp, int size ){
89         void *data;
90
91         if ( flen == FLEN_ERROR ) {
92                 return NULL;
93         }
94         if ( size < 0 ) {
95                 flen = FLEN_ERROR;
96                 return NULL;
97         }
98         data = _pico_alloc( size );
99         if ( !data ) {
100                 flen = FLEN_ERROR;
101                 return NULL;
102         }
103         if ( 1 != _pico_memstream_read( fp, data, size ) ) {
104                 flen = FLEN_ERROR;
105                 _pico_free( data );
106                 return NULL;
107         }
108
109         flen += size;
110         return data;
111 }
112
113
114 void skipbytes( picoMemStream_t *fp, int n ){
115         if ( flen == FLEN_ERROR ) {
116                 return;
117         }
118         if ( _pico_memstream_seek( fp, n, PICO_SEEK_CUR ) ) {
119                 flen = FLEN_ERROR;
120         }
121         else{
122                 flen += n;
123         }
124 }
125
126
127 int getI1( picoMemStream_t *fp ){
128         int i;
129
130         if ( flen == FLEN_ERROR ) {
131                 return 0;
132         }
133         i = _pico_memstream_getc( fp );
134         if ( i < 0 ) {
135                 flen = FLEN_ERROR;
136                 return 0;
137         }
138         if ( i > 127 ) {
139                 i -= 256;
140         }
141         flen += 1;
142         return i;
143 }
144
145
146 short getI2( picoMemStream_t *fp ){
147         short i;
148
149         if ( flen == FLEN_ERROR ) {
150                 return 0;
151         }
152         if ( 1 != _pico_memstream_read( fp, &i, 2 ) ) {
153                 flen = FLEN_ERROR;
154                 return 0;
155         }
156         revbytes( &i, 2, 1 );
157         flen += 2;
158         return i;
159 }
160
161
162 int getI4( picoMemStream_t *fp ){
163         int i;
164
165         if ( flen == FLEN_ERROR ) {
166                 return 0;
167         }
168         if ( 1 != _pico_memstream_read( fp, &i, 4 ) ) {
169                 flen = FLEN_ERROR;
170                 return 0;
171         }
172         revbytes( &i, 4, 1 );
173         flen += 4;
174         return i;
175 }
176
177
178 unsigned char getU1( picoMemStream_t *fp ){
179         int i;
180
181         if ( flen == FLEN_ERROR ) {
182                 return 0;
183         }
184         i = _pico_memstream_getc( fp );
185         if ( i < 0 ) {
186                 flen = FLEN_ERROR;
187                 return 0;
188         }
189         flen += 1;
190         return i;
191 }
192
193
194 unsigned short getU2( picoMemStream_t *fp ){
195         unsigned short i;
196
197         if ( flen == FLEN_ERROR ) {
198                 return 0;
199         }
200         if ( 1 != _pico_memstream_read( fp, &i, 2 ) ) {
201                 flen = FLEN_ERROR;
202                 return 0;
203         }
204         revbytes( &i, 2, 1 );
205         flen += 2;
206         return i;
207 }
208
209
210 unsigned int getU4( picoMemStream_t *fp ){
211         unsigned int i;
212
213         if ( flen == FLEN_ERROR ) {
214                 return 0;
215         }
216         if ( 1 != _pico_memstream_read( fp, &i, 4 ) ) {
217                 flen = FLEN_ERROR;
218                 return 0;
219         }
220         revbytes( &i, 4, 1 );
221         flen += 4;
222         return i;
223 }
224
225
226 int getVX( picoMemStream_t *fp ){
227         int i, c;
228
229         if ( flen == FLEN_ERROR ) {
230                 return 0;
231         }
232
233         c = _pico_memstream_getc( fp );
234         if ( c != 0xFF ) {
235                 i = c << 8;
236                 c = _pico_memstream_getc( fp );
237                 i |= c;
238                 flen += 2;
239         }
240         else {
241                 c = _pico_memstream_getc( fp );
242                 i = c << 16;
243                 c = _pico_memstream_getc( fp );
244                 i |= c << 8;
245                 c = _pico_memstream_getc( fp );
246                 i |= c;
247                 flen += 4;
248         }
249
250         if ( _pico_memstream_error( fp ) ) {
251                 flen = FLEN_ERROR;
252                 return 0;
253         }
254         return i;
255 }
256
257
258 float getF4( picoMemStream_t *fp ){
259         float f;
260
261         if ( flen == FLEN_ERROR ) {
262                 return 0.0f;
263         }
264         if ( 1 != _pico_memstream_read( fp, &f, 4 ) ) {
265                 flen = FLEN_ERROR;
266                 return 0.0f;
267         }
268         revbytes( &f, 4, 1 );
269         flen += 4;
270         return f;
271 }
272
273
274 char *getS0( picoMemStream_t *fp ){
275         char *s;
276         int i, c, len, pos;
277
278         if ( flen == FLEN_ERROR ) {
279                 return NULL;
280         }
281
282         pos = _pico_memstream_tell( fp );
283         for ( i = 1; ; i++ ) {
284                 c = _pico_memstream_getc( fp );
285                 if ( c <= 0 ) {
286                         break;
287                 }
288         }
289         if ( c < 0 ) {
290                 flen = FLEN_ERROR;
291                 return NULL;
292         }
293
294         if ( i == 1 ) {
295                 if ( _pico_memstream_seek( fp, pos + 2, PICO_SEEK_SET ) ) {
296                         flen = FLEN_ERROR;
297                 }
298                 else{
299                         flen += 2;
300                 }
301                 return NULL;
302         }
303
304         len = i + ( i & 1 );
305         s = _pico_alloc( len );
306         if ( !s ) {
307                 flen = FLEN_ERROR;
308                 return NULL;
309         }
310
311         if ( _pico_memstream_seek( fp, pos, PICO_SEEK_SET ) ) {
312                 flen = FLEN_ERROR;
313                 return NULL;
314         }
315         if ( 1 != _pico_memstream_read( fp, s, len ) ) {
316                 flen = FLEN_ERROR;
317                 return NULL;
318         }
319
320         flen += len;
321         return s;
322 }
323
324
325 int sgetI1( unsigned char **bp ){
326         int i;
327
328         if ( flen == FLEN_ERROR ) {
329                 return 0;
330         }
331         i = **bp;
332         if ( i > 127 ) {
333                 i -= 256;
334         }
335         flen += 1;
336         ( *bp )++;
337         return i;
338 }
339
340
341 short sgetI2( unsigned char **bp ){
342         short i;
343
344         if ( flen == FLEN_ERROR ) {
345                 return 0;
346         }
347         memcpy( &i, *bp, 2 );
348         revbytes( &i, 2, 1 );
349         flen += 2;
350         *bp += 2;
351         return i;
352 }
353
354
355 int sgetI4( unsigned char **bp ){
356         int i;
357
358         if ( flen == FLEN_ERROR ) {
359                 return 0;
360         }
361         memcpy( &i, *bp, 4 );
362         revbytes( &i, 4, 1 );
363         flen += 4;
364         *bp += 4;
365         return i;
366 }
367
368
369 unsigned char sgetU1( unsigned char **bp ){
370         unsigned char c;
371
372         if ( flen == FLEN_ERROR ) {
373                 return 0;
374         }
375         c = **bp;
376         flen += 1;
377         ( *bp )++;
378         return c;
379 }
380
381
382 unsigned short sgetU2( unsigned char **bp ){
383         unsigned char *buf = *bp;
384         unsigned short i;
385
386         if ( flen == FLEN_ERROR ) {
387                 return 0;
388         }
389         i = ( buf[ 0 ] << 8 ) | buf[ 1 ];
390         flen += 2;
391         *bp += 2;
392         return i;
393 }
394
395
396 unsigned int sgetU4( unsigned char **bp ){
397         unsigned int i;
398
399         if ( flen == FLEN_ERROR ) {
400                 return 0;
401         }
402         memcpy( &i, *bp, 4 );
403         revbytes( &i, 4, 1 );
404         flen += 4;
405         *bp += 4;
406         return i;
407 }
408
409
410 int sgetVX( unsigned char **bp ){
411         unsigned char *buf = *bp;
412         int i;
413
414         if ( flen == FLEN_ERROR ) {
415                 return 0;
416         }
417
418         if ( buf[ 0 ] != 0xFF ) {
419                 i = buf[ 0 ] << 8 | buf[ 1 ];
420                 flen += 2;
421                 *bp += 2;
422         }
423         else {
424                 i = ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ];
425                 flen += 4;
426                 *bp += 4;
427         }
428         return i;
429 }
430
431
432 float sgetF4( unsigned char **bp ){
433         float f;
434
435         if ( flen == FLEN_ERROR ) {
436                 return 0.0f;
437         }
438         memcpy( &f, *bp, 4 );
439         revbytes( &f, 4, 1 );
440         flen += 4;
441         *bp += 4;
442         return f;
443 }
444
445
446 char *sgetS0( unsigned char **bp ){
447         char *s;
448         unsigned char *buf = *bp;
449         int len;
450
451         if ( flen == FLEN_ERROR ) {
452                 return NULL;
453         }
454
455         len = strlen( (const char *) buf ) + 1;
456         if ( len == 1 ) {
457                 flen += 2;
458                 *bp += 2;
459                 return NULL;
460         }
461         len += len & 1;
462         s = _pico_alloc( len );
463         if ( !s ) {
464                 flen = FLEN_ERROR;
465                 return NULL;
466         }
467
468         memcpy( s, buf, len );
469         flen += len;
470         *bp += len;
471         return s;
472 }