| /*****************************************************************************/ |
| // 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 |
| |
| /*****************************************************************************/ |