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