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