Home | History | Annotate | Download | only in source
      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.cpp#2 $ */
     10 /* $DateTime: 2012/06/01 07:28:57 $ */
     11 /* $Change: 832715 $ */
     12 /* $Author: tknoll $ */
     13 
     14 /*****************************************************************************/
     15 
     16 #include "dng_stream.h"
     17 
     18 #include "dng_abort_sniffer.h"
     19 #include "dng_auto_ptr.h"
     20 #include "dng_bottlenecks.h"
     21 #include "dng_exceptions.h"
     22 #include "dng_flags.h"
     23 #include "dng_memory.h"
     24 #include "dng_tag_types.h"
     25 
     26 /*****************************************************************************/
     27 
     28 dng_stream::dng_stream (dng_abort_sniffer *sniffer,
     29 						uint32 bufferSize,
     30 						uint64 offsetInOriginalFile)
     31 
     32 	:	fSwapBytes			  (false)
     33 	,	fHaveLength			  (false)
     34 	,	fLength				  (0)
     35 	,	fOffsetInOriginalFile (offsetInOriginalFile)
     36 	,	fPosition			  (0)
     37 	,	fMemBlock			  (bufferSize)
     38 	,	fBuffer				  (fMemBlock.Buffer_uint8 ())
     39 	,	fBufferSize			  (bufferSize)
     40 	,	fBufferStart		  (0)
     41 	,	fBufferEnd			  (0)
     42 	,	fBufferLimit		  (bufferSize)
     43 	,	fBufferDirty		  (false)
     44 	,	fSniffer			  (sniffer)
     45 
     46 	{
     47 
     48 	}
     49 
     50 /*****************************************************************************/
     51 
     52 dng_stream::dng_stream (const void *data,
     53 						uint32 count,
     54 						uint64 offsetInOriginalFile)
     55 
     56 	:	fSwapBytes			  (false)
     57 	,	fHaveLength			  (true)
     58 	,	fLength				  (count)
     59 	,	fOffsetInOriginalFile (offsetInOriginalFile)
     60 	,	fPosition			  (0)
     61 	,	fMemBlock			  ()
     62 	,	fBuffer				  ((uint8 *) data)
     63 	,	fBufferSize			  (count)
     64 	,	fBufferStart		  (0)
     65 	,	fBufferEnd			  (count)
     66 	,	fBufferLimit		  (count)
     67 	,	fBufferDirty		  (false)
     68 	,	fSniffer			  (NULL)
     69 
     70 	{
     71 
     72 	}
     73 
     74 /*****************************************************************************/
     75 
     76 dng_stream::~dng_stream ()
     77 	{
     78 
     79 	}
     80 
     81 /*****************************************************************************/
     82 
     83 uint64 dng_stream::DoGetLength ()
     84 	{
     85 
     86 	ThrowProgramError ();
     87 
     88 	return 0;
     89 
     90 	}
     91 
     92 /*****************************************************************************/
     93 
     94 void dng_stream::DoRead (void * /* data */,
     95 						 uint32 /* count */,
     96 						 uint64 /* offset */)
     97 	{
     98 
     99 	ThrowProgramError ();
    100 
    101 	}
    102 
    103 /*****************************************************************************/
    104 
    105 void dng_stream::DoSetLength (uint64 /* length */)
    106 	{
    107 
    108 	ThrowProgramError ();
    109 
    110 	}
    111 
    112 /*****************************************************************************/
    113 
    114 void dng_stream::DoWrite (const void * /* data */,
    115 						  uint32 /* count */,
    116 						  uint64 /* offset */)
    117 	{
    118 
    119 	ThrowProgramError ();
    120 
    121 	}
    122 
    123 /*****************************************************************************/
    124 
    125 bool dng_stream::BigEndian () const
    126 	{
    127 
    128 	return fSwapBytes != (!!qDNGBigEndian);
    129 
    130 	}
    131 
    132 /*****************************************************************************/
    133 
    134 void dng_stream::SetBigEndian (bool bigEndian)
    135 	{
    136 
    137 	fSwapBytes = (bigEndian != (!!qDNGBigEndian));
    138 
    139 	}
    140 
    141 /*****************************************************************************/
    142 
    143 const void * dng_stream::Data () const
    144 	{
    145 
    146 	if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
    147 		{
    148 
    149 		return fBuffer;
    150 
    151 		}
    152 
    153 	return NULL;
    154 
    155 	}
    156 
    157 /*****************************************************************************/
    158 
    159 dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
    160 	{
    161 
    162 	Flush ();
    163 
    164 	uint64 len64 = Length ();
    165 
    166 	if (len64 > 0xFFFFFFFF)
    167 		{
    168 		ThrowProgramError ();
    169 		}
    170 
    171 	uint32 len = (uint32) len64;
    172 
    173 	AutoPtr<dng_memory_block> block (allocator.Allocate (len));
    174 
    175 	if (len)
    176 		{
    177 
    178 		SetReadPosition (0);
    179 
    180 		Get (block->Buffer (), len);
    181 
    182 		}
    183 
    184 	return block.Release ();
    185 
    186 	}
    187 
    188 /*****************************************************************************/
    189 
    190 void dng_stream::SetReadPosition (uint64 offset)
    191 	{
    192 
    193 	fPosition = offset;
    194 
    195 	if (fPosition > Length ())
    196 		{
    197 
    198 		ThrowEndOfFile ();
    199 
    200 		}
    201 
    202 	}
    203 
    204 /*****************************************************************************/
    205 
    206 uint64 dng_stream::OffsetInOriginalFile () const
    207 	{
    208 
    209 	return fOffsetInOriginalFile;
    210 
    211 	}
    212 
    213 /*****************************************************************************/
    214 
    215 uint64 dng_stream::PositionInOriginalFile () const
    216 	{
    217 
    218 	if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
    219 		return kDNGStreamInvalidOffset;
    220 
    221 	return fOffsetInOriginalFile + Position ();
    222 
    223 	}
    224 
    225 /*****************************************************************************/
    226 
    227 void dng_stream::Get (void *data, uint32 count)
    228 	{
    229 
    230 	while (count)
    231 		{
    232 
    233 		// See if the request is totally inside buffer.
    234 
    235 		if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
    236 			{
    237 
    238 			DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart),
    239 						 data,
    240 						 count);
    241 
    242 			fPosition += count;
    243 
    244 			return;
    245 
    246 			}
    247 
    248 		// See if first part of request is inside buffer.
    249 
    250 		if (fPosition >= fBufferStart && fPosition < fBufferEnd)
    251 			{
    252 
    253 			uint32 block = (uint32) (fBufferEnd - fPosition);
    254 
    255 			DoCopyBytes (fBuffer + (fPosition - fBufferStart),
    256 						 data,
    257 						 block);
    258 
    259 			count -= block;
    260 
    261 			data = (void *) (((char *) data) + block);
    262 
    263 			fPosition += block;
    264 
    265 			}
    266 
    267 		// Flush buffer if dirty.
    268 
    269 		Flush ();
    270 
    271 		// Do large reads unbuffered.
    272 
    273 		if (count > fBufferSize)
    274 			{
    275 
    276 			if (fPosition + count > Length ())
    277 				{
    278 
    279 				ThrowEndOfFile ();
    280 
    281 				}
    282 
    283 			DoRead (data,
    284 					count,
    285 					fPosition);
    286 
    287 			fPosition += count;
    288 
    289 			return;
    290 
    291 			}
    292 
    293 		// Figure out new buffer range.
    294 
    295 		fBufferStart = fPosition;
    296 
    297 		if (fBufferSize >= 4096)
    298 			{
    299 
    300 			// Align to a 4K file block.
    301 
    302 			fBufferStart &= (uint64) ~((int64) 4095);
    303 
    304 			}
    305 
    306 		fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
    307 
    308 		if (fBufferEnd <= fPosition)
    309 			{
    310 
    311 			ThrowEndOfFile ();
    312 
    313 			}
    314 
    315 		// Read data into buffer.
    316 
    317 		dng_abort_sniffer::SniffForAbort (fSniffer);
    318 
    319 		DoRead (fBuffer,
    320 				(uint32) (fBufferEnd - fBufferStart),
    321 				fBufferStart);
    322 
    323 		}
    324 
    325 	}
    326 
    327 /*****************************************************************************/
    328 
    329 void dng_stream::SetWritePosition (uint64 offset)
    330 	{
    331 
    332 	fPosition = offset;
    333 
    334 	}
    335 
    336 /*****************************************************************************/
    337 
    338 void dng_stream::Flush ()
    339 	{
    340 
    341 	if (fBufferDirty)
    342 		{
    343 
    344 		dng_abort_sniffer::SniffForAbort (fSniffer);
    345 
    346 		DoWrite (fBuffer,
    347 				 (uint32) (fBufferEnd - fBufferStart),
    348 				 fBufferStart);
    349 
    350 		fBufferStart = 0;
    351 		fBufferEnd   = 0;
    352 		fBufferLimit = fBufferSize;
    353 
    354 		fBufferDirty = false;
    355 
    356 		}
    357 
    358 	}
    359 
    360 /*****************************************************************************/
    361 
    362 void dng_stream::SetLength (uint64 length)
    363 	{
    364 
    365 	Flush ();
    366 
    367 	if (Length () != length)
    368 		{
    369 
    370 		DoSetLength (length);
    371 
    372 		fLength = length;
    373 
    374 		}
    375 
    376 	}
    377 
    378 /*****************************************************************************/
    379 
    380 void dng_stream::Put (const void *data,
    381 					  uint32 count)
    382 	{
    383 
    384 	// See if we can replace or append to the existing buffer.
    385 
    386 	uint64 endPosition = fPosition + count;
    387 
    388 	if (fBufferDirty                &&
    389 		fPosition   >= fBufferStart &&
    390 		fPosition   <= fBufferEnd   &&
    391 		endPosition <= fBufferLimit)
    392 		{
    393 
    394 		DoCopyBytes (data,
    395 					 fBuffer + (uint32) (fPosition - fBufferStart),
    396 				     count);
    397 
    398 		if (fBufferEnd < endPosition)
    399 			fBufferEnd = endPosition;
    400 
    401 		}
    402 
    403 	// Else we need to write to the file.
    404 
    405 	else
    406 		{
    407 
    408 		// Write existing buffer.
    409 
    410 		Flush ();
    411 
    412 		// Write large blocks unbuffered.
    413 
    414 		if (count >= fBufferSize)
    415 			{
    416 
    417 			dng_abort_sniffer::SniffForAbort (fSniffer);
    418 
    419 			DoWrite (data, count, fPosition);
    420 
    421 			}
    422 
    423 		// Start a new buffer with small blocks.
    424 
    425 		else
    426 			{
    427 
    428 			fBufferDirty = true;
    429 
    430 			fBufferStart = fPosition;
    431 			fBufferEnd   = endPosition;
    432 			fBufferLimit = fBufferStart + fBufferSize;
    433 
    434 			DoCopyBytes (data,
    435 						 fBuffer,
    436 					     count);
    437 
    438 			}
    439 
    440 		}
    441 
    442 	fPosition = endPosition;
    443 
    444 	fLength = Max_uint64 (Length (), fPosition);
    445 
    446 	}
    447 
    448 /*****************************************************************************/
    449 
    450 uint16 dng_stream::Get_uint16 ()
    451 	{
    452 
    453 	uint16 x;
    454 
    455 	Get (&x, 2);
    456 
    457 	if (fSwapBytes)
    458 		{
    459 
    460 		x = SwapBytes16 (x);
    461 
    462 		}
    463 
    464 	return x;
    465 
    466 	}
    467 
    468 /*****************************************************************************/
    469 
    470 void dng_stream::Put_uint16 (uint16 x)
    471 	{
    472 
    473 	if (fSwapBytes)
    474 		{
    475 
    476 		x = SwapBytes16 (x);
    477 
    478 		}
    479 
    480 	Put (&x, 2);
    481 
    482 	}
    483 
    484 /*****************************************************************************/
    485 
    486 uint32 dng_stream::Get_uint32 ()
    487 	{
    488 
    489 	uint32 x;
    490 
    491 	Get (&x, 4);
    492 
    493 	if (fSwapBytes)
    494 		{
    495 
    496 		x = SwapBytes32 (x);
    497 
    498 		}
    499 
    500 	return x;
    501 
    502 	}
    503 
    504 /*****************************************************************************/
    505 
    506 void dng_stream::Put_uint32 (uint32 x)
    507 	{
    508 
    509 	if (fSwapBytes)
    510 		{
    511 
    512 		x = SwapBytes32 (x);
    513 
    514 		}
    515 
    516 	Put (&x, 4);
    517 
    518 	}
    519 
    520 /*****************************************************************************/
    521 
    522 uint64 dng_stream::Get_uint64 ()
    523 	{
    524 
    525 	if (fSwapBytes)
    526 		{
    527 
    528 		union
    529 			{
    530 			uint32 u32 [2];
    531 			uint64 u64;
    532 			} u;
    533 
    534 		u.u32 [1] = Get_uint32 ();
    535 		u.u32 [0] = Get_uint32 ();
    536 
    537 		return u.u64;
    538 
    539 		}
    540 
    541 	uint64 x;
    542 
    543 	Get (&x, 8);
    544 
    545 	return x;
    546 
    547 	}
    548 
    549 /*****************************************************************************/
    550 
    551 void dng_stream::Put_uint64 (uint64 x)
    552 	{
    553 
    554 	if (fSwapBytes)
    555 		{
    556 
    557 		union
    558 			{
    559 			uint32 u32 [2];
    560 			uint64 u64;
    561 			} u;
    562 
    563 		u.u64 = x;
    564 
    565 		Put_uint32 (u.u32 [1]);
    566 		Put_uint32 (u.u32 [0]);
    567 
    568 		}
    569 
    570 	else
    571 		{
    572 
    573 		Put (&x, 8);
    574 
    575 		}
    576 
    577 	}
    578 
    579 /*****************************************************************************/
    580 
    581 real32 dng_stream::Get_real32 ()
    582 	{
    583 
    584 	union
    585 		{
    586 		uint32 i;
    587 		real32 r;
    588 		} u;
    589 
    590 	u.i = Get_uint32 ();
    591 
    592 	return u.r;
    593 
    594 	}
    595 
    596 /*****************************************************************************/
    597 
    598 void dng_stream::Put_real32 (real32 x)
    599 	{
    600 
    601 	if (fSwapBytes)
    602 		{
    603 
    604 		union
    605 			{
    606 			uint32 i;
    607 			real32 r;
    608 			} u;
    609 
    610 		u.r = x;
    611 
    612 		Put_uint32 (u.i);
    613 
    614 		}
    615 
    616 	else
    617 		{
    618 
    619 		Put (&x, 4);
    620 
    621 		}
    622 
    623 	}
    624 
    625 /*****************************************************************************/
    626 
    627 real64 dng_stream::Get_real64 ()
    628 	{
    629 
    630 	if (fSwapBytes)
    631 		{
    632 
    633 		union
    634 			{
    635 			uint32 i [2];
    636 			real64 r;
    637 			} u;
    638 
    639 		u.i [1] = Get_uint32 ();
    640 		u.i [0] = Get_uint32 ();
    641 
    642 		return u.r;
    643 
    644 		}
    645 
    646 	real64 x;
    647 
    648 	Get (&x, 8);
    649 
    650 	return x;
    651 
    652 	}
    653 
    654 /*****************************************************************************/
    655 
    656 void dng_stream::Put_real64 (real64 x)
    657 	{
    658 
    659 	if (fSwapBytes)
    660 		{
    661 
    662 		union
    663 			{
    664 			uint32 i [2];
    665 			real64 r;
    666 			} u;
    667 
    668 		u.r = x;
    669 
    670 		Put_uint32 (u.i [1]);
    671 		Put_uint32 (u.i [0]);
    672 
    673 		}
    674 
    675 	else
    676 		{
    677 
    678 		Put (&x, 8);
    679 
    680 		}
    681 
    682 	}
    683 
    684 /*****************************************************************************/
    685 
    686 void dng_stream::Get_CString (char *data, uint32 maxLength)
    687 	{
    688 
    689 	memset (data, 0, maxLength);
    690 
    691 	uint32 index = 0;
    692 
    693 	while (true)
    694 		{
    695 
    696 		char c = (char) Get_uint8 ();
    697 
    698 		if (index + 1 < maxLength)
    699 			data [index++] = c;
    700 
    701 		if (c == 0)
    702 			break;
    703 
    704 		}
    705 
    706 	}
    707 
    708 /*****************************************************************************/
    709 
    710 void dng_stream::Get_UString (char *data, uint32 maxLength)
    711 	{
    712 
    713 	memset (data, 0, maxLength);
    714 
    715 	uint32 index = 0;
    716 
    717 	while (true)
    718 		{
    719 
    720 		char c = (char) Get_uint16 ();
    721 
    722 		if (index + 1 < maxLength)
    723 			data [index++] = (char) c;
    724 
    725 		if (c == 0)
    726 			break;
    727 
    728 		}
    729 
    730 	}
    731 
    732 /*****************************************************************************/
    733 
    734 void dng_stream::PutZeros (uint64 count)
    735 	{
    736 
    737 	const uint32 kZeroBufferSize = 4096;
    738 
    739 	if (count >= kZeroBufferSize)
    740 		{
    741 
    742 		dng_memory_data zeroBuffer (kZeroBufferSize);
    743 
    744 		DoZeroBytes (zeroBuffer.Buffer (),
    745 					 kZeroBufferSize);
    746 
    747 		while (count)
    748 			{
    749 
    750 			uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
    751 
    752 			Put (zeroBuffer.Buffer (), (uint32) blockSize);
    753 
    754 			count -= blockSize;
    755 
    756 			}
    757 
    758 		}
    759 
    760 	else
    761 		{
    762 
    763 		uint32 count32 = (uint32) count;
    764 
    765 		for (uint32 j = 0; j < count32; j++)
    766 			{
    767 
    768 			Put_uint8 (0);
    769 
    770 			}
    771 
    772 		}
    773 
    774 	}
    775 
    776 /*****************************************************************************/
    777 
    778 void dng_stream::PadAlign2 ()
    779 	{
    780 
    781 	PutZeros (Position () & 1);
    782 
    783 	}
    784 
    785 /*****************************************************************************/
    786 
    787 void dng_stream::PadAlign4 ()
    788 	{
    789 
    790 	PutZeros ((4 - (Position () & 3)) & 3);
    791 
    792 	}
    793 
    794 /*****************************************************************************/
    795 
    796 uint32 dng_stream::TagValue_uint32 (uint32 tagType)
    797 	{
    798 
    799 	switch (tagType)
    800 		{
    801 
    802 		case ttByte:
    803 			return (uint32) Get_uint8 ();
    804 
    805 		case ttShort:
    806 			return (uint32) Get_uint16 ();
    807 
    808 		case ttLong:
    809 		case ttIFD:
    810 			return Get_uint32 ();
    811 
    812 		}
    813 
    814 	real64 x = TagValue_real64 (tagType);
    815 
    816 	if (x < 0.0)
    817 		x = 0.0;
    818 
    819 	if (x > (real64) 0xFFFFFFFF)
    820 		x = (real64) 0xFFFFFFFF;
    821 
    822 	return ConvertDoubleToUint32(x + 0.5);
    823 
    824 	}
    825 
    826 /*****************************************************************************/
    827 
    828 int32 dng_stream::TagValue_int32 (uint32 tagType)
    829 	{
    830 
    831 	switch (tagType)
    832 		{
    833 
    834 		case ttSByte:
    835 			return (int32) Get_int8 ();
    836 
    837 		case ttSShort:
    838 			return (int32) Get_int16 ();
    839 
    840 		case ttSLong:
    841 			return Get_int32 ();
    842 
    843 		}
    844 
    845 	real64 x = TagValue_real64 (tagType);
    846 
    847 	if (x < 0.0)
    848 		{
    849 
    850 		if (x < -2147483648.0)
    851 			x = -2147483648.0;
    852 
    853 		return ConvertDoubleToInt32(x - 0.5);
    854 
    855 		}
    856 
    857 	else
    858 		{
    859 
    860 		if (x > 2147483647.0)
    861 			x = 2147483647.0;
    862 
    863 		return ConvertDoubleToInt32(x + 0.5);
    864 
    865 		}
    866 
    867 	}
    868 
    869 /*****************************************************************************/
    870 
    871 dng_urational dng_stream::TagValue_urational (uint32 tagType)
    872 	{
    873 
    874 	dng_urational result;
    875 
    876 	result.n = 0;
    877 	result.d = 1;
    878 
    879 	switch (tagType)
    880 		{
    881 
    882 		case ttRational:
    883 			{
    884 
    885 			result.n = Get_uint32 ();
    886 			result.d = Get_uint32 ();
    887 
    888 			break;
    889 
    890 			}
    891 
    892 		case ttSRational:
    893 			{
    894 
    895 			int32 n = Get_int32 ();
    896 			int32 d = Get_int32 ();
    897 
    898 			if ((n < 0) == (d < 0))
    899 				{
    900 
    901 				if (d < 0)
    902 					{
    903 					result.n = (uint32) ((int64) n * -1);
    904 					result.d = (uint32) ((int64) d * -1);
    905 					}
    906 				else
    907 					{
    908 					result.n = (uint32) n;
    909 					result.d = (uint32) d;
    910 					}
    911 
    912 				}
    913 
    914 			break;
    915 
    916 			}
    917 
    918 		case ttByte:
    919 		case ttShort:
    920 		case ttLong:
    921 		case ttIFD:
    922 			{
    923 
    924 			result.n = TagValue_uint32 (tagType);
    925 
    926 			break;
    927 
    928 			}
    929 
    930 		case ttSByte:
    931 		case ttSShort:
    932 		case ttSLong:
    933 			{
    934 
    935 			int32 n = TagValue_int32 (tagType);
    936 
    937 			if (n > 0)
    938 				{
    939 				result.n = (uint32) n;
    940 				}
    941 
    942 			break;
    943 
    944 			}
    945 
    946 		default:
    947 			{
    948 
    949 			real64 x = TagValue_real64 (tagType);
    950 
    951 			if (x > 0.0)
    952 				{
    953 
    954 				while (result.d < 10000 && x < 1000000)
    955 					{
    956 
    957 					result.d *= 10;
    958 
    959 					x *= 10.0;
    960 
    961 					}
    962 
    963 				result.n = ConvertDoubleToUint32(x + 0.5);
    964 
    965 				}
    966 
    967 			}
    968 
    969 		}
    970 
    971 	return result;
    972 
    973 	}
    974 
    975 /*****************************************************************************/
    976 
    977 dng_srational dng_stream::TagValue_srational (uint32 tagType)
    978 	{
    979 
    980 	dng_srational result;
    981 
    982 	result.n = 0;
    983 	result.d = 1;
    984 
    985 	switch (tagType)
    986 		{
    987 
    988 		case ttSRational:
    989 			{
    990 
    991 			result.n = Get_int32 ();
    992 			result.d = Get_int32 ();
    993 
    994 			break;
    995 
    996 			}
    997 
    998 		default:
    999 			{
   1000 
   1001 			real64 x = TagValue_real64 (tagType);
   1002 
   1003 			if (x > 0.0)
   1004 				{
   1005 
   1006 				while (result.d < 10000 && x < 1000000.0)
   1007 					{
   1008 
   1009 					result.d *= 10;
   1010 
   1011 					x *= 10.0;
   1012 
   1013 					}
   1014 
   1015 				result.n = ConvertDoubleToInt32(x + 0.5);
   1016 
   1017 				}
   1018 
   1019 			else
   1020 				{
   1021 
   1022 				while (result.d < 10000 && x > -1000000.0)
   1023 					{
   1024 
   1025 					result.d *= 10;
   1026 
   1027 					x *= 10.0;
   1028 
   1029 					}
   1030 
   1031 				result.n = ConvertDoubleToInt32(x - 0.5);
   1032 
   1033 				}
   1034 
   1035 			}
   1036 
   1037 		}
   1038 
   1039 	return result;
   1040 
   1041 	}
   1042 
   1043 /*****************************************************************************/
   1044 
   1045 real64 dng_stream::TagValue_real64 (uint32 tagType)
   1046 	{
   1047 
   1048 	switch (tagType)
   1049 		{
   1050 
   1051 		case ttByte:
   1052 		case ttShort:
   1053 		case ttLong:
   1054 		case ttIFD:
   1055 			return (real64) TagValue_uint32 (tagType);
   1056 
   1057 		case ttSByte:
   1058 		case ttSShort:
   1059 		case ttSLong:
   1060 			return (real64) TagValue_int32 (tagType);
   1061 
   1062 		case ttRational:
   1063 			{
   1064 
   1065 			uint32 n = Get_uint32 ();
   1066 			uint32 d = Get_uint32 ();
   1067 
   1068 			if (d == 0)
   1069 				return 0.0;
   1070 			else
   1071 				return (real64) n / (real64) d;
   1072 
   1073 			}
   1074 
   1075 		case ttSRational:
   1076 			{
   1077 
   1078 			int32 n = Get_int32 ();
   1079 			int32 d = Get_int32 ();
   1080 
   1081 			if (d == 0)
   1082 				return 0.0;
   1083 			else
   1084 				return (real64) n / (real64) d;
   1085 
   1086 			}
   1087 
   1088 		case ttFloat:
   1089 			return (real64) Get_real32 ();
   1090 
   1091 		case ttDouble:
   1092 			return Get_real64 ();
   1093 
   1094 		}
   1095 
   1096 	return 0.0;
   1097 
   1098 	}
   1099 
   1100 /*****************************************************************************/
   1101 
   1102 void dng_stream::CopyToStream (dng_stream &dstStream,
   1103 							   uint64 count)
   1104 	{
   1105 
   1106 	uint8 smallBuffer [1024];
   1107 
   1108 	if (count <= sizeof (smallBuffer))
   1109 		{
   1110 
   1111 		Get (smallBuffer, (uint32) count);
   1112 
   1113 		dstStream.Put (smallBuffer, (uint32) count);
   1114 
   1115 		}
   1116 
   1117 	else
   1118 		{
   1119 
   1120 		const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
   1121 													      count);
   1122 
   1123 		dng_memory_data bigBuffer (bigBufferSize);
   1124 
   1125 		while (count)
   1126 			{
   1127 
   1128 			uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
   1129 													 count);
   1130 
   1131 			Get (bigBuffer.Buffer (),
   1132 				 blockCount);
   1133 
   1134 			dstStream.Put (bigBuffer.Buffer (),
   1135 						   blockCount);
   1136 
   1137 			count -= blockCount;
   1138 
   1139 			}
   1140 
   1141 		}
   1142 
   1143 	}
   1144 
   1145 /*****************************************************************************/
   1146 
   1147 void dng_stream::DuplicateStream (dng_stream &dstStream)
   1148 	{
   1149 
   1150 	// Turn off sniffers for this operation.
   1151 
   1152 	TempStreamSniffer noSniffer1 (*this    , NULL);
   1153 	TempStreamSniffer noSniffer2 (dstStream, NULL);
   1154 
   1155 	// First grow the destination stream if required, in an attempt to
   1156 	// reserve any needed space before overwriting the existing data.
   1157 
   1158 	if (dstStream.Length () < Length ())
   1159 		{
   1160 		dstStream.SetLength (Length ());
   1161 		}
   1162 
   1163 	SetReadPosition (0);
   1164 
   1165 	dstStream.SetWritePosition (0);
   1166 
   1167 	CopyToStream (dstStream, Length ());
   1168 
   1169 	dstStream.Flush ();
   1170 
   1171 	dstStream.SetLength (Length ());
   1172 
   1173 	}
   1174 
   1175 /*****************************************************************************/
   1176 
   1177 TempBigEndian::TempBigEndian (dng_stream &stream,
   1178 						 	  bool bigEndian)
   1179 
   1180 	:	fStream  (stream)
   1181 	,	fOldSwap (stream.SwapBytes ())
   1182 
   1183 	{
   1184 
   1185 	fStream.SetBigEndian (bigEndian);
   1186 
   1187 	}
   1188 
   1189 /*****************************************************************************/
   1190 
   1191 TempBigEndian::~TempBigEndian ()
   1192 	{
   1193 
   1194 	fStream.SetSwapBytes (fOldSwap);
   1195 
   1196 	}
   1197 
   1198 /*****************************************************************************/
   1199 
   1200 TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
   1201 									  dng_abort_sniffer *sniffer)
   1202 
   1203 	:	fStream     (stream)
   1204 	,	fOldSniffer (stream.Sniffer ())
   1205 
   1206 	{
   1207 
   1208 	fStream.SetSniffer (sniffer);
   1209 
   1210 	}
   1211 
   1212 /*****************************************************************************/
   1213 
   1214 TempStreamSniffer::~TempStreamSniffer ()
   1215 	{
   1216 
   1217 	fStream.SetSniffer (fOldSniffer);
   1218 
   1219 	}
   1220 
   1221 /*****************************************************************************/
   1222