1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
// =================================================================================================
// Copyright Adobe
// Copyright 2010 Adobe
// All Rights Reserved
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
// of the Adobe license agreement accompanying it. If you have received this file from a source other
// than Adobe, then your use, modification, or distribution of it requires the prior written permission
// of Adobe.
// =================================================================================================
#ifndef _ChunkController_h_
#define _ChunkController_h_
#include "public/include/XMP_Environment.h" // ! XMP_Environment.h must be the first included header.
#include "public/include/XMP_Const.h"
#include "public/include/XMP_IO.hpp"
#include "source/XMP_LibUtils.hpp"
#include "source/XMP_ProgressTracker.hpp"
#include "XMPFiles/source/FormatSupport/IFF/ChunkPath.h"
#include "XMPFiles/source/FormatSupport/IFF/IChunkBehavior.h"
class IEndian;
namespace IFF_RIFF
{
/**
The class ChunkController is supposed to act as an controller between the IRIFFHandler and the actual chunks (Chunk instances).
It controls the parsing and writing of the passed stream.
*/
class IChunkData;
class IChunkContainer;
class Chunk;
class ChunkController
{
public:
/**
* Constructor:
* Creates an IEndian based instance for further usage.
*
* @param IChunkBehavior* chunkBehavior : for AVI the IChunkBehavior instance would be an instance of a IChunkBehavior class, that knows
* about the 1,2,4 GB border, padding byte special cases, AVIX stuff and so on. That knowledge would
* be used during writeFile()
* In the case of WAVE it would be an instance of WAVEBehavior that would know how to get the 64bit
* size values for RF64 if required. That knowledge would be used during parseFile()
* @param XMP_Bool bigEndian set True if file chunk data is big endian (e.g. AIFF).
* Must explicitely be set, so that handlers do not accidentaly use the wrong endianess
*/
ChunkController( IChunkBehavior* chunkBehavior, XMP_Bool bigEndian );
~ChunkController () NO_EXCEPT_FALSE;
/**
* Adds the given path to the array of "Chunk's of interest",
*
* @param path List of Paths that should be parsed
* example AVI: [ RIFF:AVI/LIST:INFO , RIFF:AVIX/LIST:INFO, RIFF:AVI/LIST:TDAT ]
*/
void addChunkPath( const ChunkPath& path );
/**
* construct the tree, parse children for list of interesting Chunks
* All requested leaf chunks are cached, the parent chunks are created but not cached
* and the rest is skipped.
*
* @param stream the open [file] stream with file pointer at the beginning of the file
*
*/
void parseFile( XMP_IO* stream, XMP_OptionBits* options = NULL );
/**
* Create a new empty chunk
*
* @param id Chunk identifier
* @param type Chunk type [optional]
* @return New IChunkData with passed id/type
*/
IChunkData* createChunk( XMP_Uns32 id, XMP_Uns32 type = kType_NONE );
/**
* Insert a new chunk. The position of this new chunk within the hierarchy
* is determined internally by the behavior.
* Throws an exception if a chunk cannot be inserted into the tree
*
* @param chunk The chunk to insert into the tree
*/
void insertChunk( IChunkData* chunk );
/**
* Delete a chunk or remove/delete it from the tree.
* If the chunk exists within the chunk hierarchy the chunk gets removed from the tree and deleted.
* If it is not in the tree, then it is only destroyed.
*
* @param chunk Chunk to remove/delete
*/
void removeChunk( IChunkData* chunk );
/**
* Called by the handler to write back the changes to the file.
* 1. fix the file tree (ChunkBehavior#fixHierarchy),
* offsets are corrected, no overlapping chunks;
* if rearranging fails, the file is not touched
* 2. write the changed chunks to the file
*
* @param stream the open [file] stream for writing, the file pointer must be at the beginning
* @param progressTracker Progress tracker to track the file write progress and reporting it to client
*/
void writeFile( XMP_IO* stream,XMP_ProgressTracker * progressTracker );
/**
* Returns the first (or last) Chunk that matches the passed path.
*
* @param path the path of the Chunk to return
* @param last in case of duplicates return the last one
* @return Returns Chunk or NULL
*/
IChunkData* getChunk( const ChunkPath& path, XMP_Bool last = false ) const;
/**
* Returns all chunks that match completely to the passed path.
* E.g. if FORM:AIFF/LIST is given, it would return all LIST chunks in FORM:AIFF
*
* @param path the path of the Chunk to return
* @return list of found chunks or empty list
*/
const std::vector<IChunkData*>& getChunks( const ChunkPath& path );
/**
* returns the number of the bytes after the last valid IFF chunk
*/
inline XMP_Int64 getTrailingGarbageSize() { return mTrailingGarbageSize; };
/**
* returns the file size
*/
inline XMP_Int64 getFileSize() { return mFileSize; };
/**
* Return an array containing the types of the top level nodes
* Top level nodes are the ones beneath ROOT
*/
const std::vector<XMP_Uns32> getTopLevelTypes();
/**
* dumps the tree structure
*
*/
std::string dumpTree( );
protected:
/**
* Standard Constructor:
* Hidden on purpose. Must not be used!
* A Controller must have a behavior!
*/
ChunkController() { XMP_Throw("Ctor hidden", kXMPErr_InternalFailure); }
/**
* The function Parses all the sibling chunks. For every chunk it either caches the chunk,
* skips it, or calls the function recusivly for the children chunks
*
* @param stream the file stream
* @param currentPath the path/id of the Chunk to return
* @param options handler options
* @param parent pointer to the parent chunk
*/
void parseChunks( XMP_IO* stream, ChunkPath& currentPath, XMP_OptionBits* options = NULL, Chunk* parent = NULL );
/**
* The function parses all the sibling chunks. For every chunk it either caches the chunk,
* skips it, or calls the function recusivly for the children chunks
*
* @param ChunkPath& currentPath: the path/id of the Chunk to return
*/
ChunkPath::MatchResult compareChunkPaths( const ChunkPath& currentPath );
/**
* Find a chunk described by path in the hierarchy of chunks starting at the passed chunk.
* The position of chunk in the hierarchy is described by the parameter currentPath.
* This method is supposed to be recursively.
*/
Chunk* findChunk( const ChunkPath& path, ChunkPath& currentPath, const Chunk& chunk, XMP_Bool last = false ) const;
/**
* Find all chunks described by path in the hierarchy of chunks starting at the passed chunk.
* The position of chunks in the hierarchy is described by the parameter currentPath.
* Found chunks that match to the path are stored in the member mSearchResults.
* This method is supposed to be recursively.
*/
void findChunks( const ChunkPath& path, ChunkPath& currentPath, const Chunk& chunk );
/**
* Cleanup function called from destructor and in case of an exception
*/
void cleanupTree();
/**
* return true if the passed in Chunk is part of the Chunk tree
*
* @param chunk the chunk that shall be checked.
*/
bool isInTree( Chunk* chunk );
// Members
/**
* Endian class. Either BigEndian oder LittleEndian. Based on the file format.
*/
const IEndian* mEndian;
/**
* Chunk behaviour class. Has file format specific function for getting the size and
* rearranging the chunk tree.
*/
IChunkBehavior* mChunkBehavior;
/** The list of chunks wich should be cached. */
std::vector<ChunkPath> mChunkPaths;
/** Iterator for the list of chunk paths */
typedef std::vector<ChunkPath>::iterator PathIterator;
/** The overall filesize after parsing the file stream */
XMP_Uns64 mFileSize;
/** The root of the Chunk Tree (top level list) */
IChunkContainer* mRoot;
/** Offset of trailing garbage characters */
XMP_Uns64 mTrailingGarbageOffset;
/** Size of trailing garbage characters */
XMP_Uns64 mTrailingGarbageSize;
/** search results of method getChunks(...) */
ChunkPath mSearchPath;
/** Cached search results */
std::vector<IChunkData*> mSearchResults;
}; // ChunkController
static const XMP_Uns64 kMaxRIFFChunkSize = 0x00000000FFFFFFFFLL;
} // namespace
#endif
|