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