1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) Contributors to the OpenEXR Project.
3
4#ifndef INCLUDED_IMF_ID_MANIFEST_H
5#define INCLUDED_IMF_ID_MANIFEST_H
6
7//-----------------------------------------------------------------------------
8//
9// class IDManifest, to store a table mapping ID numbers to text
10//
11//-----------------------------------------------------------------------------
12#include "ImfForward.h"
13
14#include <cstdint>
15#include <map>
16#include <vector>
17#include <set>
18#include <string>
19
20OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_ENTER
21
22class IMF_EXPORT_TYPE IDManifest
23{
24public:
25
26 // indication of how long a mapping between an ID number and the text holds for
27 enum IMF_EXPORT_ENUM IdLifetime
28 {
29 LIFETIME_FRAME, // The mapping may change every frame:
30 LIFETIME_SHOT, // The mapping is consistent for every frame of a shot
31 LIFETIME_STABLE // The mapping is consistent for all time.
32 };
33
34 //
35 // hashing scheme is stored as a string rather than an enum, to allow
36 // proprietary schemes to be encoded with less danger of collision
37 // proprietary schemes should be encoded in a reverse-URL syntax
38 //
39
40 IMF_EXPORT
41 static const std::string UNKNOWN; // = "unknown" : default value for encoding scheme and hash scheme - should be changed
42 IMF_EXPORT
43 static const std::string NOTHASHED; // = "none" : no relationship between text and ID
44 IMF_EXPORT
45 static const std::string CUSTOMHASH; // = "custom" : text is hashed using defined scheme
46 IMF_EXPORT
47 static const std::string MURMURHASH3_32; // = "MurmurHash3_32" : MurmurHash3 32 bit is used
48 IMF_EXPORT
49 static const std::string MURMURHASH3_64; // = "MurmurHash3_64" : bottom 8 bytes of MurmarHash3_128 (64 bit architecture version) is used
50
51
52 IMF_EXPORT
53 static const std::string ID_SCHEME; // ="id" : 32 bit ID stored directly in a UINT channel
54 IMF_EXPORT
55 static const std::string ID2_SCHEME; // ="id2" : 64 bit ID stored in two channels, specified by the ChannelGroup
56
57
58
59 IMF_EXPORT
60 IDManifest();
61
62 friend class CompressedIDManifest;
63
64 //
65 // decompress a compressed IDManifest into IDManifest for reading
66 //
67 IMF_EXPORT
68 IDManifest(const CompressedIDManifest&);
69
70 //
71 // construct manifest from serialized representation stored at 'data'
72 //
73 IMF_EXPORT
74 IDManifest(const char* data, const char* end);
75
76
77private :
78 // internal helper function called by constructors
79 IMF_HIDDEN void init(const char* data,const char* end);
80public :
81
82 //
83 // Description of the information represented by a single group of channels
84 //
85 class IMF_EXPORT_TYPE ChannelGroupManifest
86 {
87 private:
88 std::set<std::string> _channels; // group of channels this manifest represents
89 std::vector<std::string> _components; // ordered list of components represented by this channel group
90 IdLifetime _lifeTime;
91 std::string _hashScheme; //one of above strings or custom value e.g "nz.co.wetafx.cleverhash2"
92 std::string _encodingScheme; //string identifying scheme to encode ID numbers within the image
93
94 typedef std::map<uint64_t, std::vector<std::string> > IDTable;
95 IDTable _table;
96
97 // used for << operator to work: tracks the last item inserted into the Manifest
98 IDTable::iterator _insertionIterator;
99 bool _insertingEntry; // true if << has been called but not enough strings yet set
100
101 public:
102 IMF_EXPORT
103 ChannelGroupManifest();
104
105 IMF_EXPORT
106 const std::set<std::string>& getChannels() const;
107
108 IMF_EXPORT
109 std::set<std::string>& getChannels();
110
111 IMF_EXPORT
112 void setChannels(const std::set<std::string>& channels);
113 IMF_EXPORT
114 void setChannel(const std::string& channel);
115
116 // get list of components for this channel group
117 IMF_EXPORT
118 const std::vector<std::string>& getComponents() const;
119
120 // set components: throws an exception if there are already entries in the table
121 // and the component length changes
122 IMF_EXPORT
123 void setComponents(const std::vector<std::string>& components);
124
125 // set name of single component: throws an exception if there are already entries in the table
126 // unless there was previously one component
127 IMF_EXPORT
128 void setComponent(const std::string& component);
129
130 IdLifetime getLifetime() const { return _lifeTime;}
131
132 void setLifetime(const IdLifetime& lifeTime) { _lifeTime = lifeTime;}
133
134 const std::string& getHashScheme() const { return _hashScheme;}
135 void setHashScheme(const std::string& hashScheme) { _hashScheme = hashScheme;}
136
137 const std::string& getEncodingScheme() const { return _encodingScheme;}
138 void setEncodingScheme(const std::string& encodingScheme) { _encodingScheme = encodingScheme;}
139
140
141 class Iterator; // iterator which allows modification of the text
142 class ConstIterator; // iterator which does not allow modification
143
144
145 IMF_EXPORT
146 Iterator begin();
147 IMF_EXPORT
148 ConstIterator begin() const;
149 IMF_EXPORT
150 Iterator end();
151 IMF_EXPORT
152 ConstIterator end() const;
153
154 // return number of entries in manifest - could be 0
155 IMF_EXPORT
156 size_t size() const ;
157
158 // insert a new entry - text must contain same number of items as getComponents
159 IMF_EXPORT
160 Iterator insert(uint64_t idValue, const std::vector<std::string>& text);
161
162 // insert a new entry - getComponents must be a single entry
163 IMF_EXPORT
164 Iterator insert(uint64_t idValue, const std::string& text);
165
166
167 // compute hash of given entry, insert into manifest, and return
168 // the computed hash. Exception will be thrown if hash scheme isn't recognised
169 IMF_EXPORT
170 uint64_t insert(const std::vector<std::string>& text);
171 IMF_EXPORT
172 uint64_t insert(const std::string& text);
173
174 IMF_EXPORT
175 Iterator find(uint64_t idValue);
176
177 IMF_EXPORT
178 ConstIterator find(uint64_t idValue) const;
179
180 IMF_EXPORT
181 void erase(uint64_t idValue);
182
183 // return reference to idName for given idValue. Adds the mapping to the vector if it doesn't exist
184 IMF_EXPORT
185 std::vector<std::string>& operator[](uint64_t idValue);
186
187 // add a new entry to the manifest as an insertion operator: <<
188 // the component strings must also be inserted using <<
189 // throws an exception if the previous insert operation didn't insert the correct number of string components
190 IMF_EXPORT
191 ChannelGroupManifest& operator<<(uint64_t idValue);
192
193 // insert a string as the next component of a previously inserted attribute
194 IMF_EXPORT
195 ChannelGroupManifest& operator<<(const std::string& text);
196
197 IMF_EXPORT
198 bool operator==(const ChannelGroupManifest& other) const;
199
200 bool operator!=(const ChannelGroupManifest& other) const { return !(*this==other);}
201
202 friend class IDManifest;
203
204 };
205
206
207
208private:
209 std::vector<ChannelGroupManifest> _manifest;
210
211public:
212
213 // add a new channel group definition to the table, presumably populated with mappings
214 // 'table' will be copied to the internal manifest; to further modify use the return value
215 IMF_EXPORT
216 ChannelGroupManifest& add(const ChannelGroupManifest& table);
217
218
219 //insert an empty table definition for the given channel / group of channels
220 IMF_EXPORT
221 ChannelGroupManifest& add(const std::set<std::string>& group);
222 IMF_EXPORT
223 ChannelGroupManifest& add(const std::string& channel);
224
225
226 // return number of items in manifest
227 IMF_EXPORT
228 size_t size() const;
229
230 // find the first manifest ChannelGroupManifest that defines the given channel
231 // if channel not find, returns a value equal to size()
232 IMF_EXPORT
233 size_t find(const std::string& channel) const;
234
235 IMF_EXPORT
236 const ChannelGroupManifest& operator[](size_t index) const;
237 IMF_EXPORT
238 ChannelGroupManifest& operator[](size_t index);
239
240 //
241 // serialize manifest into data array. Array will be resized to the required size
242 //
243 IMF_EXPORT
244 void serialize(std::vector<char>& data) const;
245
246 IMF_EXPORT
247 bool operator==(const IDManifest& other) const;
248 IMF_EXPORT
249 bool operator!=(const IDManifest& other) const;
250
251
252 //
253 // add entries from 'other' into this manifest if possible
254 // * all ChannelGroupsManifests for different ChannelGroups
255 // will be appended.
256 // * Where 'other' contains a manifest for the same
257 // ChannelGroup:
258 // * If _components differs, the entire ChannelGroupManifest is skipped
259 // * Otherwise, entries not present in 'this' will be inserted
260 // * _hashScheme, _lifeTime and _encodingScheme will be unchanged
261 //
262 // returns 'false' if the same ChannelGroupManifest appears in both 'other' and 'this',
263 // but with different _components, _hashScheme, _lifeTime or _encodingScheme
264 // or if any idValue maps to different strings in 'other' and 'this'
265 //
266 IMF_EXPORT
267 bool merge(const IDManifest& other);
268
269
270 //
271 // static has generation functions
272 //
273 IMF_EXPORT
274 static unsigned int MurmurHash32(const std::string& idString);
275 IMF_EXPORT
276 static unsigned int MurmurHash32(const std::vector<std::string>& idString);
277
278 IMF_EXPORT
279 static uint64_t MurmurHash64(const std::string& idString);
280 IMF_EXPORT
281 static uint64_t MurmurHash64(const std::vector<std::string>& idString);
282
283
284};
285
286
287//
288// zlip compressed version of IDManifest - the IDManifestAttribute encodes this format
289// This should be transparent to the user, since there is implicit casting between the two types
290//
291class CompressedIDManifest
292{
293public:
294 IMF_EXPORT
295 CompressedIDManifest();
296 IMF_EXPORT
297 CompressedIDManifest(const CompressedIDManifest& other);
298
299 IMF_EXPORT
300 CompressedIDManifest& operator=(const CompressedIDManifest& other);
301
302 //
303 // construct a compressed version of the given manifest - to decompress it cast to an IDManifest
304 //
305 IMF_EXPORT
306 CompressedIDManifest(const IDManifest& manifest);
307
308 IMF_EXPORT
309 ~CompressedIDManifest();
310
311 int _compressedDataSize;
312 size_t _uncompressedDataSize;
313 unsigned char* _data;
314
315
316};
317
318
319//
320// Read/Write Iterator object to access individual entries within a manifest
321//
322
323class IDManifest::ChannelGroupManifest::Iterator
324{
325public:
326 IMF_EXPORT
327 Iterator ();
328
329 IMF_EXPORT
330 explicit Iterator (const IDManifest::ChannelGroupManifest::IDTable::iterator &i);
331
332 friend class IDManifest::ChannelGroupManifest::ConstIterator;
333 IMF_EXPORT
334 Iterator & operator ++ ();
335
336 IMF_EXPORT
337 uint64_t id() const;
338 IMF_EXPORT
339 std::vector<std::string>& text();
340
341private:
342 std::map< uint64_t , std::vector<std::string> >::iterator _i;
343
344};
345
346//
347// Read-only Iterator object to access individual entries within a manifest
348//
349
350
351class IDManifest::ChannelGroupManifest::ConstIterator
352{
353public:
354 IMF_EXPORT
355 ConstIterator ();
356
357 // explicit cast from internal map operator (for internal use only)
358 IMF_EXPORT
359 explicit ConstIterator (const IDManifest::ChannelGroupManifest::IDTable::const_iterator &i);
360 // cast from non-const to const iterator
361 IMF_EXPORT
362 ConstIterator (const IDManifest::ChannelGroupManifest::Iterator &other);
363 IMF_EXPORT
364 ConstIterator & operator ++ ();
365
366 IMF_EXPORT
367 uint64_t id() const;
368 IMF_EXPORT
369 const std::vector<std::string>& text() const;
370
371 private:
372
373 std::map< uint64_t , std::vector<std::string> >::const_iterator _i;
374
375 friend bool operator == (const ConstIterator &, const ConstIterator &);
376 friend bool operator != (const ConstIterator &, const ConstIterator &);
377};
378
379
380//
381// ChannelGroupManifest::Iterator implementation: all inline
382//
383
384inline IDManifest::ChannelGroupManifest::Iterator::Iterator() {}
385inline IDManifest::ChannelGroupManifest::Iterator::Iterator(const IDManifest::ChannelGroupManifest::IDTable::iterator &i) :_i(i) {}
386
387
388inline uint64_t
389IDManifest::ChannelGroupManifest::Iterator::id() const { return _i->first;}
390
391inline std::vector<std::string>&
392IDManifest::ChannelGroupManifest::Iterator::text() { return _i->second;}
393
394inline IDManifest::ChannelGroupManifest::Iterator&
395IDManifest::ChannelGroupManifest::Iterator::operator++()
396{
397 ++_i;
398 return *this;
399}
400
401//
402// ChannelGroupManifest::ConstIterator implementation: all inline
403//
404
405inline IDManifest::ChannelGroupManifest::ConstIterator::ConstIterator() {}
406inline IDManifest::ChannelGroupManifest::ConstIterator::ConstIterator(const IDManifest::ChannelGroupManifest::Iterator &other) : _i(other._i) {}
407inline IDManifest::ChannelGroupManifest::ConstIterator::ConstIterator(const IDManifest::ChannelGroupManifest::IDTable::const_iterator &i) :_i(i) {}
408
409inline uint64_t
410IDManifest::ChannelGroupManifest::ConstIterator::id() const { return _i->first;}
411
412inline const std::vector<std::string>&
413IDManifest::ChannelGroupManifest::ConstIterator::text() const { return _i->second;}
414
415inline IDManifest::ChannelGroupManifest::ConstIterator &
416IDManifest::ChannelGroupManifest::ConstIterator::operator++()
417{
418 ++_i;
419 return *this;
420}
421
422inline bool
423operator==(const IDManifest::ChannelGroupManifest::ConstIterator& a, const IDManifest::ChannelGroupManifest::ConstIterator& b)
424{
425 return a._i ==b._i;
426}
427
428inline bool
429operator!=(const IDManifest::ChannelGroupManifest::ConstIterator& a, const IDManifest::ChannelGroupManifest::ConstIterator& b)
430{
431 return a._i !=b._i;
432}
433
434
435
436
437
438OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT
439#endif
440

source code of include/OpenEXR/ImfIDManifest.h