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