~noskcaj/ubuntu/trusty/libextractor/merge

« back to all changes in this revision

Viewing changes to src/plugins/exiv2/ifd.hpp

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Baumann
  • Date: 2009-11-17 20:27:32 UTC
  • mfrom: (1.10.4 upstream) (5.2.5 sid)
  • Revision ID: james.westby@ubuntu.com-20091117202732-ipm2h3gks5bdw2vx
Tags: 0.5.23+dfsg-3
* Building against libltdl7.
* Updating to standards version 3.8.3.
* Adding maintainer homepage field to control.
* Marking maintainer homepage field to be also included in binary
  packages and changelog.
* Adding README.source.
* Simplifying autotools handling in rules.
* Updating README.source.
* Moving maintainer homepage field from control to copyright.
* Dropping la files.
* Simplyfing debhelper install files.
* Bumping versioned build-depends on debhelper.
* Adding depends to dpkg install info.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// ***************************************************************** -*- C++ -*-
2
 
/*
3
 
 * Copyright (C) 2004, 2005 Andreas Huggel <ahuggel@gmx.net>
4
 
 *
5
 
 * This program is part of the Exiv2 distribution.
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or
8
 
 * modify it under the terms of the GNU General Public License
9
 
 * as published by the Free Software Foundation; either version 2
10
 
 * of the License, or (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
 
 */
21
 
/*!
22
 
  @file    ifd.hpp
23
 
  @brief   Encoding and decoding of IFD (%Image File Directory) data
24
 
  @version $Rev: 562 $
25
 
  @author  Andreas Huggel (ahu)
26
 
           <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
27
 
  @date    09-Jan-04, ahu: created<BR>
28
 
           11-Feb-04, ahu: isolated as a component
29
 
 */
30
 
#ifndef IFD_HPP_
31
 
#define IFD_HPP_
32
 
 
33
 
// *****************************************************************************
34
 
// included header files
35
 
#include "types.hpp"
36
 
 
37
 
// + standard includes
38
 
#include <string>
39
 
#include <vector>
40
 
#include <iosfwd>
41
 
 
42
 
// *****************************************************************************
43
 
// namespace extensions
44
 
namespace Exiv2 {
45
 
 
46
 
// *****************************************************************************
47
 
// class declarations
48
 
    class Ifd;
49
 
 
50
 
// *****************************************************************************
51
 
// class definitions
52
 
 
53
 
    /*!
54
 
      @brief Data structure for one IFD directory entry. See the description of
55
 
             class Ifd for an explanation of the supported modes for memory
56
 
             allocation.
57
 
    */
58
 
    class Entry {
59
 
    public:
60
 
        //! @name Creators
61
 
        //@{
62
 
        /*!
63
 
          @brief Default constructor. The entry allocates memory for its
64
 
          data if alloc is true (the default), otherwise it remembers
65
 
          just the pointers into a read and writeable data buffer which
66
 
          it doesn't allocate or delete.
67
 
         */
68
 
        explicit Entry(bool alloc =true);
69
 
        //! Destructor
70
 
        ~Entry();
71
 
        //! Copy constructor
72
 
        Entry(const Entry& rhs);
73
 
        //@}
74
 
 
75
 
        //! @name Manipulators
76
 
        //@{
77
 
        //! Assignment operator
78
 
        Entry& operator=(const Entry& rhs);
79
 
        //! Set the tag
80
 
        void setTag(uint16_t tag) { tag_ = tag; }
81
 
        //! Set the IFD id
82
 
        void setIfdId(IfdId ifdId) { ifdId_ = ifdId; }
83
 
        //! Set the index (unique id of an entry within one IFD)
84
 
        void setIdx(int idx) { idx_ = idx; }
85
 
        //! Set the offset. The offset is relative to the start of the IFD.
86
 
        void setOffset(long offset) { offset_ = offset; }
87
 
        /*!
88
 
          @brief Set the value of the entry to a single unsigned long component,
89
 
                 i.e., set the type of the entry to unsigned long, number of
90
 
                 components to one and the value according to the data provided.
91
 
 
92
 
          The size of the data buffer is set to at least four bytes, but is left
93
 
          unchanged if it can accomodate the pointer.  This method can be used
94
 
          to set the value of a tag which contains a pointer (offset) to a
95
 
          location in the Exif data (like e.g., ExifTag, 0x8769 in IFD0, which
96
 
          contains a pointer to the Exif IFD).
97
 
          <BR>This method cannot be used to set the value of a newly created
98
 
          %Entry in non-alloc mode.
99
 
 
100
 
          @note This method is now deprecated, use data area related methods
101
 
                instead.
102
 
         */
103
 
        void setValue(uint32_t data, ByteOrder byteOrder);
104
 
        /*!
105
 
          @brief Set type, count, the data buffer and its size.
106
 
 
107
 
          Copies the provided buffer when called in memory allocation mode.
108
 
          <BR>In non-alloc mode, use this method to initialise the data of a
109
 
          newly created %Entry.  In this case, only the pointer to the buffer is
110
 
          copied, i.e., the buffer must remain valid throughout the life of the
111
 
          %Entry.  Subsequent calls in non-alloc mode will overwrite the data
112
 
          pointed to by this pointer with the data provided, i.e., the buffer
113
 
          provided in subsequent calls can be deleted after the call.
114
 
          <BR>In either memory allocation mode, the data buffer provided must be
115
 
          large enough to hold count components of type. The size of the buffer
116
 
          will be as indicated in the size argument. I.e., it is possible to
117
 
          allocate (set) a data buffer larger than required to hold count
118
 
          components of the given type.
119
 
 
120
 
          @param type The type of the data.
121
 
          @param count Number of components in the buffer.
122
 
          @param data Pointer to the data buffer.
123
 
          @param size Size of the desired data buffer in bytes.
124
 
          @throw Error if no memory allocation is allowed
125
 
                 and the size of the data buffer is larger than the existing
126
 
                 data buffer of the entry or if size is not large enough to hold
127
 
                 count components of the given type.
128
 
         */
129
 
        void setValue(uint16_t type, uint32_t count, const byte* data, long size);
130
 
        /*!
131
 
          @brief Set the data area. Memory management as for
132
 
          setValue(uint16_t, uint32_t, const byte*, long)
133
 
 
134
 
          For certain tags the regular value of an IFD entry is an offset to a
135
 
          data area outside of the IFD. Examples are Exif tag 0x8769 in IFD0
136
 
          (Exif.Image.ExifTag) or tag 0x0201 in IFD1
137
 
          (Exif.Thumbnail.JPEGInterchangeFormat). The offset of ExifTag points
138
 
          to a data area containing the Exif IFD. That of JPEGInterchangeFormat
139
 
          contains the JPEG thumbnail image.
140
 
          This method sets the data area of a tag in accordance with the memory
141
 
          allocation mode.
142
 
 
143
 
          @param buf Pointer to the data area.
144
 
          @param len Size of the data area.
145
 
 
146
 
          @throw Error in non-alloc mode, if there already is a dataarea but the
147
 
                 size of the existing dataarea is not large enough for the
148
 
                 new buffer.
149
 
         */
150
 
        void setDataArea(const byte* buf, long len);
151
 
        /*!
152
 
          @brief Set the offset(s) to the data area of an entry.
153
 
 
154
 
          Add @em offset to each data component of the entry. This is used by
155
 
          Ifd::copy to convert the data components of an entry containing
156
 
          offsets relative to the data area to become offsets from the start of
157
 
          the TIFF header.  Usually, entries with a data area have exactly one
158
 
          unsigned long data component, which is 0.
159
 
 
160
 
          @param offset Offset
161
 
          @param byteOrder Byte order
162
 
 
163
 
          @throw Error if the offset is out of range for the data type of the
164
 
                 tag or the data type is not supported.
165
 
         */
166
 
        void setDataAreaOffsets(uint32_t offset, ByteOrder byteOrder);
167
 
        /*!
168
 
          @brief Update the base pointer of the Entry from \em pOldBase
169
 
                 to \em pNewBase.
170
 
 
171
 
          Allows to re-locate the underlying data buffer to a new location
172
 
          \em pNewBase. This method only has an effect in non-alloc mode.
173
 
 
174
 
          @param pOldBase Base pointer of the old data buffer
175
 
          @param pNewBase Base pointer of the new data buffer
176
 
         */
177
 
        void updateBase(byte* pOldBase, byte* pNewBase);
178
 
        //@}
179
 
 
180
 
        //! @name Accessors
181
 
        //@{
182
 
        //! Return the tag
183
 
        uint16_t tag() const { return tag_; }
184
 
        //! Return the type id.
185
 
        uint16_t type() const { return type_; }
186
 
        //! Return the name of the type
187
 
        const char* typeName() const
188
 
            { return TypeInfo::typeName(TypeId(type_)); }
189
 
        //! Return the size in bytes of one element of this type
190
 
        long typeSize() const
191
 
            { return TypeInfo::typeSize(TypeId(type_)); }
192
 
        //! Return the IFD id
193
 
        IfdId ifdId() const { return ifdId_; }
194
 
        //! Return the index (unique id >0 of an entry within an IFD, 0 if not set)
195
 
        int idx() const { return idx_; }
196
 
        //! Return the number of components in the value
197
 
        uint32_t count() const { return count_; }
198
 
        /*!
199
 
          @brief Return the size of the data buffer in bytes.
200
 
          @note  There is no minimum size for the data buffer, except that it
201
 
                 must be large enough to hold the data.
202
 
         */
203
 
        long size() const { return size_; }
204
 
        //! Return the offset from the start of the IFD to the data of the entry
205
 
        long offset() const { return offset_; }
206
 
        /*!
207
 
          @brief Return a pointer to the data buffer. Do not attempt to write
208
 
                 to this pointer.
209
 
         */
210
 
        const byte* data() const { return pData_; }
211
 
        /*!
212
 
          @brief Return a pointer to the n-th component, 0 if there is no
213
 
                 n-th component. Do not attempt to write to this pointer.
214
 
         */
215
 
        const byte* component(uint32_t n) const;
216
 
        //! Get the memory allocation mode
217
 
        bool alloc() const { return alloc_; }
218
 
        //! Return the size of the data area.
219
 
        long sizeDataArea() const { return sizeDataArea_; }
220
 
        /*!
221
 
          @brief Return a pointer to the data area. Do not attempt to write to
222
 
                 this pointer.
223
 
 
224
 
          For certain tags the regular value of an IFD entry is an offset to a
225
 
          data area outside of the IFD. Examples are Exif tag 0x8769 in IFD0
226
 
          (Exif.Image.ExifTag) or tag 0x0201 in IFD1
227
 
          (Exif.Thumbnail.JPEGInterchangeFormat). The offset of ExifTag points
228
 
          to a data area containing the Exif IFD. That of JPEGInterchangeFormat
229
 
          contains the JPEG thumbnail image.
230
 
          Use this method to access (read-only) the data area of a tag. Use
231
 
          setDataArea() to write to the data area.
232
 
 
233
 
          @return Return a pointer to the data area.
234
 
         */
235
 
        const byte* dataArea() const { return pDataArea_; }
236
 
        //@}
237
 
 
238
 
    private:
239
 
        // DATA
240
 
        /*!
241
 
          True:  Requires memory allocation and deallocation,<BR>
242
 
          False: No memory management needed.
243
 
         */
244
 
        bool alloc_;
245
 
        //! Redundant IFD id (it is also at the IFD)
246
 
        IfdId ifdId_;
247
 
        //! Unique id of an entry within an IFD (0 if not set)
248
 
        int idx_;
249
 
        //! Tag
250
 
        uint16_t tag_;
251
 
        //! Type
252
 
        uint16_t type_;
253
 
        //! Number of components
254
 
        uint32_t count_;
255
 
        //! Offset from the start of the IFD to the data
256
 
        long offset_;
257
 
        /*!
258
 
          Size of the data buffer holding the value in bytes, there is
259
 
          no minimum size.
260
 
         */
261
 
        long size_;
262
 
        //! Pointer to the data buffer
263
 
        byte* pData_;
264
 
        //! Size of the data area
265
 
        long sizeDataArea_;
266
 
        //! Pointer to the data area
267
 
        byte* pDataArea_;
268
 
 
269
 
    }; // class Entry
270
 
 
271
 
    //! Container type to hold all IFD directory entries
272
 
    typedef std::vector<Entry> Entries;
273
 
 
274
 
    //! Unary predicate that matches an Entry with a given index
275
 
    class FindEntryByIdx {
276
 
    public:
277
 
        //! Constructor, initializes the object with the index to look for
278
 
        FindEntryByIdx(int idx) : idx_(idx) {}
279
 
        /*!
280
 
          @brief Returns true if the idx of the argument entry is equal
281
 
                 to that of the object.
282
 
        */
283
 
        bool operator()(const Entry& entry) const
284
 
            { return idx_ == entry.idx(); }
285
 
 
286
 
    private:
287
 
        int idx_;
288
 
 
289
 
    }; // class FindEntryByIdx
290
 
 
291
 
    //! Unary predicate that matches an Entry with a given tag
292
 
    class FindEntryByTag {
293
 
    public:
294
 
        //! Constructor, initializes the object with the tag to look for
295
 
        FindEntryByTag(uint16_t tag) : tag_(tag) {}
296
 
        /*!
297
 
          @brief Returns true if the tag of the argument entry is equal
298
 
                 to that of the object.
299
 
        */
300
 
        bool operator()(const Entry& entry) const
301
 
            { return tag_ == entry.tag(); }
302
 
 
303
 
    private:
304
 
        uint16_t tag_;
305
 
 
306
 
    }; // class FindEntryByTag
307
 
 
308
 
    /*!
309
 
      @brief Models an IFD (%Image File Directory)
310
 
 
311
 
      This class models an IFD as described in the TIFF 6.0 specification.
312
 
 
313
 
      An instance of class %Ifd can operate in two modes, one that allocates and
314
 
      deallocates the memory required to store data, and one that doesn't
315
 
      perform such memory management.
316
 
      <BR>An external data buffer (not managed by %Ifd) is needed for an instance
317
 
      of %Ifd which operates in no memory management mode. The %Ifd will
318
 
      maintain only pointers into this buffer.
319
 
      <BR> The mode without memory management is used to make "non-intrusive
320
 
      write support" possible. This allows writing to Exif data of an image
321
 
      without changing the data layout of the Exif data, to maximize chances
322
 
      that tag data, which the Exif reader may not understand (e.g., the
323
 
      Makernote) remains valid. A "non-intrusive write operation" is the
324
 
      modification of tag data without increasing the data size.
325
 
 
326
 
      @note Use the mode with memory management (the default) if you are unsure
327
 
            or if these memory management considerations are of no concern to you.
328
 
 
329
 
      @note The two different modes imply completely different copy and
330
 
            assignment behaviours, with the first resulting in entirely separate
331
 
            classes and the second mode resulting in multiple classes using one
332
 
            and the same data buffer.
333
 
     */
334
 
    class Ifd {
335
 
        //! @name Not implemented
336
 
        //@{
337
 
        //! Assignment not allowed (memory management mode alloc_ is const)
338
 
        Ifd& operator=(const Ifd& rhs);
339
 
        //@}
340
 
 
341
 
    public:
342
 
        //! %Entries const iterator type
343
 
        typedef Entries::const_iterator const_iterator;
344
 
        //! %Entries iterator type
345
 
        typedef Entries::iterator iterator;
346
 
 
347
 
        //! @name Creators
348
 
        //@{
349
 
        /*!
350
 
          @brief Constructor. Allows to set the IFD identifier. Memory management
351
 
                 is enabled, offset is set to 0. Serves as default constructor.
352
 
         */
353
 
        explicit Ifd(IfdId ifdId =ifdIdNotSet);
354
 
        /*!
355
 
          @brief Constructor. Allows to set the IFD identifier and the offset of
356
 
                 the IFD from the start of TIFF header. Memory management is
357
 
                 enabled.
358
 
         */
359
 
        Ifd(IfdId ifdId, long offset);
360
 
        /*!
361
 
          @brief Constructor. Allows to set the IFD identifier, offset of the
362
 
                 IFD from the start of TIFF header, choose whether or not
363
 
                 memory management is required for the Entries, and decide
364
 
                 whether this IFD has a next pointer.
365
 
         */
366
 
        Ifd(IfdId ifdId, long offset, bool alloc, bool hasNext =true);
367
 
        //! Copy constructor
368
 
        Ifd(const Ifd& rhs);
369
 
        //! Destructor
370
 
        ~Ifd();
371
 
        //@}
372
 
 
373
 
        //! @name Manipulators
374
 
        //@{
375
 
        /*!
376
 
          @brief Read a complete IFD and its data from a data buffer
377
 
 
378
 
          @param buf Pointer to the data to decode. The buffer must start with the
379
 
                 IFD data (unlike the readSubIfd() method).
380
 
          @param len Number of bytes in the data buffer
381
 
          @param byteOrder Applicable byte order (little or big endian).
382
 
          @param offset (Optional) offset of the IFD from the start of the TIFF
383
 
                 header, if known. If not given, the offset will be guessed
384
 
                 using the assumption that the smallest offset of all IFD
385
 
                 directory entries points to a data buffer immediately follwing
386
 
                 the IFD.
387
 
 
388
 
          @return 0 if successful;<BR>
389
 
                  6 if the data buffer is too small, e.g., if an offset points
390
 
                    beyond the provided buffer. The IFD is cleared in this
391
 
                    case.
392
 
         */
393
 
        int read(const byte* buf, long len, ByteOrder byteOrder, long offset =0);
394
 
        /*!
395
 
          @brief Copy the IFD to a data array, update the offsets of the IFD and
396
 
                 all its entries, return the number of bytes written.
397
 
 
398
 
                 First the number of IFD entries is written (2 bytes), followed
399
 
                 by all directory entries: tag (2), type (2), number of data
400
 
                 components (4) and offset to the data or the data, if it
401
 
                 occupies not more than four bytes (4). The directory entries
402
 
                 are followed by the offset of the next IFD (4). All these
403
 
                 fields are encoded according to the byte order argument. Data
404
 
                 that doesn't fit into the offset fields follows immediately
405
 
                 after the IFD entries. The offsets in the IFD are set to
406
 
                 correctly point to the data fields, using the offset parameter
407
 
                 or the offset of the IFD.
408
 
 
409
 
          @param buf Pointer to the data buffer. The user must ensure that the
410
 
                 buffer has enough memory. Otherwise the call results in
411
 
                 undefined behaviour.
412
 
          @param byteOrder Applicable byte order (little or big endian).
413
 
          @param offset Target offset from the start of the TIFF header of the
414
 
                 data array. The IFD offsets will be adjusted as necessary. If
415
 
                 not given, then it is assumed that the IFD will remain at its
416
 
                 original position, i.e., the offset of the IFD will be used.
417
 
          @return Returns the number of characters written.
418
 
         */
419
 
        long copy(byte* buf, ByteOrder byteOrder, long offset =0);
420
 
        /*!
421
 
          @brief Reset the IFD. Delete all IFD entries from the class and put
422
 
                 the object in a state where it can accept completely new
423
 
                 entries.
424
 
         */
425
 
        void clear();
426
 
        /*!
427
 
          @brief Set the offset of the next IFD. Byte order is needed to update
428
 
                 the underlying data buffer in non-alloc mode. This method only
429
 
                 has an effect if the IFD was instantiated with hasNext = true.
430
 
         */
431
 
        void setNext(uint32_t next, ByteOrder byteOrder);
432
 
        /*!
433
 
          @brief Add the entry to the IFD. No duplicate-check is performed,
434
 
                 i.e., it is possible to add multiple entries with the same tag.
435
 
                 The memory allocation mode of the entry to be added must match
436
 
                 that of the IFD and the IFD ids of the IFD and entry must
437
 
                 match.
438
 
         */
439
 
        void add(const Entry& entry);
440
 
        /*!
441
 
          @brief Delete the directory entry with the given tag. Return the index
442
 
                 of the deleted entry or 0 if no entry with tag was found.
443
 
         */
444
 
        int erase(uint16_t tag);
445
 
        /*!
446
 
          @brief Delete the directory entry at iterator position pos, return the
447
 
                 position of the next entry. Note that iterators into the
448
 
                 directory, including pos, are potentially invalidated by this
449
 
                 call.
450
 
         */
451
 
        iterator erase(iterator pos);
452
 
        //! Sort the IFD entries by tag
453
 
        void sortByTag();
454
 
        //! The first entry
455
 
        iterator begin() { return entries_.begin(); }
456
 
        //! End of the entries
457
 
        iterator end() { return entries_.end(); }
458
 
        //! Find an IFD entry by idx, return an iterator into the entries list
459
 
        iterator findIdx(int idx);
460
 
        //! Find an IFD entry by tag, return an iterator into the entries list
461
 
        iterator findTag(uint16_t tag);
462
 
        /*!
463
 
          @brief Update the base pointer of the Ifd and all entries to \em pNewBase.
464
 
 
465
 
          Allows to re-locate the underlying data buffer to a new location
466
 
          \em pNewBase. This method only has an effect in non-alloc mode.
467
 
 
468
 
          @param pNewBase Pointer to the new data buffer
469
 
 
470
 
          @return Old base pointer or 0 if called in alloc mode
471
 
         */
472
 
        byte* updateBase(byte* pNewBase);
473
 
        //@}
474
 
 
475
 
        //! @name Accessors
476
 
        //@{
477
 
        /*!
478
 
          @brief Read a sub-IFD from the location pointed to by the directory entry
479
 
                 with the given tag.
480
 
 
481
 
          @param dest References the destination IFD.
482
 
          @param buf The data buffer to read from. The buffer must contain all Exif
483
 
                     data starting from the TIFF header (unlike the read() method).
484
 
          @param len Number of bytes in the data buffer
485
 
          @param byteOrder Applicable byte order (little or big endian).
486
 
          @param tag Tag to look for.
487
 
 
488
 
          @return 0 if successful;<BR>
489
 
                  6 if reading the sub-IFD failed (see read() above) or
490
 
                    the location pointed to by the directory entry with the
491
 
                    given tag is outside of the data buffer.
492
 
 
493
 
          @note It is not considered an error if the tag cannot be found in the
494
 
                IFD. 0 is returned and no action is taken in this case.
495
 
        */
496
 
        int readSubIfd(
497
 
            Ifd& dest, const byte* buf, long len, ByteOrder byteOrder, uint16_t tag
498
 
        ) const;
499
 
        //! Get the memory allocation mode, see the Ifd class description for details
500
 
        bool alloc() const { return alloc_; }
501
 
        //! The first entry
502
 
        const_iterator begin() const { return entries_.begin(); }
503
 
        //! End of the entries
504
 
        const_iterator end() const { return entries_.end(); }
505
 
        //! Find an IFD entry by idx, return a const iterator into the entries list
506
 
        const_iterator findIdx(int idx) const;
507
 
        //! Find an IFD entry by tag, return a const iterator into the entries list
508
 
        const_iterator findTag(uint16_t tag) const;
509
 
        //! Get the IfdId of the IFD
510
 
        IfdId ifdId() const { return ifdId_; }
511
 
        //! Get the offset of the IFD from the start of the TIFF header
512
 
        long offset() const { return offset_; }
513
 
        /*!
514
 
          @brief Get the offset of the first data entry outside of the IFD from
515
 
                 the start of the TIFF header, return 0 if there is none. The
516
 
                 data offset is determined when the IFD is read.
517
 
         */
518
 
        long dataOffset() const { return dataOffset_; }
519
 
        //! Get the offset to the next IFD from the start of the TIFF header
520
 
        uint32_t next() const { return next_; }
521
 
        //! Get the number of directory entries in the IFD
522
 
        long count() const { return static_cast<long>(entries_.size()); }
523
 
        //! Get the size of this IFD in bytes (IFD only, without data)
524
 
        long size() const;
525
 
        /*!
526
 
          @brief Return the total size of the data of this IFD in bytes; sums
527
 
                 the size of all directory entries where size is greater than
528
 
                 four plus the size of all data areas, i.e., all data that
529
 
                 requires memory outside the IFD directory entries is counted.
530
 
         */
531
 
        long dataSize() const;
532
 
        /*!
533
 
          @brief Print the IFD in human readable format to the given stream;
534
 
                 begin each line with prefix.
535
 
         */
536
 
        void print(std::ostream& os, const std::string& prefix ="") const;
537
 
        //@}
538
 
 
539
 
    private:
540
 
        //! Helper structure to build IFD entries
541
 
        struct PreEntry {
542
 
            uint16_t tag_;
543
 
            uint16_t type_;
544
 
            uint32_t count_;
545
 
            long size_;
546
 
            long offsetLoc_;
547
 
            long offset_;
548
 
        };
549
 
 
550
 
        //! cmpPreEntriesByOffset needs to know about PreEntry, that's all.
551
 
        friend bool cmpPreEntriesByOffset(const PreEntry&, const PreEntry&);
552
 
 
553
 
        //! Container for 'pre-entries'
554
 
        typedef std::vector<PreEntry> PreEntries;
555
 
 
556
 
        // DATA
557
 
        /*!
558
 
          True:  requires memory allocation and deallocation,
559
 
          False: no memory management needed.
560
 
        */
561
 
        const bool alloc_;
562
 
        //! IFD entries
563
 
        Entries entries_;
564
 
        //! IFD Id
565
 
        IfdId ifdId_;
566
 
        //! Pointer to IFD from the start of the TIFF header
567
 
        byte* pBase_;
568
 
        //! Offset of the IFD from the start of the TIFF header
569
 
        long offset_;
570
 
        //! Offset of the first data entry outside of the IFD directory
571
 
        long dataOffset_;
572
 
        //! Indicates whether the IFD has a next pointer
573
 
        bool hasNext_;
574
 
        //! Pointer to the offset of next IFD from the start of the TIFF header
575
 
        byte* pNext_;
576
 
        //! The offset of the next IFD as data value (always in sync with *pNext_)
577
 
        uint32_t next_;
578
 
 
579
 
    }; // class Ifd
580
 
 
581
 
// *****************************************************************************
582
 
// free functions
583
 
 
584
 
    /*!
585
 
      @brief Compare two IFD entries by tag. Return true if the tag of entry
586
 
             lhs is less than that of rhs.
587
 
     */
588
 
    bool cmpEntriesByTag(const Entry& lhs, const Entry& rhs);
589
 
 
590
 
    /*!
591
 
      @brief Compare two 'pre-IFD entries' by offset, taking care of special
592
 
             cases where one or both of the entries don't have an offset.
593
 
             Return true if the offset of entry lhs is less than that of rhs,
594
 
             else false. By definition, entries without an offset are greater
595
 
             than those with an offset.
596
 
    */
597
 
    bool cmpPreEntriesByOffset(const Ifd::PreEntry& lhs, const Ifd::PreEntry& rhs);
598
 
 
599
 
}                                       // namespace Exiv2
600
 
 
601
 
#endif                                  // #ifndef IFD_HPP_