Coverage Report

Created: 2026-10-14 06:45

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