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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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