]> git.mxchange.org Git - simgear.git/blob - simgear/io/lowlevel.cxx
Added support for byte swapping based on endianess. Note the assumption is
[simgear.git] / simgear / io / lowlevel.cxx
1 // lowlevel.hxx -- routines to handle lowlevel compressed binary IO of
2 //                 various datatypes
3 //
4 // Shamelessly adapted from plib (plib.sourceforge.net) January 2001
5 //
6 // Original version Copyright (C) 2000  the plib team
7 // Local changes Copyright (C) 2000  Curtis L. Olson  - curt@flightgear.org
8 //
9 // This program is free software; you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation; either version 2 of the License, or
12 // (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 //
23 // $Id$
24 //
25
26 #include "lowlevel.hxx" 
27
28 static int  read_error = false ;
29 static int write_error = false ;
30
31 void sgClearReadError() { read_error = false; }
32 void sgClearWriteError() { write_error = false; }
33 int sgReadError() { return  read_error ; }
34 int sgWriteError() { return write_error ; }
35
36 static const int sgEndianTest = 1;
37 #define sgIsLittleEndian (*((char *) &sgEndianTest ) != 0)
38 #define sgIsBigEndian    (*((char *) &sgEndianTest ) == 0)
39
40 static inline void sgEndianSwap(unsigned short *x) {
41     *x =
42         (( *x >>  8 ) & 0x00FF ) | 
43         (( *x <<  8 ) & 0xFF00 ) ;
44 }
45   
46 static inline void sgEndianSwap(unsigned int *x) {
47     *x =
48         (( *x >> 24 ) & 0x000000FF ) | 
49         (( *x >>  8 ) & 0x0000FF00 ) | 
50         (( *x <<  8 ) & 0x00FF0000 ) | 
51         (( *x << 24 ) & 0xFF000000 ) ;
52 }
53   
54 static inline void sgEndianSwap(unsigned long long *x) {
55     *x =
56         (( *x >> 56 ) & 0x00000000000000FFULL ) | 
57         (( *x >> 40 ) & 0x000000000000FF00ULL ) | 
58         (( *x >> 24 ) & 0x0000000000FF0000ULL ) | 
59         (( *x >>  8 ) & 0x00000000FF000000ULL ) | 
60         (( *x <<  8 ) & 0x000000FF00000000ULL ) | 
61         (( *x << 24 ) & 0x0000FF0000000000ULL ) |
62         (( *x << 40 ) & 0x00FF000000000000ULL ) |
63         (( *x << 56 ) & 0xFF00000000000000ULL ) ;
64 }
65   
66 void sgReadChar ( gzFile fd, char *var )
67 {
68     if ( gzread ( fd, var, sizeof(char) ) != sizeof(char) ) {
69         read_error = true ;
70     }
71 }
72
73
74 void sgWriteChar ( gzFile fd, const char var )
75 {
76     if ( gzwrite ( fd, (void *)(&var), sizeof(char) ) != sizeof(char) ) {
77         write_error = true ;
78     }
79 }
80
81
82 void sgReadFloat ( gzFile fd, float *var )
83 {
84     if ( gzread ( fd, var, sizeof(float) ) != sizeof(float) ) {
85         read_error = true ;
86     }
87     if ( sgIsBigEndian ) {
88         sgEndianSwap( (unsigned int*)var);
89     }
90 }
91
92
93 void sgWriteFloat ( gzFile fd, const float var )
94 {
95     if ( sgIsBigEndian ) {
96         sgEndianSwap( (unsigned int*)&var);
97     }
98     if ( gzwrite ( fd, (void *)(&var), sizeof(float) ) != sizeof(float) ) {
99         write_error = true ;
100     }
101 }
102
103
104 void sgReadDouble ( gzFile fd, double *var )
105 {
106     if ( gzread ( fd, var, sizeof(double) ) != sizeof(double) ) {
107         read_error = true ;
108     }
109     if ( sgIsBigEndian ) {
110         sgEndianSwap( (unsigned long long*)var);
111     }
112 }
113
114
115 void sgWriteDouble ( gzFile fd, const double var )
116 {
117     if ( sgIsBigEndian ) {
118         sgEndianSwap( (unsigned long long*)&var);
119     }
120     if ( gzwrite ( fd, (void *)(&var), sizeof(double) ) != sizeof(double) ) {
121         write_error = true ;
122     }
123 }
124
125
126 void sgReadUInt ( gzFile fd, unsigned int *var )
127 {
128     if ( gzread ( fd, var, sizeof(unsigned int) ) != sizeof(unsigned int) ) {
129         read_error = true ;
130     }
131     if ( sgIsBigEndian ) {
132         sgEndianSwap( (unsigned int*)var);
133     }
134 }
135
136
137 void sgWriteUInt ( gzFile fd, const unsigned int var )
138 {
139     if ( sgIsBigEndian ) {
140         sgEndianSwap( (unsigned int*)&var);
141     }
142     if ( gzwrite ( fd, (void *)(&var), sizeof(unsigned int) )
143          != sizeof(unsigned int) )
144     {
145         write_error = true ;
146     }
147 }
148
149
150 void sgReadInt ( gzFile fd, int *var )
151 {
152     if ( gzread ( fd, var, sizeof(int) ) != sizeof(int) ) {
153         read_error = true ;
154     }
155     if ( sgIsBigEndian ) {
156         sgEndianSwap( (unsigned int*)var);
157     }
158 }
159
160
161 void sgWriteInt ( gzFile fd, const int var )
162 {
163     if ( sgIsBigEndian ) {
164         sgEndianSwap( (unsigned int*)&var);
165     }
166     if ( gzwrite ( fd, (void *)(&var), sizeof(int) ) != sizeof(int) ) {
167         write_error = true ;
168     }
169 }
170
171
172 void sgReadLong ( gzFile fd, long int *var )
173 {
174     if ( gzread ( fd, var, sizeof(long int) ) != sizeof(long int) ) {
175         read_error = true ;
176     }
177     if ( sgIsBigEndian ) {
178         sgEndianSwap( (unsigned int*)var);
179     }
180 }
181
182
183 void sgWriteLong ( gzFile fd, const long int var )
184 {
185     if ( sgIsBigEndian ) {
186         sgEndianSwap( (unsigned int*)&var);
187     }
188     if ( gzwrite ( fd, (void *)(&var), sizeof(long int) )
189          != sizeof(long int) )
190     {
191         write_error = true ;
192     }
193 }
194
195
196 void sgReadLongLong ( gzFile fd, long long int *var )
197 {
198     if ( gzread ( fd, var, sizeof(long long int) ) != sizeof(long long int) ) {
199         read_error = true ;
200     }
201     if ( sgIsBigEndian ) {
202         sgEndianSwap( (unsigned long long int*)var);
203     }
204 }
205
206
207 void sgWriteLongLong ( gzFile fd, const long long int var )
208 {
209     if ( sgIsBigEndian ) {
210         sgEndianSwap( (unsigned long long*)&var);
211     }
212     if ( gzwrite ( fd, (void *)(&var), sizeof(long long int) )
213          != sizeof(long long int) )
214     {
215         write_error = true ;
216     }
217 }
218
219
220 void sgReadUShort ( gzFile fd, unsigned short *var )
221 {
222     if ( gzread ( fd, var, sizeof(unsigned short) ) != sizeof(unsigned short) ){
223         read_error = true ;
224     }
225     if ( sgIsBigEndian ) {
226         sgEndianSwap( (unsigned short int*)var);
227     }
228 }
229
230
231 void sgWriteUShort ( gzFile fd, const unsigned short var )
232 {
233     if ( sgIsBigEndian ) {
234         sgEndianSwap( (unsigned short*)&var);
235     }
236     if ( gzwrite ( fd, (void *)(&var), sizeof(unsigned short) )
237          != sizeof(unsigned short) )
238     {
239         write_error = true ;
240     }
241 }
242
243
244 void sgReadShort ( gzFile fd, short *var )
245 {
246     if ( gzread ( fd, var, sizeof(short) ) != sizeof(short) ) {
247         read_error = true ;
248     }
249     if ( sgIsBigEndian ) {
250         sgEndianSwap( (unsigned short int*)var);
251     }
252 }
253
254
255 void sgWriteShort ( gzFile fd, const short var )
256 {
257     if ( sgIsBigEndian ) {
258         sgEndianSwap( (unsigned short*)&var);
259     }
260     if ( gzwrite ( fd, (void *)(&var), sizeof(short) ) != sizeof(short) ) {
261         write_error = true ;
262     }
263 }
264
265
266 void sgReadFloat ( gzFile fd, const unsigned int n, float *var )
267 {
268     if ( gzread ( fd, var, sizeof(float) * n ) != (int)(sizeof(float) * n) ) {
269         read_error = true ;
270     }
271     if ( sgIsBigEndian ) {
272         for ( unsigned int i = 0; i < n; ++i ) {
273             sgEndianSwap( (unsigned int*)var++);
274         }
275     }
276 }
277
278
279 void sgWriteFloat ( gzFile fd, const unsigned int n, const float *var )
280 {
281     if ( sgIsBigEndian ) {
282         float *swab = new float[n];
283         float *ptr = swab;
284         memcpy( swab, var, sizeof(float) * n );
285         for ( unsigned int i = 0; i < n; ++i ) {
286             sgEndianSwap( (unsigned int*)ptr++);
287         }
288         var = swab;
289     }
290     if ( gzwrite ( fd, (void *)var, sizeof(float) * n )
291          != (int)(sizeof(float) * n) )
292     {
293         write_error = true ;
294     }
295 }
296
297 void sgReadDouble ( gzFile fd, const unsigned int n, double *var )
298 {
299     if ( gzread ( fd, var, sizeof(double) * n ) != (int)(sizeof(double) * n) ) {
300         read_error = true ;
301     }
302     if ( sgIsBigEndian ) {
303         for ( unsigned int i = 0; i < n; ++i ) {
304             sgEndianSwap( (unsigned long long*)var++);
305         }
306     }
307 }
308
309
310 void sgWriteDouble ( gzFile fd, const unsigned int n, const double *var )
311 {
312     if ( sgIsBigEndian ) {
313         double *swab = new double[n];
314         double *ptr = swab;
315         memcpy( swab, var, sizeof(double) * n );
316         for ( unsigned int i = 0; i < n; ++i ) {
317             sgEndianSwap( (unsigned long long*)ptr++);
318         }
319         var = swab;
320     }
321     if ( gzwrite ( fd, (void *)var, sizeof(double) * n )
322          != (int)(sizeof(double) * n) )
323     {
324         write_error = true ;
325     }
326 }
327
328 void sgReadBytes ( gzFile fd, const unsigned int n, void *var ) 
329 {
330     if ( n == 0) return;
331     if ( gzread ( fd, var, n ) != (int)n ) {
332         read_error = true ;
333     }
334 }
335
336 void sgWriteBytes ( gzFile fd, const unsigned int n, const void *var ) 
337 {
338     if ( n == 0) return;
339     if ( gzwrite ( fd, (void *)var, n ) != (int)n ) {
340         write_error = true ;
341     }
342 }
343
344
345 void sgReadUShort ( gzFile fd, const unsigned int n, unsigned short *var )
346 {
347     if ( gzread ( fd, var, sizeof(unsigned short) * n )
348          != (int)(sizeof(unsigned short) * n) )
349     {
350         read_error = true ;
351     }
352     if ( sgIsBigEndian ) {
353         for ( unsigned int i = 0; i < n; ++i ) {
354             sgEndianSwap( (unsigned short int*)var++);
355         }
356     }
357 }
358
359
360 void sgWriteUShort ( gzFile fd, const unsigned int n, const unsigned short *var )
361 {
362     if ( sgIsBigEndian ) {
363         unsigned short *swab = new unsigned short[n];
364         unsigned short *ptr = swab;
365         memcpy( swab, var, sizeof(unsigned short) * n );
366         for ( unsigned int i = 0; i < n; ++i ) {
367             sgEndianSwap( (unsigned short*)ptr++);
368         }
369         var = swab;
370     }
371     if ( gzwrite ( fd, (void *)var, sizeof(unsigned short) * n )
372          != (int)(sizeof(unsigned short) * n) )
373     {
374         write_error = true ;
375     }
376 }
377
378
379
380 void sgReadShort ( gzFile fd, const unsigned int n, short *var )
381 {
382     if ( gzread ( fd, var, sizeof(short) * n )
383          != (int)(sizeof(short) * n) )
384     {
385         read_error = true ;
386     }
387     if ( sgIsBigEndian ) {
388         for ( unsigned int i = 0; i < n; ++i ) {
389             sgEndianSwap( (unsigned short int*)var++);
390         }
391     }
392 }
393
394
395 void sgWriteShort ( gzFile fd, const unsigned int n, const short *var )
396 {
397     if ( sgIsBigEndian ) {
398         short *swab = new short[n];
399         short *ptr = swab;
400         memcpy( swab, var, sizeof(short) * n );
401         for ( unsigned int i = 0; i < n; ++i ) {
402             sgEndianSwap( (unsigned short*)ptr++);
403         }
404         var = swab;
405     }
406     if ( gzwrite ( fd, (void *)var, sizeof(short) * n )
407          != (int)(sizeof(short) * n) )
408     {
409         write_error = true ;
410     }
411 }
412
413
414 void sgReadUInt ( gzFile fd, const unsigned int n, unsigned int *var )
415 {
416     if ( gzread ( fd, var, sizeof(unsigned int) * n )
417          != (int)(sizeof(unsigned int) * n) )
418     {
419         read_error = true ;
420     }
421     if ( sgIsBigEndian ) {
422         for ( unsigned int i = 0; i < n; ++i ) {
423             sgEndianSwap( (unsigned int*)var++);
424         }
425     }
426 }
427
428
429 void sgWriteUInt ( gzFile fd, const unsigned int n, const unsigned int *var )
430 {
431     if ( sgIsBigEndian ) {
432         unsigned int *swab = new unsigned int[n];
433         unsigned int *ptr = swab;
434         memcpy( swab, var, sizeof(unsigned int) * n );
435         for ( unsigned int i = 0; i < n; ++i ) {
436             sgEndianSwap( (unsigned int*)ptr++);
437         }
438         var = swab;
439     }
440     if ( gzwrite ( fd, (void *)var, sizeof(unsigned int) * n )
441          != (int)(sizeof(unsigned int) * n) )
442     {
443         write_error = true ;
444     }
445 }
446
447
448
449 void sgReadInt ( gzFile fd, const unsigned int n, int *var )
450 {
451     if ( gzread ( fd, var, sizeof(int) * n )
452          != (int)(sizeof(int) * n) )
453     {
454         read_error = true ;
455     }
456     if ( sgIsBigEndian ) {
457         for ( unsigned int i = 0; i < n; ++i ) {
458             sgEndianSwap( (unsigned int*)var++);
459         }
460     }
461 }
462
463
464 void sgWriteInt ( gzFile fd, const unsigned int n, const int *var )
465 {
466     if ( sgIsBigEndian ) {
467         int *swab = new int[n];
468         int *ptr = swab;
469         memcpy( swab, var, sizeof(int) * n );
470         for ( unsigned int i = 0; i < n; ++i ) {
471             sgEndianSwap( (unsigned int*)ptr++);
472         }
473         var = swab;
474     }
475     if ( gzwrite ( fd, (void *)var, sizeof(int) * n )
476          != (int)(sizeof(int) * n) )
477     {
478         write_error = true ;
479     }
480 }
481
482
483
484 #define MAX_ENTITY_NAME_LENGTH 1024
485
486 void sgReadString ( gzFile fd, char **var )
487 {
488     int i ;
489     char s [ MAX_ENTITY_NAME_LENGTH ] ;
490
491     for ( i = 0 ; i < MAX_ENTITY_NAME_LENGTH ; i++ ) {
492         int c = gzgetc ( fd ) ;
493         s [ i ] = c ;
494
495         if ( c == '\0' )
496             break ;
497     }
498
499     if ( i >= MAX_ENTITY_NAME_LENGTH-1 )
500         s [ MAX_ENTITY_NAME_LENGTH-1 ] = '\0' ;
501
502
503     if ( s[0] == '\0' )
504         *var = NULL ;
505     else {
506         *var = new char [ strlen(s)+1 ] ;
507         strcpy ( *var, s ) ;
508     }
509 }
510
511
512 void sgWriteString ( gzFile fd, const char *var )
513 {
514     if ( var != NULL ) {
515         if ( gzwrite ( fd, (void *)var, strlen(var) + 1 ) == 
516              (int)(strlen(var) + 1) )
517             return ;
518     } else {
519         gzputc( fd, 0 );
520     }
521 }
522
523
524 void sgReadVec2  ( gzFile fd, sgVec2 var ) { sgReadFloat  ( fd, 2, var ) ; }
525 void sgWriteVec2 ( gzFile fd, const sgVec2 var ) {
526     sgWriteFloat ( fd, 2, var ) ;
527 }
528
529 void sgReadVec3  ( gzFile fd, sgVec3 var ) { sgReadFloat  ( fd, 3, var ) ; }
530 void sgWriteVec3 ( gzFile fd, const sgVec3 var ) {
531     sgWriteFloat ( fd, 3, var ) ;
532 }
533
534 void sgReaddVec3  ( gzFile fd, sgdVec3 var ) { sgReadDouble  ( fd, 3, var ) ; }
535 void sgWritedVec3 ( gzFile fd, const sgdVec3 var ) {
536     sgWriteDouble ( fd, 3, var ) ;
537 }
538
539 void sgReadVec4  ( gzFile fd, sgVec4 var ) { sgReadFloat  ( fd, 4, var ) ; }
540 void sgWriteVec4 ( gzFile fd, const sgVec4 var ) {
541     sgWriteFloat ( fd, 4, var ) ;
542 }
543
544 void sgReadMat4  ( gzFile fd, sgMat4 var ) {
545     sgReadFloat  ( fd, 16, (float *)var ) ;
546 }
547 void sgWriteMat4 ( gzFile fd, const sgMat4 var ) {
548     sgWriteFloat ( fd, 16, (float *)var ) ;
549 }