From f7c55fcb6415e5741f6bb51f979dacbe494860ac Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Mon, 22 Mar 2004 08:49:20 +0000 Subject: [PATCH] Bugfix: Set offset to the next IFD directly in the underlying data buffer in non-alloc mode --- src/ifd.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++++------- src/ifd.hpp | 42 ++++++++++++++++++++++++++--------- 2 files changed, 87 insertions(+), 18 deletions(-) diff --git a/src/ifd.cpp b/src/ifd.cpp index 38136ece..0539244c 100644 --- a/src/ifd.cpp +++ b/src/ifd.cpp @@ -20,14 +20,14 @@ */ /* File: ifd.cpp - Version: $Name: $ $Revision: 1.13 $ + Version: $Name: $ $Revision: 1.14 $ Author(s): Andreas Huggel (ahu) History: 26-Jan-04, ahu: created 11-Feb-04, ahu: isolated as a component */ // ***************************************************************************** #include "rcsid.hpp" -EXIV2_RCSID("@(#) $Name: $ $Revision: 1.13 $ $RCSfile: ifd.cpp,v $") +EXIV2_RCSID("@(#) $Name: $ $Revision: 1.14 $ $RCSfile: ifd.cpp,v $") // ***************************************************************************** // included header files @@ -156,18 +156,41 @@ namespace Exif { } // Entry::component Ifd::Ifd(IfdId ifdId) - : alloc_(true), ifdId_(ifdId), offset_(0), next_(0) + : alloc_(true), ifdId_(ifdId), offset_(0), pNext_(0), next_(0) { + pNext_ = new char[4]; + memset(pNext_, 0x0, 4); } Ifd::Ifd(IfdId ifdId, uint32 offset) - : alloc_(true), ifdId_(ifdId), offset_(offset), next_(0) + : alloc_(true), ifdId_(ifdId), offset_(offset), pNext_(0), next_(0) { + pNext_ = new char[4]; + memset(pNext_, 0x0, 4); } Ifd::Ifd(IfdId ifdId, uint32 offset, bool alloc) - : alloc_(alloc), ifdId_(ifdId), offset_(offset), next_(0) + : alloc_(alloc), ifdId_(ifdId), offset_(offset), pNext_(0), next_(0) { + if (alloc_) { + pNext_ = new char[4]; + memset(pNext_, 0x0, 4); + } + } + + Ifd::~Ifd() + { + if (alloc_) delete[] pNext_; + } + + Ifd::Ifd(const Ifd& rhs) + : alloc_(rhs.alloc_), entries_(rhs.entries_), ifdId_(rhs.ifdId_), + offset_(rhs.offset_), pNext_(rhs.pNext_), next_(rhs.next_) + { + if (alloc_ && rhs.pNext_) { + pNext_ = new char[4]; + memcpy(pNext_, rhs.pNext_, 4); + } } int Ifd::read(const char* buf, ByteOrder byteOrder, long offset) @@ -190,6 +213,12 @@ namespace Exif { preEntries.push_back(pe); o += 12; } + if (alloc_) { + memcpy(pNext_, buf + o, 4); + } + else { + pNext_ = const_cast(buf + o); + } next_ = getULong(buf+o, byteOrder); // Guess the offset of the IFD, if it was not given. The guess is based @@ -304,7 +333,13 @@ namespace Exif { } // Add the offset to the next IFD to the data buffer - o += ul2Data(buf + o, next_, byteOrder); + if (pNext_) { + memcpy(buf + o, pNext_, 4); + } + else { + memset(buf + o, 0x0, 4); + } + o += 4; // Add the data of all IFD entries to the data buffer for (i = b; i != e; ++i) { @@ -320,10 +355,22 @@ namespace Exif { void Ifd::clear() { entries_.clear(); - next_ = 0; + if (alloc_) { + memset(pNext_, 0x0, 4); + } + else { + pNext_ = 0; + } offset_ = 0; } // Ifd::clear + void Ifd::setNext(uint32 next, ByteOrder byteOrder) + { + assert(pNext_); + ul2Data(pNext_, next, byteOrder); + next_ = next; + } + void Ifd::add(const Entry& entry) { assert(alloc_ == entry.alloc()); @@ -407,7 +454,7 @@ namespace Exif { } os << prefix << "Next IFD: 0x" << std::setw(8) << std::setfill('0') << std::hex - << std::right << next_ << "\n"; + << std::right << next() << "\n"; // Print data of IFD entries for (i = b; i != e; ++i) { if (i->size() > 4) { diff --git a/src/ifd.hpp b/src/ifd.hpp index 883abce9..ad2b6dda 100644 --- a/src/ifd.hpp +++ b/src/ifd.hpp @@ -21,7 +21,7 @@ /*! @file ifd.hpp @brief Encoding and decoding of IFD (Image File Directory) data - @version $Name: $ $Revision: 1.11 $ + @version $Name: $ $Revision: 1.12 $ @author Andreas Huggel (ahu) ahuggel@gmx.net @date 09-Jan-04, ahu: created @@ -265,6 +265,12 @@ namespace Exif { and the same data buffer. */ class Ifd { + //! @name Not implemented + //@{ + //! Assignment not allowed (memory management mode alloc_ is const) + Ifd& operator=(const Ifd& rhs); + //@} + public: //! @name Creators //@{ @@ -285,6 +291,10 @@ namespace Exif { memory management is required for the Entries. */ Ifd(IfdId ifdId, uint32 offset, bool alloc); + //! Copy constructor + Ifd(const Ifd& rhs); + //! Destructor + ~Ifd(); //@} //! Entries const iterator type @@ -356,8 +366,11 @@ namespace Exif { entries. */ void clear(); - //! Set the offset of the next IFD - void setNext(uint32 next) { next_ = next; } + /*! + @brief Set the offset of the next IFD. Byte order is needed to update + the underlying data buffer in non-alloc mode. + */ + void setNext(uint32 next, ByteOrder byteOrder); /*! @brief Add the entry to the IFD. No duplicate-check is performed, i.e., it is possible to add multiple entries with the same tag. @@ -402,7 +415,7 @@ namespace Exif { //! Get the offset of the IFD from the start of the TIFF header long offset() const { return offset_; } //! Get the offset to the next IFD from the start of the TIFF header - long next() const { return next_; } + uint32 next() const { return next_; } //! Get the number of directory entries in the IFD long count() const { return entries_.size(); } //! Get the size of this IFD in bytes (IFD only, without data) @@ -438,12 +451,21 @@ namespace Exif { //! Container for 'pre-entries' typedef std::vector PreEntries; - const bool alloc_; // True: requires memory allocation and deallocation, - // False: no memory management needed. - Entries entries_; // IFD entries - IfdId ifdId_; // IFD Id - long offset_; // offset of the IFD from the start of TIFF header - long next_; // offset of next IFD from the start of the TIFF header + /*! + True: requires memory allocation and deallocation, + False: no memory management needed. + */ + const bool alloc_; + //! IFD entries + Entries entries_; + //! IFD Id + IfdId ifdId_; + //! offset of the IFD from the start of TIFF header + long offset_; + // Pointer to the offset of next IFD from the start of the TIFF header + char* pNext_; + // The offset of the next IFD as data value (always in sync with *pNext_) + uint32 next_; }; // class Ifd