summaryrefslogtreecommitdiff
path: root/source/XMPCore
diff options
context:
space:
mode:
Diffstat (limited to 'source/XMPCore')
-rw-r--r--source/XMPCore/ExpatAdapter.cpp33
-rw-r--r--source/XMPCore/ParseRDF.cpp77
-rw-r--r--source/XMPCore/WXMPIterator.cpp120
-rw-r--r--source/XMPCore/WXMPMeta.cpp782
-rw-r--r--source/XMPCore/WXMPUtils.cpp434
-rw-r--r--source/XMPCore/XMPCore_Impl.cpp133
-rw-r--r--source/XMPCore/XMPCore_Impl.hpp204
-rw-r--r--source/XMPCore/XMPIterator.cpp103
-rw-r--r--source/XMPCore/XMPIterator.hpp10
-rw-r--r--source/XMPCore/XMPMeta-GetSet.cpp276
-rw-r--r--source/XMPCore/XMPMeta-Parse.cpp39
-rw-r--r--source/XMPCore/XMPMeta-Serialize.cpp160
-rw-r--r--source/XMPCore/XMPMeta.cpp927
-rw-r--r--source/XMPCore/XMPMeta.hpp56
-rw-r--r--source/XMPCore/XMPUtils-FileInfo.cpp444
-rw-r--r--source/XMPCore/XMPUtils.cpp767
-rw-r--r--source/XMPCore/XMPUtils.hpp79
17 files changed, 1853 insertions, 2791 deletions
diff --git a/source/XMPCore/ExpatAdapter.cpp b/source/XMPCore/ExpatAdapter.cpp
index 3dff828..48f6763 100644
--- a/source/XMPCore/ExpatAdapter.cpp
+++ b/source/XMPCore/ExpatAdapter.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2005-2008 Adobe Systems Incorporated
+// Copyright 2005 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -62,14 +62,16 @@ static void CommentHandler ( void * userData, XMP_StringPtr commen
// =================================================================================================
-extern "C" ExpatAdapter * XMP_NewExpatAdapter()
+extern "C" ExpatAdapter * XMP_NewExpatAdapter ( bool useGlobalNamespaces )
{
- return new ExpatAdapter;
+
+ return new ExpatAdapter ( useGlobalNamespaces );
+
} // XMP_NewExpatAdapter
// =================================================================================================
-ExpatAdapter::ExpatAdapter() : parser(0)
+ExpatAdapter::ExpatAdapter ( bool useGlobalNamespaces ) : parser(0), registeredNamespaces(0)
{
#if XMP_DebugBuild
@@ -82,6 +84,12 @@ ExpatAdapter::ExpatAdapter() : parser(0)
this->parser = XML_ParserCreateNS ( 0, FullNameSeparator );
if ( this->parser == 0 ) XMP_Throw ( "Failure creating Expat parser", kXMPErr_ExternalFailure );
+ if ( useGlobalNamespaces ) {
+ this->registeredNamespaces = sRegisteredNamespaces;
+ } else {
+ this->registeredNamespaces = new XMP_NamespaceTable ( *sRegisteredNamespaces );
+ }
+
XML_SetUserData ( this->parser, this );
XML_SetNamespaceDeclHandler ( this->parser, StartNamespaceDeclHandler, EndNamespaceDeclHandler );
@@ -109,6 +117,9 @@ ExpatAdapter::~ExpatAdapter()
if ( this->parser != 0 ) XML_ParserFree ( this->parser );
this->parser = 0;
+
+ if ( this->registeredNamespaces != sRegisteredNamespaces ) delete ( this->registeredNamespaces );
+ this->registeredNamespaces = 0;
} // ExpatAdapter::~ExpatAdapter
@@ -181,7 +192,7 @@ void ExpatAdapter::ParseBuffer ( const void * buffer, size_t length, bool last /
// =================================================================================================
-static void SetQualName ( XMP_StringPtr fullName, XML_Node * node )
+static void SetQualName ( ExpatAdapter * thiz, XMP_StringPtr fullName, XML_Node * node )
{
// Expat delivers the full name as a catenation of namespace URI, separator, and local name.
@@ -207,7 +218,7 @@ static void SetQualName ( XMP_StringPtr fullName, XML_Node * node )
node->ns.assign ( fullName, sepPos );
if ( node->ns == "http://purl.org/dc/1.1/" ) node->ns = "http://purl.org/dc/elements/1.1/";
- bool found = XMPMeta::GetNamespacePrefix ( node->ns.c_str(), &prefix, &prefixLen );
+ bool found = thiz->registeredNamespaces->GetPrefix ( node->ns.c_str(), &prefix, &prefixLen );
if ( ! found ) XMP_Throw ( "Unknown URI in Expat full name", kXMPErr_ExternalFailure );
node->nsPrefixLen = prefixLen; // ! Includes the ':'.
@@ -243,9 +254,7 @@ static void StartNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix, X
// As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/.
// Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace.
- #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning.
- ExpatAdapter * thiz = (ExpatAdapter*)userData;
- #endif
+ ExpatAdapter * thiz = (ExpatAdapter*)userData;
if ( prefix == 0 ) prefix = "_dflt_"; // Have default namespace.
if ( uri == 0 ) return; // Ignore, have xmlns:pre="", no URI to register.
@@ -258,7 +267,7 @@ static void StartNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix, X
#endif
if ( XMP_LitMatch ( uri, "http://purl.org/dc/1.1/" ) ) uri = "http://purl.org/dc/elements/1.1/";
- (void) XMPMeta::RegisterNamespace ( uri, prefix, &voidStringPtr, &voidStringLen );
+ (void) thiz->registeredNamespaces->Define ( uri, prefix, 0, 0 );
} // StartNamespaceDeclHandler
@@ -313,7 +322,7 @@ static void StartElementHandler ( void * userData, XMP_StringPtr name, XMP_Strin
XML_Node * parentNode = thiz->parseStack.back();
XML_Node * elemNode = new XML_Node ( parentNode, "", kElemNode );
- SetQualName ( name, elemNode );
+ SetQualName ( thiz, name, elemNode );
for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) {
@@ -321,7 +330,7 @@ static void StartElementHandler ( void * userData, XMP_StringPtr name, XMP_Strin
XMP_StringPtr attrValue = *(attr+1);
XML_Node * attrNode = new XML_Node ( elemNode, "", kAttrNode );
- SetQualName ( attrName, attrNode );
+ SetQualName ( thiz, attrName, attrNode );
attrNode->value = attrValue;
if ( attrNode->name == "xml:lang" ) NormalizeLangValue ( &attrNode->value );
elemNode->attrs.push_back ( attrNode );
diff --git a/source/XMPCore/ParseRDF.cpp b/source/XMPCore/ParseRDF.cpp
index 31fb2b9..9931194 100644
--- a/source/XMPCore/ParseRDF.cpp
+++ b/source/XMPCore/ParseRDF.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2004 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -490,30 +490,30 @@ AddQualifierNode ( XMP_Node * xmpParent, const XMP_VarString & name, const XMP_V
XMP_Node * newQual = 0;
- newQual = new XMP_Node ( xmpParent, name, value, kXMP_PropIsQualifier );
+ newQual = new XMP_Node ( xmpParent, name, value, kXMP_PropIsQualifier );
- if ( ! (isLang | isType) ) {
+ if ( ! (isLang | isType) ) {
+ xmpParent->qualifiers.push_back ( newQual );
+ } else if ( isLang ) {
+ if ( xmpParent->qualifiers.empty() ) {
xmpParent->qualifiers.push_back ( newQual );
- } else if ( isLang ) {
- if ( xmpParent->qualifiers.empty() ) {
- xmpParent->qualifiers.push_back ( newQual );
- } else {
- xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), newQual );
- }
- xmpParent->options |= kXMP_PropHasLang;
} else {
- XMP_Assert ( isType );
- if ( xmpParent->qualifiers.empty() ) {
- xmpParent->qualifiers.push_back ( newQual );
- } else {
- size_t offset = 0;
- if ( XMP_PropHasLang ( xmpParent->options ) ) offset = 1;
- xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin()+offset, newQual );
- }
- xmpParent->options |= kXMP_PropHasType;
+ xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), newQual );
}
+ xmpParent->options |= kXMP_PropHasLang;
+ } else {
+ XMP_Assert ( isType );
+ if ( xmpParent->qualifiers.empty() ) {
+ xmpParent->qualifiers.push_back ( newQual );
+ } else {
+ size_t offset = 0;
+ if ( XMP_PropHasLang ( xmpParent->options ) ) offset = 1;
+ xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin()+offset, newQual );
+ }
+ xmpParent->options |= kXMP_PropHasType;
+ }
- xmpParent->options |= kXMP_PropHasQualifiers;
+ xmpParent->options |= kXMP_PropHasQualifiers;
return newQual;
@@ -608,26 +608,25 @@ FixupQualifiedNode ( XMP_Node * xmpParent )
for ( childNum = 1, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) {
XMP_Node * currQual = xmpParent->children[childNum];
-
- bool isLang = (currQual->name == "xml:lang");
-
- currQual->options |= kXMP_PropIsQualifier;
- currQual->parent = xmpParent;
-
- if ( isLang ) {
- if ( xmpParent->options & kXMP_PropHasLang ) XMP_Throw ( "Duplicate xml:lang qualifier", kXMPErr_BadXMP );
- xmpParent->options |= kXMP_PropHasLang;
- } else if ( currQual->name == "rdf:type" ) {
- xmpParent->options |= kXMP_PropHasType;
- }
-
- if ( (! isLang) || xmpParent->qualifiers.empty() ) {
- xmpParent->qualifiers.push_back ( currQual );
- } else {
- xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), currQual );
- }
- xmpParent->children[childNum] = 0; // We just moved it to the qualifers.
+ bool isLang = (currQual->name == "xml:lang");
+ currQual->options |= kXMP_PropIsQualifier;
+ currQual->parent = xmpParent;
+
+ if ( isLang ) {
+ if ( xmpParent->options & kXMP_PropHasLang ) XMP_Throw ( "Duplicate xml:lang qualifier", kXMPErr_BadXMP );
+ xmpParent->options |= kXMP_PropHasLang;
+ } else if ( currQual->name == "rdf:type" ) {
+ xmpParent->options |= kXMP_PropHasType;
+ }
+
+ if ( (! isLang) || xmpParent->qualifiers.empty() ) {
+ xmpParent->qualifiers.push_back ( currQual );
+ } else {
+ xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), currQual );
+ }
+ xmpParent->children[childNum] = 0; // We just moved it to the qualifers.
+
}
if ( ! xmpParent->qualifiers.empty() ) xmpParent->options |= kXMP_PropHasQualifiers;
diff --git a/source/XMPCore/WXMPIterator.cpp b/source/XMPCore/WXMPIterator.cpp
index b52fa0d..6b0e69e 100644
--- a/source/XMPCore/WXMPIterator.cpp
+++ b/source/XMPCore/WXMPIterator.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
+// Copyright 2004 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -7,11 +7,13 @@
// =================================================================================================
#include "XMP_Environment.h" // ! This must be the first include!
-#include "XMPCore_Impl.hpp"
+#include "XMP_Const.h"
-#include "XMPIterator.hpp"
#include "client-glue/WXMPIterator.hpp"
+#include "XMPCore_Impl.hpp"
+#include "XMPIterator.hpp"
+
#if XMP_WinBuild
#pragma warning ( disable : 4101 ) // unreferenced local variable
#pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
@@ -36,18 +38,20 @@ WXMPIterator_PropCTor_1 ( XMPMetaRef xmpRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPIterator_PropCTor_1" )
+ XMP_ENTER_Static ( "WXMPIterator_PropCTor_1" ) // No lib object yet, use the static entry.
if ( schemaNS == 0 ) schemaNS = "";
if ( propName == 0 ) propName = "";
const XMPMeta & xmpObj = WtoXMPMeta_Ref ( xmpRef );
- XMPIterator * iter = new XMPIterator ( xmpObj, schemaNS, propName, options );
+ XMP_AutoLock metaLock ( &xmpObj.lock, kXMP_ReadLock );
+
+ XMPIterator * iter = new XMPIterator ( xmpObj, schemaNS, propName, options );
++iter->clientRefs;
XMP_Assert ( iter->clientRefs == 1 );
wResult->ptrResult = XMPIteratorRef ( iter );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -58,7 +62,7 @@ WXMPIterator_TableCTor_1 ( XMP_StringPtr schemaNS,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPIterator_TableCTor_1" )
+ XMP_ENTER_Static ( "WXMPIterator_TableCTor_1" ) // No lib object yet, use the static entry.
if ( schemaNS == 0 ) schemaNS = "";
if ( propName == 0 ) propName = "";
@@ -68,53 +72,39 @@ WXMPIterator_TableCTor_1 ( XMP_StringPtr schemaNS,
XMP_Assert ( iter->clientRefs == 1 );
wResult->ptrResult = XMPIteratorRef ( iter );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPIterator_IncrementRefCount_1 ( XMPIteratorRef iterRef )
+WXMPIterator_IncrementRefCount_1 ( XMPIteratorRef xmpObjRef )
{
WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER ( "WXMPIterator_IncrementRefCount_1" )
+ XMP_ENTER_ObjWrite ( XMPIterator, "WXMPIterator_IncrementRefCount_1" )
- XMPIterator * thiz = (XMPIterator*)iterRef;
-
++thiz->clientRefs;
XMP_Assert ( thiz->clientRefs > 1 );
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT_NoThrow
}
// -------------------------------------------------------------------------------------------------
void
-WXMPIterator_DecrementRefCount_1 ( XMPIteratorRef iterRef )
+WXMPIterator_DecrementRefCount_1 ( XMPIteratorRef xmpObjRef )
{
WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER ( "WXMPIterator_DecrementRefCount_1" )
+ XMP_ENTER_ObjWrite ( XMPIterator, "WXMPIterator_DecrementRefCount_1" )
- XMPIterator * thiz = (XMPIterator*)iterRef;
-
XMP_Assert ( thiz->clientRefs > 0 );
--thiz->clientRefs;
- if ( thiz->clientRefs <= 0 ) delete ( thiz );
-
- XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPIterator_Unlock_1 ( XMP_OptionBits options )
-{
- WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPIterator_Unlock_1" )
+ if ( thiz->clientRefs <= 0 ) {
+ objLock.Release();
+ delete ( thiz );
+ }
- XMPIterator::Unlock ( options );
-
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT_NoThrow
}
// =================================================================================================
@@ -122,61 +112,53 @@ WXMPIterator_Unlock_1 ( XMP_OptionBits options )
// =====================
void
-WXMPIterator_Next_1 ( XMPIteratorRef iterRef,
- XMP_StringPtr * schemaNS,
- XMP_StringLen * nsSize,
- XMP_StringPtr * propPath,
- XMP_StringLen * pathSize,
- XMP_StringPtr * propValue,
- XMP_StringLen * valueSize,
+WXMPIterator_Next_1 ( XMPIteratorRef xmpObjRef,
+ void * schemaNS,
+ void * propPath,
+ void * propValue,
XMP_OptionBits * propOptions,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPIterator_Next_1" )
-
- if ( schemaNS == 0 ) schemaNS = &voidStringPtr;
- if ( nsSize == 0 ) nsSize = &voidStringLen;
- if ( propPath == 0 ) propPath = &voidStringPtr;
- if ( pathSize == 0 ) pathSize = &voidStringLen;
- if ( propValue == 0 ) propValue = &voidStringPtr;
- if ( valueSize == 0 ) valueSize = &voidStringLen;
+ XMP_ENTER_ObjWrite ( XMPIterator, "WXMPIterator_Next_1" )
+
+ XMP_StringPtr schemaPtr = 0;
+ XMP_StringLen schemaLen = 0;
+ XMP_StringPtr pathPtr = 0;
+ XMP_StringLen pathLen = 0;
+ XMP_StringPtr valuePtr = 0;
+ XMP_StringLen valueLen = 0;
+
if ( propOptions == 0 ) propOptions = &voidOptionBits;
- XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef );
- XMP_Bool found = iter->Next ( schemaNS, nsSize, propPath, pathSize, propValue, valueSize, propOptions );
+ XMP_AutoLock metaLock ( &thiz->info.xmpObj->lock, kXMP_ReadLock, (thiz->info.xmpObj != 0) );
+
+ XMP_Bool found = thiz->Next ( &schemaPtr, &schemaLen, &pathPtr, &pathLen, &valuePtr, &valueLen, propOptions );
wResult->int32Result = found;
+
+ if ( found ) {
+ if ( schemaNS != 0 ) (*SetClientString) ( schemaNS, schemaPtr, schemaLen );
+ if ( propPath != 0 ) (*SetClientString) ( propPath, pathPtr, pathLen );
+ if ( propValue != 0 ) (*SetClientString) ( propValue, valuePtr, valueLen );
+ }
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPIterator_Skip_1 ( XMPIteratorRef iterRef,
+WXMPIterator_Skip_1 ( XMPIteratorRef xmpObjRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPIterator_Skip_1" )
-
- XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef );
- iter->Skip ( options );
+ XMP_ENTER_ObjWrite ( XMPIterator, "WXMPIterator_Skip_1" )
- XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_UnlockIter_1 ( XMPIteratorRef iterRef,
- XMP_OptionBits options )
-{
- WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_UnlockIter_1" )
+ XMP_AutoLock metaLock ( &thiz->info.xmpObj->lock, kXMP_ReadLock, (thiz->info.xmpObj != 0) );
- XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef );
- iter->UnlockIter ( options );
+ thiz->Skip ( options );
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT
}
// =================================================================================================
diff --git a/source/XMPCore/WXMPMeta.cpp b/source/XMPCore/WXMPMeta.cpp
index 4c95c5d..e7138e4 100644
--- a/source/XMPCore/WXMPMeta.cpp
+++ b/source/XMPCore/WXMPMeta.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2004 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -7,11 +7,13 @@
// =================================================================================================
#include "XMP_Environment.h" // ! This must be the first include!
-#include "XMPCore_Impl.hpp"
+#include "XMP_Const.h"
-#include "XMPMeta.hpp"
#include "client-glue/WXMPMeta.hpp"
+#include "XMPCore_Impl.hpp"
+#include "XMPMeta.hpp"
+
#if XMP_WinBuild
#pragma warning ( disable : 4101 ) // unreferenced local variable
#pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
@@ -34,11 +36,11 @@ extern "C" {
WXMPMeta_GetVersionInfo_1 ( XMP_VersionInfo * info )
{
WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_GetVersionInfo_1" )
+ XMP_ENTER_NoLock ( "WXMPMeta_GetVersionInfo_1" )
XMPMeta::GetVersionInfo ( info );
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT_NoThrow
}
// -------------------------------------------------------------------------------------------------
@@ -46,12 +48,11 @@ WXMPMeta_GetVersionInfo_1 ( XMP_VersionInfo * info )
/* class static */ void
WXMPMeta_Initialize_1 ( WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Initialize_1" )
+ XMP_ENTER_NoLock ( "WXMPMeta_Initialize_1" )
- bool ok = XMPMeta::Initialize();
- wResult->int32Result = ok;
+ wResult->int32Result = XMPMeta::Initialize();
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -59,11 +60,11 @@ WXMPMeta_Initialize_1 ( WXMP_Result * wResult )
WXMPMeta_Terminate_1()
{
WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Terminate_1" )
+ XMP_ENTER_NoLock ( "WXMPMeta_Terminate_1" )
XMPMeta::Terminate();
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT_NoThrow
}
// =================================================================================================
@@ -73,83 +74,61 @@ WXMPMeta_Terminate_1()
void
WXMPMeta_CTor_1 ( WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_CTor_1" )
+ XMP_ENTER_Static ( "WXMPMeta_CTor_1" ) // No lib object yet, use the static entry.
XMPMeta * xmpObj = new XMPMeta();
++xmpObj->clientRefs;
XMP_Assert ( xmpObj->clientRefs == 1 );
wResult->ptrResult = XMPMetaRef ( xmpObj );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_IncrementRefCount_1 ( XMPMetaRef xmpRef )
+WXMPMeta_IncrementRefCount_1 ( XMPMetaRef xmpObjRef )
{
WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER ( "WXMPMeta_IncrementRefCount_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_IncrementRefCount_1" )
- XMPMeta * thiz = (XMPMeta*)xmpRef;
-
++thiz->clientRefs;
XMP_Assert ( thiz->clientRefs > 0 );
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT_NoThrow
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DecrementRefCount_1 ( XMPMetaRef xmpRef )
+WXMPMeta_DecrementRefCount_1 ( XMPMetaRef xmpObjRef )
{
WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER ( "WXMPMeta_DecrementRefCount_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_DecrementRefCount_1" )
- XMPMeta * thiz = (XMPMeta*)xmpRef;
-
XMP_Assert ( thiz->clientRefs > 0 );
--thiz->clientRefs;
- if ( thiz->clientRefs <= 0 ) delete ( thiz );
+ if ( thiz->clientRefs <= 0 ) {
+ objLock.Release();
+ delete ( thiz );
+ }
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT_NoThrow
}
// =================================================================================================
// Class Static Wrappers
// =====================
-//
-// These are DLL-entry wrappers for class-static functions. They all follow a simple pattern:
-//
-// try
-// acquire toolbox lock
-// validate parameters
-// call through to the implementation
-// retain toolbox lock if necessary
-// catch anything and return an appropriate XMP_Error object
-// return null (no error if we get to here)
-//
-// The toolbox lock is acquired through a local wrapper object that automatically unlocks when the
-// try-block is exited. The lock must be retained if the function is returning a string result. The
-// output string is owned by the toolkit, the client must copy the string then release the lock.
-// The lock used here is the overall toolkit lock. For simplicity at this time the lock is a simple
-// mutual exclusion lock, we do not allow multiple concurrent readers.
-//
-// The one exception to this model is UnlockToolkit. It does not acquire the toolkit lock since this
-// is the function the client calls to release the lock after copying an output string!
-//
-// =================================================================================================
/* class static */ void
WXMPMeta_GetGlobalOptions_1 ( WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetGlobalOptions_1" )
+ XMP_ENTER_Static ( "WXMPMeta_GetGlobalOptions_1" )
XMP_OptionBits options = XMPMeta::GetGlobalOptions();
wResult->int32Result = options;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -158,11 +137,11 @@ WXMPMeta_GetGlobalOptions_1 ( WXMP_Result * wResult )
WXMPMeta_SetGlobalOptions_1 ( XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetGlobalOptions_1" )
+ XMP_ENTER_Static ( "WXMPMeta_SetGlobalOptions_1" )
XMPMeta::SetGlobalOptions ( options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -171,109 +150,85 @@ WXMPMeta_DumpNamespaces_1 ( XMP_TextOutputProc outProc,
void * refCon,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DumpNamespaces_1" )
+ XMP_ENTER_Static ( "WXMPMeta_DumpNamespaces_1" )
if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam );
XMP_Status status = XMPMeta::DumpNamespaces ( outProc, refCon );
wResult->int32Result = status;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
/* class static */ void
-WXMPMeta_DumpAliases_1 ( XMP_TextOutputProc outProc,
- void * refCon,
- WXMP_Result * wResult )
-{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DumpAliases_1" )
-
- if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam );
-
- XMP_Status status = XMPMeta::DumpAliases ( outProc, refCon );
- wResult->int32Result = status;
-
- XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_Unlock_1 ( XMP_OptionBits options )
-{
- WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Unlock_1" )
-
- XMPMeta::Unlock ( options );
-
- XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_RegisterNamespace_1 ( XMP_StringPtr namespaceURI,
- XMP_StringPtr suggestedPrefix,
- XMP_StringPtr * registeredPrefix,
- XMP_StringLen * prefixSize,
- WXMP_Result * wResult )
+WXMPMeta_RegisterNamespace_1 ( XMP_StringPtr namespaceURI,
+ XMP_StringPtr suggestedPrefix,
+ void * actualPrefix,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterNamespace_1" )
+ XMP_ENTER_Static ( "WXMPMeta_RegisterNamespace_1" )
if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema );
if ( (suggestedPrefix == 0) || (*suggestedPrefix == 0) ) XMP_Throw ( "Empty suggested prefix", kXMPErr_BadSchema );
- if ( registeredPrefix == 0 ) registeredPrefix = &voidStringPtr;
- if ( prefixSize == 0 ) prefixSize = &voidStringLen;
+ XMP_StringPtr prefixPtr = 0;
+ XMP_StringLen prefixSize = 0;
- bool prefixMatch = XMPMeta::RegisterNamespace ( namespaceURI, suggestedPrefix, registeredPrefix, prefixSize );
+ bool prefixMatch = XMPMeta::RegisterNamespace ( namespaceURI, suggestedPrefix, &prefixPtr, &prefixSize );
wResult->int32Result = prefixMatch;
+
+ if ( actualPrefix != 0 ) (*SetClientString) ( actualPrefix, prefixPtr, prefixSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned!
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
/* class static */ void
-WXMPMeta_GetNamespacePrefix_1 ( XMP_StringPtr namespaceURI,
- XMP_StringPtr * namespacePrefix,
- XMP_StringLen * prefixSize,
- WXMP_Result * wResult )
+WXMPMeta_GetNamespacePrefix_1 ( XMP_StringPtr namespaceURI,
+ void * namespacePrefix,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetNamespacePrefix_1" )
+ XMP_ENTER_Static ( "WXMPMeta_GetNamespacePrefix_1" )
if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema );
- if ( namespacePrefix == 0 ) namespacePrefix = &voidStringPtr;
- if ( prefixSize == 0 ) prefixSize = &voidStringLen;
+ XMP_StringPtr prefixPtr = 0;
+ XMP_StringLen prefixSize = 0;
- bool found = XMPMeta::GetNamespacePrefix ( namespaceURI, namespacePrefix, prefixSize );
+ bool found = XMPMeta::GetNamespacePrefix ( namespaceURI, &prefixPtr, &prefixSize );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ if ( found && (namespacePrefix != 0) ) (*SetClientString) ( namespacePrefix, prefixPtr, prefixSize );
+
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
/* class static */ void
-WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr namespacePrefix,
- XMP_StringPtr * namespaceURI,
- XMP_StringLen * uriSize,
- WXMP_Result * wResult )
+WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr namespacePrefix,
+ void * namespaceURI,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetNamespaceURI_1" )
+ XMP_ENTER_Static ( "WXMPMeta_GetNamespaceURI_1" )
if ( (namespacePrefix == 0) || (*namespacePrefix == 0) ) XMP_Throw ( "Empty namespace prefix", kXMPErr_BadSchema );
- if ( namespaceURI == 0 ) namespaceURI = &voidStringPtr;
- if ( uriSize == 0 ) uriSize = &voidStringLen;
+ XMP_StringPtr uriPtr = 0;
+ XMP_StringLen uriSize = 0;
- bool found = XMPMeta::GetNamespaceURI ( namespacePrefix, namespaceURI, uriSize );
+ bool found = XMPMeta::GetNamespaceURI ( namespacePrefix, &uriPtr, &uriSize );
wResult->int32Result = found;
+
+ if ( found && (namespaceURI != 0) ) (*SetClientString) ( namespaceURI, uriPtr, uriSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -282,263 +237,162 @@ WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr namespacePrefix,
WXMPMeta_DeleteNamespace_1 ( XMP_StringPtr namespaceURI,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteNamespace_1" )
+ XMP_ENTER_Static ( "WXMPMeta_DeleteNamespace_1" )
if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema );
XMPMeta::DeleteNamespace ( namespaceURI );
- XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_RegisterAlias_1 ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- XMP_StringPtr actualNS,
- XMP_StringPtr actualProp,
- XMP_OptionBits arrayForm,
- WXMP_Result * wResult )
-{
- XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterAlias_1" )
-
- if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema );
- if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath );
- if ( (actualNS == 0) || (*actualNS == 0) ) XMP_Throw ( "Empty actual namespace URI", kXMPErr_BadSchema );
- if ( (actualProp == 0) || (*actualProp == 0) ) XMP_Throw ( "Empty actual property name", kXMPErr_BadXPath );
-
- XMPMeta::RegisterAlias ( aliasNS, aliasProp, actualNS, actualProp, arrayForm );
-
- XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_ResolveAlias_1 ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- XMP_StringPtr * actualNS,
- XMP_StringLen * nsSize,
- XMP_StringPtr * actualProp,
- XMP_StringLen * propSize,
- XMP_OptionBits * arrayForm,
- WXMP_Result * wResult )
-{
- XMP_ENTER_WRAPPER ( "WXMPMeta_ResolveAlias_1" )
-
- if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema );
- if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath );
-
- if ( actualNS == 0 ) actualNS = &voidStringPtr;
- if ( nsSize == 0 ) nsSize = &voidStringLen;
- if ( actualProp == 0 ) actualProp = &voidStringPtr;
- if ( propSize == 0 ) propSize = &voidStringLen;
- if ( arrayForm == 0 ) arrayForm = &voidOptionBits;
-
- bool found = XMPMeta::ResolveAlias ( aliasNS, aliasProp, actualNS, nsSize, actualProp, propSize, arrayForm );
- wResult->int32Result = found;
-
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_DeleteAlias_1 ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- WXMP_Result * wResult )
-{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteAlias_1" )
-
- if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema );
- if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath );
-
- XMPMeta::DeleteAlias ( aliasNS, aliasProp );
-
- XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_RegisterStandardAliases_1 ( XMP_StringPtr schemaNS,
- WXMP_Result * wResult )
-{
- XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterStandardAliases_1" )
-
- if ( schemaNS == 0 ) schemaNS = "";
-
- XMPMeta::RegisterStandardAliases ( schemaNS );
-
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// =================================================================================================
// Class Method Wrappers
// =====================
-//
-// These are DLL-entry wrappers for the methods. They all follow a simple pattern:
-//
-// validate parameters
-// try
-// acquire object lock
-// call through to the implementation
-// retain object lock if necessary
-// catch anything and return an appropriate XMP_Error object
-// return null (no error if we get to here)
-//
-// The object lock is acquired through a local wrapper object that automatically unlocks when the
-// try-block is exited. The lock must be retained if the function is returning a string result. The
-// output string is owned by the object, the client must copy the string then release the lock. The
-// lock used here is the per-object lock. For simplicity at this time the lock is a simple mutual
-// exclusion lock, we do not allow multiple concurrent readers.
-//
-// The one exception to this model is UnlockObject. It does not acquire the object lock since this
-// is the function the client calls to release the lock after copying an output string!
-//
-// =================================================================================================
void
-WXMPMeta_GetProperty_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetProperty_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
- XMP_StringPtr * propValue,
- XMP_StringLen * valueSize,
+ void * propValue,
XMP_OptionBits * options,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- if ( propValue == 0 ) propValue = &voidStringPtr;
- if ( valueSize == 0 ) valueSize = &voidStringLen;
+ XMP_StringPtr valuePtr = 0;
+ XMP_StringLen valueSize = 0;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetProperty ( schemaNS, propName, propValue, valueSize, options );
+ bool found = thiz.GetProperty ( schemaNS, propName, &valuePtr, &valueSize, options );
wResult->int32Result = found;
+
+ if ( found && (propValue != 0) ) (*SetClientString) ( propValue, valuePtr, valueSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetArrayItem_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetArrayItem_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
- XMP_StringPtr * itemValue,
- XMP_StringLen * valueSize,
+ void * itemValue,
XMP_OptionBits * options,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetArrayItem_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetArrayItem_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
- if ( itemValue == 0 ) itemValue = &voidStringPtr;
- if ( valueSize == 0 ) valueSize = &voidStringLen;
+ XMP_StringPtr valuePtr = 0;
+ XMP_StringLen valueSize = 0;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, valueSize, options );
+ bool found = thiz.GetArrayItem ( schemaNS, arrayName, itemIndex, &valuePtr, &valueSize, options );
wResult->int32Result = found;
+
+ if ( found && (itemValue != 0) ) (*SetClientString) ( itemValue, valuePtr, valueSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetStructField_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetStructField_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
- XMP_StringPtr * fieldValue,
- XMP_StringLen * valueSize,
+ void * fieldValue,
XMP_OptionBits * options,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetStructField_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetStructField_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
- if ( fieldValue == 0 ) fieldValue = &voidStringPtr;
- if ( valueSize == 0 ) valueSize = &voidStringLen;
+ XMP_StringPtr valuePtr = 0;
+ XMP_StringLen valueSize = 0;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, valueSize, options );
+ bool found = thiz.GetStructField ( schemaNS, structName, fieldNS, fieldName, &valuePtr, &valueSize, options );
wResult->int32Result = found;
+
+ if ( found && (fieldValue != 0) ) (*SetClientString) ( fieldValue, valuePtr, valueSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetQualifier_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetQualifier_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
- XMP_StringPtr * qualValue,
- XMP_StringLen * valueSize,
+ void * qualValue,
XMP_OptionBits * options,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetQualifier_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetQualifier_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
- if ( qualValue == 0 ) qualValue = &voidStringPtr;
- if ( valueSize == 0 ) valueSize = &voidStringLen;
+ XMP_StringPtr valuePtr = 0;
+ XMP_StringLen valueSize = 0;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, valueSize, options );
+ bool found = thiz.GetQualifier ( schemaNS, propName, qualNS, qualName, &valuePtr, &valueSize, options );
wResult->int32Result = found;
+
+ if ( found && (qualValue != 0) ) (*SetClientString) ( qualValue, valuePtr, valueSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetProperty_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetProperty_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr propValue,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetProperty_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetProperty ( schemaNS, propName, propValue, options );
+ thiz->SetProperty ( schemaNS, propName, propValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetArrayItem_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetArrayItem_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
@@ -546,21 +400,20 @@ WXMPMeta_SetArrayItem_1 ( XMPMetaRef xmpRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetArrayItem_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetArrayItem_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, options );
+ thiz->SetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_AppendArrayItem_1 ( XMPMetaRef xmpRef,
+WXMPMeta_AppendArrayItem_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_OptionBits arrayOptions,
@@ -568,21 +421,20 @@ WXMPMeta_AppendArrayItem_1 ( XMPMetaRef xmpRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_AppendArrayItem_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_AppendArrayItem_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->AppendArrayItem ( schemaNS, arrayName, arrayOptions, itemValue, options );
+ thiz->AppendArrayItem ( schemaNS, arrayName, arrayOptions, itemValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetStructField_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetStructField_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
@@ -591,23 +443,22 @@ WXMPMeta_SetStructField_1 ( XMPMetaRef xmpRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetStructField_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetStructField_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, options );
+ thiz->SetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetQualifier_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetQualifier_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
@@ -616,233 +467,227 @@ WXMPMeta_SetQualifier_1 ( XMPMetaRef xmpRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetQualifier_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetQualifier_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, options );
+ thiz->SetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DeleteProperty_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DeleteProperty_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteProperty_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_DeleteProperty_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->DeleteProperty ( schemaNS, propName );
+ thiz->DeleteProperty ( schemaNS, propName );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DeleteArrayItem_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DeleteArrayItem_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteArrayItem_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_DeleteArrayItem_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->DeleteArrayItem ( schemaNS, arrayName, itemIndex );
+ thiz->DeleteArrayItem ( schemaNS, arrayName, itemIndex );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DeleteStructField_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DeleteStructField_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteStructField_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_DeleteStructField_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->DeleteStructField ( schemaNS, structName, fieldNS, fieldName );
+ thiz->DeleteStructField ( schemaNS, structName, fieldNS, fieldName );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DeleteQualifier_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DeleteQualifier_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteQualifier_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_DeleteQualifier_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->DeleteQualifier ( schemaNS, propName, qualNS, qualName );
+ thiz->DeleteQualifier ( schemaNS, propName, qualNS, qualName );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DoesPropertyExist_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DoesPropertyExist_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DoesPropertyExist_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_DoesPropertyExist_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.DoesPropertyExist ( schemaNS, propName );
+ bool found = thiz.DoesPropertyExist ( schemaNS, propName );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DoesArrayItemExist_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DoesArrayItemExist_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DoesArrayItemExist_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_DoesArrayItemExist_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.DoesArrayItemExist ( schemaNS, arrayName, itemIndex );
+ bool found = thiz.DoesArrayItemExist ( schemaNS, arrayName, itemIndex );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DoesStructFieldExist_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DoesStructFieldExist_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DoesStructFieldExist_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_DoesStructFieldExist_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.DoesStructFieldExist ( schemaNS, structName, fieldNS, fieldName );
+ bool found = thiz.DoesStructFieldExist ( schemaNS, structName, fieldNS, fieldName );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DoesQualifierExist_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DoesQualifierExist_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DoesQualifierExist_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_DoesQualifierExist_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.DoesQualifierExist ( schemaNS, propName, qualNS, qualName );
+ bool found = thiz.DoesQualifierExist ( schemaNS, propName, qualNS, qualName );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetLocalizedText_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetLocalizedText_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_StringPtr genericLang,
XMP_StringPtr specificLang,
- XMP_StringPtr * actualLang,
- XMP_StringLen * langSize,
- XMP_StringPtr * itemValue,
- XMP_StringLen * valueSize,
+ void * actualLang,
+ void * itemValue,
XMP_OptionBits * options,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetLocalizedText_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetLocalizedText_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
if ( genericLang == 0 ) genericLang = "";
if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam );
- if ( actualLang == 0 ) actualLang = &voidStringPtr;
- if ( langSize == 0 ) langSize = &voidStringLen;
- if ( itemValue == 0 ) itemValue = &voidStringPtr;
- if ( valueSize == 0 ) valueSize = &voidStringLen;
+ XMP_StringPtr langPtr = 0;
+ XMP_StringLen langSize = 0;
+ XMP_StringPtr valuePtr = 0;
+ XMP_StringLen valueSize = 0;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetLocalizedText ( schemaNS, arrayName, genericLang, specificLang,
- actualLang, langSize, itemValue, valueSize, options );
+ bool found = thiz.GetLocalizedText ( schemaNS, arrayName, genericLang, specificLang,
+ &langPtr, &langSize, &valuePtr, &valueSize, options );
wResult->int32Result = found;
+
+ if ( found ) {
+ if ( actualLang != 0 ) (*SetClientString) ( actualLang, langPtr, langSize );
+ if ( itemValue != 0 ) (*SetClientString) ( itemValue, valuePtr, valueSize );
+ }
- XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetLocalizedText_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetLocalizedText_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_StringPtr genericLang,
@@ -851,7 +696,7 @@ WXMPMeta_SetLocalizedText_1 ( XMPMetaRef xmpRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetLocalizedText_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetLocalizedText_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
@@ -859,23 +704,43 @@ WXMPMeta_SetLocalizedText_1 ( XMPMetaRef xmpRef,
if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam );
if ( itemValue == 0 ) itemValue = "";
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetLocalizedText ( schemaNS, arrayName, genericLang, specificLang, itemValue, options );
+ thiz->SetLocalizedText ( schemaNS, arrayName, genericLang, specificLang, itemValue, options );
+
+ XMP_EXIT
+}
+
+void
+WXMPMeta_DeleteLocalizedText_1 ( XMPMetaRef xmpObjRef,
+ XMP_StringPtr schemaNS,
+ XMP_StringPtr arrayName,
+ XMP_StringPtr genericLang,
+ XMP_StringPtr specificLang,
+ WXMP_Result * wResult )
+{
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_DeleteLocalizedText_1" )
- XMP_EXIT_WRAPPER
+ if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
+ if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
+ if ( genericLang == 0 ) genericLang = "";
+ if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam );
+
+ thiz->DeleteLocalizedText ( schemaNS, arrayName, genericLang, specificLang );
+
+ XMP_EXIT
}
+
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_Bool * propValue,
XMP_OptionBits * options,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Bool_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_Bool_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
@@ -883,26 +748,25 @@ WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef xmpRef,
if ( propValue == 0 ) propValue = &voidByte;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
bool value;
- bool found = meta.GetProperty_Bool ( schemaNS, propName, &value, options );
+ bool found = thiz.GetProperty_Bool ( schemaNS, propName, &value, options );
if ( propValue != 0 ) *propValue = value;
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetProperty_Int_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetProperty_Int_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_Int32 * propValue,
XMP_OptionBits * options,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Int_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_Int_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
@@ -910,24 +774,23 @@ WXMPMeta_GetProperty_Int_1 ( XMPMetaRef xmpRef,
if ( propValue == 0 ) propValue = &voidInt32;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetProperty_Int ( schemaNS, propName, propValue, options );
+ bool found = thiz.GetProperty_Int ( schemaNS, propName, propValue, options );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef xmpRef,
- XMP_StringPtr schemaNS,
- XMP_StringPtr propName,
- XMP_Int64 * propValue,
+WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef xmpObjRef,
+ XMP_StringPtr schemaNS,
+ XMP_StringPtr propName,
+ XMP_Int64 * propValue,
XMP_OptionBits * options,
- WXMP_Result * wResult ) /* const */
+ WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Int64_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_Int64_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
@@ -935,24 +798,23 @@ WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef xmpRef,
if ( propValue == 0 ) propValue = &voidInt64;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetProperty_Int64 ( schemaNS, propName, propValue, options );
+ bool found = thiz.GetProperty_Int64 ( schemaNS, propName, propValue, options );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetProperty_Float_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetProperty_Float_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
double * propValue,
XMP_OptionBits * options,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Float_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_Float_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
@@ -960,24 +822,23 @@ WXMPMeta_GetProperty_Float_1 ( XMPMetaRef xmpRef,
if ( propValue == 0 ) propValue = &voidDouble;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetProperty_Float ( schemaNS, propName, propValue, options );
+ bool found = thiz.GetProperty_Float ( schemaNS, propName, propValue, options );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetProperty_Date_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetProperty_Date_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_DateTime * propValue,
XMP_OptionBits * options,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Date_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetProperty_Date_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
@@ -985,326 +846,295 @@ WXMPMeta_GetProperty_Date_1 ( XMPMetaRef xmpRef,
if ( propValue == 0 ) propValue = &voidDateTime;
if ( options == 0 ) options = &voidOptionBits;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- bool found = meta.GetProperty_Date ( schemaNS, propName, propValue, options );
+ bool found = thiz.GetProperty_Date ( schemaNS, propName, propValue, options );
wResult->int32Result = found;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetProperty_Bool_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetProperty_Bool_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_Bool propValue,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Bool_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetProperty_Bool_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetProperty_Bool ( schemaNS, propName, propValue, options );
+ thiz->SetProperty_Bool ( schemaNS, propName, propValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetProperty_Int_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetProperty_Int_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_Int32 propValue,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Int_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetProperty_Int_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetProperty_Int ( schemaNS, propName, propValue, options );
+ thiz->SetProperty_Int ( schemaNS, propName, propValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetProperty_Int64_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetProperty_Int64_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_Int64 propValue,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Int64_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetProperty_Int64_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetProperty_Int64 ( schemaNS, propName, propValue, options );
+ thiz->SetProperty_Int64 ( schemaNS, propName, propValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetProperty_Float_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetProperty_Float_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
double propValue,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Float_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetProperty_Float_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetProperty_Float ( schemaNS, propName, propValue, options );
+ thiz->SetProperty_Float ( schemaNS, propName, propValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetProperty_Date_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetProperty_Date_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
const XMP_DateTime & propValue,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Date_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetProperty_Date_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetProperty_Date ( schemaNS, propName, propValue, options );
+ thiz->SetProperty_Date ( schemaNS, propName, propValue, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_DumpObject_1 ( XMPMetaRef xmpRef,
+WXMPMeta_DumpObject_1 ( XMPMetaRef xmpObjRef,
XMP_TextOutputProc outProc,
void * refCon,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_DumpObject_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_DumpObject_1" )
if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam );
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- XMP_Status status = meta.DumpObject ( outProc, refCon );
- wResult->int32Result = status;
+ thiz.DumpObject ( outProc, refCon );
+ wResult->int32Result = 0;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_Sort_1 ( XMPMetaRef xmpRef,
+WXMPMeta_Sort_1 ( XMPMetaRef xmpObjRef,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_Sort_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_Sort_1" )
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->Sort();
+ thiz->Sort();
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_Erase_1 ( XMPMetaRef xmpRef,
+WXMPMeta_Erase_1 ( XMPMetaRef xmpObjRef,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_Erase_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_Erase_1" )
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->Erase();
+ thiz->Erase();
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_Clone_1 ( XMPMetaRef xmpRef,
+WXMPMeta_Clone_1 ( XMPMetaRef xmpObjRef,
XMP_OptionBits options,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_Clone_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_Clone_1" )
- const XMPMeta & xOriginal = WtoXMPMeta_Ref ( xmpRef );
- XMPMeta * xClone = new XMPMeta;
- xOriginal.Clone ( xClone, options );
+ XMPMeta * xClone = new XMPMeta; // ! Don't need an output lock, final ref assignment in client glue.
+ thiz.Clone ( xClone, options );
XMP_Assert ( xClone->clientRefs == 0 ); // ! Gets incremented in TXMPMeta::Clone.
wResult->ptrResult = xClone;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_CountArrayItems_1 ( XMPMetaRef xmpRef,
+WXMPMeta_CountArrayItems_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_CountArrayItems_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_CountArrayItems_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- XMP_Index count = meta.CountArrayItems ( schemaNS, arrayName );
+ XMP_Index count = thiz.CountArrayItems ( schemaNS, arrayName );
wResult->int32Result = count;
- XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_UnlockObject_1 ( XMPMetaRef xmpRef,
- XMP_OptionBits options ) /* const */
-{
- WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_UnlockObject_1" )
-
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- meta.UnlockObject ( options );
-
- XMP_EXIT_WRAPPER_NO_THROW
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetObjectName_1 ( XMPMetaRef xmpRef,
- XMP_StringPtr * namePtr,
- XMP_StringLen * nameLen,
- WXMP_Result * wResult ) /* const */
+WXMPMeta_GetObjectName_1 ( XMPMetaRef xmpObjRef,
+ void * objName,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetObjectName_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetObjectName_1" )
- if ( namePtr == 0 ) namePtr = &voidStringPtr;
- if ( nameLen == 0 ) nameLen = &voidStringLen;
+ XMP_StringPtr namePtr = 0;
+ XMP_StringLen nameSize = 0;
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- meta.GetObjectName ( namePtr, nameLen );
+ thiz.GetObjectName ( &namePtr, &nameSize );
+ if ( objName != 0 ) (*SetClientString) ( objName, namePtr, nameSize );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned!
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetObjectName_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetObjectName_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr name,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetObjectName_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetObjectName_1" )
if ( name == 0 ) name = "";
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetObjectName ( name );
+ thiz->SetObjectName ( name );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_GetObjectOptions_1 ( XMPMetaRef xmpRef,
+WXMPMeta_GetObjectOptions_1 ( XMPMetaRef xmpObjRef,
WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_GetObjectOptions_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_GetObjectOptions_1" )
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- XMP_OptionBits options = meta.GetObjectOptions();
+ XMP_OptionBits options = thiz.GetObjectOptions();
wResult->int32Result = options;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SetObjectOptions_1 ( XMPMetaRef xmpRef,
+WXMPMeta_SetObjectOptions_1 ( XMPMetaRef xmpObjRef,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SetObjectOptions_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_SetObjectOptions_1" )
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->SetObjectOptions ( options );
+ thiz->SetObjectOptions ( options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_ParseFromBuffer_1 ( XMPMetaRef xmpRef,
+WXMPMeta_ParseFromBuffer_1 ( XMPMetaRef xmpObjRef,
XMP_StringPtr buffer,
XMP_StringLen bufferSize,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_ParseFromBuffer_1" )
+ XMP_ENTER_ObjWrite ( XMPMeta, "WXMPMeta_ParseFromBuffer_1" )
- XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
- meta->ParseFromBuffer ( buffer, bufferSize, options );
+ thiz->ParseFromBuffer ( buffer, bufferSize, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef xmpRef,
- XMP_StringPtr * rdfString,
- XMP_StringLen * rdfSize,
- XMP_OptionBits options,
- XMP_StringLen padding,
- XMP_StringPtr newline,
- XMP_StringPtr indent,
- XMP_Index baseIndent,
- WXMP_Result * wResult ) /* const */
+WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef xmpObjRef,
+ void * pktString,
+ XMP_OptionBits options,
+ XMP_StringLen padding,
+ XMP_StringPtr newline,
+ XMP_StringPtr indent,
+ XMP_Index baseIndent,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult ) /* const */
{
- XMP_ENTER_WRAPPER ( "WXMPMeta_SerializeToBuffer_1" )
+ XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_SerializeToBuffer_1" )
- if ( rdfString == 0 ) rdfString = &voidStringPtr;
- if ( rdfSize == 0 ) rdfSize = &voidStringLen;
+ XMP_VarString localStr;
if ( newline == 0 ) newline = "";
if ( indent == 0 ) indent = "";
- const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
- meta.SerializeToBuffer ( rdfString, rdfSize, options, padding, newline, indent, baseIndent );
+ thiz.SerializeToBuffer ( &localStr, options, padding, newline, indent, baseIndent );
+ if ( pktString != 0 ) (*SetClientString) ( pktString, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned!
+ XMP_EXIT
}
// =================================================================================================
diff --git a/source/XMPCore/WXMPUtils.cpp b/source/XMPCore/WXMPUtils.cpp
index dac093a..b8a96ff 100644
--- a/source/XMPCore/WXMPUtils.cpp
+++ b/source/XMPCore/WXMPUtils.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2004 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -9,11 +9,13 @@
// *** Should change "type * inParam" to "type & inParam"
#include "XMP_Environment.h" // ! This must be the first include!
-#include "XMPCore_Impl.hpp"
+#include "XMP_Const.h"
-#include "XMPUtils.hpp"
#include "client-glue/WXMPUtils.hpp"
+#include "XMPCore_Impl.hpp"
+#include "XMPUtils.hpp"
+
#if XMP_WinBuild
#pragma warning ( disable : 4101 ) // unreferenced local variable
#pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
@@ -32,37 +34,24 @@ extern "C" {
// =====================
void
-WXMPUtils_Unlock_1 ( XMP_OptionBits options )
-{
- WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro.
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_Unlock_1" )
-
- XMPUtils::Unlock ( options );
-
- XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// =================================================================================================
-
-void
WXMPUtils_ComposeArrayItemPath_1 ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize,
+ void * itemPath,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeArrayItemPath_1" )
-
+ XMP_ENTER_Static ( "WXMPUtils_ComposeArrayItemPath_1" )
+
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
- if ( fullPath == 0 ) fullPath = &voidStringPtr;
- if ( pathSize == 0 ) pathSize = &voidStringLen;
- XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, fullPath, pathSize );
+ XMP_VarString localStr;
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &localStr );
+ if ( itemPath != 0 ) (*SetClientString) ( itemPath, localStr.c_str(), localStr.size() );
+
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -72,23 +61,23 @@ WXMPUtils_ComposeStructFieldPath_1 ( XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize,
+ void * fieldPath,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeStructFieldPath_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ComposeStructFieldPath_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-
- if ( fullPath == 0 ) fullPath = &voidStringPtr;
- if ( pathSize == 0 ) pathSize = &voidStringLen;
- XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, fullPath, pathSize );
+ XMP_VarString localStr;
+
+ XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &localStr );
+ if ( fieldPath != 0 ) (*SetClientString) ( fieldPath, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -98,23 +87,23 @@ WXMPUtils_ComposeQualifierPath_1 ( XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize,
+ void * qualPath,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeQualifierPath_1" )
-
+ XMP_ENTER_Static ( "WXMPUtils_ComposeQualifierPath_1" )
+
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
-
- if ( fullPath == 0 ) fullPath = &voidStringPtr;
- if ( pathSize == 0 ) pathSize = &voidStringLen;
- XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, fullPath, pathSize );
+ XMP_VarString localStr;
+
+ XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &localStr );
+ if ( qualPath != 0 ) (*SetClientString) ( qualPath, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -123,22 +112,22 @@ void
WXMPUtils_ComposeLangSelector_1 ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_StringPtr langName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize,
+ void * selPath,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeLangSelector_1" )
-
+ XMP_ENTER_Static ( "WXMPUtils_ComposeLangSelector_1" )
+
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
if ( (langName == 0) || (*langName == 0) ) XMP_Throw ( "Empty language name", kXMPErr_BadParam );
-
- if ( fullPath == 0 ) fullPath = &voidStringPtr;
- if ( pathSize == 0 ) pathSize = &voidStringLen;
- XMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName, fullPath, pathSize );
+ XMP_VarString localStr;
+
+ XMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName, &localStr );
+ if ( selPath != 0 ) (*SetClientString) ( selPath, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -149,123 +138,123 @@ WXMPUtils_ComposeFieldSelector_1 ( XMP_StringPtr schemaNS,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
XMP_StringPtr fieldValue,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize,
+ void * selPath,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeFieldSelector_1" )
-
+ XMP_ENTER_Static ( "WXMPUtils_ComposeFieldSelector_1" )
+
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
if ( fieldValue == 0 ) fieldValue = "";
-
- if ( fullPath == 0 ) fullPath = &voidStringPtr;
- if ( pathSize == 0 ) pathSize = &voidStringLen;
- XMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, fullPath, pathSize );
+ XMP_VarString localStr;
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, &localStr );
+ if ( selPath != 0 ) (*SetClientString) ( selPath, localStr.c_str(), localStr.size() );
+
+ XMP_EXIT
}
// =================================================================================================
void
-WXMPUtils_ConvertFromBool_1 ( XMP_Bool binValue,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize,
- WXMP_Result * wResult )
+WXMPUtils_ConvertFromBool_1 ( XMP_Bool binValue,
+ void * strValue,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromBool_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertFromBool_1" )
- if ( strValue == 0 ) strValue = &voidStringPtr;
- if ( strSize == 0 ) strSize = &voidStringLen;
+ XMP_VarString localStr;
- XMPUtils::ConvertFromBool ( binValue, strValue, strSize );
+ XMPUtils::ConvertFromBool ( binValue, &localStr );
+ if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPUtils_ConvertFromInt_1 ( XMP_Int32 binValue,
- XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize,
- WXMP_Result * wResult )
+WXMPUtils_ConvertFromInt_1 ( XMP_Int32 binValue,
+ XMP_StringPtr format,
+ void * strValue,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromInt_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertFromInt_1" )
if ( format == 0 ) format = "";
-
- if ( strValue == 0 ) strValue = &voidStringPtr;
- if ( strSize == 0 ) strSize = &voidStringLen;
- XMPUtils::ConvertFromInt ( binValue, format, strValue, strSize );
+ XMP_VarString localStr;
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMPUtils::ConvertFromInt ( binValue, format, &localStr );
+ if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() );
+
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPUtils_ConvertFromInt64_1 ( XMP_Int64 binValue,
- XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize,
- WXMP_Result * wResult )
+WXMPUtils_ConvertFromInt64_1 ( XMP_Int64 binValue,
+ XMP_StringPtr format,
+ void * strValue,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromInt64_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertFromInt64_1" )
if ( format == 0 ) format = "";
-
- if ( strValue == 0 ) strValue = &voidStringPtr;
- if ( strSize == 0 ) strSize = &voidStringLen;
- XMPUtils::ConvertFromInt64 ( binValue, format, strValue, strSize );
+ XMP_VarString localStr;
+
+ XMPUtils::ConvertFromInt64 ( binValue, format, &localStr );
+ if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPUtils_ConvertFromFloat_1 ( double binValue,
- XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize,
- WXMP_Result * wResult )
+WXMPUtils_ConvertFromFloat_1 ( double binValue,
+ XMP_StringPtr format,
+ void * strValue,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromFloat_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertFromFloat_1" )
if ( format == 0 ) format = "";
-
- if ( strValue == 0 ) strValue = &voidStringPtr;
- if ( strSize == 0 ) strSize = &voidStringLen;
- XMPUtils::ConvertFromFloat ( binValue, format, strValue, strSize );
+ XMP_VarString localStr;
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMPUtils::ConvertFromFloat ( binValue, format, &localStr );
+ if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() );
+
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
WXMPUtils_ConvertFromDate_1 ( const XMP_DateTime & binValue,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize,
+ void * strValue,
+ SetClientStringProc SetClientString,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromDate_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertFromDate_1" )
- if ( strValue == 0 ) strValue = &voidStringPtr;
- if ( strSize == 0 ) strSize = &voidStringLen;
+ XMP_VarString localStr;
- XMPUtils::ConvertFromDate( binValue, strValue, strSize );
+ XMPUtils::ConvertFromDate( binValue, &localStr );
+ if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// =================================================================================================
@@ -274,13 +263,13 @@ void
WXMPUtils_ConvertToBool_1 ( XMP_StringPtr strValue,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToBool_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToBool_1" )
if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
XMP_Bool result = XMPUtils::ConvertToBool ( strValue );
wResult->int32Result = result;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -289,13 +278,13 @@ void
WXMPUtils_ConvertToInt_1 ( XMP_StringPtr strValue,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToInt_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToInt_1" )
if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
XMP_Int32 result = XMPUtils::ConvertToInt ( strValue );
wResult->int32Result = result;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -304,13 +293,13 @@ void
WXMPUtils_ConvertToInt64_1 ( XMP_StringPtr strValue,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToInt64_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToInt64_1" )
if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
XMP_Int64 result = XMPUtils::ConvertToInt64 ( strValue );
wResult->int64Result = result;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -319,13 +308,13 @@ void
WXMPUtils_ConvertToFloat_1 ( XMP_StringPtr strValue,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToFloat_1")
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToFloat_1")
if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
double result = XMPUtils::ConvertToFloat ( strValue );
wResult->floatResult = result;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -335,12 +324,12 @@ WXMPUtils_ConvertToDate_1 ( XMP_StringPtr strValue,
XMP_DateTime * binValue,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToDate_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToDate_1" )
if ( binValue == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); // ! Pointer is from the client.
XMPUtils::ConvertToDate ( strValue, binValue );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// =================================================================================================
@@ -349,12 +338,12 @@ void
WXMPUtils_CurrentDateTime_1 ( XMP_DateTime * time,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_CurrentDateTime_1" )
-
+ XMP_ENTER_Static ( "WXMPUtils_CurrentDateTime_1" )
+
if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
XMPUtils::CurrentDateTime ( time );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -363,12 +352,12 @@ void
WXMPUtils_SetTimeZone_1 ( XMP_DateTime * time,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_SetTimeZone_1" )
+ XMP_ENTER_Static ( "WXMPUtils_SetTimeZone_1" )
if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
XMPUtils::SetTimeZone ( time );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -377,12 +366,12 @@ void
WXMPUtils_ConvertToUTCTime_1 ( XMP_DateTime * time,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToUTCTime_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToUTCTime_1" )
if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
XMPUtils::ConvertToUTCTime ( time );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -391,12 +380,12 @@ void
WXMPUtils_ConvertToLocalTime_1 ( XMP_DateTime * time,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToLocalTime_1" )
+ XMP_ENTER_Static ( "WXMPUtils_ConvertToLocalTime_1" )
if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
XMPUtils::ConvertToLocalTime ( time );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -406,77 +395,77 @@ WXMPUtils_CompareDateTime_1 ( const XMP_DateTime & left,
const XMP_DateTime & right,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_CompareDateTime_1" )
+ XMP_ENTER_Static ( "WXMPUtils_CompareDateTime_1" )
int result = XMPUtils::CompareDateTime ( left, right );
wResult->int32Result = result;
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// =================================================================================================
void
-WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr rawStr,
- XMP_StringLen rawLen,
- XMP_StringPtr * encodedStr,
- XMP_StringLen * encodedLen,
- WXMP_Result * wResult )
+WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr rawStr,
+ XMP_StringLen rawLen,
+ void * encodedStr,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_EncodeToBase64_1" )
-
- if ( encodedStr == 0 ) encodedStr = &voidStringPtr;
- if ( encodedLen == 0 ) encodedLen = &voidStringLen;
+ XMP_ENTER_Static ( "WXMPUtils_EncodeToBase64_1" )
+
+ XMP_VarString localStr;
- XMPUtils::EncodeToBase64 ( rawStr, rawLen, encodedStr, encodedLen );
+ XMPUtils::EncodeToBase64 ( rawStr, rawLen, &localStr );
+ if ( encodedStr != 0 ) (*SetClientString) ( encodedStr, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
void
-WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr encodedStr,
- XMP_StringLen encodedLen,
- XMP_StringPtr * rawStr,
- XMP_StringLen * rawLen,
- WXMP_Result * wResult )
+WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr encodedStr,
+ XMP_StringLen encodedLen,
+ void * rawStr,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_DecodeFromBase64_1" )
+ XMP_ENTER_Static ( "WXMPUtils_DecodeFromBase64_1" )
- if ( rawStr == 0 ) rawStr = &voidStringPtr;
- if ( rawLen == 0 ) rawLen = &voidStringLen;
+ XMP_VarString localStr;
- XMPUtils::DecodeFromBase64 ( encodedStr, encodedLen, rawStr, rawLen );
+ XMPUtils::DecodeFromBase64 ( encodedStr, encodedLen, &localStr );
+ if ( rawStr != 0 ) (*SetClientString) ( rawStr, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// =================================================================================================
void
-WXMPUtils_PackageForJPEG_1 ( XMPMetaRef wxmpObj,
- XMP_StringPtr * stdStr,
- XMP_StringLen * stdLen,
- XMP_StringPtr * extStr,
- XMP_StringLen * extLen,
- XMP_StringPtr * digestStr,
- XMP_StringLen * digestLen,
- WXMP_Result * wResult )
+WXMPUtils_PackageForJPEG_1 ( XMPMetaRef wxmpObj,
+ void * stdStr,
+ void * extStr,
+ void * digestStr,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_PackageForJPEG_1" )
+ XMP_ENTER_Static ( "WXMPUtils_PackageForJPEG_1" )
- if ( stdStr == 0 ) stdStr = &voidStringPtr;
- if ( stdLen == 0 ) stdLen = &voidStringLen;
- if ( extStr == 0 ) extStr = &voidStringPtr;
- if ( extLen == 0 ) extLen = &voidStringLen;
- if ( digestStr == 0 ) digestStr = &voidStringPtr;
- if ( digestLen == 0 ) digestLen = &voidStringLen;
+ XMP_VarString localStdStr;
+ XMP_VarString localExtStr;
+ XMP_VarString localDigestStr;
const XMPMeta & xmpObj = WtoXMPMeta_Ref ( wxmpObj );
- XMPUtils::PackageForJPEG ( xmpObj, stdStr, stdLen, extStr, extLen, digestStr, digestLen );
+ XMP_AutoLock metaLock ( &xmpObj.lock, kXMP_ReadLock );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMPUtils::PackageForJPEG ( xmpObj, &localStdStr, &localExtStr, &localDigestStr );
+ if ( stdStr != 0 ) (*SetClientString) ( stdStr, localStdStr.c_str(), localStdStr.size() );
+ if ( extStr != 0 ) (*SetClientString) ( extStr, localExtStr.c_str(), localExtStr.size() );
+ if ( digestStr != 0 ) (*SetClientString) ( digestStr, localDigestStr.c_str(), localDigestStr.size() );
+
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -486,45 +475,52 @@ WXMPUtils_MergeFromJPEG_1 ( XMPMetaRef wfullXMP,
XMPMetaRef wextendedXMP,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_MergeFromJPEG_1" )
+ XMP_ENTER_Static ( "WXMPUtils_MergeFromJPEG_1" )
if ( wfullXMP == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
+ if ( wfullXMP == wextendedXMP ) XMP_Throw ( "Full and extended XMP pointers match", kXMPErr_BadParam );
XMPMeta * fullXMP = WtoXMPMeta_Ptr ( wfullXMP );
+ XMP_AutoLock fullXMPLock ( &fullXMP->lock, kXMP_WriteLock );
+
const XMPMeta & extendedXMP = WtoXMPMeta_Ref ( wextendedXMP );
+ XMP_AutoLock extendedXMPLock ( &extendedXMP.lock, kXMP_ReadLock );
+
XMPUtils::MergeFromJPEG ( fullXMP, extendedXMP );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// =================================================================================================
void
-WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef wxmpObj,
- XMP_StringPtr schemaNS,
- XMP_StringPtr arrayName,
- XMP_StringPtr separator,
- XMP_StringPtr quotes,
- XMP_OptionBits options,
- XMP_StringPtr * catedStr,
- XMP_StringLen * catedLen,
- WXMP_Result * wResult )
+WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef wxmpObj,
+ XMP_StringPtr schemaNS,
+ XMP_StringPtr arrayName,
+ XMP_StringPtr separator,
+ XMP_StringPtr quotes,
+ XMP_OptionBits options,
+ void * catedStr,
+ SetClientStringProc SetClientString,
+ WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_CatenateArrayItems_1" )
+ XMP_ENTER_Static ( "WXMPUtils_CatenateArrayItems_1" )
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
+
if ( separator == 0 ) separator = "; ";
if ( quotes == 0 ) quotes = "\"";
-
- if ( catedStr == 0 ) catedStr = &voidStringPtr;
- if ( catedLen == 0 ) catedLen = &voidStringLen;
+
+ XMP_VarString localStr;
const XMPMeta & xmpObj = WtoXMPMeta_Ref ( wxmpObj );
- XMPUtils::CatenateArrayItems ( xmpObj, schemaNS, arrayName, separator, quotes, options, catedStr, catedLen );
+ XMP_AutoLock metaLock ( &xmpObj.lock, kXMP_ReadLock );
+
+ XMPUtils::CatenateArrayItems ( xmpObj, schemaNS, arrayName, separator, quotes, options, &localStr );
+ if ( catedStr != 0 ) (*SetClientString) ( catedStr, localStr.c_str(), localStr.size() );
- XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -537,17 +533,42 @@ WXMPUtils_SeparateArrayItems_1 ( XMPMetaRef wxmpObj,
XMP_StringPtr catedStr,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_SeparateArrayItems_1" )
+ XMP_ENTER_Static ( "WXMPUtils_SeparateArrayItems_1" )
if ( wxmpObj == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
if ( catedStr == 0 ) catedStr = "";
-
+
XMPMeta * xmpObj = WtoXMPMeta_Ptr ( wxmpObj );
+ XMP_AutoLock metaLock ( &xmpObj->lock, kXMP_WriteLock );
+
XMPUtils::SeparateArrayItems ( xmpObj, schemaNS, arrayName, options, catedStr );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
+}
+
+// -------------------------------------------------------------------------------------------------
+
+void
+WXMPUtils_ApplyTemplate_1 ( XMPMetaRef wWorkingXMP,
+ XMPMetaRef wTemplateXMP,
+ XMP_OptionBits actions,
+ WXMP_Result * wResult )
+{
+ XMP_ENTER_Static ( "WXMPUtils_ApplyTemplate_1" )
+
+ XMP_Assert ( (wWorkingXMP != 0) && (wTemplateXMP != 0) ); // Client glue enforced.
+
+ XMPMeta * workingXMP = WtoXMPMeta_Ptr ( wWorkingXMP );
+ XMP_AutoLock workingLock ( &workingXMP->lock, kXMP_WriteLock );
+
+ const XMPMeta & templateXMP = WtoXMPMeta_Ref ( wTemplateXMP );
+ XMP_AutoLock templateLock ( &templateXMP.lock, kXMP_ReadLock );
+
+ XMPUtils::ApplyTemplate ( workingXMP, templateXMP, actions );
+
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
@@ -559,37 +580,22 @@ WXMPUtils_RemoveProperties_1 ( XMPMetaRef wxmpObj,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_RemoveProperties_1" )
+ XMP_ENTER_Static ( "WXMPUtils_RemoveProperties_1" )
if ( wxmpObj == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
if ( schemaNS == 0 ) schemaNS = "";
if ( propName == 0 ) propName = "";
-
+
XMPMeta * xmpObj = WtoXMPMeta_Ptr ( wxmpObj );
+ XMP_AutoLock metaLock ( &xmpObj->lock, kXMP_WriteLock );
+
XMPUtils::RemoveProperties ( xmpObj, schemaNS, propName, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// -------------------------------------------------------------------------------------------------
-void
-WXMPUtils_AppendProperties_1 ( XMPMetaRef wSource,
- XMPMetaRef wDest,
- XMP_OptionBits options,
- WXMP_Result * wResult )
-{
- XMP_ENTER_WRAPPER ( "WXMPUtils_AppendProperties_1" )
-
- if ( wDest == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
-
- const XMPMeta & source = WtoXMPMeta_Ref ( wSource );
- XMPMeta * dest = WtoXMPMeta_Ptr ( wDest );
- XMPUtils::AppendProperties ( source, dest, options );
-
- XMP_EXIT_WRAPPER
-}
-
// -------------------------------------------------------------------------------------------------
void
@@ -602,8 +608,8 @@ WXMPUtils_DuplicateSubtree_1 ( XMPMetaRef wSource,
XMP_OptionBits options,
WXMP_Result * wResult )
{
- XMP_ENTER_WRAPPER ( "WXMPUtils_DuplicateSubtree_1" )
-
+ XMP_ENTER_Static ( "WXMPUtils_DuplicateSubtree_1" )
+
if ( wDest == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
if ( (sourceNS == 0) || (*sourceNS == 0) ) XMP_Throw ( "Empty source schema URI", kXMPErr_BadSchema );
if ( (sourceRoot == 0) || (*sourceRoot == 0) ) XMP_Throw ( "Empty source root name", kXMPErr_BadXPath );
@@ -611,10 +617,14 @@ WXMPUtils_DuplicateSubtree_1 ( XMPMetaRef wSource,
if ( destRoot == 0 ) destRoot = sourceRoot;
const XMPMeta & source = WtoXMPMeta_Ref ( wSource );
+ XMP_AutoLock sourceLock ( &source.lock, kXMP_ReadLock, (wSource != wDest) );
+
XMPMeta * dest = WtoXMPMeta_Ptr ( wDest );
+ XMP_AutoLock destLock ( &dest->lock, kXMP_WriteLock );
+
XMPUtils::DuplicateSubtree ( source, dest, sourceNS, sourceRoot, destNS, destRoot, options );
- XMP_EXIT_WRAPPER
+ XMP_EXIT
}
// =================================================================================================
diff --git a/source/XMPCore/XMPCore_Impl.cpp b/source/XMPCore/XMPCore_Impl.cpp
index 1cf92c6..757fe72 100644
--- a/source/XMPCore/XMPCore_Impl.cpp
+++ b/source/XMPCore/XMPCore_Impl.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
+// Copyright 2004 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -48,21 +48,9 @@ using namespace std;
XMP_Int32 sXMP_InitCount = 0;
-XMP_StringMap * sNamespaceURIToPrefixMap = 0;
-XMP_StringMap * sNamespacePrefixToURIMap = 0;
+XMP_NamespaceTable * sRegisteredNamespaces = 0;
-XMP_AliasMap * sRegisteredAliasMap = 0; // Needed by XMPIterator.
-
-XMP_VarString * sOutputNS = 0;
-XMP_VarString * sOutputStr = 0;
-XMP_VarString * sExceptionMessage = 0;
-
-XMP_Mutex sXMPCoreLock;
-int sLockCount = 0;
-
-#if TraceXMPCalls
- FILE * xmpOut = stderr;
-#endif
+XMP_AliasMap * sRegisteredAliasMap = 0;
void * voidVoidPtr = 0; // Used to backfill null output parameters.
XMP_StringPtr voidStringPtr = 0;
@@ -77,60 +65,6 @@ XMP_DateTime voidDateTime;
WXMP_Result void_wResult;
// =================================================================================================
-// Mutex Utilities
-// ===============
-
-// ! Note that the mutex need not be "recursive", allowing the same thread to acquire it multiple
-// ! times. There is a single XMP lock which is acquired in the wrapper classes. Internal calls
-// ! never go back out to the wrappers.
-
-#if XMP_WinBuild
-
- bool XMP_InitMutex ( XMP_Mutex * mutex ) {
- InitializeCriticalSection ( mutex );
- return true;
- }
-
- void XMP_TermMutex ( XMP_Mutex & mutex ) {
- DeleteCriticalSection ( &mutex );
- }
-
- void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ) {
- EnterCriticalSection ( &mutex );
- }
-
- void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ) {
- LeaveCriticalSection ( &mutex );
- }
-
-#else
-
- // Use pthread for both Mac and generic UNIX.
- // ! Would be nice to specify PTHREAD_MUTEX_ERRORCHECK, but the POSIX documentation is useless.
- // ! Would be OK but overkill to specify PTHREAD_MUTEX_RECURSIVE.
-
- bool XMP_InitMutex ( XMP_Mutex * mutex ) {
- int err = pthread_mutex_init ( mutex, 0 );
- return (err == 0 );
- }
-
- void XMP_TermMutex ( XMP_Mutex & mutex ) {
- (void) pthread_mutex_destroy ( &mutex );
- }
-
- void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ) {
- int err = pthread_mutex_lock ( &mutex );
- if ( err != 0 ) XMP_Throw ( "XMP_EnterCriticalRegion - pthread_mutex_lock failure", kXMPErr_ExternalFailure );
- }
-
- void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ) {
- int err = pthread_mutex_unlock ( &mutex );
- if ( err != 0 ) XMP_Throw ( "XMP_ExitCriticalRegion - pthread_mutex_unlock failure", kXMPErr_ExternalFailure );
- }
-
-#endif
-
-// =================================================================================================
// Local Utilities
// ===============
@@ -166,10 +100,9 @@ VerifyXPathRoot ( XMP_StringPtr schemaURI,
}
}
- XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( XMP_VarString ( schemaURI ) );
- if ( uriPos == sNamespaceURIToPrefixMap->end() ) {
- XMP_Throw ( "Unregistered schema namespace URI", kXMPErr_BadSchema );
- }
+ XMP_StringPtr schemaPrefix;
+ bool nsFound = sRegisteredNamespaces->GetPrefix ( schemaURI, &schemaPrefix, 0 );
+ if ( ! nsFound ) XMP_Throw ( "Unregistered schema namespace URI", kXMPErr_BadSchema );
XMP_StringPtr colonPos = propName;
while ( (*colonPos != 0) && (*colonPos != ':') ) ++colonPos;
@@ -182,7 +115,7 @@ VerifyXPathRoot ( XMP_StringPtr schemaURI,
// The propName is unqualified, use the schemaURI and associated prefix.
expandedXPath->push_back ( XPathStepInfo ( schemaURI, kXMP_SchemaNode ) );
- expandedXPath->push_back ( XPathStepInfo ( uriPos->second, 0 ) );
+ expandedXPath->push_back ( XPathStepInfo ( schemaPrefix, 0 ) );
(*expandedXPath)[kRootPropStep].step += propName;
} else {
@@ -193,13 +126,7 @@ VerifyXPathRoot ( XMP_StringPtr schemaURI,
VerifySimpleXMLName ( colonPos+1, colonPos+strlen(colonPos) );
XMP_VarString prefix ( propName, prefixLen );
- XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( prefix );
- if ( prefixPos == sNamespacePrefixToURIMap->end() ) {
- XMP_Throw ( "Unknown schema namespace prefix", kXMPErr_BadSchema );
- }
- if ( prefix != uriPos->second ) {
- XMP_Throw ( "Schema namespace URI and prefix mismatch", kXMPErr_BadSchema );
- }
+ if ( prefix != schemaPrefix ) XMP_Throw ( "Schema namespace URI and prefix mismatch", kXMPErr_BadSchema );
expandedXPath->push_back ( XPathStepInfo ( schemaURI, kXMP_SchemaNode ) );
expandedXPath->push_back ( XPathStepInfo ( propName, 0 ) );
@@ -226,10 +153,8 @@ VerifyQualName ( XMP_StringPtr qualName, XMP_StringPtr nameEnd )
size_t prefixLen = colonPos - qualName + 1; // ! Include the colon.
XMP_VarString prefix ( qualName, prefixLen );
- XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( prefix );
- if ( prefixPos == sNamespacePrefixToURIMap->end() ) {
- XMP_Throw ( "Unknown namespace prefix for qualified name", kXMPErr_BadXPath );
- }
+ bool nsFound = sRegisteredNamespaces->GetURI ( prefix.c_str(), 0, 0 );
+ if ( ! nsFound ) XMP_Throw ( "Unknown namespace prefix for qualified name", kXMPErr_BadXPath );
} // VerifyQualName
@@ -498,9 +423,7 @@ CheckImplicitStruct ( XMP_Node * node,
// DeleteSubtree
// -------------
-// *** Might be useful elsewhere?
-
-static void
+void
DeleteSubtree ( XMP_NodePtrPos rootNodePos )
{
XMP_Node * rootNode = *rootNodePos;
@@ -1171,7 +1094,7 @@ EXIT:
// ==============
void
-CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent )
+CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent, bool skipEmpty /* = false */ )
{
size_t qualCount = origParent->qualifiers.size();
size_t childCount = origParent->children.size();
@@ -1182,8 +1105,14 @@ CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent )
for ( size_t qualNum = 0, qualLim = qualCount; qualNum != qualLim; ++qualNum ) {
const XMP_Node * origQual = origParent->qualifiers[qualNum];
- XMP_Node * cloneQual = new XMP_Node ( cloneParent, origQual->name, origQual->value, origQual->options );
- CloneOffspring ( origQual, cloneQual );
+ if ( skipEmpty && origQual->value.empty() && origQual->children.empty() ) continue;
+ XMP_Node * cloneQual = new XMP_Node ( cloneParent, origQual->name, origQual->value, origQual->options );
+ CloneOffspring ( origQual, cloneQual, skipEmpty );
+ if ( skipEmpty && cloneQual->value.empty() && cloneQual->children.empty() ) {
+ // Check again, might have had an array or struct with all empty children.
+ delete cloneQual;
+ continue;
+ }
cloneParent->qualifiers.push_back ( cloneQual );
}
@@ -1195,8 +1124,14 @@ CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent )
for ( size_t childNum = 0, childLim = childCount; childNum != childLim; ++childNum ) {
const XMP_Node * origChild = origParent->children[childNum];
- XMP_Node * cloneChild = new XMP_Node ( cloneParent, origChild->name, origChild->value, origChild->options );
- CloneOffspring ( origChild, cloneChild );
+ if ( skipEmpty && origChild->value.empty() && origChild->children.empty() ) continue;
+ XMP_Node * cloneChild = new XMP_Node ( cloneParent, origChild->name, origChild->value, origChild->options );
+ CloneOffspring ( origChild, cloneChild, skipEmpty );
+ if ( skipEmpty && cloneChild->value.empty() && cloneChild->children.empty() ) {
+ // Check again, might have had an array or struct with all empty children.
+ delete cloneChild;
+ continue;
+ }
cloneParent->children.push_back ( cloneChild );
}
@@ -1209,7 +1144,7 @@ CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent )
// ============
XMP_Node *
-CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent )
+CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent, bool skipEmpty /* = false */ )
{
#if XMP_DebugBuild
if ( cloneParent->parent == 0 ) {
@@ -1224,9 +1159,15 @@ CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent )
#endif
XMP_Node * cloneRoot = new XMP_Node ( cloneParent, origRoot->name, origRoot->value, origRoot->options );
- CloneOffspring ( origRoot, cloneRoot ) ;
+ CloneOffspring ( origRoot, cloneRoot, skipEmpty ) ;
+
+ if ( skipEmpty && cloneRoot->value.empty() && cloneRoot->children.empty() ) {
+ // ! Can't do earlier, CloneOffspring might be skipping empty children.
+ delete cloneRoot;
+ return 0;
+ }
+
cloneParent->children.push_back ( cloneRoot );
-
return cloneRoot;
} // CloneSubtree
diff --git a/source/XMPCore/XMPCore_Impl.hpp b/source/XMPCore/XMPCore_Impl.hpp
index d1be1c3..9a5314a 100644
--- a/source/XMPCore/XMPCore_Impl.hpp
+++ b/source/XMPCore/XMPCore_Impl.hpp
@@ -1,8 +1,8 @@
#ifndef __XMPCore_Impl_hpp__
-#define __XMPCore_Impl_hpp__
+#define __XMPCore_Impl_hpp__ 1
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2004 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -12,8 +12,9 @@
#include "XMP_Environment.h" // ! Must be the first #include!
#include "XMP_Const.h"
#include "XMP_BuildInfo.h"
+#include "XMP_LibUtils.hpp"
-#include "client-glue/WXMPMeta.hpp"
+#include "client-glue/WXMP_Common.hpp"
#include <vector>
#include <string>
@@ -22,13 +23,6 @@
#include <cassert>
#if XMP_WinBuild
- #include <Windows.h>
-#else
- // Use pthread for both Mac and generic UNIX.
- #include <pthread.h>
-#endif
-
-#if XMP_WinBuild
#pragma warning ( disable : 4244 ) // possible loss of data (temporary for 64 bit builds)
#pragma warning ( disable : 4267 ) // possible loss of data (temporary for 64 bit builds)
#endif
@@ -45,16 +39,9 @@ typedef XMP_Node * XMP_NodePtr;
typedef std::vector<XMP_Node*> XMP_NodeOffspring;
typedef XMP_NodeOffspring::iterator XMP_NodePtrPos;
-typedef std::string XMP_VarString;
typedef XMP_VarString::iterator XMP_VarStringPos;
typedef XMP_VarString::const_iterator XMP_cVarStringPos;
-typedef std::pair < XMP_VarString, XMP_VarString > XMP_StringPair;
-
-typedef std::map < XMP_VarString, XMP_VarString > XMP_StringMap;
-typedef XMP_StringMap::iterator XMP_StringMapPos;
-typedef XMP_StringMap::const_iterator XMP_cStringMapPos;
-
typedef std::vector < XPathStepInfo > XMP_ExpandedXPath;
typedef XMP_ExpandedXPath::iterator XMP_ExpandedXPathPos;
typedef XMP_ExpandedXPath::const_iterator XMP_cExpandedXPathPos;
@@ -68,13 +55,14 @@ typedef XMP_AliasMap::const_iterator XMP_cAliasMapPos;
extern XMP_Int32 sXMP_InitCount;
-extern XMP_AliasMap * sRegisteredAliasMap;
+extern XMP_NamespaceTable * sRegisteredNamespaces;
-extern XMP_StringMap * sNamespaceURIToPrefixMap;
-extern XMP_StringMap * sNamespacePrefixToURIMap;
+extern XMP_AliasMap * sRegisteredAliasMap;
-extern XMP_VarString * sOutputNS;
-extern XMP_VarString * sOutputStr;
+#define WtoXMPMeta_Ref(xmpRef) (const XMPMeta &) (*((XMPMeta*)(xmpRef)))
+#define WtoXMPMeta_Ptr(xmpRef) ((XMPMeta*)(xmpRef))
+
+#define WtoXMPDocOps_Ptr(docRef) ((XMPDocOps*)(docRef))
extern void * voidVoidPtr; // Used to backfill null output parameters.
extern XMP_StringPtr voidStringPtr;
@@ -94,25 +82,10 @@ extern WXMP_Result void_wResult;
#define XMP_LitNMatch(s,l,n) (std::strncmp((s),(l),(n)) == 0)
// *** Use the above macros!
-#define kTab ((char)0x09)
-#define kLF ((char)0x0A)
-#define kCR ((char)0x0D)
-
#if XMP_WinBuild
#define snprintf _snprintf
#endif
-#define WtoXMPMeta_Ref(xmpRef) *((const XMPMeta *)(xmpRef))
-#define WtoXMPMeta_Ptr(xmpRef) (((xmpRef) == 0) ? 0 : (XMPMeta *)(xmpRef))
-
-#define WtoXMPIterator_Ref(iterRef) *((const XMPIterator *)(iterRef))
-#define WtoXMPIterator_Ptr(iterRef) (((iterRef) == 0) ? 0 : (XMPIterator *)(iterRef))
-
-#define WtoXMPDocOps_Ref(docRef) *((const XMPDocOps *)(docRef))
-#define WtoXMPDocOps_Ptr(docRef) (((docRef) == 0) ? 0 : (XMPDocOps *)(docRef))
-
-#define IgnoreParam(p) voidVoidPtr = (void*)&p
-
// =================================================================================================
// Version info
@@ -130,158 +103,40 @@ extern WXMP_Result void_wResult;
#define kXMPCoreName "XMP Core"
#define kXMPCore_VersionMessage kXMPCoreName " " XMP_API_VERSION_STRING
// =================================================================================================
-// Support for asserts
+// Support for call tracing
-#define _MakeStr(p) #p
-#define _NotifyMsg(n,c,f,l) #n " failed: " #c " in " f " at line " _MakeStr(l)
-
-#if ! XMP_DebugBuild
- #define XMP_Assert(c) ((void) 0)
-#else
- #define XMP_Assert(c) assert ( c )
+#ifndef XMP_TraceCoreCalls
+ #define XMP_TraceCoreCalls 0
+ #define XMP_TraceCoreCallsToFile 0
#endif
- #define XMP_Enforce(c) \
- if ( ! (c) ) { \
- const char * assert_msg = _NotifyMsg ( XMP_Enforce, (c), __FILE__, __LINE__ ); \
- XMP_Throw ( assert_msg , kXMPErr_EnforceFailure ); \
- }
-// =================================================================================================
-// Support for exceptions and thread locking
-
-#ifndef TraceXMPCalls
- #define TraceXMPCalls 0
-#endif
+#if XMP_TraceCoreCalls
-#if ! TraceXMPCalls
+ #undef AnnounceThrow
+ #undef AnnounceCatch
- #define AnnounceThrow(msg) /* Do nothing. */
- #define AnnounceCatch(msg) /* Do nothing. */
+ #undef AnnounceEntry
+ #undef AnnounceNoLock
+ #undef AnnounceExit
- #define AnnounceEntry(proc) /* Do nothing. */
- #define AnnounceNoLock(proc) /* Do nothing. */
- #define AnnounceExit() /* Do nothing. */
-
- #define ReportLock() ++sLockCount
- #define ReportUnlock() --sLockCount
- #define ReportKeepLock() /* Do nothing. */
-
-#else
-
- extern FILE * xmpCoreOut;
+ extern FILE * xmpCoreLog;
#define AnnounceThrow(msg) \
- fprintf ( xmpCoreOut, "XMP_Throw: %s\n", msg ); fflush ( xmpOut )
+ fprintf ( xmpCoreLog, "XMP_Throw: %s\n", msg ); fflush ( xmpCoreLog )
#define AnnounceCatch(msg) \
- fprintf ( xmpCoreOut, "Catch in %s: %s\n", procName, msg ); fflush ( xmpOut )
+ fprintf ( xmpCoreLog, "Catch in %s: %s\n", procName, msg ); fflush ( xmpCoreLog )
#define AnnounceEntry(proc) \
const char * procName = proc; \
- fprintf ( xmpCoreOut, "Entering %s\n", procName ); fflush ( xmpOut )
+ fprintf ( xmpCoreLog, "Entering %s\n", procName ); fflush ( xmpCoreLog )
#define AnnounceNoLock(proc) \
const char * procName = proc; \
- fprintf ( xmpCoreOut, "Entering %s (no lock)\n", procName ); fflush ( xmpOut )
+ fprintf ( xmpCoreLog, "Entering %s (no lock)\n", procName ); fflush ( xmpCoreLog )
#define AnnounceExit() \
- fprintf ( xmpCoreOut, "Exiting %s\n", procName ); fflush ( xmpOut )
-
- #define ReportLock() \
- ++sLockCount; fprintf ( xmpCoreOut, " Auto lock, count = %d\n", sLockCount ); fflush ( xmpOut )
- #define ReportUnlock() \
- --sLockCount; fprintf ( xmpCoreOut, " Auto unlock, count = %d\n", sLockCount ); fflush ( xmpOut )
- #define ReportKeepLock() \
- fprintf ( xmpCoreOut, " Keeping lock, count = %d\n", sLockCount ); fflush ( xmpOut )
+ fprintf ( xmpCoreLog, "Exiting %s\n", procName ); fflush ( xmpCoreLog )
#endif
-#define XMP_Throw(msg,id) { AnnounceThrow ( msg ); throw XMP_Error ( id, msg ); }
-
-// -------------------------------------------------------------------------------------------------
-
-#if XMP_WinBuild
- typedef CRITICAL_SECTION XMP_Mutex;
-#else
- // Use pthread for both Mac and generic UNIX.
- typedef pthread_mutex_t XMP_Mutex;
-#endif
-
-extern XMP_Mutex sXMPCoreLock;
-extern int sLockCount; // Keep signed to catch unlock errors.
-extern XMP_VarString * sExceptionMessage;
-
-extern bool XMP_InitMutex ( XMP_Mutex * mutex );
-extern void XMP_TermMutex ( XMP_Mutex & mutex );
-
-extern void XMP_EnterCriticalRegion ( XMP_Mutex & mutex );
-extern void XMP_ExitCriticalRegion ( XMP_Mutex & mutex );
-
-class XMP_AutoMutex {
-public:
- XMP_AutoMutex() : mutex(&sXMPCoreLock) { XMP_EnterCriticalRegion ( *mutex ); ReportLock(); };
- ~XMP_AutoMutex() { if ( mutex != 0 ) { ReportUnlock(); XMP_ExitCriticalRegion ( *mutex ); mutex = 0; } };
- void KeepLock() { ReportKeepLock(); mutex = 0; };
-private:
- XMP_Mutex * mutex;
-};
-
-// *** Switch to XMPEnterObjectWrapper & XMPEnterStaticWrapper, to allow for per-object locks.
-
-// ! Don't do the initialization check (sXMP_InitCount > 0) for the no-lock case. That macro is used
-// ! by WXMPMeta_Initialize_1.
-
-#define XMP_ENTER_WRAPPER_NO_LOCK(proc) \
- AnnounceNoLock ( proc ); \
- XMP_Assert ( (0 <= sLockCount) && (sLockCount <= 1) ); \
- try { \
- wResult->errMessage = 0;
-
-#define XMP_ENTER_WRAPPER(proc) \
- AnnounceEntry ( proc ); \
- XMP_Assert ( sXMP_InitCount > 0 ); \
- XMP_Assert ( (0 <= sLockCount) && (sLockCount <= 1) ); \
- try { \
- XMP_AutoMutex mutex; \
- wResult->errMessage = 0;
-
-#define XMP_EXIT_WRAPPER \
- XMP_CATCH_EXCEPTIONS \
- AnnounceExit();
-
-#define XMP_EXIT_WRAPPER_KEEP_LOCK(keep) \
- if ( keep ) mutex.KeepLock(); \
- XMP_CATCH_EXCEPTIONS \
- AnnounceExit();
-
-#define XMP_EXIT_WRAPPER_NO_THROW \
- } catch ( ... ) { \
- AnnounceCatch ( "no-throw catch-all" ); \
- /* Do nothing. */ \
- } \
- AnnounceExit();
-
-#define XMP_CATCH_EXCEPTIONS \
- } catch ( XMP_Error & xmpErr ) { \
- wResult->int32Result = xmpErr.GetID(); \
- wResult->ptrResult = (void*)"XMP"; \
- wResult->errMessage = xmpErr.GetErrMsg(); \
- if ( wResult->errMessage == 0 ) wResult->errMessage = ""; \
- AnnounceCatch ( wResult->errMessage ); \
- } catch ( std::exception & stdErr ) { \
- wResult->int32Result = kXMPErr_StdException; \
- wResult->errMessage = stdErr.what(); \
- if ( wResult->errMessage == 0 ) wResult->errMessage = ""; \
- AnnounceCatch ( wResult->errMessage ); \
- } catch ( ... ) { \
- wResult->int32Result = kXMPErr_UnknownException; \
- wResult->errMessage = "Caught unknown exception"; \
- AnnounceCatch ( wResult->errMessage ); \
- }
-
-#if XMP_DebugBuild
- #define RELEASE_NO_THROW /* empty */
-#else
- #define RELEASE_NO_THROW throw()
-#endif
-
// =================================================================================================
// ExpandXPath, FindNode, and related support
@@ -341,15 +196,18 @@ extern XMP_Index
LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_StringPtr fieldValue );
extern void
-CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent );
+CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent, bool skipEmpty = false );
extern XMP_Node *
-CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent );
+CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent, bool skipEmpty = false );
extern bool
CompareSubtrees ( const XMP_Node & leftNode, const XMP_Node & rightNode );
extern void
+DeleteSubtree ( XMP_NodePtrPos rootNodePos );
+
+extern void
DeleteEmptySchema ( XMP_Node * schemaNode );
extern void
diff --git a/source/XMPCore/XMPIterator.cpp b/source/XMPCore/XMPIterator.cpp
index 8032bfa..08e03fa 100644
--- a/source/XMPCore/XMPIterator.cpp
+++ b/source/XMPCore/XMPIterator.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -61,47 +61,6 @@ AddSchemaProps ( IterInfo & info, IterNode & iterSchema, const XMP_Node * xmpSch
} // AddSchemaProps
// -------------------------------------------------------------------------------------------------
-// AddSchemaAliases
-// ----------------
-//
-// Add the aliases to the IterNode for a schema, if the corresponding actual exists.
-
-static void
-AddSchemaAliases ( IterInfo & info, IterNode & iterSchema, XMP_StringPtr schemaURI )
-{
-
- // We're showing the aliases also. Look them up by their namespace prefix. Yes, the alias map is
- // sorted so we could process just that portion. But that takes more code and the extra speed
- // isn't worth it. (Plus this way we avoid a dependence on the map implementation.) Lookup the
- // XMP node from the alias, to make sure the actual exists.
-
- #if TraceIterators
- printf ( " Adding aliases\n", schemaURI );
- #endif
-
- XMP_StringPtr nsPrefix;
- XMP_StringLen nsLen;
- bool found = XMPMeta::GetNamespacePrefix ( schemaURI, &nsPrefix, &nsLen );
- if ( ! found ) XMP_Throw ( "Unknown iteration namespace", kXMPErr_BadSchema );
-
- XMP_AliasMapPos currAlias = sRegisteredAliasMap->begin();
- XMP_AliasMapPos endAlias = sRegisteredAliasMap->end();
-
- for ( ; currAlias != endAlias; ++currAlias ) {
- if ( XMP_LitNMatch ( currAlias->first.c_str(), nsPrefix, nsLen ) ) {
- const XMP_Node * actualProp = FindConstNode ( &info.xmpObj->tree, currAlias->second );
- if ( actualProp != 0 ) {
- iterSchema.children.push_back ( IterNode ( (actualProp->options | kXMP_PropIsAlias), currAlias->first, 0 ) );
- #if TraceIterators
- printf ( " %s => %s\n", currAlias->first.c_str(), actualProp->name.c_str() );
- #endif
- }
- }
- }
-
-} // AddSchemaAliases
-
-// -------------------------------------------------------------------------------------------------
// AddNodeOffspring
// ----------------
//
@@ -156,7 +115,7 @@ AddNodeOffspring ( IterInfo & info, IterNode & iterParent, const XMP_Node * xmpP
currPath += xmpChild->name;
} else {
char buffer [32]; // AUDIT: Using sizeof(buffer) below for snprintf length is safe.
- snprintf ( buffer, sizeof(buffer), "[%d]", childNum+1 ); // ! XPath indices are one-based.
+ snprintf ( buffer, sizeof(buffer), "[%lu]", childNum+1 ); // ! XPath indices are one-based.
currPath += buffer;
}
iterParent.children.push_back ( IterNode ( xmpChild->options, currPath, leafOffset ) );
@@ -390,19 +349,6 @@ XMPIterator::Terminate() RELEASE_NO_THROW
} // Terminate
-// -------------------------------------------------------------------------------------------------
-// Unlock
-// ------
-
-void
-XMPIterator::Unlock ( XMP_OptionBits options )
-{
- options = options; // Avoid unused parameter warning.
-
- XMPMeta::Unlock ( 0 );
-
-} // Unlock
-
// =================================================================================================
// Constructors
// =================================================================================================
@@ -480,8 +426,6 @@ XMPIterator::XMPIterator ( const XMPMeta & xmpObj,
XMP_Node * xmpSchema = FindConstSchema ( &xmpObj.tree, schemaNS );
if ( xmpSchema != 0 ) AddSchemaProps ( info, iterSchema, xmpSchema );
- if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, schemaNS );
-
if ( iterSchema.children.empty() ) {
info.tree.children.pop_back(); // No properties, remove the schema node.
} else {
@@ -509,40 +453,10 @@ XMPIterator::XMPIterator ( const XMPMeta & xmpObj,
if ( ! (info.options & kXMP_IterJustChildren) ) {
AddSchemaProps ( info, iterSchema, xmpSchema );
- if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, xmpSchema->name.c_str() );
if ( iterSchema.children.empty() ) info.tree.children.pop_back(); // No properties, remove the schema node.
}
}
-
- if ( info.options & kXMP_IterIncludeAliases ) {
-
- // Add the schema that only have aliases. The most convenient, and safest way, is to go
- // through the registered namespaces, see if it exists, and let AddSchemaAliases do its
- // thing if not. Don't combine with the above loop, it is nicer to have the "real" stuff
- // be in storage order (not subject to the namespace map order).
-
- // ! We don't do the kXMP_IterJustChildren handing in the same way here as above. The
- // ! existing schema (presumably) have actual children. We need to call AddSchemaAliases
- // ! here to determine if the namespace has any aliases to existing properties. We then
- // ! strip the children if necessary.
-
- XMP_cStringMapPos currNS = sNamespaceURIToPrefixMap->begin();
- XMP_cStringMapPos endNS = sNamespaceURIToPrefixMap->end();
- for ( ; currNS != endNS; ++currNS ) {
- XMP_StringPtr schemaName = currNS->first.c_str();
- if ( FindConstSchema ( &xmpObj.tree, schemaName ) != 0 ) continue;
- info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaName, 0 ) );
- IterNode & iterSchema = info.tree.children.back();
- AddSchemaAliases ( info, iterSchema, schemaName );
- if ( iterSchema.children.empty() ) {
- info.tree.children.pop_back(); // No aliases, remove the schema node.
- } else if ( info.options & kXMP_IterJustChildren ) {
- iterSchema.children.clear(); // Get rid of the children.
- }
- }
-
- }
}
@@ -719,17 +633,4 @@ XMPIterator::Skip ( XMP_OptionBits iterOptions )
} // Skip
-// -------------------------------------------------------------------------------------------------
-// UnlockIter
-// ----------
-
-void
-XMPIterator::UnlockIter ( XMP_OptionBits options )
-{
- options = options; // Avoid unused parameter warning.
-
- XMPMeta::Unlock ( 0 );
-
-} // UnlockIter
-
// =================================================================================================
diff --git a/source/XMPCore/XMPIterator.hpp b/source/XMPCore/XMPIterator.hpp
index b72b975..d55f721 100644
--- a/source/XMPCore/XMPIterator.hpp
+++ b/source/XMPCore/XMPIterator.hpp
@@ -2,7 +2,7 @@
#define __XMPIterator_hpp__
// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -97,9 +97,6 @@ public:
static void
Terminate() RELEASE_NO_THROW; // ! For internal use only!
- static void
- Unlock ( XMP_OptionBits options );
-
XMPIterator ( const XMPMeta & xmpObj, // Construct a property iterator.
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
@@ -123,12 +120,11 @@ public:
void
Skip ( XMP_OptionBits options );
- void
- UnlockIter ( XMP_OptionBits options );
-
// ! Expose so that wrappers and file static functions can see the data.
XMP_Int32 clientRefs; // ! Must be signed to allow decrement from 0.
+ XMP_ReadWriteLock lock;
+
IterInfo info;
private:
diff --git a/source/XMPCore/XMPMeta-GetSet.cpp b/source/XMPCore/XMPMeta-GetSet.cpp
index 41b01d5..3ec0997 100644
--- a/source/XMPCore/XMPMeta-GetSet.cpp
+++ b/source/XMPCore/XMPMeta-GetSet.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -79,10 +79,11 @@ SetNodeValue ( XMP_Node * node, XMP_StringPtr value )
}
#endif
- node->value = value;
+ std::string newValue = value; // Need a local copy to tweak and not change node.value for errors.
- XMP_Uns8* chPtr = (XMP_Uns8*) node->value.c_str(); // Check for valid UTF-8, replace ASCII controls with a space.
+ XMP_Uns8* chPtr = (XMP_Uns8*) newValue.c_str(); // Check for valid UTF-8, replace ASCII controls with a space.
while ( *chPtr != 0 ) {
+
while ( (*chPtr != 0) && (*chPtr < 0x80) ) {
if ( *chPtr < 0x20 ) {
if ( (*chPtr != kTab) && (*chPtr != kLF) && (*chPtr != kCR) ) *chPtr = 0x20;
@@ -91,11 +92,21 @@ SetNodeValue ( XMP_Node * node, XMP_StringPtr value )
}
++chPtr;
}
+
XMP_Assert ( (*chPtr == 0) || (*chPtr >= 0x80) );
- if ( *chPtr != 0 ) (void) GetCodePoint ( (const XMP_Uns8 **) &chPtr ); // Throws for bad UTF-8.
+
+ if ( *chPtr != 0 ) {
+ XMP_Uns32 cp = GetCodePoint ( (const XMP_Uns8 **) &chPtr ); // Throws for bad UTF-8.
+ if ( (cp == 0xFFFE) || (cp == 0xFFFF) ) {
+ XMP_Throw ( "U+FFFE and U+FFFF are not allowed in XML", kXMPErr_BadXML );
+ }
+ }
+
}
- if ( XMP_PropIsQualifier(node->options) && (node->name == "xml:lang") ) NormalizeLangValue ( &node->value );
+ if ( XMP_PropIsQualifier(node->options) && (node->name == "xml:lang") ) NormalizeLangValue ( &newValue );
+
+ node->value.swap ( newValue );
#if 0 // *** XMP_DebugBuild
node->_valuePtr = node->value.c_str();
@@ -314,8 +325,18 @@ ChooseLocalizedText ( const XMP_Node * arrayNode,
static void
AppendLangItem ( XMP_Node * arrayNode, XMP_StringPtr itemLang, XMP_StringPtr itemValue )
{
- XMP_Node * newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, itemValue, (kXMP_PropHasQualifiers | kXMP_PropHasLang) );
- XMP_Node * langQual = new XMP_Node ( newItem, "xml:lang", itemLang, kXMP_PropIsQualifier );
+ XMP_Node * newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, (kXMP_PropHasQualifiers | kXMP_PropHasLang) );
+ XMP_Node * langQual = new XMP_Node ( newItem, "xml:lang", kXMP_PropIsQualifier );
+
+ try { // ! Use SetNodeValue, not constructors above, to get the character checks.
+ SetNodeValue ( newItem, itemValue );
+ SetNodeValue ( langQual, itemLang );
+ } catch (...) {
+ delete newItem;
+ delete langQual;
+ throw;
+ }
+
newItem->qualifiers.push_back ( langQual );
if ( (arrayNode->children.empty()) || (langQual->value != "x-default") ) {
@@ -373,17 +394,19 @@ XMPMeta::GetArrayItem ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
XMP_StringPtr * itemValue,
- XMP_StringLen * valueSize,
+ XMP_StringLen * valueSize,
XMP_OptionBits * options ) const
{
XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (itemValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (itemValue != 0) && (options != 0) ); // Enforced by wrapper.
- XMP_StringPtr itemPath;
- XMP_StringLen pathLen;
+ // ! Special case check to make errors consistent if the array does not exist. The other array
+ // ! functions and existing array here (empty or not) already throw.
+ if ( (itemIndex <= 0) && (itemIndex != kXMP_ArrayLastItem) ) XMP_Throw ( "Array index must be larger than zero", kXMPErr_BadXPath );
- XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen );
- return GetProperty ( schemaNS, itemPath, itemValue, valueSize, options );
+ XMP_VarString itemPath;
+ XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath );
+ return GetProperty ( schemaNS, itemPath.c_str(), itemValue, valueSize, options );
} // GetArrayItem
@@ -402,13 +425,11 @@ XMPMeta::GetStructField ( XMP_StringPtr schemaNS,
XMP_OptionBits * options ) const
{
XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (fieldValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper.
-
- XMP_StringPtr fieldPath;
- XMP_StringLen pathLen;
+ XMP_Assert ( (fieldValue != 0) && (options != 0) ); // Enforced by wrapper.
- XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
- return GetProperty ( schemaNS, fieldPath, fieldValue, valueSize, options );
+ XMP_VarString fieldPath;
+ XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath );
+ return GetProperty ( schemaNS, fieldPath.c_str(), fieldValue, valueSize, options );
} // GetStructField
@@ -423,17 +444,15 @@ XMPMeta::GetQualifier ( XMP_StringPtr schemaNS,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
XMP_StringPtr * qualValue,
- XMP_StringLen * valueSize,
+ XMP_StringLen * valueSize,
XMP_OptionBits * options ) const
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (qualValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (qualValue != 0) && (options != 0) ); // Enforced by wrapper.
- XMP_StringPtr qualPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
- return GetProperty ( schemaNS, qualPath, qualValue, valueSize, options );
+ XMP_VarString qualPath;
+ XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath );
+ return GetProperty ( schemaNS, qualPath.c_str(), qualValue, valueSize, options );
} // GetQualifier
@@ -550,11 +569,9 @@ XMPMeta::SetStructField ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper.
- XMP_StringPtr fieldPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
- SetProperty ( schemaNS, fieldPath, fieldValue, options );
+ XMP_VarString fieldPath;
+ XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath );
+ SetProperty ( schemaNS, fieldPath.c_str(), fieldValue, options );
} // SetStructField
@@ -573,16 +590,14 @@ XMPMeta::SetQualifier ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper.
- XMP_StringPtr qualPath;
- XMP_StringLen pathLen;
-
XMP_ExpandedXPath expPath;
ExpandXPath ( schemaNS, propName, &expPath );
XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_ExistingOnly );
if ( propNode == 0 ) XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath );
- XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
- SetProperty ( schemaNS, qualPath, qualValue, options );
+ XMP_VarString qualPath;
+ XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath );
+ SetProperty ( schemaNS, qualPath.c_str(), qualValue, options );
} // SetQualifier
@@ -644,11 +659,9 @@ XMPMeta::DeleteArrayItem ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper.
- XMP_StringPtr itemPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen );
- DeleteProperty ( schemaNS, itemPath );
+ XMP_VarString itemPath;
+ XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath );
+ DeleteProperty ( schemaNS, itemPath.c_str() );
} // DeleteArrayItem
@@ -665,11 +678,9 @@ XMPMeta::DeleteStructField ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper.
- XMP_StringPtr fieldPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
- DeleteProperty ( schemaNS, fieldPath );
+ XMP_VarString fieldPath;
+ XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath );
+ DeleteProperty ( schemaNS, fieldPath.c_str() );
} // DeleteStructField
@@ -686,11 +697,9 @@ XMPMeta::DeleteQualifier ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper.
- XMP_StringPtr qualPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
- DeleteProperty ( schemaNS, qualPath );
+ XMP_VarString qualPath;
+ XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath );
+ DeleteProperty ( schemaNS, qualPath.c_str() );
} // DeleteQualifier
@@ -725,11 +734,9 @@ XMPMeta::DoesArrayItemExist ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper.
- XMP_StringPtr itemPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen );
- return DoesPropertyExist ( schemaNS, itemPath );
+ XMP_VarString itemPath;
+ XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath );
+ return DoesPropertyExist ( schemaNS, itemPath.c_str() );
} // DoesArrayItemExist
@@ -746,11 +753,9 @@ XMPMeta::DoesStructFieldExist ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper.
- XMP_StringPtr fieldPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
- return DoesPropertyExist ( schemaNS, fieldPath );
+ XMP_VarString fieldPath;
+ XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath );
+ return DoesPropertyExist ( schemaNS, fieldPath.c_str() );
} // DoesStructFieldExist
@@ -767,11 +772,9 @@ XMPMeta::DoesQualifierExist ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper.
- XMP_StringPtr qualPath;
- XMP_StringLen pathLen;
-
- XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
- return DoesPropertyExist ( schemaNS, qualPath );
+ XMP_VarString qualPath;
+ XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath );
+ return DoesPropertyExist ( schemaNS, qualPath.c_str() );
} // DoesQualifierExist
@@ -971,6 +974,107 @@ XMPMeta::SetLocalizedText ( XMP_StringPtr schemaNS,
} // SetLocalizedText
+// -------------------------------------------------------------------------------------------------
+// DeleteLocalizedText
+// -------------------
+
+void
+XMPMeta::DeleteLocalizedText ( XMP_StringPtr schemaNS,
+ XMP_StringPtr arrayName,
+ XMP_StringPtr _genericLang,
+ XMP_StringPtr _specificLang )
+{
+ XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (_genericLang != 0) && (_specificLang != 0) ); // Enforced by wrapper.
+
+ XMP_VarString zGenericLang ( _genericLang );
+ XMP_VarString zSpecificLang ( _specificLang );
+ NormalizeLangValue ( &zGenericLang );
+ NormalizeLangValue ( &zSpecificLang );
+
+ XMP_StringPtr genericLang = zGenericLang.c_str();
+ XMP_StringPtr specificLang = zSpecificLang.c_str();
+
+ XMP_ExpandedXPath arrayPath;
+ ExpandXPath ( schemaNS, arrayName, &arrayPath );
+
+ // Find the LangAlt array and the selected array item.
+
+ XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_ExistingOnly );
+ if ( arrayNode == 0 ) return;
+ size_t arraySize = arrayNode->children.size();
+
+ XMP_CLTMatch match;
+ XMP_Node * itemNode;
+
+ match = ChooseLocalizedText ( arrayNode, genericLang, specificLang, (const XMP_Node **) &itemNode );
+ if ( match != kXMP_CLT_SpecificMatch ) return;
+
+ size_t itemIndex = 0;
+ for ( ; itemIndex < arraySize; ++itemIndex ) {
+ if ( arrayNode->children[itemIndex] == itemNode ) break;
+ }
+ XMP_Enforce ( itemIndex < arraySize );
+
+ // Decide if the selected item is x-default or not, find relevant matching item.
+
+ bool itemIsXDefault = false;
+ if ( ! itemNode->qualifiers.empty() ) {
+ XMP_Node * qualNode = itemNode->qualifiers[0];
+ if ( (qualNode->name == "xml:lang") && (qualNode->value == "x-default") ) itemIsXDefault = true;
+ }
+
+ if ( itemIsXDefault && (itemIndex != 0) ) { // Enforce the x-default is first policy.
+ XMP_Node * temp = arrayNode->children[0];
+ arrayNode->children[0] = arrayNode->children[itemIndex];
+ arrayNode->children[itemIndex] = temp;
+ itemIndex = 0;
+ }
+
+ XMP_Node * assocNode = 0;
+ size_t assocIndex;
+ size_t assocIsXDefault = false;
+
+ if ( itemIsXDefault ) {
+
+ for ( assocIndex = 1; assocIndex < arraySize; ++assocIndex ) {
+ if ( arrayNode->children[assocIndex]->value == itemNode->value ) {
+ assocNode = arrayNode->children[assocIndex];
+ break;
+ }
+ }
+
+ } else if ( itemIndex > 0 ) {
+
+ XMP_Node * itemZero = arrayNode->children[0];
+ if ( itemZero->value == itemNode->value ) {
+ XMP_Node * qualNode = itemZero->qualifiers[0];
+ if ( (qualNode->name == "xml:lang") && (qualNode->value == "x-default") ) {
+ assocNode = arrayNode->children[0];
+ assocIndex = 0;
+ assocIsXDefault = true;
+ }
+ }
+
+ }
+
+ // Delete the appropriate nodes.
+
+ XMP_NodePtrPos arrayBegin = arrayNode->children.begin();
+
+ if ( assocNode == 0 ) {
+ arrayNode->children.erase ( arrayBegin + itemIndex );
+ } else if ( itemIndex < assocIndex ) {
+ arrayNode->children.erase ( arrayBegin + assocIndex );
+ arrayNode->children.erase ( arrayBegin + itemIndex );
+ } else {
+ arrayNode->children.erase ( arrayBegin + itemIndex );
+ arrayNode->children.erase ( arrayBegin + assocIndex );
+ }
+
+ delete itemNode;
+ if ( assocNode != 0 ) delete assocNode;
+
+} // DeleteLocalizedText
// -------------------------------------------------------------------------------------------------
// GetProperty_Bool
@@ -1114,11 +1218,9 @@ XMPMeta::SetProperty_Bool ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper.
- XMP_StringPtr valueStr;
- XMP_StringLen valueLen;
-
- XMPUtils::ConvertFromBool ( propValue, &valueStr, &valueLen );
- SetProperty ( schemaNS, propName, valueStr, options );
+ XMP_VarString valueStr;
+ XMPUtils::ConvertFromBool ( propValue, &valueStr );
+ SetProperty ( schemaNS, propName, valueStr.c_str(), options );
} // SetProperty_Bool
@@ -1135,11 +1237,9 @@ XMPMeta::SetProperty_Int ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper.
- XMP_StringPtr valueStr;
- XMP_StringLen valueLen;
-
- XMPUtils::ConvertFromInt ( propValue, "", &valueStr, &valueLen );
- SetProperty ( schemaNS, propName, valueStr, options );
+ XMP_VarString valueStr;
+ XMPUtils::ConvertFromInt ( propValue, "", &valueStr );
+ SetProperty ( schemaNS, propName, valueStr.c_str(), options );
} // SetProperty_Int
@@ -1156,11 +1256,9 @@ XMPMeta::SetProperty_Int64 ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper.
- XMP_StringPtr valueStr;
- XMP_StringLen valueLen;
-
- XMPUtils::ConvertFromInt64 ( propValue, "", &valueStr, &valueLen );
- SetProperty ( schemaNS, propName, valueStr, options );
+ XMP_VarString valueStr;
+ XMPUtils::ConvertFromInt64 ( propValue, "", &valueStr );
+ SetProperty ( schemaNS, propName, valueStr.c_str(), options );
} // SetProperty_Int64
@@ -1177,11 +1275,9 @@ XMPMeta::SetProperty_Float ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper.
- XMP_StringPtr valueStr;
- XMP_StringLen valueLen;
-
- XMPUtils::ConvertFromFloat ( propValue, "", &valueStr, &valueLen );
- SetProperty ( schemaNS, propName, valueStr, options );
+ XMP_VarString valueStr;
+ XMPUtils::ConvertFromFloat ( propValue, "", &valueStr );
+ SetProperty ( schemaNS, propName, valueStr.c_str(), options );
} // SetProperty_Float
@@ -1198,11 +1294,9 @@ XMPMeta::SetProperty_Date ( XMP_StringPtr schemaNS,
{
XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper.
- XMP_StringPtr valueStr;
- XMP_StringLen valueLen;
-
- XMPUtils::ConvertFromDate ( propValue, &valueStr, &valueLen );
- SetProperty ( schemaNS, propName, valueStr, options );
+ XMP_VarString valueStr;
+ XMPUtils::ConvertFromDate ( propValue, &valueStr );
+ SetProperty ( schemaNS, propName, valueStr.c_str(), options );
} // SetProperty_Date
diff --git a/source/XMPCore/XMPMeta-Parse.cpp b/source/XMPCore/XMPMeta-Parse.cpp
index 5ff64f4..a70efff 100644
--- a/source/XMPCore/XMPMeta-Parse.cpp
+++ b/source/XMPCore/XMPMeta-Parse.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -258,18 +258,27 @@ NormalizeDCArrays ( XMP_Node * xmpTree )
arrayForm = VerifySetOptions ( arrayForm, 0 ); // Set the implicit array bits.
XMP_Node * newArray = new XMP_Node ( dcSchema, currProp->name.c_str(), arrayForm );
dcSchema->children[propNum] = newArray;
- newArray->children.push_back ( currProp );
- currProp->parent = newArray;
- currProp->name = kXMP_ArrayItemName;
- if ( XMP_ArrayIsAltText ( arrayForm ) && (! (currProp->options & kXMP_PropHasLang)) ) {
- XMP_Node * newLang = new XMP_Node ( currProp, "xml:lang", "x-default", kXMP_PropIsQualifier );
- currProp->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang);
- if ( currProp->qualifiers.empty() ) { // *** Need a util?
- currProp->qualifiers.push_back ( newLang );
- } else {
- currProp->qualifiers.insert ( currProp->qualifiers.begin(), newLang );
+ if ( currProp->value.empty() ) { // Don't add an empty item, leave the array empty.
+
+ delete ( currProp );
+
+ } else {
+
+ newArray->children.push_back ( currProp );
+ currProp->parent = newArray;
+ currProp->name = kXMP_ArrayItemName;
+
+ if ( XMP_ArrayIsAltText ( arrayForm ) && (! (currProp->options & kXMP_PropHasLang)) ) {
+ XMP_Node * newLang = new XMP_Node ( currProp, "xml:lang", "x-default", kXMP_PropIsQualifier );
+ currProp->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang);
+ if ( currProp->qualifiers.empty() ) { // *** Need a util?
+ currProp->qualifiers.push_back ( newLang );
+ } else {
+ currProp->qualifiers.insert ( currProp->qualifiers.begin(), newLang );
+ }
}
+
}
}
@@ -496,11 +505,7 @@ FixGPSTimeStamp ( XMP_Node * exifSchema, XMP_Node * gpsDateTime )
binGPSStamp.month = binOtherDate.month;
binGPSStamp.day = binOtherDate.day;
- XMP_StringPtr goodStr;
- XMP_StringLen goodLen;
- XMPUtils::ConvertFromDate ( binGPSStamp, &goodStr, &goodLen );
-
- gpsDateTime->value.assign ( goodStr, goodLen );
+ XMPUtils::ConvertFromDate ( binGPSStamp, &gpsDateTime->value );
} // FixGPSTimeStamp
@@ -1086,7 +1091,7 @@ XMPMeta::ParseFromBuffer ( XMP_StringPtr buffer,
if ( this->xmlParser == 0 ) {
if ( (xmpSize == 0) && lastClientCall ) return; // Tolerate empty parse. Expat complains if there are no XML elements.
- this->xmlParser = XMP_NewExpatAdapter();
+ this->xmlParser = XMP_NewExpatAdapter ( ExpatAdapter::kUseGlobalNamespaces );
}
XMLParserAdapter& parser = *this->xmlParser;
diff --git a/source/XMPCore/XMPMeta-Serialize.cpp b/source/XMPCore/XMPMeta-Serialize.cpp
index 0aa75ae..0ae2d12 100644
--- a/source/XMPCore/XMPMeta-Serialize.cpp
+++ b/source/XMPCore/XMPMeta-Serialize.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2003-2009 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -43,7 +43,7 @@ using namespace std;
static const char * kPacketHeader = "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>";
static const char * kPacketTrailer = "<?xpacket end=\"w\"?>"; // ! The w/r is at [size-4].
-static const char * kPXMP_SchemaGroup = "XMP_SchemaGroup";
+static const char * kTXMP_SchemaGroup = "XMP_SchemaGroup";
static const char * kRDF_XMPMetaStart = "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"";
static const char * kRDF_XMPMetaEnd = "</x:xmpmeta>";
@@ -134,13 +134,13 @@ EstimateRDFSize ( const XMP_Node * currNode, XMP_Index indent, size_t indentLen
// -------------------
static void
-DeclareOneNamespace ( const XMP_VarString & nsPrefix,
- const XMP_VarString & nsURI,
- XMP_VarString & usedNS, // ! A catenation of the prefixes with colons.
- XMP_VarString & outputStr,
- XMP_StringPtr newline,
- XMP_StringPtr indentStr,
- XMP_Index indent )
+DeclareOneNamespace ( XMP_StringPtr nsPrefix,
+ XMP_StringPtr nsURI,
+ XMP_VarString & usedNS, // ! A catenation of the prefixes with colons.
+ XMP_VarString & outputStr,
+ XMP_StringPtr newline,
+ XMP_StringPtr indentStr,
+ XMP_Index indent )
{
size_t nsPos = usedNS.find ( nsPrefix );
@@ -178,9 +178,10 @@ DeclareElemNamespace ( const XMP_VarString & elemName,
if ( colonPos != XMP_VarString::npos ) {
XMP_VarString nsPrefix ( elemName.substr ( 0, colonPos+1 ) );
- XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix );
- XMP_Enforce ( prefixPos != sNamespacePrefixToURIMap->end() );
- DeclareOneNamespace ( nsPrefix, prefixPos->second, usedNS, outputStr, newline, indentStr, indent );
+ XMP_StringPtr nsURI;
+ bool nsFound = sRegisteredNamespaces->GetURI ( nsPrefix.c_str(), &nsURI, 0 );
+ XMP_Enforce ( nsFound );
+ DeclareOneNamespace ( nsPrefix.c_str(), nsURI, usedNS, outputStr, newline, indentStr, indent );
}
} // DeclareElemNamespace
@@ -190,8 +191,6 @@ DeclareElemNamespace ( const XMP_VarString & elemName,
// DeclareUsedNamespaces
// ---------------------
-// ??? Should iterators be passed by reference to avoid temp copies?
-
static void
DeclareUsedNamespaces ( const XMP_Node * currNode,
XMP_VarString & usedNS,
@@ -203,7 +202,7 @@ DeclareUsedNamespaces ( const XMP_Node * currNode,
if ( currNode->options & kXMP_SchemaNode ) {
// The schema node name is the URI, the value is the prefix.
- DeclareOneNamespace ( currNode->value, currNode->name, usedNS, outputStr, newline, indentStr, indent );
+ DeclareOneNamespace ( currNode->value.c_str(), currNode->name.c_str(), usedNS, outputStr, newline, indentStr, indent );
} else if ( currNode->options & kXMP_PropValueIsStruct ) {
for ( size_t fieldNum = 0, fieldLim = currNode->children.size(); fieldNum < fieldLim; ++fieldNum ) {
const XMP_Node * currField = currNode->children[fieldNum];
@@ -228,8 +227,6 @@ DeclareUsedNamespaces ( const XMP_Node * currNode,
// EmitRDFArrayTag
// ---------------
-// ??? Should iterators be passed by reference to avoid temp copies?
-
enum {
kIsStartTag = true,
kIsEndTag = false
@@ -438,9 +435,8 @@ SerializePrettyRDFProperty ( const XMP_Node * propNode,
for ( level = indent; level > 0; --level ) outputStr += indentStr;
outputStr += '<';
outputStr += elemName;
-
- #define isCompact false
- bool hasGeneralQualifiers = isCompact; // Might also become true later.
+
+ bool hasGeneralQualifiers = false;
bool hasRDFResourceQual = false;
for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
@@ -476,7 +472,7 @@ SerializePrettyRDFProperty ( const XMP_Node * propNode,
outputStr += newline;
SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true );
-
+
for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
const XMP_Node * currQual = propNode->qualifiers[qualNum];
if ( IsRDFAttrQualifier ( currQual->name ) ) continue;
@@ -618,13 +614,8 @@ SerializePrettyRDFSchema ( const XMP_VarString & treeName,
outputStr += treeName;
outputStr += '"';
- size_t totalLen = 8; // Start at 8 for "xml:rdf:".
- XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin();
- XMP_cStringMapPos endPos = sNamespacePrefixToURIMap->end();
- for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size();
-
XMP_VarString usedNS;
- usedNS.reserve ( totalLen );
+ usedNS.reserve ( 400 ); // The predefined prefixes add up to about 320 bytes.
usedNS = "xml:rdf:";
DeclareUsedNamespaces ( schemaNode, usedNS, outputStr, newline, indentStr, baseIndent+4 );
@@ -632,36 +623,6 @@ SerializePrettyRDFSchema ( const XMP_VarString & treeName,
outputStr += newline;
// Write alias comments, if wanted.
-
- if ( options & kXMP_WriteAliasComments ) { // *** Hoist into a routine, used for Plain XMP also.
-
- #if 0 // *** Buggy, disable for now.
-
- XMP_cAliasMapPos aliasPos = sRegisteredAliasMap->begin();
- XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end();
-
- for ( ; aliasPos != aliasEnd; ++aliasPos ) {
-
- size_t nsPos = aliasPos->first.find ( schemaNode->value );
- if ( nsPos == XMP_VarString::npos ) continue;
- XMP_Assert ( nsPos == 0 );
-
- for ( level = baseIndent+3; level > 0; --level ) outputStr += indentStr;
-
- outputStr += "<!-- ";
- outputStr += aliasPos->first;
- outputStr += " is aliased to ";
- for ( size_t step = 1, stepLim = aliasPos->second.size(); step != stepLim; ++step ) {
- outputStr += aliasPos->second[step].step;
- }
- outputStr += " -->";
- outputStr += newline;
-
- }
-
- #endif
-
- }
// Write each of the schema's actual properties.
for ( size_t propNum = 0, propLim = schemaNode->children.size(); propNum < propLim; ++propNum ) {
@@ -785,9 +746,8 @@ SerializeCompactRDFElemProps ( const XMP_Node * parentNode,
for ( level = indent; level > 0; --level ) outputStr += indentStr;
outputStr += '<';
outputStr += elemName;
-
- #define isCompact false
- bool hasGeneralQualifiers = isCompact; // Might also become true later.
+
+ bool hasGeneralQualifiers = false;
bool hasRDFResourceQual = false;
for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
@@ -821,7 +781,7 @@ SerializeCompactRDFElemProps ( const XMP_Node * parentNode,
outputStr += newline;
SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true );
-
+
size_t qualNum = 0;
size_t qualLim = propNode->qualifiers.size();
if ( propNode->options & kXMP_PropHasLang ) ++qualNum;
@@ -993,14 +953,9 @@ SerializeCompactRDFSchemas ( const XMP_Node & xmpTree,
outputStr += '"';
// Write all necessary xmlns attributes.
-
- size_t totalLen = 8; // Start at 8 for "xml:rdf:".
- XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin();
- XMP_cStringMapPos endPos = sNamespacePrefixToURIMap->end();
- for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size();
XMP_VarString usedNS;
- usedNS.reserve ( totalLen );
+ usedNS.reserve ( 400 ); // The predefined prefixes add up to about 320 bytes.
usedNS = "xml:rdf:";
for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
@@ -1166,16 +1121,16 @@ SerializeAsRDF ( const XMPMeta & xmpObj,
// -----------------
void
-XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
- XMP_StringLen * rdfSize,
+XMPMeta::SerializeToBuffer ( XMP_VarString * rdfString,
XMP_OptionBits options,
XMP_StringLen padding,
XMP_StringPtr newline,
XMP_StringPtr indentStr,
XMP_Index baseIndent ) const
{
- XMP_Assert ( (rdfString != 0) && (rdfSize != 0) && (newline != 0) && (indentStr != 0) );
-
+ XMP_Assert ( (rdfString != 0) && (newline != 0) && (indentStr != 0) );
+ rdfString->erase();
+
// Fix up some default parameters.
enum { kDefaultPad = 2048 };
@@ -1222,7 +1177,11 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
}
padding = 0;
} else {
- if ( padding == 0 ) padding = kDefaultPad * unicodeUnitSize;
+ if ( padding == 0 ) {
+ padding = kDefaultPad * unicodeUnitSize;
+ } else if ( (padding >> 28) != 0 ) {
+ XMP_Throw ( "Outrageously large padding size", kXMPErr_BadOptions ); // Bigger than 256 MB.
+ }
if ( options & kXMP_IncludeThumbnailPad ) {
if ( ! this->DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) padding += (10000 * unicodeUnitSize); // *** Need a better estimate.
}
@@ -1232,11 +1191,11 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
std::string tailStr;
- SerializeAsRDF ( *this, *sOutputStr, tailStr, options, newline, indentStr, baseIndent );
+ SerializeAsRDF ( *this, *rdfString, tailStr, options, newline, indentStr, baseIndent );
if ( charEncoding == kXMP_EncodeUTF8 ) {
if ( options & kXMP_ExactPacketLength ) {
- size_t minSize = sOutputStr->size() + tailStr.size();
+ size_t minSize = rdfString->size() + tailStr.size();
if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
padding -= minSize; // Now the actual amount of padding to add.
}
@@ -1244,19 +1203,19 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
size_t newlineLen = strlen ( newline );
if ( padding < newlineLen ) {
- sOutputStr->append ( padding, ' ' );
+ rdfString->append ( padding, ' ' );
} else {
padding -= newlineLen; // Write this newline last.
while ( padding >= (100 + newlineLen) ) {
- sOutputStr->append ( 100, ' ' );
- *sOutputStr += newline;
+ rdfString->append ( 100, ' ' );
+ *rdfString += newline;
padding -= (100 + newlineLen);
}
- sOutputStr->append ( padding, ' ' );
- *sOutputStr += newline;
+ rdfString->append ( padding, ' ' );
+ *rdfString += newline;
}
- *sOutputStr += tailStr;
+ *rdfString += tailStr;
} else {
@@ -1269,13 +1228,13 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
std::string padStr ( " " ); padStr[0] = 0; // Assume big endian.
- utf8Str.swap ( *sOutputStr );
- ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian );
+ utf8Str.swap ( *rdfString );
+ ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), rdfString, bigEndian );
utf8Str.swap ( tailStr );
ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian );
if ( options & kXMP_ExactPacketLength ) {
- size_t minSize = sOutputStr->size() + tailStr.size();
+ size_t minSize = rdfString->size() + tailStr.size();
if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
padding -= minSize; // Now the actual amount of padding to add (in bytes).
}
@@ -1285,19 +1244,19 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
size_t newlineLen = newlineStr.size();
if ( padding < newlineLen ) {
- for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr;
+ for ( int i = padding/2; i > 0; --i ) *rdfString += padStr;
} else {
padding -= newlineLen; // Write this newline last.
while ( padding >= (200 + newlineLen) ) {
- for ( int i = 100; i > 0; --i ) *sOutputStr += padStr;
- *sOutputStr += newlineStr;
+ for ( int i = 100; i > 0; --i ) *rdfString += padStr;
+ *rdfString += newlineStr;
padding -= (200 + newlineLen);
}
- for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr;
- *sOutputStr += newlineStr;
+ for ( int i = padding/2; i > 0; --i ) *rdfString += padStr;
+ *rdfString += newlineStr;
}
- *sOutputStr += tailStr;
+ *rdfString += tailStr;
} else {
@@ -1309,13 +1268,13 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
Converter = UTF8_to_UTF32LE;
}
- utf8Str.swap ( *sOutputStr );
- ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian );
+ utf8Str.swap ( *rdfString );
+ ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), rdfString, bigEndian );
utf8Str.swap ( tailStr );
ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian );
if ( options & kXMP_ExactPacketLength ) {
- size_t minSize = sOutputStr->size() + tailStr.size();
+ size_t minSize = rdfString->size() + tailStr.size();
if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
padding -= minSize; // Now the actual amount of padding to add (in bytes).
}
@@ -1325,29 +1284,24 @@ XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
size_t newlineLen = newlineStr.size();
if ( padding < newlineLen ) {
- for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr;
+ for ( int i = padding/4; i > 0; --i ) *rdfString += padStr;
} else {
padding -= newlineLen; // Write this newline last.
while ( padding >= (400 + newlineLen) ) {
- for ( int i = 100; i > 0; --i ) *sOutputStr += padStr;
- *sOutputStr += newlineStr;
+ for ( int i = 100; i > 0; --i ) *rdfString += padStr;
+ *rdfString += newlineStr;
padding -= (400 + newlineLen);
}
- for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr;
- *sOutputStr += newlineStr;
+ for ( int i = padding/4; i > 0; --i ) *rdfString += padStr;
+ *rdfString += newlineStr;
}
- *sOutputStr += tailStr;
+ *rdfString += tailStr;
}
}
- // Return the finished string.
-
- *rdfString = sOutputStr->c_str();
- *rdfSize = sOutputStr->size();
-
} // SerializeToBuffer
// =================================================================================================
diff --git a/source/XMPCore/XMPMeta.cpp b/source/XMPCore/XMPMeta.cpp
index c5def31..44bee16 100644
--- a/source/XMPCore/XMPMeta.cpp
+++ b/source/XMPCore/XMPMeta.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -52,7 +52,7 @@ using namespace std;
// Static Variables
// ================
-XMP_VarString * xdefaultName = 0;
+XMP_VarString * xdefaultName = 0; // Needed in XMPMeta-Parse.cpp, MoveExplicitAliases.
// These are embedded version strings.
@@ -63,134 +63,16 @@ const char * kXMPCore_EmbeddedCopyright = kXMPCoreName " " kXMP_CopyrightStr;
// Local Utilities
// ===============
-#define IsHexDigit(ch) ( (('0' <= (ch)) && ((ch) <= '9')) || (('A' <= (ch)) && ((ch) <= 'F')) )
-#define HexDigitValue(ch) ( (((ch) - '0') < 10) ? ((ch) - '0') : ((ch) - 'A' + 10) )
-
-static const char * kTenSpaces = " ";
-#define OutProcPadding(pad) { size_t padLen = (pad); \
- for ( ; padLen >= 10; padLen -= 10 ) OutProcNChars ( kTenSpaces, 10 ); \
- for ( ; padLen > 0; padLen -= 1 ) OutProcNChars ( " ", 1 ); }
-
-
-#define OutProcNewline() { status = (*outProc) ( refCon, "\n", 1 ); if ( status != 0 ) goto EXIT; }
-
-#define OutProcNChars(p,n) { status = (*outProc) ( refCon, (p), (n) ); if ( status != 0 ) goto EXIT; }
-
-#define OutProcLiteral(lit) { status = (*outProc) ( refCon, (lit), strlen(lit) ); if ( status != 0 ) goto EXIT; }
-
-#define OutProcString(str) { status = (*outProc) ( refCon, (str).c_str(), (str).size() ); if ( status != 0 ) goto EXIT; }
-
-#define OutProcDecInt(num) { snprintf ( buffer, sizeof(buffer), "%d", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \
- status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; }
-
-#define OutProcHexInt(num) { snprintf ( buffer, sizeof(buffer), "%X", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \
- status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; }
-
-#define OutProcHexByte(num) { snprintf ( buffer, sizeof(buffer), "%.2X", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \
- status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; }
-
-static const char * kIndent = " ";
-#define OutProcIndent(lev) { for ( size_t i = 0; i < (lev); ++i ) OutProcNChars ( kIndent, 3 ); }
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpClearString
-// ---------------
-
-static XMP_Status
-DumpClearString ( const XMP_VarString & value, XMP_TextOutputProc outProc, void * refCon )
-{
-
- char buffer [20];
- bool prevNormal;
- XMP_Status status = 0;
-
- XMP_StringPtr spanStart, spanEnd;
- XMP_StringPtr valueEnd = &value[0] + value.size();
-
- spanStart = &value[0];
- while ( spanStart < valueEnd ) {
-
- // Output the next span of regular characters.
- for ( spanEnd = spanStart; spanEnd < valueEnd; ++spanEnd ) {
- if ( *spanEnd > 0x7F ) break;
- if ( (*spanEnd < 0x20) && (*spanEnd != kTab) && (*spanEnd != kLF) ) break;
- }
- if ( spanStart != spanEnd ) status = (*outProc) ( refCon, spanStart, (spanEnd-spanStart) );
- if ( status != 0 ) break;
- spanStart = spanEnd;
-
- // Output the next span of irregular characters.
- prevNormal = true;
- for ( spanEnd = spanStart; spanEnd < valueEnd; ++spanEnd ) {
- if ( ((0x20 <= *spanEnd) && (*spanEnd <= 0x7F)) || (*spanEnd == kTab) || (*spanEnd == kLF) ) break;
- char space = ' ';
- if ( prevNormal ) space = '<';
- status = (*outProc) ( refCon, &space, 1 );
- if ( status != 0 ) break;
- OutProcHexByte ( *spanEnd );
- prevNormal = false;
- }
- if ( ! prevNormal ) {
- status = (*outProc) ( refCon, ">", 1 );
- if ( status != 0 ) return status;
- }
- spanStart = spanEnd;
-
- }
-
-EXIT:
- return status;
-
-} // DumpClearString
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpStringMap
-// -------------
-
-static XMP_Status
-DumpStringMap ( const XMP_StringMap & map, XMP_StringPtr label, XMP_TextOutputProc outProc, void * refCon )
-{
- XMP_Status status;
- XMP_cStringMapPos currPos;
- XMP_cStringMapPos endPos = map.end();
-
- size_t maxLen = 0;
- for ( currPos = map.begin(); currPos != endPos; ++currPos ) {
- size_t currLen = currPos->first.size();
- if ( currLen > maxLen ) maxLen = currLen;
- }
-
- OutProcNewline();
- OutProcLiteral ( label );
- OutProcNewline();
-
- for ( currPos = map.begin(); currPos != endPos; ++currPos ) {
- OutProcNChars ( " ", 2 );
- DumpClearString ( currPos->first, outProc, refCon );
- OutProcPadding ( maxLen - currPos->first.size() );
- OutProcNChars ( " => ", 4 );
- DumpClearString ( currPos->second, outProc, refCon );
- OutProcNewline();
- }
-
-EXIT:
- return status;
-
-} // DumpStringMap
-
// -------------------------------------------------------------------------------------------------
// DumpNodeOptions
// ---------------
-static XMP_Status
+static void
DumpNodeOptions ( XMP_OptionBits options,
XMP_TextOutputProc outProc,
void * refCon )
{
- XMP_Status status;
char buffer [32]; // Decimal of a 64 bit int is at most about 20 digits.
static const char * optNames[] = { " schema", // 0x8000_0000
@@ -244,9 +126,6 @@ DumpNodeOptions ( XMP_OptionBits options,
OutProcNChars ( ")", 1 );
}
-
-EXIT:
- return status;
} // DumpNodeOptions
@@ -257,15 +136,14 @@ EXIT:
// *** Extract the validation code into a separate routine to call on exit in debug builds.
-static XMP_Status
+static void
DumpPropertyTree ( const XMP_Node * currNode,
int indent,
size_t itemIndex,
XMP_TextOutputProc outProc,
void * refCon )
{
- XMP_Status status;
- char buffer [32]; // Decimal of a 64 bit int is at most about 20 digits.
+ char buffer [32]; // Decimal of a 64 bit int is at most about 20 digits.
OutProcIndent ( (size_t)indent );
if ( itemIndex == 0 ) {
@@ -285,8 +163,7 @@ DumpPropertyTree ( const XMP_Node * currNode,
if ( currNode->options != 0 ) {
OutProcNChars ( " ", 2 );
- status = DumpNodeOptions ( currNode->options, outProc, refCon );
- if ( status != 0 ) goto EXIT;
+ DumpNodeOptions ( currNode->options, outProc, refCon );
}
if ( currNode->options & kXMP_PropHasLang ) {
@@ -322,8 +199,7 @@ DumpPropertyTree ( const XMP_Node * currNode,
if ( (qualNum != 0) || (! (currNode->options & kXMP_PropHasLang)) ) OutProcLiteral ( "** bad lang qual => " );
}
- status = DumpPropertyTree ( currQual, indent+2, 0, outProc, refCon );
- if ( status != 0 ) goto EXIT;
+ DumpPropertyTree ( currQual, indent+2, 0, outProc, refCon );
}
@@ -342,13 +218,9 @@ DumpPropertyTree ( const XMP_Node * currNode,
if ( currChild->name == kXMP_ArrayItemName ) OutProcLiteral ( "** bad field name => " );
}
- status = DumpPropertyTree ( currChild, indent+1, itemIndex, outProc, refCon );
- if ( status != 0 ) goto EXIT;
+ DumpPropertyTree ( currChild, indent+1, itemIndex, outProc, refCon );
}
-
-EXIT:
- return status;
} // DumpPropertyTree
@@ -575,6 +447,191 @@ SortWithinOffspring ( XMP_NodeOffspring & nodeVec )
} // SortWithinOffspring
+// -------------------------------------------------------------------------------------------------
+// RegisterAlias
+// -------------
+//
+// Allow 3 kinds of alias:
+// TopProp => TopProp
+// TopProp => TopArray[1]
+// TopProp => TopArray[@xml:lang='x-default']
+//
+// A new alias can be made to something that is already aliased, as long as the net result is one of
+// the legitimate forms. The new alias can already have aliases to it, also as long as result of
+// adjusting all of the exiting aliases leaves them legal.
+//
+// ! The caller assumes all risk that new aliases do not invalidate existing XMPMeta objects. Any
+// ! conflicts will result in later references throwing bad XPath exceptions.
+
+static void
+RegisterAlias ( XMP_StringPtr aliasNS,
+ XMP_StringPtr aliasProp,
+ XMP_StringPtr actualNS,
+ XMP_StringPtr actualProp,
+ XMP_OptionBits arrayForm )
+{
+ XMP_ExpandedXPath expAlias, expActual;
+ XMP_AliasMapPos mapPos;
+ XMP_ExpandedXPath * regActual = 0;
+
+ XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) && (actualNS != 0) && (actualProp != 0) ); // Enforced by wrapper.
+
+ // Expand the alias and actual names, make sure they are one of the basic 3 forms. When counting
+ // the expanded XPath size remember that the schema URI is the first component. We don't have to
+ // compare the schema URIs though, the (unique) prefix is part of the top property name.
+
+ ExpandXPath ( aliasNS, aliasProp, &expAlias );
+ ExpandXPath ( actualNS, actualProp, &expActual );
+ if ( (expAlias.size() != 2) || (expActual.size() != 2) ) {
+ XMP_Throw ( "Alias and actual property names must be simple", kXMPErr_BadXPath );
+ }
+
+ arrayForm = VerifySetOptions ( arrayForm, 0 );
+ if ( arrayForm != 0 ) {
+ if ( (arrayForm & ~kXMP_PropArrayFormMask) != 0 ) XMP_Throw ( "Only array form flags are allowed", kXMPErr_BadOptions );
+ expActual[1].options |= arrayForm; // Set the array form for the top level step.
+ if ( ! (arrayForm & kXMP_PropArrayIsAltText) ) {
+ expActual.push_back ( XPathStepInfo ( "[1]", kXMP_ArrayIndexStep ) );
+ } else {
+ expActual.push_back ( XPathStepInfo ( "[?xml:lang=\"x-default\"]", kXMP_QualSelectorStep ) );
+ }
+ }
+
+ // See if there are any conflicts with existing aliases. A couple of the checks are easy. If the
+ // alias is already aliased it is only OK to reregister an identical alias. If the actual is
+ // already aliased to something else and the new chain is legal, just swap in the old base.
+
+ mapPos = sRegisteredAliasMap->find ( expAlias[kRootPropStep].step );
+ if ( mapPos != sRegisteredAliasMap->end() ) {
+
+ // This alias is already registered to something, make sure it is the same something.
+
+ regActual = &mapPos->second;
+ if ( arrayForm != (mapPos->second[1].options & kXMP_PropArrayFormMask) ) {
+ XMP_Throw ( "Mismatch with existing alias array form", kXMPErr_BadParam );
+ }
+ if ( expActual.size() != regActual->size() ) {
+ XMP_Throw ( "Mismatch with existing actual path", kXMPErr_BadParam );
+ }
+ if ( expActual[kRootPropStep].step != (*regActual)[kRootPropStep].step ) {
+ XMP_Throw ( "Mismatch with existing actual name", kXMPErr_BadParam );
+ }
+ if ( (expActual.size() == 3) && (expActual[kAliasIndexStep].step != (*regActual)[kAliasIndexStep].step) ) {
+ XMP_Throw ( "Mismatch with existing actual array item", kXMPErr_BadParam );
+ }
+ return;
+
+ }
+
+ mapPos = sRegisteredAliasMap->find ( expActual[kRootPropStep].step );
+ if ( mapPos != sRegisteredAliasMap->end() ) {
+
+ // The actual is already aliased to something else.
+
+ regActual = &mapPos->second;
+ if ( expActual.size() == 2 ) {
+ expActual = *regActual; // TopProp => TopProp => anything : substitute the entire old base.
+ } else if ( regActual->size() != 2 ) {
+ XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam ); // TopProp => TopArray[] => TopArray[] : nope.
+ } else {
+ expActual[kSchemaStep].step = (*regActual)[kSchemaStep].step; // TopProp => TopArray[] => TopProp :
+ expActual[kRootPropStep].step = (*regActual)[kRootPropStep].step; // substitute the old base name.
+ }
+
+ }
+
+ // Checking for existing aliases to this one is touchier. This involves updating the alias map,
+ // which must not be done unless all of the changes are legal. So we need 2 loops, one to verify
+ // that everything is OK, and one to make the changes. The bad case is:
+ // TopProp => TopArray[] => TopArray[]
+ // In the valid cases we back substitute the new base.
+
+ for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) {
+ regActual = &mapPos->second;
+ if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) {
+ if ( (regActual->size() == 2) && (expAlias.size() == 2) ) {
+ XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam );
+ }
+ }
+ }
+
+ for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) {
+ regActual = &mapPos->second;
+ if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) {
+
+ if ( regActual->size() == 1 ) {
+ *regActual = expActual; // TopProp => TopProp => anything : substitute the entire new base.
+ } else {
+ (*regActual)[kSchemaStep].step = expActual[kSchemaStep].step; // TopProp => TopArray[] => TopProp :
+ (*regActual)[kRootPropStep].step = expActual[kRootPropStep].step; // substitute the new base name.
+ }
+
+ }
+ }
+
+ // Finally, all is OK to register the new alias.
+
+ (void) sRegisteredAliasMap->insert ( XMP_AliasMap::value_type ( expAlias[kRootPropStep].step, expActual ) );
+
+} // RegisterAlias
+
+
+// -------------------------------------------------------------------------------------------------
+// RegisterStandardAliases
+// -----------------------
+
+static void
+RegisterStandardAliases()
+{
+
+ // Aliases from XMP to DC.
+ RegisterAlias ( kXMP_NS_XMP, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
+ RegisterAlias ( kXMP_NS_XMP, "Authors", kXMP_NS_DC, "creator", 0 );
+ RegisterAlias ( kXMP_NS_XMP, "Description", kXMP_NS_DC, "description", 0 );
+ RegisterAlias ( kXMP_NS_XMP, "Format", kXMP_NS_DC, "format", 0 );
+ RegisterAlias ( kXMP_NS_XMP, "Keywords", kXMP_NS_DC, "subject", 0 );
+ RegisterAlias ( kXMP_NS_XMP, "Locale", kXMP_NS_DC, "language", 0 );
+ RegisterAlias ( kXMP_NS_XMP, "Title", kXMP_NS_DC, "title", 0 );
+ RegisterAlias ( kXMP_NS_XMP_Rights, "Copyright", kXMP_NS_DC, "rights", 0 );
+
+ // Aliases from PDF to DC and XMP.
+ RegisterAlias ( kXMP_NS_PDF, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
+ RegisterAlias ( kXMP_NS_PDF, "BaseURL", kXMP_NS_XMP, "BaseURL", 0 );
+ RegisterAlias ( kXMP_NS_PDF, "CreationDate", kXMP_NS_XMP, "CreateDate", 0 );
+ RegisterAlias ( kXMP_NS_PDF, "Creator", kXMP_NS_XMP, "CreatorTool", 0 );
+ RegisterAlias ( kXMP_NS_PDF, "ModDate", kXMP_NS_XMP, "ModifyDate", 0 );
+ RegisterAlias ( kXMP_NS_PDF, "Subject", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText );
+ RegisterAlias ( kXMP_NS_PDF, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText );
+
+ // Aliases from Photoshop to DC and XMP.
+ RegisterAlias ( kXMP_NS_Photoshop, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
+ RegisterAlias ( kXMP_NS_Photoshop, "Caption", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText );
+ RegisterAlias ( kXMP_NS_Photoshop, "Copyright", kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText );
+ RegisterAlias ( kXMP_NS_Photoshop, "Keywords", kXMP_NS_DC, "subject", 0 );
+ RegisterAlias ( kXMP_NS_Photoshop, "Marked", kXMP_NS_XMP_Rights, "Marked", 0 );
+ RegisterAlias ( kXMP_NS_Photoshop, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText );
+ RegisterAlias ( kXMP_NS_Photoshop, "WebStatement", kXMP_NS_XMP_Rights, "WebStatement", 0 );
+
+ // Aliases from TIFF and EXIF to DC and XMP.
+ RegisterAlias ( kXMP_NS_TIFF, "Artist", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered);
+ RegisterAlias ( kXMP_NS_TIFF, "Copyright", kXMP_NS_DC, "rights", 0 );
+ RegisterAlias ( kXMP_NS_TIFF, "DateTime", kXMP_NS_XMP, "ModifyDate", 0 );
+ RegisterAlias ( kXMP_NS_EXIF, "DateTimeDigitized", kXMP_NS_XMP, "CreateDate", 0 );
+ RegisterAlias ( kXMP_NS_TIFF, "ImageDescription", kXMP_NS_DC, "description", 0 );
+ RegisterAlias ( kXMP_NS_TIFF, "Software", kXMP_NS_XMP, "CreatorTool", 0 );
+
+ // Aliases from PNG to DC and XMP.
+ RegisterAlias ( kXMP_NS_PNG, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered);
+ RegisterAlias ( kXMP_NS_PNG, "Copyright", kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText);
+ RegisterAlias ( kXMP_NS_PNG, "CreationTime", kXMP_NS_XMP, "CreateDate", 0 );
+ RegisterAlias ( kXMP_NS_PNG, "Description", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText);
+ RegisterAlias ( kXMP_NS_PNG, "ModificationTime", kXMP_NS_XMP, "ModifyDate", 0 );
+ RegisterAlias ( kXMP_NS_PNG, "Software", kXMP_NS_XMP, "CreatorTool", 0 );
+ RegisterAlias ( kXMP_NS_PNG, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText);
+
+} // RegisterStandardAliases
+
+
// =================================================================================================
// Constructors
// ============
@@ -634,6 +691,14 @@ XMPMeta::GetVersionInfo ( XMP_VersionInfo * info )
// Initialize
// ----------
+#if XMP_TraceCoreCalls
+ FILE * xmpCoreLog = stderr;
+#endif
+
+#if UseGlobalLibraryLock
+ XMP_BasicMutex sLibraryLock;
+#endif
+
/* class-static */ bool
XMPMeta::Initialize()
{
@@ -642,21 +707,21 @@ XMPMeta::Initialize()
++sXMP_InitCount;
if ( sXMP_InitCount > 1 ) return true;
- #if TraceXMPCalls
- // xmpOut = fopen ( "xmp.out", "w" ); // Coordinate with client glue in WXMP_Common.hpp
- fprintf ( xmpOut, "XMP initializing\n" ); fflush ( xmpOut );
+ #if XMP_TraceCoreCallsToFile
+ xmpCoreLog = fopen ( "XMPCoreLog.txt", "w" );
+ if ( xmpCoreLog == 0 ) xmpCoreLog = stderr;
#endif
- sExceptionMessage = new XMP_VarString();
- XMP_InitMutex ( &sXMPCoreLock );
- sOutputNS = new XMP_VarString;
- sOutputStr = new XMP_VarString;
+ #if UseGlobalLibraryLock
+ InitializeBasicMutex ( sLibraryLock );
+ #endif
+
+ if ( ! Initialize_LibUtils() ) return false;
xdefaultName = new XMP_VarString ( "x-default" );
- sNamespaceURIToPrefixMap = new XMP_StringMap;
- sNamespacePrefixToURIMap = new XMP_StringMap;
- sRegisteredAliasMap = new XMP_AliasMap;
+ sRegisteredNamespaces = new XMP_NamespaceTable;
+ sRegisteredAliasMap = new XMP_AliasMap;
InitializeUnicodeConversions();
@@ -692,6 +757,8 @@ XMPMeta::Initialize()
(void) RegisterNamespace ( kXMP_NS_XMP_Note, "xmpNote", &voidPtr, &voidLen );
(void) RegisterNamespace ( kXMP_NS_DM, "xmpDM", &voidPtr, &voidLen );
+ (void) RegisterNamespace ( kXMP_NS_Script, "xmpScript", &voidPtr, &voidLen );
+ (void) RegisterNamespace ( kXMP_NS_BWF, "bext", &voidPtr, &voidLen );
(void) RegisterNamespace ( kXMP_NS_XMP_Text, "xmpT", &voidPtr, &voidLen );
(void) RegisterNamespace ( kXMP_NS_XMP_PagedFile, "xmpTPg", &voidPtr, &voidLen );
(void) RegisterNamespace ( kXMP_NS_XMP_Graphics, "xmpG", &voidPtr, &voidLen );
@@ -723,7 +790,7 @@ XMPMeta::Initialize()
(void) RegisterNamespace ( "adobe:ns:meta/", "x", &voidPtr, &voidLen );
(void) RegisterNamespace ( "http://ns.adobe.com/iX/1.0/", "iX", &voidPtr, &voidLen );
- XMPMeta::RegisterStandardAliases ( "" );
+ RegisterStandardAliases();
// Initialize the other core classes.
@@ -741,13 +808,13 @@ XMPMeta::Initialize()
XMP_Assert ( sizeof(XMP_Uns64) == 8 );
XMP_Assert ( sizeof(XMP_OptionBits) == 4 ); // Check that option masking work on all 32 bits.
- XMP_OptionBits flag = ~0UL;
+ XMP_OptionBits flag = (XMP_OptionBits) (~0UL);
XMP_Assert ( flag == (XMP_OptionBits)(-1L) );
XMP_Assert ( (flag ^ kXMP_PropHasLang) == 0xFFFFFFBFUL );
XMP_Assert ( (flag & ~kXMP_PropHasLang) == 0xFFFFFFBFUL );
XMP_OptionBits opt1 = 0; // Check the general option bit macros.
- XMP_OptionBits opt2 = ~0UL;
+ XMP_OptionBits opt2 = (XMP_OptionBits)~0UL;
XMP_SetOption ( opt1, kXMP_PropValueIsArray );
XMP_ClearOption ( opt2, kXMP_PropValueIsArray );
XMP_Assert ( opt1 == ~opt2 );
@@ -803,66 +870,31 @@ XMPMeta::Initialize()
// Terminate
// ---------
-#define EliminateGlobal(g) delete ( g ); g = 0
-
/* class-static */ void
XMPMeta::Terminate() RELEASE_NO_THROW
{
--sXMP_InitCount;
- if ( sXMP_InitCount > 0 ) return;
+ if ( sXMP_InitCount != 0 ) return; // Not ready to terminate, or already terminated.
- #if TraceXMPCalls
- fprintf ( xmpOut, "XMP terminating\n" ); fflush ( xmpOut );
- // fclose ( xmpOut ); // Coordinate with fopen in XMPMeta::Initialize.
- #endif
-
XMPIterator::Terminate();
XMPUtils::Terminate();
- EliminateGlobal ( sNamespaceURIToPrefixMap );
- EliminateGlobal ( sNamespacePrefixToURIMap );
+ EliminateGlobal ( sRegisteredNamespaces );
EliminateGlobal ( sRegisteredAliasMap );
EliminateGlobal ( xdefaultName );
- EliminateGlobal ( sOutputNS );
- EliminateGlobal ( sOutputStr );
- EliminateGlobal ( sExceptionMessage );
-
- XMP_TermMutex ( sXMPCoreLock );
-
-} // Terminate
-
-// -------------------------------------------------------------------------------------------------
-// Unlock
-// ------
+ Terminate_LibUtils();
-/* class-static */ void
-XMPMeta::Unlock ( XMP_OptionBits options )
-{
- options = options; // Avoid unused parameter warning. // *** Need IgnoreParam macro.
-
- #if TraceXMPLocking
- fprintf ( xmpOut, " Unlocking XMP toolkit, count = %d\n", sLockCount ); fflush ( xmpOut );
+ #if UseGlobalLibraryLock
+ TerminateBasicMutex ( sLibraryLock );
#endif
- --sLockCount;
- XMP_Assert ( sLockCount == 0 );
- XMP_ExitCriticalRegion ( sXMPCoreLock );
-
-} // Unlock
-
-
-// -------------------------------------------------------------------------------------------------
-// UnlockObject
-// ------------
-
-void
-XMPMeta::UnlockObject ( XMP_OptionBits options ) const
-{
- options = options; // Avoid unused parameter warning.
-
- XMPMeta::Unlock ( 0 );
-
-} // UnlockObject
+
+ #if XMP_TraceCoreCallsToFile
+ if ( xmpCoreLog != stderr ) fclose ( xmpCoreLog );
+ xmpCoreLog = stderr;
+ #endif
+
+} // Terminate
// -------------------------------------------------------------------------------------------------
@@ -877,128 +909,11 @@ XMPMeta::UnlockObject ( XMP_OptionBits options ) const
XMPMeta::DumpNamespaces ( XMP_TextOutputProc outProc,
void * refCon )
{
- XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper.
- XMP_Status status = 0;
-
- XMP_StringMapPos p2uEnd = sNamespacePrefixToURIMap->end(); // ! Move up to avoid gcc complaints.
- XMP_StringMapPos u2pEnd = sNamespaceURIToPrefixMap->end();
-
- status = DumpStringMap ( *sNamespacePrefixToURIMap, "Dumping namespace prefix to URI map", outProc, refCon );
- if ( status != 0 ) goto EXIT;
-
- if ( sNamespacePrefixToURIMap->size() != sNamespaceURIToPrefixMap->size() ) {
- OutProcLiteral ( "** bad namespace map sizes **" );
- XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure );
- }
-
- for ( XMP_StringMapPos nsLeft = sNamespacePrefixToURIMap->begin(); nsLeft != p2uEnd; ++nsLeft ) {
-
- XMP_StringMapPos nsOther = sNamespaceURIToPrefixMap->find ( nsLeft->second );
- if ( (nsOther == u2pEnd) || (nsLeft != sNamespacePrefixToURIMap->find ( nsOther->second )) ) {
- OutProcLiteral ( " ** bad namespace URI ** " );
- DumpClearString ( nsLeft->second, outProc, refCon );
- goto FAILURE;
- }
-
- for ( XMP_StringMapPos nsRight = nsLeft; nsRight != p2uEnd; ++nsRight ) {
- if ( nsRight == nsLeft ) continue; // ! Can't start at nsLeft+1, no operator+!
- if ( nsLeft->second == nsRight->second ) {
- OutProcLiteral ( " ** duplicate namespace URI ** " );
- DumpClearString ( nsLeft->second, outProc, refCon );
- goto FAILURE;
- }
- }
-
- }
-
- for ( XMP_StringMapPos nsLeft = sNamespaceURIToPrefixMap->begin(); nsLeft != u2pEnd; ++nsLeft ) {
-
- XMP_StringMapPos nsOther = sNamespacePrefixToURIMap->find ( nsLeft->second );
- if ( (nsOther == p2uEnd) || (nsLeft != sNamespaceURIToPrefixMap->find ( nsOther->second )) ) {
- OutProcLiteral ( " ** bad namespace prefix ** " );
- DumpClearString ( nsLeft->second, outProc, refCon );
- goto FAILURE;
- }
-
- for ( XMP_StringMapPos nsRight = nsLeft; nsRight != u2pEnd; ++nsRight ) {
- if ( nsRight == nsLeft ) continue; // ! Can't start at nsLeft+1, no operator+!
- if ( nsLeft->second == nsRight->second ) {
- OutProcLiteral ( " ** duplicate namespace prefix ** " );
- DumpClearString ( nsLeft->second, outProc, refCon );
- goto FAILURE;
- }
- }
-
- }
-EXIT:
- return status;
-
-FAILURE:
- OutProcNewline();
- (void) DumpStringMap ( *sNamespaceURIToPrefixMap, "Dumping namespace URI to prefix map", outProc, refCon );
- XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure );
+ sRegisteredNamespaces->Dump ( outProc, refCon );
return 0;
-
-} // DumpNamespaces
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpAliases
-// -----------
-
-/* class-static */ XMP_Status
-XMPMeta::DumpAliases ( XMP_TextOutputProc outProc,
- void * refCon )
-{
- XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper.
- XMP_Status status = 0;
-
- XMP_Assert ( sRegisteredAliasMap != 0 );
-
- XMP_cAliasMapPos aliasPos;
- XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end();
-
- size_t maxLen = 0;
- for ( aliasPos = sRegisteredAliasMap->begin(); aliasPos != aliasEnd; ++aliasPos ) {
- size_t currLen = aliasPos->first.size();
- if ( currLen > maxLen ) maxLen = currLen;
- }
-
- OutProcLiteral ( "Dumping alias name to actual path map" );
- OutProcNewline();
-
- for ( aliasPos = sRegisteredAliasMap->begin(); aliasPos != aliasEnd; ++aliasPos ) {
- OutProcNChars ( " ", 3 );
- DumpClearString ( aliasPos->first, outProc, refCon );
- OutProcPadding ( maxLen - aliasPos->first.size() );
- OutProcNChars ( " => ", 4 );
-
- size_t actualPathSize = aliasPos->second.size();
- for ( size_t stepNum = 1; stepNum < actualPathSize; ++stepNum ) OutProcString ( aliasPos->second[stepNum].step );
-
- XMP_OptionBits arrayForm = aliasPos->second[1].options & kXMP_PropArrayFormMask;
-
- if ( arrayForm == 0 ) {
- if ( actualPathSize != 2 ) OutProcLiteral ( " ** bad actual path **" );
- } else {
- OutProcNChars ( " ", 2 );
- DumpNodeOptions ( arrayForm, outProc, refCon );
- if ( ! (arrayForm & kXMP_PropValueIsArray) ) OutProcLiteral ( " ** bad array form **" );
- if ( actualPathSize != 3 ) OutProcLiteral ( " ** bad actual path **" );
- }
-
- if ( aliasPos->second[0].options != kXMP_SchemaNode ) OutProcLiteral ( " ** bad schema form **" );
-
- OutProcNewline();
-
- }
-
-EXIT:
- return status;
-
-} // DumpAliases
+} // DumpNamespaces
// -------------------------------------------------------------------------------------------------
@@ -1039,55 +954,9 @@ XMPMeta::RegisterNamespace ( XMP_StringPtr namespaceURI,
XMP_StringPtr * registeredPrefix,
XMP_StringLen * prefixSize )
{
- bool prefixMatches = false;
-
- XMP_Assert ( (registeredPrefix != 0) && (prefixSize != 0) ); // ! Enforced by wrapper.
- if ( (*namespaceURI == 0) || (*suggestedPrefix == 0) ) {
- XMP_Throw ( "Empty namespace URI or prefix", kXMPErr_BadParam );
- }
-
- XMP_VarString nsURI ( namespaceURI );
- XMP_VarString suggPrefix ( suggestedPrefix );
- if ( suggPrefix[suggPrefix.size()-1] != ':' ) suggPrefix += ':';
- VerifySimpleXMLName ( suggestedPrefix, suggestedPrefix+suggPrefix.size()-1 ); // Exclude the colon.
-
- XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( nsURI );
-
- if ( uriPos == sNamespaceURIToPrefixMap->end() ) {
-
- // The URI is not yet registered, make sure we use a unique prefix.
-
- XMP_VarString uniqPrefix ( suggPrefix );
- int suffix = 0;
- char buffer [32];
-
- while ( true ) {
- if ( sNamespacePrefixToURIMap->find ( uniqPrefix ) == sNamespacePrefixToURIMap->end() ) break;
- ++suffix;
- snprintf ( buffer, sizeof(buffer), "_%d_:", suffix ); // AUDIT: Using sizeof for snprintf length is safe.
- uniqPrefix = suggPrefix;
- uniqPrefix.erase ( uniqPrefix.size()-1 ); // ! Remove the trailing ':'.
- uniqPrefix += buffer;
- }
-
- // Add the new namespace to both maps.
-
- XMP_StringPair newNS ( nsURI, uniqPrefix );
- uriPos = sNamespaceURIToPrefixMap->insert ( sNamespaceURIToPrefixMap->end(), newNS );
-
- newNS.first.swap ( newNS.second );
- (void) sNamespacePrefixToURIMap->insert ( sNamespacePrefixToURIMap->end(), newNS );
- }
-
- // Return the actual prefix and see if it matches the suggested prefix.
-
- *registeredPrefix = uriPos->second.c_str();
- *prefixSize = uriPos->second.size();
-
- prefixMatches = ( uriPos->second == suggPrefix );
- return prefixMatches;
-
+ return sRegisteredNamespaces->Define ( namespaceURI, suggestedPrefix, registeredPrefix, prefixSize );
+
} // RegisterNamespace
@@ -1100,22 +969,9 @@ XMPMeta::GetNamespacePrefix ( XMP_StringPtr namespaceURI,
XMP_StringPtr * namespacePrefix,
XMP_StringLen * prefixSize )
{
- bool found = false;
-
- XMP_Assert ( *namespaceURI != 0 ); // ! Enforced by wrapper.
- XMP_Assert ( (namespacePrefix != 0) && (prefixSize != 0) ); // ! Enforced by wrapper.
- XMP_VarString nsURI ( namespaceURI );
- XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( nsURI );
-
- if ( uriPos != sNamespaceURIToPrefixMap->end() ) {
- *namespacePrefix = uriPos->second.c_str();
- *prefixSize = uriPos->second.size();
- found = true;
- }
-
- return found;
-
+ return sRegisteredNamespaces->GetPrefix ( namespaceURI, namespacePrefix, prefixSize );
+
} // GetNamespacePrefix
@@ -1128,24 +984,9 @@ XMPMeta::GetNamespaceURI ( XMP_StringPtr namespacePrefix,
XMP_StringPtr * namespaceURI,
XMP_StringLen * uriSize )
{
- bool found = false;
-
- XMP_Assert ( *namespacePrefix != 0 ); // ! Enforced by wrapper.
- XMP_Assert ( (namespacePrefix != 0) && (namespaceURI != 0) ); // ! Enforced by wrapper.
- XMP_VarString nsPrefix ( namespacePrefix );
- if ( nsPrefix[nsPrefix.size()-1] != ':' ) nsPrefix += ':';
-
- XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix );
-
- if ( prefixPos != sNamespacePrefixToURIMap->end() ) {
- *namespaceURI = prefixPos->second.c_str();
- *uriSize = prefixPos->second.size();
- found = true;
- }
-
- return found;
-
+ return sRegisteredNamespaces->GetURI ( namespacePrefix, namespaceURI, uriSize );
+
} // GetNamespaceURI
@@ -1161,291 +1002,11 @@ XMPMeta::GetNamespaceURI ( XMP_StringPtr namespacePrefix,
XMPMeta::DeleteNamespace ( XMP_StringPtr namespaceURI )
{
- XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( namespaceURI );
- if ( uriPos == sNamespaceURIToPrefixMap->end() ) return;
-
- XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( uriPos->second );
- XMP_Assert ( prefixPos != sNamespacePrefixToURIMap->end() );
-
- sNamespaceURIToPrefixMap->erase ( uriPos );
- sNamespacePrefixToURIMap->erase ( prefixPos );
+ XMP_Throw ( "Unimplemented method XMPMeta::DeleteNamespace", kXMPErr_Unimplemented );
} // DeleteNamespace
-// -------------------------------------------------------------------------------------------------
-// RegisterAlias
-// -------------
-//
-// Allow 3 kinds of alias:
-// TopProp => TopProp
-// TopProp => TopArray[1]
-// TopProp => TopArray[@xml:lang='x-default']
-//
-// A new alias can be made to something that is already aliased, as long as the net result is one of
-// the legitimate forms. The new alias can already have aliases to it, also as long as result of
-// adjusting all of the exiting aliases leaves them legal.
-//
-// ! The caller assumes all risk that new aliases do not invalidate existing XMPMeta objects. Any
-// ! conflicts will result in later references throwing bad XPath exceptions.
-
-/* class-static */ void
-XMPMeta::RegisterAlias ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- XMP_StringPtr actualNS,
- XMP_StringPtr actualProp,
- XMP_OptionBits arrayForm )
-{
- XMP_ExpandedXPath expAlias, expActual;
- XMP_AliasMapPos mapPos;
- XMP_ExpandedXPath * regActual = 0;
-
- XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) && (actualNS != 0) && (actualProp != 0) ); // Enforced by wrapper.
-
- // Expand the alias and actual names, make sure they are one of the basic 3 forms. When counting
- // the expanded XPath size remember that the schema URI is the first component. We don't have to
- // compare the schema URIs though, the (unique) prefix is part of the top property name.
-
- ExpandXPath ( aliasNS, aliasProp, &expAlias );
- ExpandXPath ( actualNS, actualProp, &expActual );
- if ( (expAlias.size() != 2) || (expActual.size() != 2) ) {
- XMP_Throw ( "Alias and actual property names must be simple", kXMPErr_BadXPath );
- }
-
- arrayForm = VerifySetOptions ( arrayForm, 0 );
- if ( arrayForm != 0 ) {
- if ( (arrayForm & ~kXMP_PropArrayFormMask) != 0 ) XMP_Throw ( "Only array form flags are allowed", kXMPErr_BadOptions );
- expActual[1].options |= arrayForm; // Set the array form for the top level step.
- if ( ! (arrayForm & kXMP_PropArrayIsAltText) ) {
- expActual.push_back ( XPathStepInfo ( "[1]", kXMP_ArrayIndexStep ) );
- } else {
- expActual.push_back ( XPathStepInfo ( "[?xml:lang=\"x-default\"]", kXMP_QualSelectorStep ) );
- }
- }
-
- // See if there are any conflicts with existing aliases. A couple of the checks are easy. If the
- // alias is already aliased it is only OK to reregister an identical alias. If the actual is
- // already aliased to something else and the new chain is legal, just swap in the old base.
-
- mapPos = sRegisteredAliasMap->find ( expAlias[kRootPropStep].step );
- if ( mapPos != sRegisteredAliasMap->end() ) {
-
- // This alias is already registered to something, make sure it is the same something.
-
- regActual = &mapPos->second;
- if ( arrayForm != (mapPos->second[1].options & kXMP_PropArrayFormMask) ) {
- XMP_Throw ( "Mismatch with existing alias array form", kXMPErr_BadParam );
- }
- if ( expActual.size() != regActual->size() ) {
- XMP_Throw ( "Mismatch with existing actual path", kXMPErr_BadParam );
- }
- if ( expActual[kRootPropStep].step != (*regActual)[kRootPropStep].step ) {
- XMP_Throw ( "Mismatch with existing actual name", kXMPErr_BadParam );
- }
- if ( (expActual.size() == 3) && (expActual[kAliasIndexStep].step != (*regActual)[kAliasIndexStep].step) ) {
- XMP_Throw ( "Mismatch with existing actual array item", kXMPErr_BadParam );
- }
- return;
-
- }
-
- mapPos = sRegisteredAliasMap->find ( expActual[kRootPropStep].step );
- if ( mapPos != sRegisteredAliasMap->end() ) {
-
- // The actual is already aliased to something else.
-
- regActual = &mapPos->second;
- if ( expActual.size() == 2 ) {
- expActual = *regActual; // TopProp => TopProp => anything : substitute the entire old base.
- } else if ( regActual->size() != 2 ) {
- XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam ); // TopProp => TopArray[] => TopArray[] : nope.
- } else {
- expActual[kSchemaStep].step = (*regActual)[kSchemaStep].step; // TopProp => TopArray[] => TopProp :
- expActual[kRootPropStep].step = (*regActual)[kRootPropStep].step; // substitute the old base name.
- }
-
- }
-
- // Checking for existing aliases to this one is touchier. This involves updating the alias map,
- // which must not be done unless all of the changes are legal. So we need 2 loops, one to verify
- // that everything is OK, and one to make the changes. The bad case is:
- // TopProp => TopArray[] => TopArray[]
- // In the valid cases we back substitute the new base.
-
- for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) {
- regActual = &mapPos->second;
- if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) {
- if ( (regActual->size() == 2) && (expAlias.size() == 2) ) {
- XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam );
- }
- }
- }
-
- for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) {
- regActual = &mapPos->second;
- if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) {
-
- if ( regActual->size() == 1 ) {
- *regActual = expActual; // TopProp => TopProp => anything : substitute the entire new base.
- } else {
- (*regActual)[kSchemaStep].step = expActual[kSchemaStep].step; // TopProp => TopArray[] => TopProp :
- (*regActual)[kRootPropStep].step = expActual[kRootPropStep].step; // substitute the new base name.
- }
-
- }
- }
-
- // Finally, all is OK to register the new alias.
-
- (void) sRegisteredAliasMap->insert ( XMP_AliasMap::value_type ( expAlias[kRootPropStep].step, expActual ) );
-
-} // RegisterAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// ResolveAlias
-// ------------
-
-/* class-static */ bool
-XMPMeta::ResolveAlias ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- XMP_StringPtr * actualNS,
- XMP_StringLen * nsSize,
- XMP_StringPtr * actualProp,
- XMP_StringLen * propSize,
- XMP_OptionBits * arrayForm )
-{
- XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) ); // Enforced by wrapper.
- XMP_Assert ( (actualNS != 0) && (nsSize != 0) && (actualProp != 0) && (propSize != 0) && (arrayForm != 0) ); // Enforced by wrapper.
-
- // Expand the input path and look up the first component in the alias table. Return if not an alias.
-
- XMP_ExpandedXPath fullPath, minPath;
- ExpandXPath ( aliasNS, aliasProp, &fullPath );
- XMP_Assert ( fullPath.size() >= 2 );
-
- minPath.push_back ( fullPath[kSchemaStep] );
- minPath.push_back ( fullPath[kRootPropStep] );
- XMP_AliasMapPos mapPos = sRegisteredAliasMap->find ( minPath[kRootPropStep].step );
- if ( mapPos == sRegisteredAliasMap->end() ) return false;
-
- // Replace the alias portion of the full expanded path. Compose the output path string.
-
- const XMP_ExpandedXPath & actualPath = mapPos->second;
-
- fullPath[kSchemaStep] = actualPath[kSchemaStep];
- fullPath[kRootPropStep] = actualPath[kRootPropStep];
- if ( actualPath.size() > 2 ) { // This is an alias to an array item.
- XMP_ExpandedXPathPos insertPos = fullPath.begin() + kAliasIndexStep;
- fullPath.insert ( insertPos, actualPath[kAliasIndexStep] );
- }
-
- *sOutputNS = fullPath[kSchemaStep].step;
- *actualNS = sOutputNS->c_str();
- *nsSize = sOutputNS->size();
-
- ComposeXPath ( fullPath, sOutputStr );
- *actualProp = sOutputStr->c_str();
- *propSize = sOutputStr->size();
-
- *arrayForm = actualPath[kRootPropStep].options & kXMP_PropArrayFormMask;
-
- #if XMP_DebugBuild // Test that the output string is valid and unchanged by round trip expand/compose.
- XMP_ExpandedXPath rtPath;
- ExpandXPath ( *actualNS, *actualProp, &rtPath );
- std::string rtString;
- ComposeXPath ( rtPath, &rtString );
- XMP_Assert ( rtString == *sOutputStr );
- #endif
-
- return true;
-
-} // ResolveAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteAlias
-// -----------
-
-/* class-static */ void
-XMPMeta::DeleteAlias ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp )
-{
-
- XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) ); // Enforced by wrapper.
- XMP_Throw ( "Unimplemented method XMPMeta::DeleteAlias", kXMPErr_Unimplemented ); // *** #error "write me"
- void * p; p = &aliasNS; p = &aliasProp; // Avoid unused param warnings.
-
-} // DeleteAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// RegisterStandardAliases
-// -----------------------
-
-/* class-static */ void
-XMPMeta::RegisterStandardAliases ( XMP_StringPtr schemaNS )
-{
- XMP_Assert ( schemaNS != 0 ); // Enforced by wrapper.
-
- const bool doAll = (*schemaNS == 0);
-
- if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_XMP ) ) {
- // Aliases from XMP to DC.
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Authors", kXMP_NS_DC, "creator", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Description", kXMP_NS_DC, "description", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Format", kXMP_NS_DC, "format", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Keywords", kXMP_NS_DC, "subject", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Locale", kXMP_NS_DC, "language", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Title", kXMP_NS_DC, "title", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_XMP_Rights, "Copyright", kXMP_NS_DC, "rights", 0 );
- }
-
- if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_PDF ) ) {
- // Aliases from PDF to DC and XMP.
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "BaseURL", kXMP_NS_XMP, "BaseURL", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "CreationDate", kXMP_NS_XMP, "CreateDate", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Creator", kXMP_NS_XMP, "CreatorTool", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "ModDate", kXMP_NS_XMP, "ModifyDate", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Subject", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText );
- XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText );
- }
-
- if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_Photoshop ) ) {
- // Aliases from PHOTOSHOP to DC and XMP.
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Caption", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText );
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Copyright", kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText );
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Keywords", kXMP_NS_DC, "subject", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Marked", kXMP_NS_XMP_Rights, "Marked", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText );
- XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "WebStatement", kXMP_NS_XMP_Rights, "WebStatement", 0 );
- }
-
- if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_TIFF ) || XMP_LitMatch ( schemaNS, kXMP_NS_EXIF ) ) {
- // Aliases from TIFF and EXIF to DC and XMP.
- XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Artist", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered);
- XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Copyright", kXMP_NS_DC, "rights", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "DateTime", kXMP_NS_XMP, "ModifyDate", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "ImageDescription", kXMP_NS_DC, "description", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Software", kXMP_NS_XMP, "CreatorTool", 0 );
- }
-
- if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_PNG ) ) { // ! From Acrobat ImageCapture:
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered);
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Copyright", kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText);
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "CreationTime", kXMP_NS_XMP, "CreateDate", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Description", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText);
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "ModificationTime", kXMP_NS_XMP, "ModifyDate", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Software", kXMP_NS_XMP, "CreatorTool", 0 );
- XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText);
- }
-
-} // RegisterStandardAliases
-
-
// =================================================================================================
// Class Methods
// =============
@@ -1458,18 +1019,16 @@ XMPMeta::RegisterStandardAliases ( XMP_StringPtr schemaNS )
// DumpObject
// ----------
-XMP_Status
+void
XMPMeta::DumpObject ( XMP_TextOutputProc outProc,
void * refCon ) const
{
XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper.
- XMP_Status status = 0;
OutProcLiteral ( "Dumping XMPMeta object \"" );
DumpClearString ( tree.name, outProc, refCon );
OutProcNChars ( "\" ", 3 );
- status = DumpNodeOptions ( tree.options, outProc, refCon );
- if ( status != 0 ) goto EXIT;
+ DumpNodeOptions ( tree.options, outProc, refCon );
#if 0 // *** XMP_DebugBuild
if ( (tree._namePtr != tree.name.c_str()) ||
(tree._valuePtr != tree.value.c_str()) ) OutProcLiteral ( " ** bad debug string **" );
@@ -1487,7 +1046,7 @@ XMPMeta::DumpObject ( XMP_TextOutputProc outProc,
OutProcLiteral ( "** bad root qualifiers **" );
OutProcNewline();
for ( size_t qualNum = 0, qualLim = tree.qualifiers.size(); qualNum < qualLim; ++qualNum ) {
- status = DumpPropertyTree ( tree.qualifiers[qualNum], 3, 0, outProc, refCon );
+ DumpPropertyTree ( tree.qualifiers[qualNum], 3, 0, outProc, refCon );
}
}
@@ -1503,8 +1062,7 @@ XMPMeta::DumpObject ( XMP_TextOutputProc outProc,
OutProcNChars ( " ", 2 );
DumpClearString ( currSchema->name, outProc, refCon );
OutProcNChars ( " ", 2 );
- status = DumpNodeOptions ( currSchema->options, outProc, refCon );
- if ( status != 0 ) goto EXIT;
+ DumpNodeOptions ( currSchema->options, outProc, refCon );
#if 0 // *** XMP_DebugBuild
if ( (currSchema->_namePtr != currSchema->name.c_str()) ||
(currSchema->_valuePtr != currSchema->value.c_str()) ) OutProcLiteral ( " ** bad debug string **" );
@@ -1531,9 +1089,6 @@ XMPMeta::DumpObject ( XMP_TextOutputProc outProc,
}
}
-
-EXIT:
- return status;
} // DumpObject
diff --git a/source/XMPCore/XMPMeta.hpp b/source/XMPCore/XMPMeta.hpp
index dca2c2a..e2d1693 100644
--- a/source/XMPCore/XMPMeta.hpp
+++ b/source/XMPCore/XMPMeta.hpp
@@ -2,7 +2,7 @@
#define __XMPMeta_hpp__
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -20,7 +20,7 @@
#define DumpXMLParseTree 0
#endif
-extern XMP_VarString * xdefaultName;
+extern XMP_VarString * xdefaultName; // Needed in XMPMeta-Parse.cpp, MoveExplicitAliases.
class XMPIterator;
class XMPUtils;
@@ -37,9 +37,6 @@ public:
Initialize();
static void
Terminate() RELEASE_NO_THROW;
-
- static void
- Unlock ( XMP_OptionBits options );
// ---------------------------------------------------------------------------------------------
@@ -61,10 +58,6 @@ public:
DumpNamespaces ( XMP_TextOutputProc outProc,
void * refCon );
- static XMP_Status
- DumpAliases ( XMP_TextOutputProc outProc,
- void * refCon );
-
// ---------------------------------------------------------------------------------------------
static bool
@@ -88,36 +81,6 @@ public:
// ---------------------------------------------------------------------------------------------
- static void
- RegisterAlias ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- XMP_StringPtr actualNS,
- XMP_StringPtr actualProp,
- XMP_OptionBits arrayForm );
-
- static bool
- ResolveAlias ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp,
- XMP_StringPtr * actualNS,
- XMP_StringLen * nsSize,
- XMP_StringPtr * actualProp,
- XMP_StringLen * propSize,
- XMP_OptionBits * arrayForm );
-
- static void
- DeleteAlias ( XMP_StringPtr aliasNS,
- XMP_StringPtr aliasProp );
-
- static void
- RegisterStandardAliases ( XMP_StringPtr schemaNS );
-
- // ---------------------------------------------------------------------------------------------
-
- void
- UnlockObject ( XMP_OptionBits options ) const;
-
- // ---------------------------------------------------------------------------------------------
-
bool
GetProperty ( XMP_StringPtr schemaNS,
XMP_StringPtr propName,
@@ -256,6 +219,12 @@ public:
XMP_StringPtr itemValue,
XMP_OptionBits options );
+ void
+ DeleteLocalizedText ( XMP_StringPtr schemaNS,
+ XMP_StringPtr altTextName,
+ XMP_StringPtr genericLang,
+ XMP_StringPtr specificLang);
+
// ---------------------------------------------------------------------------------------------
bool
@@ -348,7 +317,7 @@ public:
CountArrayItems ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName ) const;
- XMP_Status
+ void
DumpObject ( XMP_TextOutputProc outProc,
void * refCon ) const;
@@ -360,8 +329,7 @@ public:
XMP_OptionBits options );
void
- SerializeToBuffer ( XMP_StringPtr * rdfString,
- XMP_StringLen * rdfSize,
+ SerializeToBuffer ( XMP_VarString * rdfString,
XMP_OptionBits options,
XMP_StringLen padding,
XMP_StringPtr newline,
@@ -396,6 +364,10 @@ public:
// ! Expose the implementation so that file static functions can see the data.
XMP_Int32 clientRefs; // ! Must be signed to allow decrement from 0.
+ XMP_ReadWriteLock lock;
+
+ // ! Any data member changes must be propagted to the Clone function!
+
XMP_Int32 prevTkVer; // Previous toolkit version as MMmmuubbb (major, minor, micro, build).
XMP_Node tree;
diff --git a/source/XMPCore/XMPUtils-FileInfo.cpp b/source/XMPCore/XMPUtils-FileInfo.cpp
index ebfb9a5..c8d1e90 100644
--- a/source/XMPCore/XMPUtils-FileInfo.cpp
+++ b/source/XMPCore/XMPUtils-FileInfo.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -11,6 +11,8 @@
#include "XMPUtils.hpp"
+#include <algorithm> // For binary_search.
+
#include <time.h>
#include <string.h>
#include <stdlib.h>
@@ -431,6 +433,47 @@ ApplyQuotes ( XMP_VarString * item, UniCodePoint openQuote, UniCodePoint closeQu
// *** Need static checks of the schema prefixes!
+static const char * kExternalxmpDM[] =
+ { "xmpDM:album",
+ "xmpDM:altTapeName",
+ "xmpDM:altTimecode",
+ "xmpDM:artist",
+ "xmpDM:cameraAngle",
+ "xmpDM:cameraLabel",
+ "xmpDM:cameraModel",
+ "xmpDM:cameraMove",
+ "xmpDM:client",
+ "xmpDM:comment",
+ "xmpDM:composer",
+ "xmpDM:director",
+ "xmpDM:directorPhotography",
+ "xmpDM:engineer",
+ "xmpDM:genre",
+ "xmpDM:good",
+ "xmpDM:instrument",
+ "xmpDM:logComment",
+ "xmpDM:projectName",
+ "xmpDM:releaseDate",
+ "xmpDM:scene",
+ "xmpDM:shotDate",
+ "xmpDM:shotDay",
+ "xmpDM:shotLocation",
+ "xmpDM:shotName",
+ "xmpDM:shotNumber",
+ "xmpDM:shotSize",
+ "xmpDM:speakerPlacement",
+ "xmpDM:takeNumber",
+ "xmpDM:tapeName",
+ "xmpDM:trackNumber",
+ "xmpDM:videoAlphaMode",
+ "xmpDM:videoAlphaPremultipleColor",
+ 0 }; // ! Must have zero sentinel!
+
+typedef const char ** CharStarIterator; // Used for binary search of kExternalxmpDM;
+static const char ** kLastExternalxmpDM = 0; // Set on first use.
+static int CharStarLess (const char * left, const char * right )
+ { return (strcmp ( left, right ) < 0); }
+
#define IsExternalProperty(s,p) (! IsInternalProperty ( s, p ))
static bool
@@ -490,12 +533,28 @@ IsInternalProperty ( const XMP_VarString & schema, const XMP_VarString & prop )
} else if ( schema == kXMP_NS_CameraRaw ) {
- if ( (prop == "crs:Version") ||
- (prop == "crs:RawFileName") ||
- (prop == "crs:ToneCurveName") ) {
- isInternal = true;
+ isInternal = true; // All of crs: is internal, they are processing settings.
+
+ } else if ( schema == kXMP_NS_DM ) {
+
+ // ! Most of the xmpDM schema is internal, and unknown properties default to internal.
+ if ( kLastExternalxmpDM == 0 ) {
+ for ( kLastExternalxmpDM = &kExternalxmpDM[0]; *kLastExternalxmpDM != 0; ++kLastExternalxmpDM ) {}
}
+ isInternal = (! std::binary_search ( &kExternalxmpDM[0], kLastExternalxmpDM, prop.c_str(), CharStarLess ));
+
+ } else if ( schema == kXMP_NS_Script ) {
+
+ isInternal = true; // ! Most of the xmpScript schema is internal, and unknown properties default to internal.
+ if ( (prop == "xmpScript:action") || (prop == "xmpScript:character") || (prop == "xmpScript:dialog") ||
+ (prop == "xmpScript:sceneSetting") || (prop == "xmpScript:sceneTimeOfDay") ) {
+ isInternal = false;
+ }
+
+ } else if ( schema == kXMP_NS_BWF ) {
+ if ( prop == "bext:version" ) isInternal = true;
+
} else if ( schema == kXMP_NS_AdobeStockPhoto ) {
isInternal = true; // ! The bmsp schema has only internal properties.
@@ -634,127 +693,153 @@ ItemValuesMatch ( const XMP_Node * leftNode, const XMP_Node * rightNode )
// The main implementation of XMPUtils::AppendProperties. See the description in TXMPMeta.hpp.
static void
-AppendSubtree ( const XMP_Node * sourceNode, XMP_Node * destParent, const bool replaceOld, const bool deleteEmpty )
+AppendSubtree ( const XMP_Node * sourceNode, XMP_Node * destParent,
+ const bool mergeCompound, const bool replaceOld, const bool deleteEmpty )
{
XMP_NodePtrPos destPos;
XMP_Node * destNode = FindChildNode ( destParent, sourceNode->name.c_str(), kXMP_ExistingOnly, &destPos );
bool valueIsEmpty = false;
- if ( deleteEmpty ) {
- if ( XMP_PropIsSimple ( sourceNode->options ) ) {
- valueIsEmpty = sourceNode->value.empty();
- } else {
- valueIsEmpty = sourceNode->children.empty();
- }
+ if ( XMP_PropIsSimple ( sourceNode->options ) ) {
+ valueIsEmpty = sourceNode->value.empty();
+ } else {
+ valueIsEmpty = sourceNode->children.empty();
}
-
- if ( deleteEmpty & valueIsEmpty ) {
-
- if ( destNode != 0 ) {
+
+ if ( valueIsEmpty ) {
+ if ( deleteEmpty && (destNode != 0) ) {
delete ( destNode );
destParent->children.erase ( destPos );
}
+ return; // ! Done, empty values are either ignored or cause deletions.
+ }
- } else if ( destNode == 0 ) {
-
+ if ( destNode == 0 ) {
// The one easy case, the destination does not exist.
- CloneSubtree ( sourceNode, destParent );
+ destNode = CloneSubtree ( sourceNode, destParent, true /* skipEmpty */ );
+ XMP_Assert ( (destNode == 0) || (! destNode->value.empty()) || (! destNode->children.empty()) );
+ return;
+ }
+
+ // If we get here we're going to modify an existing property, either replacing or merging.
+
+ XMP_Assert ( (! valueIsEmpty) && (destNode != 0) );
- } else if ( replaceOld ) {
+ XMP_OptionBits sourceForm = sourceNode->options & kXMP_PropCompositeMask;
+ XMP_OptionBits destForm = destNode->options & kXMP_PropCompositeMask;
- // The destination exists and should be replaced.
+ bool replaceThis = replaceOld; // ! Don't modify replaceOld, it gets passed to inner calls.
+ if ( mergeCompound && (! XMP_PropIsSimple ( sourceForm )) ) replaceThis = false;
+
+ if ( replaceThis ) {
destNode->value = sourceNode->value; // *** Should use SetNode.
destNode->options = sourceNode->options;
destNode->RemoveChildren();
destNode->RemoveQualifiers();
- CloneOffspring ( sourceNode, destNode );
+ CloneOffspring ( sourceNode, destNode, true /* skipEmpty */ );
+
+ if ( (! XMP_PropIsSimple ( destNode->options )) && destNode->children.empty() ) {
+ // Don't keep an empty array or struct. The source might be implicitly empty due to
+ // all children being empty. In this case CloneOffspring should skip them.
+ DeleteSubtree ( destPos );
+ }
- #if 0 // *** XMP_DebugBuild
- destNode->_valuePtr = destNode->value.c_str();
- #endif
-
- } else {
+ return;
- // The destination exists and is not totally replaced. Structs and arrays are merged.
+ }
+
+ // From here on are cases for merging arrays or structs.
+
+ if ( XMP_PropIsSimple ( sourceForm ) || (sourceForm != destForm) ) return;
+
+ if ( sourceForm == kXMP_PropValueIsStruct ) {
+
+ // To merge a struct process the fields recursively. E.g. add simple missing fields. The
+ // recursive call to AppendSubtree will handle deletion for fields with empty values.
- XMP_OptionBits sourceForm = sourceNode->options & kXMP_PropCompositeMask;
- XMP_OptionBits destForm = destNode->options & kXMP_PropCompositeMask;
- if ( sourceForm != destForm ) return;
-
- if ( sourceForm == kXMP_PropValueIsStruct ) {
-
- // To merge a struct process the fields recursively. E.g. add simple missing fields. The
- // recursive call to AppendSubtree will handle deletion for fields with empty values.
-
- for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
- const XMP_Node * sourceField = sourceNode->children[sourceNum];
- AppendSubtree ( sourceField, destNode, replaceOld, deleteEmpty );
- if ( deleteEmpty && destNode->children.empty() ) {
- delete ( destNode );
- destParent->children.erase ( destPos );
- }
+ for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
+ const XMP_Node * sourceField = sourceNode->children[sourceNum];
+ AppendSubtree ( sourceField, destNode, mergeCompound, replaceOld, deleteEmpty );
+ if ( deleteEmpty && destNode->children.empty() ) {
+ delete ( destNode );
+ destParent->children.erase ( destPos );
}
-
- } else if ( sourceForm & kXMP_PropArrayIsAltText ) {
+ }
- // Merge AltText arrays by the xml:lang qualifiers. Make sure x-default is first. Make a
- // special check for deletion of empty values. Meaningful in AltText arrays because the
- // xml:lang qualifier provides unambiguous source/dest correspondence.
+ } else if ( sourceForm & kXMP_PropArrayIsAltText ) {
+
+ // Merge AltText arrays by the xml:lang qualifiers. Make sure x-default is first. Make a
+ // special check for deletion of empty values. Meaningful in AltText arrays because the
+ // xml:lang qualifier provides unambiguous source/dest correspondence.
+
+ XMP_Assert ( mergeCompound );
- for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
+ for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
- const XMP_Node * sourceItem = sourceNode->children[sourceNum];
- if ( sourceItem->qualifiers.empty() || (sourceItem->qualifiers[0]->name != "xml:lang") ) continue;
-
- XMP_Index destIndex = LookupLangItem ( destNode, sourceItem->qualifiers[0]->value );
-
- if ( deleteEmpty && sourceItem->value.empty() ) {
-
- if ( destIndex != -1 ) {
- delete ( destNode->children[destIndex] );
- destNode->children.erase ( destNode->children.begin() + destIndex );
- if ( destNode->children.empty() ) {
- delete ( destNode );
- destParent->children.erase ( destPos );
- }
+ const XMP_Node * sourceItem = sourceNode->children[sourceNum];
+ if ( sourceItem->qualifiers.empty() || (sourceItem->qualifiers[0]->name != "xml:lang") ) continue;
+
+ XMP_Index destIndex = LookupLangItem ( destNode, sourceItem->qualifiers[0]->value );
+
+ if ( sourceItem->value.empty() ) {
+
+ if ( deleteEmpty && (destIndex != -1) ) {
+ delete ( destNode->children[destIndex] );
+ destNode->children.erase ( destNode->children.begin() + destIndex );
+ if ( destNode->children.empty() ) {
+ delete ( destNode );
+ destParent->children.erase ( destPos );
}
+ }
- } else {
+ } else {
+
+ if ( destIndex != -1 ) {
- if ( destIndex != -1 ) continue; // Not replacing, keep the existing item.
+ // The source and dest arrays both have this language item.
+
+ if ( replaceOld ) { // ! Yes, check replaceOld not replaceThis!
+ destNode->children[destIndex]->value = sourceItem->value;
+ }
+
+ } else {
+ // The dest array does not have this language item, add it.
+
if ( (sourceItem->qualifiers[0]->value != "x-default") || destNode->children.empty() ) {
- CloneSubtree ( sourceItem, destNode );
+ // Typical case, empty dest array or not "x-default". Non-empty should always have "x-default".
+ CloneSubtree ( sourceItem, destNode, true /* skipEmpty */ );
} else {
+ // Edge case, non-empty dest array had no "x-default", insert that at the beginning.
XMP_Node * destItem = new XMP_Node ( destNode, sourceItem->name, sourceItem->value, sourceItem->options );
- CloneOffspring ( sourceItem, destItem );
+ CloneOffspring ( sourceItem, destItem, true /* skipEmpty */ );
destNode->children.insert ( destNode->children.begin(), destItem );
- }
+ }
}
-
+
}
-
- } else if ( sourceForm & kXMP_PropValueIsArray ) {
-
- // Merge other arrays by item values. Don't worry about order or duplicates. Source
- // items with empty values do not cause deletion, that conflicts horribly with merging.
- for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
- const XMP_Node * sourceItem = sourceNode->children[sourceNum];
+ }
+
+ } else if ( sourceForm & kXMP_PropValueIsArray ) {
+
+ // Merge other arrays by item values. Don't worry about order or duplicates. Source
+ // items with empty values do not cause deletion, that conflicts horribly with merging.
- size_t destNum, destLim;
- for ( destNum = 0, destLim = destNode->children.size(); destNum != destLim; ++destNum ) {
- const XMP_Node * destItem = destNode->children[destNum];
- if ( ItemValuesMatch ( sourceItem, destItem ) ) break;
- }
- if ( destNum == destLim ) CloneSubtree ( sourceItem, destNode );
+ for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
+ const XMP_Node * sourceItem = sourceNode->children[sourceNum];
+ size_t destNum, destLim;
+ for ( destNum = 0, destLim = destNode->children.size(); destNum != destLim; ++destNum ) {
+ const XMP_Node * destItem = destNode->children[destNum];
+ if ( ItemValuesMatch ( sourceItem, destItem ) ) break;
}
-
- }
+ if ( destNum == destLim ) CloneSubtree ( sourceItem, destNode, true /* skipEmpty */ );
+ }
+
}
} // AppendSubtree
@@ -775,11 +860,10 @@ XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj,
XMP_StringPtr separator,
XMP_StringPtr quotes,
XMP_OptionBits options,
- XMP_StringPtr * catedStr,
- XMP_StringLen * catedLen )
+ XMP_VarString * catedStr )
{
XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // ! Enforced by wrapper.
- XMP_Assert ( (separator != 0) && (quotes != 0) && (catedStr != 0) && (catedLen != 0) ); // ! Enforced by wrapper.
+ XMP_Assert ( (separator != 0) && (quotes != 0) && (catedStr != 0) ); // ! Enforced by wrapper.
size_t strLen, strPos, charLen;
UniCharKind charKind;
@@ -828,19 +912,19 @@ XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj,
// Return an empty result if the array does not exist, hurl if it isn't the right form.
- sCatenatedItems->erase();
+ catedStr->erase();
XMP_ExpandedXPath arrayPath;
ExpandXPath ( schemaNS, arrayName, &arrayPath );
arrayNode = FindConstNode ( &xmpObj.tree, arrayPath );
- if ( arrayNode == 0 ) goto EXIT; // ! Need to set the output pointer and length.
+ if ( arrayNode == 0 ) return;
arrayForm = arrayNode->options & kXMP_PropCompositeMask;
if ( (! (arrayForm & kXMP_PropValueIsArray)) || (arrayForm & kXMP_PropArrayIsAlternate) ) {
XMP_Throw ( "Named property must be non-alternate array", kXMPErr_BadParam );
}
- if ( arrayNode->children.empty() ) goto EXIT; // ! Need to set the output pointer and length.
+ if ( arrayNode->children.empty() ) return;
// Build the result, quoting the array items, adding separators. Hurl if any item isn't simple.
// Start the result with the first value, then add the rest with a preceeding separator.
@@ -848,21 +932,17 @@ XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj,
currItem = arrayNode->children[0];
if ( (currItem->options & kXMP_PropCompositeMask) != 0 ) XMP_Throw ( "Array items must be simple", kXMPErr_BadParam );
- *sCatenatedItems = currItem->value;
- ApplyQuotes ( sCatenatedItems, openQuote, closeQuote, allowCommas );
+ *catedStr = currItem->value;
+ ApplyQuotes ( catedStr, openQuote, closeQuote, allowCommas );
for ( size_t itemNum = 1, itemLim = arrayNode->children.size(); itemNum != itemLim; ++itemNum ) {
const XMP_Node * currItem = arrayNode->children[itemNum];
if ( (currItem->options & kXMP_PropCompositeMask) != 0 ) XMP_Throw ( "Array items must be simple", kXMPErr_BadParam );
XMP_VarString tempStr ( currItem->value );
ApplyQuotes ( &tempStr, openQuote, closeQuote, allowCommas );
- *sCatenatedItems += separator;
- *sCatenatedItems += tempStr;
+ *catedStr += separator;
+ *catedStr += tempStr;
}
-
-EXIT:
- *catedStr = sCatenatedItems->c_str();
- *catedLen = sCatenatedItems->size();
} // CatenateArrayItems
@@ -1037,6 +1117,120 @@ XMPUtils::SeparateArrayItems ( XMPMeta * xmpObj,
// -------------------------------------------------------------------------------------------------
+// ApplyTemplate
+// -------------
+
+/* class static */ void
+XMPUtils::ApplyTemplate ( XMPMeta * workingXMP,
+ const XMPMeta & templateXMP,
+ XMP_OptionBits actions )
+{
+ bool doClear = XMP_OptionIsSet ( actions, kXMPTemplate_ClearUnnamedProperties );
+ bool doAdd = XMP_OptionIsSet ( actions, kXMPTemplate_AddNewProperties );
+ bool doReplace = XMP_OptionIsSet ( actions, kXMPTemplate_ReplaceExistingProperties );
+
+ bool deleteEmpty = XMP_OptionIsSet ( actions, kXMPTemplate_ReplaceWithDeleteEmpty );
+ doReplace |= deleteEmpty; // Delete-empty implies Replace.
+ deleteEmpty &= (! doClear); // Clear implies not delete-empty, but keep the implicit Replace.
+
+ bool doAll = XMP_OptionIsSet ( actions, kXMPTemplate_IncludeInternalProperties );
+
+ // ! In several places we do loops backwards so that deletions do not perturb the remaining indices.
+ // ! These loops use ordinals (size .. 1), we must use a zero based index inside the loop.
+
+ if ( doClear ) {
+
+ // Visit the top level working properties, delete if not in the template.
+
+ for ( size_t schemaOrdinal = workingXMP->tree.children.size(); schemaOrdinal > 0; --schemaOrdinal ) {
+
+ size_t schemaNum = schemaOrdinal-1; // ! Convert ordinal to index!
+ XMP_Node * workingSchema = workingXMP->tree.children[schemaNum];
+ const XMP_Node * templateSchema = FindConstSchema ( &templateXMP.tree, workingSchema->name.c_str() );
+
+ if ( templateSchema == 0 ) {
+
+ // The schema is not in the template, delete all properties or just all external ones.
+
+ if ( doAll ) {
+
+ workingSchema->RemoveChildren(); // Remove the properties here, delete the schema below.
+
+ } else {
+
+ for ( size_t propOrdinal = workingSchema->children.size(); propOrdinal > 0; --propOrdinal ) {
+ size_t propNum = propOrdinal-1; // ! Convert ordinal to index!
+ XMP_Node * workingProp = workingSchema->children[propNum];
+ if ( IsExternalProperty ( workingSchema->name, workingProp->name ) ) {
+ delete ( workingProp );
+ workingSchema->children.erase ( workingSchema->children.begin() + propNum );
+ }
+ }
+
+ }
+
+ } else {
+
+ // Check each of the working XMP's properties to see if it is in the template.
+
+ for ( size_t propOrdinal = workingSchema->children.size(); propOrdinal > 0; --propOrdinal ) {
+ size_t propNum = propOrdinal-1; // ! Convert ordinal to index!
+ XMP_Node * workingProp = workingSchema->children[propNum];
+ if ( (doAll || IsExternalProperty ( workingSchema->name, workingProp->name )) &&
+ (FindConstChild ( templateSchema, workingProp->name.c_str() ) == 0) ) {
+ delete ( workingProp );
+ workingSchema->children.erase ( workingSchema->children.begin() + propNum );
+ }
+ }
+
+ }
+
+ if ( workingSchema->children.empty() ) {
+ delete ( workingSchema );
+ workingXMP->tree.children.erase ( workingXMP->tree.children.begin() + schemaNum );
+ }
+
+ }
+
+ }
+
+ if ( doAdd | doReplace ) {
+
+ for ( size_t schemaNum = 0, schemaLim = templateXMP.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {
+
+ const XMP_Node * templateSchema = templateXMP.tree.children[schemaNum];
+
+ // Make sure we have an output schema node, then process the top level template properties.
+
+ XMP_NodePtrPos workingSchemaPos;
+ XMP_Node * workingSchema = FindSchemaNode ( &workingXMP->tree, templateSchema->name.c_str(),
+ kXMP_ExistingOnly, &workingSchemaPos );
+ if ( workingSchema == 0 ) {
+ workingSchema = new XMP_Node ( &workingXMP->tree, templateSchema->name, templateSchema->value, kXMP_SchemaNode );
+ workingXMP->tree.children.push_back ( workingSchema );
+ workingSchemaPos = workingXMP->tree.children.end() - 1;
+ }
+
+ for ( size_t propNum = 0, propLim = templateSchema->children.size(); propNum < propLim; ++propNum ) {
+ const XMP_Node * templateProp = templateSchema->children[propNum];
+ if ( doAll || IsExternalProperty ( templateSchema->name, templateProp->name ) ) {
+ AppendSubtree ( templateProp, workingSchema, doAdd, doReplace, deleteEmpty );
+ }
+ }
+
+ if ( workingSchema->children.empty() ) {
+ delete ( workingSchema );
+ workingXMP->tree.children.erase ( workingSchemaPos );
+ }
+
+ }
+
+ }
+
+} // ApplyTemplate
+
+
+// -------------------------------------------------------------------------------------------------
// RemoveProperties
// ----------------
@@ -1136,58 +1330,6 @@ XMPUtils::RemoveProperties ( XMPMeta * xmpObj,
// -------------------------------------------------------------------------------------------------
-// AppendProperties
-// ----------------
-
-/* class static */ void
-XMPUtils::AppendProperties ( const XMPMeta & source,
- XMPMeta * dest,
- XMP_OptionBits options )
-{
- XMP_Assert ( dest != 0 ); // ! Enforced by wrapper.
-
- const bool doAll = ((options & kXMPUtil_DoAllProperties) != 0);
- const bool replaceOld = ((options & kXMPUtil_ReplaceOldValues) != 0);
- const bool deleteEmpty = ((options & kXMPUtil_DeleteEmptyValues) != 0);
-
- for ( size_t schemaNum = 0, schemaLim = source.tree.children.size(); schemaNum != schemaLim; ++schemaNum ) {
-
- const XMP_Node * sourceSchema = source.tree.children[schemaNum];
-
- // Make sure we have a destination schema node. Remember if it is newly created.
-
- XMP_Node * destSchema = FindSchemaNode ( &dest->tree, sourceSchema->name.c_str(), kXMP_ExistingOnly );
- const bool newDestSchema = (destSchema == 0);
- if ( newDestSchema ) {
- destSchema = new XMP_Node ( &dest->tree, sourceSchema->name, sourceSchema->value, kXMP_SchemaNode );
- dest->tree.children.push_back ( destSchema );
- }
-
- // Process the source schema's children. Do this backwards in case deleteEmpty is set.
-
- for ( long propNum = ((long)sourceSchema->children.size() - 1); propNum >= 0; --propNum ) {
- const XMP_Node * sourceProp = sourceSchema->children[propNum];
- if ( doAll || IsExternalProperty ( sourceSchema->name, sourceProp->name ) ) {
- AppendSubtree ( sourceProp, destSchema, replaceOld, deleteEmpty );
-// *** RemoveMultiValueInfo ( dest, sourceSchema->name.c_str(), sourceProp->name.c_str() );
- }
- }
-
- if ( destSchema->children.empty() ) {
- if ( newDestSchema ) {
- delete ( destSchema );
- dest->tree.children.pop_back();
- } else if ( deleteEmpty ) {
- DeleteEmptySchema ( destSchema );
- }
- }
-
- }
-
-} // AppendProperties
-
-
-// -------------------------------------------------------------------------------------------------
// DuplicateSubtree
// ----------------
diff --git a/source/XMPCore/XMPUtils.cpp b/source/XMPCore/XMPUtils.cpp
index 0cfe497..3729ed1 100644
--- a/source/XMPCore/XMPUtils.cpp
+++ b/source/XMPCore/XMPUtils.cpp
@@ -1,5 +1,5 @@
// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -28,7 +28,6 @@
#pragma warning ( disable : 4996 ) // '...' was declared deprecated
#endif
-
// =================================================================================================
// Local Types and Constants
// =========================
@@ -36,30 +35,17 @@
static const char * sBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// =================================================================================================
-// Static Variables
-// ================
-
-XMP_VarString * sComposedPath = 0; // *** Only really need 1 string. Shrink periodically?
-XMP_VarString * sConvertedValue = 0;
-XMP_VarString * sBase64Str = 0;
-XMP_VarString * sCatenatedItems = 0;
-XMP_VarString * sStandardXMP = 0;
-XMP_VarString * sExtendedXMP = 0;
-XMP_VarString * sExtendedDigest = 0;
-
-// =================================================================================================
// Local Utilities
// ===============
-
// -------------------------------------------------------------------------------------------------
// ANSI Time Functions
// -------------------
//
// A bit of hackery to use the best available time functions. Mac and UNIX have thread safe versions
-// of gmtime and localtime. On Mac the CodeWarrior functions are buggy, use Apple's.
+// of gmtime and localtime.
-#if XMP_UNIXBuild
+#if XMP_MacBuild | XMP_UNIXBuild
typedef time_t ansi_tt;
typedef struct tm ansi_tm;
@@ -101,69 +87,22 @@ XMP_VarString * sExtendedDigest = 0;
}
#endif
-#elif XMP_MacBuild
-
- #if ! __MWERKS__
-
- typedef time_t ansi_tt;
- typedef struct tm ansi_tm;
-
- #define ansi_time time
- #define ansi_mktime mktime
- #define ansi_difftime difftime
-
- #define ansi_gmtime gmtime_r
- #define ansi_localtime localtime_r
-
- #else
-
- // ! The CW versions are buggy. Use Apple's code, time_t, and "struct tm".
-
- #include <mach-o/dyld.h>
-
- typedef _BSD_TIME_T_ ansi_tt;
-
- typedef struct apple_tm {
- int tm_sec; /* seconds after the minute [0-60] */
- int tm_min; /* minutes after the hour [0-59] */
- int tm_hour; /* hours since midnight [0-23] */
- int tm_mday; /* day of the month [1-31] */
- int tm_mon; /* months since January [0-11] */
- int tm_year; /* years since 1900 */
- int tm_wday; /* days since Sunday [0-6] */
- int tm_yday; /* days since January 1 [0-365] */
- int tm_isdst; /* Daylight Savings Time flag */
- long tm_gmtoff; /* offset from CUT in seconds */
- char *tm_zone; /* timezone abbreviation */
- } ansi_tm;
-
-
- typedef ansi_tt (* GetTimeProc) ( ansi_tt * ttTime );
- typedef ansi_tt (* MakeTimeProc) ( ansi_tm * tmTime );
- typedef double (* DiffTimeProc) ( ansi_tt t1, ansi_tt t0 );
-
- typedef void (* ConvertTimeProc) ( const ansi_tt * ttTime, ansi_tm * tmTime );
+#endif
- static GetTimeProc ansi_time = 0;
- static MakeTimeProc ansi_mktime = 0;
- static DiffTimeProc ansi_difftime = 0;
+// -------------------------------------------------------------------------------------------------
+// VerifyDateTimeFlags
+// -------------------
- static ConvertTimeProc ansi_gmtime = 0;
- static ConvertTimeProc ansi_localtime = 0;
-
- static void LookupTimeProcs()
- {
- _dyld_lookup_and_bind_with_hint ( "_time", "libSystem", (XMP_Uns32*)&ansi_time, 0 );
- _dyld_lookup_and_bind_with_hint ( "_mktime", "libSystem", (XMP_Uns32*)&ansi_mktime, 0 );
- _dyld_lookup_and_bind_with_hint ( "_difftime", "libSystem", (XMP_Uns32*)&ansi_difftime, 0 );
- _dyld_lookup_and_bind_with_hint ( "_gmtime_r", "libSystem", (XMP_Uns32*)&ansi_gmtime, 0 );
- _dyld_lookup_and_bind_with_hint ( "_localtime_r", "libSystem", (XMP_Uns32*)&ansi_localtime, 0 );
- }
-
- #endif
+static void
+VerifyDateTimeFlags ( XMP_DateTime * dt )
+{
-#endif
+ if ( (dt->year != 0) || (dt->month != 0) || (dt->day != 0) ) dt->hasDate = true;
+ if ( (dt->hour != 0) || (dt->minute != 0) || (dt->second != 0) || (dt->nanoSecond != 0) ) dt->hasTime = true;
+ if ( (dt->tzSign != 0) || (dt->tzHour != 0) || (dt->tzMinute != 0) ) dt->hasTimeZone = true;
+ if ( dt->hasTimeZone ) dt->hasTime = true; // ! Don't combine with above line, UTC has zero values.
+} // VerifyDateTimeFlags
// -------------------------------------------------------------------------------------------------
// IsLeapYear
@@ -183,7 +122,6 @@ IsLeapYear ( long year )
} // IsLeapYear
-
// -------------------------------------------------------------------------------------------------
// DaysInMonth
// -----------
@@ -202,7 +140,6 @@ DaysInMonth ( XMP_Int32 year, XMP_Int32 month )
} // DaysInMonth
-
// -------------------------------------------------------------------------------------------------
// AdjustTimeOverflow
// ------------------
@@ -356,7 +293,6 @@ AdjustTimeOverflow ( XMP_DateTime * time )
} // AdjustTimeOverflow
-
// -------------------------------------------------------------------------------------------------
// GatherInt
// ---------
@@ -369,6 +305,7 @@ GatherInt ( XMP_StringPtr strValue, size_t * _pos, const char * errMsg )
for ( char ch = strValue[pos]; ('0' <= ch) && (ch <= '9'); ++pos, ch = strValue[pos] ) {
value = (value * 10) + (ch - '0');
+ if ( value < 0 ) XMP_Throw ( errMsg, kXMPErr_BadValue );
}
if ( pos == *_pos ) XMP_Throw ( errMsg, kXMPErr_BadParam );
@@ -377,7 +314,6 @@ GatherInt ( XMP_StringPtr strValue, size_t * _pos, const char * errMsg )
} // GatherInt
-
// -------------------------------------------------------------------------------------------------
static void FormatFullDateTime ( XMP_DateTime & tempDate, char * buffer, size_t bufferLen )
@@ -410,7 +346,6 @@ static void FormatFullDateTime ( XMP_DateTime & tempDate, char * buffer, size_t
} // FormatFullDateTime
-
// -------------------------------------------------------------------------------------------------
// DecodeBase64Char
// ----------------
@@ -450,7 +385,6 @@ DecodeBase64Char ( XMP_Uns8 ch )
} // DecodeBase64Char ();
-
// -------------------------------------------------------------------------------------------------
// EstimateSizeForJPEG
// -------------------
@@ -497,7 +431,6 @@ EstimateSizeForJPEG ( const XMP_Node * xmpNode )
} // EstimateSizeForJPEG
-
// -------------------------------------------------------------------------------------------------
// MoveOneProperty
// ---------------
@@ -529,7 +462,6 @@ static bool MoveOneProperty ( XMPMeta & stdXMP, XMPMeta * extXMP,
} // MoveOneProperty
-
// -------------------------------------------------------------------------------------------------
// CreateEstimatedSizeMap
// ----------------------
@@ -572,7 +504,6 @@ static void CreateEstimatedSizeMap ( XMPMeta & stdXMP, PropSizeMap * propSizes )
} // CreateEstimatedSizeMap
-
// -------------------------------------------------------------------------------------------------
// MoveLargestProperty
// -------------------
@@ -608,12 +539,10 @@ static size_t MoveLargestProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, PropSize
} // MoveLargestProperty
-
// =================================================================================================
// Class Static Functions
// ======================
-
// -------------------------------------------------------------------------------------------------
// Initialize
// ----------
@@ -621,58 +550,25 @@ static size_t MoveLargestProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, PropSize
/* class static */ bool
XMPUtils::Initialize()
{
- sComposedPath = new XMP_VarString();
- sConvertedValue = new XMP_VarString();
- sBase64Str = new XMP_VarString();
- sCatenatedItems = new XMP_VarString();
- sStandardXMP = new XMP_VarString();
- sExtendedXMP = new XMP_VarString();
- sExtendedDigest = new XMP_VarString();
-
- #if XMP_MacBuild && __MWERKS__
- LookupTimeProcs();
- #endif
+ // Nothing at present.
return true;
} // Initialize
-
// -------------------------------------------------------------------------------------------------
// Terminate
// ---------
-#define EliminateGlobal(g) delete ( g ); g = 0
-
/* class static */ void
XMPUtils::Terminate() RELEASE_NO_THROW
{
- EliminateGlobal ( sComposedPath );
- EliminateGlobal ( sConvertedValue );
- EliminateGlobal ( sBase64Str );
- EliminateGlobal ( sCatenatedItems );
- EliminateGlobal ( sStandardXMP );
- EliminateGlobal ( sExtendedXMP );
- EliminateGlobal ( sExtendedDigest );
+ // Nothing at present.
return;
} // Terminate
-
-// -------------------------------------------------------------------------------------------------
-// Unlock
-// ------
-
-/* class static */ void
-XMPUtils::Unlock ( XMP_OptionBits options )
-{
- options = options; // Avoid unused parameter warning.
-
- XMPMeta::Unlock ( 0 );
-
-} // Unlock
-
// -------------------------------------------------------------------------------------------------
// ComposeArrayItemPath
// --------------------
@@ -683,12 +579,11 @@ XMPUtils::Unlock ( XMP_OptionBits options )
XMPUtils::ComposeArrayItemPath ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize )
+ XMP_VarString * _fullPath )
{
XMP_Assert ( schemaNS != 0 ); // Enforced by wrapper.
- XMP_Assert ( *arrayName != 0 ); // Enforced by wrapper.
- XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (arrayName != 0) && (*arrayName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( _fullPath != 0 ); // Enforced by wrapper.
XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path.
ExpandXPath ( schemaNS, arrayName, &expPath );
@@ -697,27 +592,23 @@ XMPUtils::ComposeArrayItemPath ( XMP_StringPtr schemaNS,
XMP_StringLen reserveLen = strlen(arrayName) + 2 + 32; // Room plus padding.
- sComposedPath->erase();
- sComposedPath->reserve ( reserveLen );
- sComposedPath->append ( reserveLen, ' ' );
+ XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str().
+ fullPath.reserve ( reserveLen );
+ fullPath = arrayName;
- if ( itemIndex != kXMP_ArrayLastItem ) {
- // AUDIT: Using string->size() for the snprintf length is safe.
- snprintf ( const_cast<char*>(sComposedPath->c_str()), sComposedPath->size(), "%s[%d]", arrayName, itemIndex );
+ if ( itemIndex == kXMP_ArrayLastItem ) {
+ fullPath += "[last()]";
} else {
- *sComposedPath = arrayName;
- *sComposedPath += "[last()] ";
- (*sComposedPath)[sComposedPath->size()-1] = 0; // ! Final null is for the strlen at exit.
+ // AUDIT: Using sizeof(buffer) for the snprintf length is safe.
+ char buffer [32]; // A 32 byte buffer is plenty, even for a 64-bit integer.
+ snprintf ( buffer, sizeof(buffer), "[%d]", itemIndex );
+ fullPath += buffer;
}
- *fullPath = sComposedPath->c_str();
- *pathSize = strlen ( *fullPath ); // ! Don't use sComposedPath->size()!
-
- XMP_Enforce ( *pathSize < sComposedPath->size() ); // Rather late, but complain about buffer overflow.
+ *_fullPath = fullPath;
} // ComposeArrayItemPath
-
// -------------------------------------------------------------------------------------------------
// ComposeStructFieldPath
// ----------------------
@@ -729,12 +620,12 @@ XMPUtils::ComposeStructFieldPath ( XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize )
+ XMP_VarString * _fullPath )
{
XMP_Assert ( (schemaNS != 0) && (fieldNS != 0) ); // Enforced by wrapper.
- XMP_Assert ( (*structName != 0) && (*fieldName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (structName != 0) && (*structName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (fieldName != 0) && (*fieldName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( _fullPath != 0 ); // Enforced by wrapper.
XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path.
ExpandXPath ( schemaNS, structName, &expPath );
@@ -745,18 +636,16 @@ XMPUtils::ComposeStructFieldPath ( XMP_StringPtr schemaNS,
XMP_StringLen reserveLen = strlen(structName) + fieldPath[kRootPropStep].step.size() + 1;
- sComposedPath->erase();
- sComposedPath->reserve ( reserveLen );
- *sComposedPath = structName;
- *sComposedPath += '/';
- *sComposedPath += fieldPath[kRootPropStep].step;
+ XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str().
+ fullPath.reserve ( reserveLen );
+ fullPath = structName;
+ fullPath += '/';
+ fullPath += fieldPath[kRootPropStep].step;
- *fullPath = sComposedPath->c_str();
- *pathSize = sComposedPath->size();
+ *_fullPath = fullPath;
} // ComposeStructFieldPath
-
// -------------------------------------------------------------------------------------------------
// ComposeQualifierPath
// --------------------
@@ -768,12 +657,12 @@ XMPUtils::ComposeQualifierPath ( XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize )
+ XMP_VarString * _fullPath )
{
- XMP_Assert ( (schemaNS != 0) && (qualNS != 0) ); // Enforced by wrapper.
- XMP_Assert ( (*propName != 0) && (*qualName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (schemaNS != 0) && (qualNS != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (propName != 0) && (*propName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (qualName != 0) && (*qualName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( _fullPath != 0 ); // Enforced by wrapper.
XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path.
ExpandXPath ( schemaNS, propName, &expPath );
@@ -784,18 +673,16 @@ XMPUtils::ComposeQualifierPath ( XMP_StringPtr schemaNS,
XMP_StringLen reserveLen = strlen(propName) + qualPath[kRootPropStep].step.size() + 2;
- sComposedPath->erase();
- sComposedPath->reserve ( reserveLen );
- *sComposedPath = propName;
- *sComposedPath += "/?";
- *sComposedPath += qualPath[kRootPropStep].step;
+ XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str().
+ fullPath.reserve ( reserveLen );
+ fullPath = propName;
+ fullPath += "/?";
+ fullPath += qualPath[kRootPropStep].step;
- *fullPath = sComposedPath->c_str();
- *pathSize = sComposedPath->size();
+ *_fullPath = fullPath;
} // ComposeQualifierPath
-
// -------------------------------------------------------------------------------------------------
// ComposeLangSelector
// -------------------
@@ -808,12 +695,12 @@ XMPUtils::ComposeQualifierPath ( XMP_StringPtr schemaNS,
XMPUtils::ComposeLangSelector ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_StringPtr _langName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize )
+ XMP_VarString * _fullPath )
{
XMP_Assert ( schemaNS != 0 ); // Enforced by wrapper.
- XMP_Assert ( (*arrayName != 0) && (*_langName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (arrayName != 0) && (*arrayName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (_langName != 0) && (*_langName != 0) ); // Enforced by wrapper.
+ XMP_Assert ( _fullPath != 0 ); // Enforced by wrapper.
XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path.
ExpandXPath ( schemaNS, arrayName, &expPath );
@@ -823,19 +710,17 @@ XMPUtils::ComposeLangSelector ( XMP_StringPtr schemaNS,
XMP_StringLen reserveLen = strlen(arrayName) + langName.size() + 14;
- sComposedPath->erase();
- sComposedPath->reserve ( reserveLen );
- *sComposedPath = arrayName;
- *sComposedPath += "[?xml:lang=\"";
- *sComposedPath += langName;
- *sComposedPath += "\"]";
+ XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str().
+ fullPath.reserve ( reserveLen );
+ fullPath = arrayName;
+ fullPath += "[?xml:lang=\"";
+ fullPath += langName;
+ fullPath += "\"]";
- *fullPath = sComposedPath->c_str();
- *pathSize = sComposedPath->size();
+ *_fullPath = fullPath;
} // ComposeLangSelector
-
// -------------------------------------------------------------------------------------------------
// ComposeFieldSelector
// --------------------
@@ -850,12 +735,11 @@ XMPUtils::ComposeFieldSelector ( XMP_StringPtr schemaNS,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
XMP_StringPtr fieldValue,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize )
+ XMP_VarString * _fullPath )
{
XMP_Assert ( (schemaNS != 0) && (fieldNS != 0) && (fieldValue != 0) ); // Enforced by wrapper.
XMP_Assert ( (*arrayName != 0) && (*fieldName != 0) ); // Enforced by wrapper.
- XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( _fullPath != 0 ); // Enforced by wrapper.
XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path.
ExpandXPath ( schemaNS, arrayName, &expPath );
@@ -866,43 +750,37 @@ XMPUtils::ComposeFieldSelector ( XMP_StringPtr schemaNS,
XMP_StringLen reserveLen = strlen(arrayName) + fieldPath[kRootPropStep].step.size() + strlen(fieldValue) + 5;
- sComposedPath->erase();
- sComposedPath->reserve ( reserveLen );
- *sComposedPath = arrayName;
- *sComposedPath += '[';
- *sComposedPath += fieldPath[kRootPropStep].step;
- *sComposedPath += "=\"";
- *sComposedPath += fieldValue;
- *sComposedPath += "\"]";
+ XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str().
+ fullPath.reserve ( reserveLen );
+ fullPath = arrayName;
+ fullPath += '[';
+ fullPath += fieldPath[kRootPropStep].step;
+ fullPath += "=\"";
+ fullPath += fieldValue;
+ fullPath += "\"]";
- *fullPath = sComposedPath->c_str();
- *pathSize = sComposedPath->size();
+ *_fullPath = fullPath;
} // ComposeFieldSelector
-
// -------------------------------------------------------------------------------------------------
// ConvertFromBool
// ---------------
/* class static */ void
XMPUtils::ConvertFromBool ( bool binValue,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize )
+ XMP_VarString * strValue )
{
- XMP_Assert ( (strValue != 0) && (strSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( strValue != 0 ); // Enforced by wrapper.
if ( binValue ) {
*strValue = kXMP_TrueStr;
- *strSize = strlen ( kXMP_TrueStr );
} else {
*strValue = kXMP_FalseStr;
- *strSize = strlen ( kXMP_FalseStr );
}
} // ConvertFromBool
-
// -------------------------------------------------------------------------------------------------
// ConvertFromInt
// --------------
@@ -910,28 +788,21 @@ XMPUtils::ConvertFromBool ( bool binValue,
/* class static */ void
XMPUtils::ConvertFromInt ( XMP_Int32 binValue,
XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize )
+ XMP_VarString * strValue )
{
- XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (format != 0) && (strValue != 0) ); // Enforced by wrapper.
+ strValue->erase();
if ( *format == 0 ) format = "%d";
- sConvertedValue->erase();
- sConvertedValue->reserve ( 100 ); // More than enough for any reasonable format and value.
- sConvertedValue->append ( 100, ' ' );
+ // AUDIT: Using sizeof(buffer) for the snprintf length is safe.
+ char buffer [32]; // Big enough for a 64-bit integer;
+ snprintf ( buffer, sizeof(buffer), format, binValue );
- // AUDIT: Using string->size() for the snprintf length is safe.
- snprintf ( const_cast<char*>(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue );
-
- *strValue = sConvertedValue->c_str();
- *strSize = strlen ( *strValue ); // ! Don't use sConvertedValue->size()!
-
- XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow.
+ *strValue = buffer;
} // ConvertFromInt
-
// -------------------------------------------------------------------------------------------------
// ConvertFromInt64
// ----------------
@@ -939,28 +810,21 @@ XMPUtils::ConvertFromInt ( XMP_Int32 binValue,
/* class static */ void
XMPUtils::ConvertFromInt64 ( XMP_Int64 binValue,
XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize )
+ XMP_VarString * strValue )
{
- XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (format != 0) && (strValue != 0) ); // Enforced by wrapper.
+ strValue->erase();
if ( *format == 0 ) format = "%lld";
- sConvertedValue->erase();
- sConvertedValue->reserve ( 100 ); // More than enough for any reasonable format and value.
- sConvertedValue->append ( 100, ' ' );
-
- // AUDIT: Using string->size() for the snprintf length is safe.
- snprintf ( const_cast<char*>(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue );
+ // AUDIT: Using sizeof(buffer) for the snprintf length is safe.
+ char buffer [32]; // Big enough for a 64-bit integer;
+ snprintf ( buffer, sizeof(buffer), format, binValue );
- *strValue = sConvertedValue->c_str();
- *strSize = strlen ( *strValue ); // ! Don't use sConvertedValue->size()!
-
- XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow.
+ *strValue = buffer;
} // ConvertFromInt64
-
// -------------------------------------------------------------------------------------------------
// ConvertFromFloat
// ----------------
@@ -968,33 +832,26 @@ XMPUtils::ConvertFromInt64 ( XMP_Int64 binValue,
/* class static */ void
XMPUtils::ConvertFromFloat ( double binValue,
XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize )
+ XMP_VarString * strValue )
{
- XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( (format != 0) && (strValue != 0) ); // Enforced by wrapper.
+ strValue->erase();
if ( *format == 0 ) format = "%f";
- sConvertedValue->erase();
- sConvertedValue->reserve ( 1000 ); // More than enough for any reasonable format and value.
- sConvertedValue->append ( 1000, ' ' );
+ // AUDIT: Using sizeof(buffer) for the snprintf length is safe.
+ char buffer [64]; // Ought to be plenty big enough.
+ snprintf ( buffer, sizeof(buffer), format, binValue );
- // AUDIT: Using string->size() for the snprintf length is safe.
- snprintf ( const_cast<char*>(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue );
-
- *strValue = sConvertedValue->c_str();
- *strSize = strlen ( *strValue ); // ! Don't use sConvertedValue->size()!
-
- XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow.
+ *strValue = buffer;
} // ConvertFromFloat
-
// -------------------------------------------------------------------------------------------------
// ConvertFromDate
// ---------------
//
-// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime:
+// Format a date-time string according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime:
// YYYY
// YYYY-MM
// YYYY-MM-DD
@@ -1012,18 +869,16 @@ XMPUtils::ConvertFromFloat ( double binValue,
// TZD = time zone designator (Z or +hh:mm or -hh:mm)
//
// Note that ISO 8601 does not seem to allow years less than 1000 or greater than 9999. We allow
-// any year, even negative ones. The year is formatted as "%.4d".
-
-// *** Need to check backward compatibility for partial forms!
+// any year, even negative ones. The year is formatted as "%.4d". The TZD is also optional in XMP,
+// even though required in the W3C profile. Finally, Photoshop 8 (CS) sometimes created time-only
+// values so we tolerate that.
/* class static */ void
-XMPUtils::ConvertFromDate ( const XMP_DateTime & binValue,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize )
+XMPUtils::ConvertFromDate ( const XMP_DateTime & _inValue,
+ XMP_VarString * strValue )
{
- XMP_Assert ( (strValue != 0) && (strSize != 0) ); // Enforced by wrapper.
+ XMP_Assert ( strValue != 0 ); // Enforced by wrapper.
- bool addTimeZone = false;
char buffer [100]; // Plenty long enough.
// Pick the format, use snprintf to format into a local buffer, assign to static output string.
@@ -1031,101 +886,82 @@ XMPUtils::ConvertFromDate ( const XMP_DateTime & binValue,
// ! Photoshop 8 creates "time only" values with zeros for year, month, and day.
- XMP_DateTime tempDate = binValue;
+ XMP_DateTime binValue = _inValue;
+ VerifyDateTimeFlags ( &binValue );
// Temporary fix for bug 1269463, silently fix out of range month or day.
- bool haveDay = (tempDate.day != 0);
- bool haveTime = ( (tempDate.hour != 0) || (tempDate.minute != 0) ||
- (tempDate.second != 0) || (tempDate.nanoSecond != 0) ||
- (tempDate.tzSign != 0) || (tempDate.tzHour != 0) || (tempDate.tzMinute != 0) );
-
- if ( tempDate.month == 0 ) {
- if ( haveDay || haveTime ) tempDate.month = 1;
+ if ( binValue.month == 0 ) {
+ if ( (binValue.day != 0) || binValue.hasTime ) binValue.month = 1;
} else {
- if ( tempDate.month < 1 ) tempDate.month = 1;
- if ( tempDate.month > 12 ) tempDate.month = 12;
+ if ( binValue.month < 1 ) binValue.month = 1;
+ if ( binValue.month > 12 ) binValue.month = 12;
}
- if ( tempDate.day == 0 ) {
- if ( haveTime ) tempDate.day = 1;
+ if ( binValue.day == 0 ) {
+ if ( binValue.hasTime ) binValue.day = 1;
} else {
- if ( tempDate.day < 1 ) tempDate.day = 1;
- if ( tempDate.day > 31 ) tempDate.day = 31;
+ if ( binValue.day < 1 ) binValue.day = 1;
+ if ( binValue.day > 31 ) binValue.day = 31;
}
// Now carry on with the original logic.
- if ( tempDate.month == 0 ) {
+ if ( binValue.month == 0 ) {
// Output YYYY if all else is zero, otherwise output a full string for the quasi-bogus
// "time only" values from Photoshop CS.
- if ( (tempDate.day == 0) && (tempDate.hour == 0) && (tempDate.minute == 0) &&
- (tempDate.second == 0) && (tempDate.nanoSecond == 0) &&
- (tempDate.tzSign == 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0) ) {
- snprintf ( buffer, sizeof(buffer), "%.4d", tempDate.year ); // AUDIT: Using sizeof for snprintf length is safe.
- } else if ( (tempDate.year == 0) && (tempDate.day == 0) ) {
- FormatFullDateTime ( tempDate, buffer, sizeof(buffer) );
- addTimeZone = true;
+ if ( (binValue.day == 0) && (! binValue.hasTime) ) {
+ snprintf ( buffer, sizeof(buffer), "%.4d", binValue.year ); // AUDIT: Using sizeof for snprintf length is safe.
+ } else if ( (binValue.year == 0) && (binValue.day == 0) ) {
+ FormatFullDateTime ( binValue, buffer, sizeof(buffer) );
} else {
XMP_Throw ( "Invalid partial date", kXMPErr_BadParam);
}
- } else if ( tempDate.day == 0 ) {
+ } else if ( binValue.day == 0 ) {
// Output YYYY-MM.
- if ( (tempDate.month < 1) || (tempDate.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam);
- if ( (tempDate.hour != 0) || (tempDate.minute != 0) ||
- (tempDate.second != 0) || (tempDate.nanoSecond != 0) ||
- (tempDate.tzSign != 0) || (tempDate.tzHour != 0) || (tempDate.tzMinute != 0) ) {
- XMP_Throw ( "Invalid partial date, non-zeros after zero month and day", kXMPErr_BadParam);
- }
- snprintf ( buffer, sizeof(buffer), "%.4d-%02d", tempDate.year, tempDate.month ); // AUDIT: Using sizeof for snprintf length is safe.
+ if ( (binValue.month < 1) || (binValue.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam);
+ if ( binValue.hasTime ) XMP_Throw ( "Invalid partial date, non-zeros after zero month and day", kXMPErr_BadParam);
+ snprintf ( buffer, sizeof(buffer), "%.4d-%02d", binValue.year, binValue.month ); // AUDIT: Using sizeof for snprintf length is safe.
- } else if ( (tempDate.hour == 0) && (tempDate.minute == 0) &&
- (tempDate.second == 0) && (tempDate.nanoSecond == 0) &&
- (tempDate.tzSign == 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0) ) {
+ } else if ( ! binValue.hasTime ) {
// Output YYYY-MM-DD.
- if ( (tempDate.month < 1) || (tempDate.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam);
- if ( (tempDate.day < 1) || (tempDate.day > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam);
- snprintf ( buffer, sizeof(buffer), "%.4d-%02d-%02d", tempDate.year, tempDate.month, tempDate.day ); // AUDIT: Using sizeof for snprintf length is safe.
+ if ( (binValue.month < 1) || (binValue.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam);
+ if ( (binValue.day < 1) || (binValue.day > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam);
+ snprintf ( buffer, sizeof(buffer), "%.4d-%02d-%02d", binValue.year, binValue.month, binValue.day ); // AUDIT: Using sizeof for snprintf length is safe.
} else {
- FormatFullDateTime ( tempDate, buffer, sizeof(buffer) );
- addTimeZone = true;
+ FormatFullDateTime ( binValue, buffer, sizeof(buffer) );
}
- sConvertedValue->assign ( buffer );
+ strValue->assign ( buffer );
- if ( addTimeZone ) {
+ if ( binValue.hasTimeZone ) {
- if ( (tempDate.tzHour < 0) || (tempDate.tzHour > 23) ||
- (tempDate.tzMinute < 0 ) || (tempDate.tzMinute > 59) ||
- (tempDate.tzSign < -1) || (tempDate.tzSign > +1) ||
- ((tempDate.tzSign != 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0)) ||
- ((tempDate.tzSign == 0) && ((tempDate.tzHour != 0) || (tempDate.tzMinute != 0))) ) {
+ if ( (binValue.tzHour < 0) || (binValue.tzHour > 23) ||
+ (binValue.tzMinute < 0 ) || (binValue.tzMinute > 59) ||
+ (binValue.tzSign < -1) || (binValue.tzSign > +1) ||
+ ((binValue.tzSign == 0) && ((binValue.tzHour != 0) || (binValue.tzMinute != 0))) ) {
XMP_Throw ( "Invalid time zone values", kXMPErr_BadParam );
}
- if ( tempDate.tzSign == 0 ) {
- *sConvertedValue += 'Z';
+ if ( binValue.tzSign == 0 ) {
+ *strValue += 'Z';
} else {
- snprintf ( buffer, sizeof(buffer), "+%02d:%02d", tempDate.tzHour, tempDate.tzMinute ); // AUDIT: Using sizeof for snprintf length is safe.
- if ( tempDate.tzSign < 0 ) buffer[0] = '-';
- *sConvertedValue += buffer;
+ snprintf ( buffer, sizeof(buffer), "+%02d:%02d", binValue.tzHour, binValue.tzMinute ); // AUDIT: Using sizeof for snprintf length is safe.
+ if ( binValue.tzSign < 0 ) buffer[0] = '-';
+ *strValue += buffer;
}
}
- *strValue = sConvertedValue->c_str();
- *strSize = sConvertedValue->size();
-
} // ConvertFromDate
-
// -------------------------------------------------------------------------------------------------
// ConvertToBool
// -------------
@@ -1157,7 +993,6 @@ XMPUtils::ConvertToBool ( XMP_StringPtr strValue )
} // ConvertToBool
-
// -------------------------------------------------------------------------------------------------
// ConvertToInt
// ------------
@@ -1183,7 +1018,6 @@ XMPUtils::ConvertToInt ( XMP_StringPtr strValue )
} // ConvertToInt
-
// -------------------------------------------------------------------------------------------------
// ConvertToInt64
// --------------
@@ -1209,7 +1043,6 @@ XMPUtils::ConvertToInt64 ( XMP_StringPtr strValue )
} // ConvertToInt64
-
// -------------------------------------------------------------------------------------------------
// ConvertToFloat
// --------------
@@ -1237,12 +1070,11 @@ XMPUtils::ConvertToFloat ( XMP_StringPtr strValue )
} // ConvertToFloat
-
// -------------------------------------------------------------------------------------------------
// ConvertToDate
// -------------
//
-// Parse a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime:
+// Parse a date-time string according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime:
// YYYY
// YYYY-MM
// YYYY-MM-DD
@@ -1260,10 +1092,9 @@ XMPUtils::ConvertToFloat ( XMP_StringPtr strValue )
// TZD = time zone designator (Z or +hh:mm or -hh:mm)
//
// Note that ISO 8601 does not seem to allow years less than 1000 or greater than 9999. We allow
-// any year, even negative ones. The year is formatted as "%.4d".
-
-// ! Tolerate missing TZD, assume is UTC. Photoshop 8 writes dates like this for exif:GPSTimeStamp.
-// ! Tolerate missing date portion, in case someone foolishly writes a time-only value that way.
+// any year, even negative ones. The year is formatted as "%.4d". The TZD is also optional in XMP,
+// even though required in the W3C profile. Finally, Photoshop 8 (CS) sometimes created time-only
+// values so we tolerate that.
// *** Put the ISO format comments in the header documentation.
@@ -1273,18 +1104,21 @@ XMPUtils::ConvertToDate ( XMP_StringPtr strValue,
{
if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue);
- size_t pos = 0;
+ size_t pos = 0;
XMP_Int32 temp;
XMP_Assert ( sizeof(*binValue) == sizeof(XMP_DateTime) );
(void) memset ( binValue, 0, sizeof(*binValue) ); // AUDIT: Safe, using sizeof destination.
+ size_t strSize = strlen ( strValue );
bool timeOnly = ( (strValue[0] == 'T') ||
- ((strlen(strValue) >= 2) && (strValue[1] == ':')) ||
- ((strlen(strValue) >= 3) && (strValue[2] == ':')) );
+ ((strSize >= 2) && (strValue[1] == ':')) ||
+ ((strSize >= 3) && (strValue[2] == ':')) );
if ( ! timeOnly ) {
-
+
+ binValue->hasDate = true;
+
if ( strValue[0] == '-' ) pos = 1;
temp = GatherInt ( strValue, &pos, "Invalid year in date string" ); // Extract the year.
@@ -1318,12 +1152,16 @@ XMPUtils::ConvertToDate ( XMP_StringPtr strValue,
}
+ // If we get here there is more of the string, otherwise we would have returned above.
+
if ( strValue[pos] == 'T' ) {
++pos;
} else if ( ! timeOnly ) {
XMP_Throw ( "Invalid date string, missing 'T' after date", kXMPErr_BadParam );
}
+ binValue->hasTime = true;
+
temp = GatherInt ( strValue, &pos, "Invalid hour in date string" ); // Extract the hour.
if ( strValue[pos] != ':' ) XMP_Throw ( "Invalid date string, after hour", kXMPErr_BadParam );
if ( temp > 23 ) temp = 23; // *** 1269463: XMP_Throw ( "Hour is out of range", kXMPErr_BadParam );
@@ -1372,11 +1210,15 @@ XMPUtils::ConvertToDate ( XMP_StringPtr strValue,
}
+ if ( strValue[pos] == 0 ) return;
+
+ binValue->hasTimeZone = true;
+
if ( strValue[pos] == 'Z' ) {
++pos;
- } else if ( strValue[pos] != 0 ) {
+ } else {
if ( strValue[pos] == '+' ) {
binValue->tzSign = kXMP_TimeEastOfUTC;
@@ -1403,7 +1245,6 @@ XMPUtils::ConvertToDate ( XMP_StringPtr strValue,
} // ConvertToDate
-
// -------------------------------------------------------------------------------------------------
// EncodeToBase64
// --------------
@@ -1415,15 +1256,13 @@ XMPUtils::ConvertToDate ( XMP_StringPtr strValue,
/* class static */ void
XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr,
XMP_StringLen rawLen,
- XMP_StringPtr * encodedStr,
- XMP_StringLen * encodedLen )
+ XMP_VarString * encodedStr )
{
if ( (rawStr == 0) && (rawLen != 0) ) XMP_Throw ( "Null raw data buffer", kXMPErr_BadParam );
- if ( rawLen == 0 ) {
- *encodedStr = 0;
- *encodedLen = 0;
- return;
- }
+ XMP_Assert ( encodedStr != 0 ); // Enforced by wrapper.
+
+ encodedStr->erase();
+ if ( rawLen == 0 ) return;
char encChunk[4];
@@ -1433,8 +1272,7 @@ XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr,
const size_t outputSize = (rawLen / 3) * 4; // Approximate, might be small.
- sBase64Str->erase();
- sBase64Str->reserve ( outputSize );
+ encodedStr->reserve ( outputSize );
// ----------------------------------------------------------------------------------------
// Each 6 bits of input produces 8 bits of output, so 3 input bytes become 4 output bytes.
@@ -1455,10 +1293,10 @@ XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr,
encChunk[3] = sBase64Chars [ merge & 0x3F ];
if ( out >= 76 ) {
- sBase64Str->append ( 1, kLF );
+ encodedStr->append ( 1, kLF );
out = 0;
}
- sBase64Str->append ( encChunk, 4 );
+ encodedStr->append ( encChunk, 4 );
}
@@ -1481,8 +1319,8 @@ XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr,
encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ];
encChunk[2] = encChunk[3] = '=';
- if ( out >= 76 ) sBase64Str->append ( 1, kLF );
- sBase64Str->append ( encChunk, 4 );
+ if ( out >= 76 ) encodedStr->append ( 1, kLF );
+ encodedStr->append ( encChunk, 4 );
break;
case 2: // Two input bytes remain.
@@ -1496,21 +1334,14 @@ XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr,
encChunk[2] = sBase64Chars [ (merge >> 6) & 0x3F ];
encChunk[3] = '=';
- if ( out >= 76 ) sBase64Str->append ( 1, kLF );
- sBase64Str->append ( encChunk, 4 );
+ if ( out >= 76 ) encodedStr->append ( 1, kLF );
+ encodedStr->append ( encChunk, 4 );
break;
}
-
- // -------------------------
- // Assign the output values.
-
- *encodedStr = sBase64Str->c_str();
- *encodedLen = sBase64Str->size();
} // EncodeToBase64
-
// -------------------------------------------------------------------------------------------------
// DecodeFromBase64
// ----------------
@@ -1523,23 +1354,20 @@ XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr,
/* class static */ void
XMPUtils::DecodeFromBase64 ( XMP_StringPtr encodedStr,
XMP_StringLen encodedLen,
- XMP_StringPtr * rawStr,
- XMP_StringLen * rawLen )
+ XMP_VarString * rawStr )
{
if ( (encodedStr == 0) && (encodedLen != 0) ) XMP_Throw ( "Null encoded data buffer", kXMPErr_BadParam );
- if ( encodedLen == 0 ) {
- *rawStr = 0;
- *rawLen = 0;
- return;
- }
+ XMP_Assert ( rawStr != 0 ); // Enforced by wrapper.
+
+ rawStr->erase();
+ if ( encodedLen == 0 ) return;
unsigned char ch, rawChunk[3];
unsigned long inStr, inChunk, inLimit, merge, padding;
XMP_StringLen outputSize = (encodedLen / 4) * 3; // Only a close approximation.
- sBase64Str->erase();
- sBase64Str->reserve ( outputSize );
+ rawStr->reserve ( outputSize );
// ----------------------------------------------------------------------------------------
@@ -1589,7 +1417,7 @@ XMPUtils::DecodeFromBase64 ( XMP_StringPtr encodedStr,
rawChunk[1] = (unsigned char) ((merge >> 8) & 0xFF);
rawChunk[2] = (unsigned char) (merge & 0xFF);
- sBase64Str->append ( (char*)rawChunk, 3 );
+ rawStr->append ( (char*)rawChunk, 3 );
}
@@ -1611,69 +1439,58 @@ XMPUtils::DecodeFromBase64 ( XMP_StringPtr encodedStr,
if ( padding == 2 ) {
rawChunk[0] = (unsigned char) (merge >> 4);
- sBase64Str->append ( (char*)rawChunk, 1 );
+ rawStr->append ( (char*)rawChunk, 1 );
} else if ( padding == 1 ) {
rawChunk[0] = (unsigned char) (merge >> 10);
rawChunk[1] = (unsigned char) ((merge >> 2) & 0xFF);
- sBase64Str->append ( (char*)rawChunk, 2 );
+ rawStr->append ( (char*)rawChunk, 2 );
} else {
rawChunk[0] = (unsigned char) (merge >> 16);
rawChunk[1] = (unsigned char) ((merge >> 8) & 0xFF);
rawChunk[2] = (unsigned char) (merge & 0xFF);
- sBase64Str->append ( (char*)rawChunk, 3 );
+ rawStr->append ( (char*)rawChunk, 3 );
}
-
- // -------------------------
- // Assign the output values.
-
- *rawStr = sBase64Str->c_str();
- *rawLen = sBase64Str->size();
} // DecodeFromBase64
-
// -------------------------------------------------------------------------------------------------
// PackageForJPEG
// --------------
/* class static */ void
XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
- XMP_StringPtr * stdStr,
- XMP_StringLen * stdLen,
- XMP_StringPtr * extStr,
- XMP_StringLen * extLen,
- XMP_StringPtr * digestStr,
- XMP_StringLen * digestLen )
+ XMP_VarString * stdStr,
+ XMP_VarString * extStr,
+ XMP_VarString * digestStr )
{
+ XMP_Assert ( (stdStr != 0) && (extStr != 0) && (digestStr != 0) ); // ! Enforced by wrapper.
+
enum { kStdXMPLimit = 65000 };
static const char * kPacketTrailer = "<?xpacket end=\"w\"?>";
static size_t kTrailerLen = strlen ( kPacketTrailer );
- XMP_StringPtr tempStr;
- XMP_StringLen tempLen;
-
+ XMP_VarString tempStr;
XMPMeta stdXMP, extXMP;
-
- sStandardXMP->clear(); // Clear the static strings that get returned to the client.
- sExtendedXMP->clear();
- sExtendedDigest->clear();
-
XMP_OptionBits keepItSmall = kXMP_UseCompactFormat | kXMP_OmitAllFormatting;
+ stdStr->erase();
+ extStr->erase();
+ digestStr->erase();
+
// Try to serialize everything. Note that we're making internal calls to SerializeToBuffer, so
// we'll be getting back the pointer and length for its internal string.
- origXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
+ origXMP.SerializeToBuffer ( &tempStr, keepItSmall, 1, "", "", 0 );
#if Trace_PackageForJPEG
- printf ( "\nXMPUtils::PackageForJPEG - Full serialize %d bytes\n", tempLen );
+ printf ( "\nXMPUtils::PackageForJPEG - Full serialize %d bytes\n", tempStr.size() );
#endif
- if ( tempLen > kStdXMPLimit ) {
+ if ( tempStr.size() > kStdXMPLimit ) {
// Couldn't fit everything, make a copy of the input XMP and make sure there is no xmp:Thumbnails property.
@@ -1684,15 +1501,15 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
if ( stdXMP.DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) {
stdXMP.DeleteProperty ( kXMP_NS_XMP, "Thumbnails" );
- stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
+ stdXMP.SerializeToBuffer ( &tempStr, keepItSmall, 1, "", "", 0 );
#if Trace_PackageForJPEG
- printf ( " Delete xmp:Thumbnails, %d bytes left\n", tempLen );
+ printf ( " Delete xmp:Thumbnails, %d bytes left\n", tempStr.size() );
#endif
}
}
- if ( tempLen > kStdXMPLimit ) {
+ if ( tempStr.size() > kStdXMPLimit ) {
// Still doesn't fit, move all of the Camera Raw namespace. Add a dummy value for xmpNote:HasExtendedXMP.
@@ -1705,30 +1522,30 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
crSchema->parent = &extXMP.tree;
extXMP.tree.children.push_back ( crSchema );
stdXMP.tree.children.erase ( crSchemaPos );
- stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
+ stdXMP.SerializeToBuffer ( &tempStr, keepItSmall, 1, "", "", 0 );
#if Trace_PackageForJPEG
- printf ( " Move Camera Raw schema, %d bytes left\n", tempLen );
+ printf ( " Move Camera Raw schema, %d bytes left\n", tempStr.size() );
#endif
}
}
- if ( tempLen > kStdXMPLimit ) {
+ if ( tempStr.size() > kStdXMPLimit ) {
// Still doesn't fit, move photoshop:History.
bool moved = MoveOneProperty ( stdXMP, &extXMP, kXMP_NS_Photoshop, "photoshop:History" );
if ( moved ) {
- stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
+ stdXMP.SerializeToBuffer ( &tempStr, keepItSmall, 1, "", "", 0 );
#if Trace_PackageForJPEG
- printf ( " Move photoshop:History, %d bytes left\n", tempLen );
+ printf ( " Move photoshop:History, %d bytes left\n", tempStr.size() );
#endif
}
}
- if ( tempLen > kStdXMPLimit ) {
+ if ( tempStr.size() > kStdXMPLimit ) {
// Still doesn't fit, move top level properties in order of estimated size. This is done by
// creating a multi-map that maps the serialized size to the string pair for the schema URI
@@ -1770,10 +1587,11 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
// Outer loop to make sure enough is actually moved.
- while ( (tempLen > kStdXMPLimit) && (! propSizes.empty()) ) {
+ while ( (tempStr.size() > kStdXMPLimit) && (! propSizes.empty()) ) {
// Inner loop, move what seems to be enough according to the estimates.
+ size_t tempLen = tempStr.size();
while ( (tempLen > kStdXMPLimit) && (! propSizes.empty()) ) {
size_t propSize = MoveLargestProperty ( stdXMP, &extXMP, propSizes );
@@ -1786,13 +1604,13 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
// Reserialize the remaining standard XMP.
- stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
+ stdXMP.SerializeToBuffer ( &tempStr, keepItSmall, 1, "", "", 0 );
}
}
- if ( tempLen > kStdXMPLimit ) {
+ if ( tempStr.size() > kStdXMPLimit ) {
// Still doesn't fit, throw an exception and let the client decide what to do.
// ! This should never happen with the policy of moving any and all top level properties.
XMP_Throw ( "Can't reduce XMP enough for JPEG file", kXMPErr_TooLargeForJPEG );
@@ -1803,59 +1621,49 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
if ( extXMP.tree.children.empty() ) {
// Just have the standard XMP.
- sStandardXMP->assign ( tempStr, tempLen );
+ *stdStr = tempStr;
} else {
// Have extended XMP. Serialize it, compute the digest, reset xmpNote:HasExtendedXMP, and
// reserialize the standard XMP.
- extXMP.SerializeToBuffer ( &tempStr, &tempLen, (keepItSmall | kXMP_OmitPacketWrapper), 0, "", "", 0 );
- sExtendedXMP->assign ( tempStr, tempLen );
+ extXMP.SerializeToBuffer ( &tempStr, (keepItSmall | kXMP_OmitPacketWrapper), 0, "", "", 0 );
+ *extStr = tempStr;
MD5_CTX context;
XMP_Uns8 digest [16];
MD5Init ( &context );
- MD5Update ( &context, (XMP_Uns8*)tempStr, tempLen );
+ MD5Update ( &context, (XMP_Uns8*)tempStr.c_str(), (XMP_Uns32)tempStr.size() );
MD5Final ( digest, &context );
- sExtendedDigest->reserve ( 32 );
+ digestStr->reserve ( 32 );
for ( size_t i = 0; i < 16; ++i ) {
XMP_Uns8 byte = digest[i];
- sExtendedDigest->push_back ( kHexDigits [ byte>>4 ] );
- sExtendedDigest->push_back ( kHexDigits [ byte&0xF ] );
+ digestStr->push_back ( kHexDigits [ byte>>4 ] );
+ digestStr->push_back ( kHexDigits [ byte&0xF ] );
}
- stdXMP.SetProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP", sExtendedDigest->c_str(), 0 );
- stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
- sStandardXMP->assign ( tempStr, tempLen );
+ stdXMP.SetProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP", digestStr->c_str(), 0 );
+ stdXMP.SerializeToBuffer ( &tempStr, keepItSmall, 1, "", "", 0 );
+ *stdStr = tempStr;
}
// Adjust the standard XMP padding to be up to 2KB.
- XMP_Assert ( (sStandardXMP->size() > kTrailerLen) && (sStandardXMP->size() <= kStdXMPLimit) );
- const char * packetEnd = sStandardXMP->c_str() + sStandardXMP->size() - kTrailerLen;
+ XMP_Assert ( (stdStr->size() > kTrailerLen) && (stdStr->size() <= kStdXMPLimit) );
+ const char * packetEnd = stdStr->c_str() + stdStr->size() - kTrailerLen;
XMP_Assert ( XMP_LitMatch ( packetEnd, kPacketTrailer ) );
- size_t extraPadding = kStdXMPLimit - sStandardXMP->size(); // ! Do this before erasing the trailer.
+ size_t extraPadding = kStdXMPLimit - stdStr->size(); // ! Do this before erasing the trailer.
if ( extraPadding > 2047 ) extraPadding = 2047;
- sStandardXMP->erase ( sStandardXMP->size() - kTrailerLen );
- sStandardXMP->append ( extraPadding, ' ' );
- sStandardXMP->append ( kPacketTrailer );
-
- // Assign the output pointer and sizes.
-
- *stdStr = sStandardXMP->c_str();
- *stdLen = sStandardXMP->size();
- *extStr = sExtendedXMP->c_str();
- *extLen = sExtendedXMP->size();
- *digestStr = sExtendedDigest->c_str();
- *digestLen = sExtendedDigest->size();
+ stdStr->erase ( stdStr->size() - kTrailerLen );
+ stdStr->append ( extraPadding, ' ' );
+ stdStr->append ( kPacketTrailer );
} // PackageForJPEG
-
// -------------------------------------------------------------------------------------------------
// MergeFromJPEG
// -------------
@@ -1868,12 +1676,12 @@ XMPUtils::MergeFromJPEG ( XMPMeta * fullXMP,
const XMPMeta & extendedXMP )
{
- XMPUtils::AppendProperties ( extendedXMP, fullXMP, kXMPUtil_DoAllProperties );
+ XMP_OptionBits apFlags = (kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties);
+ XMPUtils::ApplyTemplate ( fullXMP, extendedXMP, apFlags );
fullXMP->DeleteProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP" );
} // MergeFromJPEG
-
// -------------------------------------------------------------------------------------------------
// CurrentDateTime
// ---------------
@@ -1891,20 +1699,22 @@ XMPUtils::CurrentDateTime ( XMP_DateTime * xmpTime )
xmpTime->year = currTime.tm_year + 1900;
xmpTime->month = currTime.tm_mon + 1;
xmpTime->day = currTime.tm_mday;
+ xmpTime->hasDate = true;
+
xmpTime->hour = currTime.tm_hour;
xmpTime->minute = currTime.tm_min;
xmpTime->second = currTime.tm_sec;
-
xmpTime->nanoSecond = 0;
+ xmpTime->hasTime = true;
+
xmpTime->tzSign = 0;
xmpTime->tzHour = 0;
xmpTime->tzMinute = 0;
-
+ xmpTime->hasTimeZone = false; // ! Needed for SetTimeZone.
XMPUtils::SetTimeZone ( xmpTime );
} // CurrentDateTime
-
// -------------------------------------------------------------------------------------------------
// SetTimeZone
// -----------
@@ -1918,8 +1728,10 @@ XMPUtils::SetTimeZone ( XMP_DateTime * xmpTime )
{
XMP_Assert ( xmpTime != 0 ); // ! Enforced by wrapper.
- if ( (xmpTime->tzSign != 0) || (xmpTime->tzHour != 0) || (xmpTime->tzMinute != 0) ) {
- XMP_Throw ( "SetTimeZone can only be used on \"zoneless\" times", kXMPErr_BadParam );
+ VerifyDateTimeFlags ( xmpTime );
+
+ if ( xmpTime->hasTimeZone ) {
+ XMP_Throw ( "SetTimeZone can only be used on zone-less times", kXMPErr_BadParam );
}
// Create ansi_tt form of the input time. Need the ansi_tm form to make the ansi_tt form.
@@ -1991,6 +1803,8 @@ XMPUtils::SetTimeZone ( XMP_DateTime * xmpTime )
}
xmpTime->tzHour = XMP_Int32 ( diffSecs / 3600.0 );
xmpTime->tzMinute = XMP_Int32 ( (diffSecs / 60.0) - (xmpTime->tzHour * 60.0) );
+
+ xmpTime->hasTimeZone = xmpTime->hasTime = true;
// *** Save the tm_isdst flag in a qualifier?
@@ -2002,7 +1816,6 @@ XMPUtils::SetTimeZone ( XMP_DateTime * xmpTime )
} // SetTimeZone
-
// -------------------------------------------------------------------------------------------------
// ConvertToUTCTime
// ----------------
@@ -2012,12 +1825,16 @@ XMPUtils::ConvertToUTCTime ( XMP_DateTime * time )
{
XMP_Assert ( time != 0 ); // ! Enforced by wrapper.
+ VerifyDateTimeFlags ( time );
+
+ if ( ! time->hasTimeZone ) return; // Do nothing if there is no current time zone.
+
XMP_Assert ( (0 <= time->tzHour) && (time->tzHour <= 23) );
XMP_Assert ( (0 <= time->tzMinute) && (time->tzMinute <= 59) );
XMP_Assert ( (-1 <= time->tzSign) && (time->tzSign <= +1) );
XMP_Assert ( (time->tzSign == 0) ? ((time->tzHour == 0) && (time->tzMinute == 0)) :
((time->tzHour != 0) || (time->tzMinute != 0)) );
-
+
if ( time->tzSign == kXMP_TimeEastOfUTC ) {
// We are before (east of) GMT, subtract the offset from the time.
time->hour -= time->tzHour;
@@ -2033,7 +1850,6 @@ XMPUtils::ConvertToUTCTime ( XMP_DateTime * time )
} // ConvertToUTCTime
-
// -------------------------------------------------------------------------------------------------
// ConvertToLocalTime
// ------------------
@@ -2043,6 +1859,10 @@ XMPUtils::ConvertToLocalTime ( XMP_DateTime * time )
{
XMP_Assert ( time != 0 ); // ! Enforced by wrapper.
+ VerifyDateTimeFlags ( time );
+
+ if ( ! time->hasTimeZone ) return; // Do nothing if there is no current time zone.
+
XMP_Assert ( (0 <= time->tzHour) && (time->tzHour <= 23) );
XMP_Assert ( (0 <= time->tzMinute) && (time->tzMinute <= 59) );
XMP_Assert ( (-1 <= time->tzSign) && (time->tzSign <= +1) );
@@ -2050,6 +1870,7 @@ XMPUtils::ConvertToLocalTime ( XMP_DateTime * time )
((time->tzHour != 0) || (time->tzMinute != 0)) );
ConvertToUTCTime ( time ); // The existing time zone might not be the local one.
+ time->hasTimeZone = false; // ! Needed for SetTimeZone.
SetTimeZone ( time ); // Fill in the local timezone offset, then adjust the time.
if ( time->tzSign > 0 ) {
@@ -2066,7 +1887,6 @@ XMPUtils::ConvertToLocalTime ( XMP_DateTime * time )
} // ConvertToLocalTime
-
// -------------------------------------------------------------------------------------------------
// CompareDateTime
// ---------------
@@ -2075,46 +1895,69 @@ XMPUtils::ConvertToLocalTime ( XMP_DateTime * time )
XMPUtils::CompareDateTime ( const XMP_DateTime & _in_left,
const XMP_DateTime & _in_right )
{
- int result;
+ int result = 0;
XMP_DateTime left = _in_left;
XMP_DateTime right = _in_right;
+
+ VerifyDateTimeFlags ( &left );
+ VerifyDateTimeFlags ( &right );
+
+ // Can't compare if one has a date and the other does not.
+ if ( left.hasDate != right.hasDate ) return 0; // Throw?
+
+ if ( left.hasTimeZone & right.hasTimeZone ) {
+ // If both times have zones then convert them to UTC, otherwise assume the same zone.
+ ConvertToUTCTime ( &left );
+ ConvertToUTCTime ( &right );
+ }
+
+ if ( left.hasDate ) {
+
+ XMP_Assert ( right.hasDate );
+
+ if ( left.year < right.year ) {
+ result = -1;
+ } else if ( left.year > right.year ) {
+ result = +1;
+ } else if ( left.month < right.month ) {
+ result = -1;
+ } else if ( left.month > right.month ) {
+ result = +1;
+ } else if ( left.day < right.day ) {
+ result = -1;
+ } else if ( left.day > right.day ) {
+ result = +1;
+ }
+
+ if ( result != 0 ) return result;
+
+ }
+
+ if ( left.hasTime & right.hasTime ) {
+
+ // Ignore the time parts if either value is date-only.
+
+ if ( left.hour < right.hour ) {
+ result = -1;
+ } else if ( left.hour > right.hour ) {
+ result = +1;
+ } else if ( left.minute < right.minute ) {
+ result = -1;
+ } else if ( left.minute > right.minute ) {
+ result = +1;
+ } else if ( left.second < right.second ) {
+ result = -1;
+ } else if ( left.second > right.second ) {
+ result = +1;
+ } else if ( left.nanoSecond < right.nanoSecond ) {
+ result = -1;
+ } else if ( left.nanoSecond > right.nanoSecond ) {
+ result = +1;
+ } else {
+ result = 0;
+ }
- ConvertToUTCTime ( &left );
- ConvertToUTCTime ( &right );
-
- // *** We could use memcmp if the XMP_DateTime stuct has no holes.
-
- if ( left.year < right.year ) {
- result = -1;
- } else if ( left.year > right.year ) {
- result = +1;
- } else if ( left.month < right.month ) {
- result = -1;
- } else if ( left.month > right.month ) {
- result = +1;
- } else if ( left.day < right.day ) {
- result = -1;
- } else if ( left.day > right.day ) {
- result = +1;
- } else if ( left.hour < right.hour ) {
- result = -1;
- } else if ( left.hour > right.hour ) {
- result = +1;
- } else if ( left.minute < right.minute ) {
- result = -1;
- } else if ( left.minute > right.minute ) {
- result = +1;
- } else if ( left.second < right.second ) {
- result = -1;
- } else if ( left.second > right.second ) {
- result = +1;
- } else if ( left.nanoSecond < right.nanoSecond ) {
- result = -1;
- } else if ( left.nanoSecond > right.nanoSecond ) {
- result = +1;
- } else {
- result = 0;
}
return result;
diff --git a/source/XMPCore/XMPUtils.hpp b/source/XMPCore/XMPUtils.hpp
index e1c7e78..a7d0153 100644
--- a/source/XMPCore/XMPUtils.hpp
+++ b/source/XMPCore/XMPUtils.hpp
@@ -2,7 +2,7 @@
#define __XMPUtils_hpp__
// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
+// Copyright 2003 Adobe Systems Incorporated
// All Rights Reserved.
//
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
@@ -18,16 +18,6 @@
// -------------------------------------------------------------------------------------------------
-extern XMP_VarString * sComposedPath; // *** Only really need 1 string. Shrink periodically?
-extern XMP_VarString * sConvertedValue;
-extern XMP_VarString * sBase64Str;
-extern XMP_VarString * sCatenatedItems;
-extern XMP_VarString * sStandardXMP;
-extern XMP_VarString * sExtendedXMP;
-extern XMP_VarString * sExtendedDigest;
-
-// -------------------------------------------------------------------------------------------------
-
class XMPUtils {
public:
@@ -37,40 +27,33 @@ public:
static void
Terminate() RELEASE_NO_THROW; // ! For internal use only!
- static void
- Unlock ( XMP_OptionBits options );
-
// ---------------------------------------------------------------------------------------------
static void
ComposeArrayItemPath ( XMP_StringPtr schemaNS,
XMP_StringPtr arrayName,
XMP_Index itemIndex,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize );
+ XMP_VarString * fullPath );
static void
ComposeStructFieldPath ( XMP_StringPtr schemaNS,
XMP_StringPtr structName,
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize );
+ XMP_VarString * fullPath );
static void
ComposeQualifierPath ( XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_StringPtr qualNS,
XMP_StringPtr qualName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize );
+ XMP_VarString * fullPath );
static void
- ComposeLangSelector ( XMP_StringPtr schemaNS,
- XMP_StringPtr arrayName,
- XMP_StringPtr langName,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize );
+ ComposeLangSelector ( XMP_StringPtr schemaNS,
+ XMP_StringPtr arrayName,
+ XMP_StringPtr langName,
+ XMP_VarString * fullPath );
static void
ComposeFieldSelector ( XMP_StringPtr schemaNS,
@@ -78,38 +61,32 @@ public:
XMP_StringPtr fieldNS,
XMP_StringPtr fieldName,
XMP_StringPtr fieldValue,
- XMP_StringPtr * fullPath,
- XMP_StringLen * pathSize );
+ XMP_VarString * fullPath );
// ---------------------------------------------------------------------------------------------
static void
ConvertFromBool ( bool binValue,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize );
+ XMP_VarString * strValue );
static void
ConvertFromInt ( XMP_Int32 binValue,
XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize );
+ XMP_VarString * strValue );
static void
ConvertFromInt64 ( XMP_Int64 binValue,
XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize );
+ XMP_VarString * strValue );
static void
ConvertFromFloat ( double binValue,
XMP_StringPtr format,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize );
+ XMP_VarString * strValue );
static void
ConvertFromDate ( const XMP_DateTime & binValue,
- XMP_StringPtr * strValue,
- XMP_StringLen * strSize );
+ XMP_VarString * strValue );
// ---------------------------------------------------------------------------------------------
@@ -151,25 +128,20 @@ public:
static void
EncodeToBase64 ( XMP_StringPtr rawStr,
XMP_StringLen rawLen,
- XMP_StringPtr * encodedStr,
- XMP_StringLen * encodedLen );
+ XMP_VarString * encodedStr );
static void
DecodeFromBase64 ( XMP_StringPtr encodedStr,
XMP_StringLen encodedLen,
- XMP_StringPtr * rawStr,
- XMP_StringLen * rawLen );
+ XMP_VarString * rawStr );
// ---------------------------------------------------------------------------------------------
static void
PackageForJPEG ( const XMPMeta & xmpObj,
- XMP_StringPtr * stdStr,
- XMP_StringLen * stdLen,
- XMP_StringPtr * extStr,
- XMP_StringLen * extLen,
- XMP_StringPtr * digestStr,
- XMP_StringLen * digestLen );
+ XMP_VarString * stdStr,
+ XMP_VarString * extStr,
+ XMP_VarString * digestStr );
static void
MergeFromJPEG ( XMPMeta * fullXMP,
@@ -184,8 +156,7 @@ public:
XMP_StringPtr separator,
XMP_StringPtr quotes,
XMP_OptionBits options,
- XMP_StringPtr * catedStr,
- XMP_StringLen * catedLen );
+ XMP_VarString * catedStr );
static void
SeparateArrayItems ( XMPMeta * xmpObj,
@@ -195,17 +166,17 @@ public:
XMP_StringPtr catedStr );
static void
+ ApplyTemplate ( XMPMeta * workingXMP,
+ const XMPMeta & templateXMP,
+ XMP_OptionBits actions );
+
+ static void
RemoveProperties ( XMPMeta * xmpObj,
XMP_StringPtr schemaNS,
XMP_StringPtr propName,
XMP_OptionBits options );
static void
- AppendProperties ( const XMPMeta & source,
- XMPMeta * dest,
- XMP_OptionBits options );
-
- static void
DuplicateSubtree ( const XMPMeta & source,
XMPMeta * dest,
XMP_StringPtr sourceNS,