1 /*****************************************************************************/ 2 // Copyright 2006-2007 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_stream.cpp#2 $ */ 10 /* $DateTime: 2012/06/01 07:28:57 $ */ 11 /* $Change: 832715 $ */ 12 /* $Author: tknoll $ */ 13 14 /*****************************************************************************/ 15 16 #include "dng_stream.h" 17 18 #include "dng_abort_sniffer.h" 19 #include "dng_auto_ptr.h" 20 #include "dng_bottlenecks.h" 21 #include "dng_exceptions.h" 22 #include "dng_flags.h" 23 #include "dng_memory.h" 24 #include "dng_tag_types.h" 25 26 /*****************************************************************************/ 27 28 dng_stream::dng_stream (dng_abort_sniffer *sniffer, 29 uint32 bufferSize, 30 uint64 offsetInOriginalFile) 31 32 : fSwapBytes (false) 33 , fHaveLength (false) 34 , fLength (0) 35 , fOffsetInOriginalFile (offsetInOriginalFile) 36 , fPosition (0) 37 , fMemBlock (bufferSize) 38 , fBuffer (fMemBlock.Buffer_uint8 ()) 39 , fBufferSize (bufferSize) 40 , fBufferStart (0) 41 , fBufferEnd (0) 42 , fBufferLimit (bufferSize) 43 , fBufferDirty (false) 44 , fSniffer (sniffer) 45 46 { 47 48 } 49 50 /*****************************************************************************/ 51 52 dng_stream::dng_stream (const void *data, 53 uint32 count, 54 uint64 offsetInOriginalFile) 55 56 : fSwapBytes (false) 57 , fHaveLength (true) 58 , fLength (count) 59 , fOffsetInOriginalFile (offsetInOriginalFile) 60 , fPosition (0) 61 , fMemBlock () 62 , fBuffer ((uint8 *) data) 63 , fBufferSize (count) 64 , fBufferStart (0) 65 , fBufferEnd (count) 66 , fBufferLimit (count) 67 , fBufferDirty (false) 68 , fSniffer (NULL) 69 70 { 71 72 } 73 74 /*****************************************************************************/ 75 76 dng_stream::~dng_stream () 77 { 78 79 } 80 81 /*****************************************************************************/ 82 83 uint64 dng_stream::DoGetLength () 84 { 85 86 ThrowProgramError (); 87 88 return 0; 89 90 } 91 92 /*****************************************************************************/ 93 94 void dng_stream::DoRead (void * /* data */, 95 uint32 /* count */, 96 uint64 /* offset */) 97 { 98 99 ThrowProgramError (); 100 101 } 102 103 /*****************************************************************************/ 104 105 void dng_stream::DoSetLength (uint64 /* length */) 106 { 107 108 ThrowProgramError (); 109 110 } 111 112 /*****************************************************************************/ 113 114 void dng_stream::DoWrite (const void * /* data */, 115 uint32 /* count */, 116 uint64 /* offset */) 117 { 118 119 ThrowProgramError (); 120 121 } 122 123 /*****************************************************************************/ 124 125 bool dng_stream::BigEndian () const 126 { 127 128 return fSwapBytes != (!!qDNGBigEndian); 129 130 } 131 132 /*****************************************************************************/ 133 134 void dng_stream::SetBigEndian (bool bigEndian) 135 { 136 137 fSwapBytes = (bigEndian != (!!qDNGBigEndian)); 138 139 } 140 141 /*****************************************************************************/ 142 143 const void * dng_stream::Data () const 144 { 145 146 if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength) 147 { 148 149 return fBuffer; 150 151 } 152 153 return NULL; 154 155 } 156 157 /*****************************************************************************/ 158 159 dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator) 160 { 161 162 Flush (); 163 164 uint64 len64 = Length (); 165 166 if (len64 > 0xFFFFFFFF) 167 { 168 ThrowProgramError (); 169 } 170 171 uint32 len = (uint32) len64; 172 173 AutoPtr<dng_memory_block> block (allocator.Allocate (len)); 174 175 if (len) 176 { 177 178 SetReadPosition (0); 179 180 Get (block->Buffer (), len); 181 182 } 183 184 return block.Release (); 185 186 } 187 188 /*****************************************************************************/ 189 190 void dng_stream::SetReadPosition (uint64 offset) 191 { 192 193 fPosition = offset; 194 195 if (fPosition > Length ()) 196 { 197 198 ThrowEndOfFile (); 199 200 } 201 202 } 203 204 /*****************************************************************************/ 205 206 uint64 dng_stream::OffsetInOriginalFile () const 207 { 208 209 return fOffsetInOriginalFile; 210 211 } 212 213 /*****************************************************************************/ 214 215 uint64 dng_stream::PositionInOriginalFile () const 216 { 217 218 if (fOffsetInOriginalFile == kDNGStreamInvalidOffset) 219 return kDNGStreamInvalidOffset; 220 221 return fOffsetInOriginalFile + Position (); 222 223 } 224 225 /*****************************************************************************/ 226 227 void dng_stream::Get (void *data, uint32 count) 228 { 229 230 while (count) 231 { 232 233 // See if the request is totally inside buffer. 234 235 if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd) 236 { 237 238 DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart), 239 data, 240 count); 241 242 fPosition += count; 243 244 return; 245 246 } 247 248 // See if first part of request is inside buffer. 249 250 if (fPosition >= fBufferStart && fPosition < fBufferEnd) 251 { 252 253 uint32 block = (uint32) (fBufferEnd - fPosition); 254 255 DoCopyBytes (fBuffer + (fPosition - fBufferStart), 256 data, 257 block); 258 259 count -= block; 260 261 data = (void *) (((char *) data) + block); 262 263 fPosition += block; 264 265 } 266 267 // Flush buffer if dirty. 268 269 Flush (); 270 271 // Do large reads unbuffered. 272 273 if (count > fBufferSize) 274 { 275 276 if (fPosition + count > Length ()) 277 { 278 279 ThrowEndOfFile (); 280 281 } 282 283 DoRead (data, 284 count, 285 fPosition); 286 287 fPosition += count; 288 289 return; 290 291 } 292 293 // Figure out new buffer range. 294 295 fBufferStart = fPosition; 296 297 if (fBufferSize >= 4096) 298 { 299 300 // Align to a 4K file block. 301 302 fBufferStart &= (uint64) ~((int64) 4095); 303 304 } 305 306 fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ()); 307 308 if (fBufferEnd <= fPosition) 309 { 310 311 ThrowEndOfFile (); 312 313 } 314 315 // Read data into buffer. 316 317 dng_abort_sniffer::SniffForAbort (fSniffer); 318 319 DoRead (fBuffer, 320 (uint32) (fBufferEnd - fBufferStart), 321 fBufferStart); 322 323 } 324 325 } 326 327 /*****************************************************************************/ 328 329 void dng_stream::SetWritePosition (uint64 offset) 330 { 331 332 fPosition = offset; 333 334 } 335 336 /*****************************************************************************/ 337 338 void dng_stream::Flush () 339 { 340 341 if (fBufferDirty) 342 { 343 344 dng_abort_sniffer::SniffForAbort (fSniffer); 345 346 DoWrite (fBuffer, 347 (uint32) (fBufferEnd - fBufferStart), 348 fBufferStart); 349 350 fBufferStart = 0; 351 fBufferEnd = 0; 352 fBufferLimit = fBufferSize; 353 354 fBufferDirty = false; 355 356 } 357 358 } 359 360 /*****************************************************************************/ 361 362 void dng_stream::SetLength (uint64 length) 363 { 364 365 Flush (); 366 367 if (Length () != length) 368 { 369 370 DoSetLength (length); 371 372 fLength = length; 373 374 } 375 376 } 377 378 /*****************************************************************************/ 379 380 void dng_stream::Put (const void *data, 381 uint32 count) 382 { 383 384 // See if we can replace or append to the existing buffer. 385 386 uint64 endPosition = fPosition + count; 387 388 if (fBufferDirty && 389 fPosition >= fBufferStart && 390 fPosition <= fBufferEnd && 391 endPosition <= fBufferLimit) 392 { 393 394 DoCopyBytes (data, 395 fBuffer + (uint32) (fPosition - fBufferStart), 396 count); 397 398 if (fBufferEnd < endPosition) 399 fBufferEnd = endPosition; 400 401 } 402 403 // Else we need to write to the file. 404 405 else 406 { 407 408 // Write existing buffer. 409 410 Flush (); 411 412 // Write large blocks unbuffered. 413 414 if (count >= fBufferSize) 415 { 416 417 dng_abort_sniffer::SniffForAbort (fSniffer); 418 419 DoWrite (data, count, fPosition); 420 421 } 422 423 // Start a new buffer with small blocks. 424 425 else 426 { 427 428 fBufferDirty = true; 429 430 fBufferStart = fPosition; 431 fBufferEnd = endPosition; 432 fBufferLimit = fBufferStart + fBufferSize; 433 434 DoCopyBytes (data, 435 fBuffer, 436 count); 437 438 } 439 440 } 441 442 fPosition = endPosition; 443 444 fLength = Max_uint64 (Length (), fPosition); 445 446 } 447 448 /*****************************************************************************/ 449 450 uint16 dng_stream::Get_uint16 () 451 { 452 453 uint16 x; 454 455 Get (&x, 2); 456 457 if (fSwapBytes) 458 { 459 460 x = SwapBytes16 (x); 461 462 } 463 464 return x; 465 466 } 467 468 /*****************************************************************************/ 469 470 void dng_stream::Put_uint16 (uint16 x) 471 { 472 473 if (fSwapBytes) 474 { 475 476 x = SwapBytes16 (x); 477 478 } 479 480 Put (&x, 2); 481 482 } 483 484 /*****************************************************************************/ 485 486 uint32 dng_stream::Get_uint32 () 487 { 488 489 uint32 x; 490 491 Get (&x, 4); 492 493 if (fSwapBytes) 494 { 495 496 x = SwapBytes32 (x); 497 498 } 499 500 return x; 501 502 } 503 504 /*****************************************************************************/ 505 506 void dng_stream::Put_uint32 (uint32 x) 507 { 508 509 if (fSwapBytes) 510 { 511 512 x = SwapBytes32 (x); 513 514 } 515 516 Put (&x, 4); 517 518 } 519 520 /*****************************************************************************/ 521 522 uint64 dng_stream::Get_uint64 () 523 { 524 525 if (fSwapBytes) 526 { 527 528 union 529 { 530 uint32 u32 [2]; 531 uint64 u64; 532 } u; 533 534 u.u32 [1] = Get_uint32 (); 535 u.u32 [0] = Get_uint32 (); 536 537 return u.u64; 538 539 } 540 541 uint64 x; 542 543 Get (&x, 8); 544 545 return x; 546 547 } 548 549 /*****************************************************************************/ 550 551 void dng_stream::Put_uint64 (uint64 x) 552 { 553 554 if (fSwapBytes) 555 { 556 557 union 558 { 559 uint32 u32 [2]; 560 uint64 u64; 561 } u; 562 563 u.u64 = x; 564 565 Put_uint32 (u.u32 [1]); 566 Put_uint32 (u.u32 [0]); 567 568 } 569 570 else 571 { 572 573 Put (&x, 8); 574 575 } 576 577 } 578 579 /*****************************************************************************/ 580 581 real32 dng_stream::Get_real32 () 582 { 583 584 union 585 { 586 uint32 i; 587 real32 r; 588 } u; 589 590 u.i = Get_uint32 (); 591 592 return u.r; 593 594 } 595 596 /*****************************************************************************/ 597 598 void dng_stream::Put_real32 (real32 x) 599 { 600 601 if (fSwapBytes) 602 { 603 604 union 605 { 606 uint32 i; 607 real32 r; 608 } u; 609 610 u.r = x; 611 612 Put_uint32 (u.i); 613 614 } 615 616 else 617 { 618 619 Put (&x, 4); 620 621 } 622 623 } 624 625 /*****************************************************************************/ 626 627 real64 dng_stream::Get_real64 () 628 { 629 630 if (fSwapBytes) 631 { 632 633 union 634 { 635 uint32 i [2]; 636 real64 r; 637 } u; 638 639 u.i [1] = Get_uint32 (); 640 u.i [0] = Get_uint32 (); 641 642 return u.r; 643 644 } 645 646 real64 x; 647 648 Get (&x, 8); 649 650 return x; 651 652 } 653 654 /*****************************************************************************/ 655 656 void dng_stream::Put_real64 (real64 x) 657 { 658 659 if (fSwapBytes) 660 { 661 662 union 663 { 664 uint32 i [2]; 665 real64 r; 666 } u; 667 668 u.r = x; 669 670 Put_uint32 (u.i [1]); 671 Put_uint32 (u.i [0]); 672 673 } 674 675 else 676 { 677 678 Put (&x, 8); 679 680 } 681 682 } 683 684 /*****************************************************************************/ 685 686 void dng_stream::Get_CString (char *data, uint32 maxLength) 687 { 688 689 memset (data, 0, maxLength); 690 691 uint32 index = 0; 692 693 while (true) 694 { 695 696 char c = (char) Get_uint8 (); 697 698 if (index + 1 < maxLength) 699 data [index++] = c; 700 701 if (c == 0) 702 break; 703 704 } 705 706 } 707 708 /*****************************************************************************/ 709 710 void dng_stream::Get_UString (char *data, uint32 maxLength) 711 { 712 713 memset (data, 0, maxLength); 714 715 uint32 index = 0; 716 717 while (true) 718 { 719 720 char c = (char) Get_uint16 (); 721 722 if (index + 1 < maxLength) 723 data [index++] = (char) c; 724 725 if (c == 0) 726 break; 727 728 } 729 730 } 731 732 /*****************************************************************************/ 733 734 void dng_stream::PutZeros (uint64 count) 735 { 736 737 const uint32 kZeroBufferSize = 4096; 738 739 if (count >= kZeroBufferSize) 740 { 741 742 dng_memory_data zeroBuffer (kZeroBufferSize); 743 744 DoZeroBytes (zeroBuffer.Buffer (), 745 kZeroBufferSize); 746 747 while (count) 748 { 749 750 uint64 blockSize = Min_uint64 (count, kZeroBufferSize); 751 752 Put (zeroBuffer.Buffer (), (uint32) blockSize); 753 754 count -= blockSize; 755 756 } 757 758 } 759 760 else 761 { 762 763 uint32 count32 = (uint32) count; 764 765 for (uint32 j = 0; j < count32; j++) 766 { 767 768 Put_uint8 (0); 769 770 } 771 772 } 773 774 } 775 776 /*****************************************************************************/ 777 778 void dng_stream::PadAlign2 () 779 { 780 781 PutZeros (Position () & 1); 782 783 } 784 785 /*****************************************************************************/ 786 787 void dng_stream::PadAlign4 () 788 { 789 790 PutZeros ((4 - (Position () & 3)) & 3); 791 792 } 793 794 /*****************************************************************************/ 795 796 uint32 dng_stream::TagValue_uint32 (uint32 tagType) 797 { 798 799 switch (tagType) 800 { 801 802 case ttByte: 803 return (uint32) Get_uint8 (); 804 805 case ttShort: 806 return (uint32) Get_uint16 (); 807 808 case ttLong: 809 case ttIFD: 810 return Get_uint32 (); 811 812 } 813 814 real64 x = TagValue_real64 (tagType); 815 816 if (x < 0.0) 817 x = 0.0; 818 819 if (x > (real64) 0xFFFFFFFF) 820 x = (real64) 0xFFFFFFFF; 821 822 return ConvertDoubleToUint32(x + 0.5); 823 824 } 825 826 /*****************************************************************************/ 827 828 int32 dng_stream::TagValue_int32 (uint32 tagType) 829 { 830 831 switch (tagType) 832 { 833 834 case ttSByte: 835 return (int32) Get_int8 (); 836 837 case ttSShort: 838 return (int32) Get_int16 (); 839 840 case ttSLong: 841 return Get_int32 (); 842 843 } 844 845 real64 x = TagValue_real64 (tagType); 846 847 if (x < 0.0) 848 { 849 850 if (x < -2147483648.0) 851 x = -2147483648.0; 852 853 return ConvertDoubleToInt32(x - 0.5); 854 855 } 856 857 else 858 { 859 860 if (x > 2147483647.0) 861 x = 2147483647.0; 862 863 return ConvertDoubleToInt32(x + 0.5); 864 865 } 866 867 } 868 869 /*****************************************************************************/ 870 871 dng_urational dng_stream::TagValue_urational (uint32 tagType) 872 { 873 874 dng_urational result; 875 876 result.n = 0; 877 result.d = 1; 878 879 switch (tagType) 880 { 881 882 case ttRational: 883 { 884 885 result.n = Get_uint32 (); 886 result.d = Get_uint32 (); 887 888 break; 889 890 } 891 892 case ttSRational: 893 { 894 895 int32 n = Get_int32 (); 896 int32 d = Get_int32 (); 897 898 if ((n < 0) == (d < 0)) 899 { 900 901 if (d < 0) 902 { 903 result.n = (uint32) ((int64) n * -1); 904 result.d = (uint32) ((int64) d * -1); 905 } 906 else 907 { 908 result.n = (uint32) n; 909 result.d = (uint32) d; 910 } 911 912 } 913 914 break; 915 916 } 917 918 case ttByte: 919 case ttShort: 920 case ttLong: 921 case ttIFD: 922 { 923 924 result.n = TagValue_uint32 (tagType); 925 926 break; 927 928 } 929 930 case ttSByte: 931 case ttSShort: 932 case ttSLong: 933 { 934 935 int32 n = TagValue_int32 (tagType); 936 937 if (n > 0) 938 { 939 result.n = (uint32) n; 940 } 941 942 break; 943 944 } 945 946 default: 947 { 948 949 real64 x = TagValue_real64 (tagType); 950 951 if (x > 0.0) 952 { 953 954 while (result.d < 10000 && x < 1000000) 955 { 956 957 result.d *= 10; 958 959 x *= 10.0; 960 961 } 962 963 result.n = ConvertDoubleToUint32(x + 0.5); 964 965 } 966 967 } 968 969 } 970 971 return result; 972 973 } 974 975 /*****************************************************************************/ 976 977 dng_srational dng_stream::TagValue_srational (uint32 tagType) 978 { 979 980 dng_srational result; 981 982 result.n = 0; 983 result.d = 1; 984 985 switch (tagType) 986 { 987 988 case ttSRational: 989 { 990 991 result.n = Get_int32 (); 992 result.d = Get_int32 (); 993 994 break; 995 996 } 997 998 default: 999 { 1000 1001 real64 x = TagValue_real64 (tagType); 1002 1003 if (x > 0.0) 1004 { 1005 1006 while (result.d < 10000 && x < 1000000.0) 1007 { 1008 1009 result.d *= 10; 1010 1011 x *= 10.0; 1012 1013 } 1014 1015 result.n = ConvertDoubleToInt32(x + 0.5); 1016 1017 } 1018 1019 else 1020 { 1021 1022 while (result.d < 10000 && x > -1000000.0) 1023 { 1024 1025 result.d *= 10; 1026 1027 x *= 10.0; 1028 1029 } 1030 1031 result.n = ConvertDoubleToInt32(x - 0.5); 1032 1033 } 1034 1035 } 1036 1037 } 1038 1039 return result; 1040 1041 } 1042 1043 /*****************************************************************************/ 1044 1045 real64 dng_stream::TagValue_real64 (uint32 tagType) 1046 { 1047 1048 switch (tagType) 1049 { 1050 1051 case ttByte: 1052 case ttShort: 1053 case ttLong: 1054 case ttIFD: 1055 return (real64) TagValue_uint32 (tagType); 1056 1057 case ttSByte: 1058 case ttSShort: 1059 case ttSLong: 1060 return (real64) TagValue_int32 (tagType); 1061 1062 case ttRational: 1063 { 1064 1065 uint32 n = Get_uint32 (); 1066 uint32 d = Get_uint32 (); 1067 1068 if (d == 0) 1069 return 0.0; 1070 else 1071 return (real64) n / (real64) d; 1072 1073 } 1074 1075 case ttSRational: 1076 { 1077 1078 int32 n = Get_int32 (); 1079 int32 d = Get_int32 (); 1080 1081 if (d == 0) 1082 return 0.0; 1083 else 1084 return (real64) n / (real64) d; 1085 1086 } 1087 1088 case ttFloat: 1089 return (real64) Get_real32 (); 1090 1091 case ttDouble: 1092 return Get_real64 (); 1093 1094 } 1095 1096 return 0.0; 1097 1098 } 1099 1100 /*****************************************************************************/ 1101 1102 void dng_stream::CopyToStream (dng_stream &dstStream, 1103 uint64 count) 1104 { 1105 1106 uint8 smallBuffer [1024]; 1107 1108 if (count <= sizeof (smallBuffer)) 1109 { 1110 1111 Get (smallBuffer, (uint32) count); 1112 1113 dstStream.Put (smallBuffer, (uint32) count); 1114 1115 } 1116 1117 else 1118 { 1119 1120 const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize, 1121 count); 1122 1123 dng_memory_data bigBuffer (bigBufferSize); 1124 1125 while (count) 1126 { 1127 1128 uint32 blockCount = (uint32) Min_uint64 (bigBufferSize, 1129 count); 1130 1131 Get (bigBuffer.Buffer (), 1132 blockCount); 1133 1134 dstStream.Put (bigBuffer.Buffer (), 1135 blockCount); 1136 1137 count -= blockCount; 1138 1139 } 1140 1141 } 1142 1143 } 1144 1145 /*****************************************************************************/ 1146 1147 void dng_stream::DuplicateStream (dng_stream &dstStream) 1148 { 1149 1150 // Turn off sniffers for this operation. 1151 1152 TempStreamSniffer noSniffer1 (*this , NULL); 1153 TempStreamSniffer noSniffer2 (dstStream, NULL); 1154 1155 // First grow the destination stream if required, in an attempt to 1156 // reserve any needed space before overwriting the existing data. 1157 1158 if (dstStream.Length () < Length ()) 1159 { 1160 dstStream.SetLength (Length ()); 1161 } 1162 1163 SetReadPosition (0); 1164 1165 dstStream.SetWritePosition (0); 1166 1167 CopyToStream (dstStream, Length ()); 1168 1169 dstStream.Flush (); 1170 1171 dstStream.SetLength (Length ()); 1172 1173 } 1174 1175 /*****************************************************************************/ 1176 1177 TempBigEndian::TempBigEndian (dng_stream &stream, 1178 bool bigEndian) 1179 1180 : fStream (stream) 1181 , fOldSwap (stream.SwapBytes ()) 1182 1183 { 1184 1185 fStream.SetBigEndian (bigEndian); 1186 1187 } 1188 1189 /*****************************************************************************/ 1190 1191 TempBigEndian::~TempBigEndian () 1192 { 1193 1194 fStream.SetSwapBytes (fOldSwap); 1195 1196 } 1197 1198 /*****************************************************************************/ 1199 1200 TempStreamSniffer::TempStreamSniffer (dng_stream &stream, 1201 dng_abort_sniffer *sniffer) 1202 1203 : fStream (stream) 1204 , fOldSniffer (stream.Sniffer ()) 1205 1206 { 1207 1208 fStream.SetSniffer (sniffer); 1209 1210 } 1211 1212 /*****************************************************************************/ 1213 1214 TempStreamSniffer::~TempStreamSniffer () 1215 { 1216 1217 fStream.SetSniffer (fOldSniffer); 1218 1219 } 1220 1221 /*****************************************************************************/ 1222