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

Maximiliano Curia maxy at moszumanska.debian.org
Thu Jul 13 17:36:22 UTC 2017


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

The following commit has been merged in the master branch:
commit 29f2e78ce32342f9b7ef374f5b8b4a9266185fbb
Author: Andreas Huggel <ahuggel at gmx.net>
Date:   Mon May 24 02:18:47 2004 +0000

    * Replaced too simple prefix with a more general concept of a makernote header.
    * Fixed match() to prefer an exact match over a wildcard match with the same
      number of matching characters (Key "Nikon" now prefers registry entry "Nikon"
      over "Nikon*"), simplified the return value of match() to an int score value.
    * Added DEBUG_REGISTRY debug output.
    * Code and documentation cleanup.
---
 src/makernote.cpp | 169 +++++++++++++++++++++++++++++++++++++++---------------
 src/makernote.hpp | 114 +++++++++++++++++++++++++-----------
 2 files changed, 206 insertions(+), 77 deletions(-)

diff --git a/src/makernote.cpp b/src/makernote.cpp
index acadd35..0d478b1 100644
--- a/src/makernote.cpp
+++ b/src/makernote.cpp
@@ -20,16 +20,17 @@
  */
 /*
   File:      makernote.cpp
-  Version:   $Name:  $ $Revision: 1.18 $
+  Version:   $Name:  $ $Revision: 1.19 $
   Author(s): Andreas Huggel (ahu) <ahuggel at gmx.net>
   History:   18-Feb-04, ahu: created
  */
 // *****************************************************************************
 #include "rcsid.hpp"
-EXIV2_RCSID("@(#) $Name:  $ $Revision: 1.18 $ $RCSfile: makernote.cpp,v $")
+EXIV2_RCSID("@(#) $Name:  $ $Revision: 1.19 $ $RCSfile: makernote.cpp,v $")
 
-// Define DEBUG_MAKERNOTE to output debug information to std::cerr
+// Define DEBUG_* to output debug information to std::cerr
 #undef DEBUG_MAKERNOTE
+#define DEBUG_REGISTRY
 
 // *****************************************************************************
 // included header files
@@ -42,7 +43,7 @@ EXIV2_RCSID("@(#) $Name:  $ $Revision: 1.18 $ $RCSfile: makernote.cpp,v $")
 #include <sstream>
 #include <iomanip>
 
-#ifdef DEBUG_MAKERNOTE
+#if defined DEBUG_MAKERNOTE || defined DEBUG_REGISTRY
 #   include <iostream>
 #endif
 
@@ -50,6 +51,12 @@ EXIV2_RCSID("@(#) $Name:  $ $Revision: 1.18 $ $RCSfile: makernote.cpp,v $")
 // class member definitions
 namespace Exiv2 {
 
+    MakerNote::MakerNote(const MnTagInfo* pMnTagInfo, bool alloc) 
+        : pMnTagInfo_(pMnTagInfo), alloc_(alloc),
+          offset_(0), byteOrder_(invalidByteOrder)
+    {
+    }
+
     std::string MakerNote::makeKey(uint16 tag) const
     {
         return std::string(ExifTags::ifdItem(makerIfd))
@@ -150,6 +157,14 @@ namespace Exiv2 {
                   << tagDesc(tag);
     } // MakerNote::writeMnTagInfo
 
+
+    IfdMakerNote::IfdMakerNote(const MakerNote::MnTagInfo* pMnTagInfo,
+                               bool alloc)
+        : MakerNote(pMnTagInfo, alloc),
+          absOffset_(true), adjOffset_(0), ifd_(makerIfd, 0, alloc)
+    {
+    }
+
     int IfdMakerNote::read(const char* buf,
                            long len, 
                            ByteOrder byteOrder, 
@@ -159,24 +174,22 @@ namespace Exiv2 {
         offset_ = offset;
         // Set byte order if none is set yet
         if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder;
-        int rc = 0;
-        if (!prefix_.empty()) {
-            // Check if makernote is long enough and starts with prefix
-            if (   len < static_cast<long>(prefix_.size())
-                || prefix_ != std::string(buf, prefix_.size())) rc = 2;
-        }
-        if (!absOffset_) {
-            // Use offsets relative to the start of the Makernote field
-            offset = 0;
+        // Read and check the header (and set offset adjustment)
+        int rc = readHeader(buf, len, byteOrder);
+        if (rc == 0) {
+            rc = checkHeader();
         }
+        // Adjust the offset
+        offset = absOffset_ ? offset + adjOffset_ : adjOffset_;
+        // Read the makernote IFD
         if (rc == 0) {
-            rc = ifd_.read(buf + prefix_.size(), 
-                           len - prefix_.size(),
-                           byteOrder_, 
-                           offset + prefix_.size());
+            rc = ifd_.read(buf + headerSize(), 
+                           len - headerSize(),
+                           byteOrder_,
+                           offset);
         }
         if (rc == 0) {
-            // IfdMakerNote does not support multiple IFDs
+            // IfdMakerNote currently does not support multiple IFDs
             if (ifd_.next() != 0) rc = 3;
         }
         if (rc == 0) {
@@ -188,8 +201,8 @@ namespace Exiv2 {
 #ifdef DEBUG_MAKERNOTE
         hexdump(std::cerr, buf, len, offset);
         if (rc == 0) ifd_.print(std::cerr);
-        else std::cerr << "IfdMakerNote::read() failed, rc = " << rc << "
";
 #endif
+
         return rc;
     } // IfdMakerNote::read
 
@@ -199,20 +212,39 @@ namespace Exiv2 {
         offset_ = offset;
         // Set byte order if none is set yet
         if (byteOrder_ == invalidByteOrder) byteOrder_ = byteOrder;
+
         long len = 0;
-        if (!prefix_.empty()) {
-            // Write the prefix string to the Makernote buffer
-            memcpy(buf, prefix_.data(), prefix_.size());
-            len += prefix_.size();
-        }
-        if (!absOffset_) {
-            // Use offsets relative to the start of the Makernote field
-            offset = 0;
-        }
-        len += ifd_.copy(buf + len, byteOrder_, offset + len);
+        len += copyHeader(buf);
+        len += ifd_.copy(buf + len, byteOrder_, offset_);
+
         return len;
     } // IfdMakerNote::copy
 
+    int IfdMakerNote::readHeader(const char* buf, 
+                                 long len,
+                                 ByteOrder byteOrder)
+    {
+        // Default implementation does nothing, assuming there is no header
+        return 0;
+    }
+
+    int IfdMakerNote::checkHeader() const
+    {
+        // Default implementation does nothing, assuming there is no header
+        return 0;
+    }
+
+    long IfdMakerNote::copyHeader(char* buf) const
+    {
+        if (header_.size_ != 0) memcpy(buf, header_.pData_, header_.size_);
+        return header_.size_;
+    }
+
+    long IfdMakerNote::headerSize() const
+    {
+        return header_.size_;
+    }
+
     Entries::const_iterator IfdMakerNote::findIdx(int idx) const 
     {
         return ifd_.findIdx(idx); 
@@ -220,7 +252,7 @@ namespace Exiv2 {
 
     long IfdMakerNote::size() const
     {
-        return prefix_.size() + ifd_.size() + ifd_.dataSize();
+        return headerSize() + ifd_.size() + ifd_.dataSize();
     }
 
     MakerNoteFactory* MakerNoteFactory::pInstance_ = 0;
@@ -237,7 +269,7 @@ namespace Exiv2 {
                                              const std::string& model, 
                                              CreateFct createMakerNote)
     {
-#ifdef DEBUG_MAKERNOTE
+#ifdef DEBUG_REGISTRY
         std::cerr << "Registering MakerNote create function for \"" 
                   << make << "\" and \"" << model << "\".
";
 #endif
@@ -276,42 +308,80 @@ namespace Exiv2 {
                                         const std::string& model,
                                         bool alloc) const
     {
+#ifdef DEBUG_REGISTRY
+        std::cerr << "Entering MakerNoteFactory::create(\"" 
+                  << make << "\", \"" << model << "\", "
+                  << (alloc == true ? "true" : "false") << ")
";
+#endif
         // loop through each make of the registry to find the best matching make
-        int matchCount = -1;
+        int score = 0;
         ModelRegistry* modelRegistry = 0;
+#ifdef DEBUG_REGISTRY
+        std::string makeMatch;
+        std::cerr << "Searching make registry...
"; 
+#endif
         Registry::const_iterator end1 = registry_.end();
         Registry::const_iterator pos1;
         for (pos1 = registry_.begin(); pos1 != end1; ++pos1) {
-            std::pair<bool, int> rc = match(pos1->first, make);
-            if (rc.first && rc.second > matchCount) {
-                matchCount = rc.second;
+            int rc = match(pos1->first, make);
+            if (rc > score) {
+                score = rc;
+#ifdef DEBUG_REGISTRY
+                makeMatch = pos1->first;
+#endif
                 modelRegistry = pos1->second;
             }
         }
         if (modelRegistry == 0) return 0;
+#ifdef DEBUG_REGISTRY
+        std::cerr << "Best match is \"" << makeMatch << "\".
";
+#endif
 
         // loop through each model of the model registry to find the best match
-        matchCount = -1;
+        score = 0;
         CreateFct createMakerNote = 0;
+#ifdef DEBUG_REGISTRY
+        std::string modelMatch;
+        std::cerr << "Searching model registry...
";
+#endif
         ModelRegistry::const_iterator end2 = modelRegistry->end();
         ModelRegistry::const_iterator pos2;
         for (pos2 = modelRegistry->begin(); pos2 != end2; ++pos2) {
-            std::pair<bool, int> rc = match(pos2->first, model);
-            if (rc.first && rc.second > matchCount) {
-                matchCount = rc.second;
+            int rc = match(pos2->first, model);
+            if (rc > score) {
+                score = rc;
+#ifdef DEBUG_REGISTRY
+                modelMatch = pos2->first;
+#endif
                 createMakerNote = pos2->second;
             }
         }
         if (createMakerNote == 0) return 0;
+#ifdef DEBUG_REGISTRY
+        std::cerr << "Best match is \"" << modelMatch << "\".
";
+#endif
 
         return createMakerNote(alloc);
     } // MakerNoteFactory::create
 
-    std::pair<bool, int> MakerNoteFactory::match(const std::string& regEntry,
-                                                 const std::string& key)
+    int MakerNoteFactory::match(const std::string& regEntry,
+                                const std::string& key)
     {
+#ifdef DEBUG_REGISTRY
+        std::cerr << "   Matching registry entry \"" << regEntry << "\" (" 
+                  << regEntry.size() << ") with key \"" << key << "\" ("
+                  << key.size() << "): ";
+#endif
         // Todo: make the comparisons case insensitive
 
+        // Handle exact match (this is only necessary because of the different
+        // return value - the following algorithm also finds exact matches)
+        if (regEntry == key) {
+#ifdef DEBUG_REGISTRY
+            std::cerr << "Exact match (score: " << key.size() + 2 << ")
";
+#endif
+            return key.size() + 2;
+        }
         std::string uKey = key;
         std::string uReg = regEntry;
 
@@ -327,7 +397,10 @@ namespace Exiv2 {
                     uReg.substr(ei) : uReg.substr(ei, pos - ei);
 
                 if (ki == std::string::npos) {
-                    return std::make_pair(false, 0);
+#ifdef DEBUG_REGISTRY
+                    std::cerr << "Not a match.
";
+#endif
+                    return 0;
                 }
 
                 bool found = false;
@@ -372,15 +445,21 @@ namespace Exiv2 {
                     count += ss.size();
                 }
                 else {
-                    return std::make_pair(false, 0);
+#ifdef DEBUG_REGISTRY
+                    std::cerr << "Not a match.
";
+#endif
+                    return 0;
                 }
             } // if the substr is not empty
 
             ei = pos == std::string::npos ? std::string::npos : pos + 1;
 
         } // while ei doesn't point to the end of the registry entry
-                                     
-        return std::make_pair(true, count);
+
+#ifdef DEBUG_REGISTRY
+        std::cerr << "Match (score: " << count + 1 << ")
";
+#endif
+        return count + 1;
         
     } // MakerNoteFactory::match
 
diff --git a/src/makernote.hpp b/src/makernote.hpp
index 1b7edb5..a9da013 100644
--- a/src/makernote.hpp
+++ b/src/makernote.hpp
@@ -22,7 +22,7 @@
   @file    makernote.hpp
   @brief   Contains the Exif %MakerNote interface, IFD %MakerNote and a 
            MakerNote factory
-  @version $Name:  $ $Revision: 1.17 $
+  @version $Name:  $ $Revision: 1.18 $
   @author  Andreas Huggel (ahu)
            <a href="mailto:ahuggel at gmx.net">ahuggel at gmx.net</a>
   @date    18-Feb-04, ahu: created
@@ -85,11 +85,17 @@ namespace Exiv2 {
 
       To implement a new IFD makernote, all that you need to do is 
       - subclass %IfdMakerNote, 
-      - implement the create function,
+      - implement methods to read and check the header (if any) as well as
+        clone and create functions,
       - add a list of tag descriptions and appropriate print functions and 
       - register the camera make/model and create function in the makernote factory. 
       .
-      See CanonMakerNote for an example.
+      See existing makernote implementations for examples, e.g., CanonMakerNote
+      or FujiMakerNote.
+
+      Finally, the implementation files should be named *mn.[ch]pp, so that the
+      magic, which ensures that the makernote is automatically registered 
+      in the factory, will pick it up (see mn.sh for details).
      */
     class MakerNote {
     public:
@@ -112,21 +118,18 @@ namespace Exiv2 {
                  allows to choose whether or not memory management is required
                  for the Entries.
          */
-        MakerNote(const MnTagInfo* pMnTagInfo =0, bool alloc =true) 
-            : pMnTagInfo_(pMnTagInfo), alloc_(alloc),
-              byteOrder_(invalidByteOrder), offset_(0) {}
+        explicit MakerNote(const MnTagInfo* pMnTagInfo =0, bool alloc =true);
         //! Virtual destructor.
         virtual ~MakerNote() {}
         //@}
 
         //! @name Manipulators
         //@{
-        //! Set the byte order (little or big endian).
-        void setByteOrder(ByteOrder byteOrder) { byteOrder_ = byteOrder; }
         /*!
-          @brief Read the makernote from character buffer buf of length len at
-                 position offset (from the start of the TIFF header) and encoded
-                 in byte order byteOrder.
+          @brief Read the makernote, including the makernote header, from
+                 character buffer buf of length len at position offset (from the
+                 start of the TIFF header) and encoded in byte order byteOrder.
+                 Return 0 if successful.
          */
         virtual int read(const char* buf, 
                          long len, 
@@ -231,13 +234,16 @@ namespace Exiv2 {
                  False: no memory management needed.
          */
         const bool alloc_; 
-        /*!  
+        /*! 
+          @brief Offset of the makernote from the start of the TIFF header 
+                 (for offset()).
+         */
+        long offset_;
+        /*!
           @brief Alternative byte order to use, invalid if the byte order of the
                  Exif block can be used
          */
         ByteOrder byteOrder_;
-        //! Offset of the makernote from the start of the TIFF header
-        long offset_;
 
     }; // class MakerNote
 
@@ -253,9 +259,8 @@ namespace Exiv2 {
                  allows to choose whether or not memory management is required
                  for the Entries.
          */
-        IfdMakerNote(const MakerNote::MnTagInfo* pMnTagInfo =0, bool alloc =true)
-            : MakerNote(pMnTagInfo, alloc), 
-              absOffset_(true), ifd_(makerIfd, 0, alloc) {}
+        explicit IfdMakerNote(const MakerNote::MnTagInfo* pMnTagInfo =0, 
+                              bool alloc =true);
         //! Virtual destructor
         virtual ~IfdMakerNote() {}
         //@}
@@ -266,6 +271,17 @@ namespace Exiv2 {
                          long len, 
                          ByteOrder byteOrder, 
                          long offset);
+        /*!
+          @brief Read the makernote header from the makernote databuffer.  This
+                 method must set the offset adjustment (adjOffset_), if needed
+                 (assuming that the required information is in the header).
+                 Return 0 if successful.          
+          @note  The default implementation does nothing, assuming there is no
+                 header
+         */
+        virtual int readHeader(const char* buf, 
+                               long len,
+                               ByteOrder byteOrder);
         virtual long copy(char* buf, ByteOrder byteOrder, long offset);
         void add(const Entry& entry) { ifd_.add(entry); }
         Entries::iterator begin() { return ifd_.begin(); }
@@ -278,7 +294,27 @@ namespace Exiv2 {
         Entries::const_iterator end() const { return ifd_.end(); }
         Entries::const_iterator findIdx(int idx) const;
         long size() const;
-        virtual MakerNote* clone(bool alloc =true) const =0;
+        /*!
+          @brief Check the makernote header. This will typically check if a
+                 required prefix string is present in the header. Return 0 if
+                 successful.
+          @note  The default implementation does nothing, assuming there is no
+                 header
+         */
+        virtual int checkHeader() const;
+        /*!
+          @brief Write the makernote header to a character buffer, return the 
+                 number of characters written.
+          @note  The default implementation copies the header_ buffer.
+         */
+        virtual long copyHeader(char* buf) const;
+        /*! 
+          @brief Return the size of the makernote header in bytes.
+          @note  The default implementation returns the size of the header_ 
+                 buffer.
+         */
+        virtual long headerSize() const;
+        virtual IfdMakerNote* clone(bool alloc =true) const =0;
         virtual std::string sectionName(uint16 tag) const =0; 
         virtual std::ostream& printTag(std::ostream& os,
                                        uint16 tag, 
@@ -287,14 +323,23 @@ namespace Exiv2 {
 
     protected:
         // DATA
-        //! String prefix at the beginning of the makernote, before the IFD
-        std::string prefix_;
         /*!
-          @brief True:  Offsets are from start of the TIFF header,
-                 False: Offsets are from start of the makernote
+          @brief True:  Adjustment of the IFD offsets is to be added to the
+                        offset from the start of the TIFF header,
+                 False: Adjustment of the IFD offsets is a suitable absolute 
+                        value. Ignore the offset from the start of the TIFF 
+                        header.
+         */
+        bool absOffset_;
+        /*!
+          @brief Adjustment of the IFD offsets relative to the start of the 
+                 TIFF header or to the start of the makernote, depending on 
+                 the setting of absOffset_.
          */
-        bool absOffset_; 
-        //! MakerNote IFD
+        long adjOffset_;
+        //! Data buffer for the makernote header
+        DataBuf header_;
+        //! The makernote IFD
         Ifd ifd_;
 
     }; // class IfdMakerNote
@@ -383,15 +428,20 @@ namespace Exiv2 {
           @brief Match a registry entry with a key (used for make and model).
 
           The matching algorithm is case insensitive and wildcards ('*') in the
-          registry entry are supported. The best match is the match with the
-          most matching characters.
-
-          @return A pair of which the first component indicates whether or not
-                  the key matches and the second component contains the number
-                  of matching characters.
+          registry entry are supported. The best match is an exact match, then
+          a match is rated according to the number of matching characters.
+
+          @return A score value indicating how good the key and registry entry 
+                  match. 0 means no match, values greater than 0 indicate a
+                  match, larger values are better matches:<BR>
+                  0: key and registry entry do not match<BR>
+                  1: a pure wildcard match, i.e., the registry entry is just 
+                     a wildcard.<BR>
+                  Score values greater than 1 are computed by adding 1 to the 
+                  number of matching characters, except for an exact match, 
+                  which scores 2 plus the number of matching characters.
          */
-        static std::pair<bool, int> match(const std::string& regEntry, 
-                                          const std::string& key);
+        static int match(const std::string& regEntry, const std::string& key);
 
     private:
         //! @name Creators

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list