You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1221 lines
19 KiB
1221 lines
19 KiB
/*****************************************************************************/ |
|
// 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 ConvertDoubleToUint32(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 ConvertDoubleToInt32(x - 0.5); |
|
|
|
} |
|
|
|
else |
|
{ |
|
|
|
if (x > 2147483647.0) |
|
x = 2147483647.0; |
|
|
|
return ConvertDoubleToInt32(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 = ConvertDoubleToUint32(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 = ConvertDoubleToInt32(x + 0.5); |
|
|
|
} |
|
|
|
else |
|
{ |
|
|
|
while (result.d < 10000 && x > -1000000.0) |
|
{ |
|
|
|
result.d *= 10; |
|
|
|
x *= 10.0; |
|
|
|
} |
|
|
|
result.n = ConvertDoubleToInt32(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); |
|
|
|
} |
|
|
|
/*****************************************************************************/
|
|
|