diff options
Diffstat (limited to 'source/dng_stream.cpp')
-rw-r--r-- | source/dng_stream.cpp | 2442 |
1 files changed, 1221 insertions, 1221 deletions
diff --git a/source/dng_stream.cpp b/source/dng_stream.cpp index f8548db..c1db250 100644 --- a/source/dng_stream.cpp +++ b/source/dng_stream.cpp @@ -1,1221 +1,1221 @@ -/*****************************************************************************/
-// Copyright 2006-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE: Adobe permits you to use, modify, and distribute this file in
-// accordance with the terms of the Adobe license agreement accompanying it.
-/*****************************************************************************/
-
-/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_stream.cpp#2 $ */
-/* $DateTime: 2012/06/01 07:28:57 $ */
-/* $Change: 832715 $ */
-/* $Author: tknoll $ */
-
-/*****************************************************************************/
-
-#include "dng_stream.h"
-
-#include "dng_abort_sniffer.h"
-#include "dng_auto_ptr.h"
-#include "dng_bottlenecks.h"
-#include "dng_exceptions.h"
-#include "dng_flags.h"
-#include "dng_memory.h"
-#include "dng_tag_types.h"
-
-/*****************************************************************************/
-
-dng_stream::dng_stream (dng_abort_sniffer *sniffer,
- uint32 bufferSize,
- uint64 offsetInOriginalFile)
-
- : fSwapBytes (false)
- , fHaveLength (false)
- , fLength (0)
- , fOffsetInOriginalFile (offsetInOriginalFile)
- , fPosition (0)
- , fMemBlock (bufferSize)
- , fBuffer (fMemBlock.Buffer_uint8 ())
- , fBufferSize (bufferSize)
- , fBufferStart (0)
- , fBufferEnd (0)
- , fBufferLimit (bufferSize)
- , fBufferDirty (false)
- , fSniffer (sniffer)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_stream::dng_stream (const void *data,
- uint32 count,
- uint64 offsetInOriginalFile)
-
- : fSwapBytes (false)
- , fHaveLength (true)
- , fLength (count)
- , fOffsetInOriginalFile (offsetInOriginalFile)
- , fPosition (0)
- , fMemBlock ()
- , fBuffer ((uint8 *) data)
- , fBufferSize (count)
- , fBufferStart (0)
- , fBufferEnd (count)
- , fBufferLimit (count)
- , fBufferDirty (false)
- , fSniffer (NULL)
-
- {
-
- }
-
-/*****************************************************************************/
-
-dng_stream::~dng_stream ()
- {
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::DoGetLength ()
- {
-
- ThrowProgramError ();
-
- return 0;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DoRead (void * /* data */,
- uint32 /* count */,
- uint64 /* offset */)
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DoSetLength (uint64 /* length */)
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DoWrite (const void * /* data */,
- uint32 /* count */,
- uint64 /* offset */)
- {
-
- ThrowProgramError ();
-
- }
-
-/*****************************************************************************/
-
-bool dng_stream::BigEndian () const
- {
-
- return fSwapBytes != (!!qDNGBigEndian);
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetBigEndian (bool bigEndian)
- {
-
- fSwapBytes = (bigEndian != (!!qDNGBigEndian));
-
- }
-
-/*****************************************************************************/
-
-const void * dng_stream::Data () const
- {
-
- if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
- {
-
- return fBuffer;
-
- }
-
- return NULL;
-
- }
-
-/*****************************************************************************/
-
-dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
- {
-
- Flush ();
-
- uint64 len64 = Length ();
-
- if (len64 > 0xFFFFFFFF)
- {
- ThrowProgramError ();
- }
-
- uint32 len = (uint32) len64;
-
- AutoPtr<dng_memory_block> block (allocator.Allocate (len));
-
- if (len)
- {
-
- SetReadPosition (0);
-
- Get (block->Buffer (), len);
-
- }
-
- return block.Release ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetReadPosition (uint64 offset)
- {
-
- fPosition = offset;
-
- if (fPosition > Length ())
- {
-
- ThrowEndOfFile ();
-
- }
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::OffsetInOriginalFile () const
- {
-
- return fOffsetInOriginalFile;
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::PositionInOriginalFile () const
- {
-
- if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
- return kDNGStreamInvalidOffset;
-
- return fOffsetInOriginalFile + Position ();
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Get (void *data, uint32 count)
- {
-
- while (count)
- {
-
- // See if the request is totally inside buffer.
-
- if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
- {
-
- DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart),
- data,
- count);
-
- fPosition += count;
-
- return;
-
- }
-
- // See if first part of request is inside buffer.
-
- if (fPosition >= fBufferStart && fPosition < fBufferEnd)
- {
-
- uint32 block = (uint32) (fBufferEnd - fPosition);
-
- DoCopyBytes (fBuffer + (fPosition - fBufferStart),
- data,
- block);
-
- count -= block;
-
- data = (void *) (((char *) data) + block);
-
- fPosition += block;
-
- }
-
- // Flush buffer if dirty.
-
- Flush ();
-
- // Do large reads unbuffered.
-
- if (count > fBufferSize)
- {
-
- if (fPosition + count > Length ())
- {
-
- ThrowEndOfFile ();
-
- }
-
- DoRead (data,
- count,
- fPosition);
-
- fPosition += count;
-
- return;
-
- }
-
- // Figure out new buffer range.
-
- fBufferStart = fPosition;
-
- if (fBufferSize >= 4096)
- {
-
- // Align to a 4K file block.
-
- fBufferStart &= (uint64) ~((int64) 4095);
-
- }
-
- fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
-
- if (fBufferEnd <= fPosition)
- {
-
- ThrowEndOfFile ();
-
- }
-
- // Read data into buffer.
-
- dng_abort_sniffer::SniffForAbort (fSniffer);
-
- DoRead (fBuffer,
- (uint32) (fBufferEnd - fBufferStart),
- fBufferStart);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetWritePosition (uint64 offset)
- {
-
- fPosition = offset;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Flush ()
- {
-
- if (fBufferDirty)
- {
-
- dng_abort_sniffer::SniffForAbort (fSniffer);
-
- DoWrite (fBuffer,
- (uint32) (fBufferEnd - fBufferStart),
- fBufferStart);
-
- fBufferStart = 0;
- fBufferEnd = 0;
- fBufferLimit = fBufferSize;
-
- fBufferDirty = false;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::SetLength (uint64 length)
- {
-
- Flush ();
-
- if (Length () != length)
- {
-
- DoSetLength (length);
-
- fLength = length;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put (const void *data,
- uint32 count)
- {
-
- // See if we can replace or append to the existing buffer.
-
- uint64 endPosition = fPosition + count;
-
- if (fBufferDirty &&
- fPosition >= fBufferStart &&
- fPosition <= fBufferEnd &&
- endPosition <= fBufferLimit)
- {
-
- DoCopyBytes (data,
- fBuffer + (uint32) (fPosition - fBufferStart),
- count);
-
- if (fBufferEnd < endPosition)
- fBufferEnd = endPosition;
-
- }
-
- // Else we need to write to the file.
-
- else
- {
-
- // Write existing buffer.
-
- Flush ();
-
- // Write large blocks unbuffered.
-
- if (count >= fBufferSize)
- {
-
- dng_abort_sniffer::SniffForAbort (fSniffer);
-
- DoWrite (data, count, fPosition);
-
- }
-
- // Start a new buffer with small blocks.
-
- else
- {
-
- fBufferDirty = true;
-
- fBufferStart = fPosition;
- fBufferEnd = endPosition;
- fBufferLimit = fBufferStart + fBufferSize;
-
- DoCopyBytes (data,
- fBuffer,
- count);
-
- }
-
- }
-
- fPosition = endPosition;
-
- fLength = Max_uint64 (Length (), fPosition);
-
- }
-
-/*****************************************************************************/
-
-uint16 dng_stream::Get_uint16 ()
- {
-
- uint16 x;
-
- Get (&x, 2);
-
- if (fSwapBytes)
- {
-
- x = SwapBytes16 (x);
-
- }
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_uint16 (uint16 x)
- {
-
- if (fSwapBytes)
- {
-
- x = SwapBytes16 (x);
-
- }
-
- Put (&x, 2);
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_stream::Get_uint32 ()
- {
-
- uint32 x;
-
- Get (&x, 4);
-
- if (fSwapBytes)
- {
-
- x = SwapBytes32 (x);
-
- }
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_uint32 (uint32 x)
- {
-
- if (fSwapBytes)
- {
-
- x = SwapBytes32 (x);
-
- }
-
- Put (&x, 4);
-
- }
-
-/*****************************************************************************/
-
-uint64 dng_stream::Get_uint64 ()
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 u32 [2];
- uint64 u64;
- } u;
-
- u.u32 [1] = Get_uint32 ();
- u.u32 [0] = Get_uint32 ();
-
- return u.u64;
-
- }
-
- uint64 x;
-
- Get (&x, 8);
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_uint64 (uint64 x)
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 u32 [2];
- uint64 u64;
- } u;
-
- u.u64 = x;
-
- Put_uint32 (u.u32 [1]);
- Put_uint32 (u.u32 [0]);
-
- }
-
- else
- {
-
- Put (&x, 8);
-
- }
-
- }
-
-/*****************************************************************************/
-
-real32 dng_stream::Get_real32 ()
- {
-
- union
- {
- uint32 i;
- real32 r;
- } u;
-
- u.i = Get_uint32 ();
-
- return u.r;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_real32 (real32 x)
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 i;
- real32 r;
- } u;
-
- u.r = x;
-
- Put_uint32 (u.i);
-
- }
-
- else
- {
-
- Put (&x, 4);
-
- }
-
- }
-
-/*****************************************************************************/
-
-real64 dng_stream::Get_real64 ()
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 i [2];
- real64 r;
- } u;
-
- u.i [1] = Get_uint32 ();
- u.i [0] = Get_uint32 ();
-
- return u.r;
-
- }
-
- real64 x;
-
- Get (&x, 8);
-
- return x;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Put_real64 (real64 x)
- {
-
- if (fSwapBytes)
- {
-
- union
- {
- uint32 i [2];
- real64 r;
- } u;
-
- u.r = x;
-
- Put_uint32 (u.i [1]);
- Put_uint32 (u.i [0]);
-
- }
-
- else
- {
-
- Put (&x, 8);
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Get_CString (char *data, uint32 maxLength)
- {
-
- memset (data, 0, maxLength);
-
- uint32 index = 0;
-
- while (true)
- {
-
- char c = (char) Get_uint8 ();
-
- if (index + 1 < maxLength)
- data [index++] = c;
-
- if (c == 0)
- break;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::Get_UString (char *data, uint32 maxLength)
- {
-
- memset (data, 0, maxLength);
-
- uint32 index = 0;
-
- while (true)
- {
-
- char c = (char) Get_uint16 ();
-
- if (index + 1 < maxLength)
- data [index++] = (char) c;
-
- if (c == 0)
- break;
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::PutZeros (uint64 count)
- {
-
- const uint32 kZeroBufferSize = 4096;
-
- if (count >= kZeroBufferSize)
- {
-
- dng_memory_data zeroBuffer (kZeroBufferSize);
-
- DoZeroBytes (zeroBuffer.Buffer (),
- kZeroBufferSize);
-
- while (count)
- {
-
- uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
-
- Put (zeroBuffer.Buffer (), (uint32) blockSize);
-
- count -= blockSize;
-
- }
-
- }
-
- else
- {
-
- uint32 count32 = (uint32) count;
-
- for (uint32 j = 0; j < count32; j++)
- {
-
- Put_uint8 (0);
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::PadAlign2 ()
- {
-
- PutZeros (Position () & 1);
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::PadAlign4 ()
- {
-
- PutZeros ((4 - (Position () & 3)) & 3);
-
- }
-
-/*****************************************************************************/
-
-uint32 dng_stream::TagValue_uint32 (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttByte:
- return (uint32) Get_uint8 ();
-
- case ttShort:
- return (uint32) Get_uint16 ();
-
- case ttLong:
- case ttIFD:
- return Get_uint32 ();
-
- }
-
- real64 x = TagValue_real64 (tagType);
-
- if (x < 0.0)
- x = 0.0;
-
- if (x > (real64) 0xFFFFFFFF)
- x = (real64) 0xFFFFFFFF;
-
- return (uint32) (x + 0.5);
-
- }
-
-/*****************************************************************************/
-
-int32 dng_stream::TagValue_int32 (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttSByte:
- return (int32) Get_int8 ();
-
- case ttSShort:
- return (int32) Get_int16 ();
-
- case ttSLong:
- return Get_int32 ();
-
- }
-
- real64 x = TagValue_real64 (tagType);
-
- if (x < 0.0)
- {
-
- if (x < -2147483648.0)
- x = -2147483648.0;
-
- return (int32) (x - 0.5);
-
- }
-
- else
- {
-
- if (x > 2147483647.0)
- x = 2147483647.0;
-
- return (int32) (x + 0.5);
-
- }
-
- }
-
-/*****************************************************************************/
-
-dng_urational dng_stream::TagValue_urational (uint32 tagType)
- {
-
- dng_urational result;
-
- result.n = 0;
- result.d = 1;
-
- switch (tagType)
- {
-
- case ttRational:
- {
-
- result.n = Get_uint32 ();
- result.d = Get_uint32 ();
-
- break;
-
- }
-
- case ttSRational:
- {
-
- int32 n = Get_int32 ();
- int32 d = Get_int32 ();
-
- if ((n < 0) == (d < 0))
- {
-
- if (d < 0)
- {
- result.n = (uint32) ((int64) n * -1);
- result.d = (uint32) ((int64) d * -1);
- }
- else
- {
- result.n = (uint32) n;
- result.d = (uint32) d;
- }
-
- }
-
- break;
-
- }
-
- case ttByte:
- case ttShort:
- case ttLong:
- case ttIFD:
- {
-
- result.n = TagValue_uint32 (tagType);
-
- break;
-
- }
-
- case ttSByte:
- case ttSShort:
- case ttSLong:
- {
-
- int32 n = TagValue_int32 (tagType);
-
- if (n > 0)
- {
- result.n = (uint32) n;
- }
-
- break;
-
- }
-
- default:
- {
-
- real64 x = TagValue_real64 (tagType);
-
- if (x > 0.0)
- {
-
- while (result.d < 10000 && x < 1000000)
- {
-
- result.d *= 10;
-
- x *= 10.0;
-
- }
-
- result.n = (uint32) (x + 0.5);
-
- }
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-dng_srational dng_stream::TagValue_srational (uint32 tagType)
- {
-
- dng_srational result;
-
- result.n = 0;
- result.d = 1;
-
- switch (tagType)
- {
-
- case ttSRational:
- {
-
- result.n = Get_int32 ();
- result.d = Get_int32 ();
-
- break;
-
- }
-
- default:
- {
-
- real64 x = TagValue_real64 (tagType);
-
- if (x > 0.0)
- {
-
- while (result.d < 10000 && x < 1000000.0)
- {
-
- result.d *= 10;
-
- x *= 10.0;
-
- }
-
- result.n = (int32) (x + 0.5);
-
- }
-
- else
- {
-
- while (result.d < 10000 && x > -1000000.0)
- {
-
- result.d *= 10;
-
- x *= 10.0;
-
- }
-
- result.n = (int32) (x - 0.5);
-
- }
-
- }
-
- }
-
- return result;
-
- }
-
-/*****************************************************************************/
-
-real64 dng_stream::TagValue_real64 (uint32 tagType)
- {
-
- switch (tagType)
- {
-
- case ttByte:
- case ttShort:
- case ttLong:
- case ttIFD:
- return (real64) TagValue_uint32 (tagType);
-
- case ttSByte:
- case ttSShort:
- case ttSLong:
- return (real64) TagValue_int32 (tagType);
-
- case ttRational:
- {
-
- uint32 n = Get_uint32 ();
- uint32 d = Get_uint32 ();
-
- if (d == 0)
- return 0.0;
- else
- return (real64) n / (real64) d;
-
- }
-
- case ttSRational:
- {
-
- int32 n = Get_int32 ();
- int32 d = Get_int32 ();
-
- if (d == 0)
- return 0.0;
- else
- return (real64) n / (real64) d;
-
- }
-
- case ttFloat:
- return (real64) Get_real32 ();
-
- case ttDouble:
- return Get_real64 ();
-
- }
-
- return 0.0;
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::CopyToStream (dng_stream &dstStream,
- uint64 count)
- {
-
- uint8 smallBuffer [1024];
-
- if (count <= sizeof (smallBuffer))
- {
-
- Get (smallBuffer, (uint32) count);
-
- dstStream.Put (smallBuffer, (uint32) count);
-
- }
-
- else
- {
-
- const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
- count);
-
- dng_memory_data bigBuffer (bigBufferSize);
-
- while (count)
- {
-
- uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
- count);
-
- Get (bigBuffer.Buffer (),
- blockCount);
-
- dstStream.Put (bigBuffer.Buffer (),
- blockCount);
-
- count -= blockCount;
-
- }
-
- }
-
- }
-
-/*****************************************************************************/
-
-void dng_stream::DuplicateStream (dng_stream &dstStream)
- {
-
- // Turn off sniffers for this operation.
-
- TempStreamSniffer noSniffer1 (*this , NULL);
- TempStreamSniffer noSniffer2 (dstStream, NULL);
-
- // First grow the destination stream if required, in an attempt to
- // reserve any needed space before overwriting the existing data.
-
- if (dstStream.Length () < Length ())
- {
- dstStream.SetLength (Length ());
- }
-
- SetReadPosition (0);
-
- dstStream.SetWritePosition (0);
-
- CopyToStream (dstStream, Length ());
-
- dstStream.Flush ();
-
- dstStream.SetLength (Length ());
-
- }
-
-/*****************************************************************************/
-
-TempBigEndian::TempBigEndian (dng_stream &stream,
- bool bigEndian)
-
- : fStream (stream)
- , fOldSwap (stream.SwapBytes ())
-
- {
-
- fStream.SetBigEndian (bigEndian);
-
- }
-
-/*****************************************************************************/
-
-TempBigEndian::~TempBigEndian ()
- {
-
- fStream.SetSwapBytes (fOldSwap);
-
- }
-
-/*****************************************************************************/
-
-TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
- dng_abort_sniffer *sniffer)
-
- : fStream (stream)
- , fOldSniffer (stream.Sniffer ())
-
- {
-
- fStream.SetSniffer (sniffer);
-
- }
-
-/*****************************************************************************/
-
-TempStreamSniffer::~TempStreamSniffer ()
- {
-
- fStream.SetSniffer (fOldSniffer);
-
- }
-
-/*****************************************************************************/
+/*****************************************************************************/ +// Copyright 2006-2007 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in +// accordance with the terms of the Adobe license agreement accompanying it. +/*****************************************************************************/ + +/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_stream.cpp#2 $ */ +/* $DateTime: 2012/06/01 07:28:57 $ */ +/* $Change: 832715 $ */ +/* $Author: tknoll $ */ + +/*****************************************************************************/ + +#include "dng_stream.h" + +#include "dng_abort_sniffer.h" +#include "dng_auto_ptr.h" +#include "dng_bottlenecks.h" +#include "dng_exceptions.h" +#include "dng_flags.h" +#include "dng_memory.h" +#include "dng_tag_types.h" + +/*****************************************************************************/ + +dng_stream::dng_stream (dng_abort_sniffer *sniffer, + uint32 bufferSize, + uint64 offsetInOriginalFile) + + : fSwapBytes (false) + , fHaveLength (false) + , fLength (0) + , fOffsetInOriginalFile (offsetInOriginalFile) + , fPosition (0) + , fMemBlock (bufferSize) + , fBuffer (fMemBlock.Buffer_uint8 ()) + , fBufferSize (bufferSize) + , fBufferStart (0) + , fBufferEnd (0) + , fBufferLimit (bufferSize) + , fBufferDirty (false) + , fSniffer (sniffer) + + { + + } + +/*****************************************************************************/ + +dng_stream::dng_stream (const void *data, + uint32 count, + uint64 offsetInOriginalFile) + + : fSwapBytes (false) + , fHaveLength (true) + , fLength (count) + , fOffsetInOriginalFile (offsetInOriginalFile) + , fPosition (0) + , fMemBlock () + , fBuffer ((uint8 *) data) + , fBufferSize (count) + , fBufferStart (0) + , fBufferEnd (count) + , fBufferLimit (count) + , fBufferDirty (false) + , fSniffer (NULL) + + { + + } + +/*****************************************************************************/ + +dng_stream::~dng_stream () + { + + } + +/*****************************************************************************/ + +uint64 dng_stream::DoGetLength () + { + + ThrowProgramError (); + + return 0; + + } + +/*****************************************************************************/ + +void dng_stream::DoRead (void * /* data */, + uint32 /* count */, + uint64 /* offset */) + { + + ThrowProgramError (); + + } + +/*****************************************************************************/ + +void dng_stream::DoSetLength (uint64 /* length */) + { + + ThrowProgramError (); + + } + +/*****************************************************************************/ + +void dng_stream::DoWrite (const void * /* data */, + uint32 /* count */, + uint64 /* offset */) + { + + ThrowProgramError (); + + } + +/*****************************************************************************/ + +bool dng_stream::BigEndian () const + { + + return fSwapBytes != (!!qDNGBigEndian); + + } + +/*****************************************************************************/ + +void dng_stream::SetBigEndian (bool bigEndian) + { + + fSwapBytes = (bigEndian != (!!qDNGBigEndian)); + + } + +/*****************************************************************************/ + +const void * dng_stream::Data () const + { + + if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength) + { + + return fBuffer; + + } + + return NULL; + + } + +/*****************************************************************************/ + +dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator) + { + + Flush (); + + uint64 len64 = Length (); + + if (len64 > 0xFFFFFFFF) + { + ThrowProgramError (); + } + + uint32 len = (uint32) len64; + + AutoPtr<dng_memory_block> block (allocator.Allocate (len)); + + if (len) + { + + SetReadPosition (0); + + Get (block->Buffer (), len); + + } + + return block.Release (); + + } + +/*****************************************************************************/ + +void dng_stream::SetReadPosition (uint64 offset) + { + + fPosition = offset; + + if (fPosition > Length ()) + { + + ThrowEndOfFile (); + + } + + } + +/*****************************************************************************/ + +uint64 dng_stream::OffsetInOriginalFile () const + { + + return fOffsetInOriginalFile; + + } + +/*****************************************************************************/ + +uint64 dng_stream::PositionInOriginalFile () const + { + + if (fOffsetInOriginalFile == kDNGStreamInvalidOffset) + return kDNGStreamInvalidOffset; + + return fOffsetInOriginalFile + Position (); + + } + +/*****************************************************************************/ + +void dng_stream::Get (void *data, uint32 count) + { + + while (count) + { + + // See if the request is totally inside buffer. + + if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd) + { + + DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart), + data, + count); + + fPosition += count; + + return; + + } + + // See if first part of request is inside buffer. + + if (fPosition >= fBufferStart && fPosition < fBufferEnd) + { + + uint32 block = (uint32) (fBufferEnd - fPosition); + + DoCopyBytes (fBuffer + (fPosition - fBufferStart), + data, + block); + + count -= block; + + data = (void *) (((char *) data) + block); + + fPosition += block; + + } + + // Flush buffer if dirty. + + Flush (); + + // Do large reads unbuffered. + + if (count > fBufferSize) + { + + if (fPosition + count > Length ()) + { + + ThrowEndOfFile (); + + } + + DoRead (data, + count, + fPosition); + + fPosition += count; + + return; + + } + + // Figure out new buffer range. + + fBufferStart = fPosition; + + if (fBufferSize >= 4096) + { + + // Align to a 4K file block. + + fBufferStart &= (uint64) ~((int64) 4095); + + } + + fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ()); + + if (fBufferEnd <= fPosition) + { + + ThrowEndOfFile (); + + } + + // Read data into buffer. + + dng_abort_sniffer::SniffForAbort (fSniffer); + + DoRead (fBuffer, + (uint32) (fBufferEnd - fBufferStart), + fBufferStart); + + } + + } + +/*****************************************************************************/ + +void dng_stream::SetWritePosition (uint64 offset) + { + + fPosition = offset; + + } + +/*****************************************************************************/ + +void dng_stream::Flush () + { + + if (fBufferDirty) + { + + dng_abort_sniffer::SniffForAbort (fSniffer); + + DoWrite (fBuffer, + (uint32) (fBufferEnd - fBufferStart), + fBufferStart); + + fBufferStart = 0; + fBufferEnd = 0; + fBufferLimit = fBufferSize; + + fBufferDirty = false; + + } + + } + +/*****************************************************************************/ + +void dng_stream::SetLength (uint64 length) + { + + Flush (); + + if (Length () != length) + { + + DoSetLength (length); + + fLength = length; + + } + + } + +/*****************************************************************************/ + +void dng_stream::Put (const void *data, + uint32 count) + { + + // See if we can replace or append to the existing buffer. + + uint64 endPosition = fPosition + count; + + if (fBufferDirty && + fPosition >= fBufferStart && + fPosition <= fBufferEnd && + endPosition <= fBufferLimit) + { + + DoCopyBytes (data, + fBuffer + (uint32) (fPosition - fBufferStart), + count); + + if (fBufferEnd < endPosition) + fBufferEnd = endPosition; + + } + + // Else we need to write to the file. + + else + { + + // Write existing buffer. + + Flush (); + + // Write large blocks unbuffered. + + if (count >= fBufferSize) + { + + dng_abort_sniffer::SniffForAbort (fSniffer); + + DoWrite (data, count, fPosition); + + } + + // Start a new buffer with small blocks. + + else + { + + fBufferDirty = true; + + fBufferStart = fPosition; + fBufferEnd = endPosition; + fBufferLimit = fBufferStart + fBufferSize; + + DoCopyBytes (data, + fBuffer, + count); + + } + + } + + fPosition = endPosition; + + fLength = Max_uint64 (Length (), fPosition); + + } + +/*****************************************************************************/ + +uint16 dng_stream::Get_uint16 () + { + + uint16 x; + + Get (&x, 2); + + if (fSwapBytes) + { + + x = SwapBytes16 (x); + + } + + return x; + + } + +/*****************************************************************************/ + +void dng_stream::Put_uint16 (uint16 x) + { + + if (fSwapBytes) + { + + x = SwapBytes16 (x); + + } + + Put (&x, 2); + + } + +/*****************************************************************************/ + +uint32 dng_stream::Get_uint32 () + { + + uint32 x; + + Get (&x, 4); + + if (fSwapBytes) + { + + x = SwapBytes32 (x); + + } + + return x; + + } + +/*****************************************************************************/ + +void dng_stream::Put_uint32 (uint32 x) + { + + if (fSwapBytes) + { + + x = SwapBytes32 (x); + + } + + Put (&x, 4); + + } + +/*****************************************************************************/ + +uint64 dng_stream::Get_uint64 () + { + + if (fSwapBytes) + { + + union + { + uint32 u32 [2]; + uint64 u64; + } u; + + u.u32 [1] = Get_uint32 (); + u.u32 [0] = Get_uint32 (); + + return u.u64; + + } + + uint64 x; + + Get (&x, 8); + + return x; + + } + +/*****************************************************************************/ + +void dng_stream::Put_uint64 (uint64 x) + { + + if (fSwapBytes) + { + + union + { + uint32 u32 [2]; + uint64 u64; + } u; + + u.u64 = x; + + Put_uint32 (u.u32 [1]); + Put_uint32 (u.u32 [0]); + + } + + else + { + + Put (&x, 8); + + } + + } + +/*****************************************************************************/ + +real32 dng_stream::Get_real32 () + { + + union + { + uint32 i; + real32 r; + } u; + + u.i = Get_uint32 (); + + return u.r; + + } + +/*****************************************************************************/ + +void dng_stream::Put_real32 (real32 x) + { + + if (fSwapBytes) + { + + union + { + uint32 i; + real32 r; + } u; + + u.r = x; + + Put_uint32 (u.i); + + } + + else + { + + Put (&x, 4); + + } + + } + +/*****************************************************************************/ + +real64 dng_stream::Get_real64 () + { + + if (fSwapBytes) + { + + union + { + uint32 i [2]; + real64 r; + } u; + + u.i [1] = Get_uint32 (); + u.i [0] = Get_uint32 (); + + return u.r; + + } + + real64 x; + + Get (&x, 8); + + return x; + + } + +/*****************************************************************************/ + +void dng_stream::Put_real64 (real64 x) + { + + if (fSwapBytes) + { + + union + { + uint32 i [2]; + real64 r; + } u; + + u.r = x; + + Put_uint32 (u.i [1]); + Put_uint32 (u.i [0]); + + } + + else + { + + Put (&x, 8); + + } + + } + +/*****************************************************************************/ + +void dng_stream::Get_CString (char *data, uint32 maxLength) + { + + memset (data, 0, maxLength); + + uint32 index = 0; + + while (true) + { + + char c = (char) Get_uint8 (); + + if (index + 1 < maxLength) + data [index++] = c; + + if (c == 0) + break; + + } + + } + +/*****************************************************************************/ + +void dng_stream::Get_UString (char *data, uint32 maxLength) + { + + memset (data, 0, maxLength); + + uint32 index = 0; + + while (true) + { + + char c = (char) Get_uint16 (); + + if (index + 1 < maxLength) + data [index++] = (char) c; + + if (c == 0) + break; + + } + + } + +/*****************************************************************************/ + +void dng_stream::PutZeros (uint64 count) + { + + const uint32 kZeroBufferSize = 4096; + + if (count >= kZeroBufferSize) + { + + dng_memory_data zeroBuffer (kZeroBufferSize); + + DoZeroBytes (zeroBuffer.Buffer (), + kZeroBufferSize); + + while (count) + { + + uint64 blockSize = Min_uint64 (count, kZeroBufferSize); + + Put (zeroBuffer.Buffer (), (uint32) blockSize); + + count -= blockSize; + + } + + } + + else + { + + uint32 count32 = (uint32) count; + + for (uint32 j = 0; j < count32; j++) + { + + Put_uint8 (0); + + } + + } + + } + +/*****************************************************************************/ + +void dng_stream::PadAlign2 () + { + + PutZeros (Position () & 1); + + } + +/*****************************************************************************/ + +void dng_stream::PadAlign4 () + { + + PutZeros ((4 - (Position () & 3)) & 3); + + } + +/*****************************************************************************/ + +uint32 dng_stream::TagValue_uint32 (uint32 tagType) + { + + switch (tagType) + { + + case ttByte: + return (uint32) Get_uint8 (); + + case ttShort: + return (uint32) Get_uint16 (); + + case ttLong: + case ttIFD: + return Get_uint32 (); + + } + + real64 x = TagValue_real64 (tagType); + + if (x < 0.0) + x = 0.0; + + if (x > (real64) 0xFFFFFFFF) + x = (real64) 0xFFFFFFFF; + + return (uint32) (x + 0.5); + + } + +/*****************************************************************************/ + +int32 dng_stream::TagValue_int32 (uint32 tagType) + { + + switch (tagType) + { + + case ttSByte: + return (int32) Get_int8 (); + + case ttSShort: + return (int32) Get_int16 (); + + case ttSLong: + return Get_int32 (); + + } + + real64 x = TagValue_real64 (tagType); + + if (x < 0.0) + { + + if (x < -2147483648.0) + x = -2147483648.0; + + return (int32) (x - 0.5); + + } + + else + { + + if (x > 2147483647.0) + x = 2147483647.0; + + return (int32) (x + 0.5); + + } + + } + +/*****************************************************************************/ + +dng_urational dng_stream::TagValue_urational (uint32 tagType) + { + + dng_urational result; + + result.n = 0; + result.d = 1; + + switch (tagType) + { + + case ttRational: + { + + result.n = Get_uint32 (); + result.d = Get_uint32 (); + + break; + + } + + case ttSRational: + { + + int32 n = Get_int32 (); + int32 d = Get_int32 (); + + if ((n < 0) == (d < 0)) + { + + if (d < 0) + { + result.n = (uint32) ((int64) n * -1); + result.d = (uint32) ((int64) d * -1); + } + else + { + result.n = (uint32) n; + result.d = (uint32) d; + } + + } + + break; + + } + + case ttByte: + case ttShort: + case ttLong: + case ttIFD: + { + + result.n = TagValue_uint32 (tagType); + + break; + + } + + case ttSByte: + case ttSShort: + case ttSLong: + { + + int32 n = TagValue_int32 (tagType); + + if (n > 0) + { + result.n = (uint32) n; + } + + break; + + } + + default: + { + + real64 x = TagValue_real64 (tagType); + + if (x > 0.0) + { + + while (result.d < 10000 && x < 1000000) + { + + result.d *= 10; + + x *= 10.0; + + } + + result.n = (uint32) (x + 0.5); + + } + + } + + } + + return result; + + } + +/*****************************************************************************/ + +dng_srational dng_stream::TagValue_srational (uint32 tagType) + { + + dng_srational result; + + result.n = 0; + result.d = 1; + + switch (tagType) + { + + case ttSRational: + { + + result.n = Get_int32 (); + result.d = Get_int32 (); + + break; + + } + + default: + { + + real64 x = TagValue_real64 (tagType); + + if (x > 0.0) + { + + while (result.d < 10000 && x < 1000000.0) + { + + result.d *= 10; + + x *= 10.0; + + } + + result.n = (int32) (x + 0.5); + + } + + else + { + + while (result.d < 10000 && x > -1000000.0) + { + + result.d *= 10; + + x *= 10.0; + + } + + result.n = (int32) (x - 0.5); + + } + + } + + } + + return result; + + } + +/*****************************************************************************/ + +real64 dng_stream::TagValue_real64 (uint32 tagType) + { + + switch (tagType) + { + + case ttByte: + case ttShort: + case ttLong: + case ttIFD: + return (real64) TagValue_uint32 (tagType); + + case ttSByte: + case ttSShort: + case ttSLong: + return (real64) TagValue_int32 (tagType); + + case ttRational: + { + + uint32 n = Get_uint32 (); + uint32 d = Get_uint32 (); + + if (d == 0) + return 0.0; + else + return (real64) n / (real64) d; + + } + + case ttSRational: + { + + int32 n = Get_int32 (); + int32 d = Get_int32 (); + + if (d == 0) + return 0.0; + else + return (real64) n / (real64) d; + + } + + case ttFloat: + return (real64) Get_real32 (); + + case ttDouble: + return Get_real64 (); + + } + + return 0.0; + + } + +/*****************************************************************************/ + +void dng_stream::CopyToStream (dng_stream &dstStream, + uint64 count) + { + + uint8 smallBuffer [1024]; + + if (count <= sizeof (smallBuffer)) + { + + Get (smallBuffer, (uint32) count); + + dstStream.Put (smallBuffer, (uint32) count); + + } + + else + { + + const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize, + count); + + dng_memory_data bigBuffer (bigBufferSize); + + while (count) + { + + uint32 blockCount = (uint32) Min_uint64 (bigBufferSize, + count); + + Get (bigBuffer.Buffer (), + blockCount); + + dstStream.Put (bigBuffer.Buffer (), + blockCount); + + count -= blockCount; + + } + + } + + } + +/*****************************************************************************/ + +void dng_stream::DuplicateStream (dng_stream &dstStream) + { + + // Turn off sniffers for this operation. + + TempStreamSniffer noSniffer1 (*this , NULL); + TempStreamSniffer noSniffer2 (dstStream, NULL); + + // First grow the destination stream if required, in an attempt to + // reserve any needed space before overwriting the existing data. + + if (dstStream.Length () < Length ()) + { + dstStream.SetLength (Length ()); + } + + SetReadPosition (0); + + dstStream.SetWritePosition (0); + + CopyToStream (dstStream, Length ()); + + dstStream.Flush (); + + dstStream.SetLength (Length ()); + + } + +/*****************************************************************************/ + +TempBigEndian::TempBigEndian (dng_stream &stream, + bool bigEndian) + + : fStream (stream) + , fOldSwap (stream.SwapBytes ()) + + { + + fStream.SetBigEndian (bigEndian); + + } + +/*****************************************************************************/ + +TempBigEndian::~TempBigEndian () + { + + fStream.SetSwapBytes (fOldSwap); + + } + +/*****************************************************************************/ + +TempStreamSniffer::TempStreamSniffer (dng_stream &stream, + dng_abort_sniffer *sniffer) + + : fStream (stream) + , fOldSniffer (stream.Sniffer ()) + + { + + fStream.SetSniffer (sniffer); + + } + +/*****************************************************************************/ + +TempStreamSniffer::~TempStreamSniffer () + { + + fStream.SetSniffer (fOldSniffer); + + } + +/*****************************************************************************/ |