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.
699 lines
19 KiB
699 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
|
|
|
|
/*****************************************************************************/
|