Coverage Report

Created: 2025-07-16 07:53

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