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