TXMPMeta
provides the fundamental methods for manipulating XMP metadata. TXMPIterator
provides methods to iterate over existing XMP metadata. TXMPUtils
provides additional utilities layered on top of TXMPMeta
. Use a string class to instantiate the templates; you can use std::string
. The string class is a template parameter, which simplifies its use for clients that have an existing string model different from std::string
.
WXMPMeta
, WXMPIterator
, and WXMPUtils
. They provide wrappers between the top client layer and the actual implementation. The middle layer is responsible for acquiring the threading lock, basic parameter checking, catching propagated exceptions, and releasing the threading lock when appropriate. XMPMeta
, XMPIterator
, and XMPUtils
.TXMP_STRING_TYPE
must be defined first to provide the string class.
The string class used to instantiate the templates must have the following member functions, which match those of std::string:
assign ( const char * str, size_t len ) size_t size() const const char * c_str() const
assign
does not matter, it is always ignored.Use of the XMP Toolkit is reasonably straightforward once you understand the XMP data model. Some tips to keep in mind:
Get/SetStructField
or ComposeStructFieldPath
. Get/SetLocalizedText
when dealing with language alternative (alt-text) arrays.GetProperty
provides a good illustration of the toolkit layering. The declaration below for TXMPMeta::GetProperty
is simplified by hardwiring std::string
. The XMP_StringPtr
type is simply const char *
.
bool TXMPMeta::GetProperty ( XMP_StringPtr schemaNS, XMP_StringPtr propName, std::string * propValue, XMP_OptionBits * options ) const { XMP_StringPtr resultPtr = 0; XMP_StringLen resultLen = 0; bool found = this->xmpObj.GetProperty ( schemaNS, propName, &resultPtr, &resultLen, options ); if ( found ) { if ( propValue != 0 ) propValue->assign ( resultPtr, resultLen ); this->xmpObj.UnlockObject ( kXMP_NoOptions ); } return found; }
The template object contains a data member pointer to the underlying WXMPMeta
object. This is used to dispatch the call to the middle layer. The actual implementation of the XMP toolkit returns string values as a pointer and length, the pointer references private internal storage of the toolkit. The client code copies the string value to the client's string object. This minimizes the amount of string copying, and should the XMP toolkit be built as a DLL ensures that any memory allocation for the client's value is done on the client side. The call to WXMPMeta::UnlockObject
is explained below.
bool WXMPMeta::GetProperty ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_StringPtr * propValue, XMP_StringLen * valueSize, XMP_OptionBits * options ) const { XMP_Bool found; XMP_ENTER_WRAPPER ( "WXMPMeta::GetProperty" ) 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; if ( options == 0 ) options = &voidOptionBits; const XMPMeta & meta = WtoXMPMeta_Ref ( *this ); found = meta.GetProperty ( schemaNS, propName, propValue, valueSize, options ); XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) return found; }
The entry and exit macros in the WXMPMeta
layer acquire the threading lock on entry and usually release it on exit. The lock is kept on exit whenever a string value is returned. Since a pointer to internal data is returned, the threading lock can't be released until after the template code in the client copies the string. The entry and exit macros also prevent uncontrolled exception propagation from the lower layer back to the client. This is not critical for use of the XMP Toolkit as a static library. But it is generally not safe to propagate C++ exceptions across DLL boundaries.