Coverage Report

Created: 2026-02-26 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/exiv2/src/tiffvisitor_int.hpp
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
3
#ifndef TIFFVISITOR_INT_HPP_
4
#define TIFFVISITOR_INT_HPP_
5
6
// *****************************************************************************
7
// included header files
8
#include "exif.hpp"
9
#include "types.hpp"
10
11
#include "tiffcomposite_int.hpp"
12
13
#include <array>
14
#include <cstddef>
15
#include <cstdint>
16
#include <map>
17
#include <string>
18
#include <vector>
19
20
// *****************************************************************************
21
// namespace extensions
22
namespace Exiv2 {
23
class IptcData;
24
class XmpData;
25
26
namespace Internal {
27
// *****************************************************************************
28
// class definitions
29
30
/*!
31
  @brief Abstract base class defining the interface for TIFF composite
32
         visitors (Visitor pattern)
33
34
  A concrete visitor class is used as shown in the example below. Accept()
35
  will invoke the member function corresponding to the concrete type of each
36
  component in the composite.
37
38
  @code
39
  void visitorExample(Exiv2::TiffComponent* tiffComponent, Exiv2::TiffVisitor& visitor)
40
  {
41
      tiffComponent->accept(visitor);
42
  }
43
  @endcode
44
 */
45
class TiffVisitor {
46
 public:
47
  //! Events for the stop/go flag. See setGo().
48
  enum GoEvent {
49
    //! Signal to control traversing of the composite tree.
50
    geTraverse = 0,
51
    //! Signal used by TiffReader to signal an unknown makernote.
52
    geKnownMakernote = 1
53
    // Note: If you add more events here, adjust the events_ constant too!
54
  };
55
56
 private:
57
  static const int events_ = 2;               //!< The number of stop/go flags.
58
  std::array<bool, events_> go_{true, true};  //!< Array of stop/go flags. See setGo().
59
60
 public:
61
  //! @name Creators
62
  //@{
63
65.0k
  TiffVisitor() = default;
64
  //! Virtual destructor
65
20.6k
  virtual ~TiffVisitor() = default;
66
  TiffVisitor(const TiffVisitor&) = delete;
67
  TiffVisitor& operator=(const TiffVisitor&) = delete;
68
  //@}
69
70
  //! @name Manipulators
71
  //@{
72
  /*!
73
    @brief Set the stop/go flag: true for go, false for stop.
74
75
    This mechanism is used by visitors and components to signal special
76
    events. Specifically, TiffFinder sets the geTraverse flag as soon as
77
    it finds the correct component to signal to components that the search
78
    should be aborted. TiffReader uses geKnownMakernote to signal problems
79
    reading a makernote to the TiffMnEntry component. There is an array
80
    of flags, one for each defined \em event, so different signals can be
81
    used independent of each other.
82
   */
83
  void setGo(GoEvent event, bool go);
84
  //! Operation to perform for a TIFF entry
85
  virtual void visitEntry(TiffEntry* object) = 0;
86
  //! Operation to perform for a TIFF data entry
87
  virtual void visitDataEntry(TiffDataEntry* object) = 0;
88
  //! Operation to perform for a TIFF image entry
89
  virtual void visitImageEntry(TiffImageEntry* object) = 0;
90
  //! Operation to perform for a TIFF size entry
91
  virtual void visitSizeEntry(TiffSizeEntry* object) = 0;
92
  //! Operation to perform for a TIFF directory
93
  virtual void visitDirectory(TiffDirectory* object) = 0;
94
  /*!
95
    @brief Operation to perform for a TIFF directory, after all components
96
           and before the next entry is processed.
97
   */
98
  virtual void visitDirectoryNext(TiffDirectory* object);
99
  /*!
100
    @brief Operation to perform for a TIFF directory, at the end of the
101
           processing.
102
   */
103
  virtual void visitDirectoryEnd(TiffDirectory* object);
104
  //! Operation to perform for a TIFF sub-IFD
105
  virtual void visitSubIfd(TiffSubIfd* object) = 0;
106
  //! Operation to perform for the makernote component
107
  virtual void visitMnEntry(TiffMnEntry* object) = 0;
108
  //! Operation to perform for an IFD makernote
109
  virtual void visitIfdMakernote(TiffIfdMakernote* object) = 0;
110
  //! Operation to perform after processing an IFD makernote
111
  virtual void visitIfdMakernoteEnd(TiffIfdMakernote* object);
112
  //! Operation to perform for a binary array
113
  virtual void visitBinaryArray(TiffBinaryArray* object) = 0;
114
  /*!
115
    @brief Operation to perform for a TIFF binary array, at the end
116
           of the processing.
117
   */
118
  virtual void visitBinaryArrayEnd(TiffBinaryArray* object);
119
  //! Operation to perform for an element of a binary array
120
  virtual void visitBinaryElement(TiffBinaryElement* object) = 0;
121
  //@}
122
123
  //! @name Accessors
124
  //@{
125
  //! Check if stop flag for \em event is clear, return true if it's clear.
126
  [[nodiscard]] bool go(GoEvent event) const;
127
  //@}
128
129
};  // class TiffVisitor
130
131
/*!
132
  @brief Search the composite for a component with \em tag and \em group.
133
         Return a pointer to the component or 0, if not found. The class
134
         is ready for a first search after construction and can be
135
         re-initialized with init().
136
*/
137
class TiffFinder : public TiffVisitor {
138
 public:
139
  //! @name Creators
140
  //@{
141
  //! Constructor, taking \em tag and \em group of the component to find.
142
44.3k
  constexpr TiffFinder(uint16_t tag, IfdId group) : tag_(tag), group_(group) {
143
44.3k
  }
144
  //@}
145
146
  //! @name Manipulators
147
  //@{
148
  //! Find tag and group in a TIFF entry
149
  void visitEntry(TiffEntry* object) override;
150
  //! Find tag and group in a TIFF data entry
151
  void visitDataEntry(TiffDataEntry* object) override;
152
  //! Find tag and group in a TIFF image entry
153
  void visitImageEntry(TiffImageEntry* object) override;
154
  //! Find tag and group in a TIFF size entry
155
  void visitSizeEntry(TiffSizeEntry* object) override;
156
  //! Find tag and group in a TIFF directory
157
  void visitDirectory(TiffDirectory* object) override;
158
  //! Find tag and group in a TIFF sub-IFD
159
  void visitSubIfd(TiffSubIfd* object) override;
160
  //! Find tag and group in a TIFF makernote
161
  void visitMnEntry(TiffMnEntry* object) override;
162
  //! Find tag and group in an IFD makernote
163
  void visitIfdMakernote(TiffIfdMakernote* object) override;
164
  //! Find tag and group in a binary array
165
  void visitBinaryArray(TiffBinaryArray* object) override;
166
  //! Find tag and group in an element of a binary array
167
  void visitBinaryElement(TiffBinaryElement* object) override;
168
169
  //! Check if \em object matches \em tag and \em group
170
  void findObject(TiffComponent* object);
171
  //! Initialize the Finder for a new search.
172
  void init(uint16_t tag, IfdId group);
173
  //@}
174
175
  //! @name Accessors
176
  //@{
177
  /*!
178
    @brief Return the search result. 0 if no TIFF component was found
179
           for the tag and group combination.
180
   */
181
44.3k
  [[nodiscard]] TiffComponent* result() const {
182
44.3k
    return tiffComponent_;
183
44.3k
  }
184
  //@}
185
186
 private:
187
  uint16_t tag_;
188
  IfdId group_;
189
  TiffComponent* tiffComponent_{};
190
};  // class TiffFinder
191
192
/*!
193
  @brief Copy all image tags from the source tree (the tree that is traversed) to a
194
         target tree, which is empty except for the root element provided in the
195
         constructor.
196
*/
197
class TiffCopier : public TiffVisitor {
198
 public:
199
  //! @name Creators
200
  //@{
201
  /*!
202
    @brief Constructor
203
204
    @param pRoot Pointer to the root element of the (empty) target tree.
205
    @param root Actual root element
206
    @param pHeader Pointer to the TIFF header of the source image.
207
    @param pPrimaryGroups Pointer to the list of primary groups.
208
   */
209
  TiffCopier(TiffComponent* pRoot, uint32_t root, const TiffHeaderBase* pHeader, PrimaryGroups pPrimaryGroups);
210
  //@}
211
212
  //! @name Manipulators
213
  //@{
214
  //! Copy a TIFF entry if it is an image tag
215
  void visitEntry(TiffEntry* object) override;
216
  //! Copy a TIFF data entry if it is an image tag
217
  void visitDataEntry(TiffDataEntry* object) override;
218
  //! Copy a TIFF image entry if it is an image tag
219
  void visitImageEntry(TiffImageEntry* object) override;
220
  //! Copy a TIFF size entry if it is an image tag
221
  void visitSizeEntry(TiffSizeEntry* object) override;
222
  //! Copy a TIFF directory if it is an image tag
223
  void visitDirectory(TiffDirectory* object) override;
224
  //! Copy a TIFF sub-IFD if it is an image tag
225
  void visitSubIfd(TiffSubIfd* object) override;
226
  //! Copy a TIFF makernote if it is an image tag
227
  void visitMnEntry(TiffMnEntry* object) override;
228
  //! Copy an IFD makernote if it is an image tag
229
  void visitIfdMakernote(TiffIfdMakernote* object) override;
230
  //! Copy a binary array if it is an image tag
231
  void visitBinaryArray(TiffBinaryArray* object) override;
232
  //! Copy an element of a binary array if it is an image tag
233
  void visitBinaryElement(TiffBinaryElement* object) override;
234
235
  //! Check if \em object is an image tag and if so, copy it to the target tree.
236
  void copyObject(const TiffComponent* object);
237
  //@}
238
239
 private:
240
  TiffComponent* pRoot_;
241
  uint32_t root_;
242
  const TiffHeaderBase* pHeader_;
243
  PrimaryGroups pPrimaryGroups_;
244
};  // class TiffCopier
245
246
/*!
247
  @brief TIFF composite visitor to decode metadata from the TIFF tree and
248
         add it to an Image, which is supplied in the constructor (Visitor
249
         pattern). Used by TiffParser to decode the metadata from a
250
         TIFF composite.
251
 */
252
class TiffDecoder : public TiffVisitor {
253
 public:
254
  //! @name Creators
255
  //@{
256
  /*!
257
    @brief Constructor, taking metadata containers to add the metadata to,
258
           the root element of the composite to decode and a FindDecoderFct
259
           function to get the decoder function for each tag.
260
   */
261
  TiffDecoder(ExifData& exifData, IptcData& iptcData, XmpData& xmpData, TiffComponent* pRoot,
262
              FindDecoderFct findDecoderFct);
263
  //@}
264
265
  //! @name Manipulators
266
  //@{
267
  //! Decode a TIFF entry
268
  void visitEntry(TiffEntry* object) override;
269
  //! Decode a TIFF data entry
270
  void visitDataEntry(TiffDataEntry* object) override;
271
  //! Decode a TIFF image entry
272
  void visitImageEntry(TiffImageEntry* object) override;
273
  //! Decode a TIFF size entry
274
  void visitSizeEntry(TiffSizeEntry* object) override;
275
  //! Decode a TIFF directory
276
  void visitDirectory(TiffDirectory* object) override;
277
  //! Decode a TIFF sub-IFD
278
  void visitSubIfd(TiffSubIfd* object) override;
279
  //! Decode a TIFF makernote
280
  void visitMnEntry(TiffMnEntry* object) override;
281
  //! Decode an IFD makernote
282
  void visitIfdMakernote(TiffIfdMakernote* object) override;
283
  //! Decode a binary array
284
  void visitBinaryArray(TiffBinaryArray* object) override;
285
  //! Decode an element of a binary array
286
  void visitBinaryElement(TiffBinaryElement* object) override;
287
288
  //! Entry function, determines how to decode each tag
289
  void decodeTiffEntry(const TiffEntryBase* object);
290
  //! Decode a standard TIFF entry
291
  void decodeStdTiffEntry(const TiffEntryBase* object);
292
  //! Decode IPTC data from an IPTCNAA tag or Photoshop ImageResources
293
  void decodeIptc(const TiffEntryBase* object);
294
  //! Decode XMP packet from an XMLPacket tag
295
  void decodeXmp(const TiffEntryBase* object);
296
  //! Decode Exif.Canon.AFInfo
297
  void decodeCanonAFInfo(const TiffEntryBase* object);
298
  //@}
299
300
 private:
301
  //! @name Manipulators
302
  //@{
303
  /*!
304
    @brief Get the data for a \em tag and \em group, either from the
305
           \em object provided, if it matches or from the matching element
306
           in the hierarchy.
307
308
    Populates \em pData and \em size with the result. If no matching
309
    element is found the function leaves both of these parameters unchanged.
310
  */
311
  void getObjData(const byte*& pData, size_t& size, uint16_t tag, IfdId group, const TiffEntryBase* object);
312
  //@}
313
314
  // DATA
315
  ExifData& exifData_;             //!< Exif metadata container
316
  IptcData& iptcData_;             //!< IPTC metadata container
317
  XmpData& xmpData_;               //!< XMP metadata container
318
  TiffComponent* pRoot_;           //!< Root element of the composite
319
  FindDecoderFct findDecoderFct_;  //!< Ptr to the function to find special decoding functions
320
  std::string make_;               //!< Camera make, determined from the tags to decode
321
  bool decodedIptc_{false};        //!< Indicates if IPTC has been decoded yet
322
323
};  // class TiffDecoder
324
325
/*!
326
  @brief TIFF composite visitor to encode metadata from an image to the TIFF
327
         tree. The metadata containers and root element of the tree are
328
         supplied in the constructor. Used by TiffParserWorker to encode the
329
         metadata into a TIFF composite.
330
331
         For non-intrusive writing, the encoder is used as a visitor (by
332
         passing it to the accept() member of a TiffComponent). The
333
         composite tree is then traversed and metadata from the image is
334
         used to encode each existing component.
335
336
         For intrusive writing, add() is called, which loops through the
337
         metadata and creates and populates corresponding TiffComponents
338
         as needed.
339
 */
340
class TiffEncoder : public TiffVisitor {
341
 public:
342
  //! @name Creators
343
  //@{
344
  /*!
345
    @brief Constructor, taking the root element of the composite to encode
346
           to, the image with the metadata to encode and a function to
347
           find special encoders.
348
   */
349
  TiffEncoder(ExifData exifData, const IptcData& iptcData, const XmpData& xmpData, TiffComponent* pRoot,
350
              bool isNewImage, PrimaryGroups pPrimaryGroups, const TiffHeaderBase* pHeader,
351
              FindEncoderFct findEncoderFct);
352
  TiffEncoder(const TiffEncoder&) = delete;
353
  TiffEncoder& operator=(const TiffEncoder&) = delete;
354
  //! Virtual destructor
355
2.73k
  ~TiffEncoder() override = default;
356
  //@}
357
358
  //! @name Manipulators
359
  //@{
360
  //! Encode a TIFF entry
361
  void visitEntry(TiffEntry* object) override;
362
  //! Encode a TIFF data entry
363
  void visitDataEntry(TiffDataEntry* object) override;
364
  //! Encode a TIFF image entry
365
  void visitImageEntry(TiffImageEntry* object) override;
366
  //! Encode a TIFF size entry
367
  void visitSizeEntry(TiffSizeEntry* object) override;
368
  //! Encode a TIFF directory
369
  void visitDirectory(TiffDirectory* object) override;
370
  //! Update directory entries
371
  void visitDirectoryNext(TiffDirectory* object) override;
372
  //! Encode a TIFF sub-IFD
373
  void visitSubIfd(TiffSubIfd* object) override;
374
  //! Encode a TIFF makernote
375
  void visitMnEntry(TiffMnEntry* object) override;
376
  //! Encode an IFD makernote
377
  void visitIfdMakernote(TiffIfdMakernote* object) override;
378
  //! Reset encoder to its original state, undo makernote specific settings
379
  void visitIfdMakernoteEnd(TiffIfdMakernote* object) override;
380
  //! Encode a binary array
381
  void visitBinaryArray(TiffBinaryArray* object) override;
382
  //! Re-encrypt binary array if necessary
383
  void visitBinaryArrayEnd(TiffBinaryArray* object) override;
384
  //! Encode an element of a binary array
385
  void visitBinaryElement(TiffBinaryElement* object) override;
386
387
  /*!
388
    @brief Top level encoder function. Determines how to encode each TIFF
389
           component. This function is called by the visit methods of the
390
           encoder as well as the add() method.
391
392
    If no \em datum is provided, search the metadata based on tag and
393
    group of the \em object. This is the case if the function is called
394
    from a visit method.
395
396
    Then check if a special encoder function is registered for the tag,
397
    and if so use it to encode the \em object. Else use the callback
398
    encoder function at the object (which results in a double-dispatch to
399
    the appropriate encoding function of the encoder.
400
401
    @param object Object in the TIFF component tree to encode.
402
    @param datum  The corresponding metadatum with the updated value.
403
404
    @note Encoder functions may use metadata other than \em datum.
405
   */
406
  void encodeTiffComponent(TiffEntryBase* object, const Exifdatum* datum = nullptr);
407
408
  //! Callback encoder function for an element of a binary array.
409
  void encodeBinaryElement(TiffBinaryElement* object, const Exifdatum* datum);
410
  //! Callback encoder function for a binary array.
411
  void encodeBinaryArray(TiffBinaryArray* object, const Exifdatum* datum);
412
  //! Callback encoder function for a data entry.
413
  void encodeDataEntry(TiffDataEntry* object, const Exifdatum* datum);
414
  //! Callback encoder function for a standard TIFF entry
415
  void encodeTiffEntry(TiffEntry* object, const Exifdatum* datum);
416
  //! Callback encoder function for an image entry.
417
  void encodeImageEntry(TiffImageEntry* object, const Exifdatum* datum);
418
  //! Callback encoder function for a %Makernote entry.
419
  void encodeMnEntry(TiffMnEntry* object, const Exifdatum* datum);
420
  //! Callback encoder function for a size entry.
421
  void encodeSizeEntry(TiffSizeEntry* object, const Exifdatum* datum);
422
  //! Callback encoder function for a sub-IFD entry.
423
  void encodeSubIfd(TiffSubIfd* object, const Exifdatum* datum);
424
425
  //! Special encoder function for the base part of a TIFF entry.
426
  void encodeTiffEntryBase(TiffEntryBase* object, const Exifdatum* datum);
427
  //! Special encoder function for an offset entry.
428
  void encodeOffsetEntry(TiffEntryBase* object, const Exifdatum* datum);
429
430
  //! Special encoder function to encode SubIFD contents to Image group if it contains primary image data
431
  // Todo void encodeNikonSubIfd(TiffEntryBase* object, const Exifdatum* datum);
432
433
  //! Special encoder function to encode IPTC data to an IPTCNAA or Photoshop ImageResources tag.
434
  void encodeIptc(TiffEntryBase* object, const Exifdatum* datum);
435
  /*!
436
    @brief Add metadata from image to the TIFF composite.
437
438
    For each Exif metadatum, the corresponding TiffComponent is created
439
    if necessary and populated using encodeTiffComponent(). The add() function
440
    is used during intrusive writing, to create a new TIFF structure.
441
442
    @note For non-intrusive writing, the encoder is used as a visitor (by
443
    passing it to the accept() member of a TiffComponent). The composite
444
    tree is then traversed and metadata from the image is used to encode
445
    each existing component.
446
  */
447
  void add(TiffComponent* pRootDir, TiffComponent::UniquePtr pSourceDir, uint32_t root);
448
  //! Set the dirty flag and end of traversing signal.
449
  void setDirty(bool flag = true);
450
  //@}
451
452
  //! @name Accessors
453
  //@{
454
  /*!
455
    @brief Return the applicable byte order. May be different for
456
           the Makernote and the rest of the TIFF entries.
457
   */
458
173k
  [[nodiscard]] ByteOrder byteOrder() const {
459
173k
    return byteOrder_;
460
173k
  }
461
  /*!
462
    @brief True if any tag was deleted or allocated in the process of
463
           visiting a TIFF composite tree.
464
   */
465
  [[nodiscard]] bool dirty() const;
466
  //! Return the write method used.
467
981
  [[nodiscard]] WriteMethod writeMethod() const {
468
981
    return writeMethod_;
469
981
  }
470
  //@}
471
472
 private:
473
  //! @name Manipulators
474
  //@{
475
  /*!
476
    Encode IPTC data. Updates or adds tag Exif.Image.IPTCNAA, updates but
477
    never adds tag Exif.Image.ImageResources.
478
    This method is called from the constructor.
479
   */
480
  void encodeIptc();
481
  /*!
482
    Encode XMP data. Adds tag Exif.Image.XMLPacket with the XMP packet.
483
    This method is called from the constructor.
484
   */
485
  void encodeXmp();
486
  //@}
487
488
  //! @name Accessors
489
  //@{
490
  /*!
491
    @brief Update a directory entry. This is called after all directory
492
           entries are encoded. It takes care of type and count changes
493
           and size shrinkage for non-intrusive writing.
494
   */
495
  static uint32_t updateDirEntry(byte* buf, ByteOrder byteOrder, const TiffComponent::SharedPtr& tiffComponent);
496
  /*!
497
    @brief Check if the tag is an image tag of an existing image. Such
498
           tags are copied from the original image and can't be modified.
499
500
           The condition is true if there is an existing image (as
501
           opposed to a newly created TIFF image) and \em tag, \em group
502
           is considered an image tag of this image - whether or not
503
           it's actually present in the existing image doesn't matter.
504
   */
505
  [[nodiscard]] bool isImageTag(uint16_t tag, IfdId group) const;
506
  //@}
507
508
  // DATA
509
  ExifData exifData_;                        //!< Copy of the Exif data to encode
510
  const IptcData& iptcData_;                 //!< IPTC data to encode, just a reference
511
  const XmpData& xmpData_;                   //!< XMP data to encode, just a reference
512
  bool del_{true};                           //!< Indicates if Exif data entries should be deleted after encoding
513
  const TiffHeaderBase* pHeader_;            //!< TIFF image header
514
  TiffComponent* pRoot_;                     //!< Root element of the composite
515
  bool isNewImage_;                          //!< True if the TIFF image is created from scratch
516
  PrimaryGroups pPrimaryGroups_;             //!< List of primary image groups
517
  TiffComponent::UniquePtr pSourceTree_;     //!< Parsed source tree for reference
518
  ByteOrder byteOrder_;                      //!< Byteorder for encoding
519
  ByteOrder origByteOrder_;                  //!< Byteorder as set in the c'tor
520
  FindEncoderFct findEncoderFct_;            //!< Ptr to the function to find special encoding functions
521
  std::string make_;                         //!< Camera make, determined from the tags to encode
522
  bool dirty_{false};                        //!< Signals if any tag is deleted or allocated
523
  WriteMethod writeMethod_{wmNonIntrusive};  //!< Write method used.
524
525
};  // class TiffEncoder
526
527
/*!
528
  @brief Simple state class containing relevant state information for
529
         the TIFF reader. This is in a separate class so that the
530
         reader can change state if needed (e.g., to read certain complex
531
         makernotes).
532
 */
533
class TiffRwState {
534
 public:
535
  //! @name Creators
536
  //@{
537
  //! Constructor.
538
9.43k
  constexpr TiffRwState(ByteOrder byteOrder, size_t baseOffset) : byteOrder_(byteOrder), baseOffset_(baseOffset) {
539
9.43k
  }
540
  //@}
541
542
  //! @name Accessors
543
  //@{
544
  /*!
545
    @brief Return the applicable byte order. May be different for
546
           the Makernote and the rest of the TIFF entries.
547
   */
548
3.01M
  [[nodiscard]] ByteOrder byteOrder() const {
549
3.01M
    return byteOrder_;
550
3.01M
  }
551
  /*!
552
    @brief Return the base offset.
553
554
    TIFF standard format uses byte offsets which are always relative to
555
    the start of the TIFF file, i.e., relative to the start of the TIFF
556
    image header. In this case, the base offset is 0.  However, some
557
    camera vendors encode their makernotes in TIFF IFDs using offsets
558
    relative to (somewhere near) the start of the makernote data. In this
559
    case, base offset added to the start of the TIFF image header points
560
    to the basis for such makernote offsets.
561
   */
562
506k
  [[nodiscard]] size_t baseOffset() const {
563
506k
    return baseOffset_;
564
506k
  }
565
  //@}
566
567
 private:
568
  ByteOrder byteOrder_;
569
  size_t baseOffset_;
570
};  // TiffRwState
571
572
/*!
573
  @brief TIFF composite visitor to read the TIFF structure from a block of
574
         memory and build the composite from it (Visitor pattern). Used by
575
         TiffParser to read the TIFF data from a block of memory.
576
 */
577
class TiffReader : public TiffVisitor {
578
 public:
579
  //! @name Creators
580
  //@{
581
  /*!
582
    @brief Constructor. The data buffer and table describing the TIFF
583
                     structure of the data are set in the constructor.
584
    @param pData     Pointer to the data buffer, starting with a TIFF header.
585
    @param size      Number of bytes in the data buffer.
586
    @param pRoot     Root element of the TIFF composite.
587
    @param state     State object for creation function, byte order and
588
                     base offset.
589
   */
590
  TiffReader(const byte* pData, size_t size, TiffComponent* pRoot, TiffRwState state);
591
  //@}
592
593
  //! @name Manipulators
594
  //@{
595
  //! Read a TIFF entry from the data buffer
596
  void visitEntry(TiffEntry* object) override;
597
  //! Read a TIFF data entry from the data buffer
598
  void visitDataEntry(TiffDataEntry* object) override;
599
  //! Read a TIFF image entry from the data buffer
600
  void visitImageEntry(TiffImageEntry* object) override;
601
  //! Read a TIFF size entry from the data buffer
602
  void visitSizeEntry(TiffSizeEntry* object) override;
603
  //! Read a TIFF directory from the data buffer
604
  void visitDirectory(TiffDirectory* object) override;
605
  //! Read a TIFF sub-IFD from the data buffer
606
  void visitSubIfd(TiffSubIfd* object) override;
607
  //! Read a TIFF makernote entry from the data buffer
608
  void visitMnEntry(TiffMnEntry* object) override;
609
  //! Read an IFD makernote from the data buffer
610
  void visitIfdMakernote(TiffIfdMakernote* object) override;
611
  //! Reset reader to its original state, undo makernote specific settings
612
  void visitIfdMakernoteEnd(TiffIfdMakernote* object) override;
613
  //! Read a binary array from the data buffer
614
  void visitBinaryArray(TiffBinaryArray* object) override;
615
  //! Read an element of a binary array from the data buffer
616
  void visitBinaryElement(TiffBinaryElement* object) override;
617
618
  //! Read a standard TIFF entry from the data buffer
619
  void readTiffEntry(TiffEntryBase* object);
620
  //! Read a TiffDataEntryBase from the data buffer
621
  void readDataEntryBase(TiffDataEntryBase* object);
622
  /*!
623
    @brief Set the \em state of the reader to one suitable for the Makernote.
624
625
    Uses the \em state passed in, if any, and remembers it for use during
626
    subsequent calls without any argument.
627
   */
628
  void setMnState(const TiffRwState* state = nullptr);
629
  //! Set the state to the original state as set in the constructor.
630
  void setOrigState();
631
  //! Check IFD directory pointer \em start for circular reference
632
  bool circularReference(const byte* start, IfdId group);
633
  //! Return the next idx sequence number for \em group
634
  int nextIdx(IfdId group);
635
636
  /*!
637
    @brief Read deferred components.
638
639
    This function is called after the TIFF composite is read by passing a
640
    TiffReader to the accept() function of the root component. It reads
641
    all components for which reading was deferred during that pass.  This
642
    is usually done to make sure that all other components are accessible
643
    at the time the deferred components are processed.
644
   */
645
  void postProcess();
646
  //@}
647
648
  //! @name Accessors
649
  //@{
650
  //! Return the byte order.
651
  [[nodiscard]] ByteOrder byteOrder() const;
652
  //! Return the base offset. See class TiffRwState for details
653
  [[nodiscard]] size_t baseOffset() const;
654
  //@}
655
656
 private:
657
  using DirList = std::map<const byte*, IfdId>;
658
  using IdxSeq = std::map<IfdId, int>;
659
  using PostList = std::vector<TiffComponent*>;
660
661
  // DATA
662
  const byte* pData_;      //!< Pointer to the memory buffer
663
  size_t size_;            //!< Size of the buffer
664
  const byte* pLast_;      //!< Pointer to the last byte
665
  TiffComponent* pRoot_;   //!< Root element of the composite
666
  TiffRwState* pState_;    //!< Pointer to the state in effect (origState_ or mnState_)
667
  TiffRwState origState_;  //!< State class as set in the c'tor
668
  TiffRwState mnState_;    //!< State class as set in the c'tor or by setMnState()
669
  DirList dirList_;        //!< List of IFD pointers and their groups
670
  IdxSeq idxSeq_;          //!< Sequences for group, used for the entry's idx
671
  PostList postList_;      //!< List of components with deferred reading
672
  bool postProc_{false};   //!< True in postProcessList()
673
};
674
675
}  // namespace Internal
676
}  // namespace Exiv2
677
678
#endif  // #ifndef TIFFVISITOR_INT_HPP_