From 97956266e635698da45be30f7df956b9afa2d680 Mon Sep 17 00:00:00 2001 From: Andreas Huggel Date: Wed, 19 Sep 2007 15:21:50 +0000 Subject: [PATCH] Utility: Implemented modify action for XMP properties. Library: Bugfixes, tweaks. --- src/actions.cpp | 25 ++++++++++++++++++++++++- src/exiv2.cpp | 8 ++++++++ src/exiv2.hpp | 2 +- src/properties.cpp | 13 +++++++++---- src/properties.hpp | 14 +++++++++----- src/value.cpp | 4 ++++ src/xmp.cpp | 6 +----- 7 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/actions.cpp b/src/actions.cpp index f9646885..d14db7d8 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -1268,7 +1268,7 @@ namespace Action { case del: delMetadatum(pImage, *i); break; - default: + case invalidCmdId: // Todo: complain break; } @@ -1285,6 +1285,7 @@ namespace Action { } Exiv2::ExifData& exifData = pImage->exifData(); Exiv2::IptcData& iptcData = pImage->iptcData(); + Exiv2::XmpData& xmpData = pImage->xmpData(); Exiv2::Value::AutoPtr value = Exiv2::Value::create(modifyCmd.typeId_); if (0 == value->read(modifyCmd.value_)) { if (modifyCmd.metadataId_ == exif) { @@ -1293,6 +1294,9 @@ namespace Action { if (modifyCmd.metadataId_ == iptc) { iptcData.add(Exiv2::IptcKey(modifyCmd.key_), value.get()); } + if (modifyCmd.metadataId_ == xmp) { + xmpData.add(Exiv2::XmpKey(modifyCmd.key_), value.get()); + } } } @@ -1308,6 +1312,7 @@ namespace Action { } Exiv2::ExifData& exifData = pImage->exifData(); Exiv2::IptcData& iptcData = pImage->iptcData(); + Exiv2::XmpData& xmpData = pImage->xmpData(); Exiv2::Metadatum* metadatum = 0; if (modifyCmd.metadataId_ == exif) { Exiv2::ExifData::iterator pos = @@ -1323,6 +1328,13 @@ namespace Action { metadatum = &(*pos); } } + if (modifyCmd.metadataId_ == xmp) { + Exiv2::XmpData::iterator pos = + xmpData.findKey(Exiv2::XmpKey(modifyCmd.key_)); + if (pos != xmpData.end()) { + metadatum = &(*pos); + } + } // If a type was explicitly requested, use it; else // use the current type of the metadatum, if any; // or the default type @@ -1344,6 +1356,9 @@ namespace Action { if (modifyCmd.metadataId_ == iptc) { iptcData.add(Exiv2::IptcKey(modifyCmd.key_), value.get()); } + if (modifyCmd.metadataId_ == xmp) { + xmpData.add(Exiv2::XmpKey(modifyCmd.key_), value.get()); + } } } else { @@ -1363,6 +1378,7 @@ namespace Action { Exiv2::ExifData& exifData = pImage->exifData(); Exiv2::IptcData& iptcData = pImage->iptcData(); + Exiv2::XmpData& xmpData = pImage->xmpData(); if (modifyCmd.metadataId_ == exif) { Exiv2::ExifData::iterator pos; Exiv2::ExifKey exifKey = Exiv2::ExifKey(modifyCmd.key_); @@ -1377,6 +1393,13 @@ namespace Action { iptcData.erase(pos); } } + if (modifyCmd.metadataId_ == xmp) { + Exiv2::XmpData::iterator pos; + Exiv2::XmpKey xmpKey = Exiv2::XmpKey(modifyCmd.key_); + while((pos = xmpData.findKey(xmpKey)) != xmpData.end()) { + xmpData.erase(pos); + } + } } Modify::AutoPtr Modify::clone() const diff --git a/src/exiv2.cpp b/src/exiv2.cpp index 9ac9771b..e701225e 100644 --- a/src/exiv2.cpp +++ b/src/exiv2.cpp @@ -902,6 +902,14 @@ namespace { } catch (const Exiv2::AnyError&) {} } + if (metadataId == invalidMetadataId) { + try { + Exiv2::XmpKey xmpKey(key); + metadataId = xmp; + defaultType = Exiv2::XmpProperties::propertyType(xmpKey); + } + catch (const Exiv2::AnyError&) {} + } if (metadataId == invalidMetadataId) { throw Exiv2::Error(1, Exiv2::toString(num) + ": " + _("Invalid key") + " `" + key + "'"); diff --git a/src/exiv2.hpp b/src/exiv2.hpp index 35292c20..16bfad62 100644 --- a/src/exiv2.hpp +++ b/src/exiv2.hpp @@ -45,7 +45,7 @@ //! Command identifiers enum CmdId { invalidCmdId, add, set, del }; //! Metadata identifiers -enum MetadataId { invalidMetadataId, iptc, exif }; +enum MetadataId { invalidMetadataId, iptc, exif, xmp }; //! Structure for one parsed modification command struct ModifyCmd { //! C'tor diff --git a/src/properties.cpp b/src/properties.cpp index 5ab0308c..687200e1 100644 --- a/src/properties.cpp +++ b/src/properties.cpp @@ -837,13 +837,18 @@ namespace Exiv2 { TypeId XmpProperties::propertyType(const XmpKey& key) { - return propertyInfo(key)->typeId_; + const XmpPropertyInfo* pi = propertyInfo(key, false); + return pi ? pi->typeId_ : xmpText; } - const XmpPropertyInfo* XmpProperties::propertyInfo(const XmpKey& key) + const XmpPropertyInfo* XmpProperties::propertyInfo(const XmpKey& key, + bool doThrow) { const XmpPropertyInfo* pl = propertyList(key.groupName()); - if (!pl) throw Error(36, key.groupName()); + if (!pl) { + if (doThrow) throw Error(36, key.groupName()); + else return 0; + } const XmpPropertyInfo* pi = 0; for (int i = 0; pl[i].name_ != 0; ++i) { if (std::string(pl[i].name_) == key.tagName()) { @@ -851,7 +856,7 @@ namespace Exiv2 { break; } } - if (!pi) throw Error(38, key.groupName(), key.tagName()); + if (!pi && doThrow) throw Error(38, key.groupName(), key.tagName()); return pi; } diff --git a/src/properties.hpp b/src/properties.hpp index e8c7a7cf..1260fbdf 100644 --- a/src/properties.hpp +++ b/src/properties.hpp @@ -120,20 +120,24 @@ namespace Exiv2 { */ static const char* propertyDesc(const XmpKey& key); /*! - @brief Return the type for property \em key + @brief Return the type for property \em key. The default + for unknown keys is xmpText. @param key The property key @return The type of the property - @throw Error if the key is invalid. */ static TypeId propertyType(const XmpKey& key); /*! @brief Return information for the property for key. Always returns a valid pointer. @param key The property key + @param doThrow Flag indicating whether to throw an Error or + return 0 if the key is not valid or unknown. @return a pointer to the property information - @throw Error if the key is invalid. + @throw Error if the key is unknown and the \em doThrow + flag is true. */ - static const XmpPropertyInfo* propertyInfo(const XmpKey& key); + static const XmpPropertyInfo* propertyInfo(const XmpKey& key, + bool doThrow =true); /*! @brief Return the namespace name for the schema associated with \em prefix. @@ -207,7 +211,7 @@ namespace Exiv2 { @param key The key string. @throw Error if the first part of the key is not 'Xmp' or the second part of the key cannot be parsed and converted - to a known schema prefix. + to a known (i.e., built-in or registered) schema prefix. */ explicit XmpKey(const std::string& key); /*! diff --git a/src/value.cpp b/src/value.cpp index 2597abe9..620de28e 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -115,6 +115,9 @@ namespace Exiv2 { case xmpText: value = AutoPtr(new XmpTextValue); break; + case xmpArray: + value = AutoPtr(new XmpArrayValue); + break; case langAlt: value = AutoPtr(new LangAltValue); break; @@ -525,6 +528,7 @@ namespace Exiv2 { XmpArrayValue::XmpArrayValue() : XmpValue(xmpArray) { + setXmpArrayType(xaBag); } int XmpArrayValue::read(const std::string& buf) diff --git a/src/xmp.cpp b/src/xmp.cpp index 8d809454..526c6f82 100644 --- a/src/xmp.cpp +++ b/src/xmp.cpp @@ -274,11 +274,7 @@ namespace Exiv2 { if (p_->value_.get() == 0) { TypeId type = xmpText; if (0 != p_->key_.get()) { - try { - type = XmpProperties::propertyType(*p_->key_.get()); - } - catch (const AnyError&) { - } + type = XmpProperties::propertyType(*p_->key_.get()); } p_->value_ = Value::create(type); }