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_memory_stream.cpp#1 $ */
     10 /* $DateTime: 2012/05/30 13:28:51 $ */
     11 /* $Change: 832332 $ */
     12 /* $Author: tknoll $ */
     13 
     14 /*****************************************************************************/
     15 
     16 #include "dng_memory_stream.h"
     17 
     18 #include "dng_bottlenecks.h"
     19 #include "dng_exceptions.h"
     20 #include "dng_safe_arithmetic.h"
     21 #include "dng_utils.h"
     22 
     23 /*****************************************************************************/
     24 
     25 dng_memory_stream::dng_memory_stream (dng_memory_allocator &allocator,
     26 									  dng_abort_sniffer *sniffer,
     27 						   			  uint32 pageSize)
     28 
     29 	:	dng_stream (sniffer,
     30 					kDefaultBufferSize,
     31 					kDNGStreamInvalidOffset)
     32 
     33 	,	fAllocator (allocator)
     34 	,	fPageSize  (pageSize )
     35 
     36 	,	fPageCount      (0)
     37 	,	fPagesAllocated (0)
     38 	,	fPageList       (NULL)
     39 
     40 	,	fMemoryStreamLength (0)
     41 
     42 	{
     43 
     44 	}
     45 
     46 /*****************************************************************************/
     47 
     48 dng_memory_stream::~dng_memory_stream ()
     49 	{
     50 
     51 	if (fPageList)
     52 		{
     53 
     54 		for (uint32 index = 0; index < fPageCount; index++)
     55 			{
     56 
     57 			delete fPageList [index];
     58 
     59 			}
     60 
     61 		free (fPageList);
     62 
     63 		}
     64 
     65 	}
     66 
     67 /*****************************************************************************/
     68 
     69 uint64 dng_memory_stream::DoGetLength ()
     70 	{
     71 
     72 	return fMemoryStreamLength;
     73 
     74 	}
     75 
     76 /*****************************************************************************/
     77 
     78 void dng_memory_stream::DoRead (void *data,
     79 							    uint32 count,
     80 							    uint64 offset)
     81 	{
     82 
     83 	if (offset + count > fMemoryStreamLength)
     84 		{
     85 
     86 		ThrowEndOfFile ();
     87 
     88 		}
     89 
     90 	uint64 baseOffset = offset;
     91 
     92 	while (count)
     93 		{
     94 
     95 		uint32 pageIndex  = (uint32) (offset / fPageSize);
     96 		uint32 pageOffset = (uint32) (offset % fPageSize);
     97 
     98 		uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count);
     99 
    100 		const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () +
    101 						    pageOffset;
    102 
    103 		uint8 *dPtr = ((uint8 *) data) + (uint32) (offset - baseOffset);
    104 
    105 		DoCopyBytes (sPtr, dPtr, blockCount);
    106 
    107 		offset += blockCount;
    108 		count  -= blockCount;
    109 
    110 		}
    111 
    112 	}
    113 
    114 /*****************************************************************************/
    115 
    116 void dng_memory_stream::DoSetLength (uint64 length)
    117 	{
    118 
    119 	while (length > fPageCount * (uint64) fPageSize)
    120 		{
    121 
    122 		if (fPageCount == fPagesAllocated)
    123 			{
    124 
    125 			uint32 newSizeTemp1 = 0, newSizeTemp2 = 0;
    126 			if (!SafeUint32Add (fPagesAllocated, 32u, &newSizeTemp1) ||
    127 				!SafeUint32Mult (fPagesAllocated, 2u, &newSizeTemp2))
    128 				{
    129 				ThrowMemoryFull ("Arithmetic overflow in DoSetLength()");
    130 				}
    131 			uint32 newSize = Max_uint32 (newSizeTemp1, newSizeTemp2);
    132 			uint32 numBytes;
    133 			if (!SafeUint32Mult (newSize, sizeof (dng_memory_block *),
    134 								 &numBytes))
    135 				{
    136 				ThrowMemoryFull ("Arithmetic overflow in DoSetLength()");
    137 				}
    138 
    139 			dng_memory_block **list = (dng_memory_block **) malloc (numBytes);
    140 
    141 			if (!list)
    142 				{
    143 
    144 				ThrowMemoryFull ();
    145 
    146 				}
    147 
    148 			if (fPageCount)
    149 				{
    150 
    151 				// The multiplication here is safe against overflow. fPageCount
    152 				// can never reach a value that is large enough to cause
    153 				// overflow because the computation of numBytes above would fail
    154 				// before a list of that size could be allocated.
    155 				DoCopyBytes (fPageList,
    156 							 list,
    157 							 fPageCount * (uint32) sizeof (dng_memory_block *));
    158 
    159 				}
    160 
    161 			if (fPageList)
    162 				{
    163 
    164 				free (fPageList);
    165 
    166 				}
    167 
    168 			fPageList = list;
    169 
    170 			fPagesAllocated = newSize;
    171 
    172 			}
    173 
    174 		fPageList [fPageCount] = fAllocator.Allocate (fPageSize);
    175 
    176 		fPageCount++;
    177 
    178 		}
    179 
    180 	fMemoryStreamLength = length;
    181 
    182 	}
    183 
    184 /*****************************************************************************/
    185 
    186 void dng_memory_stream::DoWrite (const void *data,
    187 							     uint32 count,
    188 							     uint64 offset)
    189 	{
    190 
    191 	DoSetLength (Max_uint64 (fMemoryStreamLength,
    192 							 offset + count));
    193 
    194 	uint64 baseOffset = offset;
    195 
    196 	while (count)
    197 		{
    198 
    199 		uint32 pageIndex  = (uint32) (offset / fPageSize);
    200 		uint32 pageOffset = (uint32) (offset % fPageSize);
    201 
    202 		uint32 blockCount = Min_uint32 (fPageSize - pageOffset, count);
    203 
    204 		const uint8 *sPtr = ((const uint8 *) data) + (uint32) (offset - baseOffset);
    205 
    206 		uint8 *dPtr = fPageList [pageIndex]->Buffer_uint8 () +
    207 					  pageOffset;
    208 
    209 		DoCopyBytes (sPtr, dPtr, blockCount);
    210 
    211 		offset += blockCount;
    212 		count  -= blockCount;
    213 
    214 		}
    215 
    216 	}
    217 
    218 /*****************************************************************************/
    219 
    220 void dng_memory_stream::CopyToStream (dng_stream &dstStream,
    221 									  uint64 count)
    222 	{
    223 
    224 	if (count < kBigBufferSize)
    225 		{
    226 
    227 		dng_stream::CopyToStream (dstStream, count);
    228 
    229 		}
    230 
    231 	else
    232 		{
    233 
    234 		Flush ();
    235 
    236 		uint64 offset = Position ();
    237 
    238 		if (offset + count > Length ())
    239 			{
    240 
    241 			ThrowEndOfFile ();
    242 
    243 			}
    244 
    245 		while (count)
    246 			{
    247 
    248 			uint32 pageIndex  = (uint32) (offset / fPageSize);
    249 			uint32 pageOffset = (uint32) (offset % fPageSize);
    250 
    251 			uint32 blockCount = (uint32) Min_uint64 (fPageSize - pageOffset, count);
    252 
    253 			const uint8 *sPtr = fPageList [pageIndex]->Buffer_uint8 () +
    254 								pageOffset;
    255 
    256 			dstStream.Put (sPtr, blockCount);
    257 
    258 			offset += blockCount;
    259 			count  -= blockCount;
    260 
    261 			}
    262 
    263 		SetReadPosition (offset);
    264 
    265 		}
    266 
    267 	}
    268 
    269 /*****************************************************************************/
    270