[SCM] exiv2 packaging branch, master, updated. debian/0.25-3.1-3734-gdcbc29a

Maximiliano Curia maxy at moszumanska.debian.org
Thu Jul 13 17:37:29 UTC 2017


Gitweb-URL: http://git.debian.org/?p=pkg-kde/kde-extras/exiv2.git;a=commitdiff;h=973e046

The following commit has been merged in the master branch:
commit 973e046a21ee5641a958687050a803267592cf6a
Author: Andreas Huggel <ahuggel at gmx.net>
Date:   Mon Apr 10 17:08:49 2006 +0000

    Implemented the TIFF component factory as a policy class (TiffCreator), used by TiffParser and TiffReader. Added Stephan's find template to search static arrays.
---
 src/tiffimage.cpp  |  13 +--
 src/tiffimage.hpp  |  10 --
 src/tiffparse.cpp  |  18 +---
 src/tiffparser.cpp | 243 ++++--------------------------------------
 src/tiffparser.hpp | 301 ++++++++++++++++++++++++++++++++++++++++++++++-------
 src/types.hpp      |  52 +++++++++
 6 files changed, 341 insertions(+), 296 deletions(-)

diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp
index 64a6cae..68e5a0e 100644
--- a/src/tiffimage.cpp
+++ b/src/tiffimage.cpp
@@ -55,16 +55,6 @@ EXIV2_RCSID("@(#) $Id$");
 // class member definitions
 namespace Exiv2 {
 
-    const TiffStructure TiffImage::tiffStructure_[] = {
-        { Tag::root, Group::none, newTiffDirectory, Group::ifd0 },
-        {    0x8769, Group::ifd0, newTiffSubIfd,    Group::exif },
-        {    0x8825, Group::ifd0, newTiffSubIfd,    Group::gps  },
-        {    0xa005, Group::exif, newTiffSubIfd,    Group::iop  },
-        { Tag::next, Group::ifd0, newTiffDirectory, Group::ifd0 },
-        // End of list marker
-        { Tag::none, Group::none, 0, Group::none }
-    };
-
     TiffImage::TiffImage(BasicIo::AutoPtr io, bool create)
         : Image(mdExif | mdComment), io_(io)
     {
@@ -145,8 +135,7 @@ namespace Exiv2 {
         io_->read(buf.pData_, len);
         if (io_->error() || io_->eof()) throw Error(14);
 
-        TiffMetadataDecoder decoder(this);
-        TiffParser::decode(buf.pData_, buf.size_, tiffStructure_, decoder);
+        TiffParser<TiffCreator>::decode(this, buf.pData_, buf.size_);
     } // TiffImage::readMetadata
 
     void TiffImage::writeMetadata()
diff --git a/src/tiffimage.hpp b/src/tiffimage.hpp
index 3c5ba00..0a91039 100644
--- a/src/tiffimage.hpp
+++ b/src/tiffimage.hpp
@@ -43,14 +43,6 @@
 namespace Exiv2 {
 
 // *****************************************************************************
-// class declarations
-
-    struct TiffStructure;
-
-// *****************************************************************************
-// type definitions
-
-// *****************************************************************************
 // class definitions
 
     // Add TIFF to the supported image formats
@@ -167,8 +159,6 @@ namespace Exiv2 {
         IptcData          iptcData_;            //!< IPTC data container
         std::string       comment_;             //!< User comment
 
-        static const TiffStructure tiffStructure_[]; //<! TIFF structure
-
     }; // class TiffImage
 
 // *****************************************************************************
diff --git a/src/tiffparse.cpp b/src/tiffparse.cpp
index c7eb141..557fff2 100644
--- a/src/tiffparse.cpp
+++ b/src/tiffparse.cpp
@@ -36,28 +36,14 @@ try {
     io.read(buf.pData_, len);
     if (io.error() || io.eof()) throw Error(14);
 
-    const TiffStructure tiffStructure[] = {
-        { Tag::root, Group::none, newTiffDirectory, Group::ifd0 },
-        {    0x8769, Group::ifd0, newTiffSubIfd,    Group::exif },
-        {    0x8825, Group::ifd0, newTiffSubIfd,    Group::gps  },
-        {    0xa005, Group::exif, newTiffSubIfd,    Group::iop  },
-        { Tag::next, Group::ifd0, newTiffDirectory, Group::ifd0 },
-        // End of list marker
-        { Tag::none, Group::none, 0, Group::none }
-    };
-
     TiffHeade2 tiffHeader;
     if (!tiffHeader.read(buf.pData_, buf.size_)) throw Error(3, "TIFF");
 
-    TiffComponent::AutoPtr rootDir
-        = TiffParser::create(Tag::root, Group::none, tiffStructure);
+    TiffComponent::AutoPtr rootDir = TiffCreator::create(Tag::root, Group::none);
     if (0 == rootDir.get()) {
         throw Error(1, "No root element defined in TIFF structure");
     }
-    TiffReader reader(buf.pData_,
-                      buf.size_,
-                      tiffHeader.byteOrder(),
-                      tiffStructure);
+    TiffReader<TiffCreator> reader(buf.pData_, buf.size_, tiffHeader.byteOrder());
 
     rootDir->setStart(buf.pData_ + tiffHeader.offset());
     rootDir->accept(reader);
diff --git a/src/tiffparser.cpp b/src/tiffparser.cpp
index 02e1a6a..1513383 100644
--- a/src/tiffparser.cpp
+++ b/src/tiffparser.cpp
@@ -53,16 +53,17 @@ EXIV2_RCSID("@(#) $Id$");
 #include <iomanip>
 #include <cassert>
 
-
 /* --------------------------------------------------------------------------
 
    Todo:
 
    + Add further child mgmt stuff to TIFF composite: remove, find
-   + Review boundary checking, is it better to check the offsets
+   + Review boundary checking, is it better to check the offsets?
    + Define and implement consistent error handling for recursive hierarchy
-   + Better handling of TiffStructure
    + Add Makernote support
+   + Make TiffImage a template StandardImage, which can be parametrized with
+     a parser and the necessary checking functions to cover all types of 
+     images which need to be loaded completely.
 
    in crwimage.* :
 
@@ -78,46 +79,24 @@ EXIV2_RCSID("@(#) $Id$");
 // class member definitions
 namespace Exiv2 {
 
-    void TiffParser::decode(const byte* pData,
-                            uint32_t size,
-                            const TiffStructure* pTiffStructure,
-                            TiffVisitor& decoder)
-    {
-        assert(pData != 0);
-
-        TiffHeade2 tiffHeader;
-        if (!tiffHeader.read(pData, size) || tiffHeader.offset() >= size) {
-            throw Error(3, "TIFF");
-        }
-        TiffComponent::AutoPtr rootDir
-            = TiffParser::create(Tag::root, Group::none, pTiffStructure);
-        if (0 == rootDir.get()) return;
-
-        TiffReader reader(pData,
-                          size,
-                          tiffHeader.byteOrder(),
-                          pTiffStructure);
-        rootDir->setStart(pData + tiffHeader.offset());
-        rootDir->accept(reader);
-
-        rootDir->accept(decoder);
-
-    } // TiffParser::decode
+    const TiffStructure TiffCreator::tiffStructure_[] = {
+        { Tag::root, Group::none, newTiffDirectory, Group::ifd0 },
+        {    0x8769, Group::ifd0, newTiffSubIfd,    Group::exif },
+        {    0x8825, Group::ifd0, newTiffSubIfd,    Group::gps  },
+        {    0xa005, Group::exif, newTiffSubIfd,    Group::iop  },
+        { Tag::next, Group::ifd0, newTiffDirectory, Group::ifd0 }
+    };
 
-    TiffComponent::AutoPtr TiffParser::create(uint32_t extendedTag,
-                                              uint16_t group,
-                                              const TiffStructure* pTiffStructure)
+    bool TiffStructure::operator==(const TiffStructure::Key& key) const
     {
-        const TiffStructure* ts = 0;
-        int idx = 0;
-        for (; pTiffStructure[idx].extendedTag_ != Tag::none; ++idx) {
-            if (   extendedTag == pTiffStructure[idx].extendedTag_
-                && group == pTiffStructure[idx].group_) {
-                ts = &pTiffStructure[idx];
-                break;
-            }
-        }
+        return key.e_ == extendedTag_ && key.g_ == group_; 
+    }
 
+    TiffComponent::AutoPtr TiffCreator::create(uint32_t extendedTag,
+                                               uint16_t group)
+    {
+        const TiffStructure* ts = find(tiffStructure_,
+                                       TiffStructure::Key(extendedTag, group));
         TiffComponent::AutoPtr tc(0);
         if (ts && ts->newTiffCompFct_) {
             tc = ts->newTiffCompFct_(ts);
@@ -127,7 +106,7 @@ namespace Exiv2 {
             tc = TiffComponent::AutoPtr(new TiffEntry(tag, group));
         }
         return tc;
-    } // TiffParser::create
+    } // TiffCreator::create
 
     TiffDirectory::~TiffDirectory()
     {
@@ -352,188 +331,6 @@ namespace Exiv2 {
         pImage_->exifData().add(k, object->pValue());
     } // TiffMetadataDecoder::decodeTiffEntry
 
-    TiffReader::TiffReader(const byte* pData,
-                           uint32_t    size,
-                           ByteOrder   byteOrder,
-                           const TiffStructure* pTiffStructure)
-        : pData_(pData),
-          size_(size),
-          pLast_(pData + size - 1),
-          byteOrder_(byteOrder),
-          pTiffStructure_(pTiffStructure)
-    {
-        assert(pData);
-        assert(size > 0);
-        assert(pTiffStructure);
-    } // TiffReader::TiffReader
-
-    void TiffReader::visitEntry(TiffEntry* object)
-    {
-        readTiffEntry(object);
-    }
-
-    void TiffReader::visitDirectory(TiffDirectory* object)
-    {
-        assert(object != 0);
-
-        byte* p = const_cast<byte*>(object->start());
-        assert(p >= pData_);
-
-        if (p + 2 > pLast_) {
-#ifndef SUPPRESS_WARNINGS
-            std::cerr << "Error: "
-                      << "Directory " << object->groupName() << ": "
-                      << " IFD exceeds data buffer, cannot read entry count.
";
-#endif
-            return;
-        }
-        const uint16_t n = getUShort(p, byteOrder_);
-        p += 2;
-        for (uint16_t i = 0; i < n; ++i) {
-            if (p + 12 > pLast_) {
-#ifndef SUPPRESS_WARNINGS
-                std::cerr << "Error: "
-                          << "Directory " << object->groupName() << ": "
-                          << " IFD entry " << i
-                          << " lies outside of the data buffer.
";
-#endif
-                return;
-            }
-            uint16_t tag = getUShort(p, byteOrder_);
-            TiffComponent::AutoPtr tc
-                = TiffParser::create(tag, object->group(), pTiffStructure_);
-            tc->setStart(p);
-            object->addChild(tc);
-            p += 12;
-        }
-
-        if (p + 4 > pLast_) {
-#ifndef SUPPRESS_WARNINGS
-                std::cerr << "Error: "
-                          << "Directory " << object->groupName() << ": "
-                          << " IFD exceeds data buffer, cannot read next pointer.
";
-#endif
-                return;
-        }
-        uint32_t next = getLong(p, byteOrder_);
-        if (next) {
-            TiffComponent::AutoPtr tc
-                = TiffParser::create(Tag::next, object->group(), pTiffStructure_);
-            if (next > size_) {
-#ifndef SUPPRESS_WARNINGS
-                std::cerr << "Error: "
-                          << "Directory " << object->groupName() << ": "
-                          << " Next pointer is out of bounds.
";
-#endif
-                return;
-            }
-            tc->setStart(pData_ + next);
-            object->addNext(tc);
-        }
-
-    } // TiffReader::visitDirectory
-
-    void TiffReader::visitSubIfd(TiffSubIfd* object)
-    {
-        assert(object != 0);
-
-        readTiffEntry(object);
-        if (object->typeId() == unsignedLong && object->count() >= 1) {
-            uint32_t offset = getULong(object->pData(), byteOrder_);
-            if (offset > size_) {
-#ifndef SUPPRESS_WARNINGS
-                std::cerr << "Error: "
-                          << "Directory " << object->groupName()
-                          << ", entry 0x" << std::setw(4)
-                          << std::setfill('0') << std::hex << object->tag()
-                          << " Sub-IFD pointer is out of bounds; ignoring it.
";
-#endif
-                return;
-            }
-            object->ifd_.setStart(pData_ + offset);
-        }
-#ifndef SUPPRESS_WARNINGS
-        else {
-            std::cerr << "Warning: "
-                      << "Directory " << object->groupName()
-                      << ", entry 0x" << std::setw(4)
-                      << std::setfill('0') << std::hex << object->tag()
-                      << " doesn't look like a sub-IFD.";
-        }
-#endif
-
-    } // TiffReader::visitSubIfd
-
-    void TiffReader::readTiffEntry(TiffEntryBase* object)
-    {
-        assert(object != 0);
-
-        byte* p = const_cast<byte*>(object->start());
-        assert(p >= pData_);
-
-        if (p + 12 > pLast_) {
-#ifndef SUPPRESS_WARNINGS
-            std::cerr << "Error: Entry in directory " << object->groupName()
-                      << "requests access to memory beyond the data buffer. "
-                      << "Skipping entry.
";
-#endif
-            return;
-        }
-        // Component already has tag
-        p += 2;
-        object->type_ = getUShort(p, byteOrder_);
-        // todo: check type
-        p += 2;
-        object->count_ = getULong(p, byteOrder_);
-        p += 4;
-        object->size_ = TypeInfo::typeSize(object->typeId()) * object->count();
-        object->offset_ = getULong(p, byteOrder_);
-        object->pData_ = p;
-        if (object->size() > 4) {
-            if (object->offset() >= size_) {
-#ifndef SUPPRESS_WARNINGS
-                std::cerr << "Error: Offset of "
-                          << "directory " << object->groupName() << ", "
-                          << " entry 0x" << std::setw(4)
-                          << std::setfill('0') << std::hex << object->tag()
-                          << " is out of bounds:
"
-                          << "Offset = 0x" << std::setw(8)
-                          << std::setfill('0') << std::hex << object->offset()
-                          << "; truncating the entry
";
-#endif
-                object->size_ = 0;
-                object->count_ = 0;
-                object->offset_ = 0;
-                return;
-            }
-            object->pData_ = pData_ + object->offset();
-            if (object->pData() + object->size() > pLast_) {
-#ifndef SUPPRESS_WARNINGS
-                std::cerr << "Warning: Upper boundary of data for "
-                          << "directory " << object->groupName() << ", "
-                          << " entry 0x" << std::setw(4)
-                          << std::setfill('0') << std::hex << object->tag()
-                          << " is out of bounds:
"
-                          << "Offset = 0x" << std::setw(8)
-                          << std::setfill('0') << std::hex << object->offset()
-                          << ", size = " << std::dec << object->size()
-                          << ", exceeds buffer size by "
-                // cast to make MSVC happy
-                          << static_cast<uint32_t>(object->pData() + object->size() - pLast_)
-                          << " Bytes; adjusting the size
";
-#endif
-                object->size_ = size_ - object->offset();
-                // todo: adjust count_, make size_ a multiple of typeSize
-            }
-        }
-        Value::AutoPtr v = Value::create(object->typeId());
-        if (v.get()) {
-            v->read(object->pData(), object->size(), byteOrder_);
-            object->pValue_ = v.release();
-        }
-
-    } // TiffReader::readTiffEntry
-
     // *************************************************************************
     // free functions
 
diff --git a/src/tiffparser.hpp b/src/tiffparser.hpp
index 3115f95..d83120c 100644
--- a/src/tiffparser.hpp
+++ b/src/tiffparser.hpp
@@ -31,16 +31,18 @@
 
 // *****************************************************************************
 // included header files
+#include "image.hpp"
 #include "exif.hpp"
 #include "iptc.hpp"
-#include "image.hpp"
 #include "types.hpp"
+#include "error.hpp"
 
 // + standard includes
 #include <iostream>
-#include <iosfwd>
+#include <iomanip>
 #include <string>
 #include <vector>
+#include <cassert>
 
 // *****************************************************************************
 // namespace extensions
@@ -219,9 +221,11 @@ namespace Exiv2 {
     /*!
       @brief TIFF composite visitor to read the TIFF structure from a block of
              memory and build the composite from it (Visitor pattern). Used by
-             TiffParser to read the TIFF data from a block of memory.
+             TiffParser to read the TIFF data from a block of memory. Uses
+             the policy class CreationPolicy for the creation of TIFF components.
      */
-    class TiffReader : public TiffVisitor {
+    template<typename CreationPolicy>
+    class TiffReader : public TiffVisitor, public CreationPolicy {
     public:
         //! @name Creators
         //@{
@@ -231,13 +235,10 @@ namespace Exiv2 {
           @param pData     Pointer to the data buffer, starting with a TIFF header.
           @param size      Number of bytes in the data buffer.
           @param byteOrder Applicable byte order (little or big endian).
-          @param pTiffStructure Pointer to a table describing the TIFF structure
-                           used to decode the data.
          */
         TiffReader(const byte* pData,
                    uint32_t    size,
-                   ByteOrder   byteOrder,
-                   const TiffStructure* pTiffStructure);
+                   ByteOrder   byteOrder);
 
         //! Virtual destructor
         virtual ~TiffReader() {}
@@ -261,7 +262,6 @@ namespace Exiv2 {
         const uint32_t size_;                   //!< Size of the buffer
         const byte* pLast_;                     //!< Pointer to the last byte
         const ByteOrder byteOrder_;             //!< Byteorder for the image
-        const TiffStructure* pTiffStructure_;   //!< Pointer to the TIFF structure
 
     }; // class TiffReader
 
@@ -372,7 +372,8 @@ namespace Exiv2 {
              entry.
      */
     class TiffEntryBase : public TiffComponent {
-        friend void TiffReader::readTiffEntry(TiffEntryBase* object);
+        template<typename CreationPolicy>
+        friend void TiffReader<CreationPolicy>::readTiffEntry(TiffEntryBase* object);
     public:
         //! @name Creators
         //@{
@@ -497,7 +498,8 @@ namespace Exiv2 {
              GPS tags.
      */
     class TiffSubIfd : public TiffEntryBase {
-        friend void TiffReader::visitSubIfd(TiffSubIfd* object);
+        template<typename CreationPolicy>
+        friend void TiffReader<CreationPolicy>::visitSubIfd(TiffSubIfd* object);
     public:
         //! @name Creators
         //@{
@@ -552,47 +554,67 @@ namespace Exiv2 {
         uint16_t       group_;          //!< Group that contains the tag
         NewTiffCompFct newTiffCompFct_; //!< Function to create the correct TIFF component
         uint16_t       newGroup_;       //!< Group of the newly created component
+
+        struct Key;
+        //! Comparison operator to compare a TiffStructure with a TiffStructure::Key
+        bool operator==(const Key& key) const;
+    };
+
+    //! Search key for TIFF structure.
+    struct TiffStructure::Key {
+        //! Constructor
+        Key(uint32_t e, uint16_t g) : e_(e), g_(g) {}
+        uint32_t e_;                    //!< Extended tag
+        uint16_t g_;                    //!< %Group
     };
 
     /*!
+      @brief TIFF component factory for standard TIFF components. This class is
+             meant to be used as a policy class.
+     */
+    class TiffCreator {
+    public:
+        /*!
+          @brief Create the TiffComponent for TIFF entry \em extendedTag and 
+                 \em group based on the embedded lookup table.
+
+          If a tag and group combination is not found in the table, a TiffEntry
+          is created.  If the pointer that is returned is 0, then the TIFF entry
+          should be ignored.
+        */
+        static TiffComponent::AutoPtr create(uint32_t extendedTag,
+                                             uint16_t group);
+    protected:
+        //! Prevent destruction
+        ~TiffCreator() {}
+    private:
+        static const TiffStructure tiffStructure_[]; //<! TIFF structure
+    }; // class TiffCreator
+
+    /*!
       @brief Stateless parser class for data in TIFF format. Images use this
-             class to decode and encode TIFF-based data.
+             class to decode and encode TIFF-based data. Uses class 
+             CreationPolicy for the creation of TIFF components.
      */
-    class TiffParser {
+    template<typename CreationPolicy>
+    class TiffParser : public CreationPolicy {
     public:
         /*!
           @brief Decode TIFF metadata from a data buffer \em pData of length
-                 \em size into \em image.
+                 \em size into \em pImage.
 
           This is the entry point to access image data in TIFF format. The
           parser uses classes TiffHeade2 and the TiffComponent and TiffVisitor
           hierarchies.
 
+          @param pImage         Pointer to the image to hold the metadata
           @param pData          Pointer to the data buffer. Must point to data
                                 in TIFF format; no checks are performed.
           @param size           Length of the data buffer.
-          @param pTiffStructure Pointer to a table describing the TIFF structure
-                                used to decode the data.
-          @param decoder        Reference to a TIFF visitor to decode and extract
-                                the metadata from the TIFF composite structure.
-
-          @throw Error If the data buffer cannot be parsed.
-        */
-        static void decode(const byte*          pData,
-                                 uint32_t       size,
-                           const TiffStructure* pTiffStructure,
-                           TiffVisitor&   decoder);
-        /*!
-          @brief Create the TiffComponent for TIFF entry \em tag in \em group
-                 based on the lookup list \em pTiffStructure.
-
-          If a tag, group tupel is not found in the table, a TiffEntry is
-          created.  If the pointer that is returned is 0, then the TIFF entry
-          should be ignored.
         */
-        static TiffComponent::AutoPtr create(      uint32_t       extendedTag,
-                                                   uint16_t       group,
-                                             const TiffStructure* pTiffStructure);
+        static void decode(      Image*         pImage,
+                           const byte*          pData,
+                                 uint32_t       size);
     }; // class TiffParser
 
 // *****************************************************************************
@@ -604,6 +626,215 @@ namespace Exiv2 {
     //! Function to create and initialize a new TIFF sub-directory
     TiffComponent::AutoPtr newTiffSubIfd(const TiffStructure* ts);
 
+    template<typename CreationPolicy>
+    void TiffParser<CreationPolicy>::decode(Image* pImage,
+                                            const byte* pData,
+                                            uint32_t size)
+    {
+        assert(pImage != 0);
+        assert(pData != 0);
+
+        TiffHeade2 tiffHeader;
+        if (!tiffHeader.read(pData, size) || tiffHeader.offset() >= size) {
+            throw Error(3, "TIFF");
+        }
+        TiffComponent::AutoPtr rootDir = CreationPolicy::create(Tag::root, 
+                                                                Group::none);
+        if (0 == rootDir.get()) return;
+        rootDir->setStart(pData + tiffHeader.offset());
+
+        TiffReader<CreationPolicy> reader(pData,
+                                          size,
+                                          tiffHeader.byteOrder());
+        rootDir->accept(reader);
+
+        TiffMetadataDecoder decoder(pImage);
+        rootDir->accept(decoder);
+
+    } // TiffParser::decode
+
+    template<typename CreationPolicy>
+    TiffReader<CreationPolicy>::TiffReader(const byte* pData,
+                                           uint32_t    size,
+                                           ByteOrder   byteOrder)
+        : pData_(pData),
+          size_(size),
+          pLast_(pData + size - 1),
+          byteOrder_(byteOrder)
+    {
+        assert(pData);
+        assert(size > 0);
+    } // TiffReader::TiffReader
+
+    template<typename CreationPolicy>
+    void TiffReader<CreationPolicy>::visitEntry(TiffEntry* object)
+    {
+        readTiffEntry(object);
+    }
+
+    template<typename CreationPolicy>
+    void TiffReader<CreationPolicy>::visitDirectory(TiffDirectory* object)
+    {
+        assert(object != 0);
+
+        byte* p = const_cast<byte*>(object->start());
+        assert(p >= pData_);
+
+        if (p + 2 > pLast_) {
+#ifndef SUPPRESS_WARNINGS
+            std::cerr << "Error: "
+                      << "Directory " << object->groupName() << ": "
+                      << " IFD exceeds data buffer, cannot read entry count.
";
+#endif
+            return;
+        }
+        const uint16_t n = getUShort(p, byteOrder_);
+        p += 2;
+        for (uint16_t i = 0; i < n; ++i) {
+            if (p + 12 > pLast_) {
+#ifndef SUPPRESS_WARNINGS
+                std::cerr << "Error: "
+                          << "Directory " << object->groupName() << ": "
+                          << " IFD entry " << i
+                          << " lies outside of the data buffer.
";
+#endif
+                return;
+            }
+            uint16_t tag = getUShort(p, byteOrder_);
+            TiffComponent::AutoPtr tc = CreationPolicy::create(tag, object->group());
+            tc->setStart(p);
+            object->addChild(tc);
+            p += 12;
+        }
+
+        if (p + 4 > pLast_) {
+#ifndef SUPPRESS_WARNINGS
+                std::cerr << "Error: "
+                          << "Directory " << object->groupName() << ": "
+                          << " IFD exceeds data buffer, cannot read next pointer.
";
+#endif
+                return;
+        }
+        uint32_t next = getLong(p, byteOrder_);
+        if (next) {
+            TiffComponent::AutoPtr tc = CreationPolicy::create(Tag::next, object->group());
+            if (next > size_) {
+#ifndef SUPPRESS_WARNINGS
+                std::cerr << "Error: "
+                          << "Directory " << object->groupName() << ": "
+                          << " Next pointer is out of bounds.
";
+#endif
+                return;
+            }
+            tc->setStart(pData_ + next);
+            object->addNext(tc);
+        }
+
+    } // TiffReader::visitDirectory
+
+    template<typename CreationPolicy>
+    void TiffReader<CreationPolicy>::visitSubIfd(TiffSubIfd* object)
+    {
+        assert(object != 0);
+
+        readTiffEntry(object);
+        if (object->typeId() == unsignedLong && object->count() >= 1) {
+            uint32_t offset = getULong(object->pData(), byteOrder_);
+            if (offset > size_) {
+#ifndef SUPPRESS_WARNINGS
+                std::cerr << "Error: "
+                          << "Directory " << object->groupName()
+                          << ", entry 0x" << std::setw(4)
+                          << std::setfill('0') << std::hex << object->tag()
+                          << " Sub-IFD pointer is out of bounds; ignoring it.
";
+#endif
+                return;
+            }
+            object->ifd_.setStart(pData_ + offset);
+        }
+#ifndef SUPPRESS_WARNINGS
+        else {
+            std::cerr << "Warning: "
+                      << "Directory " << object->groupName()
+                      << ", entry 0x" << std::setw(4)
+                      << std::setfill('0') << std::hex << object->tag()
+                      << " doesn't look like a sub-IFD.";
+        }
+#endif
+
+    } // TiffReader::visitSubIfd
+
+    template<typename CreationPolicy>
+    void TiffReader<CreationPolicy>::readTiffEntry(TiffEntryBase* object)
+    {
+        assert(object != 0);
+
+        byte* p = const_cast<byte*>(object->start());
+        assert(p >= pData_);
+
+        if (p + 12 > pLast_) {
+#ifndef SUPPRESS_WARNINGS
+            std::cerr << "Error: Entry in directory " << object->groupName()
+                      << "requests access to memory beyond the data buffer. "
+                      << "Skipping entry.
";
+#endif
+            return;
+        }
+        // Component already has tag
+        p += 2;
+        object->type_ = getUShort(p, byteOrder_);
+        // todo: check type
+        p += 2;
+        object->count_ = getULong(p, byteOrder_);
+        p += 4;
+        object->size_ = TypeInfo::typeSize(object->typeId()) * object->count();
+        object->offset_ = getULong(p, byteOrder_);
+        object->pData_ = p;
+        if (object->size() > 4) {
+            if (object->offset() >= size_) {
+#ifndef SUPPRESS_WARNINGS
+                std::cerr << "Error: Offset of "
+                          << "directory " << object->groupName() << ", "
+                          << " entry 0x" << std::setw(4)
+                          << std::setfill('0') << std::hex << object->tag()
+                          << " is out of bounds:
"
+                          << "Offset = 0x" << std::setw(8)
+                          << std::setfill('0') << std::hex << object->offset()
+                          << "; truncating the entry
";
+#endif
+                object->size_ = 0;
+                object->count_ = 0;
+                object->offset_ = 0;
+                return;
+            }
+            object->pData_ = pData_ + object->offset();
+            if (object->pData() + object->size() > pLast_) {
+#ifndef SUPPRESS_WARNINGS
+                std::cerr << "Warning: Upper boundary of data for "
+                          << "directory " << object->groupName() << ", "
+                          << " entry 0x" << std::setw(4)
+                          << std::setfill('0') << std::hex << object->tag()
+                          << " is out of bounds:
"
+                          << "Offset = 0x" << std::setw(8)
+                          << std::setfill('0') << std::hex << object->offset()
+                          << ", size = " << std::dec << object->size()
+                          << ", exceeds buffer size by "
+                // cast to make MSVC happy
+                          << static_cast<uint32_t>(object->pData() + object->size() - pLast_)
+                          << " Bytes; adjusting the size
";
+#endif
+                object->size_ = size_ - object->offset();
+                // todo: adjust count_, make size_ a multiple of typeSize
+            }
+        }
+        Value::AutoPtr v = Value::create(object->typeId());
+        if (v.get()) {
+            v->read(object->pData(), object->size(), byteOrder_);
+            object->pValue_ = v.release();
+        }
+
+    } // TiffReader::readTiffEntry
+
 }                                       // namespace Exiv2
 
 #endif                                  // #ifndef TIFFPARSER_HPP_
diff --git a/src/types.hpp b/src/types.hpp
index 855c5e4..272e0b1 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -43,6 +43,7 @@
 #include <string>
 #include <iosfwd>
 #include <utility>
+#include <algorithm>
 #include <sstream>
 #ifdef EXV_HAVE_STDINT_H
 # include <stdint.h>
@@ -300,6 +301,57 @@ namespace Exiv2 {
 // *****************************************************************************
 // template and inline definitions
 
+    /*!
+      @brief Find an element that matches \em key in the array \em src.
+      
+      Designed to be used with lookup tables as shown in the example below.
+      Requires a %Key structure (ideally in the array) and a comparison operator
+      to compare a key with an array element.  The size of the array is
+      determined automagically. Thanks to Stephan Broennimann for this nifty
+      implementation.
+
+      @code
+      struct Bar {
+          int i;
+          int k;
+          const char* data;
+      
+          struct Key;
+          bool operator==(const Bar::Key& rhs) const;
+      };
+      
+      struct Bar::Key {
+          Key(int a, int b) : i(a), k(b) {}
+          int i;
+          int k;
+      };
+      
+      bool Bar::operator==(const Bar::Key& key) const // definition
+      {
+          return i == key.i && k == key.k;
+      }
+      
+      const Bar bars[] = {
+          { 1, 1, "bar data 1" }, 
+          { 1, 2, "bar data 2" }, 
+          { 1, 3, "bar data 3" }
+      };
+      
+      int main ( void ) {
+          const Bar* bar = find(bars, Bar::Key(1, 3));
+          if (bar) std::cout << bar->data << "
";
+          else std::cout << "Key not found.
";
+          return 0;
+      }  
+      @endcode
+    */
+    template<typename T, typename K, int N>
+    const T* find(T (&src)[N], const K& key)
+    {
+        const T* rc = std::find(src, src + N, key);
+        return rc == src + N ? 0 : rc;
+    }
+
     //! Utility function to convert the argument of any type to a string
     template<typename T>
     std::string toString(const T& arg)

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list