File indexing completed on 2025-01-19 03:55:16

0001 /*****************************************************************************/
0002 // Copyright 2006-2019 Adobe Systems Incorporated
0003 // All Rights Reserved.
0004 //
0005 // NOTICE:  Adobe permits you to use, modify, and distribute this file in
0006 // accordance with the terms of the Adobe license agreement accompanying it.
0007 /*****************************************************************************/
0008 
0009 #include "dng_stream.h"
0010 
0011 #include "dng_abort_sniffer.h"
0012 #include "dng_auto_ptr.h"
0013 #include "dng_bottlenecks.h"
0014 #include "dng_exceptions.h"
0015 #include "dng_globals.h"
0016 #include "dng_flags.h"
0017 #include "dng_memory.h"
0018 #include "dng_tag_types.h"
0019 #include "dng_assertions.h"
0020 
0021 /*****************************************************************************/
0022 
0023 dng_stream::dng_stream (dng_abort_sniffer *sniffer,
0024                         uint32 bufferSize,
0025                         uint64 offsetInOriginalFile)
0026 
0027     :   fSwapBytes            (false)
0028     ,   fHaveLength           (false)
0029     ,   fLength               (0)
0030     ,   fOffsetInOriginalFile (offsetInOriginalFile)
0031     ,   fPosition             (0)
0032     ,   fMemBlock             ()
0033     ,   fBuffer               (NULL)
0034     ,   fBufferSize           (Max_uint32 (bufferSize, gDNGStreamBlockSize * 2))
0035     ,   fBufferStart          (0)
0036     ,   fBufferEnd            (0)
0037     ,   fBufferLimit          (bufferSize)
0038     ,   fBufferDirty          (false)
0039     ,   fSniffer              (sniffer)
0040 
0041     {
0042 
0043     fMemBlock.Reset (gDefaultDNGMemoryAllocator.Allocate (fBufferSize));
0044 
0045     fBuffer = fMemBlock->Buffer_uint8 ();
0046 
0047     }
0048 
0049 /*****************************************************************************/
0050 
0051 dng_stream::dng_stream (const void *data,
0052                         uint32 count,
0053                         uint64 offsetInOriginalFile)
0054 
0055     :   fSwapBytes            (false)
0056     ,   fHaveLength           (true)
0057     ,   fLength               (count)
0058     ,   fOffsetInOriginalFile (offsetInOriginalFile)
0059     ,   fPosition             (0)
0060     ,   fMemBlock             ()
0061     ,   fBuffer               ((uint8 *) data)
0062     ,   fBufferSize           (count)
0063     ,   fBufferStart          (0)
0064     ,   fBufferEnd            (count)
0065     ,   fBufferLimit          (count)
0066     ,   fBufferDirty          (false)
0067     ,   fSniffer              (NULL)
0068 
0069     {
0070 
0071     }
0072 
0073 /*****************************************************************************/
0074 
0075 dng_stream::~dng_stream ()
0076     {
0077 
0078     }
0079 
0080 /*****************************************************************************/
0081 
0082 uint64 dng_stream::DoGetLength ()
0083     {
0084 
0085     ThrowProgramError ();
0086 
0087     return 0;
0088 
0089     }
0090 
0091 /*****************************************************************************/
0092 
0093 void dng_stream::DoRead (void * /* data */,
0094                          uint32 /* count */,
0095                          uint64 /* offset */)
0096     {
0097 
0098     ThrowProgramError ();
0099 
0100     }
0101 
0102 /*****************************************************************************/
0103 
0104 void dng_stream::DoSetLength (uint64 /* length */)
0105     {
0106 
0107     ThrowProgramError ();
0108 
0109     }
0110 
0111 /*****************************************************************************/
0112 
0113 void dng_stream::DoWrite (const void * /* data */,
0114                           uint32 /* count */,
0115                           uint64 /* offset */)
0116     {
0117 
0118     ThrowProgramError ();
0119 
0120     }
0121 
0122 /*****************************************************************************/
0123 
0124 bool dng_stream::BigEndian () const
0125     {
0126 
0127     return fSwapBytes != (!!qDNGBigEndian);
0128 
0129     }
0130 
0131 /*****************************************************************************/
0132 
0133 void dng_stream::SetBigEndian (bool bigEndian)
0134     {
0135 
0136     fSwapBytes = (bigEndian != (!!qDNGBigEndian));
0137 
0138     }
0139 
0140 /*****************************************************************************/
0141 
0142 void dng_stream::SetBufferSize (dng_memory_allocator &allocator,
0143                                 uint32 newBufferSize)
0144     {
0145 
0146     if (newBufferSize != fBufferSize &&
0147         newBufferSize >= gDNGStreamBlockSize * 2 &&
0148         !Data () &&
0149         !fBufferDirty)
0150         {
0151 
0152         try
0153             {
0154 
0155             fMemBlock.Reset (allocator.Allocate (newBufferSize));
0156 
0157             fBuffer = fMemBlock->Buffer_uint8 ();
0158 
0159             fBufferSize  = newBufferSize;
0160 
0161             fBufferStart = 0;
0162             fBufferEnd   = 0;
0163             fBufferLimit = newBufferSize;
0164 
0165             }
0166 
0167         catch (...)
0168             {
0169 
0170             }
0171 
0172         }
0173 
0174     }
0175 
0176 /*****************************************************************************/
0177 
0178 const void * dng_stream::Data () const
0179     {
0180 
0181     if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
0182         {
0183 
0184         return fBuffer;
0185 
0186         }
0187 
0188     return NULL;
0189 
0190     }
0191 
0192 /*****************************************************************************/
0193 
0194 dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
0195     {
0196 
0197     Flush ();
0198 
0199     uint64 len64 = Length ();
0200 
0201     if (len64 > 0xFFFFFFFF)
0202         {
0203         ThrowProgramError ();
0204         }
0205 
0206     uint32 len = (uint32) len64;
0207 
0208     AutoPtr<dng_memory_block> block (allocator.Allocate (len));
0209 
0210     if (len)
0211         {
0212 
0213         SetReadPosition (0);
0214 
0215         Get (block->Buffer (), len);
0216 
0217         }
0218 
0219     return block.Release ();
0220 
0221     }
0222 
0223 /*****************************************************************************/
0224 
0225 void dng_stream::SetReadPosition (uint64 offset)
0226     {
0227 
0228     fPosition = offset;
0229 
0230     if (fPosition > Length ())
0231         {
0232 
0233         ThrowEndOfFile ();
0234 
0235         }
0236 
0237     }
0238 
0239 /*****************************************************************************/
0240 
0241 uint64 dng_stream::OffsetInOriginalFile () const
0242     {
0243 
0244     return fOffsetInOriginalFile;
0245 
0246     }
0247 
0248 /*****************************************************************************/
0249 
0250 uint64 dng_stream::PositionInOriginalFile () const
0251     {
0252 
0253     if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
0254         return kDNGStreamInvalidOffset;
0255 
0256     return fOffsetInOriginalFile + Position ();
0257 
0258     }
0259 
0260 /*****************************************************************************/
0261 
0262 void dng_stream::Get (void *data, uint32 count, uint32 maxOverRead)
0263     {
0264 
0265     while (count)
0266         {
0267 
0268         // See if the request is totally inside buffer.
0269 
0270         if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
0271             {
0272 
0273             memcpy (data,
0274                     fBuffer + (uint32) (fPosition - fBufferStart),
0275                     count);
0276 
0277             fPosition += count;
0278 
0279             return;
0280 
0281             }
0282 
0283         // See if first part of request is inside buffer.
0284 
0285         if (fPosition >= fBufferStart && fPosition < fBufferEnd)
0286             {
0287 
0288             uint32 block = (uint32) (fBufferEnd - fPosition);
0289 
0290             memcpy (data,
0291                     fBuffer + (fPosition - fBufferStart),
0292                     block);
0293 
0294             count -= block;
0295 
0296             data = (void *) (((char *) data) + block);
0297 
0298             fPosition += block;
0299 
0300             }
0301 
0302         // Flush buffer if dirty.
0303 
0304         Flush ();
0305 
0306         // Do large reads unbuffered.
0307 
0308         if (count > fBufferSize)
0309             {
0310             DNG_ASSERT(maxOverRead == 0, "Over-read of large size unexpected");
0311             if (fPosition + count > Length ())
0312                 {
0313 
0314                 ThrowEndOfFile ();
0315 
0316                 }
0317 
0318             DoRead (data,
0319                     count,
0320                     fPosition);
0321 
0322             fPosition += count;
0323 
0324             return;
0325 
0326             }
0327 
0328         // Figure out new buffer range.
0329 
0330         fBufferStart = fPosition;
0331 
0332         if (fBufferSize >= gDNGStreamBlockSize)
0333             {
0334 
0335             // Align to a file block.
0336 
0337             fBufferStart &= (uint64) ~((int64) (gDNGStreamBlockSize - 1));
0338 
0339             }
0340 
0341         fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
0342 
0343         if ((fBufferEnd - fPosition) < maxOverRead)
0344             return; // ep, allow over-read requests
0345         else
0346         if (fBufferEnd <= fPosition)
0347             {
0348 
0349             ThrowEndOfFile ();
0350 
0351             }
0352 
0353         // Read data into buffer.
0354 
0355         dng_abort_sniffer::SniffForAbort (fSniffer);
0356 
0357         DoRead (fBuffer,
0358                 (uint32) (fBufferEnd - fBufferStart),
0359                 fBufferStart);
0360 
0361         }
0362 
0363     }
0364 
0365 /*****************************************************************************/
0366 
0367 void dng_stream::SetWritePosition (uint64 offset)
0368     {
0369 
0370     fPosition = offset;
0371 
0372     }
0373 
0374 /*****************************************************************************/
0375 
0376 void dng_stream::Flush ()
0377     {
0378 
0379     if (fBufferDirty)
0380         {
0381 
0382         dng_abort_sniffer::SniffForAbort (fSniffer);
0383 
0384         DoWrite (fBuffer,
0385                  (uint32) (fBufferEnd - fBufferStart),
0386                  fBufferStart);
0387 
0388         fBufferStart = 0;
0389         fBufferEnd   = 0;
0390         fBufferLimit = fBufferSize;
0391 
0392         fBufferDirty = false;
0393 
0394         }
0395 
0396     }
0397 
0398 /*****************************************************************************/
0399 
0400 void dng_stream::SetLength (uint64 length)
0401     {
0402 
0403     Flush ();
0404 
0405     if (Length () != length)
0406         {
0407 
0408         DoSetLength (length);
0409 
0410         fLength = length;
0411 
0412         }
0413 
0414     }
0415 
0416 /*****************************************************************************/
0417 
0418 void dng_stream::Put (const void *data,
0419                       uint32 count)
0420     {
0421 
0422     // See if we can replace or append to the existing buffer.
0423 
0424     uint64 endPosition = fPosition + count;
0425 
0426     if (fBufferDirty                &&
0427         fPosition   >= fBufferStart &&
0428         fPosition   <= fBufferEnd   &&
0429         endPosition <= fBufferLimit)
0430         {
0431 
0432         memcpy (fBuffer + (uint32) (fPosition - fBufferStart),
0433                 data,
0434                 count);
0435 
0436         if (fBufferEnd < endPosition)
0437             fBufferEnd = endPosition;
0438 
0439         }
0440 
0441     // Else we need to write to the file.
0442 
0443     else
0444         {
0445 
0446         // Write initial part of the data to buffer, if possible.
0447 
0448         if (fBufferDirty &&
0449             fPosition >= fBufferStart &&
0450             fPosition <= fBufferEnd   &&
0451             fPosition <  fBufferLimit)
0452             {
0453 
0454             uint32 subCount = (uint32) (fBufferLimit - fPosition);
0455 
0456             memcpy (fBuffer + (uint32) (fPosition - fBufferStart),
0457                     data,
0458                     subCount);
0459 
0460             count -= subCount;
0461             data   = (const void *) (((const uint8 *) data) + subCount);
0462 
0463             fPosition  = fBufferLimit;
0464             fBufferEnd = fBufferLimit;
0465 
0466             }
0467 
0468         // Write existing buffer.
0469 
0470         Flush ();
0471 
0472         // Figure out how much space we have in buffer from
0473         // current position to end of file block.
0474 
0475         uint64 blockRound = gDNGStreamBlockSize - 1;
0476 
0477         uint64 blockMask = ~((int64) blockRound);
0478 
0479         uint32 alignedSize = (uint32)
0480                              (((fPosition + fBufferSize) & blockMask) - fPosition);
0481 
0482         // If write request will not fit in buffer, then write everything except
0483         // for the final unaligned part of the data.
0484 
0485         if (count > alignedSize)
0486             {
0487 
0488             uint32 alignedCount = (uint32)
0489                                   (((fPosition + count) & blockMask) - fPosition);
0490 
0491             dng_abort_sniffer::SniffForAbort (fSniffer);
0492 
0493             DoWrite (data, alignedCount, fPosition);
0494 
0495             count -= alignedCount;
0496             data   = (const void *) (((const uint8 *) data) + alignedCount);
0497 
0498             fPosition += alignedCount;
0499 
0500             }
0501 
0502         // Start a new buffer with small blocks.
0503 
0504         if (count > 0)
0505             {
0506 
0507             fBufferDirty = true;
0508 
0509             fBufferStart = fPosition;
0510             fBufferEnd   = endPosition;
0511             fBufferLimit = (fBufferStart + fBufferSize) & blockMask;
0512 
0513             memcpy (fBuffer,
0514                     data,
0515                     count);
0516 
0517             }
0518 
0519         }
0520 
0521     fPosition = endPosition;
0522 
0523     fLength = Max_uint64 (Length (), fPosition);
0524 
0525     }
0526 
0527 /*****************************************************************************/
0528 
0529 uint16 dng_stream::Get_uint16 ()
0530     {
0531 
0532     uint16 x;
0533 
0534     Get (&x, 2);
0535 
0536     if (fSwapBytes)
0537         {
0538 
0539         x = SwapBytes16 (x);
0540 
0541         }
0542 
0543     return x;
0544 
0545     }
0546 
0547 /*****************************************************************************/
0548 
0549 void dng_stream::Put_uint16 (uint16 x)
0550     {
0551 
0552     if (fSwapBytes)
0553         {
0554 
0555         x = SwapBytes16 (x);
0556 
0557         }
0558 
0559     Put (&x, 2);
0560 
0561     }
0562 
0563 /*****************************************************************************/
0564 uint32 dng_stream::Get_uint32 ()
0565     {
0566 
0567     uint32 x;
0568 
0569     Get (&x, 4);
0570 
0571     if (fSwapBytes)
0572         {
0573 
0574         x = SwapBytes32 (x);
0575 
0576         }
0577 
0578     return x;
0579 
0580     }
0581 
0582 /*****************************************************************************/
0583 
0584 void dng_stream::Put_uint32 (uint32 x)
0585     {
0586 
0587     if (fSwapBytes)
0588         {
0589 
0590         x = SwapBytes32 (x);
0591 
0592         }
0593 
0594     Put (&x, 4);
0595 
0596     }
0597 
0598 /*****************************************************************************/
0599 
0600 uint64 dng_stream::Get_uint64 ()
0601     {
0602 
0603     if (fSwapBytes)
0604         {
0605 
0606         union
0607             {
0608             uint32 u32 [2];
0609             uint64 u64;
0610             } u;
0611 
0612         u.u32 [1] = Get_uint32 ();
0613         u.u32 [0] = Get_uint32 ();
0614 
0615         return u.u64;
0616 
0617         }
0618 
0619     uint64 x;
0620 
0621     Get (&x, 8);
0622 
0623     return x;
0624 
0625     }
0626 
0627 /*****************************************************************************/
0628 
0629 void dng_stream::Put_uint64 (uint64 x)
0630     {
0631 
0632     if (fSwapBytes)
0633         {
0634 
0635         union
0636             {
0637             uint32 u32 [2];
0638             uint64 u64;
0639             } u;
0640 
0641         u.u64 = x;
0642 
0643         Put_uint32 (u.u32 [1]);
0644         Put_uint32 (u.u32 [0]);
0645 
0646         }
0647 
0648     else
0649         {
0650 
0651         Put (&x, 8);
0652 
0653         }
0654 
0655     }
0656 
0657 /*****************************************************************************/
0658 
0659 real32 dng_stream::Get_real32 ()
0660     {
0661 
0662     union
0663         {
0664         uint32 i;
0665         real32 r;
0666         } u;
0667 
0668     u.i = Get_uint32 ();
0669 
0670     return u.r;
0671 
0672     }
0673 
0674 /*****************************************************************************/
0675 
0676 void dng_stream::Put_real32 (real32 x)
0677     {
0678 
0679     if (fSwapBytes)
0680         {
0681 
0682         union
0683             {
0684             uint32 i;
0685             real32 r;
0686             } u;
0687 
0688         u.r = x;
0689 
0690         Put_uint32 (u.i);
0691 
0692         }
0693 
0694     else
0695         {
0696 
0697         Put (&x, 4);
0698 
0699         }
0700 
0701     }
0702 
0703 /*****************************************************************************/
0704 
0705 real64 dng_stream::Get_real64 ()
0706     {
0707 
0708     if (fSwapBytes)
0709         {
0710 
0711         union
0712             {
0713             uint32 i [2];
0714             real64 r;
0715             } u;
0716 
0717         u.i [1] = Get_uint32 ();
0718         u.i [0] = Get_uint32 ();
0719 
0720         return u.r;
0721 
0722         }
0723 
0724     real64 x;
0725 
0726     Get (&x, 8);
0727 
0728     return x;
0729 
0730     }
0731 
0732 /*****************************************************************************/
0733 
0734 void dng_stream::Put_real64 (real64 x)
0735     {
0736 
0737     if (fSwapBytes)
0738         {
0739 
0740         union
0741             {
0742             uint32 i [2];
0743             real64 r;
0744             } u;
0745 
0746         u.r = x;
0747 
0748         Put_uint32 (u.i [1]);
0749         Put_uint32 (u.i [0]);
0750 
0751         }
0752 
0753     else
0754         {
0755 
0756         Put (&x, 8);
0757 
0758         }
0759 
0760     }
0761 
0762 /*****************************************************************************/
0763 
0764 void dng_stream::Get_CString (char *data, uint32 maxLength)
0765     {
0766 
0767     memset (data, 0, maxLength);
0768 
0769     uint32 index = 0;
0770 
0771     while (true)
0772         {
0773 
0774         char c = (char) Get_uint8 ();
0775 
0776         if (index + 1 < maxLength)
0777             data [index++] = c;
0778 
0779         if (c == 0)
0780             break;
0781 
0782         }
0783 
0784     }
0785 
0786 /*****************************************************************************/
0787 
0788 void dng_stream::Get_UString (char *data, uint32 maxLength)
0789     {
0790 
0791     memset (data, 0, maxLength);
0792 
0793     uint32 index = 0;
0794 
0795     while (true)
0796         {
0797 
0798         char c = (char) Get_uint16 ();
0799 
0800         if (index + 1 < maxLength)
0801             data [index++] = (char) c;
0802 
0803         if (c == 0)
0804             break;
0805 
0806         }
0807 
0808     }
0809 
0810 /*****************************************************************************/
0811 
0812 void dng_stream::PutZeros (uint64 count)
0813     {
0814 
0815     const uint32 kZeroBufferSize = 4096;
0816 
0817     if (count >= kZeroBufferSize)
0818         {
0819 
0820         dng_memory_data zeroBuffer (kZeroBufferSize);
0821 
0822         DoZeroBytes (zeroBuffer.Buffer (),
0823                      kZeroBufferSize);
0824 
0825         while (count)
0826             {
0827 
0828             uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
0829 
0830             Put (zeroBuffer.Buffer (), (uint32) blockSize);
0831 
0832             count -= blockSize;
0833 
0834             }
0835 
0836         }
0837 
0838     else
0839         {
0840 
0841         uint32 count32 = (uint32) count;
0842 
0843         for (uint32 j = 0; j < count32; j++)
0844             {
0845 
0846             Put_uint8 (0);
0847 
0848             }
0849 
0850         }
0851 
0852     }
0853 
0854 /*****************************************************************************/
0855 
0856 void dng_stream::PadAlign2 ()
0857     {
0858 
0859     PutZeros (Position () & 1);
0860 
0861     }
0862 
0863 /*****************************************************************************/
0864 
0865 void dng_stream::PadAlign4 ()
0866     {
0867 
0868     PutZeros ((4 - (Position () & 3)) & 3);
0869 
0870     }
0871 
0872 /*****************************************************************************/
0873 
0874 uint32 dng_stream::TagValue_uint32 (uint32 tagType)
0875     {
0876 
0877     switch (tagType)
0878         {
0879 
0880         case ttByte:
0881             return (uint32) Get_uint8 ();
0882 
0883         case ttShort:
0884             return (uint32) Get_uint16 ();
0885 
0886         case ttLong:
0887         case ttIFD:
0888             return Get_uint32 ();
0889 
0890         }
0891 
0892     real64 x = TagValue_real64 (tagType);
0893 
0894     if (x < 0.0)
0895         x = 0.0;
0896 
0897     if (x > (real64) 0xFFFFFFFF)
0898         x = (real64) 0xFFFFFFFF;
0899 
0900     return (uint32) (x + 0.5);
0901 
0902     }
0903 
0904 /*****************************************************************************/
0905 
0906 int32 dng_stream::TagValue_int32 (uint32 tagType)
0907     {
0908 
0909     switch (tagType)
0910         {
0911 
0912         case ttSByte:
0913             return (int32) Get_int8 ();
0914 
0915         case ttSShort:
0916             return (int32) Get_int16 ();
0917 
0918         case ttSLong:
0919             return Get_int32 ();
0920 
0921         }
0922 
0923     real64 x = TagValue_real64 (tagType);
0924 
0925     if (x < 0.0)
0926         {
0927 
0928         if (x < -2147483648.0)
0929             x = -2147483648.0;
0930 
0931         return (int32) (x - 0.5);
0932 
0933         }
0934 
0935     else
0936         {
0937 
0938         if (x > 2147483647.0)
0939             x = 2147483647.0;
0940 
0941         return (int32) (x + 0.5);
0942 
0943         }
0944 
0945     }
0946 
0947 /*****************************************************************************/
0948 
0949 dng_urational dng_stream::TagValue_urational (uint32 tagType)
0950     {
0951 
0952     dng_urational result;
0953 
0954     result.n = 0;
0955     result.d = 1;
0956 
0957     switch (tagType)
0958         {
0959 
0960         case ttRational:
0961             {
0962 
0963             result.n = Get_uint32 ();
0964             result.d = Get_uint32 ();
0965 
0966             break;
0967 
0968             }
0969 
0970         case ttSRational:
0971             {
0972 
0973             int32 n = Get_int32 ();
0974             int32 d = Get_int32 ();
0975 
0976             if ((n < 0) == (d < 0))
0977                 {
0978 
0979                 if (d < 0)
0980                     {
0981                     n = -n;
0982                     d = -d;
0983                     }
0984 
0985                 result.n = (uint32) n;
0986                 result.d = (uint32) d;
0987 
0988                 }
0989 
0990             break;
0991 
0992             }
0993 
0994         case ttByte:
0995         case ttShort:
0996         case ttLong:
0997         case ttIFD:
0998             {
0999 
1000             result.n = TagValue_uint32 (tagType);
1001 
1002             break;
1003 
1004             }
1005 
1006         case ttSByte:
1007         case ttSShort:
1008         case ttSLong:
1009             {
1010 
1011             int32 n = TagValue_int32 (tagType);
1012 
1013             if (n > 0)
1014                 {
1015                 result.n = (uint32) n;
1016                 }
1017 
1018             break;
1019 
1020             }
1021 
1022         default:
1023             {
1024 
1025             real64 x = TagValue_real64 (tagType);
1026 
1027             if (x > 0.0)
1028                 {
1029 
1030                 while (result.d < 10000 && x < 1000000)
1031                     {
1032 
1033                     result.d *= 10;
1034 
1035                     x *= 10.0;
1036 
1037                     }
1038 
1039                 result.n = (uint32) (x + 0.5);
1040 
1041                 }
1042 
1043             }
1044 
1045         }
1046 
1047     return result;
1048 
1049     }
1050 
1051 /*****************************************************************************/
1052 
1053 dng_srational dng_stream::TagValue_srational (uint32 tagType)
1054     {
1055 
1056     dng_srational result;
1057 
1058     result.n = 0;
1059     result.d = 1;
1060 
1061     switch (tagType)
1062         {
1063 
1064         case ttSRational:
1065             {
1066 
1067             result.n = Get_int32 ();
1068             result.d = Get_int32 ();
1069 
1070             break;
1071 
1072             }
1073 
1074         default:
1075             {
1076 
1077             real64 x = TagValue_real64 (tagType);
1078 
1079             if (x > 0.0)
1080                 {
1081 
1082                 while (result.d < 10000 && x < 1000000.0)
1083                     {
1084 
1085                     result.d *= 10;
1086 
1087                     x *= 10.0;
1088 
1089                     }
1090 
1091                 result.n = (int32) (x + 0.5);
1092 
1093                 }
1094 
1095             else
1096                 {
1097 
1098                 while (result.d < 10000 && x > -1000000.0)
1099                     {
1100 
1101                     result.d *= 10;
1102 
1103                     x *= 10.0;
1104 
1105                     }
1106 
1107                 result.n = (int32) (x - 0.5);
1108 
1109                 }
1110 
1111             }
1112 
1113         }
1114 
1115     return result;
1116 
1117     }
1118 
1119 /*****************************************************************************/
1120 
1121 real64 dng_stream::TagValue_real64 (uint32 tagType)
1122     {
1123 
1124     switch (tagType)
1125         {
1126 
1127         case ttByte:
1128         case ttShort:
1129         case ttLong:
1130         case ttIFD:
1131             return (real64) TagValue_uint32 (tagType);
1132 
1133         case ttSByte:
1134         case ttSShort:
1135         case ttSLong:
1136             return (real64) TagValue_int32 (tagType);
1137 
1138         case ttRational:
1139             {
1140 
1141             uint32 n = Get_uint32 ();
1142             uint32 d = Get_uint32 ();
1143 
1144             if (d == 0)
1145                 return 0.0;
1146             else
1147                 return (real64) n / (real64) d;
1148 
1149             }
1150 
1151         case ttSRational:
1152             {
1153 
1154             int32 n = Get_int32 ();
1155             int32 d = Get_int32 ();
1156 
1157             if (d == 0)
1158                 return 0.0;
1159             else
1160                 return (real64) n / (real64) d;
1161 
1162             }
1163 
1164         case ttFloat:
1165             return (real64) Get_real32 ();
1166 
1167         case ttDouble:
1168             return Get_real64 ();
1169 
1170         }
1171 
1172     return 0.0;
1173 
1174     }
1175 
1176 /*****************************************************************************/
1177 
1178 void dng_stream::CopyToStream (dng_stream &dstStream,
1179                                uint64 count)
1180     {
1181 
1182     uint8 smallBuffer [1024];
1183 
1184     if (count <= sizeof (smallBuffer))
1185         {
1186 
1187         Get (smallBuffer, (uint32) count);
1188 
1189         dstStream.Put (smallBuffer, (uint32) count);
1190 
1191         }
1192 
1193     else
1194         {
1195 
1196         const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
1197                                                           count);
1198 
1199         dng_memory_data bigBuffer (bigBufferSize);
1200 
1201         while (count)
1202             {
1203 
1204             uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
1205                                                      count);
1206 
1207             Get (bigBuffer.Buffer (),
1208                  blockCount);
1209 
1210             dstStream.Put (bigBuffer.Buffer (),
1211                            blockCount);
1212 
1213             count -= blockCount;
1214 
1215             }
1216 
1217         }
1218 
1219     }
1220 
1221 /*****************************************************************************/
1222 
1223 void dng_stream::DuplicateStream (dng_stream &dstStream)
1224     {
1225 
1226     // Turn off sniffers for this operation.
1227 
1228     TempStreamSniffer noSniffer1 (*this    , NULL);
1229     TempStreamSniffer noSniffer2 (dstStream, NULL);
1230 
1231     // First grow the destination stream if required, in an attempt to
1232     // reserve any needed space before overwriting the existing data.
1233 
1234     if (dstStream.Length () < Length ())
1235         {
1236         dstStream.SetLength (Length ());
1237         }
1238 
1239     SetReadPosition (0);
1240 
1241     dstStream.SetWritePosition (0);
1242 
1243     CopyToStream (dstStream, Length ());
1244 
1245     dstStream.Flush ();
1246 
1247     dstStream.SetLength (Length ());
1248 
1249     }
1250 
1251 /*****************************************************************************/
1252 
1253 dng_stream_contiguous_read_hint::dng_stream_contiguous_read_hint
1254                                  (dng_stream &stream,
1255                                   dng_memory_allocator &allocator,
1256                                   uint64 offset,
1257                                   uint64 count)
1258 
1259     :   fStream        (stream)
1260     ,   fAllocator     (allocator)
1261     ,   fOldBufferSize (stream.BufferSize ())
1262 
1263     {
1264 
1265     fStream.Flush ();       // Cannot change buffer size with dirty buffer
1266 
1267     // Don't bother changing buffer size if only a small change.
1268 
1269     if (count > fOldBufferSize * 4)
1270         {
1271 
1272         // Round contiguous size up and down to stream blocks.
1273 
1274         uint64 blockRound = gDNGStreamBlockSize - 1;
1275 
1276         uint64 blockMask  = ~((int64) blockRound);
1277 
1278         count = (count + (offset & blockRound) + blockRound) & blockMask;
1279 
1280         // Limit to maximum buffer size.
1281 
1282         uint64 newBufferSize = Min_uint64 (gDNGMaxStreamBufferSize, count);
1283 
1284         // To avoid reading too many bytes with the final read, adjust buffer
1285         // size the to make an exact number of buffers fit.
1286 
1287         uint64 numBuffers = (count + newBufferSize - 1) / newBufferSize;
1288 
1289         newBufferSize = (count + numBuffers - 1) / numBuffers;
1290 
1291         // Finally round up to a block size.
1292 
1293         newBufferSize = (newBufferSize + blockRound) & blockMask;
1294 
1295         // Change the buffer size.
1296 
1297         fStream.SetBufferSize (fAllocator, (uint32) newBufferSize);
1298 
1299         }
1300 
1301     }
1302 
1303 /*****************************************************************************/
1304 
1305 dng_stream_contiguous_read_hint::~dng_stream_contiguous_read_hint ()
1306     {
1307 
1308     fStream.SetBufferSize (fAllocator, fOldBufferSize);
1309 
1310     }
1311 
1312 /*****************************************************************************/
1313 
1314 TempBigEndian::TempBigEndian (dng_stream &stream,
1315                               bool bigEndian)
1316 
1317     :   fStream  (stream)
1318     ,   fOldSwap (stream.SwapBytes ())
1319 
1320     {
1321 
1322     fStream.SetBigEndian (bigEndian);
1323 
1324     }
1325 
1326 /*****************************************************************************/
1327 
1328 TempBigEndian::~TempBigEndian ()
1329     {
1330 
1331     fStream.SetSwapBytes (fOldSwap);
1332 
1333     }
1334 
1335 /*****************************************************************************/
1336 
1337 TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
1338                                       dng_abort_sniffer *sniffer)
1339 
1340     :   fStream     (stream)
1341     ,   fOldSniffer (stream.Sniffer ())
1342 
1343     {
1344 
1345     fStream.SetSniffer (sniffer);
1346 
1347     }
1348 
1349 /*****************************************************************************/
1350 
1351 TempStreamSniffer::~TempStreamSniffer ()
1352     {
1353 
1354     fStream.SetSniffer (fOldSniffer);
1355 
1356     }
1357 
1358 /*****************************************************************************/