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 25dng_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 48dng_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 69uint64 dng_memory_stream::DoGetLength () 70 { 71 72 return fMemoryStreamLength; 73 74 } 75 76/*****************************************************************************/ 77 78void 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 116void 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 186void 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 220void 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