1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // *       Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // *       Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // *       Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34 
35 
36 #ifndef INCLUDED_IMF_XDR_H
37 #define INCLUDED_IMF_XDR_H
38 
39 //----------------------------------------------------------------------------
40 //
41 //	Xdr -- routines to convert data between the machine's native
42 //	format and a machine-independent external data representation:
43 //
44 //	    write<R> (T &o, S v);	converts a value, v, of type S
45 //					into a machine-independent
46 //					representation and stores the
47 //					result in an output buffer, o.
48 //
49 //	    read<R> (T &i, S &v);	reads the machine-independent
50 //					representation of a value of type
51 //					S from input buffer i, converts
52 //					the value into the machine's native
53 //					representation, and stores the result
54 //					in v.
55 //
56 //	    size<S>();			returns the size, in bytes, of the
57 //					machine-independent representation
58 //					of an object of type S.
59 //
60 //	The write() and read() routines are templates; data can be written
61 //	to and read from any output or input buffer type T for which a helper
62 //	class, R, exits.  Class R must define a method to store a char array
63 //	in a T, and a method to read a char array from a T:
64 //
65 //	    struct R
66 //	    {
67 //	        static void
68 //	        writeChars (T &o, const char c[/*n*/], int n)
69 //	        {
70 //	            ... // Write c[0], c[1] ... c[n-1] to output buffer o.
71 //	        }
72 //
73 //	        static void
74 //	        readChars (T &i, char c[/*n*/], int n)
75 //	        {
76 //	            ... // Read n characters from input buffer i
77 //		        // and copy them to c[0], c[1] ... c[n-1].
78 //	        }
79 //	    };
80 //
81 //	Example - writing to and reading from iostreams:
82 //
83 //	    struct CharStreamIO
84 //	    {
85 //	        static void
86 //	        writeChars (ostream &os, const char c[], int n)
87 //	        {
88 //	            os.write (c, n);
89 //	        }
90 //
91 //	        static void
92 //	        readChars (istream &is, char c[], int n)
93 //	        {
94 //	            is.read (c, n);
95 //	        }
96 //	    };
97 //
98 //          ...
99 //
100 //	    Xdr::write<CharStreamIO> (os, 3);
101 //	    Xdr::write<CharStreamIO> (os, 5.0);
102 //
103 //----------------------------------------------------------------------------
104 
105 #include <ImfInt64.h>
106 #include "IexMathExc.h"
107 #include "half.h"
108 #include <limits.h>
109 
110 namespace Imf {
111 namespace Xdr {
112 
113 
114 //-------------------------------
115 // Write data to an output stream
116 //-------------------------------
117 
118 template <class S, class T>
119 void
120 write (T &out, bool v);
121 
122 template <class S, class T>
123 void
124 write (T &out, char v);
125 
126 template <class S, class T>
127 void
128 write (T &out, signed char v);
129 
130 template <class S, class T>
131 void
132 write (T &out, unsigned char v);
133 
134 template <class S, class T>
135 void
136 write (T &out, signed short v);
137 
138 template <class S, class T>
139 void
140 write (T &out, unsigned short v);
141 
142 template <class S, class T>
143 void
144 write (T &out, signed int v);
145 
146 template <class S, class T>
147 void
148 write (T &out, unsigned int v);
149 
150 template <class S, class T>
151 void
152 write (T &out, signed long v);
153 
154 template <class S, class T>
155 void
156 write (T &out, unsigned long v);
157 
158 #if ULONG_MAX != 18446744073709551615LU
159 
160     template <class S, class T>
161     void
162     write (T &out, Int64 v);
163 
164 #endif
165 
166 template <class S, class T>
167 void
168 write (T &out, float v);
169 
170 template <class S, class T>
171 void
172 write (T &out, double v);
173 
174 template <class S, class T>
175 void
176 write (T &out, half v);
177 
178 template <class S, class T>
179 void
180 write (T &out, const char v[/*n*/], int n);	// fixed-size char array
181 
182 template <class S, class T>
183 void
184 write (T &out, const char v[]);			// zero-terminated string
185 
186 
187 //-----------------------------------------
188 // Append padding bytes to an output stream
189 //-----------------------------------------
190 
191 template <class S, class T>
192 void
193 pad (T &out, int n);				// write n padding bytes
194 
195 
196 
197 //-------------------------------
198 // Read data from an input stream
199 //-------------------------------
200 
201 template <class S, class T>
202 void
203 read (T &in, bool &v);
204 
205 template <class S, class T>
206 void
207 read (T &in, char &v);
208 
209 template <class S, class T>
210 void
211 read (T &in, signed char &v);
212 
213 template <class S, class T>
214 void
215 read (T &in, unsigned char &v);
216 
217 template <class S, class T>
218 void
219 read (T &in, signed short &v);
220 
221 template <class S, class T>
222 void
223 read (T &in, unsigned short &v);
224 
225 template <class S, class T>
226 void
227 read (T &in, signed int &v);
228 
229 template <class S, class T>
230 void
231 read (T &in, unsigned int &v);
232 
233 template <class S, class T>
234 void
235 read (T &in, signed long &v);
236 
237 template <class S, class T>
238 void
239 read (T &in, unsigned long &v);
240 
241 #if ULONG_MAX != 18446744073709551615LU
242 
243     template <class S, class T>
244     void
245     read (T &in, Int64 &v);
246 
247 #endif
248 
249 template <class S, class T>
250 void
251 read (T &in, float &v);
252 
253 template <class S, class T>
254 void
255 read (T &in, double &v);
256 
257 template <class S, class T>
258 void
259 read (T &in, half &v);
260 
261 template <class S, class T>
262 void
263 read (T &in, char v[/*n*/], int n);		// fixed-size char array
264 
265 template <class S, class T>
266 void
267 read (T &in, int n, char v[/*n*/]);		// zero-terminated string
268 
269 
270 //-------------------------------------------
271 // Skip over padding bytes in an input stream
272 //-------------------------------------------
273 
274 template <class S, class T>
275 void
276 skip (T &in, int n);				// skip n padding bytes
277 
278 
279 
280 //--------------------------------------
281 // Size of the machine-independent
282 // representation of an object of type S
283 //--------------------------------------
284 
285 template <class S>
286 int
287 size ();
288 
289 
290 //---------------
291 // Implementation
292 //---------------
293 
294 template <class S, class T>
295 inline void
writeSignedChars(T & out,const signed char c[],int n)296 writeSignedChars (T &out, const signed char c[], int n)
297 {
298     S::writeChars (out, (const char *) c, n);
299 }
300 
301 
302 template <class S, class T>
303 inline void
writeUnsignedChars(T & out,const unsigned char c[],int n)304 writeUnsignedChars (T &out, const unsigned char c[], int n)
305 {
306     S::writeChars (out, (const char *) c, n);
307 }
308 
309 
310 template <class S, class T>
311 inline void
readSignedChars(T & in,signed char c[],int n)312 readSignedChars (T &in, signed char c[], int n)
313 {
314     S::readChars (in, (char *) c, n);
315 }
316 
317 
318 template <class S, class T>
319 inline void
readUnsignedChars(T & in,unsigned char c[],int n)320 readUnsignedChars (T &in, unsigned char c[], int n)
321 {
322     S::readChars (in, (char *) c, n);
323 }
324 
325 
326 template <class S, class T>
327 inline void
write(T & out,bool v)328 write (T &out, bool v)
329 {
330     char c = !!v;
331     S::writeChars (out, &c, 1);
332 }
333 
334 
335 template <class S, class T>
336 inline void
write(T & out,char v)337 write (T &out, char v)
338 {
339     S::writeChars (out, &v, 1);
340 }
341 
342 
343 template <class S, class T>
344 inline void
write(T & out,signed char v)345 write (T &out, signed char v)
346 {
347     writeSignedChars<S> (out, &v, 1);
348 }
349 
350 
351 template <class S, class T>
352 inline void
write(T & out,unsigned char v)353 write (T &out, unsigned char v)
354 {
355     writeUnsignedChars<S> (out, &v, 1);
356 }
357 
358 
359 template <class S, class T>
360 void
write(T & out,signed short v)361 write (T &out, signed short v)
362 {
363     signed char b[2];
364 
365     b[0] =  (signed char) (v);
366     b[1] =  (signed char) (v >> 8);
367 
368     writeSignedChars<S> (out, b, 2);
369 }
370 
371 
372 template <class S, class T>
373 void
write(T & out,unsigned short v)374 write (T &out, unsigned short v)
375 {
376     unsigned char b[2];
377 
378     b[0] =  (unsigned char) (v);
379     b[1] =  (unsigned char) (v >> 8);
380 
381     writeUnsignedChars<S> (out, b, 2);
382 }
383 
384 
385 template <class S, class T>
386 void
write(T & out,signed int v)387 write (T &out, signed int v)
388 {
389     signed char b[4];
390 
391     b[0] =  (signed char) (v);
392     b[1] =  (signed char) (v >> 8);
393     b[2] =  (signed char) (v >> 16);
394     b[3] =  (signed char) (v >> 24);
395 
396     writeSignedChars<S> (out, b, 4);
397 }
398 
399 
400 template <class S, class T>
401 void
write(T & out,unsigned int v)402 write (T &out, unsigned int v)
403 {
404     unsigned char b[4];
405 
406     b[0] =  (unsigned char) (v);
407     b[1] =  (unsigned char) (v >> 8);
408     b[2] =  (unsigned char) (v >> 16);
409     b[3] =  (unsigned char) (v >> 24);
410 
411     writeUnsignedChars<S> (out, b, 4);
412 }
413 
414 
415 template <class S, class T>
416 void
write(T & out,signed long v)417 write (T &out, signed long v)
418 {
419     signed char b[8];
420 
421     b[0] = (signed char) (v);
422     b[1] = (signed char) (v >> 8);
423     b[2] = (signed char) (v >> 16);
424     b[3] = (signed char) (v >> 24);
425 
426     #if LONG_MAX == 2147483647
427 
428     if (v >= 0)
429     {
430         b[4] = 0;
431         b[5] = 0;
432         b[6] = 0;
433         b[7] = 0;
434     }
435     else
436     {
437         b[4] = ~0;
438         b[5] = ~0;
439         b[6] = ~0;
440         b[7] = ~0;
441     }
442 
443     #elif LONG_MAX == 9223372036854775807L
444 
445     b[4] = (signed char) (v >> 32);
446     b[5] = (signed char) (v >> 40);
447     b[6] = (signed char) (v >> 48);
448     b[7] = (signed char) (v >> 56);
449 
450     #else
451 
452     #error write<T> (T &out, signed long v) not implemented
453 
454     #endif
455 
456     writeSignedChars<S> (out, b, 8);
457 }
458 
459 
460 template <class S, class T>
461 void
write(T & out,unsigned long v)462 write (T &out, unsigned long v)
463 {
464     unsigned char b[8];
465 
466     b[0] = (unsigned char) (v);
467     b[1] = (unsigned char) (v >> 8);
468     b[2] = (unsigned char) (v >> 16);
469     b[3] = (unsigned char) (v >> 24);
470 
471     #if ULONG_MAX == 4294967295U
472 
473     b[4] = 0;
474     b[5] = 0;
475     b[6] = 0;
476     b[7] = 0;
477 
478     #elif ULONG_MAX == 18446744073709551615LU
479 
480     b[4] = (unsigned char) (v >> 32);
481     b[5] = (unsigned char) (v >> 40);
482     b[6] = (unsigned char) (v >> 48);
483     b[7] = (unsigned char) (v >> 56);
484 
485     #else
486 
487     #error write<T> (T &out, unsigned long v) not implemented
488 
489     #endif
490 
491     writeUnsignedChars<S> (out, b, 8);
492 }
493 
494 
495 #if ULONG_MAX != 18446744073709551615LU
496 
497     template <class S, class T>
498     void
write(T & out,Int64 v)499     write (T &out, Int64 v)
500     {
501         unsigned char b[8];
502 
503         b[0] = (unsigned char) (v);
504         b[1] = (unsigned char) (v >> 8);
505         b[2] = (unsigned char) (v >> 16);
506         b[3] = (unsigned char) (v >> 24);
507         b[4] = (unsigned char) (v >> 32);
508         b[5] = (unsigned char) (v >> 40);
509         b[6] = (unsigned char) (v >> 48);
510         b[7] = (unsigned char) (v >> 56);
511 
512         writeUnsignedChars<S> (out, b, 8);
513     }
514 
515 #endif
516 
517 
518 template <class S, class T>
519 void
write(T & out,float v)520 write (T &out, float v)
521 {
522     union {unsigned int i; float f;} u;
523     u.f = v;
524 
525     unsigned char b[4];
526 
527     b[0] = (unsigned char) (u.i);
528     b[1] = (unsigned char) (u.i >> 8);
529     b[2] = (unsigned char) (u.i >> 16);
530     b[3] = (unsigned char) (u.i >> 24);
531 
532     writeUnsignedChars<S> (out, b, 4);
533 }
534 
535 
536 template <class S, class T>
537 void
write(T & out,double v)538 write (T &out, double v)
539 {
540     union {Int64 i; double d;} u;
541     u.d = v;
542 
543     unsigned char b[8];
544 
545     b[0] = (unsigned char) (u.i);
546     b[1] = (unsigned char) (u.i >> 8);
547     b[2] = (unsigned char) (u.i >> 16);
548     b[3] = (unsigned char) (u.i >> 24);
549     b[4] = (unsigned char) (u.i >> 32);
550     b[5] = (unsigned char) (u.i >> 40);
551     b[6] = (unsigned char) (u.i >> 48);
552     b[7] = (unsigned char) (u.i >> 56);
553 
554     writeUnsignedChars<S> (out, b, 8);
555 }
556 
557 
558 template <class S, class T>
559 inline void
write(T & out,half v)560 write (T &out, half v)
561 {
562     unsigned char b[2];
563 
564     b[0] =  (unsigned char) (v.bits());
565     b[1] =  (unsigned char) (v.bits() >> 8);
566 
567     writeUnsignedChars<S> (out, b, 2);
568 }
569 
570 
571 template <class S, class T>
572 inline void
write(T & out,const char v[],int n)573 write (T &out, const char v[], int n)	// fixed-size char array
574 {
575     S::writeChars (out, v, n);
576 }
577 
578 
579 template <class S, class T>
580 void
write(T & out,const char v[])581 write (T &out, const char v[])		// zero-terminated string
582 {
583     while (*v)
584     {
585     S::writeChars (out, v, 1);
586     ++v;
587     }
588 
589     S::writeChars (out, v, 1);
590 }
591 
592 
593 template <class S, class T>
594 void
pad(T & out,int n)595 pad (T &out, int n)			// add n padding bytes
596 {
597     for (int i = 0; i < n; i++)
598     {
599     const char c = 0;
600     S::writeChars (out, &c, 1);
601     }
602 }
603 
604 
605 template <class S, class T>
606 inline void
read(T & in,bool & v)607 read (T &in, bool &v)
608 {
609     char c;
610 
611     S::readChars (in, &c, 1);
612     v = !!c;
613 }
614 
615 
616 template <class S, class T>
617 inline void
read(T & in,char & v)618 read (T &in, char &v)
619 {
620     S::readChars (in, &v, 1);
621 }
622 
623 
624 template <class S, class T>
625 inline void
read(T & in,signed char & v)626 read (T &in, signed char &v)
627 {
628     readSignedChars<S> (in, &v, 1);
629 }
630 
631 
632 template <class S, class T>
633 inline void
read(T & in,unsigned char & v)634 read (T &in, unsigned char &v)
635 {
636     readUnsignedChars<S> (in, &v, 1);
637 }
638 
639 
640 template <class S, class T>
641 void
read(T & in,signed short & v)642 read (T &in, signed short &v)
643 {
644     signed char b[2];
645 
646     readSignedChars<S> (in, b, 2);
647 
648     v = (b[0] & 0x00ff) |
649     (b[1] << 8);
650 }
651 
652 
653 template <class S, class T>
654 void
read(T & in,unsigned short & v)655 read (T &in, unsigned short &v)
656 {
657     unsigned char b[2];
658 
659     readUnsignedChars<S> (in, b, 2);
660 
661     v = (b[0] & 0x00ff) |
662     (b[1] << 8);
663 }
664 
665 
666 template <class S, class T>
667 void
read(T & in,signed int & v)668 read (T &in, signed int &v)
669 {
670     signed char b[4];
671 
672     readSignedChars<S> (in, b, 4);
673 
674     v =  (b[0]        & 0x000000ff) |
675     ((b[1] << 8)  & 0x0000ff00) |
676     ((b[2] << 16) & 0x00ff0000) |
677      (b[3] << 24);
678 }
679 
680 
681 template <class S, class T>
682 void
read(T & in,unsigned int & v)683 read (T &in, unsigned int &v)
684 {
685     unsigned char b[4];
686 
687     readUnsignedChars<S> (in, b, 4);
688 
689     v =  (b[0]        & 0x000000ff) |
690     ((b[1] << 8)  & 0x0000ff00) |
691     ((b[2] << 16) & 0x00ff0000) |
692      (b[3] << 24);
693 }
694 
695 
696 template <class S, class T>
697 void
read(T & in,signed long & v)698 read (T &in, signed long &v)
699 {
700     signed char b[8];
701 
702     readSignedChars<S> (in, b, 8);
703 
704     #if LONG_MAX == 2147483647
705 
706     v =  (b[0]        & 0x000000ff) |
707         ((b[1] << 8)  & 0x0000ff00) |
708         ((b[2] << 16) & 0x00ff0000) |
709          (b[3] << 24);
710 
711     if (( b[4] ||  b[5] ||  b[6] ||  b[7]) &&
712         (~b[4] || ~b[5] || ~b[6] || ~b[7]))
713     {
714         throw Iex::OverflowExc ("Long int overflow - read a large "
715                     "64-bit integer in a 32-bit process.");
716     }
717 
718     #elif LONG_MAX == 9223372036854775807L
719 
720     v =  ((long) b[0]        & 0x00000000000000ff) |
721         (((long) b[1] << 8)  & 0x000000000000ff00) |
722         (((long) b[2] << 16) & 0x0000000000ff0000) |
723         (((long) b[3] << 24) & 0x00000000ff000000) |
724         (((long) b[4] << 32) & 0x000000ff00000000) |
725         (((long) b[5] << 40) & 0x0000ff0000000000) |
726         (((long) b[6] << 48) & 0x00ff000000000000) |
727          ((long) b[7] << 56);
728 
729     #else
730 
731     #error read<T> (T &in, signed long &v) not implemented
732 
733     #endif
734 }
735 
736 
737 template <class S, class T>
738 void
read(T & in,unsigned long & v)739 read (T &in, unsigned long &v)
740 {
741     unsigned char b[8];
742 
743     readUnsignedChars<S> (in, b, 8);
744 
745     #if ULONG_MAX == 4294967295U
746 
747     v =  (b[0]        & 0x000000ff) |
748         ((b[1] << 8)  & 0x0000ff00) |
749         ((b[2] << 16) & 0x00ff0000) |
750          (b[3] << 24);
751 
752     if (b[4] || b[5] || b[6] || b[7])
753     {
754         throw Iex::OverflowExc ("Long int overflow - read a large "
755                     "64-bit integer in a 32-bit process.");
756     }
757 
758     #elif ULONG_MAX == 18446744073709551615LU
759 
760     v =  ((unsigned long) b[0]        & 0x00000000000000ff) |
761         (((unsigned long) b[1] << 8)  & 0x000000000000ff00) |
762         (((unsigned long) b[2] << 16) & 0x0000000000ff0000) |
763         (((unsigned long) b[3] << 24) & 0x00000000ff000000) |
764         (((unsigned long) b[4] << 32) & 0x000000ff00000000) |
765         (((unsigned long) b[5] << 40) & 0x0000ff0000000000) |
766         (((unsigned long) b[6] << 48) & 0x00ff000000000000) |
767          ((unsigned long) b[7] << 56);
768 
769     #else
770 
771     #error read<T> (T &in, unsigned long &v) not implemented
772 
773     #endif
774 }
775 
776 
777 #if ULONG_MAX != 18446744073709551615LU
778 
779     template <class S, class T>
780     void
read(T & in,Int64 & v)781     read (T &in, Int64 &v)
782     {
783         unsigned char b[8];
784 
785         readUnsignedChars<S> (in, b, 8);
786 
787         v =  ((Int64) b[0]        & 0x00000000000000ffLL) |
788         (((Int64) b[1] << 8)  & 0x000000000000ff00LL) |
789         (((Int64) b[2] << 16) & 0x0000000000ff0000LL) |
790         (((Int64) b[3] << 24) & 0x00000000ff000000LL) |
791         (((Int64) b[4] << 32) & 0x000000ff00000000LL) |
792         (((Int64) b[5] << 40) & 0x0000ff0000000000LL) |
793         (((Int64) b[6] << 48) & 0x00ff000000000000LL) |
794         ((Int64) b[7] << 56);
795     }
796 
797 #endif
798 
799 
800 template <class S, class T>
801 void
read(T & in,float & v)802 read (T &in, float &v)
803 {
804     unsigned char b[4];
805 
806     readUnsignedChars<S> (in, b, 4);
807 
808     union {unsigned int i; float f;} u;
809 
810     u.i = (b[0]        & 0x000000ff) |
811      ((b[1] << 8)  & 0x0000ff00) |
812      ((b[2] << 16) & 0x00ff0000) |
813       (b[3] << 24);
814 
815     v = u.f;
816 }
817 
818 
819 template <class S, class T>
820 void
read(T & in,double & v)821 read (T &in, double &v)
822 {
823     unsigned char b[8];
824 
825     readUnsignedChars<S> (in, b, 8);
826 
827     union {Int64 i; double d;} u;
828 
829     u.i = ((Int64) b[0]        & 0x00000000000000ffULL) |
830      (((Int64) b[1] << 8)  & 0x000000000000ff00ULL) |
831      (((Int64) b[2] << 16) & 0x0000000000ff0000ULL) |
832      (((Int64) b[3] << 24) & 0x00000000ff000000ULL) |
833      (((Int64) b[4] << 32) & 0x000000ff00000000ULL) |
834      (((Int64) b[5] << 40) & 0x0000ff0000000000ULL) |
835      (((Int64) b[6] << 48) & 0x00ff000000000000ULL) |
836       ((Int64) b[7] << 56);
837 
838     v = u.d;
839 }
840 
841 
842 template <class S, class T>
843 inline void
read(T & in,half & v)844 read (T &in, half &v)
845 {
846     unsigned char b[2];
847 
848     readUnsignedChars<S> (in, b, 2);
849 
850     v.setBits ((b[0] & 0x00ff) | (b[1] << 8));
851 }
852 
853 
854 template <class S, class T>
855 inline void
read(T & in,char v[],int n)856 read (T &in, char v[], int n)		// fixed-size char array
857 {
858     S::readChars (in, v, n);
859 }
860 
861 
862 template <class S, class T>
863 void
read(T & in,int n,char v[])864 read (T &in, int n, char v[])		// zero-terminated string
865 {
866     while (n >= 0)
867     {
868     S::readChars (in, v, 1);
869 
870     if (*v == 0)
871         break;
872 
873     --n;
874     ++v;
875     }
876 }
877 
878 
879 template <class S, class T>
880 void
skip(T & in,int n)881 skip (T &in, int n)			// skip n padding bytes
882 {
883     char c[1024];
884 
885     while (n >= (int) sizeof (c))
886     {
887     if (!S::readChars (in, c, sizeof (c)))
888         return;
889 
890     n -= sizeof (c);
891     }
892 
893     if (n >= 1)
894     S::readChars (in, c, n);
895 }
896 
897 
898 template <> inline int size <bool> ()			{return 1;}
899 template <> inline int size <char> ()			{return 1;}
900 template <> inline int size <signed char> ()		{return 1;}
901 template <> inline int size <unsigned char> ()		{return 1;}
902 template <> inline int size <signed short> ()		{return 2;}
903 template <> inline int size <unsigned short> ()		{return 2;}
904 template <> inline int size <signed int> ()		{return 4;}
905 template <> inline int size <unsigned int> ()		{return 4;}
906 template <> inline int size <signed long> ()		{return 8;}
907 template <> inline int size <unsigned long> ()		{return 8;}
908 template <> inline int size <float> ()			{return 4;}
909 template <> inline int size <double> ()			{return 8;}
910 template <> inline int size <half> ()			{return 2;}
911 
912 
913 } // namespace Xdr
914 } // namespace Imf
915 
916 #endif
917