[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:53 UTC 2017


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

The following commit has been merged in the master branch:
commit 3a6b642c6aae27037af88b315d01e847eb45cdcd
Author: Andreas Huggel <ahuggel at gmx.net>
Date:   Tue Jan 4 16:28:51 2005 +0000

    Added modify action to exiv2 tool. Implements feature #406
---
 src/actions.cpp | 125 ++++++++++++++++++++++++++++++++
 src/actions.hpp |  31 +++++++-
 src/cmd.txt     |  30 ++++++++
 src/exiv2.cpp   | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/exiv2.hpp   |  32 ++++++++-
 src/types.cpp   |  15 +++-
 src/types.hpp   |   3 +
 7 files changed, 450 insertions(+), 6 deletions(-)

diff --git a/src/actions.cpp b/src/actions.cpp
index 758dc72..e2cd7af 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -59,6 +59,7 @@ EXIV2_RCSID("@(#) $Id$");
 #include <cstdio>
 #include <ctime>
 #include <cmath>
+#include <cassert>
 #include <sys/types.h>                  // for stat()
 #include <sys/stat.h>                   // for stat()
 #ifdef HAVE_UNISTD_H
@@ -131,6 +132,7 @@ namespace Action {
         registerTask(erase,   Task::AutoPtr(new Erase));
         registerTask(extract, Task::AutoPtr(new Extract));
         registerTask(insert,  Task::AutoPtr(new Insert));
+        registerTask(modify,  Task::AutoPtr(new Modify));
     } // TaskFactory c'tor
 
     Task::AutoPtr TaskFactory::create(TaskType type)
@@ -917,6 +919,129 @@ namespace Action {
         return new Insert(*this);
     }
 
+    int Modify::run(const std::string& path)
+    try {
+        if (!Util::fileExists(path, true)) {
+            std::cerr << path
+                      << ": Failed to open the file
";
+            return -1;
+        }
+
+        // Read both exif and iptc metadata (ignore return code)
+        exifData_.read(path);
+        iptcData_.read(path);
+
+        // loop through command table and apply each command
+        ModifyCmds& modifyCmds = Params::instance().modifyCmds_;
+        ModifyCmds::const_iterator i = modifyCmds.begin();
+        ModifyCmds::const_iterator end = modifyCmds.end();
+        for (; i != end; ++i) {
+            switch (i->cmdId_) {
+            case add:
+                addMetadatum(*i);
+                break;
+            case set:
+                setMetadatum(*i);
+                break;
+            case del:
+                delMetadatum(*i);
+                break;
+            default:
+                // Todo: complain
+                break;
+            }
+        }
+
+        // Save both exif and iptc metadata
+        int rc = exifData_.write(path);
+        if (rc) {
+            std::cerr << Exiv2::ExifData::strError(rc, path) << "
";
+        }
+        rc = iptcData_.write(path);
+        if (rc) {
+            std::cerr << Exiv2::IptcData::strError(rc, path) << "
";
+        }
+        return rc;
+    }
+    catch(const Exiv2::Error& e)
+    {
+        std::cerr << "Exif exception in modify action for file " << path
+                  << ":
" << e << "
";
+        return 1;
+    } // Modify::run
+
+    void Modify::addMetadatum(const ModifyCmd& modifyCmd)
+    {
+        if (Params::instance().verbose_) {
+            std::cout << "Add " << modifyCmd.key_ << " \""
+                      << modifyCmd.value_ << "\" (" 
+                      << Exiv2::TypeInfo::typeName(modifyCmd.typeId_) 
+                      << ")" << std::endl; 
+        }
+        Exiv2::Value::AutoPtr value = Exiv2::Value::create(modifyCmd.typeId_);
+        value->read(modifyCmd.value_);
+        if (modifyCmd.metadataId_ == exif) {
+            exifData_.add(Exiv2::ExifKey(modifyCmd.key_), value.get());
+        }
+        if (modifyCmd.metadataId_ == iptc) {
+            iptcData_.add(Exiv2::IptcKey(modifyCmd.key_), value.get());
+        }
+    }
+
+    void Modify::setMetadatum(const ModifyCmd& modifyCmd)
+    {
+        if (Params::instance().verbose_) {
+            std::cout << "Set " << modifyCmd.key_ << " \""
+                      << modifyCmd.value_ << "\" (" 
+                      << Exiv2::TypeInfo::typeName(modifyCmd.typeId_) 
+                      << ")" << std::endl; 
+        }
+        Exiv2::Metadatum* metadatum = 0;
+        if (modifyCmd.metadataId_ == exif) {
+            metadatum = &exifData_[modifyCmd.key_];
+        }
+        if (modifyCmd.metadataId_ == iptc) {
+            metadatum = &iptcData_[modifyCmd.key_];
+        }
+        assert(metadatum);
+        Exiv2::Value::AutoPtr value = metadatum->getValue();
+        // If a type was explicitly requested, use it; else
+        // use the current type of the metadatum, if any;
+        // or the default type
+        if (modifyCmd.explicitType_ || value.get() == 0) {
+            value = Exiv2::Value::create(modifyCmd.typeId_);
+        }
+        value->read(modifyCmd.value_);
+        metadatum->setValue(value.get());
+    }
+
+    void Modify::delMetadatum(const ModifyCmd& modifyCmd)
+    {
+        if (Params::instance().verbose_) {
+            std::cout << "Del " << modifyCmd.key_ << std::endl; 
+        }
+        if (modifyCmd.metadataId_ == exif) {
+            Exiv2::ExifData::iterator pos =
+                exifData_.findKey(Exiv2::ExifKey(modifyCmd.key_));
+            if (pos != exifData_.end()) exifData_.erase(pos);
+        }
+        if (modifyCmd.metadataId_ == iptc) {
+            Exiv2::IptcData::iterator pos =
+                iptcData_.findKey(Exiv2::IptcKey(modifyCmd.key_));
+            if (pos != iptcData_.end()) iptcData_.erase(pos);
+        }
+    }
+
+    Modify::AutoPtr Modify::clone() const
+    {
+        return AutoPtr(clone_());
+    }
+
+    Modify* Modify::clone_() const
+    {
+        return new Modify(*this);
+    }
+
     int Adjust::run(const std::string& path)
     try {
         adjustment_ = Params::instance().adjustment_;
diff --git a/src/actions.hpp b/src/actions.hpp
index 5a83faf..ad4e279 100644
--- a/src/actions.hpp
+++ b/src/actions.hpp
@@ -37,6 +37,10 @@
 #include <string>
 #include <map>
 
+#include "exiv2.hpp"
+#include "exif.hpp"
+#include "iptc.hpp"
+
 // *****************************************************************************
 // class declarations
 
@@ -53,7 +57,7 @@ namespace Exiv2 {
 namespace Action {
 
     //! Enumerates all tasks
-    enum TaskType { none, adjust, print, rename, erase, extract, insert };
+    enum TaskType { none, adjust, print, rename, erase, extract, insert, modify };
 
 // *****************************************************************************
 // class definitions
@@ -289,6 +293,31 @@ namespace Action {
 
     }; // class Insert
 
+    /*!
+      @brief %Modify the Exif data according to the commands in the 
+             modification table.
+     */
+    class Modify : public Task {
+    public:
+        virtual ~Modify() {}
+        virtual int run(const std::string& path);
+        typedef std::auto_ptr<Modify> AutoPtr;
+        AutoPtr clone() const;
+
+    private:
+        virtual Modify* clone_() const;
+
+        //! Add a metadatum according to \em modifyCmd 
+        void addMetadatum(const ModifyCmd& modifyCmd);
+        //! Set a metadatum according to \em modifyCmd 
+        void setMetadatum(const ModifyCmd& modifyCmd);
+        //! Delete a metadatum according to \em modifyCmd 
+        void delMetadatum(const ModifyCmd& modifyCmd);
+
+        Exiv2::ExifData exifData_;              //!< Exif metadata 
+        Exiv2::IptcData iptcData_;              //!< Iptc metadata
+    }; // class Modify
+
 }                                       // namespace Action 
 
 #endif                                  // #ifndef ACTIONS_HPP_
diff --git a/src/cmd.txt b/src/cmd.txt
new file mode 100644
index 0000000..c964d5b
--- /dev/null
+++ b/src/cmd.txt
@@ -0,0 +1,30 @@
+# Sample Exiv2 command file
+# Run exiv2 -m cmd.txt file ...
+# to apply the commands to each file.
+#
+# Command file format
+# Empty lines and lines starting with # are ignored
+# Each remaining line is a command. The format for command lines is
+# <cmd> <key> [[<type>] <value>] 
+# cmd = set|add|del
+#    set will set the value of an existing tag of the given key or add a tag
+#    add will add a tag (unless the key is a non-repeatable Iptc key)
+#    del will delete a tag 
+# key = Exiv2 Exif or Iptc key
+# type = Byte|Ascii|Short|Long|Rational|Undefined|SShort|SLong|SRational  for Exif
+#        String|Date|Time|Short|Undefined  for Iptc
+#    A default type is used if none is explicitely given. The default for Exif 
+#    keys is Ascii, that for Iptc keys is determined based on the key itself.
+# value 
+#    The remaining text on the line is the value. It can optionally be enclosed in 
+#    double quotes ("value")
+
+add  Iptc.Application2.Credit	String	"mee too! (1)"   
+add  Iptc.Application2.Credit		mee too! (2)	        
+del  Iptc.Application2.Headline	 
+
+add   Exif.Image.WhitePoint	Short	32 12 4 5 6 
+
+ set  Exif.Image.DateTime	Ascii	"Zwanzig nach fuenf"
+  set Exif.Image.Artist		Ascii	nobody
+  set Exif.Image.Artist			"Vincent van Gogh"
diff --git a/src/exiv2.cpp b/src/exiv2.cpp
index 9313c53..c140db5 100644
--- a/src/exiv2.cpp
+++ b/src/exiv2.cpp
@@ -46,6 +46,7 @@ EXIV2_RCSID("@(#) $Id$");
 
 #include <string>
 #include <iostream>
+#include <fstream>
 #include <iomanip>
 #include <cstring>
 #include <cassert>
@@ -54,6 +55,17 @@ EXIV2_RCSID("@(#) $Id$");
 // local declarations
 namespace {
 
+    //! List of all command itentifiers and corresponding strings
+    static const CmdIdAndString cmdIdAndString[] = {
+        add, "add", 
+        set, "set", 
+        del, "del", 
+        invalidCmdId, "invalidCmd"                  // End of list marker
+    };
+
+    // Return a command Id for a command string 
+    CmdId commandId(const std::string& cmdString);
+
     // Evaluate [-]HH[:MM[:SS]], returns true and sets time to the value
     // in seconds if successful, else returns false.
     bool parseTime(const std::string& ts, long& time);
@@ -66,6 +78,25 @@ namespace {
      */
     int parseCommonTargets(const std::string& optarg,
                            const std::string& action);
+
+    /*!
+      @brief Parse metadata modification commands from a file
+      @param modifyCmds Reference to a structure to store the parsed commands
+      @param filename Name of the command file
+     */
+    bool parseCommands(ModifyCmds& modifyCmds, 
+                       const std::string& filename);
+
+    /*!
+      @brief Parse one line of the command file
+      @param modifyCmd Reference to a command structure to store the parsed 
+             command
+      @param line Input line
+      @param num Line number (used for error output)
+     */
+    bool parseLine(ModifyCmd& modifyCmd,
+                   const std::string& line, int num);
+
 }
 
 // *****************************************************************************
@@ -123,7 +154,7 @@ Params& Params::instance()
 void Params::version(std::ostream& os) const
 {
     os << PACKAGE_STRING << ", " 
-       << "Copyright (C) 2004 Andreas Huggel.

"
+       << "Copyright (C) 2004, 2005 Andreas Huggel.

"
        << "This is free software; see the source for copying conditions.  "
        << "There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR "
        << "A PARTICULAR PURPOSE.
";
@@ -148,6 +179,8 @@ void Params::help(std::ostream& os) const
        << "  ex | extract  Extract metadata to *.exv and thumbnail image files.
"
        << "  mv | rename   Rename files according to the Exif create timestamp.
"
        << "                The filename format can be set with -r format.
"
+       << "  mo | modify   Apply commands to modify (add, set, delete) the Exif
"
+       << "                and Iptc metadata of image files. Requires option -m
"
        << "
Options:
"
        << "   -h      Display this help and exit.
"
        << "   -V      Show the program version and exit.
"
@@ -175,7 +208,9 @@ void Params::help(std::ostream& os) const
        << "           are the same as those for the -d option.
"
        << "   -r fmt  Filename format for the `rename' action. The format string
"
        << "           follows strftime(3). Default filename format is " 
-       <<             format_ << ".

";
+       <<             format_ << ".
"
+       << "   -m file Command file for the modify action. The format for the commands
"
+       << "           set|add|del <key> [[<Type>] <value>].

";
 } // Params::help
 
 int Params::option(int opt, const std::string& optarg, int optopt)
@@ -323,6 +358,23 @@ int Params::option(int opt, const std::string& optarg, int optopt)
             break;
         }
         break;
+    case 'm':
+        switch (action_) {
+        case Action::none:
+            action_ = Action::modify;
+            cmdFile_ = optarg;                  // parse the file later
+            break;
+        case Action::modify:
+            std::cerr << progname() 
+                      << ": Ignoring surplus option -m " << optarg << "
";
+            break;
+        default:
+            std::cerr << progname() 
+                      << ": Option -m is not compatible with a previous option
";
+            rc = 1;
+            break;
+        }
+        break;
     case ':':
         std::cerr << progname() << ": Option -" << static_cast<char>(optopt) 
                   << " requires an argument
";
@@ -404,6 +456,15 @@ int Params::nonoption(const std::string& argv)
             action = true;
             action_ = Action::rename;
         }
+        if (argv == "mo" || argv == "modify") {
+            if (action_ != Action::none && action_ != Action::modify) {
+                std::cerr << progname() << ": Action modify is not "
+                          << "compatible with the given options
";
+                rc = 1;
+            }
+            action = true;
+            action_ = Action::modify;
+        }
         if (action_ == Action::none) {
             // if everything else fails, assume print as the default action
             action_ = Action::print;
@@ -430,10 +491,22 @@ int Params::getopt(int argc, char* const argv[])
                   << ": Adjust action requires option -a time
";
         rc = 1;
     }
+    if (action_ == Action::modify && cmdFile_.empty()) {
+        std::cerr << progname() 
+                  << ": Modify action requires option -m file
";
+        rc = 1;
+    }
     if (0 == files_.size()) {
         std::cerr << progname() << ": At least one file is required
";
         rc = 1;
     }
+    if (rc == 0 && action_ == Action::modify) {
+        if (!parseCommands(modifyCmds_, cmdFile_)) {
+            std::cerr << progname() << ": Error parsing -m option argument `" 
+                      << cmdFile_ << "'
";
+            rc = 1;
+        }
+    }
     return rc;
 } // Params::getopt
 
@@ -505,4 +578,147 @@ namespace {
         return rc ? rc : target;
     } // parseCommonTargets
 
+    bool parseCommands(ModifyCmds& modifyCmds, 
+                      const std::string& filename)
+    {
+        try {
+            std::ifstream file(filename.c_str());
+            if (!file) {
+                std::cerr << filename 
+                          << ": Failed to open command file for reading
";
+                return false;
+            }
+            int num = 0;
+            std::string line;
+            while (std::getline(file, line)) {
+                ModifyCmd modifyCmd;
+                if (parseLine(modifyCmd, line, ++num)) {
+                    modifyCmds.push_back(modifyCmd);
+                }
+            }
+            return true;
+        }
+        catch (const Exiv2::Error& error) {
+            std::cerr << filename << ", " << error << "
";
+            return false;
+	}
+    } // parseCommands
+
+    bool parseLine(ModifyCmd& modifyCmd, const std::string& line, int num)
+    {
+        const std::string delim = " 	";
+
+        // Skip empty lines and comments
+        std::string::size_type cmdStart = line.find_first_not_of(delim);
+        if (cmdStart == std::string::npos || line[cmdStart] == '#') return false;
+
+        // Get command and key 
+        std::string::size_type cmdEnd = line.find_first_of(delim, cmdStart+1);
+        std::string::size_type keyStart = line.find_first_not_of(delim, cmdEnd+1);
+        std::string::size_type keyEnd = line.find_first_of(delim, keyStart+1);
+        if (   cmdStart == std::string::npos
+            || cmdEnd == std::string::npos
+            || keyStart == std::string::npos) {
+            throw Exiv2::Error("line " + Exiv2::toString(num) 
+                               + ": Invalid command line");
+        }
+
+        std::string cmd(line.substr(cmdStart, cmdEnd-cmdStart));
+        CmdId cmdId = commandId(cmd);
+        if (cmdId == invalidCmdId) {
+            throw Exiv2::Error("line " + Exiv2::toString(num) 
+                               + ": Invalid command `" + cmd + "'");
+        }
+
+        Exiv2::TypeId defaultType = Exiv2::invalidTypeId;
+        std::string key(line.substr(keyStart, keyEnd-keyStart));
+        MetadataId metadataId = invalidMetadataId;
+        try {
+            Exiv2::IptcKey iptcKey(key);
+            metadataId = iptc;
+            defaultType = Exiv2::IptcDataSets::dataSetType(iptcKey.tag(), 
+                                                           iptcKey.record());
+        }
+        catch (const Exiv2::Error&) {}
+        if (metadataId == invalidMetadataId) {
+            try {
+                Exiv2::ExifKey exifKey(key);
+                metadataId = exif;
+                defaultType = Exiv2::asciiString;
+            }
+            catch (const Exiv2::Error&) {}
+        }
+        if (metadataId == invalidMetadataId) {
+            throw Exiv2::Error("line " + Exiv2::toString(num) 
+                               + ": Invalid key `" + key + "'");
+        }
+
+        std::string value;
+        Exiv2::TypeId type = Exiv2::invalidTypeId;
+        bool explicitType = true;
+        if (cmdId != del) {
+            // Get type and value
+            std::string::size_type typeStart 
+                = line.find_first_not_of(delim, keyEnd+1);
+            std::string::size_type typeEnd 
+                = line.find_first_of(delim, typeStart+1);
+            std::string::size_type valStart = typeStart;
+            std::string::size_type valEnd = line.find_last_not_of(delim);
+
+            if (   keyEnd == std::string::npos 
+                || typeStart == std::string::npos
+                || typeEnd == std::string::npos
+                || valStart == std::string::npos) {
+                throw Exiv2::Error("line " + Exiv2::toString(num) 
+                                   + ": Invalid command line");
+            }
+
+            std::string typeStr(line.substr(typeStart, typeEnd-typeStart));
+            type = Exiv2::TypeInfo::typeId(typeStr);
+            if (type != Exiv2::invalidTypeId) {
+                valStart = line.find_first_not_of(delim, typeEnd+1);
+                if (valStart == std::string::npos) {
+                    throw Exiv2::Error("line " + Exiv2::toString(num) 
+                                       + ": Invalid command line");
+                }
+            }
+            else {
+                type = defaultType;
+                explicitType = false;
+            }
+            if (type == Exiv2::invalidTypeId) {
+                throw Exiv2::Error("line " + Exiv2::toString(num) 
+                                   + ": Invalid type");
+            }
+
+            value = line.substr(valStart, valEnd+1-valStart);
+            std::string::size_type last = value.length()-1;
+            if (  (value[0] == '"' || value[last] == '"') 
+                && value[0] != value[last]) {
+                throw Exiv2::Error("line " + Exiv2::toString(num) 
+                                   + ": Unbalanced quotes");
+            }
+            if (value[0] == '"') {
+                value = value.substr(1, value.length()-2);
+            }
+        }
+
+        modifyCmd.cmdId_ = cmdId;
+        modifyCmd.key_ = key;
+        modifyCmd.metadataId_ = metadataId;
+        modifyCmd.typeId_ = type;
+        modifyCmd.explicitType_ = explicitType;
+        modifyCmd.value_ = value;
+
+        return true;
+    } // parseLine
+
+    CmdId commandId(const std::string& cmdString)
+    {
+        int i = 0;
+        for (;   cmdIdAndString[i].cmdId_ != invalidCmdId
+                 && cmdIdAndString[i].cmdString_ != cmdString; ++i) {}
+        return cmdIdAndString[i].cmdId_;
+    }
+
 }
diff --git a/src/exiv2.hpp b/src/exiv2.hpp
index 539c27b..7c323ec 100644
--- a/src/exiv2.hpp
+++ b/src/exiv2.hpp
@@ -32,6 +32,7 @@
 // *****************************************************************************
 // included header files
 #include "utils.hpp"
+#include "types.hpp"
 
 // + standard includes
 #include <string>
@@ -40,6 +41,33 @@
 
 // *****************************************************************************
 // class definitions
+
+//! Command identifiers
+enum CmdId { invalidCmdId, add, set, del };
+//! Metadata identifiers
+enum MetadataId { invalidMetadataId, iptc, exif };
+//! Structure for one parsed modification command 
+struct ModifyCmd {
+    //! C'tor
+    ModifyCmd() :
+        cmdId_(invalidCmdId), metadataId_(invalidMetadataId), 
+        typeId_(Exiv2::invalidTypeId), explicitType_(false) {}
+    CmdId cmdId_;                               //!< Command identifier
+    std::string key_;                           //!< Exiv2 key string
+    MetadataId metadataId_;                     //!< Metadata identifier 
+    Exiv2::TypeId typeId_;                      //!< Exiv2 type identifier
+    //! Flag to indicate if the type was explicitely specified (true)
+    bool explicitType_;
+    std::string value_;                         //!< Data 
+};
+//! Container for modification commands
+typedef std::vector<ModifyCmd> ModifyCmds;
+//! Structure to link command identifiers to strings
+struct CmdIdAndString {
+    CmdId cmdId_;                               //!< Commands identifier
+    std::string cmdString_;                     //!< Command string
+};
+
 /*!
   @brief Implements the command line handling for the program. 
 
@@ -103,6 +131,8 @@ public:
 
     long adjustment_;                   //!< Adjustment in seconds.
     std::string format_;                //!< Filename format (-r option arg).
+    std::string cmdFile_;               //!< Name of the modification command file
+    ModifyCmds modifyCmds_;             //!< Parsed modification commands
 
     //! Container to store filenames.
     typedef std::vector<std::string> Files;
@@ -114,7 +144,7 @@ private:
       @brief Default constructor. Note that optstring_ is initialized here.
              The c'tor is private to force instantiation through instance().
      */
-    Params() : optstring_(":hVvfa:r:p:d:e:i:"),
+    Params() : optstring_(":hVvfa:r:p:d:e:i:m:"),
                help_(false), 
                version_(false),
                verbose_(false), 
diff --git a/src/types.cpp b/src/types.cpp
index 253158a..503c40f 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -58,14 +58,16 @@ namespace Exiv2 {
         TypeInfoTable(unsignedShort,    "Short",       2),
         TypeInfoTable(unsignedLong,     "Long",        4),
         TypeInfoTable(unsignedRational, "Rational",    8),
-        TypeInfoTable(invalid6,         "Invalid (6)", 1),
+        TypeInfoTable(invalid6,         "Invalid(6)",  1),
         TypeInfoTable(undefined,        "Undefined",   1),
         TypeInfoTable(signedShort,      "SShort",      2),
         TypeInfoTable(signedLong,       "SLong",       4),
         TypeInfoTable(signedRational,   "SRational",   8),
         TypeInfoTable(string,           "String",      1),
         TypeInfoTable(date,             "Date",        8),
-        TypeInfoTable(time,             "Time",        11)
+        TypeInfoTable(time,             "Time",        11),
+        // End of list marker
+        TypeInfoTable(lastTypeId,       "(Unknown)",   0)
     };
 
     const char* TypeInfo::typeName(TypeId typeId)
@@ -73,6 +75,15 @@ namespace Exiv2 {
         return typeInfoTable_[ typeId < lastTypeId ? typeId : 0 ].name_;
     }
 
+    TypeId TypeInfo::typeId(const std::string& typeName)
+    {
+        int i = 0;
+        for (;    typeInfoTable_[i].typeId_ != lastTypeId
+               && typeInfoTable_[i].name_ != typeName; ++i) {}
+        return typeInfoTable_[i].typeId_ == lastTypeId ?
+               invalidTypeId : typeInfoTable_[i].typeId_;
+    }
+
     long TypeInfo::typeSize(TypeId typeId)
     {
         return typeInfoTable_[ typeId < lastTypeId ? typeId : 0 ].size_;
diff --git a/src/types.hpp b/src/types.hpp
index 6d5fe5f..13b086c 100644
--- a/src/types.hpp
+++ b/src/types.hpp
@@ -46,6 +46,7 @@
 #include <iosfwd>
 #include <utility>
 #include <sstream>
+#include <cstdio>
 #ifdef HAVE_STDINT_H
 # include <stdint.h>
 #endif
@@ -113,6 +114,8 @@ namespace Exiv2 {
     public:
         //! Return the name of the type
         static const char* typeName(TypeId typeId);
+        //! Return the type id for a type name
+        static TypeId typeId(const std::string& typeName);
         //! Return the size in bytes of one element of this type
         static long typeSize(TypeId typeId);
 

-- 
exiv2 packaging



More information about the pkg-kde-commits mailing list