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