/src/FreeImage/Source/OpenEXR/IlmImf/ImfXdr.h
C++ Header | 916 lines | 576 code | 223 blank | 117 comment | 32 complexity | c0d4e4802b8c4e2ad476eea7bb680e3f MD5 | raw file
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 110namespace Imf { 111namespace Xdr { 112 113 114//------------------------------- 115// Write data to an output stream 116//------------------------------- 117 118template <class S, class T> 119void 120write (T &out, bool v); 121 122template <class S, class T> 123void 124write (T &out, char v); 125 126template <class S, class T> 127void 128write (T &out, signed char v); 129 130template <class S, class T> 131void 132write (T &out, unsigned char v); 133 134template <class S, class T> 135void 136write (T &out, signed short v); 137 138template <class S, class T> 139void 140write (T &out, unsigned short v); 141 142template <class S, class T> 143void 144write (T &out, signed int v); 145 146template <class S, class T> 147void 148write (T &out, unsigned int v); 149 150template <class S, class T> 151void 152write (T &out, signed long v); 153 154template <class S, class T> 155void 156write (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 166template <class S, class T> 167void 168write (T &out, float v); 169 170template <class S, class T> 171void 172write (T &out, double v); 173 174template <class S, class T> 175void 176write (T &out, half v); 177 178template <class S, class T> 179void 180write (T &out, const char v[/*n*/], int n); // fixed-size char array 181 182template <class S, class T> 183void 184write (T &out, const char v[]); // zero-terminated string 185 186 187//----------------------------------------- 188// Append padding bytes to an output stream 189//----------------------------------------- 190 191template <class S, class T> 192void 193pad (T &out, int n); // write n padding bytes 194 195 196 197//------------------------------- 198// Read data from an input stream 199//------------------------------- 200 201template <class S, class T> 202void 203read (T &in, bool &v); 204 205template <class S, class T> 206void 207read (T &in, char &v); 208 209template <class S, class T> 210void 211read (T &in, signed char &v); 212 213template <class S, class T> 214void 215read (T &in, unsigned char &v); 216 217template <class S, class T> 218void 219read (T &in, signed short &v); 220 221template <class S, class T> 222void 223read (T &in, unsigned short &v); 224 225template <class S, class T> 226void 227read (T &in, signed int &v); 228 229template <class S, class T> 230void 231read (T &in, unsigned int &v); 232 233template <class S, class T> 234void 235read (T &in, signed long &v); 236 237template <class S, class T> 238void 239read (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 249template <class S, class T> 250void 251read (T &in, float &v); 252 253template <class S, class T> 254void 255read (T &in, double &v); 256 257template <class S, class T> 258void 259read (T &in, half &v); 260 261template <class S, class T> 262void 263read (T &in, char v[/*n*/], int n); // fixed-size char array 264 265template <class S, class T> 266void 267read (T &in, int n, char v[/*n*/]); // zero-terminated string 268 269 270//------------------------------------------- 271// Skip over padding bytes in an input stream 272//------------------------------------------- 273 274template <class S, class T> 275void 276skip (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 285template <class S> 286int 287size (); 288 289 290//--------------- 291// Implementation 292//--------------- 293 294template <class S, class T> 295inline void 296writeSignedChars (T &out, const signed char c[], int n) 297{ 298 S::writeChars (out, (const char *) c, n); 299} 300 301 302template <class S, class T> 303inline void 304writeUnsignedChars (T &out, const unsigned char c[], int n) 305{ 306 S::writeChars (out, (const char *) c, n); 307} 308 309 310template <class S, class T> 311inline void 312readSignedChars (T &in, signed char c[], int n) 313{ 314 S::readChars (in, (char *) c, n); 315} 316 317 318template <class S, class T> 319inline void 320readUnsignedChars (T &in, unsigned char c[], int n) 321{ 322 S::readChars (in, (char *) c, n); 323} 324 325 326template <class S, class T> 327inline void 328write (T &out, bool v) 329{ 330 char c = !!v; 331 S::writeChars (out, &c, 1); 332} 333 334 335template <class S, class T> 336inline void 337write (T &out, char v) 338{ 339 S::writeChars (out, &v, 1); 340} 341 342 343template <class S, class T> 344inline void 345write (T &out, signed char v) 346{ 347 writeSignedChars<S> (out, &v, 1); 348} 349 350 351template <class S, class T> 352inline void 353write (T &out, unsigned char v) 354{ 355 writeUnsignedChars<S> (out, &v, 1); 356} 357 358 359template <class S, class T> 360void 361write (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 372template <class S, class T> 373void 374write (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 385template <class S, class T> 386void 387write (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 400template <class S, class T> 401void 402write (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 415template <class S, class T> 416void 417write (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 460template <class S, class T> 461void 462write (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 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 518template <class S, class T> 519void 520write (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 536template <class S, class T> 537void 538write (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 558template <class S, class T> 559inline void 560write (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 571template <class S, class T> 572inline void 573write (T &out, const char v[], int n) // fixed-size char array 574{ 575 S::writeChars (out, v, n); 576} 577 578 579template <class S, class T> 580void 581write (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 593template <class S, class T> 594void 595pad (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 605template <class S, class T> 606inline void 607read (T &in, bool &v) 608{ 609 char c; 610 611 S::readChars (in, &c, 1); 612 v = !!c; 613} 614 615 616template <class S, class T> 617inline void 618read (T &in, char &v) 619{ 620 S::readChars (in, &v, 1); 621} 622 623 624template <class S, class T> 625inline void 626read (T &in, signed char &v) 627{ 628 readSignedChars<S> (in, &v, 1); 629} 630 631 632template <class S, class T> 633inline void 634read (T &in, unsigned char &v) 635{ 636 readUnsignedChars<S> (in, &v, 1); 637} 638 639 640template <class S, class T> 641void 642read (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 653template <class S, class T> 654void 655read (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 666template <class S, class T> 667void 668read (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 681template <class S, class T> 682void 683read (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 696template <class S, class T> 697void 698read (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 737template <class S, class T> 738void 739read (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 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 800template <class S, class T> 801void 802read (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 819template <class S, class T> 820void 821read (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 842template <class S, class T> 843inline void 844read (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 854template <class S, class T> 855inline void 856read (T &in, char v[], int n) // fixed-size char array 857{ 858 S::readChars (in, v, n); 859} 860 861 862template <class S, class T> 863void 864read (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 879template <class S, class T> 880void 881skip (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 898template <> inline int size <bool> () {return 1;} 899template <> inline int size <char> () {return 1;} 900template <> inline int size <signed char> () {return 1;} 901template <> inline int size <unsigned char> () {return 1;} 902template <> inline int size <signed short> () {return 2;} 903template <> inline int size <unsigned short> () {return 2;} 904template <> inline int size <signed int> () {return 4;} 905template <> inline int size <unsigned int> () {return 4;} 906template <> inline int size <signed long> () {return 8;} 907template <> inline int size <unsigned long> () {return 8;} 908template <> inline int size <float> () {return 4;} 909template <> inline int size <double> () {return 8;} 910template <> inline int size <half> () {return 2;} 911 912 913} // namespace Xdr 914} // namespace Imf 915 916#endif