Index: include/exiv2/properties.hpp =================================================================== --- include/exiv2/properties.hpp (revision 4307) +++ include/exiv2/properties.hpp (working copy) @@ -38,6 +38,7 @@ #include "types.hpp" #include "metadatum.hpp" #include "tags.hpp" +#include "rwlock.hpp" // + standard includes #include @@ -107,6 +108,11 @@ //! Prevent assignment: not implemented. XmpProperties& operator=(const XmpProperties& rhs); + private: + static const XmpNsInfo* nsInfoUnsafe(const std::string& prefix); + static void unregisterNsUnsafe(const std::string& ns); + static const XmpNsInfo* lookupNsRegistryUnsafe(const XmpNsInfo::Prefix& prefix); + public: /*! @brief Return the title (label) of the property. @@ -173,6 +179,7 @@ @throw Error if no namespace is registered with \em prefix. */ static const XmpNsInfo* nsInfo(const std::string& prefix); + /*! @brief Return the (preferred) prefix for schema namespace \em ns. @param ns Schema namespace @@ -205,6 +212,7 @@ @note This invalidates XMP keys generated in this namespace. */ static void unregisterNs(const std::string& ns); + /*! @brief Unregister all custom namespaces. @@ -223,7 +231,7 @@ // DATA static NsRegistry nsRegistry_; //!< Namespace registry - + static Internal::RWLock rwLock_; }; // class XmpProperties /*! Index: src/epsimage.cpp =================================================================== --- src/epsimage.cpp (revision 4307) +++ src/epsimage.cpp (working copy) @@ -51,6 +51,7 @@ namespace { using namespace Exiv2; + using Exiv2::byte; // signature of DOS EPS const std::string dosEpsSignature = "\xC5\xD0\xD3\xC6"; Index: src/preview.cpp =================================================================== --- src/preview.cpp (revision 4307) +++ src/preview.cpp (working copy) @@ -47,6 +47,7 @@ namespace { using namespace Exiv2; + using Exiv2::byte; /*! @brief Compare two preview images by number of pixels, if width and height Index: src/properties.cpp =================================================================== --- src/properties.cpp (revision 4307) +++ src/properties.cpp (working copy) @@ -39,6 +39,7 @@ #include "metadatum.hpp" #include "i18n.h" // NLS support. #include "xmp.hpp" +#include "rwlock.hpp" #include #include @@ -2205,9 +2206,16 @@ } XmpProperties::NsRegistry XmpProperties::nsRegistry_; + Internal::RWLock XmpProperties::rwLock_; const XmpNsInfo* XmpProperties::lookupNsRegistry(const XmpNsInfo::Prefix& prefix) { + Internal::ScopedReadLock srl(rwLock_); + return lookupNsRegistryUnsafe(prefix); + } + + const XmpNsInfo* XmpProperties::lookupNsRegistryUnsafe(const XmpNsInfo::Prefix& prefix) + { for (NsRegistry::const_iterator i = nsRegistry_.begin(); i != nsRegistry_.end(); ++i) { if (i->second == prefix) return &(i->second); @@ -2218,11 +2226,13 @@ void XmpProperties::registerNs(const std::string& ns, const std::string& prefix) { + Internal::ScopedWriteLock swl(rwLock_); + std::string ns2 = ns; if ( ns2.substr(ns2.size() - 1, 1) != "/" && ns2.substr(ns2.size() - 1, 1) != "#") ns2 += "/"; // Check if there is already a registered namespace with this prefix - const XmpNsInfo* xnp = lookupNsRegistry(XmpNsInfo::Prefix(prefix)); + const XmpNsInfo* xnp = lookupNsRegistryUnsafe(XmpNsInfo::Prefix(prefix)); if (xnp) { #ifndef SUPPRESS_WARNINGS if (strcmp(xnp->ns_, ns2.c_str()) != 0) { @@ -2230,7 +2240,7 @@ << xnp->ns_ << " to " << ns2 << "\n"; } #endif - unregisterNs(xnp->ns_); + unregisterNsUnsafe(xnp->ns_); } // Allocated memory is freed when the namespace is unregistered. // Using malloc/free for better system compatibility in case @@ -2249,6 +2259,12 @@ void XmpProperties::unregisterNs(const std::string& ns) { + Internal::ScopedWriteLock swl(rwLock_); + unregisterNsUnsafe(ns); + } + + void XmpProperties::unregisterNsUnsafe(const std::string& ns) + { NsRegistry::iterator i = nsRegistry_.find(ns); if (i != nsRegistry_.end()) { std::free(const_cast(i->second.prefix_)); @@ -2259,15 +2275,18 @@ void XmpProperties::unregisterNs() { + Internal::ScopedWriteLock swl(rwLock_); + NsRegistry::iterator i = nsRegistry_.begin(); while (i != nsRegistry_.end()) { NsRegistry::iterator kill = i++; - unregisterNs(kill->first); + unregisterNsUnsafe(kill->first); } } std::string XmpProperties::prefix(const std::string& ns) { + Internal::ScopedReadLock srl(rwLock_); std::string ns2 = ns; if ( ns2.substr(ns2.size() - 1, 1) != "/" && ns2.substr(ns2.size() - 1, 1) != "#") ns2 += "/"; @@ -2285,9 +2304,10 @@ std::string XmpProperties::ns(const std::string& prefix) { - const XmpNsInfo* xn = lookupNsRegistry(XmpNsInfo::Prefix(prefix)); + Internal::ScopedReadLock srl(rwLock_); + const XmpNsInfo* xn = lookupNsRegistryUnsafe(XmpNsInfo::Prefix(prefix)); if (xn != 0) return xn->ns_; - return nsInfo(prefix)->ns_; + return nsInfoUnsafe(prefix)->ns_; } const char* XmpProperties::propertyTitle(const XmpKey& key) @@ -2351,8 +2371,15 @@ const XmpNsInfo* XmpProperties::nsInfo(const std::string& prefix) { + Internal::ScopedReadLock srl(rwLock_); + return nsInfoUnsafe(prefix); + } + + const XmpNsInfo* XmpProperties::nsInfoUnsafe(const std::string& prefix) + { + Internal::ScopedReadLock srl(rwLock_); const XmpNsInfo::Prefix pf(prefix); - const XmpNsInfo* xn = lookupNsRegistry(pf); + const XmpNsInfo* xn = lookupNsRegistryUnsafe(pf); if (!xn) xn = find(xmpNsInfo, pf); if (!xn) throw Error(35, prefix); return xn;