1 ///////////////////////////////////////////////////////////////////////////
3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
6 // All rights reserved.
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
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
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.
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.
33 ///////////////////////////////////////////////////////////////////////////
36 #ifndef INCLUDED_IMF_XDR_H
37 #define INCLUDED_IMF_XDR_H
39 //----------------------------------------------------------------------------
41 // Xdr -- routines to convert data between the machine's native
42 // format and a machine-independent external data representation:
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.
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
56 // size<S>(); returns the size, in bytes, of the
57 // machine-independent representation
58 // of an object of type S.
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:
68 // writeChars (T &o, const char c[/*n*/], int n)
70 // ... // Write c[0], c[1] ... c[n-1] to output buffer o.
74 // readChars (T &i, char c[/*n*/], int n)
76 // ... // Read n characters from input buffer i
77 // // and copy them to c[0], c[1] ... c[n-1].
81 // Example - writing to and reading from iostreams:
83 // struct CharStreamIO
86 // writeChars (ostream &os, const char c[], int n)
92 // readChars (istream &is, char c[], int n)
100 // Xdr::write<CharStreamIO> (os, 3);
101 // Xdr::write<CharStreamIO> (os, 5.0);
103 //----------------------------------------------------------------------------
105 #include <ImfInt64.h>
106 #include "IexMathExc.h"
114 //-------------------------------
115 // Write data to an output stream
116 //-------------------------------
118 template <class S, class T>
120 write (T &out, bool v);
122 template <class S, class T>
124 write (T &out, char v);
126 template <class S, class T>
128 write (T &out, signed char v);
130 template <class S, class T>
132 write (T &out, unsigned char v);
134 template <class S, class T>
136 write (T &out, signed short v);
138 template <class S, class T>
140 write (T &out, unsigned short v);
142 template <class S, class T>
144 write (T &out, signed int v);
146 template <class S, class T>
148 write (T &out, unsigned int v);
150 template <class S, class T>
152 write (T &out, signed long v);
154 template <class S, class T>
156 write (T &out, unsigned long v);
158 #if ULONG_MAX != 18446744073709551615LU
160 template <class S, class T>
162 write (T &out, Int64 v);
166 template <class S, class T>
168 write (T &out, float v);
170 template <class S, class T>
172 write (T &out, double v);
174 template <class S, class T>
176 write (T &out, half v);
178 template <class S, class T>
180 write (T &out, const char v[/*n*/], int n); // fixed-size char array
182 template <class S, class T>
184 write (T &out, const char v[]); // zero-terminated string
187 //-----------------------------------------
188 // Append padding bytes to an output stream
189 //-----------------------------------------
191 template <class S, class T>
193 pad (T &out, int n); // write n padding bytes
197 //-------------------------------
198 // Read data from an input stream
199 //-------------------------------
201 template <class S, class T>
203 read (T &in, bool &v);
205 template <class S, class T>
207 read (T &in, char &v);
209 template <class S, class T>
211 read (T &in, signed char &v);
213 template <class S, class T>
215 read (T &in, unsigned char &v);
217 template <class S, class T>
219 read (T &in, signed short &v);
221 template <class S, class T>
223 read (T &in, unsigned short &v);
225 template <class S, class T>
227 read (T &in, signed int &v);
229 template <class S, class T>
231 read (T &in, unsigned int &v);
233 template <class S, class T>
235 read (T &in, signed long &v);
237 template <class S, class T>
239 read (T &in, unsigned long &v);
241 #if ULONG_MAX != 18446744073709551615LU
243 template <class S, class T>
245 read (T &in, Int64 &v);
249 template <class S, class T>
251 read (T &in, float &v);
253 template <class S, class T>
255 read (T &in, double &v);
257 template <class S, class T>
259 read (T &in, half &v);
261 template <class S, class T>
263 read (T &in, char v[/*n*/], int n); // fixed-size char array
265 template <class S, class T>
267 read (T &in, int n, char v[/*n*/]); // zero-terminated string
270 //-------------------------------------------
271 // Skip over padding bytes in an input stream
272 //-------------------------------------------
274 template <class S, class T>
276 skip (T &in, int n); // skip n padding bytes
280 //--------------------------------------
281 // Size of the machine-independent
282 // representation of an object of type S
283 //--------------------------------------
294 template <class S, class T>
296 writeSignedChars (T &out, const signed char c[], int n)
298 S::writeChars (out, (const char *) c, n);
302 template <class S, class T>
304 writeUnsignedChars (T &out, const unsigned char c[], int n)
306 S::writeChars (out, (const char *) c, n);
310 template <class S, class T>
312 readSignedChars (T &in, signed char c[], int n)
314 S::readChars (in, (char *) c, n);
318 template <class S, class T>
320 readUnsignedChars (T &in, unsigned char c[], int n)
322 S::readChars (in, (char *) c, n);
326 template <class S, class T>
328 write (T &out, bool v)
331 S::writeChars (out, &c, 1);
335 template <class S, class T>
337 write (T &out, char v)
339 S::writeChars (out, &v, 1);
343 template <class S, class T>
345 write (T &out, signed char v)
347 writeSignedChars<S> (out, &v, 1);
351 template <class S, class T>
353 write (T &out, unsigned char v)
355 writeUnsignedChars<S> (out, &v, 1);
359 template <class S, class T>
361 write (T &out, signed short v)
365 b[0] = (signed char) (v);
366 b[1] = (signed char) (v >> 8);
368 writeSignedChars<S> (out, b, 2);
372 template <class S, class T>
374 write (T &out, unsigned short v)
378 b[0] = (unsigned char) (v);
379 b[1] = (unsigned char) (v >> 8);
381 writeUnsignedChars<S> (out, b, 2);
385 template <class S, class T>
387 write (T &out, signed int v)
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);
396 writeSignedChars<S> (out, b, 4);
400 template <class S, class T>
402 write (T &out, unsigned int v)
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);
411 writeUnsignedChars<S> (out, b, 4);
415 template <class S, class T>
417 write (T &out, signed long v)
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);
426 #if LONG_MAX == 2147483647
443 #elif LONG_MAX == 9223372036854775807L
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);
452 #error write<T> (T &out, signed long v) not implemented
456 writeSignedChars<S> (out, b, 8);
460 template <class S, class T>
462 write (T &out, unsigned long v)
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);
471 #if ULONG_MAX == 4294967295U
478 #elif ULONG_MAX == 18446744073709551615LU
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);
487 #error write<T> (T &out, unsigned long v) not implemented
491 writeUnsignedChars<S> (out, b, 8);
495 #if ULONG_MAX != 18446744073709551615LU
497 template <class S, class T>
499 write (T &out, Int64 v)
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);
512 writeUnsignedChars<S> (out, b, 8);
518 template <class S, class T>
520 write (T &out, float v)
522 union {unsigned int i; float f;} u;
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);
532 writeUnsignedChars<S> (out, b, 4);
536 template <class S, class T>
538 write (T &out, double v)
540 union {Int64 i; double d;} u;
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);
554 writeUnsignedChars<S> (out, b, 8);
558 template <class S, class T>
560 write (T &out, half v)
564 b[0] = (unsigned char) (v.bits());
565 b[1] = (unsigned char) (v.bits() >> 8);
567 writeUnsignedChars<S> (out, b, 2);
571 template <class S, class T>
573 write (T &out, const char v[], int n) // fixed-size char array
575 S::writeChars (out, v, n);
579 template <class S, class T>
581 write (T &out, const char v[]) // zero-terminated string
585 S::writeChars (out, v, 1);
589 S::writeChars (out, v, 1);
593 template <class S, class T>
595 pad (T &out, int n) // add n padding bytes
597 for (int i = 0; i < n; i++)
600 S::writeChars (out, &c, 1);
605 template <class S, class T>
607 read (T &in, bool &v)
611 S::readChars (in, &c, 1);
616 template <class S, class T>
618 read (T &in, char &v)
620 S::readChars (in, &v, 1);
624 template <class S, class T>
626 read (T &in, signed char &v)
628 readSignedChars<S> (in, &v, 1);
632 template <class S, class T>
634 read (T &in, unsigned char &v)
636 readUnsignedChars<S> (in, &v, 1);
640 template <class S, class T>
642 read (T &in, signed short &v)
646 readSignedChars<S> (in, b, 2);
648 v = (b[0] & 0x00ff) |
653 template <class S, class T>
655 read (T &in, unsigned short &v)
659 readUnsignedChars<S> (in, b, 2);
661 v = (b[0] & 0x00ff) |
666 template <class S, class T>
668 read (T &in, signed int &v)
672 readSignedChars<S> (in, b, 4);
674 v = (b[0] & 0x000000ff) |
675 ((b[1] << 8) & 0x0000ff00) |
676 ((b[2] << 16) & 0x00ff0000) |
681 template <class S, class T>
683 read (T &in, unsigned int &v)
687 readUnsignedChars<S> (in, b, 4);
689 v = (b[0] & 0x000000ff) |
690 ((b[1] << 8) & 0x0000ff00) |
691 ((b[2] << 16) & 0x00ff0000) |
696 template <class S, class T>
698 read (T &in, signed long &v)
702 readSignedChars<S> (in, b, 8);
704 #if LONG_MAX == 2147483647
706 v = (b[0] & 0x000000ff) |
707 ((b[1] << 8) & 0x0000ff00) |
708 ((b[2] << 16) & 0x00ff0000) |
711 if (( b[4] || b[5] || b[6] || b[7]) &&
712 (~b[4] || ~b[5] || ~b[6] || ~b[7]))
714 throw Iex::OverflowExc ("Long int overflow - read a large "
715 "64-bit integer in a 32-bit process.");
718 #elif LONG_MAX == 9223372036854775807L
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) |
731 #error read<T> (T &in, signed long &v) not implemented
737 template <class S, class T>
739 read (T &in, unsigned long &v)
743 readUnsignedChars<S> (in, b, 8);
745 #if ULONG_MAX == 4294967295U
747 v = (b[0] & 0x000000ff) |
748 ((b[1] << 8) & 0x0000ff00) |
749 ((b[2] << 16) & 0x00ff0000) |
752 if (b[4] || b[5] || b[6] || b[7])
754 throw Iex::OverflowExc ("Long int overflow - read a large "
755 "64-bit integer in a 32-bit process.");
758 #elif ULONG_MAX == 18446744073709551615LU
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);
771 #error read<T> (T &in, unsigned long &v) not implemented
777 #if ULONG_MAX != 18446744073709551615LU
779 template <class S, class T>
781 read (T &in, Int64 &v)
785 readUnsignedChars<S> (in, b, 8);
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);
800 template <class S, class T>
802 read (T &in, float &v)
806 readUnsignedChars<S> (in, b, 4);
808 union {unsigned int i; float f;} u;
810 u.i = (b[0] & 0x000000ff) |
811 ((b[1] << 8) & 0x0000ff00) |
812 ((b[2] << 16) & 0x00ff0000) |
819 template <class S, class T>
821 read (T &in, double &v)
825 readUnsignedChars<S> (in, b, 8);
827 union {Int64 i; double d;} u;
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);
842 template <class S, class T>
844 read (T &in, half &v)
848 readUnsignedChars<S> (in, b, 2);
850 v.setBits ((b[0] & 0x00ff) | (b[1] << 8));
854 template <class S, class T>
856 read (T &in, char v[], int n) // fixed-size char array
858 S::readChars (in, v, n);
862 template <class S, class T>
864 read (T &in, int n, char v[]) // zero-terminated string
868 S::readChars (in, v, 1);
879 template <class S, class T>
881 skip (T &in, int n) // skip n padding bytes
885 while (n >= (int) sizeof (c))
887 if (!S::readChars (in, c, sizeof (c)))
894 S::readChars (in, c, n);
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;}