1 /*****************************************************************************/
2 // Copyright 2008-2019 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 #include "dng_opcode_list.h"
10 
11 #include "dng_globals.h"
12 #include "dng_host.h"
13 #include "dng_memory_stream.h"
14 #include "dng_negative.h"
15 #include "dng_tag_values.h"
16 #include "dng_utils.h"
17 
18 #include <algorithm>
19 
20 /*****************************************************************************/
21 
dng_opcode_list(uint32 stage)22 dng_opcode_list::dng_opcode_list (uint32 stage)
23 
24 	:	fList        ()
25 	,	fAlwaysApply (false)
26 	,	fStage		 (stage)
27 
28 	{
29 
30 	}
31 
32 /******************************************************************************/
33 
~dng_opcode_list()34 dng_opcode_list::~dng_opcode_list ()
35 	{
36 
37 	Clear ();
38 
39 	}
40 
41 /******************************************************************************/
42 
Clear()43 void dng_opcode_list::Clear ()
44 	{
45 
46 	for (size_t index = 0; index < fList.size (); index++)
47 		{
48 
49 		if (fList [index])
50 			{
51 
52 			delete fList [index];
53 
54 			fList [index] = NULL;
55 
56 			}
57 
58 		}
59 
60 	fList.clear ();
61 
62 	fAlwaysApply = false;
63 
64 	}
65 
66 /******************************************************************************/
67 
Swap(dng_opcode_list & otherList)68 void dng_opcode_list::Swap (dng_opcode_list &otherList)
69 	{
70 
71 	fList.swap (otherList.fList);
72 
73 	std::swap (fAlwaysApply, otherList.fAlwaysApply);
74 
75 	std::swap (fStage, otherList.fStage);
76 
77 	}
78 
79 /******************************************************************************/
80 
MinVersion(bool includeOptional) const81 uint32 dng_opcode_list::MinVersion (bool includeOptional) const
82 	{
83 
84 	uint32 result = dngVersion_None;
85 
86 	for (size_t index = 0; index < fList.size (); index++)
87 		{
88 
89 		if (includeOptional || !fList [index]->Optional ())
90 			{
91 
92 			result = Max_uint32 (result, fList [index]->MinVersion ());
93 
94 			}
95 
96 		}
97 
98 	return result;
99 
100 	}
101 
102 /*****************************************************************************/
103 
Apply(dng_host & host,dng_negative & negative,AutoPtr<dng_image> & image)104 void dng_opcode_list::Apply (dng_host &host,
105 							 dng_negative &negative,
106 							 AutoPtr<dng_image> &image)
107 	{
108 
109 	DNG_REQUIRE (image.Get (), "Bad image in dng_opcode_list::Apply");
110 
111 	for (uint32 index = 0; index < Count (); index++)
112 		{
113 
114 		dng_opcode &opcode (Entry (index));
115 
116 		if (opcode.AboutToApply (host,
117 								 negative,
118 								 image->Bounds (),
119 								 image->Planes ()))
120 			{
121 
122 			opcode.Apply (host,
123 						  negative,
124 						  image);
125 
126 			}
127 
128 		}
129 
130 	}
131 
132 /*****************************************************************************/
133 
Append(AutoPtr<dng_opcode> & opcode)134 void dng_opcode_list::Append (AutoPtr<dng_opcode> &opcode)
135 	{
136 
137 	if (opcode->OpcodeID () == dngOpcode_Private)
138 		{
139 		SetAlwaysApply ();
140 		}
141 
142 	opcode->SetStage (fStage);
143 
144 	fList.push_back (NULL);
145 
146 	fList [fList.size () - 1] = opcode.Release ();
147 
148 	}
149 
150 /*****************************************************************************/
151 
Spool(dng_host & host) const152 dng_memory_block * dng_opcode_list::Spool (dng_host &host) const
153 	{
154 
155 	if (IsEmpty ())
156 		{
157 		return NULL;
158 		}
159 
160 	if (AlwaysApply ())
161 		{
162 		ThrowProgramError ();
163 		}
164 
165 	dng_memory_stream stream (host.Allocator ());
166 
167 	stream.SetBigEndian ();
168 
169 	stream.Put_uint32 ((uint32) fList.size ());
170 
171 	for (size_t index = 0; index < fList.size (); index++)
172 		{
173 
174 		stream.Put_uint32 (fList [index]->OpcodeID   ());
175 		stream.Put_uint32 (fList [index]->MinVersion ());
176 		stream.Put_uint32 (fList [index]->Flags      ());
177 
178 		fList [index]->PutData (stream);
179 
180 		}
181 
182 	return stream.AsMemoryBlock (host.Allocator ());
183 
184 	}
185 
186 /*****************************************************************************/
187 
FingerprintToStream(dng_stream & stream) const188 void dng_opcode_list::FingerprintToStream (dng_stream &stream) const
189 	{
190 
191 	if (IsEmpty ())
192 		{
193 		return;
194 		}
195 
196 	stream.Put_uint32 ((uint32) fList.size ());
197 
198 	for (size_t index = 0; index < fList.size (); index++)
199 		{
200 
201 		stream.Put_uint32 (fList [index]->OpcodeID   ());
202 		stream.Put_uint32 (fList [index]->MinVersion ());
203 		stream.Put_uint32 (fList [index]->Flags      ());
204 
205 		if (fList [index]->OpcodeID () != dngOpcode_Private)
206 			{
207 
208 			fList [index]->PutData (stream);
209 
210 			}
211 
212 		}
213 
214 	}
215 
216 /*****************************************************************************/
217 
Parse(dng_host & host,dng_stream & stream,uint32 byteCount,uint64 streamOffset)218 void dng_opcode_list::Parse (dng_host &host,
219 							 dng_stream &stream,
220 							 uint32 byteCount,
221 							 uint64 streamOffset)
222 	{
223 
224 	Clear ();
225 
226 	TempBigEndian tempBigEndian (stream);
227 
228 	stream.SetReadPosition (streamOffset);
229 
230 	uint32 count = stream.Get_uint32 ();
231 
232 	#if qDNGValidate
233 
234 	if (gVerbose)
235 		{
236 
237 		if (count == 1)
238 			{
239 			printf ("1 opcode\n");
240 			}
241 
242 		else
243 			{
244 			printf ("%u opcodes\n", (unsigned) count);
245 			}
246 
247 		}
248 
249 	#endif
250 
251 	for (uint32 index = 0; index < count; index++)
252 		{
253 
254 		uint32 opcodeID = stream.Get_uint32 ();
255 
256 		AutoPtr<dng_opcode> opcode (host.Make_dng_opcode (opcodeID,
257 														  stream));
258 
259 		Append (opcode);
260 
261 		}
262 
263 	if (stream.Position () != streamOffset + byteCount)
264 		{
265 
266 		ThrowBadFormat ("Error parsing opcode list");
267 
268 		}
269 
270 	}
271 
272 /*****************************************************************************/
273