#1187 Thank You to Taras for the patch.
This commit is contained in:
parent
41f14f2b7b
commit
b15a401569
@ -39,6 +39,7 @@
|
||||
#include "metadatum.hpp"
|
||||
#include "tags.hpp"
|
||||
#include "datasets.hpp"
|
||||
#include "rwlock.hpp"
|
||||
|
||||
// + standard includes
|
||||
#include <string>
|
||||
@ -108,6 +109,11 @@ namespace Exiv2 {
|
||||
//! 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.
|
||||
@ -174,6 +180,7 @@ namespace Exiv2 {
|
||||
@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
|
||||
@ -206,6 +213,8 @@ namespace Exiv2 {
|
||||
@note This invalidates XMP keys generated in this namespace.
|
||||
*/
|
||||
static void unregisterNs(const std::string& ns);
|
||||
static Internal::RWLock rwLock_;
|
||||
|
||||
/*!
|
||||
@brief Unregister all custom namespaces.
|
||||
|
||||
|
||||
138
include/exiv2/rwlock.hpp
Normal file
138
include/exiv2/rwlock.hpp
Normal file
@ -0,0 +1,138 @@
|
||||
#ifndef RW_LOCK_HPP
|
||||
#define RW_LOCK_HPP
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace Exiv2 {
|
||||
namespace Internal {
|
||||
#ifdef _WIN32
|
||||
class RWLock
|
||||
{
|
||||
public:
|
||||
RWLock()
|
||||
{
|
||||
InitializeSRWLock(&rwlock_);
|
||||
}
|
||||
|
||||
~RWLock()
|
||||
{
|
||||
// do not explicitly destroy
|
||||
}
|
||||
|
||||
void wrlock()
|
||||
{
|
||||
AcquireSRWLockExclusive(&rwlock_);
|
||||
}
|
||||
|
||||
bool trywrlock()
|
||||
{
|
||||
return TryAcquireSRWLockExclusive(&rwlock_);
|
||||
}
|
||||
|
||||
void rdlock()
|
||||
{
|
||||
AcquireSRWLockShared(&rwlock_);
|
||||
}
|
||||
|
||||
bool tryrdlock()
|
||||
{
|
||||
return TryAcquireSRWLockShared(&rwlock_);
|
||||
}
|
||||
|
||||
void rdunlock()
|
||||
{
|
||||
ReleaseSRWLockShared(&rwlock_);
|
||||
}
|
||||
|
||||
void wrunlock()
|
||||
{
|
||||
ReleaseSRWLockExclusive(&rwlock_);
|
||||
}
|
||||
|
||||
private:
|
||||
SRWLOCK rwlock_;
|
||||
};
|
||||
#else
|
||||
class RWLock
|
||||
{
|
||||
public:
|
||||
RWLock(const pthread_rwlockattr_t *attr = 0)
|
||||
{
|
||||
pthread_rwlock_init(&rwlock_, attr);
|
||||
}
|
||||
|
||||
~RWLock()
|
||||
{
|
||||
pthread_rwlock_destroy(&rwlock_);
|
||||
}
|
||||
|
||||
int wrlock()
|
||||
{
|
||||
return pthread_rwlock_wrlock(&rwlock_);
|
||||
}
|
||||
|
||||
int trywrlock()
|
||||
{
|
||||
return pthread_rwlock_trywrlock(&rwlock_);
|
||||
}
|
||||
|
||||
int rdlock()
|
||||
{
|
||||
return pthread_rwlock_rdlock(&rwlock_);
|
||||
}
|
||||
|
||||
int tryrdlock()
|
||||
{
|
||||
return pthread_rwlock_tryrdlock(&rwlock_);
|
||||
}
|
||||
|
||||
int unlock()
|
||||
{
|
||||
return pthread_rwlock_unlock(&rwlock_);
|
||||
}
|
||||
|
||||
void rdunlock() { unlock(); }
|
||||
void wrunlock() { unlock(); }
|
||||
|
||||
private:
|
||||
pthread_rwlock_t rwlock_;
|
||||
};
|
||||
#endif
|
||||
|
||||
class ScopedReadLock
|
||||
{
|
||||
public:
|
||||
ScopedReadLock(RWLock &rwlock):
|
||||
rwlock_(rwlock)
|
||||
{
|
||||
rwlock_.rdlock();
|
||||
}
|
||||
|
||||
~ScopedReadLock() { rwlock_.rdunlock(); }
|
||||
|
||||
private:
|
||||
RWLock &rwlock_;
|
||||
};
|
||||
|
||||
class ScopedWriteLock
|
||||
{
|
||||
public:
|
||||
ScopedWriteLock(RWLock &rwlock):
|
||||
rwlock_(rwlock)
|
||||
{
|
||||
rwlock_.wrlock();
|
||||
}
|
||||
|
||||
~ScopedWriteLock() { rwlock_.wrunlock(); }
|
||||
|
||||
private:
|
||||
RWLock &rwlock_;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RW_LOCK_HPP
|
||||
@ -51,6 +51,7 @@ EXIV2_RCSID("@(#) $Id: epsimage.cpp $")
|
||||
namespace {
|
||||
|
||||
using namespace Exiv2;
|
||||
using Exiv2::byte;
|
||||
|
||||
// signature of DOS EPS
|
||||
const std::string dosEpsSignature = "\xC5\xD0\xD3\xC6";
|
||||
|
||||
@ -47,6 +47,7 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
namespace {
|
||||
|
||||
using namespace Exiv2;
|
||||
using Exiv2::byte;
|
||||
|
||||
/*!
|
||||
@brief Compare two preview images by number of pixels, if width and height
|
||||
|
||||
@ -39,6 +39,7 @@ EXIV2_RCSID("@(#) $Id$")
|
||||
#include "metadatum.hpp"
|
||||
#include "i18n.h" // NLS support.
|
||||
#include "xmp.hpp"
|
||||
#include "rwlock.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
@ -2238,8 +2239,15 @@ namespace Exiv2 {
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -2251,11 +2259,13 @@ namespace Exiv2 {
|
||||
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) {
|
||||
@ -2263,7 +2273,7 @@ namespace Exiv2 {
|
||||
<< 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
|
||||
@ -2281,6 +2291,12 @@ namespace Exiv2 {
|
||||
}
|
||||
|
||||
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()) {
|
||||
@ -2292,15 +2308,18 @@ namespace Exiv2 {
|
||||
|
||||
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 += "/";
|
||||
@ -2318,9 +2337,10 @@ namespace Exiv2 {
|
||||
|
||||
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)
|
||||
@ -2384,8 +2404,15 @@ namespace Exiv2 {
|
||||
|
||||
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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user