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