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.
698 lines
19 KiB
698 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.h#2 $ */ |
|
/* $DateTime: 2012/06/01 07:28:57 $ */ |
|
/* $Change: 832715 $ */ |
|
/* $Author: tknoll $ */ |
|
|
|
/** Data stream abstraction for serializing and deserializing sequences of |
|
* basic types and RAW image data. |
|
*/ |
|
|
|
/*****************************************************************************/ |
|
|
|
#ifndef __dng_stream__ |
|
#define __dng_stream__ |
|
|
|
/*****************************************************************************/ |
|
|
|
#include "dng_classes.h" |
|
#include "dng_types.h" |
|
#include "dng_memory.h" |
|
#include "dng_rational.h" |
|
#include "dng_utils.h" |
|
|
|
/*****************************************************************************/ |
|
|
|
// Constants for invalid offset in streams. |
|
|
|
const uint64 kDNGStreamInvalidOffset = (uint64) (int64) -1; |
|
|
|
/*****************************************************************************/ |
|
|
|
/// Base stream abstraction. Has support for going between stream and pointer |
|
/// abstraction. |
|
|
|
class dng_stream |
|
{ |
|
|
|
public: |
|
|
|
enum |
|
{ |
|
|
|
kSmallBufferSize = 4 * 1024, |
|
kBigBufferSize = 64 * 1024, |
|
|
|
kDefaultBufferSize = kSmallBufferSize |
|
|
|
}; |
|
|
|
private: |
|
|
|
bool fSwapBytes; |
|
|
|
bool fHaveLength; |
|
|
|
uint64 fLength; |
|
|
|
const uint64 fOffsetInOriginalFile; |
|
|
|
uint64 fPosition; |
|
|
|
dng_memory_data fMemBlock; |
|
|
|
uint8 *fBuffer; |
|
|
|
uint32 fBufferSize; |
|
|
|
uint64 fBufferStart; |
|
uint64 fBufferEnd; |
|
uint64 fBufferLimit; |
|
|
|
bool fBufferDirty; |
|
|
|
dng_abort_sniffer *fSniffer; |
|
|
|
protected: |
|
|
|
dng_stream (dng_abort_sniffer *sniffer = NULL, |
|
uint32 bufferSize = kDefaultBufferSize, |
|
uint64 offsetInOriginalFile = kDNGStreamInvalidOffset); |
|
|
|
virtual uint64 DoGetLength (); |
|
|
|
virtual void DoRead (void *data, |
|
uint32 count, |
|
uint64 offset); |
|
|
|
virtual void DoSetLength (uint64 length); |
|
|
|
virtual void DoWrite (const void *data, |
|
uint32 count, |
|
uint64 offset); |
|
|
|
public: |
|
|
|
/// Construct a stream with initial data. |
|
/// \param data Pointer to initial contents of stream. |
|
/// \param count Number of bytes data is valid for. |
|
/// \param offsetInOriginalFile If data came from a file originally, |
|
/// offset can be saved here for later use. |
|
|
|
dng_stream (const void *data, |
|
uint32 count, |
|
uint64 offsetInOriginalFile = kDNGStreamInvalidOffset); |
|
|
|
virtual ~dng_stream (); |
|
|
|
/// Getter for whether stream is swapping byte order on input/output. |
|
/// \retval If true, data will be swapped on input/output. |
|
|
|
bool SwapBytes () const |
|
{ |
|
return fSwapBytes; |
|
} |
|
|
|
/// Setter for whether stream is swapping byte order on input/output. |
|
/// \param swapBytes If true, stream will swap byte order on input or |
|
/// output for future reads/writes. |
|
|
|
void SetSwapBytes (bool swapBytes) |
|
{ |
|
fSwapBytes = swapBytes; |
|
} |
|
|
|
/// Getter for whether data in stream is big endian. |
|
/// \retval If true, data in stream is big endian. |
|
|
|
bool BigEndian () const; |
|
|
|
/// Setter for whether data in stream is big endian. |
|
/// \param bigEndian If true, data in stream is big endian. |
|
|
|
void SetBigEndian (bool bigEndian = true); |
|
|
|
/// Getter for whether data in stream is big endian. |
|
/// \retval If true, data in stream is big endian. |
|
|
|
bool LittleEndian () const |
|
{ |
|
return !BigEndian (); |
|
} |
|
|
|
/// Setter for whether data in stream is big endian. |
|
/// \param littleEndian If true, data in stream is big endian. |
|
|
|
void SetLittleEndian (bool littleEndian = true) |
|
{ |
|
SetBigEndian (!littleEndian); |
|
} |
|
|
|
/// Returns the size of the buffer used by the stream. |
|
|
|
uint32 BufferSize () const |
|
{ |
|
return fBufferSize; |
|
} |
|
|
|
/// Getter for length of data in stream. |
|
/// \retval Length of readable data in stream. |
|
|
|
uint64 Length () |
|
{ |
|
|
|
if (!fHaveLength) |
|
{ |
|
|
|
fLength = DoGetLength (); |
|
|
|
fHaveLength = true; |
|
|
|
} |
|
|
|
return fLength; |
|
|
|
} |
|
|
|
/// Getter for current offset in stream. |
|
/// \retval current offset from start of stream. |
|
|
|
uint64 Position () const |
|
{ |
|
return fPosition; |
|
} |
|
|
|
/// Getter for current position in original file, taking into account |
|
/// OffsetInOriginalFile stream data was taken from. |
|
/// \retval kInvalidOffset if no offset in original file is set, sum |
|
/// of offset in original file and current position otherwise. |
|
|
|
uint64 PositionInOriginalFile () const; |
|
|
|
/// Getter for offset in original file. |
|
/// \retval kInvalidOffset if no offset in original file is set, |
|
/// offset in original file otherwise. |
|
|
|
uint64 OffsetInOriginalFile () const; |
|
|
|
/// Return pointer to stream contents if the stream is entirely |
|
/// available as a single memory block, NULL otherwise. |
|
|
|
const void * Data () const; |
|
|
|
/// Return the entire stream as a single memory block. |
|
/// This works for all streams, but requires copying the data to a new buffer. |
|
/// \param allocator Allocator used to allocate memory. |
|
|
|
dng_memory_block * AsMemoryBlock (dng_memory_allocator &allocator); |
|
|
|
/// Seek to a new position in stream for reading. |
|
|
|
void SetReadPosition (uint64 offset); |
|
|
|
/// Skip forward in stream. |
|
/// \param delta Number of bytes to skip forward. |
|
|
|
void Skip (uint64 delta) |
|
{ |
|
SetReadPosition (Position () + delta); |
|
} |
|
|
|
/// Get data from stream. Exception is thrown and no data is read if |
|
/// insufficient data available in stream. |
|
/// \param data Buffer to put data into. Must be valid for count bytes. |
|
/// \param count Bytes of data to read. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
void Get (void *data, uint32 count); |
|
|
|
/// Seek to a new position in stream for writing. |
|
|
|
void SetWritePosition (uint64 offset); |
|
|
|
/// Force any stored data in stream to be written to underlying storage. |
|
|
|
void Flush (); |
|
|
|
/// Set length of available data. |
|
/// \param length Number of bytes of avialble data in stream. |
|
|
|
void SetLength (uint64 length); |
|
|
|
/// Write data to stream. |
|
/// \param data Buffer of data to write to stream. |
|
/// \param count Bytes of in data. |
|
|
|
void Put (const void *data, uint32 count); |
|
|
|
/// Get an unsigned 8-bit integer from stream and advance read position. |
|
/// \retval One unsigned 8-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
uint8 Get_uint8 () |
|
{ |
|
|
|
// Fast check to see if in buffer |
|
|
|
if (fPosition >= fBufferStart && fPosition < fBufferEnd) |
|
{ |
|
|
|
return fBuffer [fPosition++ - fBufferStart]; |
|
|
|
} |
|
|
|
// Not in buffer, let main routine do the work. |
|
|
|
uint8 x; |
|
|
|
Get (&x, 1); |
|
|
|
return x; |
|
|
|
} |
|
|
|
/// Put an unsigned 8-bit integer to stream and advance write position. |
|
/// \param x One unsigned 8-bit integer. |
|
|
|
void Put_uint8 (uint8 x) |
|
{ |
|
|
|
if (fBufferDirty && |
|
fPosition >= fBufferStart && |
|
fPosition <= fBufferEnd && |
|
fPosition < fBufferLimit) |
|
{ |
|
|
|
fBuffer [fPosition - fBufferStart] = x; |
|
|
|
fPosition++; |
|
|
|
if (fBufferEnd < fPosition) |
|
fBufferEnd = fPosition; |
|
|
|
fLength = Max_uint64 (Length (), fPosition); |
|
|
|
} |
|
|
|
else |
|
{ |
|
|
|
Put (&x, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
/// Get an unsigned 16-bit integer from stream and advance read position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \retval One unsigned 16-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
uint16 Get_uint16 (); |
|
|
|
/// Put an unsigned 16-bit integer to stream and advance write position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \param x One unsigned 16-bit integer. |
|
|
|
void Put_uint16 (uint16 x); |
|
|
|
/// Get an unsigned 32-bit integer from stream and advance read position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \retval One unsigned 32-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
uint32 Get_uint32 (); |
|
|
|
/// Put an unsigned 32-bit integer to stream and advance write position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \param x One unsigned 32-bit integer. |
|
|
|
void Put_uint32 (uint32 x); |
|
|
|
/// Get an unsigned 64-bit integer from stream and advance read position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \retval One unsigned 64-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
uint64 Get_uint64 (); |
|
|
|
/// Put an unsigned 64-bit integer to stream and advance write position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \param x One unsigned 64-bit integer. |
|
|
|
void Put_uint64 (uint64 x); |
|
|
|
/// Get one 8-bit integer from stream and advance read position. |
|
/// \retval One 8-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
int8 Get_int8 () |
|
{ |
|
return (int8) Get_uint8 (); |
|
} |
|
|
|
/// Put one 8-bit integer to stream and advance write position. |
|
/// \param x One 8-bit integer. |
|
|
|
void Put_int8 (int8 x) |
|
{ |
|
Put_uint8 ((uint8) x); |
|
} |
|
|
|
/// Get one 16-bit integer from stream and advance read position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \retval One 16-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
int16 Get_int16 () |
|
{ |
|
return (int16) Get_uint16 (); |
|
} |
|
|
|
/// Put one 16-bit integer to stream and advance write position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \param x One 16-bit integer. |
|
|
|
void Put_int16 (int16 x) |
|
{ |
|
Put_uint16 ((uint16) x); |
|
} |
|
|
|
/// Get one 32-bit integer from stream and advance read position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \retval One 32-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
int32 Get_int32 () |
|
{ |
|
return (int32) Get_uint32 (); |
|
} |
|
|
|
/// Put one 32-bit integer to stream and advance write position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \param x One 32-bit integer. |
|
|
|
void Put_int32 (int32 x) |
|
{ |
|
Put_uint32 ((uint32) x); |
|
} |
|
|
|
/// Get one 64-bit integer from stream and advance read position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \retval One 64-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
int64 Get_int64 () |
|
{ |
|
return (int64) Get_uint64 (); |
|
} |
|
|
|
/// Put one 64-bit integer to stream and advance write position. |
|
/// Byte swap if byte swapping is turned on. |
|
/// \param x One 64-bit integer. |
|
|
|
void Put_int64 (int64 x) |
|
{ |
|
Put_uint64 ((uint64) x); |
|
} |
|
|
|
/// Get one 32-bit IEEE floating-point number from stream and advance |
|
/// read position. Byte swap if byte swapping is turned on. |
|
/// \retval One 32-bit IEEE floating-point number. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
real32 Get_real32 (); |
|
|
|
/// Put one 32-bit IEEE floating-point number to stream and advance write |
|
/// position. Byte swap if byte swapping is turned on. |
|
/// \param x One 32-bit IEEE floating-point number. |
|
|
|
void Put_real32 (real32 x); |
|
|
|
/// Get one 64-bit IEEE floating-point number from stream and advance |
|
/// read position. Byte swap if byte swapping is turned on. |
|
/// \retval One 64-bit IEEE floating-point number . |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
real64 Get_real64 (); |
|
|
|
/// Put one 64-bit IEEE floating-point number to stream and advance write |
|
/// position. Byte swap if byte swapping is turned on. |
|
/// \param x One64-bit IEEE floating-point number. |
|
|
|
void Put_real64 (real64 x); |
|
|
|
/// Get an 8-bit character string from stream and advance read position. |
|
/// Routine always reads until a NUL character (8-bits of zero) is read. |
|
/// (That is, only maxLength bytes will be returned in buffer, but the |
|
/// stream is always advanced until a NUL is read or EOF is reached.) |
|
/// \param data Buffer in which string is returned. |
|
/// \param maxLength Maximum number of bytes to place in buffer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if stream runs out before NUL is seen. |
|
|
|
void Get_CString (char *data, |
|
uint32 maxLength); |
|
|
|
/// Get a 16-bit character string from stream and advance read position. |
|
/// 16-bit characters are truncated to 8-bits. |
|
/// Routine always reads until a NUL character (16-bits of zero) is read. |
|
/// (That is, only maxLength bytes will be returned in buffer, but the |
|
/// stream is always advanced until a NUL is read or EOF is reached.) |
|
/// \param data Buffer to place string in. |
|
/// \param maxLength Maximum number of bytes to place in buffer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if stream runs out before NUL is seen. |
|
|
|
void Get_UString (char *data, |
|
uint32 maxLength); |
|
|
|
/// Writes the specified number of zero bytes to stream. |
|
/// \param count Number of zero bytes to write. |
|
|
|
void PutZeros (uint64 count); |
|
|
|
/// Writes zeros to align the stream position to a multiple of 2. |
|
|
|
void PadAlign2 (); |
|
|
|
/// Writes zeros to align the stream position to a multiple of 4. |
|
|
|
void PadAlign4 (); |
|
|
|
/// Get a value of size indicated by tag type from stream and advance |
|
/// read position. Byte swap if byte swapping is turned on and tag type |
|
/// is larger than a byte. Value is returned as an unsigned 32-bit integer. |
|
/// \param tagType Tag type of data stored in stream. |
|
/// \retval One unsigned 32-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
uint32 TagValue_uint32 (uint32 tagType); |
|
|
|
/// Get a value of size indicated by tag type from stream and advance read |
|
/// position. Byte swap if byte swapping is turned on and tag type is larger |
|
/// than a byte. Value is returned as a 32-bit integer. |
|
/// \param tagType Tag type of data stored in stream. |
|
/// \retval One 32-bit integer. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
int32 TagValue_int32 (uint32 tagType); |
|
|
|
/// Get a value of size indicated by tag type from stream and advance read |
|
/// position. Byte swap if byte swapping is turned on and tag type is larger |
|
/// than a byte. Value is returned as a dng_urational. |
|
/// \param tagType Tag type of data stored in stream. |
|
/// \retval One dng_urational. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
dng_urational TagValue_urational (uint32 tagType); |
|
|
|
/// Get a value of size indicated by tag type from stream and advance read |
|
/// position. Byte swap if byte swapping is turned on and tag type is larger |
|
/// than a byte. Value is returned as a dng_srational. |
|
/// \param tagType Tag type of data stored in stream. |
|
/// \retval One dng_srational. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
dng_srational TagValue_srational (uint32 tagType); |
|
|
|
/// Get a value of size indicated by tag type from stream and advance read |
|
/// position. Byte swap if byte swapping is turned on and tag type is larger |
|
/// than a byte. Value is returned as a 64-bit IEEE floating-point number. |
|
/// \param tagType Tag type of data stored in stream. |
|
/// \retval One 64-bit IEEE floating-point number. |
|
/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file |
|
/// if not enough data in stream. |
|
|
|
real64 TagValue_real64 (uint32 tagType); |
|
|
|
/// Getter for sniffer associated with stream. |
|
/// \retval The sniffer for this stream. |
|
|
|
dng_abort_sniffer * Sniffer () const |
|
{ |
|
return fSniffer; |
|
} |
|
|
|
/// Putter for sniffer associated with stream. |
|
/// \param sniffer The new sniffer to use (or NULL for none). |
|
|
|
void SetSniffer (dng_abort_sniffer *sniffer) |
|
{ |
|
fSniffer = sniffer; |
|
} |
|
|
|
/// Copy a specified number of bytes to a target stream. |
|
/// \param dstStream The target stream. |
|
/// \param count The number of bytes to copy. |
|
|
|
virtual void CopyToStream (dng_stream &dstStream, |
|
uint64 count); |
|
|
|
/// Makes the target stream a copy of this stream. |
|
/// \param dstStream The target stream. |
|
|
|
void DuplicateStream (dng_stream &dstStream); |
|
|
|
private: |
|
|
|
// Hidden copy constructor and assignment operator. |
|
|
|
dng_stream (const dng_stream &stream); |
|
|
|
dng_stream & operator= (const dng_stream &stream); |
|
|
|
}; |
|
|
|
/*****************************************************************************/ |
|
|
|
class TempBigEndian |
|
{ |
|
|
|
private: |
|
|
|
dng_stream & fStream; |
|
|
|
bool fOldSwap; |
|
|
|
public: |
|
|
|
TempBigEndian (dng_stream &stream, |
|
bool bigEndian = true); |
|
|
|
virtual ~TempBigEndian (); |
|
|
|
}; |
|
|
|
/*****************************************************************************/ |
|
|
|
class TempLittleEndian: public TempBigEndian |
|
{ |
|
|
|
public: |
|
|
|
TempLittleEndian (dng_stream &stream, |
|
bool littleEndian = true) |
|
|
|
: TempBigEndian (stream, !littleEndian) |
|
|
|
{ |
|
} |
|
|
|
virtual ~TempLittleEndian () |
|
{ |
|
} |
|
|
|
}; |
|
|
|
/*****************************************************************************/ |
|
|
|
class TempStreamSniffer |
|
{ |
|
|
|
private: |
|
|
|
dng_stream & fStream; |
|
|
|
dng_abort_sniffer *fOldSniffer; |
|
|
|
public: |
|
|
|
TempStreamSniffer (dng_stream &stream, |
|
dng_abort_sniffer *sniffer); |
|
|
|
virtual ~TempStreamSniffer (); |
|
|
|
private: |
|
|
|
// Hidden copy constructor and assignment operator. |
|
|
|
TempStreamSniffer (const TempStreamSniffer &temp); |
|
|
|
TempStreamSniffer & operator= (const TempStreamSniffer &temp); |
|
|
|
}; |
|
|
|
/*****************************************************************************/ |
|
|
|
class PreserveStreamReadPosition |
|
{ |
|
|
|
private: |
|
|
|
dng_stream & fStream; |
|
|
|
uint64 fPosition; |
|
|
|
public: |
|
|
|
PreserveStreamReadPosition (dng_stream &stream) |
|
|
|
: fStream (stream) |
|
, fPosition (stream.Position ()) |
|
|
|
{ |
|
} |
|
|
|
~PreserveStreamReadPosition () |
|
{ |
|
fStream.SetReadPosition (fPosition); |
|
} |
|
|
|
private: |
|
|
|
// Hidden copy constructor and assignment operator. |
|
|
|
PreserveStreamReadPosition (const PreserveStreamReadPosition &rhs); |
|
|
|
PreserveStreamReadPosition & operator= (const PreserveStreamReadPosition &rhs); |
|
|
|
}; |
|
|
|
/*****************************************************************************/ |
|
|
|
#endif |
|
|
|
/*****************************************************************************/
|
|
|