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 
35 const uint64 kDNGStreamInvalidOffset = (uint64) (int64) -1;
36 
37 /*****************************************************************************/
38 
39 /// Base stream abstraction. Has support for going between stream and pointer
40 /// abstraction.
41 
42 class 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 
SwapBytes()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 
SetSwapBytes(bool swapBytes)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 
LittleEndian()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 
BufferSize()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 
Length()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 
Position()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 
Skip(uint64 delta)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 
Get_uint8()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 
Put_uint8(uint8 x)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 
Get_int8()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 
Put_int8(int8 x)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 
Get_int16()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 
Put_int16(int16 x)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 
Get_int32()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 
Put_int32(int32 x)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 
Get_int64()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 
Put_int64(int64 x)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 
Sniffer()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 
SetSniffer(dng_abort_sniffer * sniffer)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 
591 class 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 
611 class 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 
~TempLittleEndian()624 		virtual ~TempLittleEndian ()
625 			{
626 			}
627 
628 	};
629 
630 /*****************************************************************************/
631 
632 class 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 
660 class PreserveStreamReadPosition
661 	{
662 
663 	private:
664 
665 		dng_stream & fStream;
666 
667 		uint64 fPosition;
668 
669 	public:
670 
PreserveStreamReadPosition(dng_stream & stream)671 		PreserveStreamReadPosition (dng_stream &stream)
672 
673 			:	fStream	  (stream)
674 			,	fPosition (stream.Position ())
675 
676 			{
677 			}
678 
~PreserveStreamReadPosition()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