1//
2// SPDX-License-Identifier: BSD-3-Clause
3// Copyright (c) Contributors to the OpenEXR Project.
4//
5
6#ifndef INCLUDED_IMF_XDR_H
7#define INCLUDED_IMF_XDR_H
8
9
10//----------------------------------------------------------------------------
11//
12// Xdr -- routines to convert data between the machine's native
13// format and a machine-independent external data representation:
14//
15// write<R> (T &o, S v); converts a value, v, of type S
16// into a machine-independent
17// representation and stores the
18// result in an output buffer, o.
19//
20// read<R> (T &i, S &v); reads the machine-independent
21// representation of a value of type
22// S from input buffer i, converts
23// the value into the machine's native
24// representation, and stores the result
25// in v.
26//
27// size<S>(); returns the size, in bytes, of the
28// machine-independent representation
29// of an object of type S.
30//
31// The write() and read() routines are templates; data can be written
32// to and read from any output or input buffer type T for which a helper
33// class, R, exits. Class R must define a method to store a char array
34// in a T, and a method to read a char array from a T:
35//
36// struct R
37// {
38// static void
39// writeChars (T &o, const char c[/*n*/], int n)
40// {
41// ... // Write c[0], c[1] ... c[n-1] to output buffer o.
42// }
43//
44// static void
45// readChars (T &i, char c[/*n*/], int n)
46// {
47// ... // Read n characters from input buffer i
48// // and copy them to c[0], c[1] ... c[n-1].
49// }
50// };
51//
52// Example - writing to and reading from iostreams:
53//
54// struct CharStreamIO
55// {
56// static void
57// writeChars (ostream &os, const char c[], int n)
58// {
59// os.write (c, n);
60// }
61//
62// static void
63// readChars (istream &is, char c[], int n)
64// {
65// is.read (c, n);
66// }
67// };
68//
69// ...
70//
71// Xdr::write<CharStreamIO> (os, 3);
72// Xdr::write<CharStreamIO> (os, 5.0);
73//
74//----------------------------------------------------------------------------
75
76#include "ImfNamespace.h"
77
78#include "IexMathExc.h"
79#include <half.h>
80#include <limits.h>
81#include <cstdint>
82
83OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
84
85namespace Xdr {
86
87
88//-------------------------------
89// Write data to an output stream
90//-------------------------------
91
92template <class S, class T>
93void
94write (T &out, bool v);
95
96template <class S, class T>
97void
98write (T &out, char v);
99
100template <class S, class T>
101void
102write (T &out, signed char v);
103
104template <class S, class T>
105void
106write (T &out, unsigned char v);
107
108template <class S, class T>
109void
110write (T &out, signed short v);
111
112template <class S, class T>
113void
114write (T &out, unsigned short v);
115
116template <class S, class T>
117void
118write (T &out, signed int v);
119
120template <class S, class T>
121void
122write (T &out, unsigned int v);
123
124template <class S, class T>
125void
126write (T &out, int64_t v);
127
128template <class S, class T>
129void
130write (T &out, uint64_t v);
131
132
133template <class S, class T>
134void
135write (T &out, float v);
136
137template <class S, class T>
138void
139write (T &out, double v);
140
141template <class S, class T>
142void
143write (T &out, half v);
144
145template <class S, class T>
146void
147write (T &out, const char v[/*n*/], int n); // fixed-size char array
148
149template <class S, class T>
150void
151write (T &out, const char v[]); // zero-terminated string
152
153
154//-----------------------------------------
155// Append padding bytes to an output stream
156//-----------------------------------------
157
158template <class S, class T>
159void
160pad (T &out, int n); // write n padding bytes
161
162
163
164//-------------------------------
165// Read data from an input stream
166//-------------------------------
167
168template <class S, class T>
169void
170read (T &in, bool &v);
171
172template <class S, class T>
173void
174read (T &in, char &v);
175
176template <class S, class T>
177void
178read (T &in, signed char &v);
179
180template <class S, class T>
181void
182read (T &in, unsigned char &v);
183
184template <class S, class T>
185void
186read (T &in, signed short &v);
187
188template <class S, class T>
189void
190read (T &in, unsigned short &v);
191
192template <class S, class T>
193void
194read (T &in, signed int &v);
195
196template <class S, class T>
197void
198read (T &in, unsigned int &v);
199
200template <class S, class T>
201void
202read (T &in, int64_t &v);
203
204template <class S, class T>
205void
206read (T &in, uint64_t &v);
207
208template <class S, class T>
209void
210read (T &in, float &v);
211
212template <class S, class T>
213void
214read (T &in, double &v);
215
216template <class S, class T>
217void
218read (T &in, half &v);
219
220template <class S, class T>
221void
222read (T &in, char v[/*n*/], int n); // fixed-size char array
223
224template <class S, class T>
225void
226read (T &in, int n, char v[/*n*/]); // zero-terminated string
227
228
229//-------------------------------------------
230// Skip over padding bytes in an input stream
231//-------------------------------------------
232
233template <class S, class T>
234void
235skip (T &in, int n); // skip n padding bytes
236
237
238
239//--------------------------------------
240// Size of the machine-independent
241// representation of an object of type S
242//--------------------------------------
243
244template <class S>
245int
246size ();
247
248
249//---------------
250// Implementation
251//---------------
252
253template <class S, class T>
254inline void
255writeSignedChars (T &out, const signed char c[], int n)
256{
257 S::writeChars (out, (const char *) c, n);
258}
259
260
261template <class S, class T>
262inline void
263writeUnsignedChars (T &out, const unsigned char c[], int n)
264{
265 S::writeChars (out, (const char *) c, n);
266}
267
268
269template <class S, class T>
270inline void
271readSignedChars (T &in, signed char c[], int n)
272{
273 S::readChars (in, (char *) c, n);
274}
275
276
277template <class S, class T>
278inline void
279readUnsignedChars (T &in, unsigned char c[], int n)
280{
281 S::readChars (in, (char *) c, n);
282}
283
284
285template <class S, class T>
286inline void
287write (T &out, bool v)
288{
289 char c = !!v;
290 S::writeChars (out, &c, 1);
291}
292
293
294template <class S, class T>
295inline void
296write (T &out, char v)
297{
298 S::writeChars (out, &v, 1);
299}
300
301
302template <class S, class T>
303inline void
304write (T &out, signed char v)
305{
306 writeSignedChars<S> (out, &v, 1);
307}
308
309
310template <class S, class T>
311inline void
312write (T &out, unsigned char v)
313{
314 writeUnsignedChars<S> (out, &v, 1);
315}
316
317
318template <class S, class T>
319void
320write (T &out, signed short v)
321{
322 signed char b[2];
323
324 b[0] = (signed char) (v);
325 b[1] = (signed char) (v >> 8);
326
327 writeSignedChars<S> (out, b, 2);
328}
329
330
331template <class S, class T>
332void
333write (T &out, unsigned short v)
334{
335 unsigned char b[2];
336
337 b[0] = (unsigned char) (v);
338 b[1] = (unsigned char) (v >> 8);
339
340 writeUnsignedChars<S> (out, b, 2);
341}
342
343
344template <class S, class T>
345void
346write (T &out, signed int v)
347{
348 signed char b[4];
349
350 b[0] = (signed char) (v);
351 b[1] = (signed char) (v >> 8);
352 b[2] = (signed char) (v >> 16);
353 b[3] = (signed char) (v >> 24);
354
355 writeSignedChars<S> (out, b, 4);
356}
357
358
359template <class S, class T>
360void
361write (T &out, unsigned int v)
362{
363 unsigned char b[4];
364
365 b[0] = (unsigned char) (v);
366 b[1] = (unsigned char) (v >> 8);
367 b[2] = (unsigned char) (v >> 16);
368 b[3] = (unsigned char) (v >> 24);
369
370 writeUnsignedChars<S> (out, b, 4);
371}
372
373
374template <class S, class T>
375void
376write (T &out, int64_t v)
377{
378 signed char b[8];
379
380 b[0] = (signed char) (v);
381 b[1] = (signed char) (v >> 8);
382 b[2] = (signed char) (v >> 16);
383 b[3] = (signed char) (v >> 24);
384 b[4] = (signed char) (v >> 32);
385 b[5] = (signed char) (v >> 40);
386 b[6] = (signed char) (v >> 48);
387 b[7] = (signed char) (v >> 56);
388
389 writeSignedChars<S> (out, b, 8);
390}
391
392template <class S, class T>
393void
394write (T &out, uint64_t v)
395{
396 unsigned char b[8];
397
398 b[0] = (unsigned char) (v);
399 b[1] = (unsigned char) (v >> 8);
400 b[2] = (unsigned char) (v >> 16);
401 b[3] = (unsigned char) (v >> 24);
402 b[4] = (unsigned char) (v >> 32);
403 b[5] = (unsigned char) (v >> 40);
404 b[6] = (unsigned char) (v >> 48);
405 b[7] = (unsigned char) (v >> 56);
406
407 writeUnsignedChars<S> (out, b, 8);
408}
409
410
411
412
413template <class S, class T>
414void
415write (T &out, float v)
416{
417 union {unsigned int i; float f;} u;
418 u.f = v;
419
420 unsigned char b[4];
421
422 b[0] = (unsigned char) (u.i);
423 b[1] = (unsigned char) (u.i >> 8);
424 b[2] = (unsigned char) (u.i >> 16);
425 b[3] = (unsigned char) (u.i >> 24);
426
427 writeUnsignedChars<S> (out, b, 4);
428}
429
430
431template <class S, class T>
432void
433write (T &out, double v)
434{
435 union {uint64_t i; double d;} u;
436 u.d = v;
437
438 unsigned char b[8];
439
440 b[0] = (unsigned char) (u.i);
441 b[1] = (unsigned char) (u.i >> 8);
442 b[2] = (unsigned char) (u.i >> 16);
443 b[3] = (unsigned char) (u.i >> 24);
444 b[4] = (unsigned char) (u.i >> 32);
445 b[5] = (unsigned char) (u.i >> 40);
446 b[6] = (unsigned char) (u.i >> 48);
447 b[7] = (unsigned char) (u.i >> 56);
448
449 writeUnsignedChars<S> (out, b, 8);
450}
451
452
453template <class S, class T>
454inline void
455write (T &out, half v)
456{
457 unsigned char b[2];
458
459 b[0] = (unsigned char) (v.bits());
460 b[1] = (unsigned char) (v.bits() >> 8);
461
462 writeUnsignedChars<S> (out, b, 2);
463}
464
465
466template <class S, class T>
467inline void
468write (T &out, const char v[], int n) // fixed-size char array
469{
470 S::writeChars (out, v, n);
471}
472
473
474template <class S, class T>
475void
476write (T &out, const char v[]) // zero-terminated string
477{
478 while (*v)
479 {
480 S::writeChars (out, v, 1);
481 ++v;
482 }
483
484 S::writeChars (out, v, 1);
485}
486
487
488template <class S, class T>
489void
490pad (T &out, int n) // add n padding bytes
491{
492 for (int i = 0; i < n; i++)
493 {
494 const char c = 0;
495 S::writeChars (out, &c, 1);
496 }
497}
498
499
500template <class S, class T>
501inline void
502read (T &in, bool &v)
503{
504 char c;
505
506 S::readChars (in, &c, 1);
507 v = !!c;
508}
509
510
511template <class S, class T>
512inline void
513read (T &in, char &v)
514{
515 S::readChars (in, &v, 1);
516}
517
518
519template <class S, class T>
520inline void
521read (T &in, signed char &v)
522{
523 readSignedChars<S> (in, &v, 1);
524}
525
526
527template <class S, class T>
528inline void
529read (T &in, unsigned char &v)
530{
531 readUnsignedChars<S> (in, &v, 1);
532}
533
534
535template <class S, class T>
536void
537read (T &in, signed short &v)
538{
539 signed char b[2];
540
541 readSignedChars<S> (in, b, 2);
542
543 v = (static_cast <unsigned char> (b[0]) & 0x00ff) |
544 (static_cast <unsigned char> (b[1]) << 8);
545}
546
547
548template <class S, class T>
549void
550read (T &in, unsigned short &v)
551{
552 unsigned char b[2];
553
554 readUnsignedChars<S> (in, b, 2);
555
556 v = (b[0] & 0x00ff) |
557 (b[1] << 8);
558}
559
560
561template <class S, class T>
562void
563read (T &in, signed int &v)
564{
565 signed char b[4];
566
567 readSignedChars<S> (in, b, 4);
568
569 v = (static_cast <unsigned char> (b[0]) & 0x000000ff) |
570 ((static_cast <unsigned char> (b[1]) << 8) & 0x0000ff00) |
571 ((static_cast <unsigned char> (b[2]) << 16) & 0x00ff0000) |
572 (static_cast <unsigned char> (b[3]) << 24);
573}
574
575
576template <class S, class T>
577void
578read (T &in, unsigned int &v)
579{
580 unsigned char b[4];
581
582 readUnsignedChars<S> (in, b, 4);
583
584 v = (b[0] & 0x000000ff) |
585 ((b[1] << 8) & 0x0000ff00) |
586 ((b[2] << 16) & 0x00ff0000) |
587 (b[3] << 24);
588}
589
590
591template <class S, class T>
592void
593read (T &in, int64_t &v)
594{
595 signed char b[8];
596
597 readSignedChars<S> (in, b, 8);
598
599 v = (static_cast <int64_t> (b[0]) & 0x00000000000000ff) |
600 ((static_cast <int64_t> (b[1]) << 8) & 0x000000000000ff00) |
601 ((static_cast <int64_t> (b[2]) << 16) & 0x0000000000ff0000) |
602 ((static_cast <int64_t> (b[3]) << 24) & 0x00000000ff000000) |
603 ((static_cast <int64_t> (b[4]) << 32) & 0x000000ff00000000) |
604 ((static_cast <int64_t> (b[5]) << 40) & 0x0000ff0000000000) |
605 ((static_cast <int64_t> (b[6]) << 48) & 0x00ff000000000000) |
606 (static_cast <int64_t> (b[7]) << 56);
607
608}
609
610
611template <class S, class T>
612void
613read (T &in, uint64_t &v)
614{
615 unsigned char b[8];
616
617 readUnsignedChars<S> (in, b, 8);
618
619 v = ((uint64_t) b[0] & 0x00000000000000ffLL) |
620 (((uint64_t) b[1] << 8) & 0x000000000000ff00LL) |
621 (((uint64_t) b[2] << 16) & 0x0000000000ff0000LL) |
622 (((uint64_t) b[3] << 24) & 0x00000000ff000000LL) |
623 (((uint64_t) b[4] << 32) & 0x000000ff00000000LL) |
624 (((uint64_t) b[5] << 40) & 0x0000ff0000000000LL) |
625 (((uint64_t) b[6] << 48) & 0x00ff000000000000LL) |
626 ((uint64_t) b[7] << 56);
627}
628
629
630template <class S, class T>
631void
632read (T &in, float &v)
633{
634 unsigned char b[4];
635
636 readUnsignedChars<S> (in, b, 4);
637
638 union {unsigned int i; float f;} u;
639
640 u.i = (b[0] & 0x000000ff) |
641 ((b[1] << 8) & 0x0000ff00) |
642 ((b[2] << 16) & 0x00ff0000) |
643 (b[3] << 24);
644
645 v = u.f;
646}
647
648
649template <class S, class T>
650void
651read (T &in, double &v)
652{
653 unsigned char b[8];
654
655 readUnsignedChars<S> (in, b, 8);
656
657 union {uint64_t i; double d;} u;
658
659 u.i = ((uint64_t) b[0] & 0x00000000000000ffULL) |
660 (((uint64_t) b[1] << 8) & 0x000000000000ff00ULL) |
661 (((uint64_t) b[2] << 16) & 0x0000000000ff0000ULL) |
662 (((uint64_t) b[3] << 24) & 0x00000000ff000000ULL) |
663 (((uint64_t) b[4] << 32) & 0x000000ff00000000ULL) |
664 (((uint64_t) b[5] << 40) & 0x0000ff0000000000ULL) |
665 (((uint64_t) b[6] << 48) & 0x00ff000000000000ULL) |
666 ((uint64_t) b[7] << 56);
667
668 v = u.d;
669}
670
671
672template <class S, class T>
673inline void
674read (T &in, half &v)
675{
676 unsigned char b[2];
677
678 readUnsignedChars<S> (in, b, 2);
679
680 v.setBits ((b[0] & 0x00ff) | (b[1] << 8));
681}
682
683
684template <class S, class T>
685inline void
686read (T &in, char v[], int n) // fixed-size char array
687{
688 S::readChars (in, v, n);
689}
690
691
692template <class S, class T>
693void
694read (T &in, int n, char v[]) // zero-terminated string
695{
696 while (n >= 0)
697 {
698 S::readChars (in, v, 1);
699
700 if (*v == 0)
701 break;
702
703 --n;
704 ++v;
705 }
706}
707
708
709template <class S, class T>
710void
711skip (T &in, int n) // skip n padding bytes
712{
713 char c[1024];
714
715 while (n >= (int) sizeof (c))
716 {
717 if (!S::readChars (in, c, sizeof (c)))
718 return;
719
720 n -= sizeof (c);
721 }
722
723 if (n >= 1)
724 S::readChars (in, c, n);
725}
726
727
728template <> inline int size <bool> () {return 1;}
729template <> inline int size <char> () {return 1;}
730template <> inline int size <signed char> () {return 1;}
731template <> inline int size <unsigned char> () {return 1;}
732template <> inline int size <signed short> () {return 2;}
733template <> inline int size <unsigned short> () {return 2;}
734template <> inline int size <signed int> () {return 4;}
735template <> inline int size <unsigned int> () {return 4;}
736template <> inline int size <signed long> () {return 8;}
737template <> inline int size <unsigned long> () {return 8;}
738template <> inline int size <unsigned long long> () {return 8;}
739template <> inline int size <float> () {return 4;}
740template <> inline int size <double> () {return 8;}
741template <> inline int size <half> () {return 2;}
742
743
744} // namespace Xdr
745OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
746
747
748#if defined (OPENEXR_IMF_INTERNAL_NAMESPACE_AUTO_EXPOSE)
749namespace Imf{using namespace OPENEXR_IMF_INTERNAL_NAMESPACE;}
750#endif
751
752
753#endif
754

source code of include/OpenEXR/ImfXdr.h