1/*****************************************************************************/
2// Copyright 2006-2007 Adobe Systems Incorporated
3// All Rights Reserved.
4//
5// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6// accordance with the terms of the Adobe license agreement accompanying it.
7/*****************************************************************************/
8
9/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_stream.h#2 $ */
10/* $DateTime: 2012/06/01 07:28:57 $ */
11/* $Change: 832715 $ */
12/* $Author: tknoll $ */
13
14/** Data stream abstraction for serializing and deserializing sequences of
15 *  basic types and RAW image data.
16 */
17
18/*****************************************************************************/
19
20#ifndef __dng_stream__
21#define __dng_stream__
22
23/*****************************************************************************/
24
25#include "dng_classes.h"
26#include "dng_types.h"
27#include "dng_memory.h"
28#include "dng_rational.h"
29#include "dng_utils.h"
30
31/*****************************************************************************/
32
33// Constants for invalid offset in streams.
34
35const uint64 kDNGStreamInvalidOffset = (uint64) (int64) -1;
36
37/*****************************************************************************/
38
39/// Base stream abstraction. Has support for going between stream and pointer
40/// abstraction.
41
42class dng_stream
43	{
44
45	public:
46
47		enum
48			{
49
50			kSmallBufferSize =  4 * 1024,
51			kBigBufferSize   = 64 * 1024,
52
53			kDefaultBufferSize = kSmallBufferSize
54
55			};
56
57	private:
58
59		bool fSwapBytes;
60
61		bool fHaveLength;
62
63		uint64 fLength;
64
65		const uint64 fOffsetInOriginalFile;
66
67		uint64 fPosition;
68
69		dng_memory_data fMemBlock;
70
71		uint8 *fBuffer;
72
73		uint32 fBufferSize;
74
75		uint64 fBufferStart;
76		uint64 fBufferEnd;
77		uint64 fBufferLimit;
78
79		bool fBufferDirty;
80
81		dng_abort_sniffer *fSniffer;
82
83	protected:
84
85		dng_stream (dng_abort_sniffer *sniffer = NULL,
86					uint32 bufferSize = kDefaultBufferSize,
87					uint64 offsetInOriginalFile = kDNGStreamInvalidOffset);
88
89		virtual uint64 DoGetLength ();
90
91		virtual void DoRead (void *data,
92							 uint32 count,
93							 uint64 offset);
94
95		virtual void DoSetLength (uint64 length);
96
97		virtual void DoWrite (const void *data,
98							  uint32 count,
99							  uint64 offset);
100
101	public:
102
103		/// Construct a stream with initial data.
104		/// \param data Pointer to initial contents of stream.
105		/// \param count Number of bytes data is valid for.
106		/// \param offsetInOriginalFile If data came from a file originally,
107		/// offset can be saved here for later use.
108
109		dng_stream (const void *data,
110					uint32 count,
111					uint64 offsetInOriginalFile = kDNGStreamInvalidOffset);
112
113		virtual ~dng_stream ();
114
115		/// Getter for whether stream is swapping byte order on input/output.
116		/// \retval If true, data will be swapped on input/output.
117
118		bool SwapBytes () const
119			{
120			return fSwapBytes;
121			}
122
123		/// Setter for whether stream is swapping byte order on input/output.
124		/// \param swapBytes If true, stream will swap byte order on input or
125		/// output for future reads/writes.
126
127		void SetSwapBytes (bool swapBytes)
128			{
129			fSwapBytes = swapBytes;
130			}
131
132		/// Getter for whether data in stream is big endian.
133		/// \retval If true, data in stream is big endian.
134
135		bool BigEndian () const;
136
137		/// Setter for whether data in stream is big endian.
138		/// \param bigEndian If true, data in stream is big endian.
139
140		void SetBigEndian (bool bigEndian = true);
141
142		/// Getter for whether data in stream is big endian.
143		/// \retval If true, data in stream is big endian.
144
145		bool LittleEndian () const
146			{
147			return !BigEndian ();
148			}
149
150		/// Setter for whether data in stream is big endian.
151		/// \param littleEndian If true, data in stream is big endian.
152
153		void SetLittleEndian (bool littleEndian = true)
154			{
155			SetBigEndian (!littleEndian);
156			}
157
158		/// Returns the size of the buffer used by the stream.
159
160		uint32 BufferSize () const
161			{
162			return fBufferSize;
163			}
164
165		/// Getter for length of data in stream.
166		/// \retval Length of readable data in stream.
167
168		uint64 Length ()
169			{
170
171			if (!fHaveLength)
172				{
173
174				fLength = DoGetLength ();
175
176				fHaveLength = true;
177
178				}
179
180			return fLength;
181
182			}
183
184		/// Getter for current offset in stream.
185		/// \retval current offset from start of stream.
186
187		uint64 Position () const
188			{
189			return fPosition;
190			}
191
192		/// Getter for current position in original file, taking into account
193		/// OffsetInOriginalFile stream data was taken from.
194		/// \retval kInvalidOffset if no offset in original file is set, sum
195		/// of offset in original file and current position otherwise.
196
197		uint64 PositionInOriginalFile () const;
198
199		/// Getter for offset in original file.
200		/// \retval kInvalidOffset if no offset in original file is set,
201		/// offset in original file otherwise.
202
203		uint64 OffsetInOriginalFile () const;
204
205		/// Return pointer to stream contents if the stream is entirely
206		/// available as a single memory block, NULL otherwise.
207
208		const void * Data () const;
209
210		/// Return the entire stream as a single memory block.
211		/// This works for all streams, but requires copying the data to a new buffer.
212		/// \param allocator Allocator used to allocate memory.
213
214		dng_memory_block * AsMemoryBlock (dng_memory_allocator &allocator);
215
216		/// Seek to a new position in stream for reading.
217
218		void SetReadPosition (uint64 offset);
219
220		/// Skip forward in stream.
221		/// \param delta Number of bytes to skip forward.
222
223		void Skip (uint64 delta)
224			{
225			SetReadPosition (Position () + delta);
226			}
227
228		/// Get data from stream. Exception is thrown and no data is read if
229		/// insufficient data available in stream.
230		/// \param data Buffer to put data into. Must be valid for count bytes.
231		/// \param count Bytes of data to read.
232		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
233		/// if not enough data in stream.
234
235		void Get (void *data, uint32 count);
236
237		/// Seek to a new position in stream for writing.
238
239		void SetWritePosition (uint64 offset);
240
241		/// Force any stored data in stream to be written to underlying storage.
242
243		void Flush ();
244
245		/// Set length of available data.
246		/// \param length Number of bytes of avialble data in stream.
247
248		void SetLength (uint64 length);
249
250		/// Write data to stream.
251		/// \param data Buffer of data to write to stream.
252		/// \param count Bytes of in data.
253
254		void Put (const void *data, uint32 count);
255
256		/// Get an unsigned 8-bit integer from stream and advance read position.
257		/// \retval One unsigned 8-bit integer.
258		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
259		/// if not enough data in stream.
260
261		uint8 Get_uint8 ()
262			{
263
264			// Fast check to see if in buffer
265
266			if (fPosition >= fBufferStart && fPosition < fBufferEnd)
267				{
268
269				return fBuffer [fPosition++ - fBufferStart];
270
271				}
272
273			// Not in buffer, let main routine do the work.
274
275			uint8 x;
276
277			Get (&x, 1);
278
279			return x;
280
281			}
282
283		/// Put an unsigned 8-bit integer to stream and advance write position.
284		/// \param x One unsigned 8-bit integer.
285
286		void Put_uint8 (uint8 x)
287			{
288
289			if (fBufferDirty               &&
290			    fPosition  >= fBufferStart &&
291				fPosition  <= fBufferEnd   &&
292				fPosition  <  fBufferLimit)
293				{
294
295				fBuffer [fPosition - fBufferStart] = x;
296
297				fPosition++;
298
299				if (fBufferEnd < fPosition)
300					fBufferEnd = fPosition;
301
302				fLength = Max_uint64 (Length (), fPosition);
303
304				}
305
306			else
307				{
308
309				Put (&x, 1);
310
311				}
312
313			}
314
315		/// Get an unsigned 16-bit integer from stream and advance read position.
316		/// Byte swap if byte swapping is turned on.
317		/// \retval One unsigned 16-bit integer.
318		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
319		/// if not enough data in stream.
320
321		uint16 Get_uint16 ();
322
323		/// Put an unsigned 16-bit integer to stream and advance write position.
324		/// Byte swap if byte swapping is turned on.
325		/// \param x One unsigned 16-bit integer.
326
327		void Put_uint16 (uint16 x);
328
329		/// Get an unsigned 32-bit integer from stream and advance read position.
330		/// Byte swap if byte swapping is turned on.
331		/// \retval One unsigned 32-bit integer.
332		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
333		/// if not enough data in stream.
334
335		uint32 Get_uint32 ();
336
337		/// Put an unsigned 32-bit integer to stream and advance write position.
338		/// Byte swap if byte swapping is turned on.
339		/// \param x One unsigned 32-bit integer.
340
341		void Put_uint32 (uint32 x);
342
343		/// Get an unsigned 64-bit integer from stream and advance read position.
344		/// Byte swap if byte swapping is turned on.
345		/// \retval One unsigned 64-bit integer.
346		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
347		/// if not enough data in stream.
348
349		uint64 Get_uint64 ();
350
351		/// Put an unsigned 64-bit integer to stream and advance write position.
352		/// Byte swap if byte swapping is turned on.
353		/// \param x One unsigned 64-bit integer.
354
355		void Put_uint64 (uint64 x);
356
357		/// Get one 8-bit integer from stream and advance read position.
358		/// \retval One 8-bit integer.
359		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
360		/// if not enough data in stream.
361
362		int8 Get_int8 ()
363			{
364			return (int8) Get_uint8 ();
365			}
366
367		/// Put one 8-bit integer to stream and advance write position.
368		/// \param x One  8-bit integer.
369
370		void Put_int8 (int8 x)
371			{
372			Put_uint8 ((uint8) x);
373			}
374
375		/// Get one 16-bit integer from stream and advance read position.
376		/// Byte swap if byte swapping is turned on.
377		/// \retval One 16-bit integer.
378		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
379		/// if not enough data in stream.
380
381		int16 Get_int16 ()
382			{
383			return (int16) Get_uint16 ();
384			}
385
386		/// Put one 16-bit integer to stream and advance write position.
387		/// Byte swap if byte swapping is turned on.
388		/// \param x One 16-bit integer.
389
390		void Put_int16 (int16 x)
391			{
392			Put_uint16 ((uint16) x);
393			}
394
395		/// Get one 32-bit integer from stream and advance read position.
396		/// Byte swap if byte swapping is turned on.
397		/// \retval One 32-bit integer.
398		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
399		/// if not enough data in stream.
400
401		int32 Get_int32 ()
402			{
403			return (int32) Get_uint32 ();
404			}
405
406		/// Put one 32-bit integer to stream and advance write position.
407		/// Byte swap if byte swapping is turned on.
408		/// \param x One 32-bit integer.
409
410		void Put_int32 (int32 x)
411			{
412			Put_uint32 ((uint32) x);
413			}
414
415		/// Get one 64-bit integer from stream and advance read position.
416		/// Byte swap if byte swapping is turned on.
417		/// \retval One 64-bit integer.
418		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
419		/// if not enough data in stream.
420
421		int64 Get_int64 ()
422			{
423			return (int64) Get_uint64 ();
424			}
425
426		/// Put one 64-bit integer to stream and advance write position.
427		/// Byte swap if byte swapping is turned on.
428		/// \param x One 64-bit integer.
429
430		void Put_int64 (int64 x)
431			{
432			Put_uint64 ((uint64) x);
433			}
434
435		/// Get one 32-bit IEEE floating-point number from stream and advance
436		/// read position. Byte swap if byte swapping is turned on.
437		/// \retval One 32-bit IEEE floating-point number.
438		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
439		/// if not enough data in stream.
440
441		real32 Get_real32 ();
442
443		/// Put one 32-bit IEEE floating-point number to stream and advance write
444		/// position. Byte swap if byte swapping is turned on.
445		/// \param x One 32-bit IEEE floating-point number.
446
447		void Put_real32 (real32 x);
448
449		/// Get one 64-bit IEEE floating-point number from stream and advance
450		/// read position. Byte swap if byte swapping is turned on.
451		/// \retval One 64-bit IEEE floating-point number .
452		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
453		/// if not enough data in stream.
454
455		real64 Get_real64 ();
456
457		/// Put one 64-bit IEEE floating-point number to stream and advance write
458		/// position. Byte swap if byte swapping is turned on.
459		/// \param x One64-bit IEEE floating-point number.
460
461		void Put_real64 (real64 x);
462
463		/// Get an 8-bit character string from stream and advance read position.
464		/// Routine always reads until a NUL character (8-bits of zero) is read.
465		/// (That is, only maxLength bytes will be returned in buffer, but the
466		/// stream is always advanced until a NUL is read or EOF is reached.)
467		/// \param data Buffer in which string is returned.
468		/// \param maxLength Maximum number of bytes to place in buffer.
469		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
470		/// if stream runs out before NUL is seen.
471
472		void Get_CString (char *data,
473						  uint32 maxLength);
474
475		/// Get a 16-bit character string from stream and advance read position.
476		/// 16-bit characters are truncated to 8-bits.
477		/// Routine always reads until a NUL character (16-bits of zero) is read.
478		/// (That is, only maxLength bytes will be returned in buffer, but the
479		/// stream is always advanced until a NUL is read or EOF is reached.)
480		/// \param data Buffer to place string in.
481		/// \param maxLength Maximum number of bytes to place in buffer.
482		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
483		/// if stream runs out before NUL is seen.
484
485		void Get_UString (char *data,
486						  uint32 maxLength);
487
488		/// Writes the specified number of zero bytes to stream.
489		/// \param count Number of zero bytes to write.
490
491		void PutZeros (uint64 count);
492
493		/// Writes zeros to align the stream position to a multiple of 2.
494
495		void PadAlign2 ();
496
497		/// Writes zeros to align the stream position to a multiple of 4.
498
499		void PadAlign4 ();
500
501		/// Get a value of size indicated by tag type from stream and advance
502		/// read position. Byte swap if byte swapping is turned on and tag type
503		/// is larger than a byte. Value is returned as an unsigned 32-bit integer.
504		/// \param tagType Tag type of data stored in stream.
505		/// \retval One unsigned 32-bit integer.
506		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
507		/// if not enough data in stream.
508
509		uint32 TagValue_uint32 (uint32 tagType);
510
511		/// Get a value of size indicated by tag type from stream and advance read
512		/// position. Byte swap if byte swapping is turned on and tag type is larger
513		/// than a byte. Value is returned as a 32-bit integer.
514		/// \param tagType Tag type of data stored in stream.
515		/// \retval One 32-bit integer.
516		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
517		/// if not enough data in stream.
518
519		int32 TagValue_int32 (uint32 tagType);
520
521		/// Get a value of size indicated by tag type from stream and advance read
522		/// position. Byte swap if byte swapping is turned on and tag type is larger
523		/// than a byte. Value is returned as a dng_urational.
524		/// \param tagType Tag type of data stored in stream.
525		/// \retval One dng_urational.
526		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
527		/// if not enough data in stream.
528
529		dng_urational TagValue_urational (uint32 tagType);
530
531		/// Get a value of size indicated by tag type from stream and advance read
532		/// position. Byte swap if byte swapping is turned on and tag type is larger
533		/// than a byte. Value is returned as a dng_srational.
534		/// \param tagType Tag type of data stored in stream.
535		/// \retval One dng_srational.
536		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
537		/// if not enough data in stream.
538
539		dng_srational TagValue_srational (uint32 tagType);
540
541		/// Get a value of size indicated by tag type from stream and advance read
542		/// position. Byte swap if byte swapping is turned on and tag type is larger
543		/// than a byte. Value is returned as a 64-bit IEEE floating-point number.
544		/// \param tagType Tag type of data stored in stream.
545		/// \retval One 64-bit IEEE floating-point number.
546		/// \exception dng_exception with fErrorCode equal to dng_error_end_of_file
547		/// if not enough data in stream.
548
549		real64 TagValue_real64 (uint32 tagType);
550
551		/// Getter for sniffer associated with stream.
552		/// \retval The sniffer for this stream.
553
554		dng_abort_sniffer * Sniffer () const
555			{
556			return fSniffer;
557			}
558
559		/// Putter for sniffer associated with stream.
560		/// \param sniffer The new sniffer to use (or NULL for none).
561
562		void SetSniffer (dng_abort_sniffer *sniffer)
563			{
564			fSniffer = sniffer;
565			}
566
567		/// Copy a specified number of bytes to a target stream.
568		/// \param dstStream The target stream.
569		/// \param count The number of bytes to copy.
570
571		virtual void CopyToStream (dng_stream &dstStream,
572								   uint64 count);
573
574		/// Makes the target stream a copy of this stream.
575		/// \param dstStream The target stream.
576
577		void DuplicateStream (dng_stream &dstStream);
578
579	private:
580
581		// Hidden copy constructor and assignment operator.
582
583		dng_stream (const dng_stream &stream);
584
585		dng_stream & operator= (const dng_stream &stream);
586
587	};
588
589/*****************************************************************************/
590
591class TempBigEndian
592	{
593
594	private:
595
596		dng_stream & fStream;
597
598		bool fOldSwap;
599
600	public:
601
602		TempBigEndian (dng_stream &stream,
603					   bool bigEndian = true);
604
605		virtual ~TempBigEndian ();
606
607	};
608
609/*****************************************************************************/
610
611class TempLittleEndian: public TempBigEndian
612	{
613
614	public:
615
616		TempLittleEndian (dng_stream &stream,
617						  bool littleEndian = true)
618
619			:	TempBigEndian (stream, !littleEndian)
620
621			{
622			}
623
624		virtual ~TempLittleEndian ()
625			{
626			}
627
628	};
629
630/*****************************************************************************/
631
632class TempStreamSniffer
633	{
634
635	private:
636
637		dng_stream & fStream;
638
639		dng_abort_sniffer *fOldSniffer;
640
641	public:
642
643		TempStreamSniffer (dng_stream &stream,
644					       dng_abort_sniffer *sniffer);
645
646		virtual ~TempStreamSniffer ();
647
648	private:
649
650		// Hidden copy constructor and assignment operator.
651
652		TempStreamSniffer (const TempStreamSniffer &temp);
653
654		TempStreamSniffer & operator= (const TempStreamSniffer &temp);
655
656	};
657
658/*****************************************************************************/
659
660class PreserveStreamReadPosition
661	{
662
663	private:
664
665		dng_stream & fStream;
666
667		uint64 fPosition;
668
669	public:
670
671		PreserveStreamReadPosition (dng_stream &stream)
672
673			:	fStream	  (stream)
674			,	fPosition (stream.Position ())
675
676			{
677			}
678
679		~PreserveStreamReadPosition ()
680			{
681			fStream.SetReadPosition (fPosition);
682			}
683
684	private:
685
686		// Hidden copy constructor and assignment operator.
687
688		PreserveStreamReadPosition (const PreserveStreamReadPosition &rhs);
689
690		PreserveStreamReadPosition & operator= (const PreserveStreamReadPosition &rhs);
691
692	};
693
694/*****************************************************************************/
695
696#endif
697
698/*****************************************************************************/
699