diff options
Diffstat (limited to 'XMPCore')
96 files changed, 14106 insertions, 294 deletions
diff --git a/XMPCore/ImplHeaders/ArrayNodeImpl.h b/XMPCore/ImplHeaders/ArrayNodeImpl.h new file mode 100644 index 0000000..d173e90 --- /dev/null +++ b/XMPCore/ImplHeaders/ArrayNodeImpl.h @@ -0,0 +1,71 @@ +#ifndef ArrayNodeImpl_h__ +#define ArrayNodeImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/ImplHeaders/CompositeNodeImpl.h" +#include "XMPCommon/Utilities/TAllocator.h" + +#include <vector> + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class ArrayNodeImpl + : public virtual IArrayNode_I + , public virtual CompositeNodeImpl + { + public: + typedef std::vector< spINode, TAllocator< spINode > > NodeVector; + + ArrayNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, eArrayForm arrarForm ); + + virtual eArrayForm APICALL GetArrayForm() const; + virtual eNodeType APICALL GetChildNodeType() const; + virtual spINode APICALL GetNodeAtIndex( sizet index ); + virtual void APICALL InsertNodeAtIndex( const spINode & node, sizet index ); + virtual spINode APICALL RemoveNodeAtIndex( sizet index ); + virtual spINode APICALL ReplaceNodeAtIndex( const spINode & node, sizet index ); + virtual void APICALL AppendNode( const spINode & node ); + virtual spINodeIterator APICALL Iterator(); + virtual sizet APICALL ChildCount() const __NOTHROW__; + virtual spIArrayNode APICALL ConvertToArrayNode(); + virtual eNodeType APICALL GetNodeType() const; + virtual bool APICALL HasContent() const; + virtual void APICALL ClearContents(); + virtual spINode APICALL CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const; + virtual bool CheckSuitabilityToBeUsedAsChildNode( const spcINode & node ) const; + + protected: + virtual ~ArrayNodeImpl() __NOTHROW__ {} + virtual void resetChangesForChildren() const; + + + eArrayForm mArrayForm; + NodeVector mChildren; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#endif // ArrayNodeImpl_h__ diff --git a/XMPCore/ImplHeaders/ClientDOMParserWrapperImpl.h b/XMPCore/ImplHeaders/ClientDOMParserWrapperImpl.h new file mode 100644 index 0000000..c2614fb --- /dev/null +++ b/XMPCore/ImplHeaders/ClientDOMParserWrapperImpl.h @@ -0,0 +1,50 @@ +#ifndef ClientDOMParserWrapperImpl_h__ +#define ClientDOMParserWrapperImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/ImplHeaders/DOMParserImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class ClientDOMParserWrapperImpl + : public virtual DOMParserImpl + { + public: + ClientDOMParserWrapperImpl( pIClientDOMParser_base parser ); + + virtual spINode APICALL ParseAsNode( const char * buffer, sizet bufferLength ); + virtual eConfigurableErrorCode APICALL ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const; + virtual DOMParserImpl * APICALL clone() const; + + protected: + virtual ~ClientDOMParserWrapperImpl() __NOTHROW__ ; + + pIClientDOMParser_base mpClientParser; + + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // ClientDOMParserWrapperImpl_h__ + diff --git a/XMPCore/ImplHeaders/ClientDOMSerializerWrapperImpl.h b/XMPCore/ImplHeaders/ClientDOMSerializerWrapperImpl.h new file mode 100644 index 0000000..5cd2e8d --- /dev/null +++ b/XMPCore/ImplHeaders/ClientDOMSerializerWrapperImpl.h @@ -0,0 +1,50 @@ +#ifndef ClientDOMSerializerWrapperImpl_h__ +#define ClientDOMSerializerWrapperImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/ImplHeaders/DOMSerializerImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class ClientDOMSerializerWrapperImpl + : public virtual DOMSerializerImpl + { + public: + ClientDOMSerializerWrapperImpl( pIClientDOMSerializer serializer ); + virtual spIUTF8String APICALL Serialize( const spINode & node, const spcINameSpacePrefixMap & map ); + virtual eConfigurableErrorCode APICALL ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const; + spIUTF8String APICALL SerializeInternal(const spINode & node, XMP_OptionBits options, sizet padding, const char * newline, const char * indent, sizet baseIndent, const spcINameSpacePrefixMap & nameSpacePrefixMap) const; + + protected: + virtual ~ClientDOMSerializerWrapperImpl() __NOTHROW__ ; + virtual DOMSerializerImpl * APICALL clone() const; + + pIClientDOMSerializer mpSerializer; + + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // ClientDOMSerializerWrapperImpl_h__ + diff --git a/XMPCore/ImplHeaders/CompositeNodeImpl.h b/XMPCore/ImplHeaders/CompositeNodeImpl.h new file mode 100644 index 0000000..90073e2 --- /dev/null +++ b/XMPCore/ImplHeaders/CompositeNodeImpl.h @@ -0,0 +1,56 @@ +#ifndef CompositeNodeImpl_h__ +#define CompositeNodeImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/ICompositeNode_I.h" +#include "XMPCore/ImplHeaders/NodeImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class CompositeNodeImpl + : public virtual ICompositeNode_I + , public virtual NodeImpl + { + public: + CompositeNodeImpl() {} + + virtual eNodeType APICALL GetNodeTypeAtPath( const spcIPath & path ) const; + virtual spINode APICALL GetNodeAtPath( const spcIPath & path ); + virtual void APICALL InsertNodeAtPath( const spINode & node, const spcIPath & path ); + virtual spINode APICALL ReplaceNodeAtPath( const spINode & node, const spcIPath & path ); + virtual spINode APICALL RemoveNodeAtPath( const spcIPath & path ); + virtual bool CheckSuitabilityToBeUsedAsChildNode( const spcINode & node ) const; + + protected: + virtual ~CompositeNodeImpl() __NOTHROW__ {} + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // CompositeNodeImpl_h__ diff --git a/XMPCore/ImplHeaders/CoreConfigurationManagerImpl.h b/XMPCore/ImplHeaders/CoreConfigurationManagerImpl.h new file mode 100644 index 0000000..d85f573 --- /dev/null +++ b/XMPCore/ImplHeaders/CoreConfigurationManagerImpl.h @@ -0,0 +1,50 @@ +#ifndef CoreConfigurationManagerImpl_h__ +#define CoreConfigurationManagerImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/ICoreConfigurationManager_I.h" +#include "XMPCommon/ImplHeaders/ConfigurationManagerImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class CoreConfigurationManagerImpl + : public virtual ICoreConfigurationManager_I + , public virtual ConfigurationManagerImpl + { + public: + CoreConfigurationManagerImpl(); + + + protected: + virtual ~CoreConfigurationManagerImpl() __NOTHROW__ {} + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif +#endif // CoreConfigurationManagerImpl_h__ + diff --git a/XMPCore/ImplHeaders/CoreObjectFactoryImpl.h b/XMPCore/ImplHeaders/CoreObjectFactoryImpl.h new file mode 100644 index 0000000..ab4125b --- /dev/null +++ b/XMPCore/ImplHeaders/CoreObjectFactoryImpl.h @@ -0,0 +1,65 @@ +#ifndef CoreObjectFactoryImpl_h__ +#define CoreObjectFactoryImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/ICoreObjectFactory_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class CoreObjectFactoryImpl + : public virtual ICoreObjectFactory_I + { + public: + CoreObjectFactoryImpl() {} + virtual ~CoreObjectFactoryImpl() __NOTHROW__ {} + + virtual pIError_base APICALL CreateError( uint32 domain, uint32 code, uint32 severity, pcIError_base & error ) __NOTHROW__; + virtual pIUTF8String_base APICALL CreateUTF8String( const char * buf, sizet count, pcIError_base & error ) __NOTHROW__; + virtual pcIPathSegment_base APICALL CreateArrayIndexPathSegment( const char * nameSpace, sizet nameSpaceLength, sizet index, pcIError_base & error ) __NOTHROW__; + virtual pIArrayNode_base APICALL CreateArrayNode( uint32 arrayForm, const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual pIMetadata_base APICALL CreateMetadata( pcIError_base & error ) __NOTHROW__; + virtual pINameSpacePrefixMap_base APICALL CreateNameSpacePrefixMap( pcIError_base & error ) __NOTHROW__; + virtual pIPath_base APICALL CreatePath( pcIError_base & error ) __NOTHROW__; + virtual pcIPathSegment_base APICALL CreatePropertyPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual pcIPathSegment_base APICALL CreateQualifierPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual pcIPathSegment_base APICALL CreateQualifierSelectorPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength, pcIError_base & error ) __NOTHROW__; + virtual pISimpleNode_base APICALL CreateSimpleNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength, pcIError_base & error ) __NOTHROW__; + virtual pIStructureNode_base APICALL CreateStructureNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual pICoreConfigurationManager_base APICALL GetCoreConfigurationManager( pcIError_base & error ) __NOTHROW__; + virtual pIDOMImplementationRegistry_base APICALL GetDOMImplementationRegistry( pcIError_base & error ) __NOTHROW__; + virtual pcINameSpacePrefixMap_base APICALL GetDefaultNameSpacePrefixMap( pcIError_base & error ) __NOTHROW__; + virtual pIPath_base APICALL ParsePath( const char * path, sizet pathLength, pcINameSpacePrefixMap_base map, pcIError_base & error ) __NOTHROW__; + + protected: + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + + + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + + +#endif // CoreObjectFactoryImpl_h__ diff --git a/XMPCore/ImplHeaders/DOMImplementationRegistryImpl.h b/XMPCore/ImplHeaders/DOMImplementationRegistryImpl.h new file mode 100644 index 0000000..c81e611 --- /dev/null +++ b/XMPCore/ImplHeaders/DOMImplementationRegistryImpl.h @@ -0,0 +1,62 @@ +#ifndef DOMImplementationRegistryImpl_h__ +#define DOMImplementationRegistryImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" +#include "XMPCommon/Utilities/IUTF8StringComparator.h" +#include "XMPCommon/Utilities/TAllocator.h" + +#include <map> +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class DOMImplementationRegistryImpl + : public virtual IDOMImplementationRegistry_I + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + { + public: + typedef std::map< spcIUTF8String, spcIDOMParser, IUTF8StringComparator, TAllocator< spcIUTF8String > > ParserMap; + typedef std::map< spcIUTF8String, spcIDOMSerializer, IUTF8StringComparator, TAllocator< spcIUTF8String > > SerializerMap; + + DOMImplementationRegistryImpl() {} + + virtual bool APICALL RegisterParser( const char * key, const spcIDOMParser & parser ); + virtual bool APICALL RegisterSerializer( const char * key, const spcIDOMSerializer & serializer ); + virtual spIDOMParser APICALL GetParser( const char * key ) const; + virtual spIDOMSerializer APICALL GetSerializer( const char * key ) const; + + + protected: + virtual ~DOMImplementationRegistryImpl() __NOTHROW__ {} + + ParserMap mParserMap; + SerializerMap mSerializerMap; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#endif // DOMImplementationRegistryImpl_h__
\ No newline at end of file diff --git a/XMPCore/ImplHeaders/DOMParserImpl.h b/XMPCore/ImplHeaders/DOMParserImpl.h new file mode 100644 index 0000000..488170f --- /dev/null +++ b/XMPCore/ImplHeaders/DOMParserImpl.h @@ -0,0 +1,64 @@ +#ifndef DOMParserImpl_h__ +#define DOMParserImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IDOMParser_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" +#include "XMPCommon/ImplHeaders/ConfigurableImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class DOMParserImpl + : public virtual IDOMParser_I + , public virtual ConfigurableImpl + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + { + public: + DOMParserImpl(); + + virtual spIDOMParser APICALL Clone() const; + virtual spIMetadata APICALL Parse( const char * buffer, sizet bufferLength ); + virtual void APICALL ParseWithSpecificAction( const char * buffer, sizet bufferLength, eActionType actionType, spINode & node ); + virtual spISharedMutex APICALL GetMutex() const; + virtual void SetErrorCallback(XMPMeta::ErrorCallbackInfo * ec); + + protected: + virtual ~DOMParserImpl() __NOTHROW__ {} + virtual DOMParserImpl * APICALL clone() const = 0; + + spISharedMutex mSharedMutex; + XMPMeta::ErrorCallbackInfo * mGenericErrorCallbackPtr; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // DOMParserImpl_h__ + diff --git a/XMPCore/ImplHeaders/DOMSerializerImpl.h b/XMPCore/ImplHeaders/DOMSerializerImpl.h new file mode 100644 index 0000000..ce8cbfa --- /dev/null +++ b/XMPCore/ImplHeaders/DOMSerializerImpl.h @@ -0,0 +1,60 @@ +#ifndef DOMSerializerImpl_h__ +#define DOMSerializerImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IDOMSerializer_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" +#include "XMPCommon/ImplHeaders/ConfigurableImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class DOMSerializerImpl + : public virtual IDOMSerializer_I + , public virtual ConfigurableImpl + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + { + public: + DOMSerializerImpl(); + + virtual spISharedMutex APICALL GetMutex() const; + virtual spIDOMSerializer APICALL Clone() const; + virtual spIUTF8String APICALL SerializeInternal(const spINode & node, XMP_OptionBits options, sizet padding, const char * newline, const char * indent, sizet baseIndent, const spcINameSpacePrefixMap & nameSpacePrefixMap) const = 0; + + protected: + virtual ~DOMSerializerImpl() __NOTHROW__ {} + virtual DOMSerializerImpl * APICALL clone() const = 0; + + spISharedMutex mSharedMutex; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif +#endif // DOMSerializerImpl_h__ + diff --git a/XMPCore/ImplHeaders/MetadataImpl.h b/XMPCore/ImplHeaders/MetadataImpl.h new file mode 100644 index 0000000..69609c4 --- /dev/null +++ b/XMPCore/ImplHeaders/MetadataImpl.h @@ -0,0 +1,82 @@ +#ifndef MetadataImpl_h__ +#define MetadataImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/ImplHeaders/StructureNodeImpl.h" +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class MetadataImpl + : public virtual IMetadata_I + , public virtual StructureNodeImpl + { + public: + MetadataImpl(); + + + protected: + virtual ~MetadataImpl() __NOTHROW__ {} + + virtual spcIUTF8String APICALL GetAboutURI() const; + virtual void APICALL SetAboutURI( const char * uri, sizet uriLength ) __NOTHROW__; + + virtual spcIUTF8String APICALL GetName() const; + virtual spcIUTF8String APICALL GetNameSpace() const; + + virtual spINode APICALL GetParent(); + virtual eNodeType APICALL GetParentNodeType() const; + + virtual void APICALL SetName( const char * name, sizet nameLength ); + virtual void APICALL SetNameSpace( const char * nameSpace, sizet nameSpaceLength ); + + virtual void APICALL ClearContents(); + virtual spINode APICALL CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const; + + virtual spIMetadata APICALL ConvertToMetadata(); + virtual void APICALL EnableFeature( const char * key, sizet keyLength ) const __NOTHROW__; + virtual void APICALL DisableFeature( const char * key, sizet keyLength ) const __NOTHROW__; + + virtual spINode APICALL GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + virtual spINode APICALL RemoveNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + virtual void APICALL InsertNode( const spINode & node ); + virtual spINode APICALL ReplaceNode( const spINode & node ); + + spIUTF8String mAboutURI; + mutable bool mSupportAliases; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#endif // MetadataImpl_h__ + diff --git a/XMPCore/ImplHeaders/NameSpacePrefixMapImpl.h b/XMPCore/ImplHeaders/NameSpacePrefixMapImpl.h new file mode 100644 index 0000000..de23e43 --- /dev/null +++ b/XMPCore/ImplHeaders/NameSpacePrefixMapImpl.h @@ -0,0 +1,79 @@ +#ifndef NameSpacePrefixMapImpl_h__ +#define NameSpacePrefixMapImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" +#include "XMPCommon/ImplHeaders/ThreadSafeImpl.h" +#include "XMPCommon/Utilities/TAllocator.h" +#include "XMPCommon/Utilities/IUTF8StringComparator.h" + + +#include <map> + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class NameSpacePrefixMapImpl + : public virtual INameSpacePrefixMap_I + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + , public virtual ThreadSafeImpl + { + public: + typedef std::pair< spcIUTF8String, spcIUTF8String > NameSpacePrefixPair; + typedef std::map< spcIUTF8String, spcIUTF8String, IUTF8StringComparator, TAllocator< spcIUTF8String > > NameSpacePrefixMap; + + NameSpacePrefixMapImpl(); + + + protected: + virtual ~NameSpacePrefixMapImpl() __NOTHROW__ {} + + virtual bool APICALL Insert( const char * prefix, sizet prefixLength, const char * nameSpace, sizet nameSpaceLength ); + virtual bool APICALL RemovePrefix( const char * prefix, sizet prefixLength ); + virtual bool APICALL RemoveNameSpace( const char * nameSpace, sizet nameSpaceLength ); + virtual bool APICALL IsPrefixPresent( const char * prefix, sizet prefixLength ) const; + virtual bool APICALL IsNameSpacePresent( const char * nameSpace, sizet nameSpaceLength ) const; + virtual spcIUTF8String APICALL GetNameSpace( const char * prefix, sizet prefixLength ) const; + virtual spcIUTF8String APICALL GetNameSpace( const spcIUTF8String & prefix ) const; + virtual spcIUTF8String APICALL GetPrefix( const char * nameSpace, sizet nameSpaceLength ) const; + virtual spcIUTF8String APICALL GetPrefix( const spcIUTF8String & nameSpace ) const; + virtual void APICALL Merge( const spcINameSpacePrefixMap & otherMap ); + virtual sizet APICALL Size() const __NOTHROW__; + virtual void APICALL Clear() __NOTHROW__; + virtual spINameSpacePrefixMap APICALL Clone() const; + + NameSpacePrefixMap mNameSpaceToPrefixMap; + NameSpacePrefixMap mPrefixToNameSpaceMap; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // NameSpacePrefixMapImpl_h__ diff --git a/XMPCore/ImplHeaders/NodeImpl.h b/XMPCore/ImplHeaders/NodeImpl.h new file mode 100644 index 0000000..7a01cdc --- /dev/null +++ b/XMPCore/ImplHeaders/NodeImpl.h @@ -0,0 +1,111 @@ +#ifndef __NodeImpl_h__ +#define __NodeImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/INode_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" +#include "XMPCommon/ImplHeaders/ThreadSafeImpl.h" +#include "XMPCommon/Utilities/TAtomicTypes.h" + +#include <map> + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class NodeImpl + : public virtual INode_I + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + , public virtual ThreadSafeImpl + { + public: + NodeImpl() {} + NodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ); + + virtual void APICALL ChangeParent( pINode parent ); + virtual pINode APICALL GetRawParentPointer(); + virtual spINode APICALL GetParent(); + virtual void APICALL SetName( const char * name, sizet nameLength ); + virtual spcIUTF8String APICALL GetName() const; + virtual void APICALL SetNameSpace( const char * nameSpace, sizet nameSpaceLength ); + virtual spcIUTF8String APICALL GetNameSpace() const; + virtual spIPath APICALL GetPath() const; + virtual sizet APICALL QualifiersCount() const __NOTHROW__; + virtual spINodeIterator APICALL QualifiersIterator(); + virtual spINode APICALL GetQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ); + virtual spINode APICALL GetQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + virtual void APICALL InsertQualifier( const spINode & node ); + virtual spINode APICALL ReplaceQualifier( const spINode & node ); + virtual spINode APICALL RemoveQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ); + virtual spINode APICALL RemoveQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + virtual bool APICALL IsArrayItem() const; + virtual bool APICALL HasQualifiers() const; + virtual bool APICALL IsEmpty() const; + virtual bool APICALL HasChanged() const; + virtual void APICALL AcknowledgeChanges() const __NOTHROW__; + virtual void APICALL Clear( bool contents = true, bool qualifiers = true ); + virtual spINode APICALL Clone( bool ignoreEmptyNodes = false, bool ignoreNodesWithOnlyQualifiers = false ) const; + virtual void SetIndex( sizet currentIndex ); + virtual void SetIsQualifierNode( bool isQualifierNode ); + virtual bool APICALL IsQualifierNode() const; + virtual sizet APICALL GetIndex() const; + virtual void RegisterChange(); + virtual eNodeType APICALL GetParentNodeType() const; + virtual eNodeType APICALL GetQualifierNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) const; + virtual spISimpleNode APICALL ConvertToSimpleNode(); + virtual spIStructureNode APICALL ConvertToStructureNode(); + virtual spIArrayNode APICALL ConvertToArrayNode(); + virtual spIMetadata APICALL ConvertToMetadata(); + virtual void UnRegisterChange(); + virtual bool ValidateNameOrNameSpaceChangeForAChild( const spcIUTF8String & currentNameSpace, const spcIUTF8String & currentName, const spcIUTF8String & newNameSpace, const spcIUTF8String & newName ); + + virtual void APICALL Acquire() const __NOTHROW__; + virtual void APICALL Release() const __NOTHROW__; + virtual void APICALL AcquireInternal() const __NOTHROW__; + + // functions base classes need to implement. + virtual void APICALL ClearContents() = 0; + virtual spINode APICALL CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const = 0; + virtual void SetQualifiers( const spIStructureNode & node ); + + protected: + void updateParentSharedPointer( bool calledFromRelease = false ); + virtual void resetChangesForChildren() const = 0; + void CreateQualifierNode(); + virtual ~NodeImpl() __NOTHROW__ {} + + spIUTF8String mNameSpace; + spIUTF8String mName; + sizet mIndex; + pINode mpParent; + spINode mspParent; + spIStructureNode mQualifiers; + mutable atomic_sizet mChangeCount; + bool mIsQualifierNode; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#endif // __NodeImpl_h__ diff --git a/XMPCore/ImplHeaders/PathImpl.h b/XMPCore/ImplHeaders/PathImpl.h new file mode 100644 index 0000000..85588f4 --- /dev/null +++ b/XMPCore/ImplHeaders/PathImpl.h @@ -0,0 +1,66 @@ +#ifndef PathImpl_h__ +#define PathImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IPath_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" +#include "XMPCommon/Utilities/TAllocator.h" +#include <vector> + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class PathImpl + : public virtual IPath_I + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + { + public: + typedef std::vector< spcIPathSegment, TAllocator< spcIPathSegment > > spcIPathSegments; + + + protected: + virtual ~PathImpl() __NOTHROW__ {} + + virtual spcINameSpacePrefixMap APICALL RegisterNameSpacePrefixMap( const spcINameSpacePrefixMap & map ); + virtual spIUTF8String APICALL Serialize( const spcINameSpacePrefixMap & map = spcINameSpacePrefixMap() ) const; + virtual void APICALL AppendPathSegment( const spcIPathSegment & segment ); + virtual spcIPathSegment APICALL RemovePathSegment( sizet index ); + virtual spcIPathSegment APICALL GetPathSegment( sizet index ) const; + virtual sizet APICALL Size() const __NOTHROW__; + virtual void APICALL Clear() __NOTHROW__; + virtual spIPath APICALL Clone( sizet startingIndex = 1, sizet countOfSegments = kMaxSize ) const; + + spcIPathSegments mSegments; + spcINameSpacePrefixMap mNameSpacePrefixMap; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // PathImpl_h__ diff --git a/XMPCore/ImplHeaders/PathSegmentImpl.h b/XMPCore/ImplHeaders/PathSegmentImpl.h new file mode 100644 index 0000000..fd89b1e --- /dev/null +++ b/XMPCore/ImplHeaders/PathSegmentImpl.h @@ -0,0 +1,66 @@ +#ifndef PathSegmentImpl_h__ +#define PathSegmentImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class PathSegmentImpl + : public virtual IPathSegment_I + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + { + public: + PathSegmentImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, + const char * value, sizet valueLength, ePathSegmentType type, sizet index ); + + virtual spcIUTF8String APICALL GetNameSpace() const; + virtual spcIUTF8String APICALL GetName() const; + virtual ePathSegmentType APICALL GetType() const; + virtual sizet APICALL GetIndex() const __NOTHROW__; + virtual spcIUTF8String APICALL GetValue() const; + virtual spcIPathSegment APICALL Clone() const; + + + protected: + virtual ~PathSegmentImpl() __NOTHROW__ {} + + spIUTF8String mNameSpace; + spIUTF8String mName; + spIUTF8String mValue; + ePathSegmentType mType; + sizet mIndex; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // PathSegmentImpl_h__ diff --git a/XMPCore/ImplHeaders/RDFDOMParserImpl.h b/XMPCore/ImplHeaders/RDFDOMParserImpl.h new file mode 100644 index 0000000..aeaeda8 --- /dev/null +++ b/XMPCore/ImplHeaders/RDFDOMParserImpl.h @@ -0,0 +1,53 @@ +#ifndef RDFDOMParserImpl_h__ +#define RDFDOMParserImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/ImplHeaders/DOMParserImpl.h" +#include "XMPCore/source/XMPMeta.hpp" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class RDFDOMParserImpl + : public virtual DOMParserImpl + { + public: + RDFDOMParserImpl() { + mGenericErrorCallbackPtr = NULL; + } + virtual spINode APICALL ParseAsNode( const char * buffer, sizet bufferLength ); + virtual eConfigurableErrorCode APICALL ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const; + void InitializeDefaultValues(); + void SetErrorCallback(XMPMeta::ErrorCallbackInfo * ec); + protected: + virtual ~RDFDOMParserImpl() __NOTHROW__ {} + virtual DOMParserImpl * APICALL clone() const; + + private: + XMPMeta::ErrorCallbackInfo * mGenericErrorCallbackPtr; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#endif // RDFDOMParserImpl_h__ diff --git a/XMPCore/ImplHeaders/RDFDOMSerializerImpl.h b/XMPCore/ImplHeaders/RDFDOMSerializerImpl.h new file mode 100644 index 0000000..77cdd7b --- /dev/null +++ b/XMPCore/ImplHeaders/RDFDOMSerializerImpl.h @@ -0,0 +1,53 @@ +#ifndef RDFDOMSerializerImpl_h__ +#define RDFDOMSerializerImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/ImplHeaders/DOMSerializerImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class RDFDOMSerializerImpl + : public virtual DOMSerializerImpl + { + public: + RDFDOMSerializerImpl() {} + virtual spIUTF8String APICALL Serialize( const spINode & node, const spcINameSpacePrefixMap & nameSpacePrefixMap ); + virtual eConfigurableErrorCode APICALL ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const; + virtual spIUTF8String APICALL SerializeInternal(const spINode & node, XMP_OptionBits options, sizet padding, const char * newline, const char * indent, sizet baseIndent, const spcINameSpacePrefixMap & nameSpacePrefixMap) const; + void InitializeDefaultValues(); + + protected: + virtual ~RDFDOMSerializerImpl() __NOTHROW__ {} + virtual DOMSerializerImpl * APICALL clone() const; + + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // RDFDOMSerializerImpl_h__ diff --git a/XMPCore/ImplHeaders/SimpleNodeImpl.h b/XMPCore/ImplHeaders/SimpleNodeImpl.h new file mode 100644 index 0000000..6e882a6 --- /dev/null +++ b/XMPCore/ImplHeaders/SimpleNodeImpl.h @@ -0,0 +1,66 @@ +#ifndef __SimpleNodeImpl_h__ +#define __SimpleNodeImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/ImplHeaders/NodeImpl.h" + + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class SimpleNodeImpl + : public virtual ISimpleNode_I + , public virtual NodeImpl + { + public: + SimpleNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength ); + virtual spcIUTF8String APICALL GetValue() const; + virtual void APICALL SetValue( const char * value, sizet valueLength ); + virtual bool APICALL IsURIType() const; + virtual void APICALL SetURIType( bool isURI ); + virtual eNodeType APICALL GetNodeType() const; + + virtual bool APICALL HasContent() const; + virtual void APICALL ClearContents(); + virtual spINode APICALL CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const; + virtual spISimpleNode APICALL ConvertToSimpleNode(); + + protected: + virtual ~SimpleNodeImpl() __NOTHROW__ {} + + virtual void resetChangesForChildren() const; + + spIUTF8String mValue; + bool mIsURIType; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // __SimpleNodeImpl_h__ diff --git a/XMPCore/ImplHeaders/StructureNodeImpl.h b/XMPCore/ImplHeaders/StructureNodeImpl.h new file mode 100644 index 0000000..c7540af --- /dev/null +++ b/XMPCore/ImplHeaders/StructureNodeImpl.h @@ -0,0 +1,87 @@ +#ifndef StructureNodeImpl_h__ +#define StructureNodeImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/IStructureNode_I.h" +#include "XMPCore/ImplHeaders/CompositeNodeImpl.h" +#include "XMPCommon/Utilities/TAllocator.h" + +#include <map> + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + class StructureNodeImpl + : public virtual IStructureNode_I + , public virtual CompositeNodeImpl + { + public: + + struct QualifiedName { + QualifiedName( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) + : mNameSpace( nameSpace ) + , mName( name ) {} + spcIUTF8String mNameSpace; + spcIUTF8String mName; + }; + + struct CompareQualifiedName { + bool operator()( const QualifiedName & key1, const QualifiedName & key2 ) const; + }; + + typedef std::map< QualifiedName, spINode, CompareQualifiedName, TAllocator< spINode > > QualifiedNameNodeMap; + + StructureNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ); + using IStructureNode_I::GetNode; + virtual spINode APICALL GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + virtual spINode APICALL GetNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ); + virtual spINode APICALL RemoveNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + virtual spINode APICALL RemoveNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ); + virtual eNodeType APICALL GetChildNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) const; + virtual eNodeType APICALL GetNodeType() const; + virtual void APICALL InsertNode( const spINode & node ); + virtual spINode APICALL ReplaceNode( const spINode & node ); + virtual void APICALL AppendNode( const spINode & node ); + virtual spINodeIterator APICALL Iterator(); + virtual sizet APICALL ChildCount() const __NOTHROW__; + virtual spIStructureNode APICALL ConvertToStructureNode(); + virtual bool APICALL HasContent() const; + virtual bool ValidateNameOrNameSpaceChangeForAChild( const spcIUTF8String & currentNameSpace, const spcIUTF8String & currentName, const spcIUTF8String & newNameSpace, const spcIUTF8String & newName ); + virtual void APICALL ClearContents(); + virtual spINode APICALL CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const; + + protected: + virtual ~StructureNodeImpl() __NOTHROW__ {} + virtual void resetChangesForChildren() const; + + QualifiedNameNodeMap mChildrenMap; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // StructureNodeImpl_h__ diff --git a/XMPCore/ImplHeaders/TNodeIteratorImpl.h b/XMPCore/ImplHeaders/TNodeIteratorImpl.h new file mode 100644 index 0000000..5e8e37a --- /dev/null +++ b/XMPCore/ImplHeaders/TNodeIteratorImpl.h @@ -0,0 +1,81 @@ +#ifndef TNodeIteratorImpl_h__ +#define TNodeIteratorImpl_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#if !(IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED) + #error "Not adhering to design constraints" + // this file should only be included from its own cpp file +#endif + +#include "XMPCore/Interfaces/INodeIterator_I.h" +#include "XMPCommon/BaseClasses/MemoryManagedObject.h" +#include "XMPCommon/ImplHeaders/SharedObjectImpl.h" + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + +namespace AdobeXMPCore_Int { + + template< typename iterator > + class TNodeIteratorImpl + : public virtual INodeIterator_I + , public virtual SharedObjectImpl + , public virtual MemoryManagedObject + { + public: + TNodeIteratorImpl( const iterator & begin, const iterator & end ) + : mCurrentPos( begin ) + , mEndPos( end ) {} + + spINode GetNodeFromIterator( const iterator & it ) const; + + virtual spINode APICALL GetNode() { + if ( mCurrentPos != mEndPos ) + return GetNodeFromIterator( mCurrentPos ); + else + return spINode(); + } + + virtual INode_v1::eNodeType APICALL GetNodeType() const { + if ( mCurrentPos != mEndPos ) + return GetNodeFromIterator( mCurrentPos )->GetNodeType(); + else + return INode_v1::kNTNone; + } + + virtual spINodeIterator APICALL Next() { + mCurrentPos++; + if ( mCurrentPos != mEndPos ) { + return MakeUncheckedSharedPointer( this, __FILE__, __LINE__, false ); + } + return spINodeIterator(); + } + + protected: + virtual ~TNodeIteratorImpl() __NOTHROW__ {} + + iterator mCurrentPos; + iterator mEndPos; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; +} + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +#endif // TNodeIteratorImpl_h__ diff --git a/XMPCore/Interfaces/IArrayNode_I.h b/XMPCore/Interfaces/IArrayNode_I.h new file mode 100644 index 0000000..a075d04 --- /dev/null +++ b/XMPCore/Interfaces/IArrayNode_I.h @@ -0,0 +1,90 @@ +#ifndef __IArrayNode_I_h__ +#define __IArrayNode_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IArrayNode.h" +#include "XMPCore/Interfaces/ICompositeNode_I.h" + + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents an ArrayNode. + //! \details Provides all the functions to access + //! + class IArrayNode_I + : public virtual IArrayNode + , public virtual ICompositeNode_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIArrayNode APICALL GetActualIArrayNode() __NOTHROW__ { return this; } + virtual pISharedObject_I APICALL GetISharedObject_I() __NOTHROW__{ return this; } + virtual pIArrayNode_I APICALL GetIArrayNode_I() __NOTHROW__ { return this; } + + //! + //! list all functions to be defined in this interface + //! + + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + // Factories to create the array node + + //! + //! Creates an unordered array node which is not part of any metadata document. + //! \param[in] nameSpace shared pointer to a constant IUTF8String object containing name space URI of the simple node. + //! \param[in] name shared pointer to a constant IUTF8String object containing local name of the simple node. + //! \param[in] arrayNodeForm a value of type #eArrayForm indicating the type of array node. + //! \return a shared pointer to a #IArrayNode object. + //! \attention Error is thrown in the following cases: + //! -# nameSpace is NULL or its contents are empty. + //! -# name is NULL or its contents are empty. + //! + XMP_PRIVATE static spIArrayNode CreateArrayNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name, eArrayForm arrayForm ); + + protected: + virtual ~IArrayNode_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual uint32 APICALL getArrayForm( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL getChildNodeType( pcIError_base & error ) const __NOTHROW__; + virtual pINode_base APICALL getNodeAtIndex( sizet index, pcIError_base & error ) __NOTHROW__; + virtual void APICALL insertNodeAtIndex( pINode_base node, sizet index, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL removeNodeAtIndex( sizet index, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL replaceNodeAtIndex( pINode_base node, sizet index, pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // __IArrayNode_I_h__ diff --git a/XMPCore/Interfaces/ICompositeNode_I.h b/XMPCore/Interfaces/ICompositeNode_I.h new file mode 100644 index 0000000..86b7558 --- /dev/null +++ b/XMPCore/Interfaces/ICompositeNode_I.h @@ -0,0 +1,73 @@ +#ifndef ICompositeNode_I_h__ +#define ICompositeNode_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/ICompositeNode.h" +#include "XMPCore/Interfaces/INode_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Version1 of the interface that serves as a base interface to all composite types of nodes in the XMP DOM ( like Arrays and Structures ). + //! \details Provides all the functions to get various properties of the composite node. + //! \attention Support multi threading through locks but can be enabled/disabled by the client. By default + //! every object created does not support multi-threading. + //! + class ICompositeNode_I + : public virtual ICompositeNode + , public virtual INode_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pICompositeNode APICALL GetActualICompositeNode() __NOTHROW__ { return this; } + virtual pICompositeNode_I APICALL GetICompositeNode_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + protected: + virtual ~ICompositeNode_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual uint32 APICALL getNodeTypeAtPath( pcIPath_base path, pcIError_base & error ) const __NOTHROW__; + virtual pINode_base APICALL getNodeAtPath( pcIPath_base path, pcIError_base & error ) __NOTHROW__; + virtual void APICALL appendNode( pINode_base node, pcIError_base & error ) __NOTHROW__; + virtual void APICALL insertNodeAtPath( pINode_base node, pcIPath_base path, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL replaceNodeAtPath( pINode_base node, pcIPath_base path, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL removeNodeAtPath( pcIPath_base path, pcIError_base & error ) __NOTHROW__; + virtual pINodeIterator_base APICALL iterator( pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // ICompositeNode_I_h__ diff --git a/XMPCore/Interfaces/ICoreConfigurationManager_I.h b/XMPCore/Interfaces/ICoreConfigurationManager_I.h new file mode 100644 index 0000000..77ab69a --- /dev/null +++ b/XMPCore/Interfaces/ICoreConfigurationManager_I.h @@ -0,0 +1,75 @@ +#ifndef ICoreConfigurationManager_I_h__ +#define ICoreConfigurationManager_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/ICoreConfigurationManager.h" +#include "XMPCommon/Interfaces/IConfigurationManager_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents interface that represents configuration settings controllable by the client. + //! \details Provides functions through which client can plug in its own memory allocators, error notifiers. + //! \attention Not Thread Safe as this functionality is generally used at the initialization phase. + //! + class ICoreConfigurationManager_I + : public virtual ICoreConfigurationManager + , public virtual IConfigurationManager_I + { + public: + + //! + //! Create the configuration manager for the XMPCore library. + //! + static void CreateCoreConfigurationManager(); + + //! + //! Destroy the configuration manager of the XMPCore library. + //! + static void DestroyCoreConfigurationManager(); + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pICoreConfigurationManager APICALL GetActualICoreConfigurationManager() __NOTHROW__ { return this; } + virtual pISharedObject_I APICALL GetISharedObject_I() __NOTHROW__{ return this; } + virtual pICoreConfigurationManager_I APICALL GetICoreConfigurationManager_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + protected: + virtual ~ICoreConfigurationManager_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} +#endif // ICoreConfigurationManager_I_h__ + diff --git a/XMPCore/Interfaces/ICoreObjectFactory_I.h b/XMPCore/Interfaces/ICoreObjectFactory_I.h new file mode 100644 index 0000000..e698756 --- /dev/null +++ b/XMPCore/Interfaces/ICoreObjectFactory_I.h @@ -0,0 +1,65 @@ +#ifndef ICoreObjectFactory_I_h__ +#define ICoreObjectFactory_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/ICoreObjectFactory.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents a factory to create various artifacts of XMP DOM like array, + //! structure, path etc. + //! + //! Provides all the functions to create instances of various artifacts of XMP DOM and return them as shared pointers + //! to the clients. This is the interface through which clients of the library actually get access to all other interfaces. + //! + //! + class ICoreObjectFactory_I + : public virtual ICoreObjectFactory + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pICoreObjectFactory APICALL GetActualICoreObjectFactory() __NOTHROW__ { return this; } + virtual pICoreObjectFactory_I APICALL GetICoreObjectFactory_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + protected: + virtual ~ICoreObjectFactory_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // ICoreObjectFactory_I_h__ diff --git a/XMPCore/Interfaces/IDOMImplementationRegistry_I.h b/XMPCore/Interfaces/IDOMImplementationRegistry_I.h new file mode 100644 index 0000000..67f2032 --- /dev/null +++ b/XMPCore/Interfaces/IDOMImplementationRegistry_I.h @@ -0,0 +1,108 @@ +#ifndef IDOMImplementationRegistry_I_h__ +#define IDOMImplementationRegistry_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/IDOMImplementationRegistry.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that serves as a database/registry of all the parsers and + //! serializers available with the XMPCore library. + //! \details Provides all the functions to + //! -# get registered serializers and parsers from the database. + //! -# add client defined serializers and parsers to the database. + //! \attention Support multi threading if library is configured to support multi-threading by default. + //! \note By default following keys are registered by default with the database by the library: + //! -# rdf + //! + class IDOMImplementationRegistry_I + : public virtual IDOMImplementationRegistry + , public virtual ISharedObject_I + { + public: + + //! + //! Registers a parser with the database along with the key. + //! \param[in] key pointer to a const NULL terminated char buffer containing key of the parser to be used while registering. + //! \param[in] parser a shared pointer to #ICDOMParser object to be registered with the database + //! \return true in case parser is successfully registered, false otherwise like in case key is already registered. + //! \attention currently it is unimplemented. + //! + virtual bool APICALL RegisterParser( const char * key, const spcIDOMParser & parser ) = 0; + virtual bool APICALL RegisterParser( const char * key, pIClientDOMParser_base parser ); + + //! + //! Registers a serializer with the database along with the key. + //! \param[in] key pointer to a const NULL terminated char buffer containing key of the serializer to be used while registering. + //! \param[in] parser a shared pointer to #IDOMSerializer object to be registered with the database. + //! \return true in case serializer is successfully registered, false otherwise like in case key is already registered. + //! \attention currently it is unimplemented. + //! + virtual bool APICALL RegisterSerializer( const char * key, const spcIDOMSerializer & serializer ) = 0; + virtual bool APICALL RegisterSerializer( const char * key, pIClientDOMSerializer_base serializer ); + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIDOMImplementationRegistry APICALL GetActualIDOMImplementationRegistry() __NOTHROW__ { return this; } + virtual pISharedObject_I APICALL GetISharedObject_I() __NOTHROW__{ return this; } + virtual pIDOMImplementationRegistry_I APICALL GetIDOMImplementationRegistry_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + // static factory functions + + //! + //! Creates an IDOMImplementationRegistry object. + //! \return a shared pointer to an IDOMImplementationRegistry object + //! + XMP_PRIVATE static spIDOMImplementationRegistry CreateDOMImplementationRegistry(); + + //! + //! Destory the IDOMImplementationRegistry object. + //! + XMP_PRIVATE static void DestoryDOMImplementationRegistry(); + + protected: + virtual ~IDOMImplementationRegistry_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pIDOMParser_base APICALL getParser( const char * key, pcIError_base & error ) const __NOTHROW__; + virtual pIDOMSerializer_base APICALL getSerializer( const char * key, pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL registerParser( const char * key, pIClientDOMParser_base parser, pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL registerSerializer( const char * key, pIClientDOMSerializer_base serializer, pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // IDOMImplementationRegistry_I_h__ diff --git a/XMPCore/Interfaces/IDOMParser_I.h b/XMPCore/Interfaces/IDOMParser_I.h new file mode 100644 index 0000000..8d680bb --- /dev/null +++ b/XMPCore/Interfaces/IDOMParser_I.h @@ -0,0 +1,92 @@ +#ifndef IDOMParser_I_h__ +#define IDOMParser_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/IDOMParser.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" +#include "XMPCommon/Interfaces/BaseInterfaces/IConfigurable_I.h" +#include "XMPCore/source/XMPMeta.hpp" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that supports parsing of the XMP Data Model. + //! Provides all functions to parse the buffer as well as to configure the parser. + //! + class IDOMParser_I + : public virtual IDOMParser + , public virtual IConfigurable_I + , public virtual ISharedObject_I + { + public: + + //! + //! Parse the buffer contents and creates an XMP DOM node. + //! \param[in] buffer pointer to a constant char buffer containing serialized XMP Data Model. + //! \param[in] bufferLength number of characters in buffer. In case name is null terminated set it to #AdobeXMPCommon::npos. + //! \return a shared pointer to an object of #INode containing all the information parsed from the buffer. + //! + virtual spINode APICALL ParseAsNode( const char * buffer, sizet bufferLength ) = 0; + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIDOMParser APICALL GetActualIDOMParser() __NOTHROW__ { return this; } + virtual pISharedObject_I APICALL GetISharedObject_I() __NOTHROW__{ return this; } + virtual pIDOMParser_I APICALL GetIDOMParser_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + // Factory functions + + //! + //! Creates a DOM Parser from the client DOM Parser. + //! \param[in] clientDOMParser a pointer to an object of type #IClientDOMParser_v1. + //! \return a shared pointer to an object of type #IDOMParser. + //! + static spIDOMParser CreateDOMParser( pIClientDOMParser_base clientDOMParser ); + + + virtual void SetErrorCallback(XMPMeta::ErrorCallbackInfo * ec) = 0; + + protected: + virtual ~IDOMParser_I() __NOTHROW__ {} + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pIDOMParser_base APICALL clone( pcIError_base & error ) const __NOTHROW__; + virtual pIMetadata_base APICALL parse( const char * buffer, sizet bufferLength, pcIError_base & error ) __NOTHROW__; + virtual void APICALL parseWithSpecificAction( const char * buffer, sizet bufferLength, uint32 actionType, pINode_base node, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + + +#endif // IDOMParser_I_h__ diff --git a/XMPCore/Interfaces/IDOMSerializer_I.h b/XMPCore/Interfaces/IDOMSerializer_I.h new file mode 100644 index 0000000..b232dfe --- /dev/null +++ b/XMPCore/Interfaces/IDOMSerializer_I.h @@ -0,0 +1,82 @@ +#ifndef IDOMSerializer_I_h__ +#define IDOMSerializer_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/IDOMSerializer.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" +#include "XMPCommon/Interfaces/BaseInterfaces/IConfigurable_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal that represents an object that can serialize an XMP Data Model to a buffer. + //! Provides the functions to serialize the XMP Data Model. + //! + + class IDOMSerializer_I + : public virtual IDOMSerializer + , public virtual IConfigurable_I + , public virtual ISharedObject_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIDOMSerializer APICALL GetActualIDOMSerializer() __NOTHROW__ { return this; } + virtual pISharedObject_I APICALL GetISharedObject_I() __NOTHROW__{ return this; } + virtual pIDOMSerializer_I APICALL GetIDOMSerializer_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + virtual spIUTF8String APICALL SerializeInternal(const spINode & node, XMP_OptionBits options, sizet padding, const char * newline, const char * indent, sizet baseIndent, const spcINameSpacePrefixMap & nameSpacePrefixMap = spcINameSpacePrefixMap()) const = 0; + + + // Factory functions + + //! + //! Creates a DOM Serializer from the client DOM Serializer. + //! \param[in] clientDOMSerializer a pointer to an object of type #IClientDOMSerializer_v1. + //! \return a shared pointer to an object of type #IDOMSerializer. + //! + static spIDOMSerializer CreateDOMSerializer( pIClientDOMSerializer_base clientDOMSerializer ); + + protected: + virtual ~IDOMSerializer_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pIDOMSerializer_base APICALL clone( pcIError_base & error ) const __NOTHROW__; + virtual pIUTF8String_base APICALL serialize( pINode_base node, pcINameSpacePrefixMap_base map, pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // IDOMSerializer_I_h__ diff --git a/XMPCore/Interfaces/IMetadata_I.h b/XMPCore/Interfaces/IMetadata_I.h new file mode 100644 index 0000000..16cb5f3 --- /dev/null +++ b/XMPCore/Interfaces/IMetadata_I.h @@ -0,0 +1,68 @@ +#ifndef __IMetadata_I_h__ +#define __IMetadata_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IMetadata.h" +#include "XMPCore/Interfaces/IStructureNode_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents the whole XMP metadata for an asset. + //! Provides all the functions to add or remove nodes to and from metadata. + //! \attention Support multi threading through locks but can be enabled/disabled by the client. By default + //! every object created does not support multi-threading. + //! + class IMetadata_I + : public virtual IMetadata + , public virtual IStructureNode_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIMetadata APICALL GetActualIMetadata() __NOTHROW__ { return this; } + virtual pISharedObject_I APICALL GetISharedObject_I() __NOTHROW__{ return this; } + virtual pIMetadata_I APICALL GetIMetadata_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + protected: + virtual ~IMetadata_I() __NOTHROW__ {} + + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pcIUTF8String_base APICALL getAboutURI( pcIError_base & error ) const __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // __IMetadata_I_h__ diff --git a/XMPCore/Interfaces/INameSpacePrefixMap_I.h b/XMPCore/Interfaces/INameSpacePrefixMap_I.h new file mode 100644 index 0000000..c6c5218 --- /dev/null +++ b/XMPCore/Interfaces/INameSpacePrefixMap_I.h @@ -0,0 +1,106 @@ +#ifndef INameSpacePrefixMap_I_h__ +#define INameSpacePrefixMap_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" +#include "XMPCommon/Interfaces/BaseInterfaces/IThreadSafe_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal Interface that represents map where each entry consists of prefix string + //! as the key and corresponding nameSpace string as its value. + //! \details Provides all the functions to get/set the entries inside the map + //! \attention Supports Multi-threading at object level through locks. + //! + + class INameSpacePrefixMap_I + : public virtual INameSpacePrefixMap + , public virtual ISharedObject_I + , public virtual IThreadSafe_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + using INameSpacePrefixMap_v1::GetNameSpace; + using INameSpacePrefixMap_v1::GetPrefix; + + virtual spcIUTF8String APICALL GetNameSpace( const spcIUTF8String & prefix ) const = 0; + virtual spcIUTF8String APICALL GetPrefix( const spcIUTF8String & nameSpace ) const = 0; + virtual void APICALL Merge( const spcINameSpacePrefixMap & otherMap ) = 0; + + virtual pINameSpacePrefixMap APICALL GetActualINameSpacePrefixMap() __NOTHROW__ { return this; } + virtual pINameSpacePrefixMap_I APICALL GetINameSpacePrefixMap_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + // static factory functions + + //! + //! Creates the DefaultNameSpacePrefixMap + //! + static void CreateDefaultNameSpacePrefixMap(); + + //! + //! Destroys the DefaultNameSpacePrefixMap + //! + static void DestroyDefaultNameSapcePrefixMap(); + + //! + //! Adds an entry in the default mapping used by XMP Core + //! \param[in] prefix pointer to a constant char buffer containing prefix string. + //! \param[in] prefixLength number of characters in prefix. In case prefix is null set it to AdobeXMPCommon::npos. + //! \param[in] nameSpace pointer to a constant char buffer containing nameSpace string. + //! \param[in] nameSpaceLength number of characters in nameSpace. In case nameSpace is null set it to AdobeXMPCommon::npos. + //! \return a bool type object containing true in case operation was successful, false otherwise. + //! \note raises warning in case of + //! - prefix or nameSpace are null pointers + //! - prefixLength or nameSpaceLength is 0. + //! + static bool InsertInDefaultNameSpacePrefixMap( const char * prefix, sizet prefixLength, const char * nameSpace, sizet nameSpaceLength ); + + protected: + virtual ~INameSpacePrefixMap_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual uint32 APICALL insert( const char * prefix, sizet prefixLength, const char * nameSpace, sizet nameSpaceLength, pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL remove( uint32 keyType, const char * key, sizet keyLength, pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL isPresent( uint32 keyType, const char * key, sizet keyLength, pcIError_base & error ) const __NOTHROW__; + virtual pcIUTF8String_base APICALL get( uint32 keyType, const char * key, sizet keyLength, pcIError_base & error ) const __NOTHROW__; + virtual pINameSpacePrefixMap_base APICALL clone( pcIError_base & error ) const __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // INameSpacePrefixMap_I_h__ diff --git a/XMPCore/Interfaces/INodeIterator_I.h b/XMPCore/Interfaces/INodeIterator_I.h new file mode 100644 index 0000000..3d8bc0b --- /dev/null +++ b/XMPCore/Interfaces/INodeIterator_I.h @@ -0,0 +1,61 @@ +#ifndef __INodeIterator_I_h__ +#define __INodeIterator_I_h__ 1 + + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/INodeIterator.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents an iterator over the mutable children of a XMP DOM Node. + //! \attention Support multi threading through locks but can be disabled by the client. + //! \note Iterators are valid as long as their are no changes performed on the node. In case there are some + //! changes performed on the node then the behavior is undefined. + //! + class INodeIterator_I + : public virtual INodeIterator + , public virtual ISharedObject_I + { + public: + virtual pINodeIterator APICALL GetActualINodeIterator() __NOTHROW__ { return this; } + virtual pINodeIterator_I APICALL GetINodeIterator_I() __NOTHROW__ { return this; } + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + virtual pvoid APICALL GetInterfacePointer(uint64 interfaceID, uint32 interfaceVersion); + protected: + virtual ~INodeIterator_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal(uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel); + virtual pINode_base APICALL getNode( pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL getNodeType( pcIError_base & error ) const __NOTHROW__; + virtual pINodeIterator_base APICALL next( pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer(uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error) __NOTHROW__; + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // __INodeIterator_I_h__ diff --git a/XMPCore/Interfaces/INode_I.h b/XMPCore/Interfaces/INode_I.h new file mode 100644 index 0000000..84d4e9f --- /dev/null +++ b/XMPCore/Interfaces/INode_I.h @@ -0,0 +1,223 @@ +#ifndef __INode_I_h__ +#define __INode_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/INode.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" +#include "XMPCommon/Interfaces/BaseInterfaces/IThreadSafe_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! Internal interface that serves as a base interface to all types of nodes in the XMP DOM. + //! Provides all the functions to get various properties of the node. + //! + class INode_I + : public virtual INode + , public virtual ISharedObject_I + , public virtual IThreadSafe_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + //! + //! Change the parent of the node. + //! \param[in] parent a pointer of #INode representing the new parent of the node. + //! \note If the parent is invalid shared pointer it will be treated like removing the node from the + //! tree. + //! + virtual void APICALL ChangeParent( pINode parent ) = 0; + + //! + //! @{ + //! Get the qualifier of the node having specified namespace and name. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the qualifier node. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the qualifier node. + //! \return a shared pointer to either a const or const qualifier node. + //! \note In case no qualifier exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! + using INode_v1::GetQualifier; + XMP_PRIVATE spcINode GetQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + return const_cast< INode_I * >( this )->GetQualifier( nameSpace, name ); + } + virtual spINode APICALL GetQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) = 0; + //! + //! @} + + //! + //! @{ + //! Get the node's qualifier having specified name space and name as simple node. + //! \param[in] nameSpace pointer to a const IUTF8String object containing name space URI of the qualifier node. + //! \param[in] name pointer to a const IUTF8String object containing local name of the qualifier node. + //! \return a shared pointer to const or non const #ISimpleNode object containing qualifier. + //! \note In case no qualifier exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! \attention Error is thrown in case + //! - a qualifier exists with the specified nameSpace and name combination but is not a simple node. + //! + using INode_v1::GetSimpleQualifier; + XMP_PRIVATE spcISimpleNode GetSimpleQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + auto node = GetQualifier( nameSpace, name ); + if ( node ) return node->ConvertToSimpleNode(); + return spcISimpleNode(); + } + + XMP_PRIVATE spISimpleNode GetSimpleQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + auto node = GetQualifier( nameSpace, name ); + if ( node ) return node->ConvertToSimpleNode(); + return spISimpleNode(); + } + //! @} + + //! + //! @{ + //! Get the node's qualifier having specified name space and name as structure node. + //! \param[in] nameSpace pointer to a const IUTF8String object containing name space URI of the qualifier node. + //! \param[in] name pointer to a const IUTF8String object containing local name of the qualifier node. + //! \return a shared pointer to const or non const #IStructureNode object containing qualifier. + //! \note In case no qualifier exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! \attention Error is thrown in case + //! - a qualifier exists with the specified nameSpace and name combination but is not a structure node. + //! + using INode_v1::GetStructureQualifier; + XMP_PRIVATE spcIStructureNode GetStructureQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + auto node = GetQualifier( nameSpace, name ); + if ( node ) return node->ConvertToStructureNode(); + return spcIStructureNode(); + } + + XMP_PRIVATE spIStructureNode GetStructureQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + auto node = GetQualifier( nameSpace, name ); + if ( node ) return node->ConvertToStructureNode(); + return spIStructureNode(); + } + //! @} + + //! + //! @{ + //! Get the node's qualifier having specified name space and name as an array node. + //! \param[in] nameSpace pointer to a const IUTF8String object containing name space URI of the qualifier node. + //! \param[in] name pointer to a const IUTF8String object containing local name of the qualifier node. + //! \return a shared pointer to const or non const #ISimpleNode object containing qualifier. + //! \note In case no qualifier exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! \attention Error is thrown in case + //! - a qualifier exists with the specified nameSpace and name combination but is not an array node. + //! + using INode_v1::GetArrayQualifier; + XMP_PRIVATE spcIArrayNode GetArrayQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + auto node = GetQualifier( nameSpace, name ); + if ( node ) return node->ConvertToArrayNode(); + return spcIArrayNode(); + } + + XMP_PRIVATE spIArrayNode GetArrayQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + auto node = GetQualifier( nameSpace, name ); + if ( node ) return node->ConvertToArrayNode(); + return spIArrayNode(); + } + //! @} + + //! + //! Remove the qualifier node with the specified nameSpace and name. + //! \param[in] nameSpace pointer to a const IUTF8String object containing name space URI of the qualifier node. + //! \param[in] name pointer to a const IUTF8String object containing local name of the qualifier node. + //! \return a shared pointer to #AdobeXMPCore::INode object representing qualifier node which is removed from the node. + //! \note In case no qualifier node exists at the given index an invalid shared pointer is returned. + //! + using INode_v1::RemoveQualifier; + virtual spINode APICALL RemoveQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) = 0; + + //! + //! @{ + //! Get the raw pointer to the parent of the node. + //! \return a const or non const pointer to the parent of the node. + //! + pcINode GetRawParentPointer() const { + return const_cast< INode_I * >( this )->GetRawParentPointer(); + } + virtual pINode APICALL GetRawParentPointer() = 0; + //! @} + + + virtual pINode APICALL GetActualINode() __NOTHROW__ { return this; } + virtual pINode_I APICALL GetINode_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + virtual void SetIndex( sizet currentIndex ) = 0; + virtual void SetIsQualifierNode( bool isQualifierNode ) = 0; + virtual void RegisterChange() = 0; + virtual bool ValidateNameOrNameSpaceChangeForAChild( const spcIUTF8String & currentNameSpace, const spcIUTF8String & currentName, + const spcIUTF8String & newNameSpace, const spcIUTF8String & newName ) = 0; + virtual void UnRegisterChange() = 0; + virtual void SetQualifiers( const spIStructureNode & node ) = 0; + + protected: + virtual ~INode_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pINode_base APICALL getParent( pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL getParentNodeType( pcIError_base & error ) const __NOTHROW__; + virtual void APICALL setName( const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual pcIUTF8String_base APICALL getName( pcIError_base & error ) const __NOTHROW__; + virtual void APICALL setNameSpace( const char * nameSpace, sizet nameSpaceLength, pcIError_base & error ) __NOTHROW__; + virtual pcIUTF8String_base APICALL getNameSpace( pcIError_base & error ) const __NOTHROW__; + virtual pIPath_base APICALL getPath( pcIError_base & error ) const __NOTHROW__; + virtual pINodeIterator_base APICALL qualifiersIterator( pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL getQualifierNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) const __NOTHROW__; + virtual pINode_base APICALL getQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual void APICALL insertQualifier( pINode_base base, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL replaceQualifier( pINode_base node, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL removeQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL getNodeType( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL isArrayItem( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL isQualifierNode( pcIError_base & error ) const __NOTHROW__; + virtual sizet APICALL getIndex( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL hasQualifiers( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL hasContent( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL isEmpty( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL hasChanged( pcIError_base & error ) const __NOTHROW__; + virtual void APICALL clear( uint32 contents, uint32 qualifiers, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL clone( uint32 igoreEmptyNodes, uint32 ignoreNodesWithOnlyQualifiers, pcIError_base & error ) const __NOTHROW__; + virtual pISimpleNode_base APICALL convertToSimpleNode( pcIError_base & error ) __NOTHROW__; + virtual pIStructureNode_base APICALL convertToStructureNode( pcIError_base & error ) __NOTHROW__; + virtual pIArrayNode_base APICALL convertToArrayNode( pcIError_base & error ) __NOTHROW__; + virtual pIMetadata_base APICALL convertToMetadata( pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // __INode_I_h__ diff --git a/XMPCore/Interfaces/IPathSegment_I.h b/XMPCore/Interfaces/IPathSegment_I.h new file mode 100644 index 0000000..5afd68b --- /dev/null +++ b/XMPCore/Interfaces/IPathSegment_I.h @@ -0,0 +1,125 @@ +#ifndef __IPathSegment_I_h__ +#define __IPathSegment_I_h__ 1 + +// ================================================================================================= +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/IPathSegment.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents an PathSegment. + //! \details Provides all the functions to access + //! + class IPathSegment_I + : public virtual IPathSegment + , public virtual ISharedObject_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + using IPathSegment_v1::GetNameSpace; + using IPathSegment_v1::GetName; + using IPathSegment_v1::GetType; + using IPathSegment_v1::GetValue; + + virtual spcIPathSegment APICALL Clone() const = 0; + virtual pIPathSegment APICALL GetActualIPathSegment() __NOTHROW__ { return this; } + virtual pIPathSegment_I APICALL GetIPathSegment_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + // static factory functions + + // Factories to create the specific segments + + //! + //! Creates a normal property path segment.These are essentially all properties (simple, struct and arrays). + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the property. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the property. + //! \return a shared pointer to const #IPathSegment. + //! \attention throws #AdobeXMPCommon::pcIError in case + //! - shared pointers are invalid, + //! - their content is empty. + //! + XMP_PRIVATE static spcIPathSegment CreatePropertyPathSegment( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + + //! + //! Creates an array index path segment that denotes a specific element of an array. + //! Such segments do not have an own name and inherits the namespace from the Array property itself. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the property. + //! \param[in] index an object of type #AdobeXMP::sizet containting the index of the array element. + //! \return a shared pointer to const #IPathSegment. + //! \attention throws #AdobeXMP::pcIError in case + //! - pointers to const char buffers are NULL, + //! - their content is empty. + //! + //! + XMP_PRIVATE static spcIPathSegment CreateArrayIndexPathSegment( const spcIUTF8String & nameSpace, sizet index ); + + //! + //! Creates a Qualifier path segment, which behaves like a normal property + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the property. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the property. + //! \return a shared pointer to const #IPathSegment. + //! \attention throws #AdobeXMPCommon::pcIError in case + //! - shared pointers are invalid, + //! - their content is empty. + //! + XMP_PRIVATE static spcIPathSegment CreateQualifierPathSegment( const spcIUTF8String & nameSpace, const spcIUTF8String & name ); + + //! + //! Creates a path segment that selects a specific qualifier by its value. + //! For example a specific language in a alternative array of languages. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the property. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the property. + //! \param[in] value shared pointer to a const IUTF8String object containing value of the language (xml:lang) + //! \return a shared pointer to const #IPathSegment. + //! \attention throws #AdobeXMPCommon::pcIError in case + //! - shared pointers are invalid, + //! - their content is empty. + //! + XMP_PRIVATE static spcIPathSegment CreateQualifierSelectorPathSegment( const spcIUTF8String & nameSpace, const spcIUTF8String & name, const spcIUTF8String & value ); + + + protected: + virtual ~IPathSegment_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pcIUTF8String_base APICALL getNameSpace( pcIError_base & error ) const __NOTHROW__; + virtual pcIUTF8String_base APICALL getName( pcIError_base & error ) const __NOTHROW__; + virtual uint32 APICALL getType( pcIError_base & error ) const __NOTHROW__; + virtual pcIUTF8String_base APICALL getValue( pcIError_base & error ) const __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} +#endif // __IPathSegment_I_h__ diff --git a/XMPCore/Interfaces/IPath_I.h b/XMPCore/Interfaces/IPath_I.h new file mode 100644 index 0000000..7c0ca8f --- /dev/null +++ b/XMPCore/Interfaces/IPath_I.h @@ -0,0 +1,72 @@ +#ifndef __IPath_I_h__ +#define __IPath_I_h__ 1 + +// ================================================================================================= +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/IPath.h" +#include "XMPCommon/Interfaces/BaseInterfaces/ISharedObject_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! Internal interface that provides an easy iterative description of a specific path into the XMP tree. + //! \details Path consists of multiple path segments in an order and each #AdobeXMPCore::IPathSegment represents one segment + //! of the path into the XMP tree. Provides all the functions to create path and get the various properties of a path. + //! \attention Do not support multi-threading. + //! \note Index in the path are 1-based. + //! + class IPath_I + : public virtual IPath + , public virtual ISharedObject_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIPath APICALL GetActualIPath() __NOTHROW__ { return this; } + virtual pIPath_I APICALL GetIPath_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + protected: + virtual ~IPath_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pcINameSpacePrefixMap_base APICALL registerNameSpacePrefixMap( pcINameSpacePrefixMap_base map, pcIError_base & error ) __NOTHROW__; + virtual pIUTF8String_base APICALL serialize( pcINameSpacePrefixMap_base map, pcIError_base & error ) const __NOTHROW__; + virtual void APICALL appendPathSegment( pcIPathSegment_base segment, pcIError_base & error ) __NOTHROW__; + virtual pcIPathSegment_base APICALL removePathSegment( sizet index, pcIError_base & error ) __NOTHROW__; + virtual pcIPathSegment_base APICALL getPathSegment( sizet index, pcIError_base & error ) const __NOTHROW__; + virtual pIPath_base APICALL clone( sizet startingIndex, sizet countOfSegemetns, pcIError_base & error ) const __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // __IPath_I_h__ diff --git a/XMPCore/Interfaces/ISimpleNode_I.h b/XMPCore/Interfaces/ISimpleNode_I.h new file mode 100644 index 0000000..6f6da83 --- /dev/null +++ b/XMPCore/Interfaces/ISimpleNode_I.h @@ -0,0 +1,83 @@ +#ifndef __ISimpleNode_I_h__ +#define __ISimpleNode_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/ISimpleNode.h" +#include "XMPCore/Interfaces/INode_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents a Simple Property Node of XMP DOM. + //! \details Provides all the functions to get and set various properties of the simple node. + //! \attention Support multi threading through locks but can be enabled/disabled by the client. By default + //! every object created does not support multi-threading. + //! + class ISimpleNode_I + : public virtual ISimpleNode + , public virtual INode_I + { + public: + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pISimpleNode APICALL GetActualISimpleNode() __NOTHROW__ { return this; } + virtual pISimpleNode_I APICALL GetISimpleNode_I() __NOTHROW__ { return this; } + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + //! + //! Creates a simple property node which is not part of any metadata document. + //! \param[in] nameSpace shared pointer to a constant IUTF8String object containing name space URI of the simple node. + //! \param[in] name shared pointer to a constant IUTF8String object containing local name of the simple node. + //! \param[in] value shared pointer to a constant IUTF8String object containing value of the simple node. + //! \return a shared pointer to a #AdobeXMPCore::ISimpleNode object. + //! \attention Error is thrown in case + //! - nameSpace or name are invalid pointers, or + //! - their contents are empty. + //! \note In case the value is an invalid pointer or its contents are empty than the value is set to empty string. + //! + XMP_PRIVATE static spISimpleNode CreateSimpleNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name, const spcIUTF8String & value = spcIUTF8String() ); + + protected: + virtual ~ISimpleNode_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pcIUTF8String_base APICALL getValue( pcIError_base & error ) const __NOTHROW__; + virtual void APICALL setValue( const char * value, sizet valueLength, pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL isURIType( pcIError_base & error ) const __NOTHROW__; + virtual void APICALL setURIType( uint32 isURI, pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // __ISimpleNode_I_h__ diff --git a/XMPCore/Interfaces/IStructureNode_I.h b/XMPCore/Interfaces/IStructureNode_I.h new file mode 100644 index 0000000..209438a --- /dev/null +++ b/XMPCore/Interfaces/IStructureNode_I.h @@ -0,0 +1,189 @@ +#ifndef IStructureNode_I_h__ +#define IStructureNode_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IStructureNode.h" +#include "XMPCore/Interfaces/ICompositeNode_I.h" + +namespace AdobeXMPCore_Int { + +#if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) +#endif + + //! + //! \brief Internal interface that represents a structure Node of XMP DOM. + //! \details Provides all the functions to get and set various properties of the structure node. + //! \attention Support multi threading through locks but can be enabled/disabled by the client. By default + //! every object created does not support multi-threading. + //! + class IStructureNode_I + : public virtual IStructureNode + , public virtual ICompositeNode_I + { + public: + + //! + //! @{ + //! Get the child of the node having specified namespace and name. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the child node. + //! \param[in] name shared pointer to a const IUTF8String object local name of the child node. + //! \return a shared pointer to either a const or const child node. + //! \note In case no child exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! + using IStructureNode_v1::GetNode; + XMP_PRIVATE spcINode GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + return const_cast< IStructureNode_I * >( this )->GetNode( nameSpace, name ); + } + virtual spINode APICALL GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) = 0; + //! @} + + //! + //! @{ + //! Get the node's child having specified name space and name as simple node. + //! \param[in] nameSpace shared pointer to a const IUTF8String object name space URI of the child node. + //! \param[in] name shared pointer to a const IUTF8String object local name of the child node. + //! \return a shared pointer to const or non const #ISimpleNode object containing child. + //! \note In case no child exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! \attention Error is thrown in case + //! - a child exists with the specified nameSpace and name combination but is not a simple node. + //! + using IStructureNode_v1::GetSimpleNode; + XMP_PRIVATE spcISimpleNode GetSimpleNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + auto node = GetNode( nameSpace, name ); + if ( node ) return node->ConvertToSimpleNode(); + return spcISimpleNode(); + } + + XMP_PRIVATE spISimpleNode GetSimpleNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + auto node = GetNode( nameSpace, name ); + if ( node ) return node->ConvertToSimpleNode(); + return spISimpleNode(); + } + //! @} + + //! + //! @{ + //! Get the node's child having specified name space and name as structure node. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the child node. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the child node. + //! \return a shared pointer to const or non const #IStructureNode object containing child. + //! \note In case no child exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! \attention Error is thrown in case + //! - a child exists with the specified nameSpace and name combination but is not a structure node. + //! + using IStructureNode_v1::GetStructureNode; + XMP_PRIVATE spcIStructureNode GetStructureNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + auto node = GetNode( nameSpace, name ); + if ( node ) return node->ConvertToStructureNode(); + return spcIStructureNode(); + } + + XMP_PRIVATE spIStructureNode GetStructureNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + auto node = GetNode( nameSpace, name ); + if ( node ) return node->ConvertToStructureNode(); + return spIStructureNode(); + } + //! @} + + //! + //! @{ + //! Get the node's child having specified name space and name as an array node. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the child node. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the child node. + //! \return a shared pointer to const or non const #ISimpleNode object containing child. + //! \note In case no child exists with the specified nameSpace and name combination then an invalid shared pointer + //! is returned. + //! \attention Error is thrown in case + //! - a child exists with the specified nameSpace and name combination but is not an array node. + //! + using IStructureNode_v1::GetArrayNode; + XMP_PRIVATE spcIArrayNode GetArrayNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) const { + auto node = GetNode( nameSpace, name ); + if ( node ) return node->ConvertToArrayNode(); + return spcIArrayNode(); + } + + XMP_PRIVATE spIArrayNode GetArrayNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + auto node = GetNode( nameSpace, name ); + if ( node ) return node->ConvertToArrayNode(); + return spIArrayNode(); + } + //! @} + + //! + //! Remove the node with the specified nameSpace and name. + //! \param[in] nameSpace shared pointer to a const IUTF8String object containing name space URI of the child node. + //! \param[in] name shared pointer to a const IUTF8String object containing local name of the child node. + //! \return a shared pointer to #AdobeXMPCore::INode object containing node which is removed from the tree. + //! \note In case no node exists with the given nameSpace and name combination an invalid shared pointer is returned. + //! + using IStructureNode_v1::RemoveNode; + virtual spINode APICALL RemoveNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) = 0; + + //! + //! return the version of the interface. + //! \return 32 bit unsigned integer representing the version of the interface. + //! + static uint32 GetInterfaceVersion() { return kInternalInterfaceVersionNumber; } + + virtual pIStructureNode APICALL GetActualIStructureNode() __NOTHROW__ { return this; } + virtual pIStructureNode_I APICALL GetIStructureNode_I() __NOTHROW__ { return this; } + + //! + //! list all functions to be defined in this interface + //! + + + virtual pvoid APICALL GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ); + + // static factory functions + + //! + //! Creates a simple property node which is not part of any metadata document. + //! \param[in] nameSpace shared pointer to a constant IUTF8String object containing name space URI of the simple node. + //! \param[in] name shared pointer to a constant IUTF8String object containing local name of the simple node. + //! \return a shared pointer to a #IStructureNode object. + //! \attention Error is thrown in case + //! - nameSpace or name are invalid pointers, or + //! - their contents are empty. + //! + XMP_PRIVATE static spIStructureNode CreateStructureNode( const spcIUTF8String & nameSpace, const spcIUTF8String name ); + + protected: + virtual ~IStructureNode_I() __NOTHROW__ {} + pvoid APICALL GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ); + + virtual pINode_base APICALL getNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual uint32 APICALL getChildNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) const __NOTHROW__; + virtual void APICALL insertNode( pINode_base node, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL removeNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__; + virtual pINode_base APICALL replaceNode( pINode_base node, pcIError_base & error ) __NOTHROW__; + virtual pvoid APICALL getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__; + + #ifdef FRIEND_CLASS_DECLARATION + FRIEND_CLASS_DECLARATION(); + #endif + REQ_FRIEND_CLASS_DECLARATION(); + }; + +#if XMP_WinBuild + #pragma warning( pop ) +#endif + +} + +#endif // IStructureNode_I_h__ diff --git a/XMPCore/Interfaces/IXMPLanguageAlternative_I.h b/XMPCore/Interfaces/IXMPLanguageAlternative_I.h new file mode 100644 index 0000000..8e5983f --- /dev/null +++ b/XMPCore/Interfaces/IXMPLanguageAlternative_I.h @@ -0,0 +1,30 @@ +#ifndef __IXMPLanguageAlternative_I_h__ +#define __IXMPLanguageAlternative_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#include "XMPCore/XMPCore_Defines.h" +#include "XMPCommon/XMPCommonFwdDeclarations.h" + +#include "XMPCore/Interfaces/IXMPStructNode.h" +#include "XMPCore/Interfaces/IXMPLanguageAlternative.h" + +namespace AdobeXMPCore_Int{ + + class IXMPLanguageAlternative + : public virtual IXMPLanguageAlternative_latest + { + + + + }; +}; + +#endif // __IXMPLanguageAlternative_I_h__ diff --git a/XMPCore/XMPCoreDefines_I.h b/XMPCore/XMPCoreDefines_I.h new file mode 100644 index 0000000..c549789 --- /dev/null +++ b/XMPCore/XMPCoreDefines_I.h @@ -0,0 +1,39 @@ +#ifndef XMPCoreDefines_I_h__ +#define XMPCoreDefines_I_h__ 1 + +// ================================================================================================= +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +// ================================================================================================= +// All Platform Settings +// =========================== +#include "XMPCore/XMPCoreDefines.h" +#include "XMPCommon/XMPCommonDefines_I.h" + +namespace AdobeXMPCore_Int { + extern const char * kArrayItemName; + extern const char * kArrayItemNameSpace; +} + +// ================================================================================================= +// Macintosh Specific Settings +// =========================== + +// ================================================================================================= +// Windows Specific Settings +// ========================= + +// ================================================================================================= +// UNIX Specific Settings +// ====================== + +// ================================================================================================= +// IOS Specific Settings +// =========================== + +#endif // XMPCoreDefines_I_h__ diff --git a/XMPCore/XMPCoreFwdDeclarations_I.h b/XMPCore/XMPCoreFwdDeclarations_I.h new file mode 100644 index 0000000..c2aa0c5 --- /dev/null +++ b/XMPCore/XMPCoreFwdDeclarations_I.h @@ -0,0 +1,82 @@ +#ifndef XMPCoreFwdDeclarations_I_h__ +#define XMPCoreFwdDeclarations_I_h__ 1 + +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#include "XMPCore/XMPCoreDefines_I.h" +#include "XMPCore/XMPCoreFwdDeclarations.h" +#include "XMPCommon/XMPCommonFwdDeclarations_I.h" + +namespace AdobeXMPCore_Int { + using namespace AdobeXMPCore; + using namespace AdobeXMPCommon; + using namespace AdobeXMPCommon_Int; + + // INameSpacePrefixMap + typedef shared_ptr< INameSpacePrefixMap_I > spINameSpacePrefixMap_I; + typedef shared_ptr< const INameSpacePrefixMap_I > spcINameSpacePrefixMap_I; + + // IPath + typedef shared_ptr< IPath_I > spIPath_I; + typedef shared_ptr< const IPath_I > spcIPath_I; + + // IPathSegment + typedef shared_ptr< IPathSegment_I > spIPathSegment_I; + typedef shared_ptr< const IPathSegment_I > spcIPathSegment_I; + + // INode + typedef shared_ptr< INode_I > spINode_I; + typedef shared_ptr< const INode_I > spcINode_I; + + // ISimpleNode + typedef shared_ptr< ISimpleNode_I > spISimpleNode_I; + typedef shared_ptr< const ISimpleNode_I > spcISimpleNode_I; + + // ICompositeNode + typedef shared_ptr< ICompositeNode_I > spICompositeNode_I; + typedef shared_ptr< const ICompositeNode_I > spcICompositeNode_I; + + // IStructureNode + typedef shared_ptr< IStructureNode_I > spIStructureNode_I; + typedef shared_ptr< const IStructureNode_I > spcIStructureNode_I; + + // IArrayNode + typedef shared_ptr< IArrayNode_I > spIArrayNode_I; + typedef shared_ptr< const IArrayNode_I > spcIArrayNode_I; + + // INodeIterator + typedef shared_ptr< INodeIterator_I > spINodeIterator_I; + typedef shared_ptr< const INodeIterator_I > spcINodeIterator_I; + + // IMetadata + typedef shared_ptr< IMetadata_I > spIXMPMetadata_I; + typedef shared_ptr< const IMetadata_I > spcIXMPMetadata_I; + + // IDOMParser + typedef shared_ptr< IDOMParser_I > spIIDOMParser_I; + typedef shared_ptr< const IDOMParser_I > spcIIDOMParser_I; + + // IDOMSerializer + typedef shared_ptr< IDOMSerializer_I > spIDOMSerializer_I; + typedef shared_ptr< const IDOMSerializer_I > spcIDOMSerializer_I; + + // IDOMImplementationRegistry + typedef shared_ptr< IDOMImplementationRegistry_I > spIDOMImplementationRegistry_I; + typedef shared_ptr< const IDOMImplementationRegistry_I > spcIDOMImplementationRegistry_I; + + // ICoreObjectFactory + typedef shared_ptr< ICoreObjectFactory_I > spICoreObjectFactory_I; + typedef shared_ptr< const ICoreObjectFactory_I > spcICoreObjectFactory_I; + + // ICoreConfigurationManager + typedef shared_ptr< ICoreConfigurationManager_I > spICoreConfigurationManager_I; + typedef shared_ptr< const ICoreConfigurationManager_I > spcICoreConfigurationManager_I; +} +#endif // XMPCoreFwdDeclarations_I_h__ diff --git a/XMPCore/build/CMakeLists.txt b/XMPCore/build/CMakeLists.txt index 9196c4b..7b7ebdd 100644 --- a/XMPCore/build/CMakeLists.txt +++ b/XMPCore/build/CMakeLists.txt @@ -9,7 +9,7 @@ # ============================================================================== # define minimum cmake version -cmake_minimum_required(VERSION 2.8.6) +cmake_minimum_required(VERSION 3.5.2) # Enable folder grouping of projects in IDEs set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -39,6 +39,13 @@ set(XMP_THIS_PROJECT_RELATIVEPATH "../..") include(${CMAKE_CURRENT_SOURCE_DIR}/${XMP_THIS_PROJECT_RELATIVEPATH}/build/XMP_Config.cmake) +add_definitions(-DBUILDING_XMPCORE_LIB=1 -DXMP_COMPONENT_INT_NAMESPACE=AdobeXMPCore_Int) +if (XMP_BUILD_STATIC) + add_definitions(-DBUILDING_XMPCORE_AS_STATIC=1) +else() + add_definitions(-DBUILDING_XMPCORE_AS_DYNAMIC=1) +endif() + set(TP_ZUID_PATH "${XMPROOT_DIR}/third-party/zuid/interfaces") set(TP_EXPAT_PATH "${PROJECT_ROOT}/../../third-party/expat/lib/") diff --git a/XMPCore/build/CMakeListsCommon.txt b/XMPCore/build/CMakeListsCommon.txt index b757273..20bc92a 100644 --- a/XMPCore/build/CMakeListsCommon.txt +++ b/XMPCore/build/CMakeListsCommon.txt @@ -24,10 +24,19 @@ list (APPEND INTERNAL_HEADER_FILES ) source_group("Header Files\\Private\\XMPCore" FILES ${INTERNAL_HEADER_FILES}) -file (GLOB PRIVATE_XMPCOMMON_HEADERS ${XMPROOT_DIR}/XMPCommon/ImplHeaders/*.h) -source_group("Header Files\\Private\\XMPCommon" FILES ${PRIVATE_XMPCOMMON_HEADERS}) +if (INCLUDE_CPP_DOM_SOURCE) + file (GLOB_RECURSE PRIVATE_XMPCOMMON_HEADERS ${XMPROOT_DIR}/XMPCommon/*.h) + source_group("Header Files\\Private\\XMPCommon" FILES ${PRIVATE_XMPCOMMON_HEADERS}) -file (GLOB PRIVATE_XMPCORE_HEADERS ${XMPROOT_DIR}/XMPCore/headers/*.h ${XMPROOT_DIR}/XMPCore/Interfaces/*.h) + file (GLOB_RECURSE PRIVATE_XMPCOMMON_SOURCES ${XMPROOT_DIR}/XMPCommon/source/*.cpp) + source_group("Source Files\\Private\\XMPCommon" FILES ${PRIVATE_XMPCOMMON_SOURCES}) +endif (INCLUDE_CPP_DOM_SOURCE) + +file (GLOB PRIVATE_XMPCORE_HEADERS + ${XMPROOT_DIR}/XMPCore/*.h + ${XMPROOT_DIR}/XMPCore/ImplHeaders/*.h + ${XMPROOT_DIR}/XMPCore/headers/*.h + ${XMPROOT_DIR}/XMPCore/Interfaces/*.h ) source_group("Header Files\\Private\\XMPCore" FILES ${PRIVATE_XMPCORE_HEADERS}) file (GLOB_RECURSE PUBLIC_CLIENTGLUE_HEADER_FILES ${XMPROOT_DIR}/public/include/client-glue/*.*) @@ -44,15 +53,31 @@ list (REMOVE_ITEM PUBLIC_HEADER_FILES ) source_group("Header Files\\Public" FILES ${PUBLIC_HEADER_FILES}) -file (GLOB_RECURSE PUBLIC_XMPCOMMON_HEADERS ${XMPROOT_DIR}/public/include/XMPCommon/*.h ${XMPROOT_DIR}/XMPCommon/*.h) +file (GLOB_RECURSE PUBLIC_XMPCOMMON_HEADERS ${XMPROOT_DIR}/public/include/XMPCommon/*.h ) source_group("Header Files\\Public\\XMPCommon" FILES ${PUBLIC_XMPCOMMON_HEADERS}) +file (GLOB_RECURSE PUBLIC_XMPCOMMON_SOURCES ${XMPROOT_DIR}/public/include/XMPCommon/source/*.cpp ) +source_group("Source Files\\Public\\XMPCommon" FILES ${PUBLIC_XMPCOMMON_SOURCES}) + file (GLOB_RECURSE PUBLIC_XMPCORE_HEADERS ${XMPROOT_DIR}/public/include/XMPCore/*.h) source_group("Header Files\\Public\\XMPCore" FILES ${PUBLIC_XMPCORE_HEADERS}) +file (GLOB_RECURSE PUBLIC_XMPCORE_SOURCES ${XMPROOT_DIR}/public/include/XMPCore/source/*.cpp ) +source_group("Source Files\\Public\\XMPCore" FILES ${PUBLIC_XMPCORE_SOURCES}) + file (GLOB ABIWRAPPER_SOURCE_FILES ${SOURCE_ROOT}/WXMP*.cpp) source_group("Source Files\\ABI Wrappers" FILES ${ABIWRAPPER_SOURCE_FILES}) +if (INCLUDE_CPP_DOM_SOURCE) + file (GLOB PRIVATE_XMPCORE_ISOURCE_FILES ${SOURCE_ROOT}/*_I.cpp) + file (GLOB PRIVATE_XMPCORE_IMPLSOURCE_FILES ${SOURCE_ROOT}/*Impl.cpp) + list (REMOVE_ITEM PRIVATE_XMPCORE_IMPLSOURCE_FILES ${SOURCE_ROOT}/XMPCore_Impl.cpp) + source_group("Source Files\\Private\\XMPCore" FILES ${PRIVATE_XMPCORE_ISOURCE_FILES} ${PRIVATE_XMPCORE_IMPLSOURCE_FILES}) +else (INCLUDE_CPP_DOM_SOURCE) + file (GLOB PRIVATE_XMPCORE_IMPLSOURCE_FILES ${SOURCE_ROOT}/CoreObjectFactoryImpl.cpp) + source_group("Source Files\\Private\\XMPCore" FILES ${PRIVATE_XMPCORE_IMPLSOURCE_FILES}) +endif (INCLUDE_CPP_DOM_SOURCE) + #XMP Core classes file (GLOB CORECLASS_SOURCE_FILES ${SOURCE_ROOT}/XMP*.cpp) list (REMOVE_ITEM CORECLASS_SOURCE_FILES ${SOURCE_ROOT}/XMPCore_Impl.cpp) @@ -64,12 +89,13 @@ list (APPEND THIRDPARTY_SOURCE_FILES ${TP_EXPAT_PATH}/xmlrole.c ${TP_EXPAT_PATH}/xmltok.c ) -list (APPEND THIRDPARTY_SOURCE_FILES ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/expat_config.h) +if(WIN32) + list (APPEND THIRDPARTY_SOURCE_FILES ${RESOURCE_ROOT}/win/expat_config.h) +else() + list (APPEND THIRDPARTY_SOURCE_FILES ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/expat_config.h) +endif() source_group("Source Files\\Third Party" FILES ${THIRDPARTY_SOURCE_FILES}) -file (GLOB XMPCOMMON_SOURCES ${XMPROOT_DIR}/XMPCommon/source/*.cpp) -source_group("Source Files\\Private\\XMPCommon" FILES ${XMPCOMMON_SOURCES}) - list (APPEND UTILITY_SOURCE_FILES ${SOURCE_ROOT}/ExpatAdapter.cpp ${SOURCE_ROOT}/ParseRDF.cpp @@ -81,13 +107,17 @@ list (APPEND UTILITY_SOURCE_FILES source_group("Source Files\\Utilities" FILES ${UTILITY_SOURCE_FILES}) #resource files -file (GLOB RESOURCE_FILES ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/*.*) +if (WIN32) + file (GLOB RESOURCE_FILES ${RESOURCE_ROOT}/win/*.*) +else () + file (GLOB RESOURCE_FILES ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/*.*) +endif() if(WIN32 AND ${XMP_BUILD_STATIC}) list(REMOVE_ITEM RESOURCE_FILES ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}.rc) endif() source_group("Resource Files" FILES ${RESOURCE_FILES}) -if (WIN32 OR (UNIX AND APPLE)) +if (WIN32 OR UNIX) list(APPEND SOURCE_FILES ${PUBLIC_CLIENTGLUE_HEADER_FILES} ${PUBLIC_HEADER_FILES} @@ -97,48 +127,35 @@ if (WIN32 OR (UNIX AND APPLE)) ${CORECLASS_SOURCE_FILES} ${THIRDPARTY_SOURCE_FILES} ${UTILITY_SOURCE_FILES} + ${PRIVATE_XMPCORE_ISOURCE_FILES} + ${PRIVATE_XMPCORE_IMPLSOURCE_FILES} ${PRIVATE_XMPCOMMON_HEADERS} + ${PRIVATE_XMPCOMMON_SOURCES} ${PRIVATE_XMPCORE_HEADERS} ${PUBLIC_XMPCOMMON_HEADERS} + ${PUBLIC_XMPCOMMON_SOURCES} ${PUBLIC_XMPCORE_HEADERS} - ${XMPCOMMON_SOURCES} + ${PUBLIC_XMPCORE_SOURCES} ${RESOURCE_FILES} ) -else() - list (REMOVE_ITEM CORECLASS_SOURCE_FILES - ${SOURCE_ROOT}/XMPArrayNode_v1_Impl.cpp - ${SOURCE_ROOT}/XMPArrayNodeIterator_v1_Impl.cpp - ${SOURCE_ROOT}/XMPCoreObjectFactory_Impl.cpp - ${SOURCE_ROOT}/XMPMetadata_v1_Impl.cpp - ${SOURCE_ROOT}/XMPNode_v1_Impl.cpp - ${SOURCE_ROOT}/XMPPathSegment_v1_Impl.cpp - ${SOURCE_ROOT}/XMPPath_v1_Impl.cpp - ${SOURCE_ROOT}/XMPQName_v1_Impl.cpp - ${SOURCE_ROOT}/XMPQualifiers_v1_Impl.cpp - ${SOURCE_ROOT}/XMPSimpleNode_v1_Impl.cpp - ${SOURCE_ROOT}/XMPStructNode_v1_Impl.cpp - ${SOURCE_ROOT}/XMPStructNodeIterator_v1_Impl.cpp - ) - - list(APPEND SOURCE_FILES - ${PUBLIC_CLIENTGLUE_HEADER_FILES} - ${PUBLIC_HEADER_FILES} - ${INTERNAL_HEADER_FILES} - ${ABIWRAPPER_SOURCE_FILES} - ${ABIWRAPPER_SOURCE_FILES} - ${CORECLASS_SOURCE_FILES} - ${THIRDPARTY_SOURCE_FILES} - ${UTILITY_SOURCE_FILES} - ${RESOURCE_FILES} - ) - endif() + # include directories include_directories(${XMPROOT_DIR}) include_directories(${XMPROOT_DIR}/public/include) include_directories(${XMPROOT_DIR}/third-party/expat/public/lib) include_directories(${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}) +if(UNIX AND NOT APPLE AND NOT ${XMP_BUILD_STATIC}) +include_directories(${XMPROOT_DIR}/XMPCore/third-party/uuid/include) +endif() +if (WIN32) + include_directories(${RESOURCE_ROOT}/win) +else () + include_directories(${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}) +endif () +#additional link directory +link_directories(${OUTPUT_DIR}) # ============================================================================== @@ -151,26 +168,47 @@ if (UNIX AND APPLE AND NOT ${XMP_BUILD_STATIC}) else() set (INFO_PLIST_FLAGS "-DNDEBUG=1") endif() - - add_custom_target(${TARGET_NAME}InfoPlist - COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} - COMMAND if [ $(CONFIGURATION) != Debug ]; then - ${GCCTOOL} -E -P -x c ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}.plist - -F${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ - -DPRODUCT_NAME=${TARGET_NAME} -DMAC_ENV=1 -DNDEBUG=1 - -include ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}PList.h - -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist - \; else - ${GCCTOOL} -E -P -x c ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}.plist - -F${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ - -DPRODUCT_NAME=${TARGET_NAME} -DMAC_ENV=1 -DDEBUG=1 - -include ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}PList.h - -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist - \; fi - COMMAND rm -f ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../CMakeFiles/${TARGET_NAME}.dir/Info.plist - COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../CMakeFiles/${TARGET_NAME}.dir/Info.plist - COMMENT "Preprocessing Info-plist" - ) + if(NOT APPLE_IOS) + add_custom_target(${TARGET_NAME}InfoPlist + COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMAND if [ $(CONFIGURATION) != Debug ]; then + ${GCCTOOL} -E -P -x c ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}.plist + -F${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ + -DPRODUCT_NAME=${TARGET_NAME} -DMAC_ENV=1 -DNDEBUG=1 + -include ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}PList.h + -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist + \; else + ${GCCTOOL} -E -P -x c ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}.plist + -F${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ + -DPRODUCT_NAME=${TARGET_NAME} -DMAC_ENV=1 -DDEBUG=1 + -include ${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}PList.h + -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist + \; fi + COMMAND rm -f ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../CMakeFiles/${TARGET_NAME}.dir/Info.plist + COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../CMakeFiles/${TARGET_NAME}.dir/Info.plist + COMMENT "Preprocessing Info-plist" + ) + else() + add_custom_target(${TARGET_NAME}InfoPlist + COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} + COMMAND if [ $(CONFIGURATION) != Debug ]; then + ${GCCTOOL} -E -P -x c ${RESOURCE_ROOT}/ios/${TARGET_NAME}.plist + -F${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ + -DPRODUCT_NAME=${TARGET_NAME} -DIOS_ENV=1 -DNDEBUG=1 + -include ${RESOURCE_ROOT}/ios/${TARGET_NAME}PList.h + -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist + \; else + ${GCCTOOL} -E -P -x c ${RESOURCE_ROOT}/ios/${TARGET_NAME}.plist + -F${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/ + -DPRODUCT_NAME=${TARGET_NAME} -DIOS_ENV=1 -DDEBUG=1 + -include ${RESOURCE_ROOT}/ios/${TARGET_NAME}PList.h + -o ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist + \; fi + COMMAND rm -f ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../CMakeFiles/${TARGET_NAME}.dir/Info.plist + COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../CMakeFiles/${TARGET_NAME}.dir/Info.plist + COMMENT "Preprocessing Info-plist" + ) + endif() set(DEPENDENCY_LIST "ALL:${TARGET_NAME}InfoPlist") else () set(DEPENDENCY_LIST "") @@ -183,7 +221,7 @@ set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${XMPCORE_LIB}) # ============================================================================== # Link dependencies -set(FRAMEWORK_LIST "Mac:CoreFoundation" "Mac:CoreServices") +set(FRAMEWORK_LIST "ALL:CoreFoundation" "Mac:CoreServices") AddMacFramework(${TARGET_NAME} FRAMEWORK_LIST) @@ -193,6 +231,10 @@ else(WIN32) if(UNIX AND NOT APPLE) SetWinLinkFlags(${TARGET_NAME} "-Xlinker --version-script -Xlinker \"${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/${TARGET_NAME}.exp\"" "") else() + if(APPLE_IOS AND NOT XMP_BUILD_STATIC) + set_target_properties(${TARGET_NAME} PROPERTIES XCODE_ATTRIBUTE_DYLIB_INSTALL_NAME_BASE "@rpath") + set_target_properties(${TARGET_NAME} PROPERTIES XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.adobe.Adobe${TARGET_NAME}") + endif() set_target_properties(${TARGET_NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH ON INSTALL_NAME_DIR "@executable_path/../Frameworks") SetWinLinkFlags(${TARGET_NAME} "-unexported_symbols_list \"${RESOURCE_ROOT}/${XMP_PLATFORM_SHORT}/XMPCore.unexp\"" "${XMPCORE_LIB}") set_target_properties(${TARGET_NAME} PROPERTIES XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN "YES") diff --git a/XMPCore/resource/linux/XMPCore.exp b/XMPCore/resource/linux/XMPCore.exp index d1c7b1b..1e47310 100644 --- a/XMPCore/resource/linux/XMPCore.exp +++ b/XMPCore/resource/linux/XMPCore.exp @@ -62,6 +62,7 @@ global: WXMPMeta_SetDefaultErrorCallback_1; WXMPMeta_SetErrorCallback_1; WXMPMeta_ResetErrorCallbackLimit_1; + WXMPMeta_GetXMPDOMFactoryInstance_1; WXMPIterator_PropCTor_1; WXMPIterator_TableCTor_1; diff --git a/XMPCore/resource/mac/XMPCore.exp b/XMPCore/resource/mac/XMPCore.exp index fad61af..80079e0 100644 --- a/XMPCore/resource/mac/XMPCore.exp +++ b/XMPCore/resource/mac/XMPCore.exp @@ -59,6 +59,7 @@ _WXMPMeta_SerializeToBuffer_1 _WXMPMeta_SetDefaultErrorCallback_1 _WXMPMeta_SetErrorCallback_1 _WXMPMeta_ResetErrorCallbackLimit_1 +_WXMPMeta_GetXMPDOMFactoryInstance_1 _WXMPIterator_PropCTor_1 _WXMPIterator_TableCTor_1 diff --git a/XMPCore/resource/win/XMPCore.def b/XMPCore/resource/win/XMPCore.def index 505edef..6e1ad63 100644 --- a/XMPCore/resource/win/XMPCore.def +++ b/XMPCore/resource/win/XMPCore.def @@ -1,5 +1,5 @@ ; Declares the entry points for the DLL. -; Highest index: 126 - WXMPMeta_ResetErrorCallbackLimit_1 +; Highest index: 127 - WXMPMeta_GetXMPDOMFactoryInstance_1 LIBRARY XMPCore @@ -73,6 +73,7 @@ EXPORTS WXMPMeta_SetDefaultErrorCallback_1 @124 WXMPMeta_SetErrorCallback_1 @125 WXMPMeta_ResetErrorCallbackLimit_1 @126 + WXMPMeta_GetXMPDOMFactoryInstance_1 @127 WXMPIterator_PropCTor_1 @62 WXMPIterator_TableCTor_1 @63 diff --git a/XMPCore/source/ArrayNodeImpl.cpp b/XMPCore/source/ArrayNodeImpl.cpp new file mode 100644 index 0000000..792d0a7 --- /dev/null +++ b/XMPCore/source/ArrayNodeImpl.cpp @@ -0,0 +1,227 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/ArrayNodeImpl.h" + #include "XMPCore/ImplHeaders/TNodeIteratorImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCore/Interfaces/INodeIterator_I.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + // All virtual functions + + ArrayNodeImpl::ArrayNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, eArrayForm arrayForm ) + : NodeImpl( nameSpace, nameSpaceLength, name, nameLength ) + , mArrayForm( arrayForm ) {} + + IArrayNode_v1::eArrayForm APICALL ArrayNodeImpl::GetArrayForm() const { + return mArrayForm; + } + + INode_v1::eNodeType APICALL ArrayNodeImpl::GetChildNodeType() const { + AutoSharedLock lock( mSharedMutex ); + if ( mChildren.size() != 0 ) + return mChildren[ 0 ]->GetNodeType(); + return kNTAll; + } + + spINode APICALL ArrayNodeImpl::GetNodeAtIndex( sizet index ) { + sizet actualIndex = index - 1; + + AutoSharedLock lock( mSharedMutex ); + + if ( actualIndex < mChildren.size() ) { + return MakeUncheckedSharedPointer( mChildren.at( actualIndex ).get(), __FILE__, __LINE__ ); + } + return spINode_I(); + } + + void APICALL ArrayNodeImpl::InsertNodeAtIndex( const spINode & node, sizet index ) { + sizet actualIndex = index - 1; + { + AutoSharedLock lock( mSharedMutex ); + if ( actualIndex > mChildren.size() ) + NOTIFY_ERROR( IError_base::kEDGeneral, kGECIndexOutOfBounds, + "Trying to insert a node at an invalid index", IError_v1::kESOperationFatal, + true, index, true, static_cast< sizet >( mChildren.size() ) ); + } + bool goAhead = CheckSuitabilityToBeUsedAsChildNode( node ); + + if ( goAhead ) { + AutoSharedLock lock( mSharedMutex, true ); + auto it = mChildren.begin(); + std::advance( it, actualIndex ); + it = mChildren.insert( it, MakeUncheckedSharedPointer( node.get(), __FILE__, __LINE__ ) ); + pINode_I node_I = node->GetINode_I(); + node_I->SetIndex( index ); + node_I->ChangeParent( this ); + std::advance( it, 1 ); + for ( auto endIt = mChildren.end(); it != endIt; ++it ) { + ( *it )->GetINode_I()->SetIndex( ++index ); + } + } + } + + spINode APICALL ArrayNodeImpl::RemoveNodeAtIndex( sizet index ) { + spINode node = GetNodeAtIndex( index ); + if ( node ) { + sizet actualIndex = index - 1; + AutoSharedLock lock( mSharedMutex, true ); + auto it = mChildren.begin(); + std::advance( it, actualIndex ); + it = mChildren.erase( it ); + node->GetINode_I()->ChangeParent( NULL ); + for ( auto endIt = mChildren.end(); it != endIt; ++it ) { + ( *it )->GetINode_I()->SetIndex( index++ ); + } + } + return node; + } + + spINode APICALL ArrayNodeImpl::ReplaceNodeAtIndex( const spINode & node, sizet index ) { + if ( CheckSuitabilityToBeUsedAsChildNode( node ) && GetNodeAtIndex( index ) ) { + auto retValue = RemoveNodeAtIndex( index ); + InsertNodeAtIndex( node, index ); + return retValue; + } else { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECIndexOutOfBounds, + "Trying to replace a node at an invalid index", IError_v1::kESOperationFatal, + true, index, true, static_cast< sizet >( mChildren.size() ) ); + } + return spINode(); + } + + void APICALL ArrayNodeImpl::AppendNode( const spINode & node ) { + InsertNodeAtIndex( node, ChildCount() + 1 ); + } + + spINodeIterator APICALL ArrayNodeImpl::Iterator() { + AutoSharedLock lock( mSharedMutex ); + auto beginIt = mChildren.begin(), endIt = mChildren.end(); + if ( beginIt == endIt ) + return spINodeIterator(); + else + return MakeUncheckedSharedPointer( new TNodeIteratorImpl< NodeVector::iterator >( beginIt, endIt ), __FILE__, __LINE__, true ); + } + + sizet APICALL ArrayNodeImpl::ChildCount() const __NOTHROW__ { + AutoSharedLock lock( mSharedMutex ); + return mChildren.size(); + } + + spIArrayNode APICALL ArrayNodeImpl::ConvertToArrayNode() { + return MakeUncheckedSharedPointer( this, __FILE__, __LINE__ ); + } + + INode_v1::eNodeType APICALL ArrayNodeImpl::GetNodeType() const { + return kNTArray; + } + + bool APICALL ArrayNodeImpl::HasContent() const { + AutoSharedLock lock( mSharedMutex ); + return mChildren.size() > 0; + } + + void APICALL ArrayNodeImpl::ClearContents() { + AutoSharedLock lock( mSharedMutex, true ); + for ( auto it = mChildren.begin(), itEnd = mChildren.end(); it != itEnd; ++it ) { + ( *it )->GetINode_I()->ChangeParent( NULL ); + } + mChildren.clear(); + } + + spINode APICALL ArrayNodeImpl::CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const { + spIArrayNode newNode; + if ( ignoreEmptyNodes && mChildren.size() == 0 ) { + if ( ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 ) + return newNode; + } + + newNode = IArrayNode_I::CreateArrayNode( mNameSpace, mName, mArrayForm ); + + for ( auto it = mChildren.begin(), endIt = mChildren.end(); it != endIt; ++it ) { + spINode childNode = ( *it )->Clone( ignoreEmptyNodes, ignoreNodesWithOnlyQualifiers ); + if ( childNode ) { + newNode->AppendNode( childNode ); + } + } + + if ( ignoreEmptyNodes && newNode->ChildCount() == 0 ) { + if ( ignoreNodesWithOnlyQualifiers ) + return spINode(); + else if ( !ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 ) + return spINode(); + } + return newNode; + } + + void ArrayNodeImpl::resetChangesForChildren() const { + AutoSharedLock lock( mSharedMutex ); + for ( auto it = mChildren.begin(), itEnd = mChildren.end(); it != itEnd; ++it ) { + ( *it )->AcknowledgeChanges(); + } + } + + bool ArrayNodeImpl::CheckSuitabilityToBeUsedAsChildNode( const spcINode & node ) const { + bool result = CompositeNodeImpl::CheckSuitabilityToBeUsedAsChildNode( node ); + if ( !result ) return false; + + eNodeType currentChildType = GetChildNodeType(); + if ( currentChildType == kNTAll || currentChildType == node->GetNodeType() ) + return true; + else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECArrayItemTypeDifferent, + "node type is different than what currently array can hold", IError_v1::kESOperationFatal, + true, static_cast< uint64 >( currentChildType ), true, static_cast< uint64 >( node->GetNodeType() ) ); + } + return false; + } + + spIArrayNode IArrayNode_I::CreateArrayNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name, eArrayForm arrayForm ) { + return MakeUncheckedSharedPointer( new ArrayNodeImpl( + nameSpace ? nameSpace->c_str() : NULL, nameSpace ? nameSpace->size() : 0, + name ? name->c_str() : NULL, name ? name->size() : 0, arrayForm ), __FILE__, __LINE__, true ); + } + + template<> + spINode TNodeIteratorImpl< ArrayNodeImpl::NodeVector::iterator >::GetNodeFromIterator( const ArrayNodeImpl::NodeVector::iterator & it ) const { + return MakeUncheckedSharedPointer( it->get(), __FILE__, __LINE__, false ); + } +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + spIArrayNode IArrayNode_v1::MakeShared( pIArrayNode_base ptr ) { + if ( !ptr ) return spIArrayNode(); + pIArrayNode p = IArrayNode::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IArrayNode >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + + spIArrayNode IArrayNode_v1::CreateUnorderedArrayNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + return MakeUncheckedSharedPointer( new ArrayNodeImpl( nameSpace, nameSpaceLength, name, nameLength, IArrayNode::kAFUnordered ), __FILE__, __LINE__, true ); + } + + spIArrayNode IArrayNode_v1::CreateOrderedArrayNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + return MakeUncheckedSharedPointer( new ArrayNodeImpl( nameSpace, nameSpaceLength, name, nameLength, IArrayNode::kAFOrdered ), __FILE__, __LINE__, true ); + } + + spIArrayNode IArrayNode_v1::CreateAlternativeArrayNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + return MakeUncheckedSharedPointer( new ArrayNodeImpl( nameSpace, nameSpaceLength, name, nameLength, IArrayNode::kAFAlternative ), __FILE__, __LINE__, true ); + } + +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB diff --git a/XMPCore/source/ClientDOMParserWrapperImpl.cpp b/XMPCore/source/ClientDOMParserWrapperImpl.cpp new file mode 100644 index 0000000..b3bad60 --- /dev/null +++ b/XMPCore/source/ClientDOMParserWrapperImpl.cpp @@ -0,0 +1,90 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +namespace AdobeXMPCore_Int { + class ClientDOMParserWrapperImpl; +} + +#define FRIEND_CLASS_DECLARATION() friend class AdobeXMPCore_Int::ClientDOMParserWrapperImpl; + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/ClientDOMParserWrapperImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCore/Interfaces/IClientDOMParser.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" +#include "XMPCore/Interfaces/INode.h" + +namespace AdobeXMPCore_Int { + + + ClientDOMParserWrapperImpl::ClientDOMParserWrapperImpl( pIClientDOMParser_base parser ) + : mpClientParser( parser ) + { + if ( parser ) { + pcIError_base error( NULL ); + uint32 unknownExceptionCaught( 0 ); + TreatKeyAsCaseInsensitive( parser->areKeysCaseSensitive( error, unknownExceptionCaught ) == 0 ); + if ( !error && unknownExceptionCaught == 0 ) + parser->initialize( this, error, unknownExceptionCaught ); + if ( error ) { + auto spError = IError::MakeShared( error ); + error->Release(); + throw spError; + } + if ( unknownExceptionCaught ) + NOTIFY_ERROR( IError::kEDGeneral, kGECUnknownExceptionCaught, "Unknown Exception caught in the client code", IError::kESOperationFatal, false, false ); + } + } + + spINode APICALL ClientDOMParserWrapperImpl::ParseAsNode( const char * buffer, sizet bufferLength ) { + pcIError_base error( NULL ); + uint32 unknownExceptionCaught( 0 ); + auto pnode = mpClientParser->parse( buffer, bufferLength, this, &ReportErrorAndContinueABISafe, error, unknownExceptionCaught ); + if ( error ) { + auto spError = IError::MakeShared( error ); + error->Release(); + throw spError; + } + if ( unknownExceptionCaught ) + NOTIFY_ERROR( IError::kEDGeneral, kGECUnknownExceptionCaught, "Unknown Exception caught in the client code", IError::kESOperationFatal, false, false ); + return MakeUncheckedSharedPointer( pnode, __FILE__, __LINE__, false ); + } + + ClientDOMParserWrapperImpl::~ClientDOMParserWrapperImpl() __NOTHROW__ { + if ( mpClientParser ) { + mpClientParser->Release(); + mpClientParser = NULL; + } + } + + eConfigurableErrorCode APICALL ClientDOMParserWrapperImpl::ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const { + pcIError_base error( NULL ); + uint32 unknownExceptionCaught( 0 ); + auto retValue = mpClientParser->validate( key, static_cast< uint32 >( type ), value, error, unknownExceptionCaught ); + if ( error ) { + auto spError = IError::MakeShared( error ); + error->Release(); + throw spError; + } + if ( unknownExceptionCaught ) + NOTIFY_ERROR( IError::kEDGeneral, kGECUnknownExceptionCaught, "Unknown Exception caught in the client code", IError::kESOperationFatal, false, false ); + return static_cast< eConfigurableErrorCode >( retValue ); + } + + DOMParserImpl * APICALL ClientDOMParserWrapperImpl::clone() const { + ClientDOMParserWrapperImpl * cloned = new ClientDOMParserWrapperImpl( NULL ); + if ( cloned ) + cloned->mpClientParser = mpClientParser; + return cloned; + } + +} diff --git a/XMPCore/source/ClientDOMSerializerWrapperImpl.cpp b/XMPCore/source/ClientDOMSerializerWrapperImpl.cpp new file mode 100644 index 0000000..4c6e984 --- /dev/null +++ b/XMPCore/source/ClientDOMSerializerWrapperImpl.cpp @@ -0,0 +1,106 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +namespace AdobeXMPCore_Int { + class ClientDOMSerializerWrapperImpl; +} + +#define FRIEND_CLASS_DECLARATION() friend class AdobeXMPCore_Int::ClientDOMSerializerWrapperImpl; + + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/ClientDOMSerializerWrapperImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCore/Interfaces/IClientDOMSerializer.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/INode.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" + +namespace AdobeXMPCore_Int { + + ClientDOMSerializerWrapperImpl::ClientDOMSerializerWrapperImpl( pIClientDOMSerializer serializer ) + : mpSerializer( serializer ) + { + if ( serializer ) { + pcIError_base error( NULL ); + uint32 unknownExceptionCaught( 0 ); + TreatKeyAsCaseInsensitive( serializer->areKeysCaseSensitive( error, unknownExceptionCaught ) == 0 ); + if ( !error && unknownExceptionCaught == 0 ) + serializer->initialize( this, error, unknownExceptionCaught ); + if ( error ) { + auto spError = IError::MakeShared( error ); + error->Release(); + throw spError; + } + if ( unknownExceptionCaught ) + NOTIFY_ERROR( IError::kEDGeneral, kGECUnknownExceptionCaught, "Unknown Exception caught in the client code", IError::kESOperationFatal, false, false ); + } + } + + ClientDOMSerializerWrapperImpl::~ClientDOMSerializerWrapperImpl() __NOTHROW__ { + if ( mpSerializer ) { + mpSerializer->Release(); + mpSerializer = NULL; + } + } + + DOMSerializerImpl * APICALL ClientDOMSerializerWrapperImpl::clone() const { + ClientDOMSerializerWrapperImpl * cloned = new ClientDOMSerializerWrapperImpl( NULL ); + if ( cloned ) + cloned->mpSerializer = mpSerializer; + return cloned; + } + + spIUTF8String APICALL ClientDOMSerializerWrapperImpl::Serialize( const spINode & node, const spcINameSpacePrefixMap & map ) { + spIUTF8String str( IUTF8String_I::CreateUTF8String( NULL, 0 ) ); + pcIError_base error( NULL ); + uint32 unknownExceptionCaught( 0 ); + spcINameSpacePrefixMap mergedMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + + if ( map ) { + spINameSpacePrefixMap newMergedMap = mergedMap->Clone(); + newMergedMap->GetINameSpacePrefixMap_I()->Merge( map ); + mergedMap = newMergedMap; + } + + mpSerializer->serialize( node ? node->GetActualINode() : NULL, mergedMap ? mergedMap->GetActualINameSpacePrefixMap() : NULL, this, + &ReportErrorAndContinueABISafe, str->GetActualIUTF8String(), error, unknownExceptionCaught ); + if ( error ) { + auto spError = IError::MakeShared( error ); + error->Release(); + throw spError; + } + if ( unknownExceptionCaught ) + NOTIFY_ERROR( IError::kEDGeneral, kGECUnknownExceptionCaught, "Unknown Exception caught in the client code", IError::kESOperationFatal, false, false ); + return str; + } + + eConfigurableErrorCode APICALL ClientDOMSerializerWrapperImpl::ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const { + pcIError_base error( NULL ); + uint32 unknownExceptionCaught( 0 ); + auto retValue = mpSerializer->validate( key, static_cast< uint32 >( type ), value, error, unknownExceptionCaught ); + if ( error ) { + auto spError = IError::MakeShared( error ); + error->Release(); + throw spError; + } + if ( unknownExceptionCaught ) + NOTIFY_ERROR( IError::kEDGeneral, kGECUnknownExceptionCaught, "Unknown Exception caught in the client code", IError::kESOperationFatal, false, false ); + return static_cast< eConfigurableErrorCode >( retValue ); + } + + spIUTF8String APICALL ClientDOMSerializerWrapperImpl::SerializeInternal(const spINode & node, XMP_OptionBits options, sizet padding, const char * newline, const char * indent, sizet baseIndent, const spcINameSpacePrefixMap & nameSpacePrefixMap) const { + + return spIUTF8String(); + + } +} diff --git a/XMPCore/source/CompositeNodeImpl.cpp b/XMPCore/source/CompositeNodeImpl.cpp new file mode 100644 index 0000000..e2d7797 --- /dev/null +++ b/XMPCore/source/CompositeNodeImpl.cpp @@ -0,0 +1,154 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/CompositeNodeImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCore/Interfaces/IPath.h" +#include "XMPCore/Interfaces/IPathSegment.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/ISimpleNode.h" +#include "XMPCore/Interfaces/IStructureNode_I.h" +#include "XMPCore/Interfaces/IArrayNode.h" +#include "XMPCore/Interfaces/INodeIterator.h" + +namespace AdobeXMPCore_Int { + + static spISimpleNode GetArrayItemBasedOnSimpleQual( const spIArrayNode & arrayNode, const spcIUTF8String & nameSpace, const spcIUTF8String & name, const spcIUTF8String & value ) { + spINodeIterator it = arrayNode->Iterator(); + while ( it ) { + spINode node = it->GetNode(); + if ( node->HasQualifiers() ) { + spISimpleNode simpleQualifer = node->GetINode_I()->GetSimpleQualifier( nameSpace, name ); + if ( simpleQualifer ) { + if ( value->compare( simpleQualifer->GetValue() ) == 0 ) + return simpleQualifer; + } + } + it = it->Next(); + } + return spISimpleNode(); + } + + INode_v1::eNodeType APICALL CompositeNodeImpl::GetNodeTypeAtPath( const spcIPath & path ) const { + auto node = const_cast< CompositeNodeImpl * >( this )->GetNodeAtPath( path ); + if ( node ) return node->GetNodeType(); + return INode_v1::kNTNone; + } + + spINode APICALL CompositeNodeImpl::GetNodeAtPath( const spcIPath & path ) { + if ( !path ) + return spINode(); + + spINode current = MakeUncheckedSharedPointer( this, __FILE__, __LINE__ ); + spINode parent = current, result = current; + + sizet segCount = path->Size(); + for ( sizet i = 0; i < segCount && current; ++i ) { + spcIPathSegment segment = path->GetPathSegment( i + 1 ); + + switch ( segment->GetType() ) { + + case IPathSegment::kPSTProperty: + { + auto node = parent->ConvertToStructureNode(); + if ( node ) + current = node->GetIStructureNode_I()->GetNode( segment->GetNameSpace(), segment->GetName() ); + else + current = spINode(); + } + break; + + case IPathSegment::kPSTArrayIndex: + { + auto node = parent->ConvertToArrayNode(); + if ( node ) + current = node->GetNodeAtIndex( segment->GetIndex() ); + else + current = spINode(); + } + break; + + case IPathSegment::kPSTQualifier: + if ( parent->HasQualifiers() ) { + current = current->GetINode_I()->GetQualifier( segment->GetNameSpace(), segment->GetName() ); + } else { + current = spINode(); + } + break; + + case IPathSegment::kPSTQualifierSelector: + { + auto node = parent->ConvertToArrayNode(); + if ( node ) { + current = GetArrayItemBasedOnSimpleQual( node, segment->GetNameSpace(), segment->GetName(), segment->GetValue() ); + } else { + current = spINode(); + } + } + break; + + default: + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECLogicalError, + "unhandled situtation occured", IError_v1::kESOperationFatal, true, static_cast< uint32 >( segment->GetType() ) ); + break; + } + + parent = result = current; + } + return result; + } + + void APICALL CompositeNodeImpl::InsertNodeAtPath( const spINode & node, const spcIPath & path ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECNotImplemented, + "InsertNodeAtPath( path ) is not yet implemented", IError_v1::kESOperationFatal, false, false ); + } + + spINode APICALL CompositeNodeImpl::ReplaceNodeAtPath( const spINode & node, const spcIPath & path ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECNotImplemented, + "ReplaceNodeAtPath( path ) is not yet implemented", IError_v1::kESOperationFatal, false, false ); + } + + spINode APICALL CompositeNodeImpl::RemoveNodeAtPath( const spcIPath & path ) { + spINode node = GetNodeAtPath( path ); + if ( node ) { + auto parentNode_I = node->GetINode_I()->GetRawParentPointer()->GetINode_I(); + if ( node->IsQualifierNode() ) { + node = parentNode_I->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( node->GetNameSpace(), node->GetName() ); + } else if ( node->IsArrayItem() ) { + auto parentArrayNode = parentNode_I->ConvertToArrayNode(); + node = parentArrayNode->RemoveNodeAtIndex( node->GetIndex() ); + } else { + auto parentStructureNode = parentNode_I->ConvertToStructureNode()->GetIStructureNode_I(); + node = parentStructureNode->RemoveNode( node->GetNameSpace(), node->GetName() ); + } + } + return node; + } + + bool CompositeNodeImpl::CheckSuitabilityToBeUsedAsChildNode( const spcINode & node ) const { + if ( node ) { + if ( node->GetParentNodeType() == INode_v1::kNTNone ) { + return true; + } else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNodeAlreadyAChild, + "node is already a part of tree", IError_v1::kESOperationFatal, false, false ); + } + } else { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECParametersNotAsExpected, + "invalid shared pointer", IError_v1::kESOperationFatal, false, false ); + } + return false; + } + +} diff --git a/XMPCore/source/CoreConfigurationManagerImpl.cpp b/XMPCore/source/CoreConfigurationManagerImpl.cpp new file mode 100644 index 0000000..35a7bbe --- /dev/null +++ b/XMPCore/source/CoreConfigurationManagerImpl.cpp @@ -0,0 +1,56 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/CoreConfigurationManagerImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + CoreConfigurationManagerImpl::CoreConfigurationManagerImpl() { } + + static spICoreConfigurationManager ManageCoreConfigurationManager( bool destroy = false ) { + static spICoreConfigurationManager sCoreConfigurationManager; + if ( destroy ) { + sCoreConfigurationManager.reset(); + } else { + if ( !sCoreConfigurationManager ) + sCoreConfigurationManager = MakeUncheckedSharedPointer( new CoreConfigurationManagerImpl(), __FILE__, __LINE__, true ); + } + return sCoreConfigurationManager; + } + + void ICoreConfigurationManager_I::CreateCoreConfigurationManager() { + ManageCoreConfigurationManager(); + } + + void ICoreConfigurationManager_I::DestroyCoreConfigurationManager() { + ManageCoreConfigurationManager( true ); + } + +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + spICoreConfigurationManager ICoreConfigurationManager_v1::MakeShared( pICoreConfigurationManager_base ptr ) { + if ( !ptr ) return spICoreConfigurationManager(); + pICoreConfigurationManager p = ICoreConfigurationManager::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< ICoreConfigurationManager >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + + spICoreConfigurationManager ICoreConfigurationManager::GetCoreConfigurationManager() { + return AdobeXMPCore_Int::ManageCoreConfigurationManager(); + } +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB diff --git a/XMPCore/source/CoreObjectFactoryImpl.cpp b/XMPCore/source/CoreObjectFactoryImpl.cpp new file mode 100644 index 0000000..71fe1cc --- /dev/null +++ b/XMPCore/source/CoreObjectFactoryImpl.cpp @@ -0,0 +1,158 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/CoreObjectFactoryImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" + +#include "XMPCommon/Interfaces/IUTF8String_I.h" + +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCore/Interfaces/IPath_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/IStructureNode_I.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" +#include "XMPCore/Interfaces/ICoreConfigurationManager_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" + +#if ENABLE_CPP_DOM_MODEL + +namespace AdobeXMPCore_Int { + + pcIPathSegment_base APICALL CoreObjectFactoryImpl::CreateArrayIndexPathSegment( const char * nameSpace, sizet nameSpaceLength, sizet index, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< const IPathSegment, pcIPathSegment_base >( + &IPathSegment::CreateArrayIndexPathSegment, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, index ); + } + + pIArrayNode_base APICALL CoreObjectFactoryImpl::CreateArrayNode( uint32 arrayForm, const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + switch ( static_cast< IArrayNode::eArrayForm >( arrayForm ) ) { + case IArrayNode::kAFOrdered: + return ReturnRawPointerFromSharedPointer< IArrayNode, pIArrayNode_base >( + &IArrayNode::CreateOrderedArrayNode, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + break; + + case IArrayNode::kAFUnordered: + return ReturnRawPointerFromSharedPointer< IArrayNode, pIArrayNode_base >( + &IArrayNode::CreateUnorderedArrayNode, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + break; + + case IArrayNode::kAFAlternative: + return ReturnRawPointerFromSharedPointer< IArrayNode, pIArrayNode_base >( + &IArrayNode::CreateAlternativeArrayNode, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + break; + + } + return NULL; + } + + pIMetadata_base APICALL CoreObjectFactoryImpl::CreateMetadata( pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< IMetadata, pIMetadata_base >( + &IMetadata::CreateMetadata, error, __FILE__, __LINE__ ); + } + + pINameSpacePrefixMap_base APICALL CoreObjectFactoryImpl::CreateNameSpacePrefixMap( pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< INameSpacePrefixMap, pINameSpacePrefixMap_base >( + &INameSpacePrefixMap::CreateNameSpacePrefixMap, error, __FILE__, __LINE__ ); + } + + pIPath_base APICALL CoreObjectFactoryImpl::CreatePath( pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< IPath, pIPath_base >( + &IPath::CreatePath, error, __FILE__, __LINE__ ); + } + + pcIPathSegment_base APICALL CoreObjectFactoryImpl::CreatePropertyPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< const IPathSegment, pcIPathSegment_base >( + &IPathSegment::CreatePropertyPathSegment, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + pcIPathSegment_base APICALL CoreObjectFactoryImpl::CreateQualifierPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< const IPathSegment, pcIPathSegment_base >( + &IPathSegment::CreateQualifierPathSegment, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + pcIPathSegment_base APICALL CoreObjectFactoryImpl::CreateQualifierSelectorPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< const IPathSegment, pcIPathSegment_base >( + &IPathSegment::CreateQualifierSelectorPathSegment, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength, value, valueLength ); + } + + pISimpleNode_base APICALL CoreObjectFactoryImpl::CreateSimpleNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< ISimpleNode, pISimpleNode_base >( + &ISimpleNode::CreateSimpleNode, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength, value, valueLength ); + } + + pIStructureNode_base APICALL CoreObjectFactoryImpl::CreateStructureNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< IStructureNode, pIStructureNode_base >( + &IStructureNode::CreateStructureNode, error, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + pICoreConfigurationManager_base APICALL CoreObjectFactoryImpl::GetCoreConfigurationManager( pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< ICoreConfigurationManager, pICoreConfigurationManager_base >( + &ICoreConfigurationManager::GetCoreConfigurationManager, error, __FILE__, __LINE__ ); + } + + pIDOMImplementationRegistry_base CoreObjectFactoryImpl::GetDOMImplementationRegistry( pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< IDOMImplementationRegistry, pIDOMImplementationRegistry_base >( + &IDOMImplementationRegistry::GetDOMImplementationRegistry, error, __FILE__, __LINE__ ); + } + + pcINameSpacePrefixMap_base CoreObjectFactoryImpl::GetDefaultNameSpacePrefixMap( pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< const INameSpacePrefixMap, pcINameSpacePrefixMap_base >( + &INameSpacePrefixMap::GetDefaultNameSpacePrefixMap, error, __FILE__, __LINE__ ); + } + + pIPath_base CoreObjectFactoryImpl::ParsePath( const char * path, sizet pathLength, pcINameSpacePrefixMap_base map, pcIError_base & error ) __NOTHROW__ { + return ReturnRawPointerFromSharedPointer< IPath, pIPath_base, const char *, sizet, const spcINameSpacePrefixMap & >( + &IPath::ParsePath, error, __FILE__, __LINE__, path, pathLength, INameSpacePrefixMap::MakeShared( map ) ); + } + + pIError_base CoreObjectFactoryImpl::CreateError(uint32 domain, uint32 code, uint32 severity, pcIError_base & error) __NOTHROW__{ + return ReturnRawPointerFromSharedPointer< IError_I, pIError_base, IError::eErrorDomain, IError::eErrorCode, IError::eErrorSeverity >( + &IError_I::CreateError, error, __FILE__, __LINE__, static_cast< IError::eErrorDomain >( domain ), static_cast< IError::eErrorCode >( code ), static_cast< IError::eErrorSeverity >( severity ) ); + } + + pIUTF8String_base CoreObjectFactoryImpl::CreateUTF8String(const char * buf, sizet count, pcIError_base & error) __NOTHROW__{ + return ReturnRawPointerFromSharedPointer< IUTF8String, pIUTF8String_base >( + &IUTF8String_I::CreateUTF8String, error, __FILE__, (sizet) __LINE__, buf, count ); + } + + static pICoreObjectFactory ManageCoreObjectFactory( bool destroy = false ) { + static CoreObjectFactoryImpl coreObjectFactoryImplObj; + return &coreObjectFactoryImplObj; + } + +} + +namespace AdobeXMPCore { + + void ICoreObjectFactory_v1::SetupCoreObjectFactory() { + AdobeXMPCore_Int::ManageCoreObjectFactory(); + } + + pICoreObjectFactory ICoreObjectFactory_v1::GetCoreObjectFactory() { + return AdobeXMPCore_Int::ManageCoreObjectFactory(); + } + + void ICoreObjectFactory_v1::DestroyCoreObjectFactory() { + AdobeXMPCore_Int::ManageCoreObjectFactory( true ); + } +} +#endif +extern "C" XMP_PUBLIC AdobeXMPCore::pICoreObjectFactory_base WXMPMeta_GetXMPDOMFactoryInstance_1() { +#if ENABLE_CPP_DOM_MODEL + return AdobeXMPCore_Int::ManageCoreObjectFactory(); +#endif + + return NULL; +} diff --git a/XMPCore/source/DOMImplementationRegistryImpl.cpp b/XMPCore/source/DOMImplementationRegistryImpl.cpp new file mode 100644 index 0000000..2b520b5 --- /dev/null +++ b/XMPCore/source/DOMImplementationRegistryImpl.cpp @@ -0,0 +1,96 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/DOMImplementationRegistryImpl.h" + #include "XMPCore/ImplHeaders/RDFDOMParserImpl.h" + #include "XMPCore/ImplHeaders/RDFDOMSerializerImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/IDOMParser.h" +#include "XMPCore/Interfaces/IDOMSerializer.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + bool APICALL DOMImplementationRegistryImpl::RegisterParser( const char * key, const spcIDOMParser & parser ) { + spcIUTF8String keyStr( IUTF8String_I::CreateUTF8String( key, AdobeXMPCommon::npos ) ); + auto it = mParserMap.insert( std::pair< spcIUTF8String, spcIDOMParser >( keyStr, parser ) ); + return it.second; + } + + bool APICALL DOMImplementationRegistryImpl::RegisterSerializer( const char * key, const spcIDOMSerializer & serializer ) { + spcIUTF8String keyStr( IUTF8String_I::CreateUTF8String( key, AdobeXMPCommon::npos ) ); + auto it = mSerializerMap.insert( std::pair< spcIUTF8String, spcIDOMSerializer >( keyStr, serializer ) ); + return it.second; + } + + spIDOMParser APICALL DOMImplementationRegistryImpl::GetParser( const char * key ) const { + spcIUTF8String keyStr( IUTF8String_I::CreateUTF8String( key, AdobeXMPCommon::npos ) ); + auto it = mParserMap.find( keyStr ); + if ( it != mParserMap.end() ) { + return it->second->Clone(); + } + return spIDOMParser(); + } + + spIDOMSerializer APICALL DOMImplementationRegistryImpl::GetSerializer( const char * key ) const { + spcIUTF8String keyStr( IUTF8String_I::CreateUTF8String( key, AdobeXMPCommon::npos ) ); + auto it = mSerializerMap.find( keyStr ); + if ( it != mSerializerMap.end() ) { + return it->second->Clone(); + } + return spIDOMSerializer(); + } + + static spIDOMImplementationRegistry ManageDOMImplementationRegistry( bool destroy = false ) { + static spIDOMImplementationRegistry sDOMImplementationRegistry; + + if ( destroy ) { + if ( sDOMImplementationRegistry ) + sDOMImplementationRegistry.reset(); + return sDOMImplementationRegistry; + } + + if ( !sDOMImplementationRegistry ) { + DOMImplementationRegistryImpl * ptr = new DOMImplementationRegistryImpl(); + ptr->RegisterParser( "rdf", MakeUncheckedSharedPointer( new RDFDOMParserImpl(), __FILE__, __LINE__, true ) ); + ptr->RegisterSerializer( "rdf", MakeUncheckedSharedPointer( new RDFDOMSerializerImpl(), __FILE__, __LINE__, true ) ); + sDOMImplementationRegistry = MakeUncheckedSharedPointer( ptr, __FILE__, __LINE__, true ); + } + return sDOMImplementationRegistry; + } + + spIDOMImplementationRegistry IDOMImplementationRegistry_I::CreateDOMImplementationRegistry() { + return ManageDOMImplementationRegistry(); + } + + void IDOMImplementationRegistry_I::DestoryDOMImplementationRegistry() { + ManageDOMImplementationRegistry( true ); + } + +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + spIDOMImplementationRegistry IDOMImplementationRegistry_v1::MakeShared( pIDOMImplementationRegistry_base ptr ) { + if ( !ptr ) return spIDOMImplementationRegistry(); + pIDOMImplementationRegistry p = IDOMImplementationRegistry::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IDOMImplementationRegistry >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + + spIDOMImplementationRegistry IDOMImplementationRegistry::GetDOMImplementationRegistry() { + return AdobeXMPCore_Int::ManageDOMImplementationRegistry(); + } +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB diff --git a/XMPCore/source/DOMParserImpl.cpp b/XMPCore/source/DOMParserImpl.cpp new file mode 100644 index 0000000..d215b8c --- /dev/null +++ b/XMPCore/source/DOMParserImpl.cpp @@ -0,0 +1,325 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/DOMParserImpl.h" + #include "XMPCore/ImplHeaders/ClientDOMParserWrapperImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/INodeIterator.h" +#include "XMPCommon/Interfaces/ISharedMutex.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + DOMParserImpl::DOMParserImpl() + : mSharedMutex( ISharedMutex::CreateSharedMutex() ) { } + + spIDOMParser APICALL DOMParserImpl::Clone() const { + DOMParserImpl * cloned = clone(); + if ( cloned ) { + AutoSharedLock lock( mSharedMutex ); + cloned->mTreatKeyAsCaseInsensitiveCharBuffer = mTreatKeyAsCaseInsensitiveCharBuffer; + cloned->mAllowDifferentValueTypesForExistingEntries = mAllowDifferentValueTypesForExistingEntries; + if ( mKeysSet ) + cloned->mKeysSet = new KeysSet( mKeysSet->begin(), mKeysSet->end() ); + + if ( mKeyValueTypeMap ) + cloned->mKeyValueTypeMap = new keyValueTypeMap( mKeyValueTypeMap->begin(), mKeyValueTypeMap->end() ); + + for ( auto it = mMap.begin(), itEnd = mMap.end(); it != itEnd; ++it ) { + cloned->mMap[ it->first ] = it->second; + } + } + return MakeUncheckedSharedPointer( cloned, __FILE__, __LINE__, true ); + } + + spIMetadata APICALL DOMParserImpl::Parse( const char * buffer, sizet bufferLength ) { + auto node = ParseAsNode( buffer, bufferLength ); + if ( node ) { + switch ( node->GetNodeType() ) { + case INode::kNTSimple: + case INode::kNTArray: + { + spIMetadata meta = IMetadata::CreateMetadata(); + meta->AppendNode( node ); + return meta; + } + break; + + case INode::kNTStructure: + { + pIMetadata meta( NULL ); + try { + meta = node->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + if ( meta ) { + return MakeUncheckedSharedPointer( meta, __FILE__, __LINE__ ); + } else { + spIMetadata meta = IMetadata::CreateMetadata(); + meta->AppendNode( node ); + return meta; + } + } + break; + + default: + NOTIFY_ERROR( IError::kEDGeneral, kGECInternalFailure, "Unhandled situation occured", IError::kESOperationFatal, false, false ); + } + } + return spIMetadata(); + } + + static void AppendAsChildren( const spINode & contextNode, const spINode & parsedNode ) { + if ( !contextNode ) + NOTIFY_ERROR( IError::kEDParser, kPECInvalidContextNode, "Context Node is invalid", IError::kESOperationFatal, false, false ); + auto contextNodeType = contextNode->GetNodeType(); + if ( contextNodeType != INode::kNTStructure && contextNodeType != INode::kNTArray ) + NOTIFY_ERROR( IError::kEDParser, kPECContextNodeIsNonComposite, "Context Node is non composite", IError::kESOperationFatal, + true, static_cast< sizet >( contextNodeType ) ); + pICompositeNode compositeContextNode = contextNode->GetInterfacePointer< ICompositeNode >(); + pIMetadata meta( NULL ); + try { + meta = parsedNode->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + if ( meta ) { + auto it = meta->Iterator(); + while ( it ) { + auto childNode = it->GetNode(); + it = it->Next(); + childNode = meta->GetIMetadata_I()->RemoveNode( childNode->GetNameSpace(), childNode->GetName() ); + compositeContextNode->AppendNode( childNode ); + } + } else { + compositeContextNode->AppendNode( parsedNode ); + } + } + + static void ReplaceChildren( pIArrayNode contextArrayNode, const spINode & parsedNode ) { + contextArrayNode->Clear(); + pIMetadata meta( NULL ); + try { + meta = parsedNode->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + if ( meta ) { + auto it = meta->Iterator(); + while ( it ) { + auto childNode = it->GetNode(); + it = it->Next(); + childNode = meta->GetIMetadata_I()->RemoveNode( childNode->GetNameSpace(), childNode->GetName() ); + contextArrayNode->AppendNode( childNode ); + } + } else { + contextArrayNode->AppendNode( parsedNode ); + } + } + + static void ReplaceChildren( pIStructureNode contextStructureNode, const spINode & parsedNode ) { + pIMetadata meta( NULL ); + try { + meta = parsedNode->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + if ( meta ) { + auto it = meta->Iterator(); + while ( it ) { + auto childNode = it->GetNode(); + it = it->Next(); + childNode = meta->GetIMetadata_I()->RemoveNode( childNode->GetNameSpace(), childNode->GetName() ); + contextStructureNode->ReplaceNode( childNode ); + } + } else { + contextStructureNode->ReplaceNode( parsedNode ); + } + } + + static void ReplaceChildren( const spINode & contextNode, const spINode & parsedNode ) { + if ( !contextNode ) + NOTIFY_ERROR( IError::kEDParser, kPECInvalidContextNode, "Context Node is invalid", IError::kESOperationFatal, false, false ); + auto contextNodeType = contextNode->GetNodeType(); + if ( contextNodeType != INode::kNTStructure && contextNodeType != INode::kNTArray ) + NOTIFY_ERROR( IError::kEDParser, kPECContextNodeIsNonComposite, "Context Node is non composite", IError::kESOperationFatal, + true, static_cast< sizet >( contextNodeType ) ); + switch ( contextNodeType ) { + case INode::kNTArray: + ReplaceChildren( contextNode->GetInterfacePointer< IArrayNode >(), parsedNode ); + break; + + case INode::kNTStructure: + ReplaceChildren( contextNode->GetInterfacePointer< IStructureNode >(), parsedNode ); + break; + } + } + + static void AppendOrReplaceChildren( pIStructureNode contextStructureNode, const spINode & parsedNode ) { + pIMetadata meta( NULL ); + try { + meta = parsedNode->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + if ( meta ) { + auto it = meta->Iterator(); + while ( it ) { + auto childNode = it->GetNode(); + it = it->Next(); + childNode = meta->GetIMetadata_I()->RemoveNode( childNode->GetNameSpace(), childNode->GetName() ); + if ( contextStructureNode->GetIStructureNode_I()->GetNode( childNode->GetNameSpace(), childNode->GetName() ) ) + contextStructureNode->ReplaceNode( childNode ); + else + contextStructureNode->AppendNode( childNode ); + } + } else { + if ( contextStructureNode->GetIStructureNode_I()->GetNode( parsedNode->GetNameSpace(), parsedNode->GetName() ) ) + contextStructureNode->ReplaceNode( parsedNode ); + else + contextStructureNode->AppendNode( parsedNode ); + } + } + + static void AppendOrReplaceChildren( const spINode & contextNode, const spINode & parsedNode ) { + if ( !contextNode ) + NOTIFY_ERROR( IError::kEDParser, kPECInvalidContextNode, "Context Node is invalid", IError::kESOperationFatal, false, false ); + auto contextNodeType = contextNode->GetNodeType(); + if ( contextNodeType != INode::kNTStructure && contextNodeType != INode::kNTArray ) + NOTIFY_ERROR( IError::kEDParser, kPECContextNodeIsNonComposite, "Context Node is non composite", IError::kESOperationFatal, + true, static_cast< sizet >( contextNodeType ) ); + switch ( contextNodeType ) { + case INode::kNTArray: + ReplaceChildren( contextNode->GetInterfacePointer< IArrayNode >(), parsedNode ); + break; + + case INode::kNTStructure: + AppendOrReplaceChildren( contextNode->GetInterfacePointer< IStructureNode >(), parsedNode ); + break; + } + } + + static void InsertBefore( const spINode & contextNode, const spINode & parsedNode ) { + if ( !contextNode ) + NOTIFY_ERROR( IError::kEDParser, kPECInvalidContextNode, "Context Node is invalid", IError::kESOperationFatal, false, false ); + if ( !contextNode->IsArrayItem() ) + NOTIFY_ERROR( IError::kEDParser, kPECContextNodeParentIsNonArray, "Context Node's Parent is non array node", IError::kESOperationFatal, false, false ); + pIMetadata meta( NULL ); + try { + meta = parsedNode->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + pIArrayNode parentArrayNode = contextNode->GetINode_I()->GetRawParentPointer()->GetInterfacePointer< IArrayNode >(); + if ( meta ) { + auto it = meta->Iterator(); + while ( it ) { + auto childNode = it->GetNode(); + it = it->Next(); + childNode = meta->GetIMetadata_I()->RemoveNode( childNode->GetNameSpace(), childNode->GetName() ); + parentArrayNode->InsertNodeAtIndex( childNode, contextNode->GetIndex() ); + } + } else { + parentArrayNode->InsertNodeAtIndex( parsedNode, contextNode->GetIndex() ); + } + + } + + static void InsertAfter( const spINode & contextNode, const spINode & parsedNode ) { + if ( !contextNode ) + NOTIFY_ERROR( IError::kEDParser, kPECInvalidContextNode, "Context Node is invalid", IError::kESOperationFatal, false, false ); + if ( !contextNode->IsArrayItem() ) + NOTIFY_ERROR( IError::kEDParser, kPECContextNodeParentIsNonArray, "Context Node's Parent is non array node", IError::kESOperationFatal, false, false ); + pIMetadata meta( NULL ); + try { + meta = parsedNode->GetInterfacePointer< IMetadata >(); + } catch ( spcIError err ) { + meta = NULL; + } + pIArrayNode parentArrayNode = contextNode->GetINode_I()->GetRawParentPointer()->GetInterfacePointer< IArrayNode >(); + if ( meta ) { + auto it = meta->Iterator(); + sizet index = contextNode->GetIndex() + 1; + while ( it ) { + auto childNode = it->GetNode(); + it = it->Next(); + childNode = meta->GetIMetadata_I()->RemoveNode( childNode->GetNameSpace(), childNode->GetName() ); + parentArrayNode->InsertNodeAtIndex( childNode, index ); + index = childNode->GetIndex() + 1; + } + } else { + parentArrayNode->InsertNodeAtIndex( parsedNode, contextNode->GetIndex() + 1 ); + } + } + + static void ReplaceNode( spINode & node, const spINode & parsedNode ) { + if ( node && node->IsArrayItem() && node->GetNodeType() != parsedNode->GetNodeType() ) { + NOTIFY_ERROR( IError::kEDDataModel, kDMECArrayItemTypeDifferent, "node type is different than what currently array can hold", + IError_v1::kESOperationFatal, true, static_cast< sizet >( node->GetNodeType() ), true, static_cast< sizet >( parsedNode->GetNodeType() ) ); + } + node = parsedNode; + } + + void APICALL DOMParserImpl::ParseWithSpecificAction( const char * buffer, sizet bufferLength, eActionType actionType, spINode & node ) { + auto parsedNode = ParseAsNode( buffer, bufferLength ); + + if ( parsedNode ) { + switch ( actionType ) { + case kATAppendAsChildren: + AppendAsChildren( node, parsedNode ); + break; + + case kATReplaceChildren: + ReplaceChildren( node, parsedNode ); + break; + + case kATAppendOrReplaceChildren: + AppendOrReplaceChildren( node, parsedNode ); + break; + + case kATInsertBefore: + InsertBefore( node, parsedNode ); + break; + + case kATInsertAfter: + InsertAfter( node, parsedNode ); + break; + + case kATReplace: + ReplaceNode( node, parsedNode ); + break; + + default: + NOTIFY_ERROR( IError::kEDGeneral, kGECNotImplemented, "Not yet implemented", IError::kESOperationFatal, true, static_cast< sizet >( actionType ) ); + } + + } + } + + spISharedMutex APICALL DOMParserImpl::GetMutex() const { + return mSharedMutex; + } + + AdobeXMPCore::spIDOMParser IDOMParser_I::CreateDOMParser( pIClientDOMParser_base clientDOMParser ) { + return MakeUncheckedSharedPointer( new ClientDOMParserWrapperImpl( clientDOMParser ), __FILE__, __LINE__, true ); + } + + + void DOMParserImpl::SetErrorCallback(XMPMeta::ErrorCallbackInfo * ec) { + mGenericErrorCallbackPtr = ec; + } +} diff --git a/XMPCore/source/DOMSerializerImpl.cpp b/XMPCore/source/DOMSerializerImpl.cpp new file mode 100644 index 0000000..07da8dc --- /dev/null +++ b/XMPCore/source/DOMSerializerImpl.cpp @@ -0,0 +1,54 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/DOMSerializerImpl.h" + #include "XMPCore/ImplHeaders/ClientDOMSerializerWrapperImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/ISharedMutex.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + DOMSerializerImpl::DOMSerializerImpl() + : mSharedMutex( ISharedMutex::CreateSharedMutex() ) { } + + spISharedMutex APICALL DOMSerializerImpl::GetMutex() const { + return mSharedMutex; + } + + spIDOMSerializer APICALL DOMSerializerImpl::Clone() const { + DOMSerializerImpl * cloned = clone(); + if ( cloned ) { + AutoSharedLock lock( mSharedMutex ); + cloned->mTreatKeyAsCaseInsensitiveCharBuffer = mTreatKeyAsCaseInsensitiveCharBuffer; + cloned->mAllowDifferentValueTypesForExistingEntries = mAllowDifferentValueTypesForExistingEntries; + if ( mKeysSet ) + cloned->mKeysSet = new KeysSet( mKeysSet->begin(), mKeysSet->end() ); + + if ( mKeyValueTypeMap ) + cloned->mKeyValueTypeMap = new keyValueTypeMap( mKeyValueTypeMap->begin(), mKeyValueTypeMap->end() ); + + for ( auto it = mMap.begin(), itEnd = mMap.end(); it != itEnd; ++it ) { + cloned->mMap[ it->first ] = it->second; + } + } + return MakeUncheckedSharedPointer( cloned, __FILE__, __LINE__, true ); + } + + AdobeXMPCore::spIDOMSerializer IDOMSerializer_I::CreateDOMSerializer( pIClientDOMSerializer_base clientDOMSerializer ) { + return MakeUncheckedSharedPointer( new ClientDOMSerializerWrapperImpl( clientDOMSerializer ), __FILE__, __LINE__, true ); + } + + +} diff --git a/XMPCore/source/ExpatAdapter.cpp b/XMPCore/source/ExpatAdapter.cpp index 0d7813b..5fe0181 100644 --- a/XMPCore/source/ExpatAdapter.cpp +++ b/XMPCore/source/ExpatAdapter.cpp @@ -142,7 +142,7 @@ void ExpatAdapter::ParseBuffer ( const void * buffer, size_t length, bool last / length = 1; } - status = XML_Parse ( this->parser, (const char *)buffer, length, last ); + status = XML_Parse ( this->parser, (const char *)buffer, static_cast< XMP_StringLen >( length ), last ); #if BanAllEntityUsage if ( this->isAborted ) { @@ -275,7 +275,12 @@ 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) thiz->registeredNamespaces->Define ( uri, prefix, 0, 0 ); + if (thiz->registeredNamespaces == sRegisteredNamespaces) { + (void)XMPMeta::RegisterNamespace(uri, prefix, 0, 0); + } + else { + (void)thiz->registeredNamespaces->Define(uri, prefix, 0, 0); + } } // StartNamespaceDeclHandler diff --git a/XMPCore/source/IArrayNode_I.cpp b/XMPCore/source/IArrayNode_I.cpp new file mode 100644 index 0000000..b7099eb --- /dev/null +++ b/XMPCore/source/IArrayNode_I.cpp @@ -0,0 +1,85 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IArrayNode_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IArrayNode_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IArrayNode_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IArrayNode_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IArrayNode_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIArrayNodeID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IArrayNode_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else { + pvoid returnValue( NULL ); + returnValue = ICompositeNode_I::GetInterfacePointerInternal( interfaceID, interfaceVersion, false ); + if ( returnValue ) return returnValue; + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIArrayNodeID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + uint32 APICALL IArrayNode_I::getArrayForm( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< IArrayNode_v1, uint32, eArrayForm >( + error, this, 0, &IArrayNode_v1::GetArrayForm, __FILE__, __LINE__ ); + } + + uint32 APICALL IArrayNode_I::getChildNodeType( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< IArrayNode_v1, uint32, eNodeType >( + error, this, 0, &IArrayNode_v1::GetChildNodeType, __FILE__, __LINE__ ); + } + + pINode_base APICALL IArrayNode_I::getNodeAtIndex( sizet index, pcIError_base & error ) __NOTHROW__ { + typedef spINode( APICALL IArrayNode_v1::*Func )( sizet ); + Func fnPtr = &IArrayNode_v1::GetNodeAtIndex; + return CallUnSafeFunctionReturningSharedPointer< IArrayNode_v1, pINode_base, INode, sizet >( + error, this, fnPtr, __FILE__, __LINE__, index ); + } + + void APICALL IArrayNode_I::insertNodeAtIndex( pINode_base node, sizet index, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< IArrayNode_v1, const spINode &, sizet >( + error, this, &IArrayNode_v1::InsertNodeAtIndex, __FILE__, __LINE__, INode::MakeShared( node ), index ); + } + + pINode_base APICALL IArrayNode_I::removeNodeAtIndex( sizet index, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IArrayNode_v1, pINode_base, INode, sizet >( + error, this, &IArrayNode_v1::RemoveNodeAtIndex, __FILE__, __LINE__, index ); + } + + pINode_base APICALL IArrayNode_I::replaceNodeAtIndex( pINode_base node, sizet index, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IArrayNode_v1, pINode_base, INode, const spINode &, sizet >( + error, this, &IArrayNode_v1::ReplaceNodeAtIndex, __FILE__, __LINE__, INode::MakeShared( node ), index ); + } + +} diff --git a/XMPCore/source/ICompositeNode_I.cpp b/XMPCore/source/ICompositeNode_I.cpp new file mode 100644 index 0000000..b590058 --- /dev/null +++ b/XMPCore/source/ICompositeNode_I.cpp @@ -0,0 +1,92 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/ICompositeNode_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/Interfaces/IPath.h" +#include "XMPCore/Interfaces/INodeIterator.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL ICompositeNode_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL ICompositeNode_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< ICompositeNode_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &ICompositeNode_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL ICompositeNode_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kICompositeNodeID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< ICompositeNode_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else { + pvoid returnValue( NULL ); + returnValue = INode_I::GetInterfacePointerInternal( interfaceID, interfaceVersion, false ); + if ( returnValue ) return returnValue; + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kICompositeNodeID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + uint32 APICALL ICompositeNode_I::getNodeTypeAtPath( pcIPath_base path, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< ICompositeNode_v1, uint32, eNodeType, const spcIPath & >( + error, this, 0, &ICompositeNode_v1::GetNodeTypeAtPath, __FILE__, __LINE__, IPath_v1::MakeShared( path ) ); + } + + pINode_base APICALL ICompositeNode_I::getNodeAtPath( pcIPath_base path, pcIError_base & error ) __NOTHROW__ { + typedef spINode( APICALL ICompositeNode_v1::*Func )( const spcIPath & ); + Func fnPtr = &ICompositeNode_v1::GetNodeAtPath; + return CallUnSafeFunctionReturningSharedPointer< ICompositeNode_v1, pINode_base, INode, const spcIPath & >( + error, this, fnPtr, __FILE__, __LINE__, IPath_v1::MakeShared( path ) ); + } + + void APICALL ICompositeNode_I::appendNode( pINode_base node, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< ICompositeNode_v1, const spINode & >( + error, this, &ICompositeNode_v1::AppendNode, __FILE__, __LINE__, INode::MakeShared( node ) ); + } + + void APICALL ICompositeNode_I::insertNodeAtPath( pINode_base node, pcIPath_base path, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< ICompositeNode_v1, const spINode &, const spcIPath & >( + error, this, &ICompositeNode_v1::InsertNodeAtPath, __FILE__, __LINE__, INode::MakeShared( node ), IPath::MakeShared( path ) ); + } + + pINode_base APICALL ICompositeNode_I::replaceNodeAtPath( pINode_base node, pcIPath_base path, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< ICompositeNode_v1, pINode_base, INode, const spINode &, const spcIPath & >( + error, this, &ICompositeNode_v1::ReplaceNodeAtPath, __FILE__, __LINE__, INode_v1::MakeShared( node ), IPath_v1::MakeShared( path ) ); + } + + pINode_base APICALL ICompositeNode_I::removeNodeAtPath( pcIPath_base path, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< ICompositeNode_v1, pINode_base, INode, const spcIPath & >( + error, this, &ICompositeNode_v1::RemoveNodeAtPath, __FILE__, __LINE__, IPath_v1::MakeShared( path ) ); + } + + pINodeIterator_base APICALL ICompositeNode_I::iterator( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< ICompositeNode_v1, pINodeIterator_base, INodeIterator >( + error, this, &ICompositeNode_v1::Iterator, __FILE__, __LINE__ ); + } + +}
\ No newline at end of file diff --git a/XMPCore/source/ICoreConfigurationManager_I.cpp b/XMPCore/source/ICoreConfigurationManager_I.cpp new file mode 100644 index 0000000..27d6852 --- /dev/null +++ b/XMPCore/source/ICoreConfigurationManager_I.cpp @@ -0,0 +1,54 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/ICoreConfigurationManager_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL ICoreConfigurationManager_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL ICoreConfigurationManager_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< ICoreConfigurationManager_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &ICoreConfigurationManager_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL ICoreConfigurationManager_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kICoreConfigurationManagerID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< ICoreConfigurationManager_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else { + pvoid returnValue( NULL ); + returnValue = IConfigurationManager_I::GetInterfacePointerInternal( interfaceID, interfaceVersion, false ); + if ( returnValue ) return returnValue; + } + + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kICoreConfigurationManagerID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + +}
\ No newline at end of file diff --git a/XMPCore/source/ICoreObjectFactory_I.cpp b/XMPCore/source/ICoreObjectFactory_I.cpp new file mode 100644 index 0000000..ff2613a --- /dev/null +++ b/XMPCore/source/ICoreObjectFactory_I.cpp @@ -0,0 +1,62 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/ICoreObjectFactory_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL ICoreObjectFactory_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL ICoreObjectFactory_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< ICoreObjectFactory_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &ICoreObjectFactory_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL ICoreObjectFactory_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kICoreObjectFactoryID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< ICoreObjectFactory_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else if ( interfaceID == kIObjectFactoryID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IObjectFactory_v1 * >( this ); + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + + } + } + + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kICoreObjectFactoryID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + +}
\ No newline at end of file diff --git a/XMPCore/source/IDOMImplementationRegistry_I.cpp b/XMPCore/source/IDOMImplementationRegistry_I.cpp new file mode 100644 index 0000000..ef5b7ce --- /dev/null +++ b/XMPCore/source/IDOMImplementationRegistry_I.cpp @@ -0,0 +1,84 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/Interfaces/IDOMParser_I.h" +#include "XMPCore/Interfaces/IDOMSerializer_I.h" +#include <stdexcept> + +namespace AdobeXMPCore_Int { + + pvoid APICALL IDOMImplementationRegistry_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IDOMImplementationRegistry_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IDOMImplementationRegistry_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IDOMImplementationRegistry_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IDOMImplementationRegistry_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIDOMImplementationRegistryID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IDOMImplementationRegistry_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIDOMImplementationRegistryID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pIDOMParser_base APICALL IDOMImplementationRegistry_I::getParser( const char * key, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IDOMImplementationRegistry_v1, pIDOMParser_base, IDOMParser, const char * >( + error, this, &IDOMImplementationRegistry_v1::GetParser, __FILE__, __LINE__, key ); + } + + pIDOMSerializer_base APICALL IDOMImplementationRegistry_I::getSerializer( const char * key, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IDOMImplementationRegistry_v1, pIDOMSerializer_base, IDOMSerializer, const char * >( + error, this, &IDOMImplementationRegistry_v1::GetSerializer, __FILE__, __LINE__, key ); + } + + uint32 APICALL IDOMImplementationRegistry_I::registerParser( const char * key, pIClientDOMParser_base parser, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IDOMImplementationRegistry_I, uint32, bool, const char *, const spcIDOMParser & >( + error, this, 0, &IDOMImplementationRegistry_I::RegisterParser, __FILE__, __LINE__, key, IDOMParser_I::CreateDOMParser( parser ) ); + } + + uint32 APICALL IDOMImplementationRegistry_I::registerSerializer( const char * key, pIClientDOMSerializer_base serializer, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IDOMImplementationRegistry_I, uint32, bool, const char *, const spcIDOMSerializer & >( + error, this, 0, &IDOMImplementationRegistry_I::RegisterSerializer, __FILE__, __LINE__, key, IDOMSerializer_I::CreateDOMSerializer( serializer ) ); + } + + bool APICALL IDOMImplementationRegistry_I::RegisterParser(const char * key, pIClientDOMParser_base parser) { + + spcIDOMParser spParser = IDOMParser_I::CreateDOMParser(parser); + return RegisterParser(key, spParser); + } + + bool APICALL IDOMImplementationRegistry_I::RegisterSerializer(const char * key, pIClientDOMSerializer_base serializer) { + + spcIDOMSerializer spSerializer = IDOMSerializer_I::CreateDOMSerializer(serializer); + return RegisterSerializer(key, spSerializer); + } + +}
\ No newline at end of file diff --git a/XMPCore/source/IDOMParser_I.cpp b/XMPCore/source/IDOMParser_I.cpp new file mode 100644 index 0000000..cb231d8 --- /dev/null +++ b/XMPCore/source/IDOMParser_I.cpp @@ -0,0 +1,66 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IDOMParser_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/Interfaces/IMetadata.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IDOMParser_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IDOMParser_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IDOMParser_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IDOMParser_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IDOMParser_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIDOMParserID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IDOMParser_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIDOMParserID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pIDOMParser_base APICALL IDOMParser_I::clone( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IDOMParser_v1, pIDOMParser_base, IDOMParser >( + error, this, &IDOMParser_v1::Clone, __FILE__, __LINE__ ); + } + + pIMetadata_base APICALL IDOMParser_I::parse( const char * buffer, sizet bufferLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IDOMParser_v1, pIMetadata_base, IMetadata, const char *, sizet >( + error, this, &IDOMParser_v1::Parse, __FILE__, __LINE__, buffer, bufferLength ); + } + + void APICALL IDOMParser_I::parseWithSpecificAction( const char * buffer, sizet bufferLength, uint32 actionType, pINode_base node, pcIError_base & error ) __NOTHROW__ { + auto spNode = INode::MakeShared( node ); + return CallUnSafeFunctionReturningVoid< IDOMParser_v1, const char *, sizet, eActionType, spINode & >( + error, this, &IDOMParser_v1::ParseWithSpecificAction, __FILE__, __LINE__, buffer, bufferLength, static_cast< eActionType >( actionType ), spNode ); + } + +} diff --git a/XMPCore/source/IDOMSerializer_I.cpp b/XMPCore/source/IDOMSerializer_I.cpp new file mode 100644 index 0000000..104b7a5 --- /dev/null +++ b/XMPCore/source/IDOMSerializer_I.cpp @@ -0,0 +1,62 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IDOMSerializer_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/Interfaces/INode.h" +#include "XMPCommon/Interfaces/IUTF8String.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IDOMSerializer_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IDOMSerializer_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IDOMSerializer_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IDOMSerializer_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IDOMSerializer_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIDOMSerializerID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IDOMSerializer_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIDOMSerializerID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pIDOMSerializer_base APICALL IDOMSerializer_I::clone( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IDOMSerializer_v1, pIDOMSerializer_base, IDOMSerializer >( + error, this, &IDOMSerializer_v1::Clone, __FILE__, __LINE__ ); + } + + pIUTF8String_base APICALL IDOMSerializer_I::serialize( pINode_base node, pcINameSpacePrefixMap_base map, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IDOMSerializer_v1, pIUTF8String_base, IUTF8String, const spINode &, const spcINameSpacePrefixMap & >( + error, this, &IDOMSerializer_v1::Serialize, __FILE__, __LINE__, INode::MakeShared( node ), INameSpacePrefixMap::MakeShared( map ) ); + } + +}
\ No newline at end of file diff --git a/XMPCore/source/IMetadata_I.cpp b/XMPCore/source/IMetadata_I.cpp new file mode 100644 index 0000000..9ba8250 --- /dev/null +++ b/XMPCore/source/IMetadata_I.cpp @@ -0,0 +1,59 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IMetadata_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IMetadata_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IMetadata_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IMetadata_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IMetadata_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIMetadataID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IMetadata_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else { + pvoid returnValue( NULL ); + returnValue = IStructureNode_I::GetInterfacePointerInternal( interfaceID, interfaceVersion, false ); + if ( returnValue ) return returnValue; + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIMetadataID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pcIUTF8String_base APICALL IMetadata_I::getAboutURI( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IMetadata_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &IMetadata_v1::GetAboutURI, __FILE__, __LINE__ ); + } + +} diff --git a/XMPCore/source/INameSpacePrefixMap_I.cpp b/XMPCore/source/INameSpacePrefixMap_I.cpp new file mode 100644 index 0000000..68d7d09 --- /dev/null +++ b/XMPCore/source/INameSpacePrefixMap_I.cpp @@ -0,0 +1,84 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Interfaces/IUTF8String.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL INameSpacePrefixMap_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL INameSpacePrefixMap_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< INameSpacePrefixMap_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &INameSpacePrefixMap_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL INameSpacePrefixMap_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kINameSpacePrefixMapID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< INameSpacePrefixMap_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kINameSpacePrefixMapID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + uint32 APICALL INameSpacePrefixMap_I::insert( const char * prefix, sizet prefixLength, const char * nameSpace, sizet nameSpaceLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< INameSpacePrefixMap_v1, uint32, bool, const char *, sizet, const char *, sizet >( + error, this, 0, &INameSpacePrefixMap_v1::Insert, __FILE__, __LINE__, prefix, prefixLength, nameSpace, nameSpaceLength ); + } + + uint32 APICALL INameSpacePrefixMap_I::remove( uint32 keyType, const char * key, sizet keyLength, pcIError_base & error ) __NOTHROW__ { + typedef bool ( APICALL INameSpacePrefixMap_v1::*Func )( const char *, sizet ); + Func fnPtr = &INameSpacePrefixMap_v1::RemovePrefix; + if ( keyType == kNameSpaceIsParameter ) fnPtr = &INameSpacePrefixMap_v1::RemoveNameSpace; + return CallUnSafeFunction< INameSpacePrefixMap_v1, uint32, bool >( + error, this, 0, fnPtr, __FILE__, __LINE__, key, keyLength ); + } + + uint32 APICALL INameSpacePrefixMap_I::isPresent( uint32 keyType, const char * key, sizet keyLength, pcIError_base & error ) const __NOTHROW__ { + typedef bool ( APICALL INameSpacePrefixMap_v1::*Func )( const char *, sizet ) const; + Func fnPtr = &INameSpacePrefixMap_v1::IsPrefixPresent; + if ( keyType == kNameSpaceIsParameter ) fnPtr = &INameSpacePrefixMap_v1::IsNameSpacePresent; + return CallConstUnSafeFunction< INameSpacePrefixMap_v1, uint32, bool >( + error, this, 0, fnPtr, __FILE__, __LINE__, key, keyLength ); + } + + pcIUTF8String_base APICALL INameSpacePrefixMap_I::get( uint32 keyType, const char * key, sizet keyLength, pcIError_base & error ) const __NOTHROW__ { + typedef spcIUTF8String ( APICALL INameSpacePrefixMap_v1::*Func )( const char *, sizet ) const; + Func fnPtr = &INameSpacePrefixMap_v1::GetNameSpace; + if ( keyType == kNameSpaceIsParameter ) fnPtr = &INameSpacePrefixMap_v1::GetPrefix; + return CallConstUnSafeFunctionReturningSharedPointer< INameSpacePrefixMap_v1, pcIUTF8String_base, const IUTF8String >( + error, this, fnPtr, __FILE__, __LINE__, key, keyLength ); + } + + pINameSpacePrefixMap_base APICALL INameSpacePrefixMap_I::clone( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< INameSpacePrefixMap_v1, pINameSpacePrefixMap_base, INameSpacePrefixMap >( + error, this, &INameSpacePrefixMap_v1::Clone, __FILE__, __LINE__ ); + } + +} diff --git a/XMPCore/source/INodeIterator_I.cpp b/XMPCore/source/INodeIterator_I.cpp new file mode 100644 index 0000000..0867c9a --- /dev/null +++ b/XMPCore/source/INodeIterator_I.cpp @@ -0,0 +1,78 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/INodeIterator_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL INodeIterator_I::GetInterfacePointer(uint64 interfaceID, uint32 interfaceVersion) { + return GetInterfacePointerInternal(interfaceID, interfaceVersion, true); + } + + pvoid APICALL INodeIterator_I::getInterfacePointer(uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error) __NOTHROW__{ + return CallUnSafeFunction< INodeIterator_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &INodeIterator_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion); + } + + pvoid APICALL INodeIterator_I::GetInterfacePointerInternal(uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel) { + if (interfaceID == kINodeIteratorID) { + switch (interfaceVersion) { + case 1: + return static_cast< INodeIterator_v1 * >(this); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__); + break; + } + } + if (isTopLevel) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kINodeIteratorID, interfaceID, __FILE__, __LINE__); + return NULL; + } + + + pINode_base APICALL INodeIterator_I::getNode( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INodeIterator_v1, pINode_base, INode >( + error, this, &INodeIterator_v1::GetNode, __FILE__, __LINE__ ); + } + + uint32 APICALL INodeIterator_I::getNodeType( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INodeIterator_v1, uint32, INode_v1::eNodeType >( + error, this, 0, &INodeIterator_v1::GetNodeType, __FILE__, __LINE__ ); + } + + pINodeIterator_base APICALL INodeIterator_I::next( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INodeIterator_v1, pINodeIterator, INodeIterator >( + error, this, &INodeIterator_v1::Next, __FILE__, __LINE__ ); + } + +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + spINodeIterator INodeIterator_v1::MakeShared( pINodeIterator_base ptr ) { + if ( !ptr ) return spINodeIterator(); + pINodeIterator p = INodeIterator::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< INodeIterator >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB + diff --git a/XMPCore/source/INode_I.cpp b/XMPCore/source/INode_I.cpp new file mode 100644 index 0000000..003be46 --- /dev/null +++ b/XMPCore/source/INode_I.cpp @@ -0,0 +1,183 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/INode_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Interfaces/IUTF8String.h" +#include "XMPCore/Interfaces/IPath.h" +#include "XMPCore/Interfaces/ISimpleNode.h" +#include "XMPCore/Interfaces/IMetadata.h" +#include "XMPCore/Interfaces/IArrayNode.h" +#include "XMPCore/Interfaces/INodeIterator.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL INode_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL INode_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< INode_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &INode_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL INode_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kINodeID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< INode_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kINodeID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pINode_base APICALL INode_I::getParent( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pINode_base, INode >( + error, this, &INode_v1::GetParent, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::getParentNodeType( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, eNodeType >( + error, this, 0, &INode_v1::GetParentNodeType, __FILE__, __LINE__ ); + } + + void APICALL INode_I::setName( const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< INode_v1, const char *, sizet >( + error, this, &INode_v1::SetName, __FILE__, __LINE__, name, nameLength ); + } + + pcIUTF8String_base APICALL INode_I::getName( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< INode_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &INode_v1::GetName, __FILE__, __LINE__ ); + } + + void APICALL INode_I::setNameSpace( const char * nameSpace, sizet nameSpaceLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< INode_v1, const char *, sizet >( + error, this, &INode_v1::SetNameSpace, __FILE__, __LINE__, nameSpace, nameSpaceLength ); + + } + + pcIUTF8String_base APICALL INode_I::getNameSpace( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< INode_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &INode_v1::GetNameSpace, __FILE__, __LINE__ ); + } + + pIPath_base APICALL INode_I::getPath( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< INode_v1, pIPath_base, IPath >( + error, this, &INode_v1::GetPath, __FILE__, __LINE__ ); + } + + pINodeIterator_base APICALL INode_I::qualifiersIterator( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pINodeIterator_base, INodeIterator >( + error, this, &INode_v1::QualifiersIterator, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::getQualifierNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, eNodeType, const char *, sizet, const char *, sizet >( + error, this, 0, &INode_v1::GetQualifierNodeType, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + pINode_base APICALL INode_I::getQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + typedef spINode( APICALL INode_v1::*Func )( const char *, sizet, const char *, sizet ); + Func fnPtr = &INode_v1::GetQualifier; + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pINode_base, INode, const char *, sizet, const char *, sizet >( + error, this, fnPtr, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + void APICALL INode_I::insertQualifier( pINode_base base, pcIError_base & error ) __NOTHROW__ { + CallUnSafeFunctionReturningVoid< INode_v1, const spINode & >( error, this, &INode_v1::InsertQualifier, __FILE__, __LINE__, INode_v1::MakeShared( base ) ); + } + + pINode_base APICALL INode_I::replaceQualifier( pINode_base node, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pINode_base, INode, const spINode & >( + error, this, &INode_v1::ReplaceQualifier, __FILE__, __LINE__, INode_v1::MakeShared( node ) ); + } + + pINode_base APICALL INode_I::removeQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pINode_base, INode, const char *, sizet, const char *, sizet >( + error, this, &INode_v1::RemoveQualifier, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + uint32 APICALL INode_I::getNodeType( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, eNodeType >( error, this, 0, &INode_v1::GetNodeType, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::isArrayItem( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, bool>( error, this, 0, &INode_v1::IsArrayItem, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::isQualifierNode( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, bool >( error, this, 0, &INode_v1::IsQualifierNode, __FILE__, __LINE__ ); + } + + sizet APICALL INode_I::getIndex( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, sizet, sizet >( error, this, 0, &INode_v1::GetIndex, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::hasQualifiers( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, bool>( error, this, 0, &INode_v1::HasQualifiers, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::hasContent( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, bool>( error, this, 0, &INode_v1::HasContent, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::isEmpty( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, bool>( error, this, 0, &INode_v1::IsEmpty, __FILE__, __LINE__ ); + } + + uint32 APICALL INode_I::hasChanged( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< INode_v1, uint32, bool>( error, this, 0, &INode_v1::HasChanged, __FILE__, __LINE__ ); + } + + void APICALL INode_I::clear( uint32 contents, uint32 qualifiers, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< INode_v1, bool, bool >( error, this, &INode_v1::Clear, __FILE__, __LINE__, contents != 0, qualifiers != 0 ); + } + + pINode_base APICALL INode_I::clone( uint32 igoreEmptyNodes, uint32 ignoreNodesWithOnlyQualifiers, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< INode_v1, pINode_base, INode, bool, bool >( + error, this, &INode_v1::Clone, __FILE__, __LINE__, igoreEmptyNodes != 0, ignoreNodesWithOnlyQualifiers != 0 ); + } + + pISimpleNode_base APICALL INode_I::convertToSimpleNode( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pISimpleNode_base, ISimpleNode >( + error, this, &INode_v1::ConvertToSimpleNode, __FILE__, __LINE__ ); + } + + pIStructureNode_base APICALL INode_I::convertToStructureNode( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pIStructureNode_base, IStructureNode >( + error, this, &INode_v1::ConvertToStructureNode, __FILE__, __LINE__ ); + } + + pIArrayNode_base APICALL INode_I::convertToArrayNode( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pIArrayNode_base, IArrayNode >( + error, this, &INode_v1::ConvertToArrayNode, __FILE__, __LINE__ ); + } + + pIMetadata_base APICALL INode_I::convertToMetadata( pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< INode_v1, pIMetadata_base, IMetadata >( + error, this, &INode_v1::ConvertToMetadata, __FILE__, __LINE__ ); + } + +}
\ No newline at end of file diff --git a/XMPCore/source/IPathSegment_I.cpp b/XMPCore/source/IPathSegment_I.cpp new file mode 100644 index 0000000..c94adb6 --- /dev/null +++ b/XMPCore/source/IPathSegment_I.cpp @@ -0,0 +1,70 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Interfaces/IUTF8String.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IPathSegment_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IPathSegment_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IPathSegment_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IPathSegment_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IPathSegment_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIPathSegmentID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IPathSegment_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIPathSegmentID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pcIUTF8String_base APICALL IPathSegment_I::getNameSpace( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IPathSegment_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &IPathSegment_v1::GetNameSpace, __FILE__, __LINE__ ); + } + + pcIUTF8String_base APICALL IPathSegment_I::getName( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IPathSegment_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &IPathSegment_v1::GetName, __FILE__, __LINE__ ); + } + + uint32 APICALL IPathSegment_I::getType( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< IPathSegment_v1, uint32, ePathSegmentType >( + error, this, 0, &IPathSegment_v1::GetType, __FILE__, __LINE__ ); + } + + pcIUTF8String_base APICALL IPathSegment_I::getValue( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IPathSegment_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &IPathSegment_v1::GetValue, __FILE__, __LINE__ ); + } + +}
\ No newline at end of file diff --git a/XMPCore/source/IPath_I.cpp b/XMPCore/source/IPath_I.cpp new file mode 100644 index 0000000..d66d641 --- /dev/null +++ b/XMPCore/source/IPath_I.cpp @@ -0,0 +1,82 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IPath_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap.h" +#include "XMPCore/Interfaces/IPathSegment.h" +#include "XMPCommon/Interfaces/IUTF8String.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IPath_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IPath_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IPath_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IPath_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IPath_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIPathID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IPath_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIPathID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pcINameSpacePrefixMap_base APICALL IPath_I::registerNameSpacePrefixMap( pcINameSpacePrefixMap_base map, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IPath_v1, pcINameSpacePrefixMap_base, const INameSpacePrefixMap, const spcINameSpacePrefixMap & >( + error, this, &IPath_v1::RegisterNameSpacePrefixMap, __FILE__, __LINE__, INameSpacePrefixMap::MakeShared( map ) ); + } + + pIUTF8String_base APICALL IPath_I::serialize( pcINameSpacePrefixMap_base map, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IPath_v1, pIUTF8String_base, IUTF8String, const spcINameSpacePrefixMap & >( + error, this, &IPath_v1::Serialize, __FILE__, __LINE__, INameSpacePrefixMap::MakeShared( map ) ); + } + + void APICALL IPath_I::appendPathSegment( pcIPathSegment_base segment, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< IPath_v1, const spcIPathSegment &>( + error, this, &IPath_v1::AppendPathSegment, __FILE__, __LINE__, IPathSegment::MakeShared( segment ) ); + } + + pcIPathSegment_base APICALL IPath_I::removePathSegment( sizet index, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IPath_v1, pcIPathSegment_base, const IPathSegment, sizet >( + error, this, &IPath_v1::RemovePathSegment, __FILE__, __LINE__, index ); + } + + pcIPathSegment_base APICALL IPath_I::getPathSegment( sizet index, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IPath_v1, pcIPathSegment_base, const IPathSegment, sizet >( + error, this, &IPath_v1::GetPathSegment, __FILE__, __LINE__, index ); + } + + pIPath_base APICALL IPath_I::clone( sizet startingIndex, sizet countOfSegemetns, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< IPath_v1, pIPath_base, IPath, sizet, sizet >( + error, this, &IPath_v1::Clone, __FILE__, __LINE__, startingIndex, countOfSegemetns ); + } + +} diff --git a/XMPCore/source/ISimpleNode_I.cpp b/XMPCore/source/ISimpleNode_I.cpp new file mode 100644 index 0000000..6e2ff34 --- /dev/null +++ b/XMPCore/source/ISimpleNode_I.cpp @@ -0,0 +1,74 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Interfaces/IUTF8String.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL ISimpleNode_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL ISimpleNode_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< ISimpleNode_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &ISimpleNode_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL ISimpleNode_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + pvoid returnValue( NULL ); + if ( interfaceID == kISimpleNodeID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< ISimpleNode_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else { + returnValue = INode_I::GetInterfacePointerInternal( interfaceID, interfaceVersion, false ); + if ( returnValue ) return returnValue; + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kISimpleNodeID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pcIUTF8String_base APICALL ISimpleNode_I::getValue( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunctionReturningSharedPointer< ISimpleNode_v1, pcIUTF8String_base, const IUTF8String >( + error, this, &ISimpleNode_v1::GetValue, __FILE__, __LINE__ ); + } + + void APICALL ISimpleNode_I::setValue( const char * value, sizet valueLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< ISimpleNode_v1, const char *, sizet >( + error, this, &ISimpleNode_v1::SetValue, __FILE__, __LINE__, value, valueLength ); + } + + uint32 APICALL ISimpleNode_I::isURIType( pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< ISimpleNode_v1, uint32, bool >( + error, this, 0, &ISimpleNode_v1::IsURIType, __FILE__, __LINE__ ); + } + + void APICALL ISimpleNode_I::setURIType( uint32 isURI, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< ISimpleNode_v1, bool >( + error, this, &ISimpleNode_v1::SetURIType, __FILE__, __LINE__, isURI != 0 ); + } + +} diff --git a/XMPCore/source/IStructureNode_I.cpp b/XMPCore/source/IStructureNode_I.cpp new file mode 100644 index 0000000..b07bcec --- /dev/null +++ b/XMPCore/source/IStructureNode_I.cpp @@ -0,0 +1,78 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "XMPCore/Interfaces/IStructureNode_I.h" +#include "XMPCommon/Utilities/TWrapperFunctions_I.h" +#include "XMPCommon/Interfaces/IError_I.h" + +namespace AdobeXMPCore_Int { + + pvoid APICALL IStructureNode_I::GetInterfacePointer( uint64 interfaceID, uint32 interfaceVersion ) { + return GetInterfacePointerInternal( interfaceID, interfaceVersion, true ); + } + + pvoid APICALL IStructureNode_I::getInterfacePointer( uint64 interfaceID, uint32 interfaceVersion, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunction< IStructureNode_I, pvoid, pvoid, uint64, uint32 >( + error, this, NULL, &IStructureNode_I::GetInterfacePointer, __FILE__, __LINE__, interfaceID, interfaceVersion ); + } + + pvoid APICALL IStructureNode_I::GetInterfacePointerInternal( uint64 interfaceID, uint32 interfaceVersion, bool isTopLevel ) { + if ( interfaceID == kIStructureNodeID ) { + switch ( interfaceVersion ) { + case 1: + return static_cast< IStructureNode_v1 * >( this ); + break; + + case kInternalInterfaceVersionNumber: + return this; + break; + + default: + throw IError_I::CreateInterfaceVersionNotAvailableError( + IError_v1::kESOperationFatal, interfaceID, interfaceVersion, __FILE__, __LINE__ ); + break; + } + } else { + pvoid returnValue( NULL ); + returnValue = ICompositeNode_I::GetInterfacePointerInternal( interfaceID, interfaceVersion, false ); + if ( returnValue ) return returnValue; + } + if ( isTopLevel ) + throw IError_I::CreateInterfaceNotAvailableError( + IError_v1::kESOperationFatal, kIStructureNodeID, interfaceID, __FILE__, __LINE__ ); + return NULL; + } + + pINode_base APICALL IStructureNode_I::getNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IStructureNode_v1, pINode_base, INode, const char *, sizet, const char *, sizet >( + error, this, &IStructureNode_v1::GetNode, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + uint32 APICALL IStructureNode_I::getChildNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) const __NOTHROW__ { + return CallConstUnSafeFunction< IStructureNode_v1, uint32, eNodeType, const char *, sizet, const char *, sizet >( + error, this, 0, &IStructureNode_v1::GetChildNodeType, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + void APICALL IStructureNode_I::insertNode( pINode_base node, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningVoid< IStructureNode_v1, const spINode & >( + error, this, &IStructureNode_v1::InsertNode, __FILE__, __LINE__, INode::MakeShared( node ) ); + } + + pINode_base APICALL IStructureNode_I::removeNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IStructureNode_v1, pINode_base, INode, const char *, sizet, const char *, sizet >( + error, this, &IStructureNode_v1::RemoveNode, __FILE__, __LINE__, nameSpace, nameSpaceLength, name, nameLength ); + } + + pINode_base APICALL IStructureNode_I::replaceNode( pINode_base node, pcIError_base & error ) __NOTHROW__ { + return CallUnSafeFunctionReturningSharedPointer< IStructureNode_v1, pINode_base, INode, const spINode & >( + error, this, &IStructureNode_v1::ReplaceNode, __FILE__, __LINE__, INode::MakeShared( node ) ); + } + +} diff --git a/XMPCore/source/MetadataImpl.cpp b/XMPCore/source/MetadataImpl.cpp new file mode 100644 index 0000000..f1c659b --- /dev/null +++ b/XMPCore/source/MetadataImpl.cpp @@ -0,0 +1,445 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/MetadataImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/INodeIterator_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/source/XMPCore_Impl.hpp" + +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" +#include "XMPCommon/Utilities/UTF8String.h" + +#include <assert.h> + +namespace AdobeXMPCore_Int { + static const char * kMetadataNameSpace( "http://metadata" ); + static const AdobeXMPCommon::sizet kMetadataNameSpaceLength( 15 ); + static const char * kMetadataLocalName( "_metadata_" ); + static const AdobeXMPCommon::sizet kMetadataLocalNameLength( 10 ); + + MetadataImpl::MetadataImpl() + : StructureNodeImpl( kMetadataNameSpace, kMetadataNameSpaceLength, kMetadataLocalName, kMetadataLocalNameLength ) + , NodeImpl( kMetadataNameSpace, kMetadataNameSpaceLength, kMetadataLocalName, kMetadataLocalNameLength ) + , mAboutURI( IUTF8String_I::CreateUTF8String() ) + , mSupportAliases( false ) { } + + spcIUTF8String APICALL MetadataImpl::GetAboutURI() const { + AutoSharedLock lock( mSharedMutex ); + return mAboutURI; + } + + void APICALL MetadataImpl::SetAboutURI( const char * uri, sizet uriLength ) __NOTHROW__ { + AutoSharedLock lock( mSharedMutex, true ); + mAboutURI->assign( uri, uriLength ); + } + + spcIUTF8String APICALL MetadataImpl::GetName() const { + return IUTF8String_I::CreateUTF8String(); + } + + spcIUTF8String APICALL MetadataImpl::GetNameSpace() const { + return IUTF8String_I::CreateUTF8String(); + } + + spINode APICALL MetadataImpl::GetParent() { + return spINode(); + } + + INode::eNodeType APICALL MetadataImpl::GetParentNodeType() const { + return INode::kNTNone; + } + + void APICALL MetadataImpl::SetName( const char * name, sizet nameLength ) { + return; + } + + void APICALL MetadataImpl::SetNameSpace( const char * nameSpace, sizet nameSpaceLength ) { + return; + } + + void APICALL MetadataImpl::ClearContents() { + StructureNodeImpl::ClearContents(); + { + AutoSharedLock lock( mSharedMutex, true ); + mAboutURI->clear(); + } + } + + spINode APICALL MetadataImpl::CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const { + spIMetadata newNode = IMetadata::CreateMetadata(); + auto endIt = mChildrenMap.end(); + for ( auto it = mChildrenMap.begin(); it != endIt; ++it ) { + spINode childNode = it->second->Clone( ignoreEmptyNodes, ignoreNodesWithOnlyQualifiers ); + if ( childNode ) { + newNode->AppendNode( childNode ); + } + } + newNode->SetAboutURI( mAboutURI->c_str(), mAboutURI->size() ); + return newNode; + } + + spIMetadata APICALL MetadataImpl::ConvertToMetadata() { + return MakeUncheckedSharedPointer( this, __FILE__, __LINE__ ); + } + + void APICALL MetadataImpl::EnableFeature( const char * key, sizet keyLength ) const __NOTHROW__ { + UTF8String keyStr( key, keyLength ); + if ( keyStr.compare( "alias" ) == 0 ) + mSupportAliases = true; + } + + void APICALL MetadataImpl::DisableFeature( const char * key, sizet keyLength ) const __NOTHROW__ { + UTF8String keyStr( key, keyLength ); + if ( keyStr.compare( "alias" ) == 0 ) + mSupportAliases = false; + } + + bool IsNodeAlias( const char * nameSpace, const char * name, XMP_ExpandedXPath & exPath ) { + spIUTF8String qualName = IUTF8String_I::CreateUTF8String(); + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + spcIUTF8String prefixStr = defaultMap->GetPrefix( nameSpace, AdobeXMPCommon::npos ); + if ( !prefixStr ) { + return false; + } + + qualName->append( prefixStr )->append( ":", AdobeXMPCommon::npos )->append( name, AdobeXMPCommon::npos ); + + bool aliasFound = sRegisteredAliasMap->count( qualName->c_str() ) > 0; + if ( aliasFound ) { + exPath = ( *sRegisteredAliasMap )[ qualName->c_str() ]; + return aliasFound; + } + return aliasFound; + } + + bool HandleConstAlias( const spIMetadata & meta, spINode & destNode, const XMP_ExpandedXPath & expandedXPath, sizet & nodeIndex ) { + if ( expandedXPath.empty() ) NOTIFY_ERROR( IError::kEDGeneral, kGECLogicalError, "Empty XPath", IError::kESOperationFatal, false, false ); + + if ( !( expandedXPath[ kSchemaStep ].options & kXMP_SchemaNode ) ) { + return false; + } else { + XMP_VarString namespaceName = expandedXPath[ kSchemaStep ].step.c_str(); + size_t colonPos = expandedXPath[ kRootPropStep ].step.find( ":" ); + assert( colonPos != std::string::npos ); + XMP_VarString propertyName = expandedXPath[ kRootPropStep ].step.substr( colonPos + 1 ); + + // here find the node with this name + destNode = meta->GetNode( namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if ( !destNode ) return false; + if ( expandedXPath.size() == 2 ) return true; + assert( destNode->GetNodeType() == INode::kNTArray ); + + if ( expandedXPath[ 2 ].options == kXMP_ArrayIndexStep ) { + assert( expandedXPath[ 2 ].step == "[1]" ); + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + auto actualNodeType = destNode->GetNodeType(); + if ( destNode ) { + if ( nodeIndex ) nodeIndex = 1; + return true; + } + return false; + } else if ( expandedXPath[ 2 ].options == kXMP_QualSelectorStep ) { + assert( expandedXPath[ 2 ].step == "[?xml:lang=\"x-default\"]" ); + if ( !destNode || destNode->GetNodeType() != INode::kNTArray ) return false; + spINodeIterator iter = destNode->ConvertToArrayNode()->Iterator(); + sizet index = 1; + while ( iter ) { + spINode node = iter->GetNode(); + try { + spISimpleNode qualNode = node->GetSimpleQualifier( "http://www.w3.org/XML/1998/namespace", AdobeXMPCommon::npos, "lang", AdobeXMPCommon::npos ); + if ( qualNode->GetValue()->compare( "x-default" ) == 0 ) { + destNode = node; + if ( nodeIndex ) nodeIndex = index; + return true; + } + } catch ( spcIError err ) { + + } catch ( ... ) {} + index++; + iter = iter->Next(); + } + return false; + } + return false; + } + } + + spINode CreateTerminalNode( const char* nameSpace, const char * name, XMP_OptionBits options, const spcINode & nodeToBeCloned = spINode() ) { + + spINode newNode; + if ( nodeToBeCloned ) { + newNode = nodeToBeCloned->Clone(); + } + + else if ( XMP_PropIsSimple( options ) ) { + newNode = ISimpleNode::CreateSimpleNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + } else if ( XMP_PropIsStruct( options ) ) { + newNode = IStructureNode_v1::CreateStructureNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + } else if ( XMP_PropIsArray( options ) ) { + if ( options & kXMP_PropArrayIsAltText ) + newNode = IArrayNode_v1::CreateAlternativeArrayNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + else if ( options & kXMP_PropArrayIsOrdered ) + newNode = IArrayNode_v1::CreateOrderedArrayNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + else + newNode = IArrayNode_v1::CreateUnorderedArrayNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + } + return newNode; + } + + bool HandleNonConstAlias( const spIMetadata & meta, XMP_ExpandedXPath & expandedXPath, bool createNodes, XMP_OptionBits leafOptions, spINode & destNode, sizet & nodeIndex, bool ignoreLastStep, const spINode & inputNode ) { + destNode = meta; + spcIUTF8String inputNodeValue; + if ( inputNode && inputNode->GetNodeType() == INode::kNTSimple ) { + + inputNodeValue = inputNode->ConvertToSimpleNode()->GetValue(); + } + bool isAliasBeingCreated = expandedXPath.size() == 2; + if ( expandedXPath.empty() ) + NOTIFY_ERROR( IError::kEDDataModel, kDMECBadXPath, "Empty XPath", IError::kESOperationFatal, false, false ); + if ( !( expandedXPath[ kSchemaStep ].options & kXMP_SchemaNode ) ) { + return false; + } else { + XMP_VarString namespaceName = expandedXPath[ kSchemaStep ].step.c_str(); + size_t colonPos = expandedXPath[ kRootPropStep ].step.find( ":" ); + assert( colonPos != std::string::npos ); + XMP_VarString propertyName = expandedXPath[ kRootPropStep ].step.substr( colonPos + 1 ); + spcINode childNode = meta->GetNode( namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if ( !childNode && !createNodes ) return false; + if ( expandedXPath.size() == 2 ) { + if ( childNode ) return true; + XMP_OptionBits createOptions = 0; + spINode tempNode; + if ( isAliasBeingCreated ) tempNode = CreateTerminalNode( namespaceName.c_str(), propertyName.c_str(), leafOptions ); + else tempNode = CreateTerminalNode( namespaceName.c_str(), propertyName.c_str(), createOptions ); + if ( !tempNode ) return false; + if ( inputNodeValue ) tempNode->ConvertToSimpleNode()->SetValue( inputNodeValue->c_str(), inputNodeValue->size() ); + if ( destNode == meta ) { + meta->InsertNode( tempNode ); + } else { + destNode->ConvertToStructureNode()->AppendNode( tempNode ); + } + destNode = tempNode; + if ( destNode ) return true; + return false; + } + + XMP_Assert( expandedXPath.size() == 3 ); + if ( expandedXPath[ 2 ].options == kXMP_ArrayIndexStep ) { + XMP_Assert( expandedXPath[ 2 ].step == "[1]" ); + destNode = meta->GetNode( namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if ( !destNode && !createNodes ) return false; + if ( !destNode ) { + spINode arrayNode = CreateTerminalNode( namespaceName.c_str(), propertyName.c_str(), kXMP_PropArrayIsOrdered | kXMP_PropValueIsArray ); + meta->AppendNode( arrayNode ); + destNode = arrayNode; + } + + if ( destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ) ) { + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + if ( nodeIndex ) nodeIndex = 1; + return true; + } else { + spISimpleNode indexNode = ISimpleNode::CreateSimpleNode( namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if ( inputNodeValue ) { + indexNode->SetValue( inputNodeValue->c_str(), inputNodeValue->size() ); + } + destNode->ConvertToArrayNode()->InsertNodeAtIndex( indexNode, 1 ); + destNode = indexNode; + return true; + } + return false; + } else if ( expandedXPath[ 2 ].options == kXMP_QualSelectorStep ) { + assert( expandedXPath[ 2 ].step == "[?xml:lang=\"x-default\"]" ); + destNode = meta->GetNode( namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if ( !destNode && !createNodes ) return false; + spINode arrayNode = CreateTerminalNode( namespaceName.c_str(), propertyName.c_str(), kXMP_PropValueIsArray | kXMP_PropArrayIsAltText); + meta->AppendNode( arrayNode ); + destNode = arrayNode; + auto iter = destNode->ConvertToArrayNode()->Iterator(); + XMP_Index index = 1; + while ( iter ) { + spINode node = iter->GetNode(); + spINode qualNode = node->GetQualifier( "http://www.w3.org/XML/1998/namespace", AdobeXMPCommon::npos, "lang", AdobeXMPCommon::npos ); + if ( qualNode->GetNodeType() == INode::kNTSimple ) { + if ( !qualNode->ConvertToSimpleNode()->GetValue()->compare( "x-default" ) ) { + destNode = node; + if ( nodeIndex ) nodeIndex = index; + return true; + } + } + index++; + iter = iter->Next(); + } + spISimpleNode qualifierNode = ISimpleNode::CreateSimpleNode( "http://www.w3.org/XML/1998/namespace", AdobeXMPCommon::npos, "lang", AdobeXMPCommon::npos, "x-default", AdobeXMPCommon::npos ); + if ( destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ) ) { + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + if ( nodeIndex ) nodeIndex = 1; + destNode->InsertQualifier( qualifierNode ); + return true; + } else { + spISimpleNode indexNode = ISimpleNode::CreateSimpleNode( namespaceName.c_str(), AdobeXMPCommon::npos, propertyName.c_str(), AdobeXMPCommon::npos ); + if ( inputNodeValue ) { + indexNode->SetValue( inputNodeValue->c_str(), inputNodeValue->size() ); + } + destNode->ConvertToArrayNode()->InsertNodeAtIndex( indexNode, 1 ); + destNode->InsertQualifier( qualifierNode ); + destNode = indexNode; + return true; + } + } + } + return false; + } + + + spINode APICALL MetadataImpl::ReplaceNode( const spINode & node ) { + if ( mSupportAliases ) { + XMP_ExpandedXPath exPath; + QualifiedName qName( node->GetNameSpace(), node->GetName() ); + bool nodeIsAlias = IsNodeAlias( node->GetNameSpace()->c_str(), node->GetName()->c_str(), exPath ); + if ( nodeIsAlias ) { + spINode actualNodeToBeRemoved; + sizet nodeIndex = 0; + auto spSelf = MakeUncheckedSharedPointer( this, __FILE__, __LINE__, false ); + if ( HandleConstAlias( spSelf, actualNodeToBeRemoved, exPath, nodeIndex ) ) { + qName = QualifiedName( actualNodeToBeRemoved->GetNameSpace(), actualNodeToBeRemoved->GetName() ); + } + } + + if ( CheckSuitabilityToBeUsedAsChildNode( node ) && GetNode( qName.mNameSpace, qName.mName ) ) { + auto retValue = RemoveNode( qName.mNameSpace, qName.mName ); + spINode destNode = node; + if ( nodeIsAlias ) { + sizet destNodeIndex = 0; + auto spSelf = MakeUncheckedSharedPointer( this, __FILE__, __LINE__, false ); + if ( !HandleNonConstAlias( spSelf, exPath, true, 0, destNode, destNodeIndex, false, node ) ) { + return destNode; + } + } + InsertNode( destNode ); + return retValue; + } else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNoSuchNodeExists, + "no such node exists with the specified qualified name", IError_v1::kESOperationFatal, + true, node->GetNameSpace(), true, node->GetName() ); + } + return spINode(); + } else { + return StructureNodeImpl::ReplaceNode( node ); + } + } + + void APICALL MetadataImpl::InsertNode( const spINode & node ) { + + if ( mSupportAliases ) { + if ( !node ) return; + XMP_ExpandedXPath exPath; + if ( IsNodeAlias( node->GetNameSpace()->c_str(), node->GetName()->c_str(), exPath ) ) { + + spINode destNode; + sizet destNodeIndex = 0; + AutoSharedLock lock( mSharedMutex, true ); + auto spSelf = MakeUncheckedSharedPointer(this, __FILE__, __LINE__, false); + if ( HandleNonConstAlias( spSelf, exPath, true, 0, destNode, destNodeIndex, false, node ) ) { + } + } else { + + return StructureNodeImpl::InsertNode( node ); + } + } else { + return StructureNodeImpl::InsertNode( node ); + } + + return; + } + + spINode APICALL MetadataImpl::RemoveNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + if ( mSupportAliases ) { + XMP_ExpandedXPath exPath; + if (IsNodeAlias(nameSpace->c_str(), name->c_str(), exPath)) { + spINode destNode; + sizet destNodeIndex = 0; + auto spSelf = MakeUncheckedSharedPointer(this, __FILE__, __LINE__, false); + AutoSharedLock lock(mSharedMutex, true); + /*if (!HandleConstAlias(spSelf, destNode, exPath, destNodeIndex)) { + destNode = spINode(); + } + return destNode;*/ + if (!HandleConstAlias(spSelf, destNode, exPath, destNodeIndex)) { + destNode = spINode(); + return destNode; + } + else + { + return StructureNodeImpl::RemoveNode(destNode->GetNameSpace(), destNode->GetName()); + } + + + } + else { + + //return StructureNodeImpl::GetNode(nameSpace, name); + return StructureNodeImpl::RemoveNode(nameSpace, name); + } + + } else { + return StructureNodeImpl::RemoveNode( nameSpace, name ); + } + } + + spINode APICALL MetadataImpl::GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + if ( mSupportAliases ) { + XMP_ExpandedXPath exPath; + if (IsNodeAlias(nameSpace->c_str(), name->c_str(), exPath)) { + spINode destNode; + sizet destNodeIndex = 0; + AutoSharedLock lock(mSharedMutex, true); + auto spSelf = MakeUncheckedSharedPointer(this, __FILE__, __LINE__, false); + if (!HandleConstAlias(spSelf, destNode, exPath, destNodeIndex)) { + destNode = spINode(); + } + return destNode; + } + else { + + return StructureNodeImpl::GetNode(nameSpace, name); + } + + } else { + return StructureNodeImpl::GetNode( nameSpace, name ); + } + } + +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + + spIMetadata IMetadata::CreateMetadata() { + return MakeUncheckedSharedPointer( new MetadataImpl(), __FILE__, __LINE__, true ); + } + + spIMetadata IMetadata_v1::MakeShared( pIMetadata_base ptr ) { + if ( !ptr ) return spIMetadata(); + pIMetadata p = IMetadata::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IMetadata >() : ptr; + return XMP_COMPONENT_INT_NAMESPACE::MakeUncheckedSharedPointer( p, __FILE__, __LINE__, true ); + } + +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB diff --git a/XMPCore/source/NameSpacePrefixMapImpl.cpp b/XMPCore/source/NameSpacePrefixMapImpl.cpp new file mode 100644 index 0000000..f95967e --- /dev/null +++ b/XMPCore/source/NameSpacePrefixMapImpl.cpp @@ -0,0 +1,311 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2015 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/NameSpacePrefixMapImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +#include "source/XMP_LibUtils.hpp" +#include "source/UnicodeInlines.incl_cpp" + +#include "XMPCore/XMPCoreErrorCodes.h" +#include <cstring> + +namespace AdobeXMPCore_Int { + + static sizet ActualLength( const char * parameter, sizet length ) { + if ( length == npos && parameter ) return strlen( parameter ); + return length; + } + + static bool VerifyParameters( bool prefixPresent, bool nameSpacePresent, const spcIUTF8String & prefix, const spcIUTF8String & nameSpace ) { + bool allOk = true; + if ( prefixPresent ) { + if ( !prefix ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "prefix is NULL", false, false ); + allOk = false; + } else { + if ( prefix->size() == 0) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "prefixLength is 0", false, false ); + allOk = false; + } + } + } + + if ( nameSpacePresent ) { + if ( !nameSpace ) { + if ( !nameSpace ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "nameSpace is NULL", false, false ); + allOk = false; + } else { + if ( nameSpace->size() == 0 ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "nameSpaceLength is 0", false, false ); + allOk = false; + } + } + } + } + + return allOk; + } + + static bool VerifyParameters( bool prefixPresent, bool nameSpacePresent, const char * prefix, const char * nameSpace, sizet prefixLength, sizet nameSpaceLength ) { + bool allOk = true; + if ( prefixPresent ) { + if ( !prefix ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "prefix is NULL", true, ( void * ) prefix ); + allOk = false; + } else { + if ( prefixLength == npos ) prefixLength = strlen( prefix ); + if ( prefixLength == 0 ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "prefixLength is 0", true, prefixLength ); + allOk = false; + } + } + } + + if ( nameSpacePresent ) { + if ( !nameSpace ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "nameSpace is NULL", true, ( void * ) nameSpace ); + allOk = false; + } else { + if ( nameSpaceLength == npos ) nameSpaceLength = strlen( nameSpace ); + if ( nameSpaceLength == 0 ) { + NOTIFY_WARNING( IError_v1::kEDGeneral, kGECParametersNotAsExpected, "nameSpaceLength is 0", true, nameSpaceLength ); + allOk = false; + } + } + } + + return allOk; + } + + NameSpacePrefixMapImpl::NameSpacePrefixMapImpl() {} + + // All virtual functions + bool APICALL NameSpacePrefixMapImpl::Insert( const char * prefix, sizet prefixLength, const char * nameSpace, sizet nameSpaceLength ) { + if ( VerifyParameters( true, true, prefix, nameSpace, prefixLength, nameSpaceLength ) ) { + prefixLength = ActualLength( prefix, prefixLength ); + nameSpaceLength = ActualLength( nameSpace, nameSpaceLength ); + try { + VerifySimpleXMLName( prefix, prefix + prefixLength ); + } catch ( ... ) { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECBadXPath, "prefix is not a valid XML Name", IError_v1::kESOperationFatal, true, prefix ); + return false; + } + spcIUTF8String prefixStr = IUTF8String_I::CreateUTF8String( prefix, prefixLength ); + spcIUTF8String nameSpaceStr = IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ); + + AutoSharedLock( mSharedMutex, true ); + + // remove old entries + if ( mPrefixToNameSpaceMap.find( prefixStr ) != mPrefixToNameSpaceMap.end() ) { + spcIUTF8String oldValue = mPrefixToNameSpaceMap[ prefixStr ]; + mPrefixToNameSpaceMap.erase( prefixStr ); + mNameSpaceToPrefixMap.erase( oldValue ); + } + + if ( mNameSpaceToPrefixMap.find( nameSpaceStr ) != mNameSpaceToPrefixMap.end() ) { + spcIUTF8String oldValue = mNameSpaceToPrefixMap[ nameSpaceStr ]; + mPrefixToNameSpaceMap.erase( oldValue ); + mNameSpaceToPrefixMap.erase( nameSpaceStr ); + } + + mNameSpaceToPrefixMap[ nameSpaceStr ] = prefixStr; + mPrefixToNameSpaceMap[ prefixStr ] = nameSpaceStr; + return true; + } + return false; + } + + bool APICALL NameSpacePrefixMapImpl::RemovePrefix( const char * prefix, sizet prefixLength ) { + if ( VerifyParameters( true, false, prefix, NULL, prefixLength, 0 ) ) { + spcIUTF8String prefixStr = IUTF8String_I::CreateUTF8String( prefix, prefixLength ); + AutoSharedLock lock( mSharedMutex, true ); + if ( mPrefixToNameSpaceMap.find( prefixStr ) != mPrefixToNameSpaceMap.end() ) { + spcIUTF8String nameSpaceStr = mPrefixToNameSpaceMap[ prefixStr ]; + mPrefixToNameSpaceMap.erase( prefixStr ); + mNameSpaceToPrefixMap.erase( nameSpaceStr ); + return true; + } + } + return false; + } + + bool APICALL NameSpacePrefixMapImpl::RemoveNameSpace( const char * nameSpace, sizet nameSpaceLength ) { + if ( VerifyParameters( false, true, NULL, nameSpace, 0, nameSpaceLength ) ) { + spcIUTF8String nameSpaceStr = IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ); + AutoSharedLock lock( mSharedMutex, true ); + if ( mNameSpaceToPrefixMap.find( nameSpaceStr ) != mNameSpaceToPrefixMap.end() ) { + spcIUTF8String prefixStr = mNameSpaceToPrefixMap[ nameSpaceStr ]; + mPrefixToNameSpaceMap.erase( prefixStr ); + mNameSpaceToPrefixMap.erase( nameSpaceStr ); + return true; + } + } + return false; + } + + bool APICALL NameSpacePrefixMapImpl::IsPrefixPresent( const char * prefix, sizet prefixLength ) const { + if ( VerifyParameters( true, false, prefix, NULL, prefixLength, 0 ) ) { + spcIUTF8String prefixStr = IUTF8String_I::CreateUTF8String( prefix, prefixLength ); + AutoSharedLock lock( mSharedMutex, true ); + return mPrefixToNameSpaceMap.find( prefixStr ) != mPrefixToNameSpaceMap.end(); + } + return false; + } + + bool APICALL NameSpacePrefixMapImpl::IsNameSpacePresent( const char * nameSpace, sizet nameSpaceLength ) const { + if ( VerifyParameters( false, true, NULL, nameSpace, 0, nameSpaceLength ) ) { + spcIUTF8String nameSpaceStr = IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ); + AutoSharedLock lock( mSharedMutex, true ); + return mNameSpaceToPrefixMap.find( nameSpaceStr ) != mNameSpaceToPrefixMap.end(); + } + return false; + } + + spcIUTF8String APICALL NameSpacePrefixMapImpl::GetNameSpace( const char * prefix, sizet prefixLength ) const { + if ( VerifyParameters( true, false, prefix, NULL, prefixLength, 0 ) ) { + spcIUTF8String prefixStr = IUTF8String_I::CreateUTF8String( prefix, prefixLength ); + AutoSharedLock lock( mSharedMutex, true ); + auto it = mPrefixToNameSpaceMap.find( prefixStr ); + if ( it != mPrefixToNameSpaceMap.end() ) + return it->second; + } + return spcIUTF8String(); + } + + spcIUTF8String APICALL NameSpacePrefixMapImpl::GetNameSpace( const spcIUTF8String & prefix ) const { + if ( VerifyParameters( true, false, prefix, spcIUTF8String() ) ) { + AutoSharedLock lock( mSharedMutex, true ); + auto it = mPrefixToNameSpaceMap.find( prefix ); + if ( it != mPrefixToNameSpaceMap.end() ) + return it->second; + } + return spcIUTF8String(); + } + + spcIUTF8String APICALL NameSpacePrefixMapImpl::GetPrefix( const char * nameSpace, sizet nameSpaceLength ) const { + if ( VerifyParameters( false, true, NULL, nameSpace, 0, nameSpaceLength ) ) { + spcIUTF8String nameSpaceStr = IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ); + AutoSharedLock lock( mSharedMutex, true ); + auto it = mNameSpaceToPrefixMap.find( nameSpaceStr ); + if ( it != mNameSpaceToPrefixMap.end() ) + return it->second; + } + return spcIUTF8String(); + } + + spcIUTF8String APICALL NameSpacePrefixMapImpl::GetPrefix( const spcIUTF8String & nameSpace ) const { + if ( VerifyParameters( false, true, spcIUTF8String(), nameSpace ) ) { + AutoSharedLock lock( mSharedMutex, true ); + auto it = mNameSpaceToPrefixMap.find( nameSpace ); + if ( it != mNameSpaceToPrefixMap.end() ) + return it->second; + } + return spcIUTF8String(); + } + + sizet APICALL NameSpacePrefixMapImpl::Size() const __NOTHROW__ { + AutoSharedLock lock( mSharedMutex, false ); + return mNameSpaceToPrefixMap.size(); + } + + void APICALL NameSpacePrefixMapImpl::Clear() __NOTHROW__ { + AutoSharedLock lock( mSharedMutex, true ); + mNameSpaceToPrefixMap.clear(); + mPrefixToNameSpaceMap.clear(); + } + + spINameSpacePrefixMap APICALL NameSpacePrefixMapImpl::Clone() const { + NameSpacePrefixMapImpl * ptr = new NameSpacePrefixMapImpl(); + if ( !ptr ) + NOTIFY_ERROR( IError_v1::kEDMemoryManagement, kMMECAllocationFailure, "Unable to allocate required memory", IError_v1::kESProcessFatal, false, false ); + AutoSharedLock lock( mSharedMutex, false ); + + // Replacing the shallow copy with deep copy + auto iterator = mPrefixToNameSpaceMap.begin(); + while ( iterator != mPrefixToNameSpaceMap.end() ) { + ptr->mPrefixToNameSpaceMap[ iterator->first ] = iterator->second; + iterator++; + } + + iterator = mNameSpaceToPrefixMap.begin(); + while ( iterator != mNameSpaceToPrefixMap.end() ) { + ptr->mNameSpaceToPrefixMap[ iterator->first ] = iterator->second; + iterator++; + } + + return MakeUncheckedSharedPointer( ptr, __FILE__, __LINE__ ); + } + + void APICALL NameSpacePrefixMapImpl::Merge( const spcINameSpacePrefixMap & otherMap ) { + if ( otherMap ) { + const NameSpacePrefixMapImpl * otherMapPtr = dynamic_cast< const NameSpacePrefixMapImpl * >( otherMap.get() ); + for (auto it = otherMapPtr->mPrefixToNameSpaceMap.begin(), itEnd = otherMapPtr->mPrefixToNameSpaceMap.end(); it != itEnd; ++it) { + Insert( it->first->c_str(), it->first->size(), it->second->c_str(), it->second->size() ); + } + } + } + + // All static functions of _I class. + + static spINameSpacePrefixMap ManageDefaultNameSpacePrefixMap( bool destroy = false ) { + static spINameSpacePrefixMap sDefaultNameSpacePrefixMap; + if ( destroy ) { + sDefaultNameSpacePrefixMap.reset(); + } else { + if ( !sDefaultNameSpacePrefixMap ) { + sDefaultNameSpacePrefixMap = INameSpacePrefixMap_I::CreateNameSpacePrefixMap(); + sDefaultNameSpacePrefixMap->EnableThreadSafety(); + } + } + return sDefaultNameSpacePrefixMap; + } + + void INameSpacePrefixMap_I::CreateDefaultNameSpacePrefixMap() { + ManageDefaultNameSpacePrefixMap( false ); + } + + void INameSpacePrefixMap_I::DestroyDefaultNameSapcePrefixMap() { + ManageDefaultNameSpacePrefixMap( true ); + } + + bool INameSpacePrefixMap_I::InsertInDefaultNameSpacePrefixMap( const char * prefix, sizet prefixLength, const char * nameSpace, sizet nameSpaceLength ) { + return ManageDefaultNameSpacePrefixMap( false )->Insert( prefix, prefixLength, nameSpace, nameSpaceLength ); + } +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB + +namespace AdobeXMPCore { + using AdobeXMPCore_Int::MakeUncheckedSharedPointer; + + spINameSpacePrefixMap INameSpacePrefixMap_v1::CreateNameSpacePrefixMap() { + return MakeUncheckedSharedPointer( new AdobeXMPCore_Int::NameSpacePrefixMapImpl(), __FILE__, __LINE__, true ); + } + + spcINameSpacePrefixMap INameSpacePrefixMap_v1::GetDefaultNameSpacePrefixMap() { + return AdobeXMPCore_Int::ManageDefaultNameSpacePrefixMap( false ); + } + + spINameSpacePrefixMap INameSpacePrefixMap_v1::MakeShared( pINameSpacePrefixMap_base ptr ) { + if ( !ptr ) return spINameSpacePrefixMap(); + pINameSpacePrefixMap p = INameSpacePrefixMap::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< INameSpacePrefixMap >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } +} + +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB + diff --git a/XMPCore/source/NodeImpl.cpp b/XMPCore/source/NodeImpl.cpp new file mode 100644 index 0000000..46375cc --- /dev/null +++ b/XMPCore/source/NodeImpl.cpp @@ -0,0 +1,479 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/NodeImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" +#include "XMPCore/Interfaces/IPath.h" +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCore/Interfaces/IStructureNode_I.h" + +#include "source/XMP_LibUtils.hpp" +#include "source/UnicodeInlines.incl_cpp" +#include <cstring> +#include <algorithm> + +namespace AdobeXMPCore_Int { + + // All virtual functions + static bool VerifyNameSpace( const char * nameSpace, sizet nameSpaceLength ) { + if ( ( nameSpace == NULL ) || ( nameSpaceLength == 0 ) || ( nameSpaceLength == AdobeXMPCommon::npos && strlen( nameSpace ) == 0 ) ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECParametersNotAsExpected, + "nameSpace can't be null or empty", IError_v1::kESOperationFatal, + true, ( void * ) nameSpace, true, nameSpaceLength, nameSpace, nameSpace ); + return false; + } + return true; + } + + static bool VerifyName( const char * name, sizet nameLength ) { + if ( ( name == NULL ) || ( nameLength == 0 ) || ( nameLength == AdobeXMPCommon::npos && strlen( name ) == 0 ) ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECParametersNotAsExpected, + "name can't be null or empty", IError_v1::kESOperationFatal, + true, ( void * ) name, true, nameLength, name, name ); + return false; + } + if ( nameLength == AdobeXMPCommon::npos ) nameLength = strlen( name ); + try { + if ( nameLength != 2 && strncmp( name, "[]", 2 ) != 0 ) + VerifySimpleXMLName( name, name + nameLength ); + } catch ( ... ) { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECBadXPath, + "name is not a valid XML Name", IError_base::kESOperationFatal, + true, name ); + return false; + } + return true; + } + + static spcIPathSegment CreatePathSegmentToParent( pcINode node ) { + if ( node->IsQualifierNode() ) { + return IPathSegment_I::CreateQualifierPathSegment( node->GetNameSpace(), node->GetName() ); + } + if ( node->IsArrayItem() ) { + return IPathSegment_I::CreateArrayIndexPathSegment( node->GetNameSpace(), node->GetIndex() ); + } + return IPathSegment_I::CreatePropertyPathSegment( node->GetNameSpace(), node->GetName() ); + } + + static const char * kQualifierNodeNameSpace( "http://qualifiers" ); + static const AdobeXMPCommon::sizet kQualifiersNodeNameSpaceLength( 17 ); + static const char * kQualifierNodeLocalName( "_qualifiers_" ); + static const AdobeXMPCommon::sizet kQualifierNodeLocalNameLength( 12 ); + + NodeImpl::NodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) + : mNameSpace( IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ) ) + , mName( IUTF8String_I::CreateUTF8String( name, nameLength ) ) + , mIndex( 0 ) + , mpParent( NULL ) + , mspParent() + , mChangeCount( 0 ) + , mIsQualifierNode( false ) + { + VerifyNameSpace( nameSpace, nameSpaceLength ); + VerifyName( name, nameLength ); + } + + void APICALL NodeImpl::ChangeParent( pINode parent ) { + AutoSharedLock lock( mSharedMutex, true ); + if ( mspParent ) { + if ( mspParent.get() == parent ) { + return; + } else { + mspParent.reset(); + if ( mChangeCount > 1 ) { + mpParent->GetINode_I()->UnRegisterChange(); + if ( parent ) parent->GetINode_I()->RegisterChange(); + } + mpParent = parent; + updateParentSharedPointer(); + } + } else { + if ( mChangeCount > 1 ) { + if ( mpParent ) mpParent->GetINode_I()->UnRegisterChange(); + if ( parent ) parent->GetINode_I()->RegisterChange(); + } + if ( parent ) parent->GetINode_I()->RegisterChange(); + mpParent = parent; + updateParentSharedPointer(); + } + + if ( !mpParent ) { + mIsQualifierNode = false; + mIndex = 0; + } + } + + pINode APICALL NodeImpl::GetRawParentPointer() { + AutoSharedLock lock( mSharedMutex ); + return mpParent; + } + + spINode APICALL NodeImpl::GetParent() { + AutoSharedLock lock( mSharedMutex ); + if ( mpParent ) { + if ( mIsQualifierNode ) + return MakeUncheckedSharedPointer( mpParent->GetINode_I()->GetRawParentPointer(), __FILE__, __LINE__ ); + else + return MakeUncheckedSharedPointer( mpParent, __FILE__, __LINE__ ); + } + else + return spINode(); + } + + void APICALL NodeImpl::SetName( const char * name, sizet nameLength ) { + if ( VerifyName( name, nameLength ) ) { + spIUTF8String newName = IUTF8String_I::CreateUTF8String( name, nameLength ); + if ( mName->compare( newName ) == 0 ) return; + if ( mpParent ) { + if ( mpParent->GetINode_I()->ValidateNameOrNameSpaceChangeForAChild( mNameSpace, mName, mNameSpace, newName ) ) { + AutoSharedLock( mSharedMutex, true ); + mName = newName; + RegisterChange(); + } else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNodeAlreadyExists, + "One of the sibling have same name and nameSpace combination", IError_v1::kESOperationFatal, + true, mNameSpace->c_str(), true, mName->c_str(), true, mNameSpace->c_str(), true, newName->c_str() ); + } + } else { + AutoSharedLock( mSharedMutex, true ); + mName = newName; + RegisterChange(); + } + } + } + + spcIUTF8String APICALL NodeImpl::GetName() const { + if ( this->IsArrayItem() ) + return mpParent->GetName(); + AutoSharedLock lock( mSharedMutex ); + return mName; + } + + void APICALL NodeImpl::SetNameSpace( const char * nameSpace, sizet nameSpaceLength ) { + if ( VerifyNameSpace( nameSpace, nameSpaceLength ) ) { + spIUTF8String newNameSpace = IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ); + if ( mNameSpace->compare( newNameSpace ) == 0 ) return; + if ( mpParent ) { + if ( mpParent->GetINode_I()->ValidateNameOrNameSpaceChangeForAChild( mNameSpace, mName, newNameSpace, mName ) ) { + AutoSharedLock( mSharedMutex, true ); + mNameSpace = newNameSpace; + RegisterChange(); + } else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNodeAlreadyExists, + "One of the sibling have same name and nameSpace combination", IError_v1::kESOperationFatal, + true, mNameSpace->c_str(), true, mName->c_str(), true, newNameSpace->c_str(), true, mName->c_str() ); + } + } else { + AutoSharedLock( mSharedMutex, true ); + mNameSpace = newNameSpace; + RegisterChange(); + } + } + } + + spcIUTF8String APICALL NodeImpl::GetNameSpace() const { + if ( this->IsArrayItem() ) + return( mpParent->GetNameSpace() ); + AutoSharedLock lock( mSharedMutex ); + return mNameSpace; + } + + spIPath APICALL NodeImpl::GetPath() const { + typedef std::vector< pcINode, TAllocator< pcINode > > pcINodeList; + pcINodeList pathToParent; + + pcINode node = this; + + while ( node != NULL ) { + pcINode_I node_I = node->GetINode_I(); + if ( node_I->IsQualifierNode() ) { + node = node_I->GetRawParentPointer(); + continue; + } + pathToParent.push_back( node ); + node = node_I->GetRawParentPointer(); + } + + // reverse the array + std::reverse( pathToParent.begin(), pathToParent.end() ); + spIPath xmpPath = IPath::CreatePath(); + pcINode parent = NULL; + + sizet nElements = pathToParent.size(); + for ( sizet i = 0; i < nElements; i++ ) { + if ( pathToParent[ i ]->GetINode_I()->GetRawParentPointer() == NULL ) { + continue; + } + + spcIPathSegment segment = CreatePathSegmentToParent( pathToParent[ i ] ); + + if ( segment ) { + xmpPath->AppendPathSegment( segment ); + } + + parent = pathToParent[ i ]; + } + return xmpPath; + } + + spINode APICALL NodeImpl::GetQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + { + AutoSharedLock lock( mSharedMutex ); + if ( !mQualifiers ) return spINode(); + } + return mQualifiers->GetNode( nameSpace, nameSpaceLength, name, nameLength ); + } + + spINode APICALL NodeImpl::GetQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + { + AutoSharedLock lock( mSharedMutex ); + if ( !mQualifiers ) return spINode(); + } + return mQualifiers->GetIStructureNode_I()->GetNode( nameSpace, name ); + } + + void APICALL NodeImpl::InsertQualifier( const spINode & node ) { + CreateQualifierNode(); + mQualifiers->InsertNode( node ); + node->GetINode_I()->SetIsQualifierNode( true ); + } + + spINode APICALL NodeImpl::ReplaceQualifier( const spINode & node ) { + CreateQualifierNode(); + auto retValue = mQualifiers->ReplaceNode( node ); + node->GetINode_I()->SetIsQualifierNode( true ); + return retValue; + } + + spINode APICALL NodeImpl::RemoveQualifier( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + CreateQualifierNode(); + return mQualifiers->RemoveNode( nameSpace, nameSpaceLength, name, nameLength ); + } + + spINode APICALL NodeImpl::RemoveQualifier( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + CreateQualifierNode(); + return mQualifiers->GetIStructureNode_I()->RemoveQualifier( nameSpace, name ); + } + + bool APICALL NodeImpl::IsArrayItem() const { + AutoSharedLock lock( mSharedMutex ); + return mIndex > 0; + } + + bool APICALL NodeImpl::HasQualifiers() const { + { + AutoSharedLock lock( mSharedMutex ); + if ( !mQualifiers ) return false; + } + return mQualifiers->ChildCount() > 0; + } + + bool APICALL NodeImpl::IsEmpty() const { + return !HasContent() && !HasQualifiers(); + } + + bool APICALL NodeImpl::HasChanged() const { + return mChangeCount != 0; + } + + void APICALL NodeImpl::AcknowledgeChanges() const __NOTHROW__ { + { + AutoSharedLock lock( mSharedMutex ); + if ( mChangeCount > 1 && mpParent ) + mpParent->GetINode_I()->UnRegisterChange(); + } + + resetChangesForChildren(); + + { + AutoSharedLock lock( mSharedMutex ); + if ( mQualifiers ) + mQualifiers->AcknowledgeChanges(); + } + AutoSharedLock lock( mSharedMutex, true ); + mChangeCount = 0; + } + + void APICALL NodeImpl::Clear( bool contents, bool qualifiers ) { + if ( qualifiers && mQualifiers ) { + mQualifiers->Clear(); + } + if ( contents ) { + ClearContents(); + RegisterChange(); + } + } + + spINode APICALL NodeImpl::Clone( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers ) const { + AutoSharedLock lock( mSharedMutex ); + + sizet qualifiersCount( mQualifiers ? mQualifiers->ChildCount() : 0 ); + + spIStructureNode qualifierNode; + // copy the qualifiers + if ( qualifiersCount > 0 ) { + auto node = mQualifiers->Clone( ignoreEmptyNodes, ignoreNodesWithOnlyQualifiers ); + if ( node ) qualifierNode = node->ConvertToStructureNode(); + qualifiersCount = qualifierNode ? qualifierNode->ChildCount() : 0; + } + + spINode newNode = CloneContents( ignoreEmptyNodes, ignoreNodesWithOnlyQualifiers, qualifiersCount ); + + if ( newNode ) + newNode->GetINode_I()->SetIsQualifierNode( newNode->IsQualifierNode() ); + + // set the qualifier + if ( newNode && qualifierNode && qualifiersCount > 0 ) { + newNode->GetINode_I()->SetQualifiers( qualifierNode ); + } + + return newNode; + } + + void NodeImpl::updateParentSharedPointer( bool calledFromRelease ) { + if ( !calledFromRelease ) { + if ( !mspParent && mRefCount > 1 && mpParent ) + mspParent = MakeUncheckedSharedPointer( mpParent, __FILE__, __LINE__, true ); + } else { + if ( mspParent && mRefCount <= 2 ) + mspParent.reset(); + } + } + + void NodeImpl::CreateQualifierNode() { + AutoSharedLock( mSharedMutex, true ); + if ( !mQualifiers ) { + mQualifiers = IStructureNode::CreateStructureNode( kQualifierNodeNameSpace, kQualifierNodeLocalNameLength, kQualifierNodeLocalName, kQualifierNodeLocalNameLength ); + mQualifiers->GetINode_I()->ChangeParent( this ); + } + } + + void NodeImpl::SetQualifiers( const spIStructureNode & node ) { + AutoSharedLock( mSharedMutex, true ); + mQualifiers = node; + } + + sizet APICALL NodeImpl::QualifiersCount() const __NOTHROW__ { + { + AutoSharedLock lock( mSharedMutex ); + if ( !mQualifiers ) return 0; + } + return mQualifiers->ChildCount(); + } + + spINodeIterator APICALL NodeImpl::QualifiersIterator() { + { + AutoSharedLock lock( mSharedMutex ); + if ( !mQualifiers ) return spINodeIterator(); + } + return mQualifiers->Iterator(); + } + + bool NodeImpl::ValidateNameOrNameSpaceChangeForAChild( const spcIUTF8String & currentNameSpace, const spcIUTF8String & currentName, const spcIUTF8String & newNameSpace, const spcIUTF8String & newName ) { + return true; + } + + INode_v1::eNodeType APICALL NodeImpl::GetParentNodeType() const { + if ( mpParent ) + return mpParent->GetNodeType(); + return INode_v1::kNTNone; + } + + INode_v1::eNodeType APICALL NodeImpl::GetQualifierNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) const { + { + AutoSharedLock lock( mSharedMutex ); + if ( !mQualifiers ) return INode::kNTNone; + } + return mQualifiers->GetChildNodeType( nameSpace, nameSpaceLength, name, nameLength ); + } + + spISimpleNode APICALL NodeImpl::ConvertToSimpleNode() { + return spISimpleNode(); + } + + spIStructureNode APICALL NodeImpl::ConvertToStructureNode() { + return spIStructureNode(); + } + + spIArrayNode APICALL NodeImpl::ConvertToArrayNode() { + return spIArrayNode(); + } + + spIMetadata APICALL NodeImpl::ConvertToMetadata() { + return spIMetadata(); + } + + void NodeImpl::UnRegisterChange() { + if ( mChangeCount > 0 ) + mChangeCount--; + if ( mChangeCount == 0 && mpParent ) { + mpParent->GetINode_I()->UnRegisterChange(); + } + } + + void APICALL NodeImpl::Acquire() const __NOTHROW__ { + SharedObjectImpl::Acquire(); + AutoSharedLock lock( mSharedMutex, true ); + const_cast< NodeImpl * >( this )->updateParentSharedPointer(); + } + + void APICALL NodeImpl::Release() const __NOTHROW__ { + AutoSharedLock lock( mSharedMutex, true ); + const_cast< NodeImpl * >( this )->updateParentSharedPointer( true ); + SharedObjectImpl::Release(); + } + + void APICALL NodeImpl::AcquireInternal() const __NOTHROW__ { + SharedObjectImpl::AcquireInternal(); + AutoSharedLock lock( mSharedMutex, true ); + const_cast< NodeImpl * >( this )->updateParentSharedPointer(); + } + + void NodeImpl::RegisterChange() { + mChangeCount++; + if ( mChangeCount == 1 ) { + auto parent = GetRawParentPointer(); + if ( parent ) parent->GetINode_I()->RegisterChange(); + } + } + + void NodeImpl::SetIndex( sizet currentIndex ) { + mIndex = currentIndex; + } + + void NodeImpl::SetIsQualifierNode( bool isQualifierNode ) { + mIsQualifierNode = isQualifierNode; + } + + bool APICALL NodeImpl::IsQualifierNode() const { + return mIsQualifierNode; + } + + sizet APICALL NodeImpl::GetIndex() const { + return mIndex; + } + +} + +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + spINode INode_v1::MakeShared( pINode_base ptr ) { + if ( !ptr ) return spINode(); + pINode p = INode::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< INode >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + +} diff --git a/XMPCore/source/PathImpl.cpp b/XMPCore/source/PathImpl.cpp new file mode 100644 index 0000000..4589c79 --- /dev/null +++ b/XMPCore/source/PathImpl.cpp @@ -0,0 +1,186 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/PathImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/IPathSegment.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCommon/Utilities/UTF8String.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + // All virtual functions + + spcINameSpacePrefixMap APICALL PathImpl::RegisterNameSpacePrefixMap( const spcINameSpacePrefixMap & map ) { + spcINameSpacePrefixMap old = mNameSpacePrefixMap; + mNameSpacePrefixMap = map->Clone(); + return old; + } + + static const char * sSegmentSeperator = "/"; + static const char * sValueSeperator = ":"; + static const char * sQualifierIndicator = "@"; + static const char * sValueIndicatorBegin = "["; + static const char * sValueIndicatorEnd = "]"; + static const char * sQualifierValueIndicator = "?"; + static const char * sQualifierValueSeperator = "="; + static const char * sQuotes = "\""; + + spIUTF8String APICALL PathImpl::Serialize( const spcINameSpacePrefixMap & map ) const { + bool firstSegment = true; + + auto it = mSegments.begin(); + auto endIt = mSegments.end(); + spIUTF8String serailizedOutput = IUTF8String_I::CreateUTF8String(); + + for (it = mSegments.begin(); it != endIt; it++) { + spcIUTF8String nameSpace = it->get()->GetNameSpace(); + spcIUTF8String nameSpaceOrPrefix; + + if (!map && !mNameSpacePrefixMap) + nameSpaceOrPrefix = nameSpace; + + if (map) + nameSpaceOrPrefix = map->GetINameSpacePrefixMap_I()->GetPrefix(nameSpace); + if (!nameSpaceOrPrefix && mNameSpacePrefixMap) + nameSpaceOrPrefix = mNameSpacePrefixMap->GetINameSpacePrefixMap_I()->GetPrefix(nameSpace); + + if (!nameSpaceOrPrefix) + NOTIFY_ERROR(IError_v1::kEDDataModel, kDMECNameSpacePrefixMapEntryMissing, + "A required entry missing in the provided mapping table", IError_v1::kESOperationFatal, false, false); + + switch (it->get()->GetType()) { + case IPathSegment_v1::kPSTProperty: + if (!firstSegment) { + serailizedOutput->append(sSegmentSeperator, npos); + } + serailizedOutput->append(nameSpaceOrPrefix)->append(sValueSeperator, npos)->append(it->get()->GetName()); + break; + + case IPathSegment_v1::kPSTArrayIndex: + { + //std::string strIndex = std::to_string(it->get()->GetIndex()); + std::ostringstream oss; + oss << (it->get()->GetIndex()); + std::string strIndex = oss.str(); + serailizedOutput->append(sValueIndicatorBegin, npos)->append(strIndex.c_str(), strIndex.size())->append(sValueIndicatorEnd, npos); + } + break; + + case IPathSegment_v1::kPSTQualifier: + if (!firstSegment) { + serailizedOutput->append(sSegmentSeperator, npos); + } + serailizedOutput->append(sQualifierIndicator, npos)->append(nameSpaceOrPrefix)->append(sValueSeperator, npos)->append(it->get()->GetName()); + break; + + case IPathSegment_v1::kPSTQualifierSelector: + serailizedOutput->append(sValueIndicatorBegin, npos)->append(sQualifierValueIndicator, npos)->append(it->get()->GetName())-> + append(sQualifierValueSeperator, npos)->append(sQuotes, npos)->append(it->get()->GetValue())-> + append(sQuotes, npos)->append(sValueIndicatorEnd, npos); + + default: + break; + } + + if (firstSegment) { + firstSegment = false; + } + } + + return serailizedOutput; + + } + + void APICALL PathImpl::AppendPathSegment( const spcIPathSegment & segment ) { + if ( !segment ) + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECParametersNotAsExpected, + "Parameters to PathImpl::AppendPathSegment are not as expected", IError_v1::kESOperationFatal, + true, ( void * ) segment.get() ); + + mSegments.push_back( segment ); + } + + spcIPathSegment APICALL PathImpl::RemovePathSegment( sizet index ) { + if ( index - 1 >= mSegments.size() ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECIndexOutOfBounds, + "Requested Index to PathImpl::RemovePathSegment is out of bounds", IError_v1::kESOperationFatal, true, Size(), true, index ); + } else { + spcIPathSegment returnValue = mSegments[ index - 1 ]; + mSegments.erase( mSegments.begin() + index - 1 ); + return returnValue; + } + return spcIPathSegment(); + } + + spcIPathSegment APICALL PathImpl::GetPathSegment( sizet index ) const { + if ( index - 1 >= mSegments.size() ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECIndexOutOfBounds, + "Requested Index to PathImpl::GetPathSegment is out of bounds", IError_v1::kESOperationFatal, true, Size(), true, index ); + } else { + return mSegments[ index - 1 ]; + } + return spcIPathSegment(); + } + + AdobeXMPCommon::sizet PathImpl::Size() const __NOTHROW__ { + return mSegments.size(); + } + + void APICALL PathImpl::Clear() __NOTHROW__ { + mSegments.clear(); + } + + spIPath APICALL PathImpl::Clone( sizet startingIndex, sizet countOfSegments ) const { + sizet totalCountOfSegments = mSegments.size(); + + if ( startingIndex - 1 >= totalCountOfSegments ) { + NOTIFY_ERROR( IError_v1::kEDGeneral, kGECIndexOutOfBounds, + "Requested startIndex to PathImpl::Clone is out of bounds", IError_v1::kESOperationFatal, true, Size(), true, startingIndex ); + } + spIPath newPath = MakeUncheckedSharedPointer( new PathImpl(), __FILE__, __LINE__, true ); + + for ( sizet index = startingIndex; countOfSegments != 0; countOfSegments--, index++ ) { + newPath->AppendPathSegment( mSegments[ index - 1 ] ); + if ( index == totalCountOfSegments ) + break; + } + if ( mNameSpacePrefixMap ) + newPath->RegisterNameSpacePrefixMap( mNameSpacePrefixMap->Clone() ); + return newPath; + } + +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + + spIPath IPath_v1::MakeShared( pIPath_base ptr ) { + if ( !ptr ) return spIPath(); + pIPath p = IPath::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IPath >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + + spIPath IPath_v1::CreatePath() { + return MakeUncheckedSharedPointer( new PathImpl(), __FILE__, __LINE__, true ); + } + + spIPath IPath_v1::ParsePath( const char * path, sizet pathLength, const spcINameSpacePrefixMap & map ) { + NOTIFY_ERROR( IError::kEDGeneral, kGECNotImplemented, "API is not implemented", IError::kESOperationFatal, true, "ParsePath" ); + } + +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB diff --git a/XMPCore/source/PathSegmentImpl.cpp b/XMPCore/source/PathSegmentImpl.cpp new file mode 100644 index 0000000..2ef1aad --- /dev/null +++ b/XMPCore/source/PathSegmentImpl.cpp @@ -0,0 +1,145 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/PathSegmentImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +#include <cstring> +namespace AdobeXMPCore_Int { + + // All virtual functions + + PathSegmentImpl::PathSegmentImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, + const char * value, sizet valueLength, ePathSegmentType type, sizet index ) + : mNameSpace( IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ) ) + , mName( IUTF8String_I::CreateUTF8String( name, nameLength ) ) + , mValue( IUTF8String_I::CreateUTF8String( value, valueLength ) ) + , mType( type ) + , mIndex( index ) { } + + spcIUTF8String APICALL PathSegmentImpl::GetNameSpace() const { + return mNameSpace; + } + + spcIUTF8String APICALL PathSegmentImpl::GetName() const { + return mName; + } + + IPathSegment_v1::ePathSegmentType APICALL PathSegmentImpl::GetType() const { + return mType; + } + + sizet APICALL PathSegmentImpl::GetIndex() const __NOTHROW__ { + return mIndex; + } + + spcIUTF8String APICALL PathSegmentImpl::GetValue() const { + return mValue; + } + + AdobeXMPCore::spcIPathSegment PathSegmentImpl::Clone() const { + return MakeUncheckedSharedPointer( + new PathSegmentImpl( this->mNameSpace->c_str(), this->mNameSpace->size(), + this->mName->c_str(), this->mName->size(), this->mValue->c_str(), this->mValue->size(), mType, mIndex ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_I::CreatePropertyPathSegment( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace->c_str(), nameSpace->size(), name->c_str(), name->size(), NULL, AdobeXMPCommon::npos, kPSTProperty, kMaxSize ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_I::CreateArrayIndexPathSegment( const spcIUTF8String & nameSpace, sizet index ) { + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace->c_str(), nameSpace->size() , NULL, AdobeXMPCommon::npos, NULL, AdobeXMPCommon::npos, kPSTArrayIndex, index ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_I::CreateQualifierPathSegment( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace->c_str(), nameSpace->size(), name->c_str(), name->size(), NULL, AdobeXMPCommon::npos, kPSTQualifier, kMaxSize ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_I::CreateQualifierSelectorPathSegment( const spcIUTF8String & nameSpace, const spcIUTF8String & name, const spcIUTF8String & value ) { + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace->c_str(), nameSpace->size(), name->c_str(), name->size(), value->c_str(), value->size(), kPSTQualifierSelector, kMaxSize ), __FILE__, __LINE__, true ); + } + +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + + spcIPathSegment IPathSegment_v1::CreatePropertyPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + if ( nameSpace && nameSpaceLength == AdobeXMPCommon::npos ) + nameSpaceLength = strlen( nameSpace ); + if ( name && nameLength == AdobeXMPCommon::npos ) + nameLength = strlen( name ); + + if ( nameSpace == NULL || name == NULL || nameSpaceLength == 0 || nameLength == 0 ) + NOTIFY_ERROR( IError::kEDGeneral, kGECParametersNotAsExpected, "Parameters to CreatePropertyPathSegment() are not as expected", + IError::kESOperationFatal, true, ( void * ) nameSpace, true, ( void * ) name, true, nameSpaceLength, true, nameLength, nameSpace, nameSpace, name, name ); + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace, nameSpaceLength, name, nameLength, NULL, AdobeXMPCommon::npos, kPSTProperty, kMaxSize ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_v1::CreateArrayIndexPathSegment( const char * nameSpace, sizet nameSpaceLength, sizet index ) { + if ( nameSpace && nameSpaceLength == AdobeXMPCommon::npos ) + nameSpaceLength = strlen( nameSpace ); + if ( nameSpace == NULL || nameSpaceLength == 0 ) + NOTIFY_ERROR( IError::kEDGeneral, kGECParametersNotAsExpected, "Parameters to CreateArrayIndexPathSegment() are not as expected", + IError::kESOperationFatal, true, ( void * ) nameSpace, true, nameSpaceLength, nameSpace, nameSpace ); + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace, nameSpaceLength, NULL, AdobeXMPCommon::npos, NULL, AdobeXMPCommon::npos, kPSTArrayIndex, index ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_v1::CreateQualifierPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + if ( nameSpace && nameSpaceLength == AdobeXMPCommon::npos ) + nameSpaceLength = strlen( nameSpace ); + if ( name && nameLength == AdobeXMPCommon::npos ) + nameLength = strlen( name ); + + if ( nameSpace == NULL || name == NULL || nameSpaceLength == 0 || nameLength == 0 ) + NOTIFY_ERROR( IError::kEDGeneral, kGECParametersNotAsExpected, "Parameters to CreateQualifierPathSegment() are not as expected", + IError::kESOperationFatal, true, ( void * ) nameSpace, true, ( void * ) name, true, nameSpaceLength, true, nameLength, nameSpace, nameSpace, name, name ); + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace, nameSpaceLength, name, nameLength, NULL, AdobeXMPCommon::npos, kPSTQualifier, kMaxSize ), __FILE__, __LINE__, true ); + } + + spcIPathSegment IPathSegment_v1::CreateQualifierSelectorPathSegment( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, + const char * value, sizet valueLength ) + { + if ( nameSpace && nameSpaceLength == AdobeXMPCommon::npos ) + nameSpaceLength = strlen( nameSpace ); + if ( name && nameLength == AdobeXMPCommon::npos ) + nameLength = strlen( name ); + if ( value && valueLength == AdobeXMPCommon::npos ) + valueLength = strlen( value ); + + if ( nameSpace == NULL || name == NULL || value == NULL || nameSpaceLength == 0 || nameLength == 0 || valueLength == 0 ) + NOTIFY_ERROR( IError::kEDGeneral, kGECParametersNotAsExpected, "Parameters to CreateQualifierSelectorPathSegment() are not as expected", + IError::kESOperationFatal, true, ( void * ) nameSpace, true, ( void * ) name, true, ( void * ) value, + true, nameSpaceLength, true, nameLength, true, valueLength ); + return MakeUncheckedSharedPointer( + new PathSegmentImpl( nameSpace, nameSpaceLength, name, nameLength, value, valueLength, kPSTQualifierSelector, kMaxSize ), __FILE__, __LINE__, true ); + } + + spIPathSegment IPathSegment_v1::MakeShared( pIPathSegment_base ptr ) { + if ( !ptr ) return spIPathSegment(); + pIPathSegment p = IPathSegment::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IPathSegment >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB + diff --git a/XMPCore/source/RDFDOMParserImpl.cpp b/XMPCore/source/RDFDOMParserImpl.cpp new file mode 100644 index 0000000..a97153f --- /dev/null +++ b/XMPCore/source/RDFDOMParserImpl.cpp @@ -0,0 +1,156 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/RDFDOMParserImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" + +#include "XMPCore/source/XMPMeta.hpp" +#include "XMPUtils.hpp" + +namespace AdobeXMPCore_Int { + + const char * kArrayItemName = "arrayItem"; + const char * kArrayItemNameSpace = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; + + namespace Parser { + static uint64 kAllowedKeys[] = { IConfigurable::ConvertCharBufferToUint64( "rqMetaEl" ), IConfigurable::ConvertCharBufferToUint64( "sctAlias" ) }; + static ConfigurableImpl::KeyValueTypePair kAllowedKeyValueTypes[] = { + std::make_pair( kAllowedKeys[ 0 ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ 1 ], IConfigurable::kDTBool ) }; + } + + static void CreateAndPopulateNode( const spINode & parentNode, XMP_Node * node, bool nodeIsQualifier = false ) { + XMP_StringPtr nameSpaceStr, nameStr; + XMP_StringLen nameSpaceLen, nameLen; + node->GetFullQualifiedName( &nameSpaceStr, &nameSpaceLen, &nameStr, &nameLen ); + if ( nameSpaceLen == 0 && nameLen == 0 ) { //true in case of array element + nameSpaceStr = kArrayItemNameSpace; + nameStr = kArrayItemName; + nameSpaceLen = strlen( kArrayItemNameSpace ); + nameLen = strlen( kArrayItemName ); + } + + spINode spNode; + if ( XMP_PropIsSimple( node->options ) ) { + spISimpleNode spSimpleNode = ISimpleNode::CreateSimpleNode( nameSpaceStr, nameSpaceLen, nameStr, nameLen, node->value.c_str(), node->value.size() ); + spSimpleNode->SetURIType( XMP_OptionIsSet( node->options, kXMP_PropValueIsURI ) ); + spNode = spSimpleNode; + } else if ( XMP_PropIsStruct( node->options ) ) { + spIStructureNode spStructNode = IStructureNode::CreateStructureNode( nameSpaceStr, nameSpaceLen, nameStr, nameLen ); + for ( sizet index = 0, count = node->children.size(); index < count; index++ ) + CreateAndPopulateNode( spStructNode, node->children[ index ] ); + spNode = spStructNode; + } else if ( XMP_PropIsArray( node->options ) ) { + IArrayNode::eArrayForm arrayNodeForm = IArrayNode::kAFUnordered; + if ( XMP_ArrayIsAlternate( node->options ) ) arrayNodeForm = IArrayNode::kAFAlternative; + else if ( XMP_ArrayIsOrdered( node->options ) ) arrayNodeForm = IArrayNode::kAFOrdered; + spIUTF8String nameSpaceUTF8Str( IUTF8String_I::CreateUTF8String( nameSpaceStr, nameSpaceLen ) ); + spIUTF8String nameUTF8Str( IUTF8String_I::CreateUTF8String( nameStr, nameLen ) ); + spIArrayNode spArrayNode = IArrayNode_I::CreateArrayNode( nameSpaceUTF8Str, nameUTF8Str, arrayNodeForm ); + for ( sizet index = 0, count = node->children.size(); index < count; index++ ) + CreateAndPopulateNode( spArrayNode, node->children[ index ] ); + spNode = spArrayNode; + } + + if ( spNode ) { + // append qualifiers. + if ( node->qualifiers.size() > 0 ) { + for ( sizet index = 0, count = node->qualifiers.size(); index < count; index++ ) { + CreateAndPopulateNode( spNode, node->qualifiers[ index ], true ); + } + } + if ( nodeIsQualifier ) + parentNode->InsertQualifier( spNode ); + else + parentNode->GetInterfacePointer< ICompositeNode_v1 >()->AppendNode( spNode ); + } + + } + + DOMParserImpl * APICALL RDFDOMParserImpl::clone() const { + return new RDFDOMParserImpl(); + } + + spINode APICALL RDFDOMParserImpl::ParseAsNode( const char * buffer, sizet bufferLength ) { + shared_ptr < XMPMeta > spMeta( new XMPMeta() ); + try { + + if (mGenericErrorCallbackPtr && mGenericErrorCallbackPtr->wrapperProc) { + spMeta->SetErrorCallback(mGenericErrorCallbackPtr->wrapperProc, mGenericErrorCallbackPtr->clientProc, mGenericErrorCallbackPtr->context, mGenericErrorCallbackPtr->limit); + spMeta->errorCallback.notifications = mGenericErrorCallbackPtr->notifications; + } + XMP_OptionBits options( 0 ); + bool value; + if ( GetParameter( Parser::kAllowedKeys[ 0 ], value ) && value ) + options |= kXMP_RequireXMPMeta; + if ( GetParameter( Parser::kAllowedKeys[ 1 ], value ) && value ) + options |= kXMP_StrictAliasing; + spMeta->ParseFromBuffer( buffer, static_cast< XMP_StringLen >( bufferLength ), static_cast< XMP_OptionBits >( options ) ); + } catch ( XMP_Error & xmpError ) { + IError::eErrorDomain domain( IError::kEDNone ); + IError::eErrorCode code( kGECNone ); + if ( mGenericErrorCallbackPtr && mGenericErrorCallbackPtr->wrapperProc ) { + mGenericErrorCallbackPtr->notifications = spMeta->errorCallback.notifications; + } +#if ENABLE_CPP_DOM_MODEL + XMPUtils::MapXMPErrorToIError( xmpError.GetID(), domain, code ); +#endif + NOTIFY_ERROR( domain, code, "XMP Error caught", IError::kESOperationFatal, false, false ); + + } + if ( mGenericErrorCallbackPtr && mGenericErrorCallbackPtr->wrapperProc ) { + mGenericErrorCallbackPtr->notifications = spMeta->errorCallback.notifications; + } + spIMetadata metadata = IMetadata::CreateMetadata(); + if ( spMeta ) { + metadata->SetAboutURI( spMeta->tree.name.c_str(), spMeta->tree.name.size() ); + + // all the top level children of this tree are actually top level namespace entries. + // name begin the namespace string and value contains the prefix with colon. + // actual nodes are below these top level children. + for ( sizet index = 0, count = spMeta->tree.children.size(); index < count; ++index ) { + XMP_Node * topLevelNode = spMeta->tree.children[ index ]; + for ( sizet innerIndex = 0, innerCount = topLevelNode->children.size(); innerIndex < innerCount; ++innerIndex ) { + CreateAndPopulateNode( metadata, topLevelNode->children[ innerIndex ] ); + } + } + } + metadata->AcknowledgeChanges(); + return metadata; + } + + eConfigurableErrorCode APICALL RDFDOMParserImpl::ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const { + return kCECNone; + } + + void RDFDOMParserImpl::InitializeDefaultValues() { + TreatKeyAsCaseInsensitive( true ); + AllowDifferentValueTypesForExistingEntries( false ); + + SetAllowedKeys( &Parser::kAllowedKeys[ 0 ], 2 ); + SetAllowedValueTypesForKeys( &Parser::kAllowedKeyValueTypes[ 0 ], 2 ); + SetParameter( Parser::kAllowedKeys[ 0 ], false ); + SetParameter( Parser::kAllowedKeys[ 1 ], false ); + } + + void RDFDOMParserImpl::SetErrorCallback(XMPMeta::ErrorCallbackInfo * ec) { + mGenericErrorCallbackPtr = ec; + } + + + +} diff --git a/XMPCore/source/RDFDOMSerializerImpl.cpp b/XMPCore/source/RDFDOMSerializerImpl.cpp new file mode 100644 index 0000000..4888152 --- /dev/null +++ b/XMPCore/source/RDFDOMSerializerImpl.cpp @@ -0,0 +1,508 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/RDFDOMSerializerImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" + +#include "XMPCommon/Utilities/AutoSharedLock.h" + +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" +#include "XMPCommon/Utilities/UTF8String.h" +#include "XMPCore/Interfaces/INodeIterator_I.h" + +#include "XMPMeta.hpp" + +// some declaration of functions defined in XMPMeta-Parse.cpp +extern void NormalizeDCArrays( XMP_Node * xmpTree ); +extern void MoveExplicitAliases( XMP_Node * tree, XMP_OptionBits parseOptions, XMPMeta::ErrorCallbackInfo & errorCallback ); +extern void TouchUpDataModel( XMPMeta * xmp, XMPMeta::ErrorCallbackInfo & errorCallback ); + +namespace AdobeXMPCore_Int { + + namespace Serializer { + typedef enum { + kCPOmitPacketWrapper, + kCPMarkReadOnlyPacket, + kCPUseCompactFormat, + kCPUseCanonicalFormat, + kCPIncludeThumbnailPadding, + kCPUseExactPacketLength, + kCPOmitAllFormatting, + kCPOmitMetaElement, + kCPOmitRDFHash, + kCPUseEncoding, + kCPUseBigEndian, + kCPPaddingLength + } eConfigurableParameters; + + static uint64 kAllowedKeys[] = { + IConfigurable::ConvertCharBufferToUint64( "oPktWrap" ), + IConfigurable::ConvertCharBufferToUint64( "mRoPkt " ), + IConfigurable::ConvertCharBufferToUint64( "uCompact" ), + IConfigurable::ConvertCharBufferToUint64( "uCanonic" ), + IConfigurable::ConvertCharBufferToUint64( "eThmbPad" ), + IConfigurable::ConvertCharBufferToUint64( "uExctLen" ), + IConfigurable::ConvertCharBufferToUint64( "oFormat " ), + IConfigurable::ConvertCharBufferToUint64( "oMetaEl " ), + IConfigurable::ConvertCharBufferToUint64( "oRDFHash" ), + IConfigurable::ConvertCharBufferToUint64( "encoding" ), + IConfigurable::ConvertCharBufferToUint64( "bgEndian"), + IConfigurable::ConvertCharBufferToUint64( "padLen " ), + }; + + static ConfigurableImpl::KeyValueTypePair kAllowedKeyValueTypes[] = { + std::make_pair( kAllowedKeys[ kCPOmitPacketWrapper ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPMarkReadOnlyPacket ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPUseCompactFormat ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPUseCanonicalFormat ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPIncludeThumbnailPadding ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPUseExactPacketLength ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPOmitAllFormatting ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPOmitMetaElement ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPOmitRDFHash ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPUseEncoding ], IConfigurable::kDTUint64 ), + std::make_pair( kAllowedKeys[ kCPUseBigEndian ], IConfigurable::kDTBool ), + std::make_pair( kAllowedKeys[ kCPPaddingLength ], IConfigurable::kDTUint64 ) + }; + } + + // static utility functions + static spcIUTF8String CreateQualifiedName( const spINode & node, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap ) { + spIUTF8String qualName = IUTF8String_I::CreateUTF8String( NULL, AdobeXMPCommon::npos ); + spcIUTF8String nameSpace = node->GetNameSpace(); + static sizet count( 0 ); + + spcIUTF8String prefixStr = userSuppliedMap->GetPrefix( node->GetNameSpace() ); + + if ( !prefixStr && !generatedMap ) { + generatedMap = MakeUncheckedSharedPointer( INameSpacePrefixMap_I::CreateNameSpacePrefixMap()->GetINameSpacePrefixMap_I(), __FILE__, __LINE__, true ); + count = 0; + } + else if (!prefixStr && generatedMap) { + + if (generatedMap->GetPrefix(node->GetNameSpace())) { + + prefixStr = generatedMap->GetPrefix(node->GetNameSpace()); + } + } + if ( !prefixStr ) { + + spIUTF8String autoGeneratedPrefix = IUTF8String_I::CreateUTF8String( NULL, AdobeXMPCommon::npos ); + do { + autoGeneratedPrefix->clear(); + autoGeneratedPrefix->append( "ns", (sizet) 2 ); + //std::string numStr = std::to_string( ++count ); + std::ostringstream oss; + oss << ++count; + std::string numStr = oss.str(); + autoGeneratedPrefix->append( numStr.c_str(), numStr.size() ); + } while (generatedMap->IsPrefixPresent ( autoGeneratedPrefix->c_str ( ), autoGeneratedPrefix->size ( ) )); + generatedMap->Insert( autoGeneratedPrefix->c_str(), autoGeneratedPrefix->size(), nameSpace->c_str(), nameSpace->size() ); + prefixStr = autoGeneratedPrefix; + } + + qualName->append( prefixStr ); + qualName->append( ":", 1 ); + qualName->append( node->GetName() ); + return qualName; + } + + bool FindPrefixFromUserSuppliedMap ( void * voidUserSuppliedMap, XMP_StringPtr nsURI, XMP_StringPtr * namespacePrefix, XMP_StringLen * prefixSize ) { + if (voidUserSuppliedMap) { + pcINameSpacePrefixMap userSuppliedMap = reinterpret_cast<pcINameSpacePrefixMap>( voidUserSuppliedMap ); + auto prefix = userSuppliedMap->GetPrefix ( nsURI, AdobeXMPCommon::npos ); + if (prefix) { + *namespacePrefix = prefix->c_str ( ); + *prefixSize = prefix->size ( ); + return true; + } + } + return false; + } + + static XMP_Node * AddChildNode( XMP_Node * xmpParent, const spINode & node, const char * value, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap, bool isTopLevel ) { + bool isArrayItem = node->IsArrayItem(); + if ( isTopLevel ) { + isArrayItem = false; + } + + XMP_OptionBits childOptions = 0; + + spcIUTF8String qualName = CreateQualifiedName( node, userSuppliedMap, generatedMap ); + + XMP_StringPtr childName = qualName->c_str(); + XMP_StringPtr nameSpaceStrPtr = node->GetNameSpace()->c_str(); + + if ( isTopLevel ) { + // Lookup the schema node, adjust the XMP parent pointer. + XMP_Assert( xmpParent->parent == 0 ); // Incoming parent must be the tree root. + XMP_Node * schemaNode = FindSchemaNode( xmpParent, nameSpaceStrPtr, kXMP_CreateNodes, NULL, &FindPrefixFromUserSuppliedMap, generatedMap ? generatedMap->GetActualINameSpacePrefixMap() : NULL ); + if ( schemaNode->options & kXMP_NewImplicitNode ) schemaNode->options ^= kXMP_NewImplicitNode; // Clear the implicit node bit. + // *** Should use "opt &= ~flag" (no conditional), need runtime check for proper 32 bit code. + xmpParent = schemaNode; + + // If this is an alias set the isAlias flag in the node and the hasAliases flag in the tree. + XMP_StringPtr prefixForAlias( NULL ); + XMP_StringLen prefixLenForAlias( 0 ); + if ( sRegisteredNamespaces->GetPrefix( nameSpaceStrPtr, &prefixForAlias, &prefixLenForAlias ) && prefixForAlias && prefixLenForAlias > 0 ) { + spIUTF8String childNameForAlias( IUTF8String_I::CreateUTF8String( NULL, npos ) ); + childNameForAlias->append( prefixForAlias, prefixLenForAlias )->append( node->GetName() ); + if ( sRegisteredAliasMap->find( childNameForAlias->c_str() ) != sRegisteredAliasMap->end() ) { + childOptions |= kXMP_PropIsAlias; + schemaNode->parent->options |= kXMP_PropHasAliases; + } + } + + } + + if ( isArrayItem ) { + childName = kXMP_ArrayItemName; + } + + // Add the new child to the XMP parent node. + XMP_Node * newChild = new XMP_Node( xmpParent, childName, value, childOptions ); + xmpParent->children.push_back( newChild ); + + return newChild; + } + + static XMP_Node * AddQualifierNode( XMP_Node * xmpParent, const spINode & node, const char * value, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap ) { + spcIUTF8String qualName = CreateQualifiedName( node, userSuppliedMap, generatedMap ); + XMP_StringPtr childName = qualName->c_str(); + + static const char * kLanguageName = "lang"; + static const char * kTypeName = "type"; + + const bool isLang = ( node->GetName()->compare( kLanguageName ) == 0 ) && ( node->GetNameSpace()->compare( kXMP_NS_XML ) == 0 ); + const bool isType = ( node->GetName()->compare( kTypeName ) == 0 ) && ( node->GetNameSpace()->compare( kXMP_NS_RDF ) == 0 ); + + bool isArrayItem = node->IsArrayItem(); + + XMP_OptionBits childOptions = 0; + + XMP_StringPtr nameSpaceStrPtr = node->GetNameSpace()->c_str(); + + if ( isArrayItem ) { + childName = kXMP_ArrayItemName; + } + + XMP_Node * newQual = 0; + + newQual = new XMP_Node( xmpParent, childName, value, kXMP_PropIsQualifier ); + + if ( !( isLang | isType ) ) { + 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->options |= kXMP_PropHasQualifiers; + + return newQual; + } + + void HandleNode( const spINode & node, XMP_Node * parent, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap, bool isTopLevel, bool isQualifierNode ); + + XMP_Node * HandleSimpleNode( const spISimpleNode & simpleNode, XMP_Node * parent, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap, bool isTopLevel, bool isQualifierNode ) { + XMP_Node * node = NULL; + if ( isQualifierNode ) { + node = AddQualifierNode( parent, simpleNode, simpleNode->GetValue()->c_str(), userSuppliedMap, generatedMap ); + } else { + node = AddChildNode( parent, simpleNode, simpleNode->GetValue()->c_str(), userSuppliedMap, generatedMap, isTopLevel ); + } + if ( simpleNode->IsURIType() ) + node->options |= kXMP_PropValueIsURI; + return node; + } + + XMP_Node * HandleStructureNode( const spIStructureNode & structureNode, XMP_Node * parent, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap, bool isTopLevel, bool isQualifierNode ) { + bool metadataNode = false; + if ( isTopLevel ) { + // check if it is a XMPMetadata node + spIMetadata metadata = structureNode->ConvertToMetadata(); + if ( metadata ) { + metadataNode = true; + parent->name = metadata->GetAboutURI()->c_str(); + } + } + + XMP_Node * newComposite = NULL; + if ( !metadataNode ) { + if ( isQualifierNode ) { + newComposite = AddQualifierNode( parent, structureNode, "", userSuppliedMap, generatedMap ); + } else { + newComposite = AddChildNode( parent, structureNode, "", userSuppliedMap, generatedMap, isTopLevel ); + } + } else { + newComposite = parent; + } + + if ( newComposite == 0 ) return NULL; // Ignore lower level errors. + + newComposite->options |= kXMP_PropValueIsStruct; + + // iterate over all the children + spINodeIterator it = structureNode->Iterator(); + + while ( it ) { + spINode spNode = it->GetNode(); + if ( metadataNode ) + HandleNode( spNode, newComposite, userSuppliedMap, generatedMap, true, false ); + else + HandleNode( spNode, newComposite, userSuppliedMap, generatedMap, false, false ); + it = it->Next(); + } + + return newComposite; + } + + XMP_Node * HandleArrayNode( const spIArrayNode & arrayNode, XMP_Node * parent, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap, bool isTopLevel, bool isQualifierNode ) { + XMP_Node * newComposite = NULL; + if ( isQualifierNode ) { + newComposite = AddQualifierNode( parent, arrayNode, "", userSuppliedMap, generatedMap ); + } else { + newComposite = AddChildNode( parent, arrayNode, "", userSuppliedMap, generatedMap, isTopLevel ); + } + + if ( newComposite == 0 ) return NULL; // Ignore lower level errors. + + newComposite->options |= kXMP_PropValueIsArray; + + IArrayNode::eArrayForm arrayNodeForm = arrayNode->GetArrayForm(); + if ( arrayNodeForm == IArrayNode::kAFAlternative ) + newComposite->options |= kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate; + else if ( arrayNodeForm == IArrayNode::kAFOrdered ) + newComposite->options |= kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered; + + // iterate over all the children + spINodeIterator it = arrayNode->Iterator(); + + while ( it ) { + spINode spNode = it->GetNode(); + HandleNode( spNode, newComposite, userSuppliedMap, generatedMap, false, false ); + it = it->Next(); + } + return newComposite; + } + + void HandleNode( const spINode & node, XMP_Node * parent, const spcINameSpacePrefixMap_I & userSuppliedMap, spINameSpacePrefixMap_I & generatedMap, bool isTopLevel, bool isQualifierNode ) { + XMP_Node * nodeCreated = NULL; + if (!node) return; + switch ( node->GetNodeType() ) { + case INode::kNTSimple: + nodeCreated = HandleSimpleNode( node->ConvertToSimpleNode(), parent, userSuppliedMap, generatedMap, isTopLevel, isQualifierNode ); + break; + + case INode::kNTStructure: + nodeCreated = HandleStructureNode( node->ConvertToStructureNode(), parent, userSuppliedMap, generatedMap, isTopLevel, isQualifierNode ); + break; + + case INode::kNTArray: + nodeCreated = HandleArrayNode( node->ConvertToArrayNode(), parent, userSuppliedMap, generatedMap, isTopLevel, isQualifierNode ); + break; + + default: + break; + } + + if ( node->HasQualifiers() && nodeCreated ) { + spINodeIterator it = node->QualifiersIterator(); + while ( it ) { + spINode spNode = it->GetNode(); + HandleNode( spNode, nodeCreated, userSuppliedMap, generatedMap, false, true ); + it = it->Next(); + } + } + } + + DOMSerializerImpl * APICALL RDFDOMSerializerImpl::clone() const { + return new RDFDOMSerializerImpl(); + } + + static void GetSerializationOptions( pcIConfigurable configurationParameters, XMP_OptionBits & options, uint64 & paddingSize ) { + options = 0; + bool flag; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitPacketWrapper ], flag ) && flag ) + options |= kXMP_OmitPacketWrapper; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPMarkReadOnlyPacket ], flag ) && flag ) + options |= kXMP_ReadOnlyPacket; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseCompactFormat ], flag ) && flag ) + options |= kXMP_UseCompactFormat; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseCanonicalFormat ], flag ) && flag ) + options |= kXMP_UseCanonicalFormat; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPIncludeThumbnailPadding ], flag ) && flag ) + options |= kXMP_IncludeThumbnailPad; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseExactPacketLength ], flag ) && flag ) + options |= kXMP_ExactPacketLength; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitAllFormatting ], flag ) && flag ) + options |= kXMP_OmitAllFormatting; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitMetaElement ], flag ) && flag ) + options |= kXMP_OmitXMPMetaElement; + if ( configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitRDFHash ], flag ) && !flag ) + options |= kXMP_IncludeRDFHash; + + uint64 encoding( 8 ); + if ( !configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseBigEndian ], flag ) ) + flag = false; + if ( !configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseEncoding ], encoding ) ) + encoding = 8; + + switch ( encoding ) { + case 16: + if ( flag ) options |= kXMP_EncodeUTF16Big; else options |= kXMP_EncodeUTF16Little; + break; + + case 32: + if ( flag ) options |= kXMP_EncodeUTF32Big; else options |= kXMP_EncodeUTF32Little; + break; + + default: + options |= kXMP_EncodeUTF8; + } + + if ( !configurationParameters->GetParameter( Serializer::kAllowedKeys[ Serializer::kCPPaddingLength ], paddingSize ) ) + paddingSize = 2048; + } + + + + spIUTF8String APICALL RDFDOMSerializerImpl::Serialize( const spINode & node, const spcINameSpacePrefixMap & nameSpacePrefixMap ) { + XMP_OptionBits options = 0; + shared_ptr< XMPMeta > spMeta( new XMPMeta() ); + spINameSpacePrefixMap_I genereatedMap; + + spcINameSpacePrefixMap mergedMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + if ( nameSpacePrefixMap ) { + spINameSpacePrefixMap newMergedMap = mergedMap->Clone(); + newMergedMap->GetINameSpacePrefixMap_I()->Merge( nameSpacePrefixMap ); + mergedMap = newMergedMap; + } + spINameSpacePrefixMap_I userSuppliedMap( MakeUncheckedSharedPointer( const_pointer_cast< INameSpacePrefixMap >( mergedMap )->GetINameSpacePrefixMap_I(), __FILE__, __LINE__, true ) ); + + // TODO:meta->SetErrorCallback() + HandleNode( node, &spMeta->tree, userSuppliedMap, genereatedMap, true, false ); + + NormalizeDCArrays( &( spMeta->tree ) ); + if ( spMeta->tree.options & kXMP_PropHasAliases ) MoveExplicitAliases( &spMeta->tree, options, spMeta->errorCallback ); + TouchUpDataModel( spMeta.get(), spMeta->errorCallback ); + + // Delete empty schema nodes. Do this last, other cleanup can make empty schema. + size_t schemaNum = 0; + while ( schemaNum < spMeta->tree.children.size() ) { + XMP_Node * currSchema = spMeta->tree.children[ schemaNum ]; + if ( currSchema->children.size() > 0 ) { + ++schemaNum; + } else { + delete spMeta->tree.children[ schemaNum ]; // ! Delete the schema node itself. + spMeta->tree.children.erase( spMeta->tree.children.begin() + schemaNum ); + } + } + + std::string buffer; + uint64 padding; + GetSerializationOptions( this, options, padding ); + spMeta->SerializeToBuffer( &buffer, options, padding, "", "", 0 ); + spIUTF8String serializedOutput = IUTF8String_I::CreateUTF8String( buffer.c_str(), buffer.size() ); + return serializedOutput; + } + + eConfigurableErrorCode APICALL RDFDOMSerializerImpl::ValidateValue( const uint64 & key, eDataType type, const CombinedDataValue & value ) const { + if ( key == Serializer::kAllowedKeys[ Serializer::kCPUseEncoding ] ) { + if ( type == IConfigurable::kDTUint64 && ( value.uint64Value == 8 || value.uint64Value == 16 || value.uint64Value == 32 ) ) + return kCECNone; + return kCECValueNotSupported; + } + return kCECNone; + } + + void RDFDOMSerializerImpl::InitializeDefaultValues() { + TreatKeyAsCaseInsensitive( true ); + AllowDifferentValueTypesForExistingEntries( false ); + + SetAllowedKeys( &Serializer::kAllowedKeys[ 0 ], 12 ); + SetAllowedValueTypesForKeys( &Serializer::kAllowedKeyValueTypes[ 0 ], 12 ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitPacketWrapper ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPMarkReadOnlyPacket ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseCompactFormat ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseCanonicalFormat ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPIncludeThumbnailPadding ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseExactPacketLength ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitAllFormatting ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitMetaElement ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPOmitRDFHash ], true ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseEncoding ], ( uint64 ) 8 ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPUseBigEndian ], false ); + SetParameter( Serializer::kAllowedKeys[ Serializer::kCPPaddingLength ], ( uint64 ) 2048 ); + + } + + spIUTF8String APICALL RDFDOMSerializerImpl::SerializeInternal(const spINode & node, XMP_OptionBits options, sizet padding, const char * newline, const char * indent, sizet baseIndent, const spcINameSpacePrefixMap & nameSpacePrefixMap) const { + + shared_ptr< XMPMeta > spMeta(new XMPMeta()); + spINameSpacePrefixMap_I genereatedMap; + + spcINameSpacePrefixMap mergedMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + if (nameSpacePrefixMap) { + spINameSpacePrefixMap newMergedMap = mergedMap->Clone(); + newMergedMap->GetINameSpacePrefixMap_I()->Merge(nameSpacePrefixMap); + mergedMap = newMergedMap; + } + spINameSpacePrefixMap_I userSuppliedMap(MakeUncheckedSharedPointer(const_pointer_cast<INameSpacePrefixMap>(mergedMap)->GetINameSpacePrefixMap_I(), __FILE__, __LINE__, true)); + + // TODO:meta->SetErrorCallback() + HandleNode(node, &spMeta->tree, userSuppliedMap, genereatedMap, true, false); + + NormalizeDCArrays(&(spMeta->tree)); + if (spMeta->tree.options & kXMP_PropHasAliases) MoveExplicitAliases(&spMeta->tree, options, spMeta->errorCallback); + TouchUpDataModel(spMeta.get(), spMeta->errorCallback); + + // Delete empty schema nodes. Do this last, other cleanup can make empty schema. + size_t schemaNum = 0; + while (schemaNum < spMeta->tree.children.size()) { + XMP_Node * currSchema = spMeta->tree.children[schemaNum]; + if (currSchema->children.size() > 0) { + ++schemaNum; + } + else { + delete spMeta->tree.children[schemaNum]; // ! Delete the schema node itself. + spMeta->tree.children.erase(spMeta->tree.children.begin() + schemaNum); + } + } + std::string buffer; + spMeta->SerializeToBuffer(&buffer, options, padding, newline, indent, baseIndent); + spIUTF8String serializedOutput = IUTF8String_I::CreateUTF8String(buffer.c_str(), buffer.size()); + return serializedOutput; + + } + +}
\ No newline at end of file diff --git a/XMPCore/source/SimpleNodeImpl.cpp b/XMPCore/source/SimpleNodeImpl.cpp new file mode 100644 index 0000000..69fcd87 --- /dev/null +++ b/XMPCore/source/SimpleNodeImpl.cpp @@ -0,0 +1,105 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/SimpleNodeImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +#include <assert.h> + +namespace AdobeXMPCore_Int { + + SimpleNodeImpl::SimpleNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength ) + : NodeImpl( nameSpace, nameSpaceLength, name, nameLength ) + , mValue( IUTF8String_I::CreateUTF8String( value, valueLength ) ) + , mIsURIType( false ) { } + + spcIUTF8String APICALL SimpleNodeImpl::GetValue() const { + AutoSharedLock lock( mSharedMutex ); + return mValue; + } + + void APICALL SimpleNodeImpl::SetValue( const char * value, sizet valueLength ) { + AutoSharedLock lock( mSharedMutex, true ); + mValue->assign( value, valueLength ); + RegisterChange(); + } + + bool APICALL SimpleNodeImpl::IsURIType() const { + AutoSharedLock lock( mSharedMutex ); + return mIsURIType; + } + + void APICALL SimpleNodeImpl::SetURIType( bool isURI ) { + AutoSharedLock( mSharedMutex, true ); + mIsURIType = isURI; + RegisterChange(); + } + + INode_v1::eNodeType APICALL SimpleNodeImpl::GetNodeType() const { + return INode_v1::kNTSimple; + } + + bool APICALL SimpleNodeImpl::HasContent() const { + AutoSharedLock lock( mSharedMutex ); + return !mValue->empty(); + } + + void APICALL SimpleNodeImpl::ClearContents() { + AutoSharedLock lock( mSharedMutex, true ); + mValue->clear(); + RegisterChange(); + } + + spINode APICALL SimpleNodeImpl::CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const { + if ( ignoreEmptyNodes && mValue->empty() ) { + if ( ignoreNodesWithOnlyQualifiers ) + return spINode(); + else if ( !ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 ) + return spINode(); + } + + spISimpleNode newNode = ISimpleNode_I::CreateSimpleNode( mNameSpace, mName, mValue ); + newNode->SetURIType( mIsURIType ); + return newNode; + } + + void SimpleNodeImpl::resetChangesForChildren() const { } + + spISimpleNode APICALL SimpleNodeImpl::ConvertToSimpleNode() { + return MakeUncheckedSharedPointer( this, __FILE__, __LINE__ ); + } + + spISimpleNode ISimpleNode_I::CreateSimpleNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name, const spcIUTF8String & value ) { + return MakeUncheckedSharedPointer( + new SimpleNodeImpl( nameSpace->c_str(), nameSpace->size(), name->c_str(), name->size(), + value ? value->c_str() : NULL, value ? value->size() : AdobeXMPCommon::npos ), __FILE__, __LINE__, true ); + } + +} + +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + spISimpleNode ISimpleNode::CreateSimpleNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength, const char * value, sizet valueLength ) { + return MakeUncheckedSharedPointer( new SimpleNodeImpl( nameSpace, nameSpaceLength, name, nameLength, value, valueLength ), __FILE__, __LINE__, true ); + } + + spISimpleNode ISimpleNode_v1::MakeShared( pISimpleNode_base ptr ) { + if ( !ptr ) return spISimpleNode(); + pISimpleNode p = ISimpleNode::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< ISimpleNode >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + +} diff --git a/XMPCore/source/StructureNodeImpl.cpp b/XMPCore/source/StructureNodeImpl.cpp new file mode 100644 index 0000000..646829e --- /dev/null +++ b/XMPCore/source/StructureNodeImpl.cpp @@ -0,0 +1,231 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#define IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED 1 + #include "XMPCore/ImplHeaders/StructureNodeImpl.h" + #include "XMPCore/ImplHeaders/TNodeIteratorImpl.h" +#undef IMPLEMENTATION_HEADERS_CAN_BE_INCLUDED + +#include "XMPCommon/Interfaces/IError_I.h" +#include "XMPCore/XMPCoreErrorCodes.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCommon/Utilities/AutoSharedLock.h" +#include "XMPCore/Interfaces/INodeIterator_I.h" +#include "XMPCommon/Utilities/TSmartPointers_I.h" + +namespace AdobeXMPCore_Int { + + // All virtual functions + + StructureNodeImpl::StructureNodeImpl( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) + : NodeImpl( nameSpace, nameSpaceLength, name, nameLength ) { } + + spINode APICALL StructureNodeImpl::GetNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + if ( nameSpace->size() == 0 || name->size() == 0 ) + return spINode(); + QualifiedName qName( nameSpace, name ); + AutoSharedLock lock( mSharedMutex ); + auto it = mChildrenMap.find( qName ); + if ( it != mChildrenMap.end() ) + return MakeUncheckedSharedPointer( it->second.get(), __FILE__, __LINE__ ); + return spINode(); + } + + spINode APICALL StructureNodeImpl::GetNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + spIUTF8String nameSpaceStr( IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ) ); + spIUTF8String nameStr( IUTF8String_I::CreateUTF8String( name, nameLength ) ); + return GetNode( nameSpaceStr, nameStr ); + } + + spINode APICALL StructureNodeImpl::RemoveNode( const spcIUTF8String & nameSpace, const spcIUTF8String & name ) { + if ( nameSpace->size() == 0 || name->size() == 0 ) + return spINode(); + QualifiedName qName( nameSpace, name ); + AutoSharedLock lock( mSharedMutex, true ); + auto it = mChildrenMap.find( qName ); + if ( it == mChildrenMap.end() ) { + return spINode(); + } else { + spINode node = it->second; + mChildrenMap.erase( it ); + node->GetINode_I()->ChangeParent( NULL ); + return node; + } + } + + spINode APICALL StructureNodeImpl::RemoveNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + spIUTF8String nameSpaceStr( IUTF8String_I::CreateUTF8String( nameSpace, nameSpaceLength ) ); + spIUTF8String nameStr( IUTF8String_I::CreateUTF8String( name, nameLength ) ); + return RemoveNode( nameSpaceStr, nameStr ); + } + + INode_v1::eNodeType APICALL StructureNodeImpl::GetChildNodeType( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) const { + auto node = GetNode( nameSpace, nameSpaceLength, name, nameLength ); + if ( node ) + return node->GetNodeType(); + return INode::kNTNone; + } + + INode_v1::eNodeType APICALL StructureNodeImpl::GetNodeType() const { + return INode_v1::kNTStructure; + } + + void APICALL StructureNodeImpl::InsertNode( const spINode & node ) { + if ( !CheckSuitabilityToBeUsedAsChildNode( node ) ) + return; + QualifiedName qName( node->GetNameSpace(), node->GetName() ); + AutoSharedLock lock( mSharedMutex, true ); + auto it = mChildrenMap.find( qName ); + if ( it == mChildrenMap.end() ) { + mChildrenMap[ qName ] = MakeUncheckedSharedPointer( node.get(), __FILE__, __LINE__ ); + node->GetINode_I()->ChangeParent( this ); + } else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNodeAlreadyExists, + "a node already exists with the same qualified name", IError_v1::kESOperationFatal, + true, node->GetNameSpace(), true, node->GetName() ); + } + } + + spINode APICALL StructureNodeImpl::ReplaceNode( const spINode & node ) { + if ( CheckSuitabilityToBeUsedAsChildNode( node ) && GetNode( node->GetNameSpace(), node->GetName() ) ) { + auto retValue = RemoveNode( node->GetNameSpace(), node->GetName() ); + InsertNode( node ); + return retValue; + } else { + NOTIFY_ERROR( IError_v1::kEDDataModel, kDMECNoSuchNodeExists, + "no such node exists with the specified qualified name", IError_v1::kESOperationFatal, + true, node->GetNameSpace(), true, node->GetName() ); + } + return spINode(); + } + + void APICALL StructureNodeImpl::AppendNode( const spINode & node ) { + InsertNode( node ); + } + + spINodeIterator APICALL StructureNodeImpl::Iterator() { + AutoSharedLock lock( mSharedMutex ); + auto beginIt = mChildrenMap.begin(), endIt = mChildrenMap.end(); + if ( beginIt == endIt ) + return spINodeIterator(); + else + return MakeUncheckedSharedPointer( new TNodeIteratorImpl< QualifiedNameNodeMap::iterator >( beginIt, endIt ), __FILE__, __LINE__, true ); + } + + sizet APICALL StructureNodeImpl::ChildCount() const __NOTHROW__ { + AutoSharedLock lock( mSharedMutex ); + return mChildrenMap.size(); + } + + spIStructureNode APICALL StructureNodeImpl::ConvertToStructureNode() { + return MakeUncheckedSharedPointer( this, __FILE__, __LINE__ ); + } + + bool APICALL StructureNodeImpl::HasContent() const { + AutoSharedLock lock( mSharedMutex ); + return mChildrenMap.size() > 0; + } + + bool StructureNodeImpl::ValidateNameOrNameSpaceChangeForAChild( const spcIUTF8String & currentNameSpace, const spcIUTF8String & currentName, const spcIUTF8String & newNameSpace, const spcIUTF8String & newName ) { + auto node = GetNode( newNameSpace, newNameSpace ); + if ( node ) { + return false; + } else { + node = RemoveNode( currentNameSpace, currentName ); + AutoSharedLock( mSharedMutex, true ); + mChildrenMap[ QualifiedName( newNameSpace, newName ) ] = node; + return true; + } + } + + void APICALL StructureNodeImpl::ClearContents() { + AutoSharedLock lock( mSharedMutex, true ); + for ( auto it = mChildrenMap.begin(), itEnd = mChildrenMap.end(); it != itEnd; ++it ) { + it->second->GetINode_I()->ChangeParent( NULL ); + } + mChildrenMap.clear(); + } + + spINode APICALL StructureNodeImpl::CloneContents( bool ignoreEmptyNodes, bool ignoreNodesWithOnlyQualifiers, sizet qualifiersCount ) const { + AutoSharedLock lock( mSharedMutex ); + spIStructureNode newNode; + if ( ignoreEmptyNodes && mChildrenMap.size() == 0 ) { + if ( ignoreNodesWithOnlyQualifiers ) + return newNode; + else if ( !ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 ) + return newNode; + } + + newNode = IStructureNode_I::CreateStructureNode( mNameSpace, mName ); + + auto endIt = mChildrenMap.end(); + for ( auto it = mChildrenMap.begin(); it != endIt; ++it ) { + spINode childNode = it->second->Clone( ignoreEmptyNodes, ignoreNodesWithOnlyQualifiers ); + if ( childNode ) { + newNode->AppendNode( childNode ); + } + } + + if ( ignoreEmptyNodes && newNode->ChildCount() == 0 ) { + if ( ignoreNodesWithOnlyQualifiers ) + return spINode(); + else if ( !ignoreNodesWithOnlyQualifiers && qualifiersCount == 0 ) + return spINode(); + } + + return newNode; + } + + void StructureNodeImpl::resetChangesForChildren() const { + AutoSharedLock lock( mSharedMutex ); + for ( auto it = mChildrenMap.begin(), itEnd = mChildrenMap.end(); it != itEnd; ++it ) { + it->second->AcknowledgeChanges(); + } + } + + bool StructureNodeImpl::CompareQualifiedName::operator()( const QualifiedName & key1, const QualifiedName & key2 ) const { + int result = key1.mNameSpace->compare( key2.mNameSpace ); + + if ( result < 0 ) { + return true; + } else if ( result == 0 ) { + result = key1.mName->compare( key2.mName ); + if ( result < 0 ) + return true; + } + return false; + } + + spIStructureNode IStructureNode_I::CreateStructureNode( const spcIUTF8String & nameSpace, const spcIUTF8String name ) { + return MakeUncheckedSharedPointer( new StructureNodeImpl( + nameSpace ? nameSpace->c_str() : NULL, nameSpace ? nameSpace->size() : 0, + name ? name->c_str() : NULL, name ? name->size(): 0 ), __FILE__, __LINE__ ); + } + + template<> + spINode TNodeIteratorImpl< StructureNodeImpl::QualifiedNameNodeMap::iterator >::GetNodeFromIterator( const StructureNodeImpl::QualifiedNameNodeMap::iterator & it ) const { + return MakeUncheckedSharedPointer( it->second.get(), __FILE__, __LINE__, false ); + } +} + +#if BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB +namespace AdobeXMPCore { + using namespace AdobeXMPCore_Int; + + spIStructureNode IStructureNode_v1::MakeShared( pIStructureNode_base ptr ) { + if ( !ptr ) return spIStructureNode(); + pIStructureNode p = IStructureNode::GetInterfaceVersion() > 1 ? ptr->GetInterfacePointer< IStructureNode >() : ptr; + return MakeUncheckedSharedPointer( p, __FILE__, __LINE__, false ); + } + + spIStructureNode IStructureNode_v1::CreateStructureNode( const char * nameSpace, sizet nameSpaceLength, const char * name, sizet nameLength ) { + return MakeUncheckedSharedPointer( new StructureNodeImpl( nameSpace, nameSpaceLength, name, nameLength ), __FILE__, __LINE__, true ); + } +} +#endif // BUILDING_XMPCORE_LIB || SOURCE_COMPILING_XMPCORE_LIB diff --git a/XMPCore/source/WXMPIterator.cpp b/XMPCore/source/WXMPIterator.cpp index 401b468..1c3ebab 100644 --- a/XMPCore/source/WXMPIterator.cpp +++ b/XMPCore/source/WXMPIterator.cpp @@ -13,7 +13,6 @@ #include "XMPCore/source/XMPCore_Impl.hpp" #include "XMPCore/source/XMPIterator.hpp" - #if XMP_WinBuild #pragma warning ( disable : 4101 ) // unreferenced local variable #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced @@ -46,7 +45,11 @@ WXMPIterator_PropCTor_1 ( XMPMetaRef xmpRef, const XMPMeta & xmpObj = WtoXMPMeta_Ref ( xmpRef ); XMP_AutoLock metaLock ( &xmpObj.lock, kXMP_ReadLock ); - XMPIterator * iter = new XMPIterator ( xmpObj, schemaNS, propName, options ); + XMPIterator * iter = NULL; + if (!iter) { + + iter = new XMPIterator(xmpObj, schemaNS, propName, options); + } ++iter->clientRefs; XMP_Assert ( iter->clientRefs == 1 ); wResult->ptrResult = XMPIteratorRef ( iter ); diff --git a/XMPCore/source/WXMPMeta.cpp b/XMPCore/source/WXMPMeta.cpp index 61f13f1..b547f76 100644 --- a/XMPCore/source/WXMPMeta.cpp +++ b/XMPCore/source/WXMPMeta.cpp @@ -13,6 +13,11 @@ #include "XMPCore/source/XMPCore_Impl.hpp" #include "XMPCore/source/XMPMeta.hpp" +#include "XMPCore/source/XMPMeta2.hpp" +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL + #include "XMPCore/Interfaces/IMetadata_I.h" +#endif #if XMP_WinBuild #pragma warning ( disable : 4101 ) // unreferenced local variable @@ -76,7 +81,19 @@ WXMPMeta_CTor_1 ( WXMP_Result * wResult ) { XMP_ENTER_Static ( "WXMPMeta_CTor_1" ) // No lib object yet, use the static entry. - XMPMeta * xmpObj = new XMPMeta(); + XMPMeta * xmpObj( NULL ); + XMP_Bool isCreated = false; + +#if ENABLE_CPP_DOM_MODEL + if ( sUseNewCoreAPIs ) { + xmpObj = new XMPMeta2(); + isCreated = true; + } +#endif + + if(!isCreated) + xmpObj = new XMPMeta(); + ++xmpObj->clientRefs; XMP_Assert ( xmpObj->clientRefs == 1 ); wResult->ptrResult = XMPMetaRef ( xmpObj ); @@ -1005,11 +1022,56 @@ WXMPMeta_Clone_1 ( XMPMetaRef xmpObjRef, { XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_Clone_1" ) - XMPMeta * xClone = new XMPMeta; // ! Don't need an output lock, final ref assignment in client glue. + XMPMeta * xClone ( NULL ); + XMP_Bool isCloned = false; +#if ENABLE_CPP_DOM_MODEL + if(sUseNewCoreAPIs) { + isCloned = true; + try { + const XMPMeta2 & temp = dynamic_cast< const XMPMeta2 & >( thiz ); + xClone = new XMPMeta2; + } + catch ( ... ) { + xClone = new XMPMeta; + } + } +#endif + if(!isCloned) { + xClone = new XMPMeta; + } + + thiz.Clone ( xClone, options ); XMP_Assert ( xClone->clientRefs == 0 ); // ! Gets incremented in TXMPMeta::Clone. wResult->ptrResult = xClone; - + + XMP_EXIT +} + +void +WXMPMeta_GetIXMPMetadata_1(XMPMetaRef xmpObjRef, + WXMP_Result * wResult ) +{ + XMP_ENTER_ObjRead( XMPMeta, "WXMPMeta_GetIXMPMetadata_1" ) + XMP_Bool haveResult = false; +#if ENABLE_CPP_DOM_MODEL + if(sUseNewCoreAPIs){ + haveResult = true; + try { + const XMPMeta2 & temp = dynamic_cast< const XMPMeta2 & >( thiz ); + auto ptr = temp.mDOM.get(); + wResult->ptrResult = ptr; + } catch ( ... ) { + wResult->ptrResult = NULL; + wResult->errMessage = "Not Available"; + } + } +#endif + if(!haveResult) { + wResult->ptrResult = NULL; + wResult->errMessage = "Not Available"; + } + XMP_EXIT } @@ -1132,7 +1194,7 @@ WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef xmpObjRef, if ( indent == 0 ) indent = ""; thiz.SerializeToBuffer ( &localStr, options, padding, newline, indent, baseIndent ); - if ( pktString != 0 ) (*SetClientString) ( pktString, localStr.c_str(), localStr.size() ); + if ( pktString != 0 ) (*SetClientString) ( pktString, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -1184,8 +1246,17 @@ WXMPMeta_ResetErrorCallbackLimit_1 ( XMPMetaRef xmpObjRef, XMP_EXIT } -// ================================================================================================= +void WXMPMeta_Use_CPP_DOM_APIs_1(XMP_Bool useNewCoreAPIs, + WXMP_Result * wResult ) +{ +#if ENABLE_CPP_DOM_MODEL + XMP_ENTER_Static ( "WXMPMeta_Use_CPP_DOM_APIs_1" ) + sUseNewCoreAPIs = useNewCoreAPIs; + XMP_EXIT +#endif +} +// ================================================================================================= #if __cplusplus } /* extern "C" */ #endif diff --git a/XMPCore/source/WXMPUtils.cpp b/XMPCore/source/WXMPUtils.cpp index 6d8f995..a31453c 100644 --- a/XMPCore/source/WXMPUtils.cpp +++ b/XMPCore/source/WXMPUtils.cpp @@ -10,7 +10,6 @@ #include "public/include/XMP_Environment.h" // ! This must be the first include! #include "public/include/XMP_Const.h" - #include "public/include/client-glue/WXMPUtils.hpp" #include "XMPCore/source/XMPCore_Impl.hpp" @@ -49,7 +48,7 @@ WXMPUtils_ComposeArrayItemPath_1 ( XMP_StringPtr schemaNS, XMP_VarString localStr; XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &localStr ); - if ( itemPath != 0 ) (*SetClientString) ( itemPath, localStr.c_str(), localStr.size() ); + if ( itemPath != 0 ) (*SetClientString) ( itemPath, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -75,7 +74,7 @@ WXMPUtils_ComposeStructFieldPath_1 ( XMP_StringPtr schemaNS, XMP_VarString localStr; XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &localStr ); - if ( fieldPath != 0 ) (*SetClientString) ( fieldPath, localStr.c_str(), localStr.size() ); + if ( fieldPath != 0 ) (*SetClientString) ( fieldPath, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() )); XMP_EXIT } @@ -101,7 +100,7 @@ WXMPUtils_ComposeQualifierPath_1 ( XMP_StringPtr schemaNS, XMP_VarString localStr; XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &localStr ); - if ( qualPath != 0 ) (*SetClientString) ( qualPath, localStr.c_str(), localStr.size() ); + if ( qualPath != 0 ) (*SetClientString) ( qualPath, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -125,7 +124,7 @@ WXMPUtils_ComposeLangSelector_1 ( XMP_StringPtr schemaNS, XMP_VarString localStr; XMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName, &localStr ); - if ( selPath != 0 ) (*SetClientString) ( selPath, localStr.c_str(), localStr.size() ); + if ( selPath != 0 ) (*SetClientString) ( selPath, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -153,7 +152,7 @@ WXMPUtils_ComposeFieldSelector_1 ( XMP_StringPtr schemaNS, XMP_VarString localStr; XMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, &localStr ); - if ( selPath != 0 ) (*SetClientString) ( selPath, localStr.c_str(), localStr.size() ); + if ( selPath != 0 ) (*SetClientString) ( selPath, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() )); XMP_EXIT } @@ -171,7 +170,7 @@ WXMPUtils_ConvertFromBool_1 ( XMP_Bool binValue, XMP_VarString localStr; XMPUtils::ConvertFromBool ( binValue, &localStr ); - if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() ); + if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -192,7 +191,7 @@ WXMPUtils_ConvertFromInt_1 ( XMP_Int32 binValue, XMP_VarString localStr; XMPUtils::ConvertFromInt ( binValue, format, &localStr ); - if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() ); + if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -213,7 +212,7 @@ WXMPUtils_ConvertFromInt64_1 ( XMP_Int64 binValue, XMP_VarString localStr; XMPUtils::ConvertFromInt64 ( binValue, format, &localStr ); - if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() ); + if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -234,7 +233,7 @@ WXMPUtils_ConvertFromFloat_1 ( double binValue, XMP_VarString localStr; XMPUtils::ConvertFromFloat ( binValue, format, &localStr ); - if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() ); + if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -252,7 +251,7 @@ WXMPUtils_ConvertFromDate_1 ( const XMP_DateTime & binValue, XMP_VarString localStr; XMPUtils::ConvertFromDate( binValue, &localStr ); - if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), localStr.size() ); + if ( strValue != 0 ) (*SetClientString) ( strValue, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() ) ); XMP_EXIT } @@ -417,7 +416,7 @@ WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr rawStr, XMP_VarString localStr; XMPUtils::EncodeToBase64 ( rawStr, rawLen, &localStr ); - if ( encodedStr != 0 ) (*SetClientString) ( encodedStr, localStr.c_str(), localStr.size() ); + if ( encodedStr != 0 ) (*SetClientString) ( encodedStr, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size()) ); XMP_EXIT } @@ -436,7 +435,7 @@ WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr encodedStr, XMP_VarString localStr; XMPUtils::DecodeFromBase64 ( encodedStr, encodedLen, &localStr ); - if ( rawStr != 0 ) (*SetClientString) ( rawStr, localStr.c_str(), localStr.size() ); + if ( rawStr != 0 ) (*SetClientString) ( rawStr, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size()) ); XMP_EXIT } @@ -461,9 +460,9 @@ WXMPUtils_PackageForJPEG_1 ( XMPMetaRef wxmpObj, XMP_AutoLock metaLock ( &xmpObj.lock, kXMP_ReadLock ); 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() ); + if ( stdStr != 0 ) (*SetClientString) ( stdStr, localStdStr.c_str(), static_cast< XMP_StringLen >( localStdStr.size()) ); + if ( extStr != 0 ) (*SetClientString) ( extStr, localExtStr.c_str(), static_cast< XMP_StringLen >( localExtStr.size()) ); + if ( digestStr != 0 ) (*SetClientString) ( digestStr, localDigestStr.c_str(), static_cast< XMP_StringLen >( localDigestStr.size()) ); XMP_EXIT } @@ -518,7 +517,7 @@ WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef wxmpObj, 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() ); + if ( catedStr != 0 ) (*SetClientString) ( catedStr, localStr.c_str(), static_cast< XMP_StringLen >( localStr.size() )); XMP_EXIT } diff --git a/XMPCore/source/XMPCore_Impl.cpp b/XMPCore/source/XMPCore_Impl.cpp index ddae20a..daec535 100644 --- a/XMPCore/source/XMPCore_Impl.cpp +++ b/XMPCore/source/XMPCore_Impl.cpp @@ -10,9 +10,7 @@ #include "public/include/XMP_Version.h" #include "XMPCore/source/XMPCore_Impl.hpp" #include "XMPCore/source/XMPMeta.hpp" // *** For use of GetNamespacePrefix in FindSchemaNode. - #include "source/UnicodeInlines.incl_cpp" - #include <algorithm> using namespace std; @@ -56,6 +54,8 @@ XMP_NamespaceTable * sRegisteredNamespaces = 0; XMP_AliasMap * sRegisteredAliasMap = 0; +XMP_ReadWriteLock * sDefaultNamespacePrefixMapLock = 0; + void * voidVoidPtr = 0; // Used to backfill null output parameters. XMP_StringPtr voidStringPtr = 0; XMP_StringLen voidStringLen = 0; @@ -68,6 +68,60 @@ double voidDouble = 0.0; XMP_DateTime voidDateTime; WXMP_Result void_wResult; + #if ENABLE_CPP_DOM_MODEL + XMP_Bool sUseNewCoreAPIs = false; + #endif + + #if ! XMP_StaticBuild + + #undef malloc + #undef free + typedef void * (*XMP_AllocateProc) (size_t size); + + typedef void(*XMP_DeleteProc) (void * ptr); + + XMP_AllocateProc sXMP_MemAlloc = malloc; + XMP_DeleteProc sXMP_MemFree = free; + #define malloc(size) (*sXMP_MemAlloc) ( size ) + #define free(addr) (*sXMP_MemFree) ( addr ) + + void * operator new ( size_t len ) throw ( std::bad_alloc ) + { + void * mem = (*sXMP_MemAlloc) ( len ); + if ( (mem == 0) && (len != 0) ) throw std::bad_alloc(); + return mem; + } + + void * operator new( std::size_t len, const std::nothrow_t & nothrow ) throw () { + void * mem = (*sXMP_MemAlloc) ( len ); + return mem; + } + + void * operator new[] ( size_t len ) throw ( std::bad_alloc ) + { + void * mem = (*sXMP_MemAlloc) ( len ); + if ( (mem == 0) && (len != 0) ) throw std::bad_alloc(); + return mem; + } + + void operator delete ( void * ptr ) throw() + { + if ( ptr != 0 ) (*sXMP_MemFree) ( ptr ); + } + + void operator delete ( void * ptr, const std::nothrow_t & nothrow ) throw () + { + return operator delete( ptr ); + } + + void operator delete[] ( void * ptr ) throw() + { + if ( ptr != 0 ) (*sXMP_MemFree) ( ptr ); + } + +#endif + + // ================================================================================================= // Local Utilities // =============== @@ -212,7 +266,7 @@ FindIndexedItem ( XMP_Node * arrayNode, const XMP_VarString & indexStep, bool cr // The value portion is a string quoted by ''' or '"'. The value may contain any character including // a doubled quoting character. The value may be empty. -static void +void SplitNameAndValue ( const XMP_VarString & selStep, XMP_VarString * nameStr, XMP_VarString * valueStr ) { XMP_StringPtr partBegin = selStep.c_str(); @@ -263,7 +317,7 @@ SplitNameAndValue ( const XMP_VarString & selStep, XMP_VarString * nameStr, XMP_ static XMP_Index LookupQualSelector ( XMP_Node * arrayNode, const XMP_VarString & qualName, XMP_VarString & qualValue ) { - XMP_Index index; + size_t index; if ( qualName == "xml:lang" ) { @@ -273,7 +327,7 @@ LookupQualSelector ( XMP_Node * arrayNode, const XMP_VarString & qualName, XMP_V } else { - XMP_Index itemLim; + size_t itemLim; for ( index = 0, itemLim = arrayNode->children.size(); index != itemLim; ++index ) { const XMP_Node * currItem = arrayNode->children[index]; @@ -293,7 +347,7 @@ LookupQualSelector ( XMP_Node * arrayNode, const XMP_VarString & qualName, XMP_V } - return index; + return static_cast<XMP_Index>( index ); } // LookupQualSelector @@ -348,7 +402,7 @@ FollowXPathStep ( XMP_Node * parentNode, if ( stepKind == kXMP_ArrayIndexStep ) { index = FindIndexedItem ( parentNode, nextStep.step, createNodes ); } else if ( stepKind == kXMP_ArrayLastStep ) { - index = parentNode->children.size() - 1; + index = static_cast<XMP_Index>( parentNode->children.size() - 1 ); } else if ( stepKind == kXMP_FieldSelectorStep ) { XMP_VarString fieldName, fieldValue; SplitNameAndValue ( nextStep.step, &fieldName, &fieldValue ); @@ -588,7 +642,7 @@ ExpandXPath ( XMP_StringPtr schemaNS, XMP_Assert ( (schemaNS != 0) && (propPath != 0) && (*propPath != 0) && (expandedXPath != 0) ); XMP_StringPtr stepBegin, stepEnd; - XMP_StringPtr qualName, nameEnd; + XMP_StringPtr qualName = 0 , nameEnd = 0; XMP_VarString currStep; size_t resCount = 2; // Guess at the number of steps. At least 2, plus 1 for each '/' or '['. @@ -748,7 +802,9 @@ XMP_Node * FindSchemaNode ( XMP_Node * xmpTree, XMP_StringPtr nsURI, bool createNodes, - XMP_NodePtrPos * ptrPos /* = 0 */ ) + XMP_NodePtrPos * ptrPos /* = 0 */, + PrefixSearchFnPtr prefixSearchFnPtr/* = NULL*/, + void * privateData/* = NULL*/ ) { XMP_Node * schemaNode = 0; @@ -771,7 +827,13 @@ FindSchemaNode ( XMP_Node * xmpTree, try { XMP_StringPtr prefixPtr; XMP_StringLen prefixLen; - bool found = XMPMeta::GetNamespacePrefix ( nsURI, &prefixPtr, &prefixLen ); // *** Use map directly? + bool found ( false ); + if (prefixSearchFnPtr && privateData) { + found = prefixSearchFnPtr ( privateData, nsURI, &prefixPtr, &prefixLen ); + } + else { + found = XMPMeta::GetNamespacePrefix ( nsURI, &prefixPtr, &prefixLen ); // *** Use map directly? + } XMP_Assert ( found ); schemaNode->value.assign ( prefixPtr, prefixLen ); } catch (...) { // Don't leak schemaNode in case of an exception before adding it to the children vector. @@ -919,7 +981,7 @@ FindQualifierNode ( XMP_Node * parent, XMP_Index LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_StringPtr fieldValue ) { - XMP_Index index, itemLim; + size_t index, itemLim; for ( index = 0, itemLim = arrayNode->children.size(); index != itemLim; ++index ) { @@ -942,7 +1004,7 @@ LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_S } if ( index == itemLim ) index = -1; - return index; + return static_cast<XMP_Index>( index ); } // LookupFieldSelector @@ -959,8 +1021,8 @@ LookupLangItem ( const XMP_Node * arrayNode, XMP_VarString & lang ) XMP_Throw ( "Language item must be used on array", kXMPErr_BadXPath ); } - XMP_Index index = 0; - XMP_Index itemLim = arrayNode->children.size(); + size_t index = 0; + size_t itemLim = arrayNode->children.size(); for ( ; index != itemLim; ++index ) { const XMP_Node * currItem = arrayNode->children[index]; @@ -970,7 +1032,7 @@ LookupLangItem ( const XMP_Node * arrayNode, XMP_VarString & lang ) } if ( index == itemLim ) index = -1; - return index; + return static_cast<XMP_Index>( index ); } // LookupLangItem diff --git a/XMPCore/source/XMPCore_Impl.hpp b/XMPCore/source/XMPCore_Impl.hpp index 180f581..52aa114 100644 --- a/XMPCore/source/XMPCore_Impl.hpp +++ b/XMPCore/source/XMPCore_Impl.hpp @@ -58,10 +58,28 @@ typedef XMP_AliasMap::const_iterator XMP_cAliasMapPos; extern XMP_Int32 sXMP_InitCount; +typedef void * (*XMP_AllocateProc) (size_t size); + +typedef void(*XMP_DeleteProc) (void * ptr); + +#if ! XMP_StaticBuild + + extern XMP_AllocateProc sXMP_MemAlloc; + extern XMP_DeleteProc sXMP_MemFree; + + #define malloc(size) (*sXMP_MemAlloc) ( size ) + #define free(addr) (*sXMP_MemFree) ( addr ) + +#endif + + +extern XMP_Bool sUseNewCoreAPIs; extern XMP_NamespaceTable * sRegisteredNamespaces; extern XMP_AliasMap * sRegisteredAliasMap; +extern XMP_ReadWriteLock * sDefaultNamespacePrefixMapLock; + #define WtoXMPMeta_Ref(xmpRef) (const XMPMeta &) (*((XMPMeta*)(xmpRef))) #define WtoXMPMeta_Ptr(xmpRef) ((XMPMeta*)(xmpRef)) @@ -151,9 +169,9 @@ extern WXMP_Result void_wResult; #define kXMP_ExistingOnly false #define FindConstSchema(t,u) FindSchemaNode ( const_cast<XMP_Node*>(t), u, kXMP_ExistingOnly, 0 ) -#define FindConstChild(p,c) FindChildNode ( const_cast<XMP_Node*>(p), c, kXMP_ExistingOnly, 0 ) +#define FindConstChild(p,c) ::FindChildNode ( const_cast<XMP_Node*>(p), c, kXMP_ExistingOnly, 0 ) #define FindConstQualifier(p,c) FindQualifierNode ( const_cast<XMP_Node*>(p), c, kXMP_ExistingOnly, 0 ) -#define FindConstNode(t,p) FindNode ( const_cast<XMP_Node*>(t), p, kXMP_ExistingOnly, 0 ) +#define FindConstNode(t,p) ::FindNode ( const_cast<XMP_Node*>(t), p, kXMP_ExistingOnly, 0 ) extern XMP_OptionBits VerifySetOptions ( XMP_OptionBits options, XMP_StringPtr propValue ); @@ -167,11 +185,15 @@ ExpandXPath ( XMP_StringPtr schemaNS, XMP_StringPtr propPath, XMP_ExpandedXPath * expandedXPath ); +typedef bool (*PrefixSearchFnPtr) ( void * privateData, XMP_StringPtr nsURI, XMP_StringPtr * namespacePrefix, XMP_StringLen * prefixSize ); + extern XMP_Node * FindSchemaNode ( XMP_Node * xmpTree, XMP_StringPtr nsURI, bool createNodes, - XMP_NodePtrPos * ptrPos = 0 ); + XMP_NodePtrPos * ptrPos = 0, + PrefixSearchFnPtr prefixSearchFnPtr = NULL, + void * privateData = NULL ); extern XMP_Node * FindChildNode ( XMP_Node * parent, @@ -229,7 +251,7 @@ static inline bool IsPathPrefix ( XMP_StringPtr fullPath, XMP_StringPtr prefix ) { bool isPrefix = false; - XMP_StringLen prefixLen = strlen(prefix); + XMP_StringLen prefixLen = static_cast< XMP_StringLen >( strlen(prefix) ); if ( XMP_LitNMatch ( prefix, fullPath, prefixLen ) ) { char separator = fullPath[prefixLen]; if ( (separator == 0) || (separator == '/') || @@ -334,6 +356,8 @@ public: void GetLocalURI ( XMP_StringPtr * uriStr, XMP_StringLen * uriSize ) const; + void GetFullQualifiedName( XMP_StringPtr * uriStr, XMP_StringLen * uriSize, XMP_StringPtr * nameStr, XMP_StringLen * nameSize ) const; + void RemoveChildren() { for ( size_t i = 0, vLim = children.size(); i < vLim; ++i ) { @@ -359,6 +383,8 @@ public: this->RemoveQualifiers(); } + void SetValue( XMP_StringPtr value ); + virtual ~XMP_Node() { RemoveChildren(); RemoveQualifiers(); }; private: diff --git a/XMPCore/source/XMPIterator.cpp b/XMPCore/source/XMPIterator.cpp index 5d0c24b..275e32f 100644 --- a/XMPCore/source/XMPIterator.cpp +++ b/XMPCore/source/XMPIterator.cpp @@ -489,9 +489,8 @@ XMPIterator::XMPIterator ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_OptionBits options ) : info(IterInfo(options,0)), clientRefs(0) { - - XMP_Throw ( "Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented ); - void * p; p = &schemaNS; p = &propName; p = &options; // Avoid unused param warnings. + void * p; p = &schemaNS; p = &propName; p = &options; // Avoid unused param warnings. + XMP_Throw("Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented); } // XMPIterator for global tables @@ -553,7 +552,7 @@ XMPIterator::Next ( XMP_StringPtr * schemaNS, } *schemaNS = info.currSchema.c_str(); - *nsSize = info.currSchema.size(); + *nsSize = static_cast<XMP_StringLen>(info.currSchema.size()); *propOptions = info.currPos->options; @@ -565,7 +564,7 @@ XMPIterator::Next ( XMP_StringPtr * schemaNS, if ( ! (*propOptions & kXMP_SchemaNode) ) { *propPath = info.currPos->fullPath.c_str(); - *pathSize = info.currPos->fullPath.size(); + *pathSize = static_cast<XMP_StringLen>(info.currPos->fullPath.size()); if ( info.options & kXMP_IterJustLeafName ) { *propPath += info.currPos->leafOffset; @@ -575,7 +574,7 @@ XMPIterator::Next ( XMP_StringPtr * schemaNS, if ( ! (*propOptions & kXMP_PropCompositeMask) ) { *propValue = xmpNode->value.c_str(); - *valueSize = xmpNode->value.size(); + *valueSize = static_cast<XMP_StringLen>(xmpNode->value.size()); } } diff --git a/XMPCore/source/XMPIterator.hpp b/XMPCore/source/XMPIterator.hpp index 1bdc1f3..544bf34 100644 --- a/XMPCore/source/XMPIterator.hpp +++ b/XMPCore/source/XMPIterator.hpp @@ -108,7 +108,7 @@ public: virtual ~XMPIterator() RELEASE_NO_THROW; - bool + virtual bool Next ( XMP_StringPtr * schemaNS, XMP_StringLen * nsSize, XMP_StringPtr * propPath, @@ -117,7 +117,7 @@ public: XMP_StringLen * valueSize, XMP_OptionBits * propOptions ); - void + virtual void Skip ( XMP_OptionBits options ); // ! Expose so that wrappers and file static functions can see the data. diff --git a/XMPCore/source/XMPIterator2.cpp b/XMPCore/source/XMPIterator2.cpp new file mode 100644 index 0000000..586fa35 --- /dev/null +++ b/XMPCore/source/XMPIterator2.cpp @@ -0,0 +1,542 @@ +// ================================================================================================= +// Copyright 2003 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "public/include/XMP_Environment.h" // ! This must be the first include! +#include "XMPCore/source/XMPCore_Impl.hpp" + +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL +#include "XMPCore/source/XMPIterator2.hpp" +#include "XMPCore/source/XMPMeta2.hpp" +#include "XMPCore/source/XMPUtils.hpp" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include <map> +#include <string> +#include <stdio.h> // For snprintf. + +#if XMP_WinBuild + #pragma warning ( disable : 4702 ) // unreachable code + #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) + #pragma warning ( disable : 4996 ) // '...' was declared deprecated +#endif + +// ================================================================================================= +// Support Routines +// ================================================================================================= + + +#ifndef TraceIterators + #define TraceIterators 0 +#endif + +#if TraceIterators + static const char * sStageNames[] = { "before", "self", "qualifiers", "children" }; +#endif + + +XMP_VarString GetNameSpace( const AdobeXMPCommon::spcIUTF8String & nameSpace ) +{ + auto defaultMap = AdobeXMPCore::INameSpacePrefixMap::GetDefaultNameSpacePrefixMap()->GetINameSpacePrefixMap_I(); + auto prefix = defaultMap->GetPrefix( nameSpace ); + return prefix->c_str(); +} + + +XMP_VarString NodeFullName( const AdobeXMPCore::spcINode & node ) +{ + XMP_VarString name = GetNameSpace(node->GetNameSpace()) + ":" + node->GetName()->c_str(); + return name; +} + +void XMPIterator2::AddSchemaProperties(IteratorNode & iterSchema, const char * nameSpace) +{ + using namespace AdobeXMPCore; + + for (auto childIter = mDOM->Iterator(); childIter; childIter = childIter->Next()) { + + spINode childNode = childIter->GetNode(); + //TODO check name + if (!strcmp(childNode->GetNameSpace()->c_str(), nameSpace)) { + iterSchema.nodeChildren.push_back(IteratorNode( XMPUtils::GetIXMPOptions(childNode), NodeFullName(childNode), 0 )); + } + + } + +} + void XMPIterator2::SetCurrentSchema(XMP_StringPtr schemaName) +{ + + info.currSchema = schemaName; + +} // SetCurrSchema + + void XMPIterator2::SetCurrentSchema(XMP_VarString & schemaName) +{ + + info.currSchema = schemaName; + +} // SetCurrSchema + +void XMPIterator2::AdvanceIteratorPosition() +{ + + while (true) { + + if (info.currPos == info.endPos) { + + if (info.ancestors.empty()) break; + + IteratorPosPair & parent = info.ancestors.back(); + info.currPos = parent.first; + info.endPos = parent.second; + info.ancestors.pop_back(); + } + else { + + if (info.currPos->visitStage == kIter_BeforeVisit) { + if (info.currPos->options & kXMP_SchemaNode) SetCurrentSchema(info.currPos->fullPath); + break; + } + + + if (info.currPos->visitStage == kIter_VisitSelf) { + + info.currPos->visitStage = kIter_VisitQualifiers; + if (!info.currPos->nodeQualifiers.empty()) { + + info.ancestors.push_back(IteratorPosPair(info.currPos, info.endPos)); + info.endPos = info.currPos->nodeQualifiers.end(); + info.currPos = info.currPos->nodeQualifiers.begin(); + break; + } + } + + if (info.currPos->visitStage == kIter_VisitQualifiers) { // Just finished visiting the qualifiers. + info.currPos->nodeQualifiers.clear(); + info.currPos->visitStage = kIter_VisitChildren; // Start visiting the children. + if (!info.currPos->nodeChildren.empty()) { + info.ancestors.push_back(IteratorPosPair(info.currPos, info.endPos)); + info.endPos = info.currPos->nodeChildren.end(); // ! Set the parent's endPos before changing currPos! + info.currPos = info.currPos->nodeChildren.begin(); + break; + } + } + + if (info.currPos->visitStage == kIter_VisitChildren) { + info.currPos->nodeChildren.clear(); + ++info.currPos; + continue; + } + } + } + + XMP_Assert((info.currPos == info.endPos) || (info.currPos->visitStage == kIter_BeforeVisit)); + +} + +AdobeXMPCore::spINode XMPIterator2::GetNextNode(bool & isSchema) +{ + using namespace AdobeXMPCore; + spINode xmpNode = spINode(); + + if (info.currPos->visitStage != kIter_BeforeVisit) AdvanceIteratorPosition(); + + bool isSchemaNode = false; + XMP_ExpandedXPath exPath; + + while (info.currPos != info.endPos) { + + isSchemaNode = XMP_NodeIsSchema(info.currPos->options); + if (isSchemaNode) { + + SetCurrentSchema(info.currPos->fullPath); + + isSchema = isSchemaNode; + } + else { + + ExpandXPath(info.currSchema.c_str(), info.currPos->fullPath.c_str(), &exPath); + bool found = XMPUtils::FindCnstNode(mDOM, exPath, xmpNode); + } + if (xmpNode || isSchemaNode) break; + + info.currPos->visitStage = kIter_VisitChildren; + info.currPos->nodeChildren.clear(); + info.currPos->nodeQualifiers.clear(); + + AdvanceIteratorPosition(); + } + + if (info.currPos == info.endPos) return spINode(); + + XMP_Assert(info.currPos->visitStage == kIter_BeforeVisit); + + if (info.currPos->visitStage == kIter_BeforeVisit) { + + if (!isSchemaNode && !(info.options & kXMP_IterJustChildren)) { + + AddNodeOffSpring(*info.currPos, xmpNode); + } + info.currPos->visitStage = kIter_VisitSelf; + } + + return xmpNode; +} + +void XMPIterator2::AddNodeOffSpring(IteratorNode &iterParent, const AdobeXMPCore::spINode & xmpParent) +{ + + using namespace AdobeXMPCore; + XMP_VarString currPath(iterParent.fullPath); + size_t leafOffset = currPath.size(); + if (xmpParent->HasQualifiers() && (!(info.options & kXMP_IterOmitQualifiers))) { + + currPath += "/?"; // All qualifiers are named and use paths like "Prop/?Qual". + leafOffset += 2; + + for ( auto qualIter = xmpParent->QualifiersIterator(); qualIter; qualIter = qualIter->Next() ) { + + spINode qualNode = qualIter->GetNode(); + //TOTO Add prefix too + currPath += NodeFullName( qualNode ); + + iterParent.nodeQualifiers.push_back( IteratorNode( XMPUtils::GetIXMPOptions( qualNode ), currPath, leafOffset ) ); + currPath.erase( leafOffset ); + } + + leafOffset -= 2; + currPath.erase(leafOffset); + + } + if (XMPUtils::GetNodeChildCount(xmpParent)) { + + + + if (xmpParent->GetNodeType() == INode::kNTStructure) { + currPath += '/'; + leafOffset += 1; + } + size_t childIdx = 0; + for (auto childIter = XMPUtils::GetNodeChildIterator(xmpParent); childIter; childIter = childIter->Next(), ++childIdx) { + + spcINode xmpChild = childIter->GetNode(); + if (xmpParent->GetNodeType() != INode::kNTArray) { + //TODO Add prefix as well + currPath += NodeFullName(xmpChild); + } + else { + + char buffer[32]; // AUDIT: Using sizeof(buffer) below for snprintf length is safe. + #if XMP_WinBuild + snprintf(buffer, sizeof(buffer), "[%Iu]", childIdx + 1); // ! XPath indices are one-based. + #else + snprintf(buffer, sizeof(buffer), "[%zu]", childIdx + 1); + #endif + currPath += buffer; + } + + iterParent.nodeChildren.push_back(IteratorNode(XMPUtils::GetIXMPOptions(xmpChild), currPath, leafOffset)); + currPath.erase(leafOffset); + + } + + + } + + + + } // AddNodeOffspring + +// ================================================================================================= +// Constructors +// ================================================================================================= + +// ------------------------------------------------------------------------------------------------- +// XMPIterator +// ----------- +// +// Constructor for iterations over the nodes in an XMPMeta object. This builds a tree of iteration +// nodes that caches the existing node names of the XMPMeta object. The iteration tree is a partial +// replica of the XMPMeta tree. The initial iteration tree normally has just the root node, all of +// the schema nodes for a full object iteration. Lower level nodes (children and qualifiers) are +// added when the parent is visited. If the kXMP_IterJustChildren option is passed then the initial +// iterator includes the children and the parent is marked as done. The iteration tree nodes are +// pruned when they are no longer needed. + +XMPIterator2::XMPIterator2 ( const XMPMeta & xmpObjBase, + XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_OptionBits options) :XMPIterator(xmpObjBase, schemaNS, propName, options) +{ + using namespace AdobeXMPCore; + if ( (options & kXMP_IterClassMask) != kXMP_IterProperties ) { + XMP_Throw ( "Unsupported iteration kind", kXMPErr_BadOptions ); + } + iteratorOptions = options; + info.options = options; + + if(sUseNewCoreAPIs) { + + const XMPMeta2 & tempPtr = dynamic_cast<const XMPMeta2 &>(xmpObjBase); + + } + else { + XMP_Throw("Unsupported iteration kind", kXMPErr_BadOptions); + } + + const XMPMeta2 & xmpObj = dynamic_cast<const XMPMeta2 &>(xmpObjBase); + + spIMetadata root = xmpObj.mDOM; + mDOM = xmpObj.mDOM; + // *** Lock the XMPMeta object if we ever stop using a full DLL lock. + + if ( *propName != 0 ) { + XMP_ExpandedXPath propPath; + ExpandXPath(schemaNS, propName, &propPath); + spINode destNode; + XMP_OptionBits destOptions = 0; + bool nodeFound = XMPUtils::FindCnstNode(root, propPath, destNode,&destOptions); + + if (nodeFound) { + + XMP_VarString rootName(propPath[1].step); // The schema is [0]. + for (size_t i = 2; i < propPath.size(); ++i) { + XMP_OptionBits stepKind = GetStepKind(propPath[i].options); + if (stepKind <= kXMP_QualifierStep) rootName += '/'; + rootName += propPath[i].step; + } + + propName = rootName.c_str(); + size_t leafOffset = rootName.size(); + while ((leafOffset > 0) && (propName[leafOffset] != '/') && (propName[leafOffset] != '[')) --leafOffset; + if (propName[leafOffset] == '/') ++leafOffset; + + info.tree.nodeChildren.push_back( IteratorNode( destOptions, propName, leafOffset ) ); + SetCurrentSchema(propPath[kSchemaStep].step.c_str()); + if (options & kXMP_IterJustChildren) { + + AddNodeOffSpring(info.tree.nodeChildren.back(), destNode); + } + + } + + + } else if ( *schemaNS != 0 ) { + + info.tree.nodeChildren.push_back(IteratorNode(kXMP_SchemaNode, schemaNS, 0)); + IteratorNode & iterSchema = info.tree.nodeChildren.back(); + + bool schemaFound = false; + + for (auto childIter = mDOM->Iterator(); childIter; childIter = childIter->Next()) { + + if (!strcmp(childIter->GetNode()->GetNameSpace()->c_str(), schemaNS)) { + + schemaFound = true; + break; + } + } + + + if (schemaFound) AddSchemaProperties(iterSchema, schemaNS); + + if (iterSchema.nodeChildren.empty()) { + info.tree.nodeChildren.pop_back(); // No properties, remove the schema node. + } + else { + SetCurrentSchema(schemaNS); + } + + + } else { + + std::map < XMP_VarString, bool > schemaProperties; + + for (auto childIter = mDOM->Iterator(); childIter; childIter = childIter->Next()) { + + spINode childNode = childIter->GetNode(); + + schemaProperties[childNode->GetNameSpace()->c_str()] = true; + } + + + for (auto key : schemaProperties) { + //TODO check name + info.tree.nodeChildren.push_back(IteratorNode( kXMP_SchemaNode, key.first, 0 )); + + IteratorNode & iterSchema = info.tree.nodeChildren.back(); + + if (!(info.options & kXMP_IterJustChildren)) { + AddSchemaProperties(iterSchema, key.first.c_str()); + // if (iterSchema.nodeChildren.empty()) info.tree.nodeChildren.pop_back(); // No properties, remove the schema node. + } + } + + + + + } + + info.currPos = info.tree.nodeChildren.begin(); + info.endPos = info.tree.nodeChildren.end(); + + if ((info.options & kXMP_IterJustChildren) && (info.currPos != info.endPos) && (*schemaNS != 0)) { + info.currPos->visitStage = kIter_VisitSelf; + } + + + +} // XMPIterator for XMPMeta objects + +// ------------------------------------------------------------------------------------------------- +// XMPIterator +// ----------- +// +// Constructor for iterations over global tables such as registered namespaces or aliases. + +XMPIterator2::XMPIterator2 ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_OptionBits options) : XMPIterator(schemaNS, propName, options) +{ + void * p; p = &schemaNS; p = &propName; p = &options; // Avoid unused param warnings. + XMP_Throw("Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented); + +} // XMPIterator for global tables + +// ------------------------------------------------------------------------------------------------- +// ~XMPIterator +// ----------- + +XMPIterator2::~XMPIterator2() RELEASE_NO_THROW +{ + + // Let everything else default. + +} // ~XMPIterator + +// ================================================================================================= +// Iteration Methods +// ================================================================================================= + +// ------------------------------------------------------------------------------------------------- +// Next +// ---- +// +// Do a preorder traversal of the cached nodes. + +// *** Need to document the relationships between currPos, endPos, and visitStage. + +bool +XMPIterator2::Next ( XMP_StringPtr * schemaNS, + XMP_StringLen * nsSize, + XMP_StringPtr * propPath, + XMP_StringLen * pathSize, + XMP_StringPtr * propValue, + XMP_StringLen * valueSize, + XMP_OptionBits * propOptions ) +{ + + if (info.currPos == info.endPos) return false; + using namespace AdobeXMPCore; + using namespace AdobeXMPCommon; + bool isSchema = false; + spcINode xmpNode = GetNextNode(isSchema); + if (!xmpNode && !isSchema) return false; + bool isSchemaNode = isSchema; + if (info.options & kXMP_IterJustLeafNodes) { + while (isSchemaNode || ( xmpNode && XMPUtils::GetNodeChildCount(xmpNode))) { + info.currPos->visitStage = kIter_VisitQualifiers; // Skip to this node's children. + xmpNode = GetNextNode(isSchemaNode); + if (xmpNode == 0 && !isSchemaNode) return false; + isSchemaNode = XMP_NodeIsSchema(info.currPos->options); + } + } + + *schemaNS = info.currSchema.c_str(); + *nsSize = info.currSchema.size(); + + + *propOptions = info.currPos->options; + + *propPath = ""; + *pathSize = 0; + *propValue = ""; + *valueSize = 0; + + if (!(*propOptions & kXMP_SchemaNode)) { + + *propPath = info.currPos->fullPath.c_str(); + *pathSize = info.currPos->fullPath.size(); + + if (info.options & kXMP_IterJustLeafName) { + *propPath += info.currPos->leafOffset; + *pathSize -= info.currPos->leafOffset; + if (! xmpNode->IsArrayItem()) { + *schemaNS = xmpNode->GetNameSpace()->c_str(); + *nsSize = xmpNode->GetNameSpace()->size(); + } + else { + *schemaNS = ""; + *nsSize = 0; + } + + } + + if (!(*propOptions & kXMP_PropCompositeMask)) { + spcIUTF8String nodeValue = xmpNode->ConvertToSimpleNode()->GetValue(); + *propValue = nodeValue->c_str(); + *valueSize = nodeValue->size(); + } + + } + + return true; +} // Next + +// ------------------------------------------------------------------------------------------------- +// Skip +// ---- +// +// Skip some portion of the traversal related to the last visited node. We skip either that node's +// children, or those children and the previous node's siblings. The implementation might look a bit +// awkward because info.currNode always points to the next node to be visited. We might already have +// moved past the things to skip, e.g. if the previous node was simple and the last of its siblings. + +enum { + kXMP_ValidIterSkipOptions = kXMP_IterSkipSubtree | kXMP_IterSkipSiblings +}; + + +void +XMPIterator2::Skip ( XMP_OptionBits iterOptions ) +{ + // if ( (info.currPos == kIter_NullPos) ) XMP_Throw ( "No prior postion to skip from", kXMPErr_BadIterPosition ); + if (iterOptions == 0) XMP_Throw("Must specify what to skip", kXMPErr_BadOptions); + if ((iterOptions & ~kXMP_ValidIterSkipOptions) != 0) XMP_Throw("Undefined options", kXMPErr_BadOptions); + + + if (iterOptions & kXMP_IterSkipSubtree) { + + info.currPos->visitStage = kIter_VisitChildren; + } + else if (iterOptions & kXMP_IterSkipSiblings) { + + info.currPos = info.endPos; + AdvanceIteratorPosition(); + } + +} // Skip + + + +// ================================================================================================= +#endif // ENABLE_CPP_DOM_MODEL
\ No newline at end of file diff --git a/XMPCore/source/XMPIterator2.hpp b/XMPCore/source/XMPIterator2.hpp new file mode 100644 index 0000000..6664a53 --- /dev/null +++ b/XMPCore/source/XMPIterator2.hpp @@ -0,0 +1,153 @@ +#ifndef __XMPIterator2_hpp__ +#define __XMPIterator2_hpp__ + +// ================================================================================================= +// Copyright 2003 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + + +#include "public/include/XMP_Environment.h" +#include "public/include/XMP_Const.h" +#include "XMPCore/source/XMPMeta.hpp" +#include "XMPCore/source/XMPIterator.hpp" +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/INodeIterator_I.h" +#include <vector> +// ================================================================================================= + + +// ================================================================================================= + + +struct IteratorNode; + +typedef std::vector< IteratorNode > IteratorOffSpring; +typedef IteratorOffSpring::iterator IteratorPos; +typedef std::pair<IteratorPos, IteratorPos> IteratorPosPair; +typedef std::vector< IteratorPosPair> IteratorPosStack; +struct IteratorNode +{ + AdobeXMPCore::spINode node; + XMP_Uns8 visitStage; + IteratorOffSpring nodeQualifiers, nodeChildren; + XMP_VarString fullPath; + size_t leafOffset; + XMP_OptionBits options; + + + + IteratorNode() : options(0), leafOffset(0), visitStage(kIter_BeforeVisit) + { + + }; + + IteratorNode(XMP_OptionBits _options, const XMP_VarString& _fullPath, size_t _leafOffset) + : options(_options), fullPath(_fullPath), leafOffset(_leafOffset), visitStage(kIter_BeforeVisit) + { + + }; +}; + + + +struct IteratorState +{ + + XMP_VarString schema; + XMP_OptionBits options; + + XMP_VarString currSchema; + IteratorPos currPos, endPos; + IteratorPosStack ancestors; + IteratorNode tree; + + + + IteratorState() : options(0) + { + + }; + + IteratorState(XMP_OptionBits _options) : options(_options) + { + + }; + + + IteratorState(const AdobeXMPCore::spINode & inNode, XMP_VarString inSchema, XMP_VarString inPath) { + + + /* schema = inSchema; + path = inPath;*/ + } + + IteratorState(const AdobeXMPCore::spcINode & inNode, XMP_VarString inSchema, XMP_VarString inPath) { + + /*node = inNode; + schema = inSchema; + path = inPath;*/ + } + + +}; +class XMPIterator2: public XMPIterator { + +public: + + + + XMPIterator2(const XMPMeta & xmpObj, // Construct a property iterator. + XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_OptionBits options); + + XMPIterator2(XMP_StringPtr schemaNS, // Construct a table iterator. + XMP_StringPtr propName, + XMP_OptionBits options); + + virtual ~XMPIterator2() RELEASE_NO_THROW; + + bool + Next ( XMP_StringPtr * schemaNS, + XMP_StringLen * nsSize, + XMP_StringPtr * propPath, + XMP_StringLen * pathSize, + XMP_StringPtr * propValue, + XMP_StringLen * valueSize, + XMP_OptionBits * propOptions ); + + void + Skip ( XMP_OptionBits options ); + + // ! Expose so that wrappers and file static functions can see the data. + + + + +private: + + + + void AddNodeOffSpring(IteratorNode &iterParent, const AdobeXMPCore::spINode & xmpParent); + AdobeXMPCore::spINode GetNextNode(bool &); + void AdvanceIteratorPosition(); + void SetCurrentSchema(XMP_VarString &fullPath); + void SetCurrentSchema(const char * fullPath); + void AddSchemaProperties(IteratorNode & iterSchema, const char * nameSpace); + XMP_OptionBits iteratorOptions; + XMP_VarString fullPath; + AdobeXMPCore::spINode currNode; + IteratorState info; + AdobeXMPCore::spIMetadata mDOM; + + +}; + +// ================================================================================================= + +#endif // __XMPIterator2_hpp__ diff --git a/XMPCore/source/XMPMeta-GetSet.cpp b/XMPCore/source/XMPMeta-GetSet.cpp index 112298a..18c024c 100644 --- a/XMPCore/source/XMPMeta-GetSet.cpp +++ b/XMPCore/source/XMPMeta-GetSet.cpp @@ -21,6 +21,27 @@ #include "source/UnicodeConversions.hpp" #include "source/ExpatAdapter.hpp" + +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL +#include "third-party/zuid/interfaces/MD5.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCore/Interfaces/IPath_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" +#include "XMPCore/XMPCoreFwdDeclarations_I.h" +#include "XMPCore/XMPCoreFwdDeclarations.h" +#include "XMPCore/Interfaces/IStructureNode_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/INodeIterator.h" +#include "XMPCore/Interfaces/ICoreObjectFactory.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/INode_I.h" +#endif + + #if XMP_DebugBuild #include <iostream> #endif @@ -45,6 +66,30 @@ using namespace std; typedef unsigned char XMP_CLTMatch; +#if XMP_MARKER_EXTENSIBILITY_BACKWARD_COMPATIBILITY +extern "C" { + void ReleaseXMP_Node(void * node) { + if (node) { + XMP_Node * ptr = (XMP_Node *)node; + delete ptr; + ptr = NULL; + } + } +} + +#if ENABLE_CPP_DOM_MODEL +extern "C" { + void ReleaseIStructureNode(void * node) { + if (node) { + AdobeXMPCore::pIStructureNode_base ptr = ( AdobeXMPCore::pIStructureNode_base )node; + ptr->Release(); + node = NULL; + } + } +} +#endif +#endif + enum { // Values for XMP_CLTMatch. kXMP_CLT_NoValues, kXMP_CLT_SpecificMatch, @@ -68,14 +113,18 @@ enum { // Values for XMP_CLTMatch. // ------------------------------------------------------------------------------------------------- // SetNodeValue // ------------ - static inline void -SetNodeValue ( XMP_Node * node, XMP_StringPtr value ) + SetNodeValue ( XMP_Node * node, XMP_StringPtr value ) +{ + node->SetValue( value ); +} //SetNodeValue + +void XMP_Node::SetValue( XMP_StringPtr value ) { #if XMP_DebugBuild // ! Hack to force an assert. - if ( (node->name == "xmp:TestAssertNotify") && XMP_LitMatch ( value, "DoIt!" ) ) { - XMP_Assert ( node->name != "xmp:TestAssertNotify" ); + if ( (this->name == "xmp:TestAssertNotify") && XMP_LitMatch ( value, "DoIt!" ) ) { + XMP_Assert ( this->name != "xmp:TestAssertNotify" ); } #endif @@ -98,21 +147,21 @@ SetNodeValue ( XMP_Node * node, XMP_StringPtr value ) 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 ); + XMP_Throw ( "U+FFFE and U+FFFF are not allowed in XML", kXMPErr_BadUnicode ); } } } - if ( XMP_PropIsQualifier(node->options) && (node->name == "xml:lang") ) NormalizeLangValue ( &newValue ); + if ( XMP_PropIsQualifier(this->options) && (this->name == "xml:lang") ) NormalizeLangValue ( &newValue ); - node->value.swap ( newValue ); + this->value.swap ( newValue ); #if 0 // *** XMP_DebugBuild - node->_valuePtr = node->value.c_str(); + this->_valuePtr = this->value.c_str(); #endif -} // SetNodeValue +} // XMP_Node::SetValue // ------------------------------------------------------------------------------------------------- @@ -168,7 +217,7 @@ DoSetArrayItem ( XMP_Node * arrayNode, XMP_OptionBits options ) { XMP_OptionBits itemLoc = options & kXMP_PropArrayLocationMask; - XMP_Index arraySize = arrayNode->children.size(); + XMP_Index arraySize = static_cast<XMP_Index>( arrayNode->children.size() ); options &= ~kXMP_PropArrayLocationMask; options = VerifySetOptions ( options, itemValue ); @@ -377,7 +426,7 @@ XMPMeta::GetProperty ( XMP_StringPtr schemaNS, if ( propNode == 0 ) return false; *propValue = propNode->value.c_str(); - *valueSize = propNode->value.size(); + *valueSize = static_cast<XMP_StringLen>( propNode->value.size() ); *options = propNode->options; return true; @@ -819,9 +868,9 @@ XMPMeta::GetLocalizedText ( XMP_StringPtr schemaNS, if ( match == kXMP_CLT_NoValues ) return false; *actualLang = itemNode->qualifiers[0]->value.c_str(); - *langSize = itemNode->qualifiers[0]->value.size(); + *langSize = static_cast<XMP_Index>( itemNode->qualifiers[0]->value.size() ); *itemValue = itemNode->value.c_str(); - *valueSize = itemNode->value.size(); + *valueSize = static_cast<XMP_Index>( itemNode->value.size() ); *options = itemNode->options; return true; diff --git a/XMPCore/source/XMPMeta-Parse.cpp b/XMPCore/source/XMPMeta-Parse.cpp index 62b9404..49d9007 100644 --- a/XMPCore/source/XMPMeta-Parse.cpp +++ b/XMPCore/source/XMPMeta-Parse.cpp @@ -18,6 +18,8 @@ #include "source/UnicodeInlines.incl_cpp" #include "source/UnicodeConversions.hpp" #include "source/ExpatAdapter.hpp" +#define STATIC_SAFE_API +#include "source/SafeStringAPIs.h" #if XMP_DebugBuild #include <iostream> @@ -178,7 +180,7 @@ static const XML_Node * FindRootNode ( const XMLParserAdapter & xmlParser, XMP_O // *** This depends on the dc: namespace prefix. -static void +void NormalizeDCArrays ( XMP_Node * xmpTree ) { XMP_Node * dcSchema = FindSchemaNode ( xmpTree, kXMP_NS_DC, kXMP_ExistingOnly ); @@ -347,7 +349,7 @@ TransplantNamedAlias ( XMP_Node * oldParent, size_t oldNum, XMP_Node * newParent // MoveExplicitAliases // ------------------- -static void +void MoveExplicitAliases ( XMP_Node * tree, XMP_OptionBits parseOptions, XMPMeta::ErrorCallbackInfo & errorCallback ) { tree->options ^= kXMP_PropHasAliases; @@ -534,7 +536,7 @@ MigrateAudioCopyright ( XMPMeta * xmp, XMP_Node * dmCopyright ) // 3. Look for a double linefeed in the x-default value. XMP_Assert ( xdIndex == 0 ); std::string & defaultValue = dcRightsArray->children[xdIndex]->value; - XMP_Index lfPos = defaultValue.find ( kDoubleLF ); + XMP_Index lfPos = static_cast<XMP_Index>( defaultValue.find ( kDoubleLF )); if ( lfPos < 0 ) { @@ -588,7 +590,7 @@ RepairAltText ( XMP_Node & tree, XMP_StringPtr schemaNS, XMP_StringPtr arrayName arrayNode->options |= (kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText); - for ( int i = arrayNode->children.size()-1; i >= 0; --i ) { // ! Need a signed index type. + for ( int i = static_cast<int>( arrayNode->children.size()-1 ); i >= 0; --i ) { // ! Need a signed index type. XMP_Node * currChild = arrayNode->children[i]; @@ -630,7 +632,7 @@ RepairAltText ( XMP_Node & tree, XMP_StringPtr schemaNS, XMP_StringPtr arrayName // TouchUpDataModel // ---------------- -static void +void TouchUpDataModel ( XMPMeta * xmp, XMPMeta::ErrorCallbackInfo & errorCallback ) { XMP_Node & tree = xmp->tree; @@ -907,7 +909,7 @@ CountControlEscape ( const XMP_Uns8 * escStart, const XMP_Uns8 * bufEnd ) if ( (escValue == kTab) || (escValue == kLF) || (escValue == kCR) ) return 0; // An allowed escape. - return escLen; // Found a full "prohibited" numeric escape. + return static_cast<int>(escLen); // Found a full "prohibited" numeric escape. } // CountControlEscape @@ -975,7 +977,7 @@ ProcessUTF8Portion ( XMLParserAdapter * xmlParser, // Not a valid UTF-8 sequence. Replace the first byte with the Latin-1 equivalent. xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false ); const char * replacement = kReplaceLatin1 [ *spanEnd - 0x80 ]; - xmlParser->ParseBuffer ( replacement, strlen ( replacement ), false ); + xmlParser->ParseBuffer(replacement, strnlen_safe(replacement, Max_XMP_Uns32), false); spanStart = spanEnd + 1; // ! The loop increment will do "spanEnd = spanStart". } @@ -1242,7 +1244,7 @@ XMPMeta::ParseFromBuffer ( XMP_StringPtr buffer, XMP_OptionBits options ) { if ( (buffer == 0) && (xmpSize != 0) ) XMP_Throw ( "Null parse buffer", kXMPErr_BadParam ); - if ( xmpSize == kXMP_UseNullTermination ) xmpSize = strlen ( buffer ); + if (xmpSize == kXMP_UseNullTermination) xmpSize = static_cast<XMP_Index>(strnlen_safe(buffer, Max_XMP_Uns32)); const bool lastClientCall = ((options & kXMP_ParseMoreBuffers) == 0); // *** Could use FlagIsSet & FlagIsClear macros. diff --git a/XMPCore/source/XMPMeta-Serialize.cpp b/XMPCore/source/XMPMeta-Serialize.cpp index 9ac13fc..39a5270 100644 --- a/XMPCore/source/XMPMeta-Serialize.cpp +++ b/XMPCore/source/XMPMeta-Serialize.cpp @@ -153,7 +153,10 @@ DeclareOneNamespace ( XMP_StringPtr nsPrefix, for ( ; indent > 0; --indent ) outputStr += indentStr; outputStr += "xmlns:"; outputStr += nsPrefix; - outputStr[outputStr.size()-1] = '='; // Change the colon to =. + if (outputStr[outputStr.size ( ) - 1] == ':') + outputStr[outputStr.size ( ) - 1] = '='; // Change the colon to =. + else + outputStr += '='; outputStr += '"'; outputStr += nsURI; outputStr += '"'; @@ -575,14 +578,14 @@ SerializeCanonicalRDFProperty ( const XMP_Node * propNode, // This is an array. outputStr += '>'; outputStr += newline; - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsStartTag ); + EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, static_cast<XMP_Index>(propNode->children.size()), kIsStartTag ); if ( XMP_ArrayIsAltText(propNode->options) ) NormalizeLangArray ( (XMP_Node*)propNode ); for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) { const XMP_Node * currChild = propNode->children[childNum]; SerializeCanonicalRDFProperty ( currChild, outputStr, newline, indentStr, indent+2, useCanonicalRDF, kEmitAsNormalValue ); } - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag ); + EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, static_cast<XMP_Index>(propNode->children.size()), kIsEndTag ); } else if ( ! hasRDFResourceQual ) { @@ -908,12 +911,12 @@ SerializeCompactRDFElemProps ( const XMP_Node * parentNode, outputStr += '>'; outputStr += newline; - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsStartTag ); + EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, static_cast<XMP_Index>(propNode->children.size()), kIsStartTag ); if ( XMP_ArrayIsAltText(propNode->options) ) NormalizeLangArray ( (XMP_Node*)propNode ); SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+2 ); - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag ); + EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, static_cast<XMP_Index>(propNode->children.size()), kIsEndTag ); } else { @@ -1260,7 +1263,7 @@ XMPMeta::SerializeToBuffer ( XMP_VarString * rdfString, padding = 0; } else { if ( padding == 0 ) { - padding = kDefaultPad * unicodeUnitSize; + padding = static_cast<XMP_StringLen>(kDefaultPad * unicodeUnitSize); } else if ( (padding >> 28) != 0 ) { XMP_Throw ( "Outrageously large padding size", kXMPErr_BadOptions ); // Bigger than 256 MB. } diff --git a/XMPCore/source/XMPMeta.cpp b/XMPCore/source/XMPMeta.cpp index fd8e8ac..b2f02b6 100644 --- a/XMPCore/source/XMPMeta.cpp +++ b/XMPCore/source/XMPMeta.cpp @@ -19,6 +19,19 @@ #include "source/UnicodeInlines.incl_cpp" #include "source/UnicodeConversions.hpp" + +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL + #include "XMPCommon/XMPCommon_I.h" + #include "XMPCore/Interfaces/ICoreConfigurationManager_I.h" + #include "XMPCommon/Interfaces/IMemoryAllocator.h" + #include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" + #include "XMPCommon/ImplHeaders/SharedObjectImpl.h" + #include "XMPCore/Interfaces/ICoreObjectFactory_I.h" + #include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" +#endif + + #include <algorithm> // For sort and stable_sort. #include <cstdio> // For snprintf. @@ -36,6 +49,41 @@ using namespace std; #endif + #if ENABLE_CPP_DOM_MODEL + #if !XMP_StaticBuild + + #if XMP_WinBuild + #pragma warning( push ) + #pragma warning( disable : 4250 ) + #endif + class InternalClientAllocator + : public AdobeXMPCommon::IMemoryAllocator + { + public: + virtual void * APICALL allocate( AdobeXMPCommon::sizet size ) __NOTHROW__ { + return sXMP_MemAlloc( size ); + } + + virtual void APICALL deallocate( void * ptr ) __NOTHROW__ { + sXMP_MemFree( ptr ); + } + + virtual void * APICALL reallocate( void * ptr, AdobeXMPCommon::sizet size ) __NOTHROW__ { + return NULL; + } + + virtual ~InternalClientAllocator(){} + + }; + static InternalClientAllocator * sInternalClientAllocator( NULL ); + #if XMP_WinBuild + #pragma warning( pop ) + #endif + + #endif // !XMP_StaticBuild + #endif // ENABLE_CPP_DOM_MODEL + + // *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros // *** Add debug codegen checks, e.g. that typical masking operations really work // *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch @@ -68,7 +116,7 @@ const char * kXMPCore_EmbeddedCopyright = kXMPCoreName " " kXMP_CopyrightStr; // DumpNodeOptions // --------------- -static void +void DumpNodeOptions ( XMP_OptionBits options, XMP_TextOutputProc outProc, void * refCon ) @@ -618,7 +666,7 @@ RegisterStandardAliases() 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, "ImageDescription", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText ); RegisterAlias ( kXMP_NS_TIFF, "Software", kXMP_NS_XMP, "CreatorTool", 0 ); // Aliases from PNG to DC and XMP. @@ -725,11 +773,25 @@ XMPMeta::Initialize() #endif if ( ! Initialize_LibUtils() ) return false; + + #if ENABLE_CPP_DOM_MODEL + try { + AdobeXMPCore_Int::InitializeXMPCommonFramework(); + + } catch ( ... ) { + return false; + } + AdobeXMPCore_Int::INameSpacePrefixMap_I::CreateDefaultNameSpacePrefixMap(); + sDefaultNamespacePrefixMapLock = new XMP_ReadWriteLock; + + // Explicitly setting sUseNewCoreAPIs as false (default value) + sUseNewCoreAPIs = false; + #endif + xdefaultName = new XMP_VarString ( "x-default" ); sRegisteredNamespaces = new XMP_NamespaceTable; sRegisteredAliasMap = new XMP_AliasMap; - InitializeUnicodeConversions(); @@ -803,6 +865,8 @@ XMPMeta::Initialize() (void) RegisterNamespace ( "adobe:ns:meta/", "x", &voidPtr, &voidLen ); (void) RegisterNamespace ( "http://ns.adobe.com/iX/1.0/", "iX", &voidPtr, &voidLen ); + (void) RegisterNamespace( kXMP_NS_iXML, "iXML", &voidPtr, &voidLen ); + RegisterStandardAliases(); // Initialize the other core classes. @@ -892,11 +956,21 @@ XMPMeta::Terminate() RELEASE_NO_THROW XMPIterator::Terminate(); XMPUtils::Terminate(); -#if ENABLE_NEW_DOM_MODEL - NS_XMPCOMMON::ITSingleton< NS_INT_XMPCORE::IXMPCoreObjectFactory >::DestroyInstance(); - NS_INT_XMPCOMMON::TerminateXMPCommonFramework(); +#if ENABLE_CPP_DOM_MODEL + AdobeXMPCore_Int::INameSpacePrefixMap_I::DestroyDefaultNameSapcePrefixMap(); + AdobeXMPCore_Int::IDOMImplementationRegistry_I::DestoryDOMImplementationRegistry(); + AdobeXMPCore_Int::ICoreObjectFactory_I::DestroyCoreObjectFactory(); + AdobeXMPCore_Int::ICoreConfigurationManager_I::DestroyCoreConfigurationManager(); + AdobeXMPCore_Int::TerminateXMPCommonFramework(); + EliminateGlobal( sDefaultNamespacePrefixMapLock ); + // Explicitly setting sUseNewCoreAPIs as false (default value) + sUseNewCoreAPIs = false; + #if !XMP_StaticBuild + EliminateGlobal( sInternalClientAllocator ); + #endif #endif + EliminateGlobal ( sRegisteredNamespaces ); EliminateGlobal ( sRegisteredAliasMap ); @@ -959,8 +1033,8 @@ XMPMeta::GetGlobalOptions() XMPMeta::SetGlobalOptions ( XMP_OptionBits options ) { - XMP_Throw ( "Unimplemented method XMPMeta::SetGlobalOptions", kXMPErr_Unimplemented ); - void * p; p = &options; // Avoid unused param warnings. + void * p; p = &options; // Avoid unused param warnings. + XMP_Throw("Unimplemented method XMPMeta::SetGlobalOptions", kXMPErr_Unimplemented); } // SetGlobalOptions @@ -976,8 +1050,18 @@ XMPMeta::RegisterNamespace ( XMP_StringPtr namespaceURI, XMP_StringLen * prefixSize ) { - return sRegisteredNamespaces->Define ( namespaceURI, suggestedPrefix, registeredPrefix, prefixSize ); - + bool returnValue = sRegisteredNamespaces->Define ( namespaceURI, suggestedPrefix, registeredPrefix, prefixSize ); +#if ENABLE_CPP_DOM_MODEL + const char * prefix = NULL; + XMP_StringLen len = 0; + sRegisteredNamespaces->GetPrefix( namespaceURI, &prefix, &len ); + XMP_VarString prefixWithoutColon( prefix, len - 1 ); + { + XMP_AutoLock aLock( sDefaultNamespacePrefixMapLock, true ); + AdobeXMPCore_Int::INameSpacePrefixMap_I::InsertInDefaultNameSpacePrefixMap( prefixWithoutColon.c_str(), prefixWithoutColon.size(), namespaceURI, AdobeXMPCommon::npos ); + } +#endif + return returnValue; } // RegisterNamespace @@ -1131,7 +1215,7 @@ XMPMeta::CountArrayItems ( XMP_StringPtr schemaNS, if ( arrayNode == 0 ) return 0; if ( ! (arrayNode->options & kXMP_PropValueIsArray) ) XMP_Throw ( "The named property is not an array", kXMPErr_BadXPath ); - return arrayNode->children.size(); + return static_cast<XMP_Index>( arrayNode->children.size() ); } // CountArrayItems @@ -1146,7 +1230,7 @@ XMPMeta::GetObjectName ( XMP_StringPtr * namePtr, { *namePtr = tree.name.c_str(); - *nameLen = tree.name.size(); + *nameLen = static_cast<XMP_Index>( tree.name.size() ); } // GetObjectName @@ -1185,9 +1269,9 @@ XMPMeta::GetObjectOptions() const void XMPMeta::SetObjectOptions ( XMP_OptionBits options ) { - + void * p; p = &options; // Avoid unused param warnings. XMP_Throw ( "Unimplemented method XMPMeta::SetObjectOptions", kXMPErr_Unimplemented ); - void * p; p = &options; // Avoid unused param warnings. + } // SetObjectOptions @@ -1282,7 +1366,7 @@ void XMP_Node::GetLocalURI ( XMP_StringPtr * uriStr, XMP_StringLen * uriSize ) c if ( XMP_NodeIsSchema ( this->options ) ) { if ( uriStr != 0 ) *uriStr = this->name.c_str(); - if ( uriSize != 0 ) *uriSize = this->name.size(); + if ( uriSize != 0 ) *uriSize = static_cast<XMP_StringLen>( this->name.size() ); } else { @@ -1296,6 +1380,34 @@ void XMP_Node::GetLocalURI ( XMP_StringPtr * uriStr, XMP_StringLen * uriSize ) c } +void XMP_Node::GetFullQualifiedName( XMP_StringPtr * uriStr, XMP_StringLen * uriSize, XMP_StringPtr * nameStr, XMP_StringLen * nameSize ) const +{ + if ( uriStr != 0 ) *uriStr = ""; // Set up empty defaults. + if ( uriSize != 0 ) *uriSize = 0; + if ( nameStr != 0 ) *nameStr = ""; + if ( nameSize != 0 ) *nameSize = 0; + + if ( this->name.empty() ) return; + + if ( XMP_NodeIsSchema ( this->options ) ) { + + if ( uriStr != 0 ) *uriStr = this->name.c_str(); + if ( uriSize != 0 ) *uriSize = static_cast<XMP_StringLen>( this->name.size() ); + if ( nameStr != 0 ) *nameStr = this->value.c_str(); + if ( nameSize != 0 ) *nameSize = static_cast<XMP_StringLen>( this->value.size() ); + + } else { + + size_t colonPos = this->name.find_first_of(':'); + if ( colonPos == XMP_VarString::npos ) return; // ! Name of array items is "[]". + + XMP_VarString prefix ( this->name, 0, colonPos ); + XMPMeta::GetNamespaceURI ( prefix.c_str(), uriStr, uriSize ); + *nameStr = this->name.c_str() + colonPos + 1; + *nameSize = static_cast<XMP_StringLen>( this->name.size() - colonPos - 1 ); + } +} + // ================================================================================================= // Error notifications // =================== diff --git a/XMPCore/source/XMPMeta.hpp b/XMPCore/source/XMPMeta.hpp index 4ca9250..34b71aa 100644 --- a/XMPCore/source/XMPMeta.hpp +++ b/XMPCore/source/XMPMeta.hpp @@ -81,14 +81,14 @@ public: // --------------------------------------------------------------------------------------------- - bool + virtual bool GetProperty ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_StringPtr * propValue, XMP_StringLen * valueSize, XMP_OptionBits * options ) const; - bool + virtual bool GetArrayItem ( XMP_StringPtr schemaNS, XMP_StringPtr arrayName, XMP_Index itemIndex, @@ -96,7 +96,7 @@ public: XMP_StringLen * valueSize, XMP_OptionBits * options ) const; - bool + virtual bool GetStructField ( XMP_StringPtr schemaNS, XMP_StringPtr structName, XMP_StringPtr fieldNS, @@ -105,7 +105,7 @@ public: XMP_StringLen * valueSize, XMP_OptionBits * options ) const; - bool + virtual bool GetQualifier ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_StringPtr qualNS, @@ -116,20 +116,20 @@ public: // --------------------------------------------------------------------------------------------- - void + virtual void SetProperty ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_StringPtr propValue, XMP_OptionBits options ); - void + virtual void SetArrayItem ( XMP_StringPtr schemaNS, XMP_StringPtr arrayName, XMP_Index itemIndex, XMP_StringPtr itemValue, XMP_OptionBits options ); - void + virtual void AppendArrayItem ( XMP_StringPtr schemaNS, XMP_StringPtr arrayName, XMP_OptionBits arrayOptions, @@ -144,7 +144,7 @@ public: XMP_StringPtr fieldValue, XMP_OptionBits options ); - void + virtual void SetQualifier ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_StringPtr qualNS, @@ -154,22 +154,22 @@ public: // --------------------------------------------------------------------------------------------- - void + virtual void DeleteProperty ( XMP_StringPtr schemaNS, XMP_StringPtr propName ); - void + virtual void DeleteArrayItem ( XMP_StringPtr schemaNS, XMP_StringPtr arrayName, XMP_Index itemIndex ); - void + virtual void DeleteStructField ( XMP_StringPtr schemaNS, XMP_StringPtr structName, XMP_StringPtr fieldNS, XMP_StringPtr fieldName ); - void + virtual void DeleteQualifier ( XMP_StringPtr schemaNS, XMP_StringPtr propName, XMP_StringPtr qualNS, @@ -177,7 +177,7 @@ public: // --------------------------------------------------------------------------------------------- - bool + virtual bool DoesPropertyExist ( XMP_StringPtr schemaNS, XMP_StringPtr propName ) const; @@ -200,7 +200,7 @@ public: // --------------------------------------------------------------------------------------------- - bool + virtual bool GetLocalizedText ( XMP_StringPtr schemaNS, XMP_StringPtr altTextName, XMP_StringPtr genericLang, @@ -211,7 +211,7 @@ public: XMP_StringLen * valueSize, XMP_OptionBits * options ) const; - void + virtual void SetLocalizedText ( XMP_StringPtr schemaNS, XMP_StringPtr altTextName, XMP_StringPtr genericLang, @@ -219,7 +219,7 @@ public: XMP_StringPtr itemValue, XMP_OptionBits options ); - void + virtual void DeleteLocalizedText ( XMP_StringPtr schemaNS, XMP_StringPtr altTextName, XMP_StringPtr genericLang, @@ -291,11 +291,11 @@ public: // --------------------------------------------------------------------------------------------- - void + virtual void GetObjectName ( XMP_StringPtr * namePtr, XMP_StringLen * nameLen ) const; - void + virtual void SetObjectName ( XMP_StringPtr name ); XMP_OptionBits @@ -304,31 +304,31 @@ public: void SetObjectOptions ( XMP_OptionBits options ); - void + virtual void Sort(); - void + virtual void Erase(); - void + virtual void Clone ( XMPMeta * clone, XMP_OptionBits options ) const; - XMP_Index + virtual XMP_Index CountArrayItems ( XMP_StringPtr schemaNS, XMP_StringPtr arrayName ) const; - void + virtual void DumpObject ( XMP_TextOutputProc outProc, void * refCon ) const; // --------------------------------------------------------------------------------------------- - void + virtual void ParseFromBuffer ( XMP_StringPtr buffer, XMP_StringLen bufferSize, XMP_OptionBits options ); - void + virtual void SerializeToBuffer ( XMP_VarString * rdfString, XMP_OptionBits options, XMP_StringLen padding, @@ -344,13 +344,13 @@ public: void * context, XMP_Uns32 limit ); - void + virtual void SetErrorCallback ( XMPMeta_ErrorCallbackWrapper wrapperProc, XMPMeta_ErrorCallbackProc clientProc, void * context, XMP_Uns32 limit ); - void + virtual void ResetErrorCallbackLimit ( XMP_Uns32 limit ); class ErrorCallbackInfo : public GenericErrorCallback { diff --git a/XMPCore/source/XMPMeta2-GetSet.cpp b/XMPCore/source/XMPMeta2-GetSet.cpp new file mode 100644 index 0000000..f7f1d9b --- /dev/null +++ b/XMPCore/source/XMPMeta2-GetSet.cpp @@ -0,0 +1,1356 @@ +// ================================================================================================= +// Copyright 2003 Adobe Systems Incorporated +// All Rights Reserved. +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// +// Adobe patent application tracking #P435, entitled 'Unique markers to simplify embedding data of +// one format in a file with a different format', inventors: Sean Parent, Greg Gilley. +// ================================================================================================= +// ================================================================================================= + +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL +#include "public/include/XMP_Environment.h" // ! This must be the first include! +#include "XMPCore/source/XMPCore_Impl.hpp" + + +#include "XMPCore/source/XMPMeta2.hpp" +#include "XMPCore/source/XMPIterator.hpp" +#include "XMPCore/source/XMPUtils.hpp" + +#include "public/include/XMP_Version.h" +#include "source/UnicodeInlines.incl_cpp" +#include "source/UnicodeConversions.hpp" +#include "source/ExpatAdapter.hpp" +#include "third-party/zuid/interfaces/MD5.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCore/Interfaces/IPath_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" +#include "XMPCore/Interfaces/IDOMParser.h" +#include "XMPCore/Interfaces/IDOMSerializer.h" +#include "XMPCore/Interfaces/INodeIterator.h" +#include "XMPCore/Interfaces/IDOMParser_I.h" +#include "XMPCore/Interfaces/IDOMSerializer_I.h" +#include "XMPCore/Interfaces/ICoreConfigurationManager.h" + + + +#if XMP_DebugBuild + #include <iostream> +#endif + +using namespace std; + +#if XMP_WinBuild + #pragma warning ( disable : 4533 ) // initialization of '...' is skipped by 'goto ...' + #pragma warning ( disable : 4702 ) // unreachable code + #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) +#endif + + + +// *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros +// *** Add debug codegen checks, e.g. that typical masking operations really work +// *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch + + +// ================================================================================================= +// Local Types and Constants +// ========================= + +typedef unsigned char XMP_CLTMatch; + +enum { // Values for XMP_CLTMatch. + kXMP_CLT_NoValues, + kXMP_CLT_SpecificMatch, + kXMP_CLT_SingleGeneric, + kXMP_CLT_MultipleGeneric, + kXMP_CLT_XDefault, + kXMP_CLT_FirstItem +}; +const XMP_VarString xmlNameSpace = "http://www.w3.org/XML/1998/namespace"; + +// ================================================================================================= +// Static Variables +// ================ + + +// ================================================================================================= +// Local Utilities +// =============== +extern void SplitNameAndValue ( const XMP_VarString & selStep, XMP_VarString * nameStr, XMP_VarString * valueStr ); + +extern void DumpNodeOptions ( XMP_OptionBits options,XMP_TextOutputProc outProc,void *refCon ); +using namespace AdobeXMPCore_Int; +using namespace AdobeXMPCommon_Int; + + + + +static void +AppendIXMPLangItem ( const spIArrayNode & arrayNode, XMP_StringPtr itemLang, XMP_StringPtr itemValue ) +{ + + + + spISimpleNode newItem = ISimpleNode::CreateSimpleNode( arrayNode->GetNameSpace()->c_str(), arrayNode->GetNameSpace()->size(), arrayNode->GetName()->c_str(), arrayNode->GetName()->size(), "", AdobeXMPCommon::npos ); + spISimpleNode langQual = ISimpleNode::CreateSimpleNode( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos, "", AdobeXMPCommon::npos ); + + try { + + XMPUtils::SetNode(newItem,itemValue,(kXMP_PropHasQualifiers | kXMP_PropHasLang)); + XMPUtils::SetNode(langQual, itemLang, kXMP_PropIsQualifier); + + } catch (...) { + + newItem->Clear(); + langQual->Clear(); + throw; + } + + + newItem->InsertQualifier(langQual); + if ( (!arrayNode->ChildCount() || !XMP_LitMatch(langQual->GetValue()->c_str(),"x-default") )) { + + size_t arraySize = arrayNode->ChildCount(); + arrayNode->InsertNodeAtIndex(newItem, arraySize + 1); + + } else { + + arrayNode->InsertNodeAtIndex(newItem, 1); + } + +} // AppendLangItem + + + + +// ------------------------------------------------------------------------------------------------- +// GetProperty +// ----------- + + + + + +XMPMeta2::XMPMeta2() +{ + mDOM = IMetadata::CreateMetadata(); + mDOM->EnableFeature("alias", 5); + spRegistry = IDOMImplementationRegistry::GetDOMImplementationRegistry(); + spParser = spRegistry->GetParser( "rdf" ); +} + +XMPMeta2::~XMPMeta2() +{ + +} + + + +bool +XMPMeta2::GetProperty ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr * propValue, + XMP_StringLen * valueSize, + XMP_OptionBits * options ) const +{ + XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. + XMP_Assert ( (propValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper. + XMP_ExpandedXPath expPath; + ExpandXPath ( schemaNS, propName, &expPath ); + + + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + spINode destNode = mDOM; + bool qualifierFlag = false; + size_t pathStartIdx = 1; + if (expPath[kRootPropStep].options & kXMP_StepIsAlias) { + + if (!XMPUtils::HandleConstAliasStep(mDOM, destNode, expPath, 0)) return false; + pathStartIdx = 2; + + } + for ( size_t i = pathStartIdx, endIndex = expPath.size(); i < endIndex; i++ ) { + + if(!destNode) return false; + XMP_VarString stepStr = expPath[i].step; + XMP_VarString prevStep = ( i == 0 ) ? "" : expPath[i - 1].step; + spcIUTF8String nameSpace ; + + switch( expPath[i].options ) { + case kXMP_StructFieldStep: + { + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr( 0, colonPos ); + // get the namespace from the prefix + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + if(destNode->GetNodeType() == INode::kNTStructure) { + spIStructureNode tempNode = destNode->ConvertToStructureNode(); + destNode = tempNode->GetNode(nameSpace->c_str(), AdobeXMPCommon::npos, stepStr.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + } + else { + return false; + } + } + break; + case kXMP_ArrayIndexStep: + { + + if(destNode->GetNodeType() != INode::kNTArray) { + return false; + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + XMP_Index index = 0; + XMP_Assert ( (stepStr.length() >= 2) && (*( stepStr.begin()) == '[') && (stepStr[stepStr.length()-1] == ']') ); + for ( size_t chNum = 1,chEnd = stepStr.length() -1 ; chNum != chEnd; ++chNum ) { + XMP_Assert ( ('0' <= stepStr[chNum]) && (stepStr[chNum] <= '9') ); + index = (index * 10) + (stepStr[chNum] - '0'); + } + if ( index < 1) XMP_Throw ( "Array index must be larger than one", kXMPErr_BadXPath ); + size_t colonPos = prevStep.find(':'); + XMP_VarString prefix = prevStep.substr( 0, colonPos ); + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + destNode = tempNode->GetNodeAtIndex( index ); + } + break; + case kXMP_ArrayLastStep: + { + if(destNode->GetNodeType() != INode::kNTArray) { + return false; + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + + size_t colonPos = prevStep.find(':'); + XMP_VarString prefix = prevStep.substr( 0, colonPos ); + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + spINode parentNode = destNode; + if(parentNode && parentNode->GetNodeType()== INode::kNTArray) { + size_t childCount = parentNode->ConvertToArrayNode()->ChildCount(); + if(!childCount) { + XMP_Throw ( "Array index overflow", kXMPErr_BadXPath ); + } + destNode = tempNode->GetNodeAtIndex(childCount); + } + + } + break; + case kXMP_QualifierStep: + { + + XMP_Assert(stepStr[0]=='?'); + stepStr = stepStr.substr(1); + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr( 0, colonPos); + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + destNode = destNode->GetQualifier(nameSpace->c_str(), nameSpace->size(), stepStr.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + qualifierFlag = true; + } + + break; + + case kXMP_QualSelectorStep: + { + + if(destNode->GetNodeType() != INode::kNTArray) { + return false; + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + XMP_VarString qualName, qualValue, qualNameSpace; + SplitNameAndValue (stepStr, &qualName, &qualValue ); + spINode parentNode = destNode; + size_t colonPos = qualName.find(':'); + XMP_VarString prefix = qualName.substr( 0, colonPos); + qualNameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() )->c_str(); + bool indexFound = false; + if(parentNode && parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + size_t arrayChildCount = parentArrayNode->ChildCount(); + for(size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + spINode currentArrayItem = parentArrayNode->GetNodeAtIndex(arrayIdx); + spINode qualNode = currentArrayItem->GetQualifier(qualNameSpace.c_str(), qualNameSpace.size(), qualName.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if(!qualNode) continue; + XMP_VarString currentQualValue = qualNode->ConvertToSimpleNode()->GetValue()->c_str(); + if( currentQualValue == qualValue) { + indexFound = true; + destNode = parentArrayNode->GetNodeAtIndex( arrayIdx); + break; + } + } + + } + if(!indexFound) { + return false; + } + } + break; + + case kXMP_FieldSelectorStep : + { + + XMP_VarString fieldName, fieldValue, fieldNameSpace; + SplitNameAndValue (stepStr, &fieldName, &fieldValue ); + spINode parentNode = destNode; + size_t colonPos = fieldName.find(':'); + XMP_VarString prefix = fieldName.substr( 0, colonPos); + fieldNameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() )->c_str(); + bool indexFound = false; + if(parentNode && parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + size_t arrayChildCount = parentArrayNode->ChildCount(); + for(size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + + spINode currentItem = parentArrayNode->GetNodeAtIndex(arrayIdx); + + if(currentItem->GetNodeType() != INode::kNTStructure) { + return false; + } + + spINode fieldNode = currentItem->ConvertToStructureNode()->GetNode(fieldNameSpace.c_str(), fieldNameSpace.size(), fieldName.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if(!fieldNode || fieldNode->GetNodeType() != INode::kNTSimple) continue; + XMP_VarString currentFieldValue = fieldNode->ConvertToSimpleNode()->GetValue()->c_str(); + if( currentFieldValue == fieldValue) { + indexFound = true; + destNode = parentArrayNode->GetNodeAtIndex( arrayIdx); + break; + } + } + } + if(!indexFound) { + return false; + } + } + break; + default: + break; + + } + + } + + + if (!destNode) { + return false; + } + if(options)*options = XMPUtils::GetIXMPOptions(destNode); + if ( destNode->GetNodeType() == INode::kNTSimple ) { + + spcIUTF8String value = destNode->ConvertToSimpleNode()->GetValue(); + *propValue = value->c_str(); + *valueSize = static_cast<XMP_StringLen>( value->size() ); + } + return true; + +} // GetProperty + +// ------------------------------------------------------------------------------------------------- +// CountArrayItems +// --------------- + +XMP_Index +XMPMeta2::CountArrayItems ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName ) const +{ + XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. + + XMP_ExpandedXPath expPath; + ExpandXPath ( schemaNS, arrayName, &expPath ); + + spINode arrayNode ; + XMP_OptionBits arrayOptions = 0; + if(!XMPUtils::FindCnstNode(this->mDOM, expPath, arrayNode, &arrayOptions)) return false; + + + if ( ! (arrayOptions & kXMP_PropValueIsArray) ) XMP_Throw ( "The named property is not an array", kXMPErr_BadXPath ); + return static_cast<XMP_Index>( XMPUtils::GetNodeChildCount(arrayNode) ); + +} // CountArrayItems + + +void XMPMeta2::ParseFromBuffer ( XMP_StringPtr buffer, XMP_StringLen bufferSize, XMP_OptionBits options ) +{ + bool lastClientCall = (options & kXMP_ParseMoreBuffers) ? false : true; + if (!mBuffer) { + mBuffer = IUTF8String_I::CreateUTF8String("", 0); + } + sizet bufferSizeIn64Bits = static_cast<sizet>(bufferSize); + if (bufferSize == kXMP_UseNullTermination) { + bufferSizeIn64Bits = std::string::npos; + } + mBuffer->append(buffer, bufferSizeIn64Bits); + + + if (!lastClientCall) { + return; + } + + spParser->GetIDOMParser_I()->SetErrorCallback(&errorCallback); + mDOM = spParser->Parse( mBuffer->c_str(), mBuffer->size() ); + mBuffer->clear(); +} + +void XMPMeta2::SerializeToBuffer ( XMP_VarString * rdfString, + XMP_OptionBits options, + XMP_StringLen padding, + XMP_StringPtr newline, + XMP_StringPtr indent, + XMP_Index baseIndent ) const +{ + auto spRegistry = IDOMImplementationRegistry::GetDOMImplementationRegistry(); + auto rdfSerializer = spRegistry->GetSerializer( "rdf" ); + auto str = rdfSerializer->GetIDOMSerializer_I()->SerializeInternal( mDOM, options, padding, newline, indent, baseIndent); + rdfString->clear(); + if (str) + rdfString->append( str->c_str() ); +} + + +void +XMPMeta2::Sort() +{ + // need internal implementation of sort here + return; + +} // Sort + +void +XMPMeta2::Erase() +{ + + if ( this->xmlParser != 0 ) { + delete ( this->xmlParser ); + this->xmlParser = 0; + } + mDOM->Clear(); +} +// DoesPropertyExist +// ----------------- + +bool +XMPMeta2::DoesPropertyExist ( XMP_StringPtr schemaNS, + XMP_StringPtr propName ) const +{ + XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. + + XMP_ExpandedXPath expPath; + ExpandXPath ( schemaNS, propName, &expPath ); + spINode destNode; + XMP_OptionBits options; + return XMPUtils::FindCnstNode ( this->mDOM, expPath, destNode, &options ); + + +} // DoesPropertyExist + +// SetProperty +// ----------- + +// *** Should handle array items specially, calling SetArrayItem. + +void +XMPMeta2::SetProperty ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr propValue, + XMP_OptionBits options ) +{ + XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. + + options = VerifySetOptions ( options, propValue ); + + XMP_ExpandedXPath expPath; + ExpandXPath ( schemaNS, propName, &expPath ); + + spINode node ; + bool propertyFound = XMPUtils::FindNode ( mDOM, expPath, kXMP_CreateNodes, options, node, 0 ); + if (!propertyFound) XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath ); + + XMPUtils::SetNode ( node, propValue, options ); + +} // SetProperty +// -------------------------------------------------------------------------------------------------' +// ------------------------------------------------------------------------------------------------- +// SetArrayItem +// ------------ + +void +XMPMeta2::SetArrayItem ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_Index itemIndex, + XMP_StringPtr itemValue, + XMP_OptionBits options ) +{ + XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. + + XMP_ExpandedXPath arrayPath; + ExpandXPath ( schemaNS, arrayName, &arrayPath ); + spINode destNode; + if(!XMPUtils::FindNode ( mDOM, arrayPath, false,options, destNode ) ) { + XMP_Throw ( "Specified array does not exist", kXMPErr_BadXPath ); + } + int x = destNode->GetNodeType(); + if(destNode->GetNodeType() != INode::kNTArray) { + XMP_Throw ( "Specified array does not exist", kXMPErr_BadXPath ); + } + + spIArrayNode arrayNode = destNode->ConvertToArrayNode(); + XMPUtils::DoSetArrayItem ( arrayNode, itemIndex, itemValue, options ); + +} // SetArrayItem + + +// ------------------------------------------------------------------------------------------------- +// AppendArrayItem +// --------------- + +void +XMPMeta2::AppendArrayItem ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_OptionBits arrayOptions, + XMP_StringPtr itemValue, + XMP_OptionBits options ) +{ + // TO DO check in case array node doesn't already exist, and the parent of the array to be created is also an array -currently appending the array at the end of the existing array + XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. + + arrayOptions = VerifySetOptions ( arrayOptions, 0 ); + if ( (arrayOptions & ~kXMP_PropArrayFormMask) != 0 ) { + XMP_Throw ( "Only array form flags allowed for arrayOptions", kXMPErr_BadOptions ); + } + + + XMP_ExpandedXPath arrayPath; + ExpandXPath ( schemaNS, arrayName, &arrayPath ); + spINode destNode; + spIArrayNode arrayNode; + XMP_OptionBits dummyOptions; + XMP_Index insertIndex = 0; + // either destNode will be the array node or it will be the parent node of the array + if(XMPUtils::FindCnstNode (mDOM, arrayPath, destNode, &dummyOptions )) { + + if ( destNode->GetNodeType() != INode::kNTArray) { + + XMP_Throw ( "The named property is not an array", kXMPErr_BadXPath ); + + } + + + } + else { + + if ( arrayOptions == 0 ) XMP_Throw ( "Explicit arrayOptions required to create new array", kXMPErr_BadOptions ); + XPathStepInfo lastPathSegment( arrayPath.back()); + XMP_VarString arrayStep = lastPathSegment.step; + //arrayPath.pop_back(); + + if(!XMPUtils::FindNode(this->mDOM, arrayPath, kXMP_CreateNodes, arrayOptions, destNode, &insertIndex)) { + XMP_Throw ( "Failure creating array node", kXMPErr_BadXPath ); + } + + } + arrayNode = destNode->ConvertToArrayNode(); + XMPUtils::DoSetArrayItem ( arrayNode, kXMP_ArrayLastItem, itemValue, (options | kXMP_InsertAfterItem) ); + + + +} // AppendArrayItem + +// ------------------------------------------------------------------------------------------------- +// SetQualifier +// ------------ + +void +XMPMeta2::SetQualifier ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr qualNS, + XMP_StringPtr qualName, + XMP_StringPtr qualValue, + XMP_OptionBits options ) +{ + XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper. + + XMP_ExpandedXPath expPath; + ExpandXPath ( schemaNS, propName, &expPath ); + spINode destNode ; + + if(!XMPUtils::FindCnstNode ( mDOM, expPath, destNode) ) + XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath ); + + XMP_VarString qualPath; + XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath ); + SetProperty ( schemaNS, qualPath.c_str(), qualValue, options ); + +} +// SetQualifier + +// Clone +// ----- + +void +XMPMeta2::Clone ( XMPMeta * clone, XMP_OptionBits options ) const +{ + + XMPMeta2 * xmpMeta2Ptr = dynamic_cast<XMPMeta2 *>(clone); + // Possible to do a safer/better cast? + if (xmpMeta2Ptr== 0 ) XMP_Throw ( "Null clone pointer", kXMPErr_BadParam ); + if ( options != 0 ) XMP_Throw ( "No options are defined yet", kXMPErr_BadOptions ); + + xmpMeta2Ptr->mDOM->Clear(); + xmpMeta2Ptr->mDOM = mDOM->Clone()->ConvertToMetadata(); + +} // Clone + + +// ------------------------------------------------------------------------------------------------- +// DeleteProperty +// -------------- + + +void +XMPMeta2::DeleteProperty ( XMP_StringPtr schemaNS, + XMP_StringPtr propName ) +{ + XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. + + XMP_ExpandedXPath expPath; + ExpandXPath ( schemaNS, propName, &expPath ); + + XMP_NodePtrPos ptrPos; + spINode propNode ; + XMP_OptionBits options = 0; + XMP_Index arrayIndex = 0; + if(!XMPUtils::FindCnstNode ( mDOM, expPath, propNode, &options, &arrayIndex ) || !propNode ) { + + return; + } + if (!propNode) return; + + spINode parentNode = propNode->GetParent(); + + // Erase the pointer from the parent's vector, then delete the node and all below it. + + if ( (options & kXMP_PropIsQualifier) ) { + + parentNode->RemoveQualifier( propNode->GetNameSpace()->c_str(), propNode->GetNameSpace()->size(), + propNode->GetName()->c_str(), propNode->GetName()->size() ); + + + } + else if(parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + parentArrayNode->RemoveNodeAtIndex(arrayIndex); + + + } + else if(parentNode->GetNodeType() == INode::kNTStructure) { + spIStructureNode parentStructureNode = parentNode->ConvertToStructureNode(); + parentStructureNode->RemoveNode( propNode->GetNameSpace()->c_str(), propNode->GetNameSpace()->size(), + propNode->GetName()->c_str(), propNode->GetName()->size() ); + } + // delete subtree - needed ? + //propNode->Clear(); + + +} // DeleteProperty + +void +XMPMeta2::GetObjectName ( XMP_StringPtr * namePtr, + XMP_StringLen * nameLen ) const +{ + *namePtr = this->mDOM->GetAboutURI()->c_str(); + *nameLen = static_cast<XMP_StringLen> ( this->mDOM->GetAboutURI()->size() ); + +} // GetObjectName + + +// ------------------------------------------------------------------------------------------------- +// SetObjectName +// ------------- + +void +XMPMeta2::SetObjectName ( XMP_StringPtr name ) +{ + VerifyUTF8 (name); // Throws if the string is not legit UTF-8. + this->mDOM->SetAboutURI(name, AdobeXMPCommon::npos ); + +} // SetObjectName + +// ------------------------------------------------------------------------------------------------- +// ChooseLocalizedText +// ------------------- +// +// 1. Look for an exact match with the specific language. +// 2. If a generic language is given, look for partial matches. +// 3. Look for an "x-default" item. +// 4. Choose the first item. + +static XMP_CLTMatch +ChooseIXMPLocalizedText ( + const spIArrayNode &arrayNode, + XMP_OptionBits &options, + XMP_StringPtr genericLang, + XMP_StringPtr specificLang, + spINode &itemNode ) +{ + spINode currItem ; + const size_t itemLim = arrayNode->ChildCount(); + size_t itemNum; + const XMP_VarString xmlLangQualifierName = "lang"; + + // See if the array has the right form. Allow empty alt arrays, that is what parsing returns. + // *** Should check alt-text bit when that is reliably maintained. + + if ( ! ( XMP_ArrayIsAltText(options) || + (!itemLim && XMP_ArrayIsAlternate(options)) ) ) { + XMP_Throw ( "Localized text array is not alt-text", kXMPErr_BadXPath ); + } + if ( !itemLim ) { + + return kXMP_CLT_NoValues; + } + + for ( itemNum = 1; itemNum <= itemLim; ++itemNum ) { + currItem = arrayNode->GetNodeAtIndex(itemNum); + if ( currItem->GetNodeType()!= INode::kNTSimple ) { + XMP_Throw ( "Alt-text array item is not simple", kXMPErr_BadXPath ); + } + if ( !currItem->HasQualifiers() || !currItem->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), xmlLangQualifierName.c_str(), xmlLangQualifierName.size() ) ) { + XMP_Throw ( "Alt-text array item has no language qualifier", kXMPErr_BadXPath ); + } + } + + // Look for an exact match with the specific language. + spISimpleNode xmlLangQualifierNode, currItemValue; + for ( itemNum = 1; itemNum <= itemLim; ++itemNum ) { + currItem = arrayNode->GetNodeAtIndex(itemNum); + xmlLangQualifierNode = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode(); + currItemValue = currItem->ConvertToSimpleNode(); + if ( !strcmp(xmlLangQualifierNode->GetValue()->c_str(), specificLang ) ) { + itemNode = currItem; + return kXMP_CLT_SpecificMatch; + } + } + + if ( *genericLang != 0 ) { + + // Look for the first partial match with the generic language. + const size_t genericLen = strlen ( genericLang ); + for ( itemNum = 1; itemNum <= itemLim; ++itemNum ) { + currItem = arrayNode->GetNodeAtIndex(itemNum); + xmlLangQualifierNode = currItem->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), + xmlLangQualifierName.c_str(), xmlLangQualifierName.size() )->ConvertToSimpleNode(); + XMP_StringPtr currLang = xmlLangQualifierNode->GetValue()->c_str(); + const size_t currLangSize = xmlLangQualifierNode->GetValue()->size(); + if ( (currLangSize >= genericLen) && + XMP_LitNMatch ( currLang, genericLang, genericLen ) && + ((currLangSize == genericLen) || (currLang[genericLen] == '-')) ) { + itemNode = currItem; + break; // ! Don't return, need to look for other matches. + } + } + + if ( itemNum <= itemLim ) { + + // Look for a second partial match with the generic language. + for ( ++itemNum; itemNum <= itemLim; ++itemNum ) { + currItem = arrayNode->GetNodeAtIndex(itemNum); + xmlLangQualifierNode = currItem->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), + xmlLangQualifierName.c_str(), xmlLangQualifierName.size() )->ConvertToSimpleNode(); + XMP_StringPtr currLang = xmlLangQualifierNode->GetValue()->c_str(); + const size_t currLangSize = xmlLangQualifierNode->GetValue()->size(); + if ( (currLangSize >= genericLen) && + XMP_LitNMatch ( currLang, genericLang, genericLen ) && + ((currLangSize == genericLen) || (currLang[genericLen] == '-')) ) { + return kXMP_CLT_MultipleGeneric; // ! Leave itemNode with the first partial match. + } + } + return kXMP_CLT_SingleGeneric; // No second partial match was found. + + } + + } + + // Look for an 'x-default' item. + for ( itemNum = 1; itemNum <= itemLim; ++itemNum ) { + currItem = arrayNode->GetNodeAtIndex(itemNum); + xmlLangQualifierNode = currItem->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), + xmlLangQualifierName.c_str(), xmlLangQualifierName.size() )->ConvertToSimpleNode(); + if ( !XMP_LitMatch(xmlLangQualifierNode->GetValue()->c_str(), "x-default" ) ) { + itemNode = currItem; + return kXMP_CLT_XDefault; + } + } + + // Everything failed, choose the first item. + itemNode = arrayNode->GetNodeAtIndex(1); + return kXMP_CLT_FirstItem; + +} // ChooseLocalizedText + + + +// ------------------------------------------------------------------------------------------------- +// GetLocalizedText +// ---------------- + +bool +XMPMeta2::GetLocalizedText ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr _genericLang, + XMP_StringPtr _specificLang, + XMP_StringPtr * actualLang, + XMP_StringLen * langSize, + XMP_StringPtr * itemValue, + XMP_StringLen * valueSize, + XMP_OptionBits * options ) const +{ + // TO DO : options + XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (_genericLang != 0) && (_specificLang != 0) ); // Enforced by wrapper. + XMP_Assert ( (actualLang != 0) && (langSize != 0) ); // Enforced by wrapper. + XMP_Assert ( (itemValue != 0) && (valueSize != 0) && (options != 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 ); + spINode arrayNode, itemNode; + XMP_OptionBits arrayOptions; + if(!XMPUtils::FindCnstNode( this->mDOM, arrayPath, arrayNode, &arrayOptions)) return false; + XMP_CLTMatch match = ChooseIXMPLocalizedText( arrayNode->ConvertToArrayNode(), arrayOptions, genericLang, specificLang, itemNode ); + if ( match == kXMP_CLT_NoValues ) return false; + + spISimpleNode qualifierNode = itemNode->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos )->ConvertToSimpleNode(); + *actualLang = qualifierNode->GetValue()->c_str(); + *langSize = static_cast<XMP_StringLen>( qualifierNode->GetValue()->size() ); + spcIUTF8String itemNodeValue = itemNode->ConvertToSimpleNode()->GetValue(); + *itemValue = itemNodeValue->c_str(); + *valueSize = static_cast<XMP_StringLen>( itemNodeValue->size() ); + *options = XMPUtils::GetIXMPOptions(itemNode); + return true; + +} // GetLocalizedText + +// ------------------------------------------------------------------------------------------------- +// DeleteLocalizedText +// ------------------- + + +void +XMPMeta2::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. + spINode destNode, itemNode; + spIArrayNode arrayNode; + XMP_OptionBits arrayOptions; + if(!XMPUtils::FindCnstNode( this->mDOM, arrayPath, destNode, &arrayOptions)) return; + arrayNode = destNode->ConvertToArrayNode(); + size_t arraySize = arrayNode->ChildCount(); + XMP_CLTMatch match = ChooseIXMPLocalizedText( arrayNode->ConvertToArrayNode(), arrayOptions, genericLang, specificLang, itemNode ); + spcIUTF8String itemValue = itemNode->ConvertToSimpleNode()->GetValue(); + if ( match != kXMP_CLT_SpecificMatch ) return; + + + size_t itemIndex = 1; + for ( ; itemIndex <= arraySize; ++itemIndex ) { + if ( arrayNode->GetNodeAtIndex(itemIndex) == itemNode ) break; + } + XMP_Enforce ( itemIndex <= arraySize ); + + // Decide if the selected item is x-default or not, find relevant matching item. + spISimpleNode qualNode ; + bool itemIsXDefault = false; + + if ( itemNode->HasQualifiers() ) { + qualNode = itemNode->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos )->ConvertToSimpleNode(); + if (XMP_LitMatch(qualNode->GetValue()->c_str(), "x-default")) itemIsXDefault = true; + } + + if ( itemIsXDefault && (itemIndex != 1) ) { // Enforce the x-default is first policy. + auto sp = arrayNode->GetNodeAtIndex( itemIndex ); + arrayNode->GetNodeAtIndex(1).swap( sp ); + itemIndex = 1; + } + + spINode assocNode; + size_t assocIndex = 0; + size_t assocIsXDefault = false; + if ( itemIsXDefault ) { + + for ( assocIndex = 2; assocIndex <= arraySize; ++assocIndex ) { + spISimpleNode indexNode = arrayNode->GetNodeAtIndex( assocIndex )->ConvertToSimpleNode(); + if ( !strcmp(indexNode->GetValue()->c_str(), itemValue->c_str()) ) { + assocNode = arrayNode->GetNodeAtIndex(assocIndex); + break; + } + } + + } + else if ( itemIndex > 1 ) { + + spcIUTF8String itemOneValue = arrayNode->GetNodeAtIndex( 1 )->ConvertToSimpleNode()->GetValue(); + if ( !strcmp(itemOneValue->c_str(), itemValue->c_str()) ) { + qualNode = arrayNode->GetNodeAtIndex( 1 )->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos )->ConvertToSimpleNode(); + if ( XMP_LitMatch(qualNode->GetValue()->c_str(),"x-default") ) { + assocNode = arrayNode->GetNodeAtIndex(1); + assocIndex = 1; + assocIsXDefault = true; + } + } + + } + if ( !assocIndex) { + arrayNode->RemoveNodeAtIndex(itemIndex); + } + else if ( itemIndex < assocIndex ) { + arrayNode->RemoveNodeAtIndex(assocIndex); + arrayNode->RemoveNodeAtIndex(itemIndex); + } + else { + arrayNode->RemoveNodeAtIndex(itemIndex); + arrayNode->RemoveNodeAtIndex(assocIndex); + } + +} // DeleteLocalizedText +// ------------------------------------------------------------------------------------------------- + +// SetLocalizedText +// ---------------- + + +void +XMPMeta2::SetLocalizedText ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr _genericLang, + XMP_StringPtr _specificLang, + XMP_StringPtr itemValue, + XMP_OptionBits options ) +{ + + // is new DOM enforcing that first qualifier should be a lang alt + IgnoreParam(options); + + 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 array node and set the options if it was just created. + spINode destNode; + spIArrayNode arrayNode; + XMP_OptionBits arrayOptions; + if( !XMPUtils::FindCnstNode(this->mDOM, arrayPath, destNode) ) { + + XPathStepInfo lastPathSegment( arrayPath.back()); + XMP_VarString arrayStep = lastPathSegment.step; + XMP_Index insertIndex = 0; + if (!XMPUtils::FindNode(this->mDOM, arrayPath, kXMP_CreateNodes, kXMP_PropArrayIsAlternate | kXMP_PropValueIsArray, destNode, &insertIndex)) { + XMP_Throw ( "Failure creating array node", kXMPErr_BadXPath ); + } + + } + + arrayNode = destNode->ConvertToArrayNode(); + arrayOptions = XMPUtils::GetIXMPOptions(arrayNode); + + + + size_t arrayChildCount = arrayNode->ChildCount(); + if ( !arrayNode ) XMP_Throw ( "Failed to find or create array node", kXMPErr_BadXPath ); + if ( ! XMP_ArrayIsAltText(arrayOptions) ) { + if ( !arrayChildCount && XMP_ArrayIsAlternate(arrayOptions) ) { + arrayOptions |= kXMP_PropArrayIsAltText; + } + else { + XMP_Throw ( "Localized text array is not alt-text", kXMPErr_BadXPath ); + } + } + + // Make sure the x-default item, if any, is first. + + size_t itemNum, itemLim; + spcISimpleNode firstQualifier; + spINode xdItem; + bool haveXDefault = false; + + for ( itemNum = 1, itemLim = arrayNode->ChildCount(); itemNum <= itemLim; ++itemNum ) { + spINode currItem = arrayNode->GetNodeAtIndex(itemNum); + + XMP_Assert (XMP_PropHasLang(XMPUtils::GetIXMPOptions(currItem))); + if(!currItem->HasQualifiers()) { + XMP_Throw ( "Language qualifier must be first", kXMPErr_BadXPath ); + } + firstQualifier = currItem->QualifiersIterator()->GetNode()->ConvertToSimpleNode(); + if (!XMP_LitMatch(firstQualifier->GetName()->c_str(),"lang")) { + XMP_Throw ( "Language qualifier must be first", kXMPErr_BadXPath ); + } + if (XMP_LitMatch(firstQualifier->GetValue()->c_str(),"x-default" )) { + xdItem = currItem; + haveXDefault = true; + break; + } + } + + if ( haveXDefault && (itemNum != 1) ) { + //TODO or not to do + XMP_Assert ( XMP_LitMatch(firstQualifier->GetValue()->c_str(), "x-default") ); + spcISimpleNode tempNode = arrayNode->GetNodeAtIndex( itemNum )->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos )->ConvertToSimpleNode(); + + firstQualifier.swap(tempNode); + } + + spINode itemNode; + spcIUTF8String xdValue, itemNodeValue; + if(xdItem && xdItem->GetNodeType() == INode::kNTSimple) { + xdValue = xdItem->ConvertToSimpleNode()->GetValue(); + } + XMP_CLTMatch match = ChooseIXMPLocalizedText ( arrayNode->ConvertToArrayNode(), arrayOptions, genericLang, specificLang, itemNode); + if(itemNode && itemNode->GetNodeType() == INode::kNTSimple) { + itemNodeValue = itemNode->ConvertToSimpleNode()->GetValue(); + } + const bool specificXDefault = XMP_LitMatch ( specificLang, "x-default" ); + switch ( match ) { + + case kXMP_CLT_NoValues : + + // Create the array items for the specificLang and x-default, with x-default first. + AppendIXMPLangItem ( arrayNode, "x-default", itemValue ); + haveXDefault = true; + if ( ! specificXDefault ) AppendIXMPLangItem ( arrayNode, specificLang, itemValue ); + break; + + case kXMP_CLT_SpecificMatch : + + if ( ! specificXDefault ) { + // Update the specific item, update x-default if it matches the old value. + if ( xdItem && haveXDefault && (xdItem != itemNode) && (XMP_LitMatch(xdValue->c_str(), itemNodeValue->c_str())) ) { + XMPUtils::SetNode ( xdItem, itemValue, XMPUtils::GetIXMPOptions( xdItem)); + } + XMPUtils::SetNode(itemNode, itemValue,XMPUtils:: GetIXMPOptions(itemNode)); + + } else { + // Update all items whose values match the old x-default value. + XMP_Assert ( xdItem && haveXDefault && (xdItem.get() == itemNode.get()) ); + for ( itemNum = 1, itemLim = arrayNode->ChildCount(); itemNum <= itemLim; ++itemNum ) { + spISimpleNode currItem = arrayNode->GetNodeAtIndex( itemNum )->ConvertToSimpleNode(); + if ( (currItem.get() == xdItem.get() ) || (strcmp(currItem->GetValue()->c_str(), xdValue->c_str()) )) continue; + XMPUtils::SetNode ( currItem, itemValue, XMPUtils::GetIXMPOptions(currItem) ); + } + + XMPUtils::SetNode( xdItem, itemValue,XMPUtils:: GetIXMPOptions(xdItem)); + } + break; + + case kXMP_CLT_SingleGeneric : + + // Update the generic item, update x-default if it matches the old value. + if ( xdItem && haveXDefault && (xdItem != itemNode) && (XMP_LitMatch(xdValue->c_str(),itemNodeValue->c_str()) ) ) { + XMPUtils::SetNode ( xdItem, itemValue, XMPUtils::GetIXMPOptions(xdItem) ); + } + XMPUtils::SetNode( itemNode, itemValue,XMPUtils:: GetIXMPOptions(itemNode) ); // ! Do this after the x-default check! + break; + + case kXMP_CLT_MultipleGeneric : + + // Create the specific language, ignore x-default. + AppendIXMPLangItem ( arrayNode, specificLang, itemValue ); + if ( specificXDefault ) haveXDefault = true; + break; + + case kXMP_CLT_XDefault : + + // Create the specific language, update x-default if it was the only item. + if ( arrayNode->ChildCount()== 1 ) XMPUtils::SetNode ( xdItem, itemValue, XMPUtils::GetIXMPOptions(xdItem) ); + AppendIXMPLangItem ( arrayNode, specificLang, itemValue ); + break; + + case kXMP_CLT_FirstItem : + + // Create the specific language, don't add an x-default item. + AppendIXMPLangItem ( arrayNode, specificLang, itemValue ); + if ( specificXDefault ) haveXDefault = true; + break; + + default : + XMP_Throw ( "Unexpected result from ChooseLocalizedText", kXMPErr_InternalFailure ); + + } + + // Add an x-default at the front if needed. + if ( (! haveXDefault) && (arrayNode->ChildCount() == 1) ) { + AppendIXMPLangItem ( arrayNode, "x-default", itemValue ); + } + +} // SetLocalizedText + + + + +// ------------------------------------------------------------------------------------------------- +// DumpPropertyTree +// ---------------- + +// *** Extract the validation code into a separate routine to call on exit in debug builds. + +static void +DumpIXMPPropertyTree ( const spcINode & currNode, + int indent, + size_t itemIndex, + XMP_TextOutputProc outProc, + void * refCon ) +{ + if(!currNode) return; + char buffer [32]; // Decimal of a 64 bit int is at most about 20 digits. + XMP_OptionBits options = XMPUtils::GetIXMPOptions(currNode); + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + XMP_VarString currNameSpace = defaultMap->GetPrefix(currNode->GetNameSpace()->c_str(), currNode->GetNameSpace()->size() )->c_str(); + XMP_VarString nodeFullName = currNameSpace + ":" + currNode->GetName()->c_str(); + + OutProcIndent ( (size_t)indent ); + + size_t childCount = 0; + if ( itemIndex == 0 ) { + if ( options & kXMP_PropIsQualifier ) OutProcNChars ( "? ", 2 ); + DumpClearString ( nodeFullName, outProc, refCon ); + } + else { + OutProcNChars ( "[", 1 ); + OutProcDecInt ( itemIndex ); + OutProcNChars ( "]", 1 ); + } + + if ( ! (options & kXMP_PropCompositeMask) ) { + OutProcNChars ( " = \"", 4 ); + DumpClearString ( currNode->ConvertToSimpleNode()->GetValue()->c_str(), outProc, refCon ); + OutProcNChars ( "\"", 1 ); + } + + if ( options != 0 ) { + OutProcNChars ( " ", 2 ); + DumpNodeOptions ( options, outProc, refCon ); + } + + if ( options & kXMP_PropHasLang ) { + + spcISimpleNode firstQualifier = currNode->QualifiersIterator()->GetNode()->ConvertToSimpleNode(); + if ( !currNode->HasQualifiers() || !(XMP_LitMatch(firstQualifier->GetName()->c_str(), "lang") ) ) { + OutProcLiteral ( " ** bad lang flag **" ); + } + } + // *** Check rdf:type also. + + if ( ! (options & kXMP_PropCompositeMask) ) { + if(currNode->GetNodeType() == INode::kNTArray) { + childCount = currNode->ConvertToArrayNode()->ChildCount(); + } + if(currNode->GetNodeType() == INode::kNTStructure) { + childCount = currNode->ConvertToStructureNode()->ChildCount(); + } + if ( childCount ) OutProcLiteral ( " ** bad children **" ); + + } + else if ( options & kXMP_PropValueIsArray ) { + if ( options & kXMP_PropValueIsStruct ) OutProcLiteral ( " ** bad comp flags **" ); + } + else if ( (options & kXMP_PropCompositeMask) != kXMP_PropValueIsStruct ) { + OutProcLiteral ( " ** bad comp flags **" ); + } + + OutProcNewline(); + + if( currNode->HasQualifiers() ) { + auto qualIter = currNode->QualifiersIterator(); + for (size_t qualNum = 0 ; qualIter; qualIter = qualIter->Next(), qualNum++ ) { + spcINode currQual = qualIter->GetNode(); + XMP_OptionBits currQualOptions = XMPUtils::GetIXMPOptions(currQual); + if ( currQual->GetParent() && currQual->GetParent()->GetParent()!= currNode ) OutProcLiteral ( "** bad parent link => " ); + if ( XMP_LitMatch(currQual->GetName()->c_str(), kXMP_ArrayItemName ) ) OutProcLiteral ( "** bad qual name => " ); + if ( ! (currQualOptions & kXMP_PropIsQualifier) ) OutProcLiteral ( "** bad qual flag => " ); + if ( XMP_LitMatch(currQual->GetName()->c_str(), "lang" )) { + if ( (qualNum != 0) || (! (options & kXMP_PropHasLang)) ) OutProcLiteral ( "** bad lang qual => " ); + } + + DumpIXMPPropertyTree ( currQual, indent + 2, 0, outProc, refCon ); + + } + } + spcINodeIterator childIter; + if(currNode->GetNodeType() == INode::kNTArray) { + childIter = currNode->ConvertToArrayNode()->Iterator(); + } + if(currNode->GetNodeType() == INode::kNTStructure) { + childIter = currNode->ConvertToStructureNode()->Iterator(); + } + for (size_t childNum = 0; childIter; childIter = childIter->Next(), childNum++) { + spcINode currentChild = childIter->GetNode(); + XMP_OptionBits currentChildOptions = XMPUtils::GetIXMPOptions( currentChild); + if( !currentChild) continue; + if ( currentChild->GetParent() != currNode ) OutProcLiteral ( "** bad parent link => " ); + if ( currentChildOptions & kXMP_PropIsQualifier ) OutProcLiteral ( "** bad qual flag => " ); + + if ( options & kXMP_PropValueIsArray ) { + + itemIndex = childNum + 1; + if (XMP_LitMatch(currentChild->GetName()->c_str(), kXMP_ArrayItemName) ) OutProcLiteral ( "** bad item name => " ); + } + else { + + itemIndex = 0; + if ( XMP_LitMatch(currentChild->GetName()->c_str(), kXMP_ArrayItemName ) ) OutProcLiteral ( "** bad field name => " ); + } + + DumpIXMPPropertyTree ( currentChild, indent + 1, itemIndex, outProc, refCon ); + + } + +} // DumpPropertyTree + + +// ------------------------------------------------------------------------------------------------- +// DumpObject +// ---------- + +void +XMPMeta2::DumpObject ( XMP_TextOutputProc outProc, + void * refCon ) const +{ + // TODO + // value of mDOM ? + + + XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper. + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + OutProcLiteral ( "Dumping XMPMeta object \"" ); + DumpClearString (mDOM->GetAboutURI()->c_str(), outProc, refCon ); + OutProcNChars ( "\" ", 3 ); + DumpNodeOptions ( XMPUtils::GetIXMPOptions(mDOM), outProc, refCon ); + OutProcNewline(); + + // One can't possibly allocate mDOM a value ?! + /* + if ( ! tree.value.empty() ) { + OutProcLiteral ( "** bad root value ** \"" ); + DumpClearString ( tree.value, outProc, refCon ); + OutProcNChars ( "\"", 1 ); + OutProcNewline(); + } + */ + if ( mDOM->HasQualifiers() ) { + OutProcLiteral ( "** bad root qualifiers **" ); + OutProcNewline(); + spINodeIterator qualIter = mDOM->QualifiersIterator(); + for ( ; qualIter; qualIter = qualIter->Next() ) { + DumpIXMPPropertyTree ( qualIter->GetNode(), 3, 0, outProc, refCon ); + } + } + map<std::string, bool> schemaUsed; + if ( mDOM->ChildCount() ) { + + spINodeIterator childIter = mDOM->Iterator(); + for ( ;childIter; childIter = childIter->Next() ) { + + spINode currSchema = childIter->GetNode(); + XMP_OptionBits currSchemaOptions = kXMP_SchemaNode; + if(!schemaUsed.count(currSchema->GetNameSpace()->c_str())) { + OutProcNewline(); + OutProcIndent ( 1 ); + XMP_VarString prefix = defaultMap->GetPrefix(currSchema->GetNameSpace()->c_str(), currSchema->GetNameSpace()->size() )->c_str(); + prefix += ":"; + DumpClearString ( prefix.c_str(), outProc, refCon ); + OutProcNChars ( " ", 2 ); + DumpClearString ( currSchema->GetNameSpace()->c_str(), outProc, refCon ); + OutProcNChars ( " ", 2 ); + DumpNodeOptions ( currSchemaOptions, outProc, refCon ); + OutProcNewline(); + + if ( ! (currSchemaOptions & kXMP_SchemaNode) ) { + OutProcLiteral ( "** bad schema options **" ); + OutProcNewline(); + } + + schemaUsed[currSchema->GetNameSpace()->c_str()] = true; + } + + DumpIXMPPropertyTree ( currSchema, 2, 0, outProc, refCon ); + + } + + } + +} // DumpObject + + + +// ------------------------------------------------------------------------------------------------- +// SetErrorCallback +// ---------------- + +void +XMPMeta2::SetErrorCallback( XMPMeta_ErrorCallbackWrapper wrapperProc, + XMPMeta_ErrorCallbackProc clientProc, + void * context, + XMP_Uns32 limit) +{ + XMP_Assert(wrapperProc != 0); // Must always be set by the glue; + + this->errorCallback.Clear(); + this->errorCallback.wrapperProc = wrapperProc; + this->errorCallback.clientProc = clientProc; + this->errorCallback.context = context; + this->errorCallback.limit = limit; + spParser->GetIDOMParser_I()->SetErrorCallback(&errorCallback); + +} // SetErrorCallback + +// ------------------------------------------------------------------------------------------------- +// ResetErrorCallbackLimit +// ----------------------- + +void +XMPMeta2::ResetErrorCallbackLimit(XMP_Uns32 limit) +{ + + this->errorCallback.limit = limit; + this->errorCallback.notifications = 0; + this->errorCallback.topSeverity = kXMPErrSev_Recoverable; + spParser->GetIDOMParser_I()->SetErrorCallback(&errorCallback); + +} // ResetErrorCallbackLimit +#endif diff --git a/XMPCore/source/XMPMeta2.hpp b/XMPCore/source/XMPMeta2.hpp new file mode 100644 index 0000000..bd1aa9b --- /dev/null +++ b/XMPCore/source/XMPMeta2.hpp @@ -0,0 +1,190 @@ +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL +#ifndef __XMPMeta2_hpp__ +#define __XMPMeta2_hpp__ + + +#include "public/include/XMP_Environment.h" +#include "public/include/XMP_Const.h" +#include "XMPCore/source/XMPCore_Impl.hpp" +#include "source/XMLParserAdapter.hpp" +#include "XMPCore/source/XMPMeta.hpp" +#include "XMPCore/XMPCoreFwdDeclarations_I.h" + +#ifndef DumpXMLParseTree + #define DumpXMLParseTree 0 +#endif + +extern XMP_VarString * xdefaultName; // Needed in XMPMeta-Parse.cpp, MoveExplicitAliases. + +class XMPIterator; +class XMPUtils; + +class XMPMeta2 : public XMPMeta { +public: + + + + + // --------------------------------------------------------------------------------------------- + + XMPMeta2(); + + virtual ~XMPMeta2() RELEASE_NO_THROW; + + // --------------------------------------------------------------------------------------------- + + virtual bool + GetProperty ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr * propValue, + XMP_StringLen * valueSize, + XMP_OptionBits * options ) const; + + // --------------------------------------------------------------------------------------------- + + virtual void + SetProperty ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr propValue, + XMP_OptionBits options ); + + + virtual void + SetArrayItem ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_Index itemIndex, + XMP_StringPtr itemValue, + XMP_OptionBits options ); + + virtual void + AppendArrayItem ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_OptionBits arrayOptions, + XMP_StringPtr itemValue, + XMP_OptionBits options ); + + virtual void + SetQualifier ( XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr qualNS, + XMP_StringPtr qualName, + XMP_StringPtr qualValue, + XMP_OptionBits options ); + /* + virtual void + SetStructField ( XMP_StringPtr schemaNS, + XMP_StringPtr structName, + XMP_StringPtr fieldNS, + XMP_StringPtr fieldName, + XMP_StringPtr fieldValue, + XMP_OptionBits options ); + + + + + + + */ + /* + + + // --------------------------------------------------------------------------------------------- + */ + virtual bool + GetLocalizedText ( XMP_StringPtr schemaNS, + XMP_StringPtr altTextName, + XMP_StringPtr genericLang, + XMP_StringPtr specificLang, + XMP_StringPtr * actualLang, + XMP_StringLen * langSize, + XMP_StringPtr * itemValue, + XMP_StringLen * valueSize, + XMP_OptionBits * options ) const; + virtual void + SetLocalizedText ( XMP_StringPtr schemaNS, + XMP_StringPtr altTextName, + XMP_StringPtr genericLang, + XMP_StringPtr specificLang, + XMP_StringPtr itemValue, + XMP_OptionBits options ); + + virtual void + DeleteLocalizedText ( XMP_StringPtr schemaNS, + XMP_StringPtr altTextName, + XMP_StringPtr genericLang, + XMP_StringPtr specificLang); + virtual void + GetObjectName ( XMP_StringPtr * namePtr, + XMP_StringLen * nameLen ) const; + + virtual void + SetObjectName ( XMP_StringPtr name ); + + + virtual void + ParseFromBuffer ( XMP_StringPtr buffer, + XMP_StringLen bufferSize, + XMP_OptionBits options ); + virtual void + SerializeToBuffer ( XMP_VarString * rdfString, + XMP_OptionBits options, + XMP_StringLen padding, + XMP_StringPtr newline, + XMP_StringPtr indent, + XMP_Index baseIndent ) const; + virtual void + Clone ( XMPMeta * clone, XMP_OptionBits options ) const; + virtual bool + DoesPropertyExist ( XMP_StringPtr schemaNS, + XMP_StringPtr propName ) const; + virtual void + Erase(); + virtual void + Sort(); + virtual XMP_Index + CountArrayItems ( XMP_StringPtr schemaNS, + XMP_StringPtr arrayName ) const; + virtual void + DeleteProperty ( XMP_StringPtr schemaNS, + XMP_StringPtr propName ); + virtual void + DumpObject ( XMP_TextOutputProc outProc, + void * refCon ) const; + + void + SetErrorCallback(XMPMeta_ErrorCallbackWrapper wrapperProc, + XMPMeta_ErrorCallbackProc clientProc, + void * context, + XMP_Uns32 limit); + + void + ResetErrorCallbackLimit(XMP_Uns32 limit); + + + // --------------------------------------------------------------------------------------------- + + AdobeXMPCore::spIMetadata mDOM; + AdobeXMPCore::spIDOMImplementationRegistry spRegistry; + AdobeXMPCore::spIDOMParser spParser; + + friend class XMPIterator; + friend class XMPUtils; + +private: + + AdobeXMPCommon::spIUTF8String mBuffer; + XMPMeta2 ( const XMPMeta2 & ) + { XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); }; + void operator= ( const XMPMeta2 & ) + { XMP_Throw ( "Call to hidden operator=", kXMPErr_InternalFailure ); }; + + void ProcessXMLTree ( XMP_OptionBits options ); + bool ProcessXMLBuffer ( XMP_StringPtr buffer, XMP_StringLen xmpSize, bool lastClientCall ); + void ProcessRDF ( const XML_Node & xmlTree, XMP_OptionBits options ); + + +}; + +#endif +#endif
\ No newline at end of file diff --git a/XMPCore/source/XMPUtils-FileInfo.cpp b/XMPCore/source/XMPUtils-FileInfo.cpp index 107fa58..6c7073f 100644 --- a/XMPCore/source/XMPUtils-FileInfo.cpp +++ b/XMPCore/source/XMPUtils-FileInfo.cpp @@ -9,8 +9,23 @@ #include "public/include/XMP_Environment.h" // ! This must be the first include! #include "XMPCore/source/XMPCore_Impl.hpp" +#include "XMPCore/XMPCoreDefines.h" #include "XMPCore/source/XMPUtils.hpp" - +#if ENABLE_CPP_DOM_MODEL + #include "source/UnicodeInlines.incl_cpp" + #include "source/UnicodeConversions.hpp" + #include "source/ExpatAdapter.hpp" + #include "third-party/zuid/interfaces/MD5.h" + #include "XMPCore/Interfaces/IMetadata_I.h" + #include "XMPCore/Interfaces/IArrayNode_I.h" + #include "XMPCore/Interfaces/ISimpleNode_I.h" + #include "XMPCore/Interfaces/INodeIterator_I.h" + #include "XMPCore/Interfaces/IPathSegment_I.h" + #include "XMPCore/Interfaces/IPath_I.h" + #include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" + #include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" + #include "XMPCommon/Interfaces/IUTF8String_I.h" +#endif #include <algorithm> // For binary_search. #include <time.h> @@ -127,7 +142,7 @@ ClassifyCharacter ( XMP_StringPtr fullString, size_t offset, *uniChar = (*uniChar << 6) | (UnsByte(fullString[i]) & 0x3F); } - XMP_Uns32 upperBits = *uniChar >> 8; // First filter on just the high order 24 bits. + XMP_Uns32 upperBits = static_cast<XMP_Uns32>(*uniChar >> 8); // First filter on just the high order 24 bits. if ( upperBits == 0xFF ) { // U+FFxx @@ -481,7 +496,7 @@ static int CharStarLess (const char * left, const char * right ) #define IsExternalProperty(s,p) (! IsInternalProperty ( s, p )) -static bool +bool IsInternalProperty ( const XMP_VarString & schema, const XMP_VarString & prop ) { bool isInternal = false; @@ -859,6 +874,122 @@ AppendSubtree ( const XMP_Node * sourceNode, XMP_Node * destParent, // CatenateArrayItems // ------------------ + +#if ENABLE_CPP_DOM_MODEL +// ------------------------------------------------------------------------------------------------- +// CatenateArrayItems_v2 +// ------------------ + +/* class static */ void +XMPUtils::CatenateArrayItems_v2(const XMPMeta & ptr, + XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr separator, + XMP_StringPtr quotes, + XMP_OptionBits options, + XMP_VarString * catedStr) +{ + using namespace AdobeXMPCore; + using namespace AdobeXMPCommon; + + if(sUseNewCoreAPIs) { + const XMPMeta2 & xmpObj = dynamic_cast<const XMPMeta2 &>(ptr); + XMP_Assert((schemaNS != 0) && (arrayName != 0)); // ! Enforced by wrapper. + XMP_Assert((separator != 0) && (quotes != 0) && (catedStr != 0)); // ! Enforced by wrapper. + + size_t strLen, strPos, charLen; + UniCharKind charKind; + UniCodePoint currUCP, openQuote, closeQuote; + + const bool allowCommas = ((options & kXMPUtil_AllowCommas) != 0); + + spINode arrayNode; // ! Move up to avoid gcc complaints. + XMP_OptionBits arrayForm = 0, arrayOptions = 0; + spcINode currItem; + + // Make sure the separator is OK. It must be one semicolon surrounded by zero or more spaces. + // Any of the recognized semicolons or spaces are allowed. + + strPos = 0; + strLen = strlen(separator); + bool haveSemicolon = false; + + while (strPos < strLen) { + ClassifyCharacter(separator, strPos, &charKind, &charLen, &currUCP); + strPos += charLen; + if (charKind == UCK_semicolon) { + if (haveSemicolon) XMP_Throw("Separator can have only one semicolon", kXMPErr_BadParam); + haveSemicolon = true; + } + else if (charKind != UCK_space) { + XMP_Throw("Separator can have only spaces and one semicolon", kXMPErr_BadParam); + } + }; + if (!haveSemicolon) XMP_Throw("Separator must have one semicolon", kXMPErr_BadParam); + + // Make sure the open and close quotes are a legitimate pair. + + strLen = strlen(quotes); + ClassifyCharacter(quotes, 0, &charKind, &charLen, &openQuote); + if (charKind != UCK_quote) XMP_Throw("Invalid quoting character", kXMPErr_BadParam); + + if (charLen == strLen) { + closeQuote = openQuote; + } + else { + strPos = charLen; + ClassifyCharacter(quotes, strPos, &charKind, &charLen, &closeQuote); + if (charKind != UCK_quote) XMP_Throw("Invalid quoting character", kXMPErr_BadParam); + if ((strPos + charLen) != strLen) XMP_Throw("Quoting string too long", kXMPErr_BadParam); + } + if (closeQuote != GetClosingQuote(openQuote)) XMP_Throw("Mismatched quote pair", kXMPErr_BadParam); + + // Return an empty result if the array does not exist, hurl if it isn't the right form. + + catedStr->erase(); + + XMP_ExpandedXPath arrayPath; + ExpandXPath(schemaNS, arrayName, &arrayPath); + + XMPUtils::FindCnstNode((xmpObj.mDOM), arrayPath, arrayNode, &arrayOptions); + + if (!arrayNode) return; + + arrayForm = arrayOptions & kXMP_PropCompositeMask; + if ((!(arrayForm & kXMP_PropValueIsArray)) || (arrayForm & kXMP_PropArrayIsAlternate)) { + XMP_Throw("Named property must be non-alternate array", kXMPErr_BadParam); + } + size_t arrayChildCount = XMPUtils::GetNodeChildCount(arrayNode); + if (!arrayChildCount) 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. + + spcINodeIterator arrayIter = XMPUtils::GetNodeChildIterator(arrayNode); + + if ((XMPUtils::GetIXMPOptions(currItem) & kXMP_PropCompositeMask) != 0) XMP_Throw("Array items must be simple", kXMPErr_BadParam); + + *catedStr = arrayIter->GetNode()->ConvertToSimpleNode()->GetValue()->c_str(); + ApplyQuotes(catedStr, openQuote, closeQuote, allowCommas); + + //ArrayNodes in the new DOM are homogeneous so need to check types of other items in the arary if the first one is Simple + for (arrayIter = arrayIter->Next(); arrayIter; arrayIter = arrayIter->Next()) { + + XMP_VarString tempStr( arrayIter->GetNode()->ConvertToSimpleNode()->GetValue()->c_str()); + ApplyQuotes(&tempStr, openQuote, closeQuote, allowCommas); + *catedStr += separator; + *catedStr += tempStr; + } + } + else { + return; + } + + +} // CatenateArrayItems_v2 + +#endif +// ------------------------------------------------------------------------------------------------- /* class static */ void XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj, XMP_StringPtr schemaNS, @@ -868,6 +999,19 @@ XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj, XMP_OptionBits options, XMP_VarString * catedStr ) { + +#if ENABLE_CPP_DOM_MODEL + + if(sUseNewCoreAPIs) { + + dynamic_cast<const XMPMeta2 &>(xmpObj); + CatenateArrayItems_v2(xmpObj, schemaNS, arrayName, separator, quotes, options, catedStr); + return; + + } + +#endif + XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // ! Enforced by wrapper. XMP_Assert ( (separator != 0) && (quotes != 0) && (catedStr != 0) ); // ! Enforced by wrapper. @@ -954,6 +1098,263 @@ XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj, // ------------------------------------------------------------------------------------------------- +// SeparateArrayItems_v2 +// ------------------ +#if ENABLE_CPP_DOM_MODEL +/* class static */ void +XMPUtils::SeparateArrayItems_v2(XMPMeta * xmpObj2, +XMP_StringPtr schemaNS, +XMP_StringPtr arrayName, +XMP_OptionBits options, +XMP_StringPtr catedStr) +{ + +#if ENABLE_CPP_DOM_MODEL + using namespace AdobeXMPCore; + using namespace AdobeXMPCommon; + XMPMeta2 * xmpObj = NULL; + if(sUseNewCoreAPIs) { + xmpObj = dynamic_cast<XMPMeta2 *> (xmpObj2); + } + +#endif + XMP_Assert((schemaNS != 0) && (arrayName != 0) && (catedStr != 0)); // ! Enforced by wrapper. + // TODO - check if the array item name should be arrayname one or karrayitem + // TODO - check the find array in case array doesn't already exist + XMP_VarString itemValue; + size_t itemStart, itemEnd; + size_t nextSize, charSize = 0; + UniCharKind nextKind, charKind = UCK_normal; + UniCodePoint nextChar, uniChar = 0; + XMP_OptionBits arrayOptions = 0; + + + bool preserveCommas = false; + if (options & kXMPUtil_AllowCommas) { + preserveCommas = true; + options ^= kXMPUtil_AllowCommas; + } + + options = VerifySetOptions(options, 0); + if (options & ~kXMP_PropArrayFormMask) XMP_Throw("Options can only provide array form", kXMPErr_BadOptions); + + // Find the array node, make sure it is OK. Move the current children aside, to be readded later if kept. + + XMP_ExpandedXPath arrayPath; + ExpandXPath(schemaNS, arrayName, &arrayPath); + spINode arrayNode; + if (XMPUtils::FindCnstNode(xmpObj->mDOM, arrayPath, arrayNode, &arrayOptions)){ + + XMP_OptionBits arrayForm = arrayOptions & kXMP_PropArrayFormMask; + if ((arrayForm == 0) || (arrayForm & kXMP_PropArrayIsAlternate)) { + XMP_Throw("Named property must be non-alternate array", kXMPErr_BadXPath); + } + + if ((options != 0) && (options != arrayForm)) XMP_Throw("Mismatch of specified and existing array form", kXMPErr_BadXPath); // *** Right error? + } + else { + // The array does not exist, try to create it. + + XPathStepInfo lastPathSegment(arrayPath.back()); + XMP_VarString arrayStep = lastPathSegment.step; + //arrayPath.pop_back(); + spINode destNode; + XMP_Index insertIndex = 0; + if (!XMPUtils::FindNode(xmpObj->mDOM, arrayPath, kXMP_CreateNodes, options, destNode, &insertIndex, true)) { + XMP_Throw("Failure creating array node", kXMPErr_BadXPath); + } + std::string arrayNameSpace, arrayName; + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + arrayOptions = options; + XMPUtils::GetNameSpaceAndNameFromStepValue(lastPathSegment.step, defaultMap, arrayNameSpace, arrayName); + // Need to check Alternate first + if (arrayOptions & kXMP_PropArrayIsAlternate) { + arrayNode = IArrayNode::CreateAlternativeArrayNode( arrayNameSpace.c_str(), arrayNameSpace.size(), arrayName.c_str(), arrayName.size()); + } + else if (arrayOptions & kXMP_PropArrayIsOrdered) { + arrayNode = IArrayNode::CreateOrderedArrayNode( arrayNameSpace.c_str(), arrayNameSpace.size(), arrayName.c_str(), arrayName.size() ); + } + else if (arrayOptions & kXMP_PropArrayIsUnordered) { + arrayNode = IArrayNode::CreateUnorderedArrayNode( arrayNameSpace.c_str(), arrayNameSpace.size(), arrayName.c_str(), arrayName.size() ); + } + + else { + XMP_Throw("Failure creating array node", kXMPErr_BadXPath); + } + if (destNode->GetNodeType() == INode::kNTStructure) { + + destNode->ConvertToStructureNode()->InsertNode(arrayNode); + } + else if (destNode->GetNodeType() == INode::kNTArray) { + + destNode->ConvertToArrayNode()->AppendNode(arrayNode); + } + else { + + XMP_Throw("Failure creating array node", kXMPErr_BadXPath); + } + + if (!arrayNode) XMP_Throw("Failed to create named array", kXMPErr_BadXPath); + } + + + size_t oldChildCount = XMPUtils::GetNodeChildCount(arrayNode); + std::vector<XMP_VarString> oldArrayNodes; + std::vector<spINode> qualifiers; + + // used to handle duplicates + std::vector<bool> oldArrayNodeSeen(oldChildCount, false); + spcINodeIterator oldArrayChildIter = XMPUtils::GetNodeChildIterator(arrayNode); + + for (; oldArrayChildIter; oldArrayChildIter = oldArrayChildIter->Next()) { + + oldArrayNodes.push_back( oldArrayChildIter->GetNode()->ConvertToSimpleNode()->GetValue()->c_str()); + if (oldArrayChildIter->GetNode()->HasQualifiers()) { + + qualifiers.push_back(oldArrayChildIter->GetNode()->Clone()); + /*for ( auto it = oldArrayChildIter->GetNode()->QualifiersIterator(); it; it = it->Next() ) { + qualifiers.push_back( it->GetNode()->Clone() ); + }*/ + } + else { + qualifiers.push_back(spINode()); + } + + } + + arrayNode->Clear(true, false); + // used to avoid typecasting repeatedly! + spIArrayNode tempArrayNode = arrayNode->ConvertToArrayNode(); + + size_t endPos = strlen(catedStr); + + itemEnd = 0; + while (itemEnd < endPos) { + + + + for (itemStart = itemEnd; itemStart < endPos; itemStart += charSize) { + ClassifyCharacter(catedStr, itemStart, &charKind, &charSize, &uniChar); + if ((charKind == UCK_normal) || (charKind == UCK_quote)) break; + } + if (itemStart >= endPos) break; + + if (charKind != UCK_quote) { + + + + for (itemEnd = itemStart; itemEnd < endPos; itemEnd += charSize) { + + ClassifyCharacter(catedStr, itemEnd, &charKind, &charSize, &uniChar); + + if ((charKind == UCK_normal) || (charKind == UCK_quote)) continue; + if ((charKind == UCK_comma) && preserveCommas) continue; + if (charKind != UCK_space) break; + + if ((itemEnd + charSize) >= endPos) break; // Anything left? + ClassifyCharacter(catedStr, (itemEnd + charSize), &nextKind, &nextSize, &nextChar); + if ((nextKind == UCK_normal) || (nextKind == UCK_quote)) continue; + if ((nextKind == UCK_comma) && preserveCommas) continue; + break; // Have multiple spaces, or a space followed by a separator. + + } + + itemValue.assign(catedStr, itemStart, (itemEnd - itemStart)); + + } + else { + + // Accumulate quoted values into a local string, undoubling internal quotes that + // match the surrounding quotes. Do not undouble "unmatching" quotes. + + UniCodePoint openQuote = uniChar; + UniCodePoint closeQuote = GetClosingQuote(openQuote); + + itemStart += charSize; // Skip the opening quote; + itemValue.erase(); + + for (itemEnd = itemStart; itemEnd < endPos; itemEnd += charSize) { + + ClassifyCharacter(catedStr, itemEnd, &charKind, &charSize, &uniChar); + + if ((charKind != UCK_quote) || (!IsSurroundingQuote(uniChar, openQuote, closeQuote))) { + + // This is not a matching quote, just append it to the item value. + itemValue.append(catedStr, itemEnd, charSize); + + } + else { + + // This is a "matching" quote. Is it doubled, or the final closing quote? Tolerate + // various edge cases like undoubled opening (non-closing) quotes, or end of input. + + if ((itemEnd + charSize) < endPos) { + ClassifyCharacter(catedStr, itemEnd + charSize, &nextKind, &nextSize, &nextChar); + } + else { + nextKind = UCK_semicolon; nextSize = 0; nextChar = 0x3B; + } + + if (uniChar == nextChar) { + // This is doubled, copy it and skip the double. + itemValue.append(catedStr, itemEnd, charSize); + itemEnd += nextSize; // Loop will add in charSize. + } + else if (!IsClosingingQuote(uniChar, openQuote, closeQuote)) { + // This is an undoubled, non-closing quote, copy it. + itemValue.append(catedStr, itemEnd, charSize); + } + else { + // This is an undoubled closing quote, skip it and exit the loop. + itemEnd += charSize; + break; + } + + } + + } // Loop to accumulate the quoted value. + + } + + // Add the separated item to the array. Keep a matching old value in case it had separators. + + size_t oldChild; + + spISimpleNode newItem; + for (oldChild = 1; oldChild <= oldChildCount; ++oldChild) { + if (!oldArrayNodeSeen[oldChild - 1] && itemValue == oldArrayNodes[oldChild - 1]) break; + } + + + if (oldChild == oldChildCount + 1) { + // newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, itemValue.c_str(), 0 ); + newItem = ISimpleNode::CreateSimpleNode(arrayNode->GetNameSpace()->c_str(), arrayNode->GetNameSpace()->size(), + kXMP_ArrayItemName, AdobeXMPCommon::npos, itemValue.c_str()); + } + else { + newItem = ISimpleNode::CreateSimpleNode(arrayNode->GetNameSpace()->c_str(), arrayNode->GetNameSpace()->size(), + kXMP_ArrayItemName, AdobeXMPCommon::npos, oldArrayNodes[oldChild - 1].c_str()); + if (qualifiers[ oldChild - 1] && qualifiers[ oldChild - 1] ->HasQualifiers() ) { + + for (auto it = qualifiers[oldChild - 1] ->QualifiersIterator(); it; it = it->Next()) { + + newItem->InsertQualifier(it->GetNode()->Clone()); + } + } + oldArrayNodeSeen[oldChild - 1] = true; // ! Don't match again, let duplicates be seen. + } + + tempArrayNode->AppendNode(newItem); + + } // Loop through all of the returned items. + + // Delete any of the old children that were not kept. + + +} // SeparateArrayItems_v2 +#endif + +// ------------------------------------------------------------------------------------------------- // SeparateArrayItems // ------------------ @@ -964,6 +1365,13 @@ XMPUtils::SeparateArrayItems ( XMPMeta * xmpObj, XMP_OptionBits options, XMP_StringPtr catedStr ) { + +#if ENABLE_CPP_DOM_MODEL + if (sUseNewCoreAPIs) { + SeparateArrayItems_v2(xmpObj, schemaNS, arrayName, options, catedStr); + return; + } +#endif XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (catedStr != 0) ); // ! Enforced by wrapper. XMP_VarString itemValue; @@ -987,7 +1395,7 @@ XMPUtils::SeparateArrayItems ( XMPMeta * xmpObj, XMP_ExpandedXPath arrayPath; ExpandXPath ( schemaNS, arrayName, &arrayPath ); - XMP_Node * arrayNode = FindNode ( &xmpObj->tree, arrayPath, kXMP_ExistingOnly ); + XMP_Node * arrayNode = ::FindNode( &xmpObj->tree, arrayPath, kXMP_ExistingOnly ); if ( arrayNode != 0 ) { // The array exists, make sure the form is compatible. Zero arrayForm means take what exists. @@ -998,7 +1406,7 @@ XMPUtils::SeparateArrayItems ( XMPMeta * xmpObj, if ( (options != 0) && (options != arrayForm) ) XMP_Throw ( "Mismatch of specified and existing array form", kXMPErr_BadXPath ); // *** Right error? } else { // The array does not exist, try to create it. - arrayNode = FindNode ( &xmpObj->tree, arrayPath, kXMP_CreateNodes, (options | kXMP_PropValueIsArray) ); + arrayNode = ::FindNode( &xmpObj->tree, arrayPath, kXMP_CreateNodes, (options | kXMP_PropValueIsArray) ); if ( arrayNode == 0 ) XMP_Throw ( "Failed to create named array", kXMPErr_BadXPath ); } @@ -1131,6 +1539,14 @@ XMPUtils::ApplyTemplate ( XMPMeta * workingXMP, const XMPMeta & templateXMP, XMP_OptionBits actions ) { + +#if ENABLE_CPP_DOM_MODEL + if (sUseNewCoreAPIs) { + ApplyTemplate_v2(workingXMP, templateXMP, actions); + return; + } +#endif + bool doClear = XMP_OptionIsSet ( actions, kXMPTemplate_ClearUnnamedProperties ); bool doAdd = XMP_OptionIsSet ( actions, kXMPTemplate_AddNewProperties ); bool doReplace = XMP_OptionIsSet ( actions, kXMPTemplate_ReplaceExistingProperties ); @@ -1246,6 +1662,15 @@ XMPUtils::RemoveProperties ( XMPMeta * xmpObj, XMP_StringPtr propName, XMP_OptionBits options ) { + +#if ENABLE_CPP_DOM_MODEL + if (sUseNewCoreAPIs) { + + RemoveProperties_v2(xmpObj, schemaNS, propName, options); + return; + } +#endif + XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // ! Enforced by wrapper. const bool doAll = XMP_TestOption (options, kXMPUtil_DoAllProperties ); @@ -1262,7 +1687,7 @@ XMPUtils::RemoveProperties ( XMPMeta * xmpObj, ExpandXPath ( schemaNS, propName, &expPath ); XMP_NodePtrPos propPos; - XMP_Node * propNode = FindNode ( &(xmpObj->tree), expPath, kXMP_ExistingOnly, kXMP_NoOptions, &propPos ); + XMP_Node * propNode = ::FindNode( &(xmpObj->tree), expPath, kXMP_ExistingOnly, kXMP_NoOptions, &propPos ); if ( propNode != 0 ) { if ( doAll || IsExternalProperty ( expPath[kSchemaStep].step, expPath[kRootPropStep].step ) ) { XMP_Node * parent = propNode->parent; // *** Should have XMP_Node::RemoveChild(pos). @@ -1298,7 +1723,7 @@ XMPUtils::RemoveProperties ( XMPMeta * xmpObj, for ( ; currAlias != endAlias; ++currAlias ) { if ( strncmp ( currAlias->first.c_str(), nsPrefix, nsLen ) == 0 ) { XMP_NodePtrPos actualPos; - XMP_Node * actualProp = FindNode ( &xmpObj->tree, currAlias->second, kXMP_ExistingOnly, kXMP_NoOptions, &actualPos ); + XMP_Node * actualProp = ::FindNode( &xmpObj->tree, currAlias->second, kXMP_ExistingOnly, kXMP_NoOptions, &actualPos ); if ( actualProp != 0 ) { XMP_Node * rootProp = actualProp; while ( ! XMP_NodeIsSchema ( rootProp->parent->options ) ) rootProp = rootProp->parent; @@ -1348,6 +1773,15 @@ XMPUtils::DuplicateSubtree ( const XMPMeta & source, XMP_StringPtr destRoot, XMP_OptionBits options ) { + +#if ENABLE_CPP_DOM_MODEL + if(sUseNewCoreAPIs) { + (void)dynamic_cast<const XMPMeta2 &>(source); + return XMPUtils::DuplicateSubtree_v2(source, dest, sourceNS, sourceRoot, destNS, destRoot, options); + } + +#endif + IgnoreParam(options); bool fullSourceTree = false; @@ -1379,7 +1813,7 @@ XMPUtils::DuplicateSubtree ( const XMPMeta & source, // The destination must be an existing empty struct, copy all of the source top level as fields. ExpandXPath ( destNS, destRoot, &destPath ); - destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly ); + destNode = ::FindNode( &dest->tree, destPath, kXMP_ExistingOnly ); if ( (destNode == 0) || (! XMP_PropIsStruct ( destNode->options )) ) { XMP_Throw ( "Destination must be an existing struct", kXMPErr_BadXPath ); @@ -1461,10 +1895,10 @@ XMPUtils::DuplicateSubtree ( const XMPMeta & source, sourceNode = FindConstNode ( &source.tree, sourcePath ); if ( sourceNode == 0 ) XMP_Throw ( "Can't find source subtree", kXMPErr_BadXPath ); - destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly ); // Dest must not yet exist. + destNode = ::FindNode ( &dest->tree, destPath, kXMP_ExistingOnly ); // Dest must not yet exist. if ( destNode != 0 ) XMP_Throw ( "Destination subtree must not exist", kXMPErr_BadXPath ); - destNode = FindNode ( &dest->tree, destPath, kXMP_CreateNodes ); // Now create the dest. + destNode = ::FindNode ( &dest->tree, destPath, kXMP_CreateNodes ); // Now create the dest. if ( destNode == 0 ) XMP_Throw ( "Can't create destination root node", kXMPErr_BadXPath ); // Make sure the destination is not within the source! The source can't be inside the destination diff --git a/XMPCore/source/XMPUtils.cpp b/XMPCore/source/XMPUtils.cpp index b39a908..8a8c4fc 100644 --- a/XMPCore/source/XMPUtils.cpp +++ b/XMPCore/source/XMPUtils.cpp @@ -21,8 +21,22 @@ #include <stdlib.h> #include <locale.h> #include <errno.h> +#include <vector> #include <stdio.h> // For snprintf. +#if ENABLE_CPP_DOM_MODEL +#include "source/UnicodeInlines.incl_cpp" +#include "source/UnicodeConversions.hpp" +#include "XMPMeta2.hpp" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCommon/Interfaces/IUTF8String_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap.h" +#include "XMPCore/Interfaces/INodeIterator.h" +using namespace AdobeXMPCore; +using namespace AdobeXMPCommon; +#endif #if XMP_WinBuild #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) @@ -34,10 +48,1192 @@ // ========================= static const char * sBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - +const XMP_VarString xmlNameSpace = "http://www.w3.org/XML/1998/namespace"; // ================================================================================================= // Local Utilities // =============== +extern void SplitNameAndValue ( const XMP_VarString & selStep, XMP_VarString * nameStr, XMP_VarString * valueStr ); + +extern void DumpNodeOptions ( XMP_OptionBits options,XMP_TextOutputProc outProc,void *refCon ); +// ------------------------------------------------------------------------------------------------- +// SetINode +// -------------- + +#if ENABLE_CPP_DOM_MODEL + +void XMPUtils::SetNode ( const spINode & node , XMP_StringPtr value, XMP_OptionBits options ) +{ + if (!node) return; + //TO DO check UTF-8 + if ( options & kXMP_DeleteExisting ) { + XMP_ClearOption ( options, kXMP_DeleteExisting ); + node->Clear(); + } + if ( value != 0 ) { + + if ( options & kXMP_PropCompositeMask ) XMP_Throw ( "Composite nodes can't have values", kXMPErr_BadXPath ); + if ( !node ) return; + XMP_Assert( node->GetNodeType() == INode::kNTSimple); + spISimpleNode simpleNode = node->ConvertToSimpleNode(); + std::string newValue = value; + + 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; + } + else if (*chPtr == 0x7F ) { + *chPtr = 0x20; + } + ++chPtr; + } + + XMP_Assert ( (*chPtr == 0) || (*chPtr >= 0x80) ); + + 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_BadUnicode ); + } + } + + } + if ( XMP_PropIsQualifier(options) && XMP_LitMatch(node->GetNameSpace()->c_str(), xmlNameSpace.c_str()) && XMP_LitMatch(node->GetName()->c_str(), "lang")) NormalizeLangValue ( &newValue ); + + simpleNode->SetValue(newValue.c_str(), newValue.size()); + } + else { + + if((node->GetNodeType() == INode::kNTStructure && (options & kXMP_PropValueIsArray)) || (node->GetNodeType() == INode::kNTArray && (options & kXMP_PropValueIsStruct))) { + XMP_Throw ( "Requested and existing composite form mismatch", kXMPErr_BadXPath ); + } + node->Clear(); + + } + +} // SetINode +XMP_OptionBits XMPUtils::ConvertNewArrayFormToOldArrayForm (const spcIArrayNode & arrayNode) { + + XMP_OptionBits options = 0; + if(!arrayNode) return options; + if( arrayNode->GetArrayForm() == IArrayNode::kAFAlternative) return kXMP_PropArrayIsAlternate; + if( arrayNode->GetArrayForm() == IArrayNode::kAFOrdered) return kXMP_PropArrayIsOrdered; + if( arrayNode->GetArrayForm() == IArrayNode::kAFUnordered) return kXMP_PropArrayIsUnordered; + return 0; +} + +spINode XMPUtils::CreateArrayChildNode( const spIArrayNode & arrayNode, XMP_OptionBits options) { + + XMP_VarString nodeNameSpace = arrayNode->GetNameSpace()->c_str(), nodeName = arrayNode->GetName()->c_str(); + spINode itemNode; + size_t arrayChildCount = arrayNode->ChildCount(); + spINode firstChildNode; + if (!arrayChildCount) { + itemNode = XMPUtils::CreateTerminalNode(nodeNameSpace.c_str(), nodeName.c_str(), options); + return itemNode; + } + if(arrayChildCount) firstChildNode = arrayNode->GetNodeAtIndex(1); + XMP_OptionBits childOptions = 0; + if(firstChildNode && firstChildNode->GetNodeType() == INode::kNTArray) { + childOptions = ConvertNewArrayFormToOldArrayForm(firstChildNode->ConvertToArrayNode()); + } + if(XMP_PropIsStruct(options) && (!arrayChildCount || firstChildNode->GetNodeType() == INode::kNTStructure ) ) { + itemNode = IStructureNode::CreateStructureNode(nodeNameSpace.c_str(), nodeNameSpace.size(), nodeName.c_str(), nodeName.size() ); + } + else if(XMP_PropIsSimple(options) && (!arrayChildCount || firstChildNode->GetNodeType() == INode::kNTSimple ) ) { + itemNode = ISimpleNode::CreateSimpleNode(nodeNameSpace.c_str(), nodeNameSpace.size(), nodeName.c_str(), nodeName.size(), "", 0 ); + } + else if((options & kXMP_PropArrayIsAlternate) && (childOptions & kXMP_PropArrayIsAlternate) ) { + itemNode = IArrayNode::CreateAlternativeArrayNode( nodeNameSpace.c_str(), nodeNameSpace.size(), nodeName.c_str(), nodeName.size() ); + } + else if((options & kXMP_PropArrayIsOrdered) && (childOptions & kXMP_PropArrayIsOrdered)) { + itemNode = IArrayNode::CreateOrderedArrayNode( nodeNameSpace.c_str(), nodeNameSpace.size(), nodeName.c_str(), nodeName.size() ); + } + else if((options & kXMP_PropArrayIsUnordered) && (childOptions & kXMP_PropArrayIsUnordered)) { + itemNode = IArrayNode::CreateUnorderedArrayNode( nodeNameSpace.c_str(), nodeNameSpace.size(), nodeName.c_str(), nodeName.size() ); + } + if(!itemNode) XMP_Throw("Array has to be homogeneous", kXMPErr_BadXPath); + + return itemNode; + +} + +void + XMPUtils::DoSetArrayItem ( const spIArrayNode &arrayNode, + XMP_Index itemIndex, + XMP_StringPtr itemValue, + XMP_OptionBits options ) +{ + XMP_OptionBits itemLoc = options & kXMP_PropArrayLocationMask; + XMP_Index arraySize = static_cast<XMP_Index>( arrayNode->ChildCount() ); + XMP_VarString arrayNameSpace = arrayNode->GetNameSpace()->c_str(); + XMP_VarString arrayName = arrayNode->GetName()->c_str(); + options &= ~kXMP_PropArrayLocationMask; + options = VerifySetOptions ( options, itemValue ); + + // Now locate or create the item node and set the value. Note the index parameter is one-based! + // The index can be in the range [0..size+1] or "last", normalize it and check the insert flags. + // The order of the normalization checks is important. If the array is empty we end up with an + // index and location to set item size+1. + + + + spINode itemNode; + if ( itemIndex == kXMP_ArrayLastItem ) itemIndex = arraySize; + if ( (itemIndex == 0) && (itemLoc == kXMP_InsertAfterItem) ) { + itemIndex = 1; + itemLoc = kXMP_InsertBeforeItem; + } + if ( (itemIndex == arraySize) && (itemLoc == kXMP_InsertAfterItem) ) { + itemIndex += 1; + itemLoc = 0; + } + if ( (itemIndex == arraySize + 1) && (itemLoc == kXMP_InsertBeforeItem) ) itemLoc = 0; + + if ( itemIndex == arraySize + 1 ) { + + if ( itemLoc ) XMP_Throw ( "Can't insert before or after implicit new item", kXMPErr_BadIndex ); + itemNode = CreateArrayChildNode(arrayNode, options); + arrayNode->InsertNodeAtIndex(itemNode, arraySize + 1); + } + else { + + if ( (itemIndex < 1) || (itemIndex > arraySize) ) XMP_Throw ( "Array index out of bounds", kXMPErr_BadIndex ); + + if ( itemLoc == 0 ) { + itemNode = arrayNode->GetNodeAtIndex( itemIndex )->ConvertToSimpleNode(); + } + else { + itemNode = CreateArrayChildNode(arrayNode, options); + if ( itemLoc == kXMP_InsertAfterItem ) ++itemIndex; + arrayNode->InsertNodeAtIndex (itemNode, itemIndex ); + } + + } + SetNode(itemNode, itemValue, options); + +} // DoSetIXMPArrayItem + + +void XMPUtils::SetImplicitNodeInformation( bool & firstImplicitNodeFound, + spINode &implicitNodeRoot, + spINode &destNode, + XMP_Index &implicitNodeIndex, + XMP_Index index ) +{ + if(!firstImplicitNodeFound) { + implicitNodeRoot = destNode; + firstImplicitNodeFound = true; + if( index) { + implicitNodeIndex = index; + } + } +} +void XMPUtils::GetNameSpaceAndNameFromStepValue( const std::string & stepStr, + const spcINameSpacePrefixMap & defaultMap, + std::string &stepNameSpace, + std::string &stepName) +{ + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr( 0, colonPos ); + stepNameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() )->c_str(); + stepName = stepStr.substr( colonPos + 1); +} + +// ================================================================================================= +// FindNode +// ======== +// +// Follow an expanded path expression to find or create a node. Returns a pointer to the node, and +// optionally an iterator for the node's position in the parent's vector of children or qualifiers. +// The iterator is unchanged if no child node (null) is returned. + + +spINode XMPUtils::CreateTerminalNode(const char* nameSpace, const char * name, XMP_OptionBits options) { + + spINode newNode; + if(XMP_PropIsSimple(options)) { + + spISimpleNode simpleNode = ISimpleNode::CreateSimpleNode(nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos, NULL, 0 ); + newNode = simpleNode; + } + if(XMP_PropIsStruct(options)){ + + spIStructureNode structNode = IStructureNode::CreateStructureNode(nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos); + newNode = structNode; + } + if(XMP_PropIsArray(options)) { + + if ( options & kXMP_PropArrayIsAlternate ) + newNode = IArrayNode::CreateAlternativeArrayNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + else if(options & kXMP_PropArrayIsOrdered) + newNode = IArrayNode::CreateOrderedArrayNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + else + newNode = IArrayNode::CreateUnorderedArrayNode( nameSpace, AdobeXMPCommon::npos, name, AdobeXMPCommon::npos ); + } + + return newNode; +} + +bool XMPUtils::HandleConstAliasStep(const spIMetadata & mDOM, + spINode &destNode, + const XMP_ExpandedXPath & expandedXPath, + XMP_Index *nodeIndex + ) +{ + destNode = mDOM; + if (expandedXPath.empty()) XMP_Throw("Empty XPath", kXMPErr_BadXPath); + if (!(expandedXPath[kRootPropStep].options & kXMP_StepIsAlias)) { + + return false; + + } + else { + + XMP_AliasMapPos aliasPos = sRegisteredAliasMap->find(expandedXPath[kRootPropStep].step); + XMP_Assert(aliasPos != sRegisteredAliasMap->end()); + XMP_VarString namespaceName = aliasPos->second[kSchemaStep].step.c_str(); + size_t colonPos = aliasPos->second[kRootPropStep].step.find(":"); + XMP_Assert(colonPos != std::string::npos); + XMP_VarString propertyName = aliasPos->second[kRootPropStep].step.substr( colonPos + 1); + destNode = mDOM->GetNode( namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if (!destNode) return false; + if (aliasPos->second.size() == 2) return true; + XMP_Assert(destNode->GetNodeType() == INode::kNTArray); + if (aliasPos->second[2].options == kXMP_ArrayIndexStep) { + + XMP_Assert(aliasPos->second[2].step == "[1]"); + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + INode::eNodeType actualNodeType = destNode->GetNodeType(); + if (destNode) { + if (nodeIndex) *nodeIndex = 1; + return true; + } + return false; + } + else if (aliasPos->second[2].options == kXMP_QualSelectorStep) { + XMP_Assert(aliasPos->second[2].step == "[?xml:lang=\"x-default\"]"); + spcINodeIterator iter = XMPUtils::GetNodeChildIterator(destNode); + XMP_Index index = 1; + while (iter) { + spcINode node = iter->GetNode(); + spcINode qualNode = node->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if (qualNode->GetNodeType() == INode::kNTSimple) { + if (!strcmp("x-default", qualNode->ConvertToSimpleNode()->GetValue()->c_str())){ + destNode = AdobeXMPCore_Int::const_pointer_cast<INode>(node); + if (nodeIndex) *nodeIndex = index; + return true; + } + } + index++; + iter =iter->Next(); + } + return false; + } + + return false; + + } +} +bool XMPUtils::HandleAliasStep(const spIMetadata & mDOM, + XMP_ExpandedXPath &expandedXPath, + bool createNodes, + XMP_OptionBits leafOptions /* = 0 */, + spINode &destNode, + XMP_Index *nodeIndex, + bool ignoreLastStep + ) + +{ + destNode = mDOM; + bool isAliasBeingCreated = expandedXPath.size() == 2; + if (expandedXPath.empty()) XMP_Throw("Empty XPath", kXMPErr_BadXPath); + if (!(expandedXPath[kRootPropStep].options & kXMP_StepIsAlias)) { + + return false; + + } + else { + + XMP_AliasMapPos aliasPos = sRegisteredAliasMap->find(expandedXPath[kRootPropStep].step); + XMP_Assert(aliasPos != sRegisteredAliasMap->end()); + XMP_VarString namespaceName = aliasPos->second[kSchemaStep].step.c_str(); + size_t colonPos = aliasPos->second[kRootPropStep].step.find(":"); + XMP_Assert(colonPos != std::string::npos); + XMP_VarString propertyName = aliasPos->second[kRootPropStep].step.substr(colonPos + 1); + destNode = mDOM->GetNode(namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if (!destNode && !createNodes) return false; + if (aliasPos->second.size() == 2) { + if (destNode) return true; + XMP_OptionBits createOptions = 0; + destNode = mDOM; + if (isAliasBeingCreated) createOptions = leafOptions; + spINode tempNode = CreateTerminalNode(namespaceName.c_str(), propertyName.c_str(), createOptions); + if (!tempNode) return false; + destNode->ConvertToStructureNode()->AppendNode( tempNode ); + destNode = tempNode; + if (destNode) return true; + return false; + } + + + //XMP_Assert(destNode->GetNodeType() == INode::kNTArray); + XMP_Assert(aliasPos->second.size() == 3); + if (aliasPos->second[2].options == kXMP_ArrayIndexStep) { + XMP_Assert(aliasPos->second[2].step == "[1]"); + destNode = mDOM->GetNode(namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if (!destNode && !createNodes) return false; + if (!destNode) { + spINode arrayNode = CreateTerminalNode(namespaceName.c_str(), propertyName.c_str(), kXMP_PropArrayIsOrdered | kXMP_PropValueIsArray); + mDOM->AppendNode(arrayNode); + destNode = arrayNode; + } + + if ( destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ) ) { + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + if (nodeIndex) *nodeIndex = 1; + return true; + } + else { + spISimpleNode indexNode = ISimpleNode::CreateSimpleNode( namespaceName.c_str(), namespaceName.size(), "[]", AdobeXMPCommon::npos, "", AdobeXMPCommon::npos ); + destNode->ConvertToArrayNode()->InsertNodeAtIndex( indexNode, 1 ); + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + return true; + } + return false; + } + else if (aliasPos->second[2].options == kXMP_QualSelectorStep) { + XMP_Assert(aliasPos->second[2].step == "[?xml:lang=\"x-default\"]"); + destNode = mDOM->GetNode(namespaceName.c_str(), namespaceName.size(), propertyName.c_str(), propertyName.size() ); + if (!destNode && !createNodes) return false; + spINode arrayNode = CreateTerminalNode(namespaceName.c_str(), propertyName.c_str(), kXMP_PropArrayIsAltText | kXMP_PropValueIsArray); + mDOM->AppendNode(arrayNode); + destNode = arrayNode; + spcINodeIterator iter = XMPUtils::GetNodeChildIterator(destNode); + XMP_Index index = 1; + while (iter) { + spcINode node = iter->GetNode(); + spcINode qualNode = node->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if (qualNode->GetNodeType() == INode::kNTSimple) { + if (!strcmp("x-default", qualNode->ConvertToSimpleNode()->GetValue()->c_str())){ + destNode = AdobeXMPCore_Int::const_pointer_cast<INode>(node); + if (nodeIndex) *nodeIndex = index; + return true; + } + } + index++; + iter = iter->Next(); + } + spISimpleNode qualifierNode = ISimpleNode::CreateSimpleNode(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos, "x-default" ); + if ( destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ) ) { + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + if (nodeIndex) *nodeIndex = 1; + destNode->InsertQualifier(qualifierNode); + + return true; + } + else { + spISimpleNode indexNode = ISimpleNode::CreateSimpleNode(namespaceName.c_str(), namespaceName.size(), "[]", AdobeXMPCommon::npos ); + destNode->ConvertToArrayNode()->InsertNodeAtIndex( indexNode, 1 ); + destNode->InsertQualifier(qualifierNode); + destNode = destNode->ConvertToArrayNode()->GetNodeAtIndex( 1 ); + return true; + } + + } + + + + } + return false; +} +bool XMPUtils:: FindNode ( const spIMetadata & mDOM, + XMP_ExpandedXPath & expPath, + bool createNodes, + XMP_OptionBits leafOptions /* = 0 */, + spINode &retNode, + XMP_Index *nodeIndex , + bool ignoreLastStep + ) +{ + + // TO DO - Differentiate between failures on last step and steps before that + spINode destNode = mDOM; + spINode parentDestNode = mDOM; + bool firstImplicitNodeFound = false; + bool leafIsNew = false; + spINode implicitNodeRoot; + bool qualifierFlag = false; + XMP_Index implicitNodeIndex ; // used in case first implicit node's parent is an array + XMP_Assert ( (leafOptions == 0) || createNodes ); + + if ( expPath.empty() ) XMP_Throw ( "Empty XPath", kXMPErr_BadXPath ); + + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + size_t pathStartIdx = 1; + if (expPath[kRootPropStep].options & kXMP_StepIsAlias) { + + if (!HandleAliasStep(mDOM, expPath, createNodes, leafOptions, destNode,0, 0 )) return false; + pathStartIdx = 2; + + } + try{ + for (size_t i = pathStartIdx, endIndex = (ignoreLastStep) ? expPath.size() - 1 : expPath.size(); i < endIndex; i++) { + // split the path into prefix and property name + if (!destNode) goto EXIT; + XMP_VarString stepStr = expPath[i].step; + XMP_VarString prevStep = (i == 0) ? "" : expPath[i - 1].step; + spcIUTF8String nameSpace; + XMP_VarString stepName; + + switch (expPath[i].options) { + case kXMP_StructFieldStep: + { + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr(0, colonPos); + // get the namespace from the prefix + nameSpace = defaultMap->GetNameSpace(prefix.c_str(), prefix.size()); + stepName = stepStr.substr(colonPos + 1); + if (destNode->GetNodeType() == INode::kNTStructure) { + spIStructureNode tempNode = destNode->ConvertToStructureNode(); + parentDestNode = destNode; + destNode = tempNode->GetNode(nameSpace->c_str(), nameSpace->size(), stepStr.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if (destNode) continue; + if (!createNodes) return false; + if (i == (expPath.size() - 1)) { + + spINode simpleInsertNode = CreateTerminalNode(nameSpace->c_str(), stepName.c_str(), leafOptions); + tempNode->InsertNode(simpleInsertNode); + destNode = simpleInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex); + + } + else { + + switch (expPath[i + 1].options) { + + case kXMP_StructFieldStep: + { + // TODO : Exit and handle deletetion of implicit node + // TODO : structInsertNode : + spIStructureNode structInsertNode = IStructureNode::CreateStructureNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + spIStructureNode parentStructNode = parentDestNode->ConvertToStructureNode(); + parentStructNode->InsertNode(structInsertNode); + destNode = structInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex); + + } + break; + case kXMP_FieldSelectorStep: + case kXMP_QualSelectorStep: + case kXMP_ArrayLastStep: + case kXMP_ArrayIndexStep: + { + // from where will you get arrayform ? which arrayform to set by default? + spIArrayNode arrayInsertNode = IArrayNode::CreateOrderedArrayNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + spIStructureNode parentStructNode = parentDestNode->ConvertToStructureNode(); + parentStructNode->InsertNode(arrayInsertNode); + destNode = arrayInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex); + + } + break; + case kXMP_QualifierStep: + { + spISimpleNode simpleInsertNode = ISimpleNode::CreateSimpleNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + spIStructureNode parentStructNode = parentDestNode->ConvertToStructureNode(); + parentStructNode->InsertNode(simpleInsertNode); + destNode = simpleInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex); + + + } + default: + break; + } + + } + } + else { + goto EXIT; + } + } + break; + case kXMP_ArrayIndexStep: + { + // TO DO : type array item + // if array not empty -> see type of first array element + // else if next is array type , arrayitem is array + // if next is struct select type, array item is struct + // if next is type qualifier , array item is simple property + // TODO : HANDLE EXIT CASE + // + // we should check if the previous segment is an array segment + if (destNode->GetNodeType() != INode::kNTArray) { + XMP_Throw("Indexing applied to non-array", kXMPErr_BadXPath); + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + size_t index = 0; + XMP_Assert((stepStr.length() >= 2) && (*(stepStr.begin()) == '[') && (stepStr[stepStr.length() - 1] == ']')); + for (size_t chNum = 1, chEnd = stepStr.length() - 1; chNum != chEnd; ++chNum) { + XMP_Assert(('0' <= stepStr[chNum]) && (stepStr[chNum] <= '9')); + index = (index * 10) + (stepStr[chNum] - '0'); + } + if (index < 1) XMP_Throw("Array index must be larger than one", kXMPErr_BadXPath); + if (nodeIndex) *nodeIndex = static_cast<XMP_Index>(index); + size_t colonPos = prevStep.find(':'); + XMP_VarString prefix = prevStep.substr(0, colonPos); + nameSpace = defaultMap->GetNameSpace(prefix.c_str(), prefix.size() ); + stepName = kXMP_ArrayItemName; + parentDestNode = destNode; + destNode = tempNode->GetNodeAtIndex(index); + + if (destNode) continue; + if (!createNodes) return false; + spIArrayNode parentArrayNode = parentDestNode->ConvertToArrayNode(); + if (parentArrayNode->ChildCount() + 1 < index) goto EXIT; + if (i == expPath.size() - 1) { + // to do if array not empty create of type already existing type + /// else create simple node + spINode simpleInsertNode = CreateTerminalNode((nameSpace) ? nameSpace->c_str() : kXMP_NS_XMP, stepName.c_str(), leafOptions); + parentArrayNode->InsertNodeAtIndex(simpleInsertNode, index); + destNode = simpleInsertNode; + if (!firstImplicitNodeFound) { + firstImplicitNodeFound = true; + implicitNodeRoot = destNode; + implicitNodeIndex = static_cast<XMP_Index>(index); + } + } + else { + + switch (expPath[i + 1].options) { + + case kXMP_StructFieldStep: + { + // TODO : Exit and handle deletetion of implicit node + + spIStructureNode structInsertNode = IStructureNode::CreateStructureNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + + parentArrayNode->InsertNodeAtIndex(structInsertNode, index); + destNode = structInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)index); + } + break; + case kXMP_FieldSelectorStep: + case kXMP_QualSelectorStep: + case kXMP_ArrayLastStep: + case kXMP_ArrayIndexStep: + { + spIArrayNode arrayInsertNode = IArrayNode::CreateOrderedArrayNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size()); + parentArrayNode->InsertNodeAtIndex(arrayInsertNode, index); + destNode = arrayInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)index); + } + break; + case kXMP_QualifierStep: + { + spISimpleNode simpleInsertNode = ISimpleNode::CreateSimpleNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + parentArrayNode->InsertNodeAtIndex(simpleInsertNode, index); + destNode = simpleInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)index); + + } + default: + break; + } + + } + + } + break; + + case kXMP_ArrayLastStep: + { + // what is the interpretation of last when array is empty ? creating an array item for index 1 if creatNodes is true + // rest of the things are same as above case + // old implementation has an assertion failing for this case + if (destNode->GetNodeType() != INode::kNTArray) { + XMP_Throw("Indexing applied to non-array", kXMPErr_BadXPath); + + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + + size_t colonPos = prevStep.find(':'); + XMP_VarString prefix = prevStep.substr(0, colonPos); + nameSpace = defaultMap->GetNameSpace(prefix.c_str(), prefix.size()); + stepName = prevStep.substr(colonPos + 1); + spINode parentNode = destNode; + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + if (parentNode && parentNode->GetNodeType() == INode::kNTArray) { + size_t childCount = parentNode->ConvertToArrayNode()->ChildCount(); + if (nodeIndex) *nodeIndex = (XMP_Index)childCount + 1; + if (childCount) { + destNode = parentArrayNode->GetNodeAtIndex(childCount); + continue; + } + if (!createNodes) return false; + if (i == expPath.size() - 1) { + + spINode simpleInsertNode = CreateTerminalNode(nameSpace->c_str(), stepName.c_str(), leafOptions); + parentArrayNode->InsertNodeAtIndex(simpleInsertNode, 1); + destNode = simpleInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)childCount + 1); + continue; + } + switch (expPath[i + 1].options) { + + case kXMP_QualifierStep: + { + spISimpleNode simpleInsertNode = ISimpleNode::CreateSimpleNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size()); + parentArrayNode->InsertNodeAtIndex(simpleInsertNode, 1); + destNode = simpleInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)childCount + 1); + continue; + } + break; + case kXMP_ArrayIndexStep: + case kXMP_ArrayLastStep: + case kXMP_FieldSelectorStep: + case kXMP_QualSelectorStep: + { + spIArrayNode arrayInsertNode = IArrayNode::CreateOrderedArrayNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + parentArrayNode->InsertNodeAtIndex(arrayInsertNode, childCount + 1); + destNode = arrayInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)childCount + 1); + } + break; + case kXMP_StructFieldStep: + { + spIStructureNode structInsertNode = IStructureNode::CreateStructureNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + parentArrayNode->InsertNodeAtIndex(structInsertNode, childCount + 1); + destNode = structInsertNode; + SetImplicitNodeInformation(firstImplicitNodeFound, implicitNodeRoot, destNode, implicitNodeIndex, (XMP_Index)childCount + 1); + + } + break; + + default: + break; + } + + + } + + } + break; + case kXMP_QualifierStep: + { + // if qualifier exists for the parent node, continue + // else create qualifier if createnodes is true + XMP_Assert(stepStr[0] == '?'); + stepStr = stepStr.substr(1); + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr(0, colonPos); + nameSpace = defaultMap->GetNameSpace(prefix.c_str(),prefix.size()); + stepName = stepStr.substr(colonPos + 1); + qualifierFlag = true; + parentDestNode = destNode; + destNode = destNode->GetQualifier(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + if (destNode) continue; + if (!createNodes) return false; + spISimpleNode qualifierNode = ISimpleNode::CreateSimpleNode(nameSpace->c_str(), nameSpace->size(), stepName.c_str(), stepName.size() ); + parentDestNode->InsertQualifier(qualifierNode); + destNode = qualifierNode; + } + + break; + + case kXMP_QualSelectorStep: + { + // TODO - check the old behavior - checked - no implicit nodes except in one case + // TODO it is perhaps not required, can be done later + // if next path step is array(index/lastinddex/qualselect/fieldselect) - this will be an arraynode + // if next path step is a struct, this will be an structnode + // if next path step is a qualifier , this will be a simple property + + if (destNode->GetNodeType() != INode::kNTArray) { + goto EXIT; + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + XMP_VarString qualName, qualValue, qualNameSpace; + SplitNameAndValue(stepStr, &qualName, &qualValue); + spINode parentNode = destNode; + size_t colonPos = qualName.find(':'); + XMP_VarString prefix = qualName.substr(0, colonPos); + qualNameSpace = defaultMap->GetNameSpace(prefix.c_str(), prefix.size())->c_str(); + bool indexFound = false; + if (parentNode && parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + size_t arrayChildCount = parentArrayNode->ChildCount(); + for (size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + + spINode currentArrayItem = parentArrayNode->GetNodeAtIndex(arrayIdx); + spINode qualNode = currentArrayItem->GetQualifier(qualNameSpace.c_str(), qualNameSpace.size(), qualName.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if (!qualNode) continue; + XMP_VarString currentQualValue = qualNode->ConvertToSimpleNode()->GetValue()->c_str(); + if (currentQualValue == qualValue) { + indexFound = true; + destNode = parentArrayNode->GetNodeAtIndex(arrayIdx); + break; + } + } + + } + if (!indexFound) { + goto EXIT; + } + } + break; + + case kXMP_FieldSelectorStep: + { + // what if multiple indices match search criterion ? + // what if parent node isn't an array- exception or return false ? + // same issue what if one or more child nodes aren't structures ? + XMP_VarString fieldName, fieldValue, fieldNameSpace; + SplitNameAndValue(stepStr, &fieldName, &fieldValue); + spINode parentNode = destNode; + size_t colonPos = fieldName.find(':'); + XMP_VarString prefix = fieldName.substr(0, colonPos); + fieldNameSpace = defaultMap->GetNameSpace(prefix.c_str(), prefix.size())->c_str(); + bool indexFound = false; + if (parentNode && parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + size_t arrayChildCount = parentArrayNode->ChildCount(); + for (size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + + spINode currentItem = parentArrayNode->GetNodeAtIndex(arrayIdx); + + if (currentItem->GetNodeType() != INode::kNTStructure) { + goto EXIT; + } + + spINode fieldNode = currentItem->ConvertToStructureNode()->GetNode(fieldNameSpace.c_str(), fieldNameSpace.size(), fieldName.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if (!fieldNode || fieldNode->GetNodeType() != INode::kNTSimple) continue; + XMP_VarString currentFieldValue = fieldNode->ConvertToSimpleNode()->GetValue()->c_str(); + if (currentFieldValue == fieldValue) { + indexFound = true; + destNode = parentArrayNode->GetNodeAtIndex(arrayIdx); + break; + } + } + } + if (!indexFound) { + goto EXIT; + } + } + break; + default: + break; + + } + + } + } + catch (...) { + if (firstImplicitNodeFound) { + + spINode parentImplicitNode = implicitNodeRoot->GetParent(); + if (parentImplicitNode->GetNodeType() == INode::kNTArray) { + parentImplicitNode->ConvertToArrayNode()->RemoveNodeAtIndex( implicitNodeIndex ); + } + else if (parentImplicitNode->GetNodeType() == INode::kNTStructure) { + parentImplicitNode->ConvertToStructureNode()->RemoveNode(implicitNodeRoot->GetNameSpace()->c_str(), implicitNodeRoot->GetNameSpace()->size(), implicitNodeRoot->GetName()->c_str(), implicitNodeRoot->GetName()->size() ); + } + } + throw; + } + +retNode = destNode; +return true; + +EXIT: +{ + //XMP_Assert ( !destNode || (currNode == *currPos) ); + //XMP_Assert ( (destNode!= 0) || (! createNodes) ); + if(!destNode) { + + if( firstImplicitNodeFound ) { + + spINode parentImplicitNode = implicitNodeRoot->GetParent(); + if(parentImplicitNode->GetNodeType() == INode::kNTArray) { + parentImplicitNode->ConvertToArrayNode()->RemoveNodeAtIndex( implicitNodeIndex ); + } + else if(parentImplicitNode->GetNodeType()== INode::kNTStructure) { + parentImplicitNode->ConvertToStructureNode()->RemoveNode( implicitNodeRoot->GetNameSpace()->c_str(), implicitNodeRoot->GetNameSpace()->size(), implicitNodeRoot->GetName()->c_str(), implicitNodeRoot->GetName()->size() ); + } + } + } return false; +} +return false; +} // FindNode + +bool XMPUtils::FindCnstNode ( const spIMetadata & mDOM,XMP_ExpandedXPath &expPath , spINode &destNode, XMP_OptionBits *options , XMP_Index * arrayIndex ) +{ + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + destNode = mDOM; + bool qualifierFlag = false; + size_t pathStartIdx = 1; + if (expPath[kRootPropStep].options & kXMP_StepIsAlias) { + + if (!HandleConstAliasStep(mDOM, destNode, expPath, 0)) return false; + pathStartIdx = 2; + + } + for ( size_t i = pathStartIdx, endIndex = expPath.size(); i < endIndex; i++ ) { + // split the path into prefix and property name + if(!destNode) return false; + XMP_VarString stepStr = expPath[i].step; + XMP_VarString prevStep = (i == 0)? "" : expPath[i - 1].step; + spcIUTF8String nameSpace ; + + switch( expPath[i].options ) { + case kXMP_StructFieldStep: + { + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr( 0, colonPos ); + // get the namespace from the prefix + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + if(destNode->GetNodeType() == INode::kNTStructure) { + spIStructureNode tempNode = destNode->ConvertToStructureNode(); + destNode = tempNode->GetNode(nameSpace->c_str(), nameSpace->size(), stepStr.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + } + else { + XMP_Throw ( "Named children only allowed for schemas and structs", kXMPErr_BadXPath ); + } + } + break; + case kXMP_ArrayIndexStep: + { + // should we check if previous segment is an array segment + if(destNode->GetNodeType() != INode::kNTArray) { + XMP_Throw ( "Indexes allowed for arrays only", kXMPErr_BadXPath ); + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + XMP_Index index = 0; + XMP_Assert ( (stepStr.length() >= 2) && (*( stepStr.begin()) == '[') && (stepStr[stepStr.length()-1] == ']') ); + for ( size_t chNum = 1,chEnd = stepStr.length() -1 ; chNum != chEnd; ++chNum ) { + XMP_Assert ( ('0' <= stepStr[chNum]) && (stepStr[chNum] <= '9') ); + index = (index * 10) + (stepStr[chNum] - '0'); + } + if ( index < 1) XMP_Throw ( "Array index must be larger than one", kXMPErr_BadXPath ); + size_t colonPos = prevStep.find(':'); + XMP_VarString prefix = prevStep.substr( 0, colonPos ); + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + destNode = tempNode->GetNodeAtIndex( index); + if(arrayIndex) *arrayIndex = index; + } + break; + case kXMP_ArrayLastStep: + { + if(destNode->GetNodeType() != INode::kNTArray) { + XMP_Throw ( "Indexes allowed for arrays only", kXMPErr_BadXPath ); + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + + size_t colonPos = prevStep.find(':'); + XMP_VarString prefix = prevStep.substr( 0, colonPos ); + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + spINode parentNode = destNode; + if(parentNode && parentNode->GetNodeType()== INode::kNTArray) { + size_t childCount = parentNode->ConvertToArrayNode()->ChildCount(); + if(!childCount) { + XMP_Throw ( "Array index overflow", kXMPErr_BadXPath ); + } + destNode = tempNode->GetNodeAtIndex(childCount); + if(arrayIndex) *arrayIndex = (XMP_Index)childCount; + } + + } + break; + case kXMP_QualifierStep: + { + + XMP_Assert(stepStr[0]=='?'); + stepStr = stepStr.substr(1); + size_t colonPos = stepStr.find(':'); + XMP_VarString prefix = stepStr.substr( 0, colonPos); + nameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() ); + qualifierFlag = true; + destNode = destNode->GetQualifier(nameSpace->c_str(), nameSpace->size(), stepStr.c_str() + colonPos + 1, AdobeXMPCommon::npos); + + // spINode node = mDOM->GetNode( path); + } + + break; + + case kXMP_QualSelectorStep: + { + // what if multiple indices match search criterion ? + if(destNode->GetNodeType() != INode::kNTArray) { + XMP_Throw ( "Indexes allowed for arrays only", kXMPErr_BadXPath ); + } + spIArrayNode tempNode = destNode->ConvertToArrayNode(); + XMP_VarString qualName, qualValue, qualNameSpace; + SplitNameAndValue (stepStr, &qualName, &qualValue ); + spINode parentNode = destNode; + size_t colonPos = qualName.find(':'); + XMP_VarString prefix = qualName.substr( 0, colonPos); + qualNameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() )->c_str(); + bool indexFound = false; + if(parentNode && parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + size_t arrayChildCount = parentArrayNode->ChildCount(); + for(size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + + spINode currentArrayItem = parentArrayNode->GetNodeAtIndex(arrayIdx); + spINode qualNode = currentArrayItem->GetQualifier(qualNameSpace.c_str(), qualNameSpace.size(), qualName.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if(!qualNode) continue; + XMP_VarString currentQualValue = qualNode->ConvertToSimpleNode()->GetValue()->c_str(); + if( currentQualValue == qualValue) { + indexFound = true; + if(arrayIndex) *arrayIndex = (XMP_Index)arrayIdx; + destNode = parentArrayNode->GetNodeAtIndex( arrayIdx); + break; + } + } + + } + if(!indexFound) { + return false; + } + } + break; + + case kXMP_FieldSelectorStep : + { + // what if multiple indices match search criterion ? + // what if parent node isn't an array- exception or return false ? + // same issue what if one or more child nodes aren't structures ? + XMP_VarString fieldName, fieldValue, fieldNameSpace; + SplitNameAndValue (stepStr, &fieldName, &fieldValue ); + spINode parentNode = destNode; + size_t colonPos = fieldName.find(':'); + XMP_VarString prefix = fieldName.substr( 0, colonPos); + fieldNameSpace = defaultMap->GetNameSpace( prefix.c_str(), prefix.size() )->c_str(); + bool indexFound = false; + if(parentNode && parentNode->GetNodeType() == INode::kNTArray) { + + spIArrayNode parentArrayNode = parentNode->ConvertToArrayNode(); + size_t arrayChildCount = parentArrayNode->ChildCount(); + for(size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + + spINode currentItem = parentArrayNode->GetNodeAtIndex(arrayIdx); + + if(currentItem->GetNodeType() != INode::kNTStructure) { + return false; + } + + spINode fieldNode = currentItem->ConvertToStructureNode()->GetNode(fieldNameSpace.c_str(), fieldNameSpace.size(), fieldName.c_str() + colonPos + 1, AdobeXMPCommon::npos ); + if(!fieldNode || fieldNode->GetNodeType() != INode::kNTSimple) continue; + XMP_VarString currentFieldValue = fieldNode->ConvertToSimpleNode()->GetValue()->c_str(); + if( currentFieldValue == fieldValue) { + indexFound = true; + if(arrayIndex) *arrayIndex = (XMP_Index)arrayIdx; + destNode = parentArrayNode->GetNodeAtIndex( arrayIdx); + break; + } + } + } + if(!indexFound) { + return false; + } + } + break; + default: + break; + + } + + } + if(!destNode) return false; + if(!options) return true; + *options = GetIXMPOptions(destNode); + return true; +} + +size_t XMPUtils:: GetNodeChildCount(const spcINode & node){ + size_t childCount = 0; + if( node->GetNodeType() == INode::kNTArray) { + childCount = node->ConvertToArrayNode()->ChildCount(); + } + else if (node->GetNodeType() == INode::kNTStructure) { + childCount = node->ConvertToStructureNode()->ChildCount(); + } + return childCount; + +} + +spcINodeIterator XMPUtils::GetNodeChildIterator(const spcINode & node){ + spcINodeIterator childIter; + if( node->GetNodeType() == INode::kNTArray) { + childIter = node->ConvertToArrayNode()->Iterator(); + } + else if (node->GetNodeType() == INode::kNTStructure) { + childIter = node->ConvertToStructureNode()->Iterator(); + } + return childIter; + +} + +std::vector<spcINode> XMPUtils:: GetChildVector( const spINode & node) { + + std::vector<spcINode> childNodes; + spcINodeIterator childIter = GetNodeChildIterator(node); + for(; childIter; childIter = childIter->Next()) { + childNodes.push_back(childIter->GetNode()); + } + return childNodes; +} +XMP_OptionBits XMPUtils:: GetIXMPOptions( const spcINode & node) { + + XMP_OptionBits options = 0; + if(!node) return options; + if ( node->HasQualifiers()) { + options |= kXMP_PropHasQualifiers; + // ( destNode->GetQualifier( " + if( node->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos )) { + options |= kXMP_PropHasLang; + } + + if( node->GetQualifier("http://www.w3.org/1999/02/22-rdf-syntax-ns#", AdobeXMPCommon::npos, "type", AdobeXMPCommon::npos )) { + options |= kXMP_PropHasType; + } + } + XMP_VarString snamespace = node->GetNameSpace()->c_str(); + XMP_VarString sname = node->GetName()->c_str(); + spcINode parentNode = node->GetParent(); + + if (node->IsQualifierNode()){ + options |= kXMP_PropIsQualifier; + } + + if ( node->GetNodeType() == INode::kNTSimple ) { + + if( node->ConvertToSimpleNode()->IsURIType()){ + options |= kXMP_PropValueIsURI; + } + + } + else if ( node->GetNodeType() == INode::kNTArray) { + + spcIArrayNode arrayNode = node->ConvertToArrayNode(); + options |= kXMP_PropValueIsArray; + + switch(arrayNode->GetArrayForm()) { + + case IArrayNode::kAFAlternative: + options |= kXMP_PropArrayIsAlternate;options|= kXMP_PropArrayIsOrdered; + break; + + case IArrayNode::kAFOrdered: + options |= kXMP_PropArrayIsOrdered; + break; + + case IArrayNode::kAFUnordered: + options |= kXMP_PropArrayIsUnordered; + break; + + default: + return false; + break; + } + bool isAltTextArray = (arrayNode->GetArrayForm() == IArrayNode::kAFAlternative ); + + for( size_t arrayIndex = 1; arrayIndex <= arrayNode->ChildCount(); arrayIndex++) { + spcINode childNode = arrayNode->GetNodeAtIndex(arrayIndex); + if((childNode->GetNodeType() != INode::kNTSimple || !childNode->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ))) { + isAltTextArray = false; + break; + } + } + if(isAltTextArray) { + options |= kXMP_PropArrayIsAltText; + } + + } + else if( node->GetNodeType() == INode::kNTStructure && node->GetParent() ) { + options |= kXMP_PropValueIsStruct; + } + return options; +} + +spINode +XMPUtils::FindChildNode ( const spINode &parent, + XMP_StringPtr childName, + XMP_StringPtr childNameSpace, + bool createNodes, + size_t * pos /* = 0 */ ) +{ + // need to pass childnamespace too + spINode childNode; + XMP_OptionBits parentOptions = XMPUtils::GetIXMPOptions(parent); + if ( ! (parentOptions & (kXMP_SchemaNode | kXMP_PropValueIsStruct)) ) { + + if ( parentOptions & kXMP_PropValueIsArray ) { + XMP_Throw ( "Named children not allowed for arrays", kXMPErr_BadXPath ); + } + } + spcINodeIterator childIter = XMPUtils::GetNodeChildIterator(parent); + + for (size_t idx = 1 ; childIter; childIter = childIter->Next(), ++idx ) { + spcINode currChild = childIter->GetNode(); + + if (currChild && XMP_LitMatch(currChild->GetName()->c_str(), childName) && XMP_LitMatch(currChild->GetNameSpace()->c_str(), childNameSpace) ) { + childNode = AdobeXMPCore_Int::const_pointer_cast<INode>(currChild); + if(pos) *pos = idx; + break; + } + } + + if ( (!childNode) && createNodes ) { + childNode = ISimpleNode::CreateSimpleNode(childNameSpace, AdobeXMPCommon::npos, childName, AdobeXMPCommon::npos ); + parent->ConvertToStructureNode()->InsertNode( childNode ); + } + + XMP_Assert ( (childNode ) || (! createNodes) ); + return childNode; + +} // FindChildNode + +spcIUTF8String XMPUtils::GetNodeValue( const spINode & node) { + + + if (node && node->GetNodeType() == INode::kNTSimple) { + return node->ConvertToSimpleNode()->GetValue(); + } + return spIUTF8String(); +} + + +XMP_Index XMPUtils::LookupFieldSelector_v2(const spIArrayNode & arrayNode, XMP_VarString fieldName, XMP_VarString fieldValue) { + + XMP_Index destIdx = -1; + if (arrayNode->GetNodeType() != INode::kNTArray) return destIdx; + for (size_t index = 1, indexLim = arrayNode->ChildCount(); index <= indexLim; ++index) { + + spINode childNode = arrayNode->GetNodeAtIndex(index); + if (childNode->GetNodeType() != INode::kNTStructure) { + XMP_Throw("Field selector must be used on array of struct", kXMPErr_BadXPath); + } + for (spcINodeIterator childNodeIter = XMPUtils::GetNodeChildIterator(childNode); childNodeIter; childNodeIter = childNodeIter->Next()) { + spcINode currentField = childNodeIter->GetNode(); + if (!XMP_LitMatch(currentField->GetName()->c_str(), fieldName.c_str())) continue; + if (currentField->GetNodeType() != INode::kNTSimple) continue; + XMP_VarString currentFieldValue = currentField->ConvertToSimpleNode()->GetValue()->c_str(); + if (currentFieldValue == fieldValue) { + return index; + } + } + } + return destIdx; +} + +#endif // ------------------------------------------------------------------------------------------------- // ANSI Time Functions @@ -435,7 +1631,69 @@ EstimateSizeForJPEG ( const XMP_Node * xmpNode ) return estSize; -} // EstimateSizeForJPEG +} + + +#if ENABLE_CPP_DOM_MODEL +// ------------------------------------------------------------------------------------------------- +// EstimateSizeForJPEG +// ------------------- +// +// Estimate the serialized size for the subtree of an XMP_Node. Support for PackageForJPEG. + +static size_t +EstimateSizeForJPEG(const spINode &xmpNode) +{ + + size_t estSize = 0; + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap(); + + size_t nameSize = xmpNode->GetName()->size() + 1 ; + nameSize += defaultMap->GetPrefix(xmpNode->GetNameSpace()->c_str(), xmpNode->GetNameSpace()->size())->size(); + + XMP_OptionBits xmpNodeOptions = XMPUtils::GetIXMPOptions(xmpNode); + bool includeName = (xmpNode->GetParent()->GetNodeType() != INode::kNTArray); + + if (XMP_PropIsSimple(xmpNodeOptions)) { + + if (includeName) estSize += (nameSize + 3); // Assume attribute form. + estSize += xmpNode->ConvertToSimpleNode()->GetValue()->size(); + } + else if (XMP_PropIsArray(xmpNodeOptions)) { + + // The form of the value portion is: <rdf:Xyz><rdf:li>...</rdf:li>...</rdf:Xyx> + if (includeName) estSize += (2 * nameSize + 5); + spIArrayNode structNode = xmpNode->ConvertToArrayNode(); + size_t arraySize = structNode->ChildCount(); + estSize += 9 + 10; // The rdf:Xyz tags. + estSize += arraySize * (8 + 9); // The rdf:li tags. + + for (auto structIter = structNode->Iterator(); structIter; structIter = structIter->Next()) { + + estSize += EstimateSizeForJPEG(structIter->GetNode()); + } + + } + else { + + // The form is: <headTag rdf:parseType="Resource">...fields...</tailTag> + if (includeName) estSize += (2 * nameSize + 5); + spIStructureNode structNode = xmpNode->ConvertToStructureNode(); + estSize += 25; // The rdf:parseType="Resource" attribute. + size_t fieldCount = structNode->ChildCount(); + + for (auto structIter = structNode->Iterator(); structIter; structIter = structIter->Next()) { + + estSize += EstimateSizeForJPEG(structIter->GetNode()); + } + + + } + + return estSize; + +} +#endif // ------------------------------------------------------------------------------------------------- // MoveOneProperty @@ -468,6 +1726,34 @@ static bool MoveOneProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, } // MoveOneProperty + + +// ------------------------------------------------------------------------------------------------- +// MoveOneProperty +// --------------- +#if ENABLE_CPP_DOM_MODEL +static bool MoveOneProperty(XMPMeta2 & stdXMP, XMPMeta2 * extXMP, + XMP_StringPtr schemaURI, XMP_StringPtr propName) +{ + + spINode rootNode = stdXMP.mDOM; + if (!rootNode) return false; + spINode propNode = rootNode->ConvertToStructureNode()->GetNode(schemaURI, AdobeXMPCommon::npos, propName, AdobeXMPCommon::npos); + if (!propNode) return false; + + spINode clonedNode = propNode->Clone(); + + spIStructureNode rootNode2 = extXMP->mDOM; + + if (rootNode2->GetNode(schemaURI, AdobeXMPCommon::npos, propName, AdobeXMPCommon::npos )) { + rootNode2->RemoveNode(schemaURI, AdobeXMPCommon::npos, propName, AdobeXMPCommon::npos); + } + rootNode2->AppendNode(clonedNode); + rootNode->ConvertToStructureNode()->RemoveNode( schemaURI, AdobeXMPCommon::npos, propName, AdobeXMPCommon::npos ); + return true; +} // MoveOneProperty +#endif + // ------------------------------------------------------------------------------------------------- // CreateEstimatedSizeMap // ---------------------- @@ -477,7 +1763,9 @@ static bool MoveOneProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, #endif typedef std::pair < XMP_VarString*, XMP_VarString* > StringPtrPair; +typedef std::pair < const char *, const char * > StringPtrPair2; typedef std::multimap < size_t, StringPtrPair > PropSizeMap; +typedef std::multimap < size_t, StringPtrPair2 > PropSizeMap2; static void CreateEstimatedSizeMap ( XMPMeta & stdXMP, PropSizeMap * propSizes ) { @@ -510,6 +1798,71 @@ static void CreateEstimatedSizeMap ( XMPMeta & stdXMP, PropSizeMap * propSizes ) } // CreateEstimatedSizeMap +#if ENABLE_CPP_DOM_MODEL +static void CreateEstimatedSizeMap(XMPMeta2 & stdXMP, PropSizeMap2 * propSizes) +{ +#if Trace_PackageForJPEG + printf(" Creating top level property map:\n"); +#endif + + + + spIStructureNode rootNode = stdXMP.mDOM; + + for (auto rootIter = rootNode->Iterator(); rootIter; rootIter = rootIter->Next()) { + + const spINode & node = rootIter->GetNode(); + if (!strcmp(node->GetNameSpace()->c_str(), kXMP_NS_XMP_Note) && !strcmp(node->GetName()->c_str(), "HasExtendedXMP")) continue; + size_t propSize = EstimateSizeForJPEG(node); + StringPtrPair2 namePair(node->GetNameSpace()->c_str(), node->GetName()->c_str()); + PropSizeMap2::value_type mapValue(propSize, namePair); + (void)propSizes->insert(propSizes->upper_bound(propSize), mapValue); +#if Trace_PackageForJPEG + printf(" %d bytes, %s in %s\n", propSize, stdProp->name.c_str(), stdSchema->name.c_str()); +#endif + } + + +} // CreateEstimatedSizeMap +#endif + +#if ENABLE_CPP_DOM_MODEL +// ------------------------------------------------------------------------------------------------- +// MoveLargestProperty +// ------------------- + +static size_t MoveLargestProperty(XMPMeta2 & stdXMP, XMPMeta2 * extXMP, PropSizeMap2 & propSizes) +{ + XMP_Assert(!propSizes.empty()); + +#if 0 + // *** Xocde 2.3 on Mac OS X 10.4.7 seems to have a bug where this does not pick the last + // *** item in the map. We'll just avoid it on all platforms until thoroughly tested. + PropSizeMap::iterator lastPos = propSizes.end(); + --lastPos; // Move to the actual last item. +#else + PropSizeMap2::iterator lastPos = propSizes.begin(); + PropSizeMap2::iterator nextPos = lastPos; + for (++nextPos; nextPos != propSizes.end(); ++nextPos) lastPos = nextPos; +#endif + + size_t propSize = lastPos->first; + const char * schemaURI = lastPos->second.first; + const char * propName = lastPos->second.second; + +#if Trace_PackageForJPEG + printf(" Move %s, %d bytes\n", propName, propSize); +#endif + + bool moved = MoveOneProperty(stdXMP, extXMP, schemaURI, propName); + XMP_Assert(moved); + + propSizes.erase(lastPos); + return propSize; + +} // MoveLargestProperty +#endif + // ------------------------------------------------------------------------------------------------- // MoveLargestProperty // ------------------- @@ -600,7 +1953,7 @@ XMPUtils::ComposeArrayItemPath ( XMP_StringPtr schemaNS, if ( (itemIndex < 0) && (itemIndex != kXMP_ArrayLastItem) ) XMP_Throw ( "Array index out of bounds", kXMPErr_BadParam ); - XMP_StringLen reserveLen = strlen(arrayName) + 2 + 32; // Room plus padding. + size_t reserveLen = strlen(arrayName) + 2 + 32; // Room plus padding. XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str(). fullPath.reserve ( reserveLen ); @@ -644,7 +1997,7 @@ XMPUtils::ComposeStructFieldPath ( XMP_StringPtr schemaNS, ExpandXPath ( fieldNS, fieldName, &fieldPath ); if ( fieldPath.size() != 2 ) XMP_Throw ( "The fieldName must be simple", kXMPErr_BadXPath ); - XMP_StringLen reserveLen = strlen(structName) + fieldPath[kRootPropStep].step.size() + 1; + size_t reserveLen = strlen(structName) + fieldPath[kRootPropStep].step.size() + 1; XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str(). fullPath.reserve ( reserveLen ); @@ -681,7 +2034,7 @@ XMPUtils::ComposeQualifierPath ( XMP_StringPtr schemaNS, ExpandXPath ( qualNS, qualName, &qualPath ); if ( qualPath.size() != 2 ) XMP_Throw ( "The qualifier name must be simple", kXMPErr_BadXPath ); - XMP_StringLen reserveLen = strlen(propName) + qualPath[kRootPropStep].step.size() + 2; + size_t reserveLen = strlen(propName) + qualPath[kRootPropStep].step.size() + 2; XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str(). fullPath.reserve ( reserveLen ); @@ -718,7 +2071,7 @@ XMPUtils::ComposeLangSelector ( XMP_StringPtr schemaNS, XMP_VarString langName ( _langName ); NormalizeLangValue ( &langName ); - XMP_StringLen reserveLen = strlen(arrayName) + langName.size() + 14; + size_t reserveLen = strlen(arrayName) + langName.size() + 14; XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str(). fullPath.reserve ( reserveLen ); @@ -758,7 +2111,7 @@ XMPUtils::ComposeFieldSelector ( XMP_StringPtr schemaNS, ExpandXPath ( fieldNS, fieldName, &fieldPath ); if ( fieldPath.size() != 2 ) XMP_Throw ( "The fieldName must be simple", kXMPErr_BadXPath ); - XMP_StringLen reserveLen = strlen(arrayName) + fieldPath[kRootPropStep].step.size() + strlen(fieldValue) + 5; + size_t reserveLen = strlen(arrayName) + fieldPath[kRootPropStep].step.size() + strlen(fieldValue) + 5; XMP_VarString fullPath; // ! Allow for arrayName to be the incoming _fullPath.c_str(). fullPath.reserve ( reserveLen ); @@ -1480,6 +2833,14 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP, XMP_VarString * extStr, XMP_VarString * digestStr ) { + +#if ENABLE_CPP_DOM_MODEL + if(sUseNewCoreAPIs) { + + const XMPMeta2 & orig = dynamic_cast<const XMPMeta2 &>(origXMP); + return XMPUtils::PackageForJPEG(orig, stdStr, extStr, digestStr); + } +#endif XMP_Assert ( (stdStr != 0) && (extStr != 0) && (digestStr != 0) ); // ! Enforced by wrapper. enum { kStdXMPLimit = 65000 }; @@ -1676,6 +3037,225 @@ XMPUtils::PackageForJPEG ( const XMPMeta & origXMP, } // PackageForJPEG + +#if ENABLE_CPP_DOM_MODEL +// ------------------------------------------------------------------------------------------------- +// PackageForJPEG +// -------------- + +/* class static */ void +XMPUtils::PackageForJPEG(const XMPMeta2 & origXMP, + 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_VarString tempStr; + XMPMeta2 stdXMP, extXMP; + 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, keepItSmall, 1, "", "", 0); +#if Trace_PackageForJPEG + printf("\nXMPUtils::PackageForJPEG - Full serialize %d bytes\n", tempStr.size()); +#endif + + if (tempStr.size() > kStdXMPLimit) { + + // Couldn't fit everything, make a copy of the input XMP and make sure there is no xmp:Thumbnails property. + + stdXMP.mDOM = origXMP.mDOM->Clone()->ConvertToMetadata(); + + + if (stdXMP.DoesPropertyExist(kXMP_NS_XMP, "Thumbnails")) { + stdXMP.DeleteProperty(kXMP_NS_XMP, "Thumbnails"); + stdXMP.SerializeToBuffer(&tempStr, keepItSmall, 1, "", "", 0); +#if Trace_PackageForJPEG + printf(" Delete xmp:Thumbnails, %d bytes left\n", tempStr.size()); +#endif + } + + } + + if (tempStr.size() > kStdXMPLimit) { + + // Still doesn't fit, move all of the Camera Raw namespace. Add a dummy value for xmpNote:HasExtendedXMP. + + stdXMP.SetProperty(kXMP_NS_XMP_Note, "HasExtendedXMP", "123456789-123456789-123456789-12", 0); + + spIStructureNode currRootNode = stdXMP.mDOM; + std::vector<XMP_VarString> nodes; + for (auto rootPropIter = currRootNode->Iterator(); rootPropIter; rootPropIter = rootPropIter->Next()) { + + auto rootPropNodeCloned = rootPropIter->GetNode()->Clone(); + if (strcmp(rootPropNodeCloned->GetNameSpace()->c_str(), kXMP_NS_CameraRaw ) ) continue; + extXMP.mDOM->AppendNode(rootPropNodeCloned); + nodes.push_back(rootPropNodeCloned->GetName()->c_str()); + } + + for (size_t childIdx = 0, childLim = nodes.size(); childIdx != childLim; ++childIdx) { + + stdXMP.mDOM->RemoveNode(kXMP_NS_CameraRaw, AdobeXMPCommon::npos, nodes[childIdx].c_str(), nodes[childIdx].size() ); + } + + + if (nodes.size() != 0) { + + stdXMP.SerializeToBuffer(&tempStr, keepItSmall, 1, "", "", 0); +#if Trace_PackageForJPEG + printf(" Move Camera Raw schema, %d bytes left\n", tempStr.size()); +#endif + } + + } + + if (tempStr.size() > kStdXMPLimit) { + + // Still doesn't fit, move photoshop:History. + + bool moved = MoveOneProperty(stdXMP, &extXMP, kXMP_NS_Photoshop, "History"); + + if (moved) { + stdXMP.SerializeToBuffer(&tempStr, keepItSmall, 1, "", "", 0); +#if Trace_PackageForJPEG + printf(" Move photoshop:History, %d bytes left\n", tempStr.size()); +#endif + } + + } + + 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 + // and top level property name. Since maps are inherently ordered, a reverse iteration of + // the map can be done to move the largest things first. We use a double loop to keep going + // until the serialization actually fits, in case the estimates are off. + + PropSizeMap2 propSizes; + CreateEstimatedSizeMap(stdXMP, &propSizes); + +#if Trace_PackageForJPEG + if (!propSizes.empty()) { + printf(" Top level property map, smallest to largest:\n"); + PropSizeMap::iterator mapPos = propSizes.begin(); + PropSizeMap::iterator mapEnd = propSizes.end(); + for (; mapPos != mapEnd; ++mapPos) { + size_t propSize = mapPos->first; + const char * schemaName = mapPos->second.first->c_str(); + const char * propName = mapPos->second.second->c_str(); + printf(" %d bytes, %s in %s\n", propSize, propName, schemaName); + } + } +#endif + +#if 0 // Trace_PackageForJPEG *** Xcode 2.3 on 10.4.7 has bugs in backwards iteration + if (!propSizes.empty()) { + printf(" Top level property map, largest to smallest:\n"); + PropSizeMap::iterator mapPos = propSizes.end(); + PropSizeMap::iterator mapBegin = propSizes.begin(); + for (--mapPos; true; --mapPos) { + size_t propSize = mapPos->first; + const char * schemaName = mapPos->second.first->c_str(); + const char * propName = mapPos->second.second->c_str(); + printf(" %d bytes, %s in %s\n", propSize, propName, schemaName); + if (mapPos == mapBegin) break; + } + } +#endif + + // Outer loop to make sure enough is actually moved. + + 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); + XMP_Assert(propSize > 0); + + if (propSize > tempLen) propSize = tempLen; // ! Don't go negative. + tempLen -= propSize; + + } + + // Reserialize the remaining standard XMP. + + stdXMP.SerializeToBuffer(&tempStr, keepItSmall, 1, "", "", 0); + + } + + } + + 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); + } + + // Set the static output strings. + + if (!extXMP.mDOM->ChildCount()) { + + // Just have the standard XMP. + *stdStr = tempStr; + + } + else { + + // Have extended XMP. Serialize it, compute the digest, reset xmpNote:HasExtendedXMP, and + // reserialize the standard XMP. + + extXMP.SerializeToBuffer(&tempStr, (keepItSmall | kXMP_OmitPacketWrapper), 0, "", "", 0); + *extStr = tempStr; + + MD5_CTX context; + XMP_Uns8 digest[16]; + MD5Init(&context); + MD5Update(&context, (XMP_Uns8*)tempStr.c_str(), (XMP_Uns32)tempStr.size()); + MD5Final(digest, &context); + + digestStr->reserve(32); + for (size_t i = 0; i < 16; ++i) { + XMP_Uns8 byte = digest[i]; + digestStr->push_back(kHexDigits[byte >> 4]); + digestStr->push_back(kHexDigits[byte & 0xF]); + } + + 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((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 - stdStr->size(); // ! Do this before erasing the trailer. + if (extraPadding > 2047) extraPadding = 2047; + stdStr->erase(stdStr->size() - kTrailerLen); + stdStr->append(extraPadding, ' '); + stdStr->append(kPacketTrailer); + +} // PackageForJPEG + +#endif // ------------------------------------------------------------------------------------------------- // MergeFromJPEG // ------------- @@ -1694,6 +3274,10 @@ XMPUtils::MergeFromJPEG ( XMPMeta * fullXMP, } // MergeFromJPEG + + + + // ------------------------------------------------------------------------------------------------- // CurrentDateTime // --------------- @@ -1978,6 +3562,10 @@ XMPUtils::CompareDateTime ( const XMP_DateTime & _in_left, // ================================================================================================= + + +std::string * XMPUtils::WhiteSpaceStrPtr = NULL; + std::string& XMPUtils::Trim( std::string& string ) { size_t pos = string.find_last_not_of( *WhiteSpaceStrPtr ); @@ -1992,6 +3580,162 @@ std::string& XMPUtils::Trim( std::string& string ) return string; } -std::string * XMPUtils::WhiteSpaceStrPtr = NULL; +#if ENABLE_CPP_DOM_MODEL +#include "XMPCore/XMPCoreErrorCodes.h" + +void XMPUtils::MapXMPErrorToIError( XMP_Int32 xmpErrorCode, IError::eErrorDomain & domain, IError::eErrorCode & code ) { + + switch ( xmpErrorCode ) { + case kXMPErr_Unknown: + case kXMPErr_TBD: + code = kGECUnknownFailure; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_Unavailable: + case kXMPErr_Unimplemented: + code = kGECNotImplemented; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_BadObject: + case kXMPErr_BadParam: + case kXMPErr_BadValue: + code = kGECParametersNotAsExpected; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_AssertFailure: + case kXMPErr_EnforceFailure: + code = kGECAssertionFailure; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_InternalFailure: + code = kGECInternalFailure; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_Deprecated: + code = kGECDeprecatedFunctionCall; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_ExternalFailure: + code = kGECExternalFailure; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_UserAbort: + case kXMPErr_ProgressAbort: + code = kGECUserAbort; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_StdException: + code = kGECStandardException; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_UnknownException: + code = kGECUnknownExceptionCaught; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_NoMemory: + code = kMMECAllocationFailure; + domain = IError_base::kEDMemoryManagement; + break; + + case kXMPErr_BadSchema: + code = kDMECBadSchema; + domain = IError_base::kEDDataModel; + break; + + case kXMPErr_BadXPath: + code = kDMECBadXPath; + domain = IError_base::kEDDataModel; + break; + + case kXMPErr_BadOptions: + code = kDMECBadOptions; + domain = IError_base::kEDDataModel; + break; + + case kXMPErr_BadIndex: + code = kGECIndexOutOfBounds; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_BadIterPosition: + code = kDMECBadIterPosition; + domain = IError_base::kEDDataModel; + break; + + case kXMPErr_BadParse: + code = kPECBadXMP; + domain = IError_base::kEDParser; + break; + + case kXMPErr_BadSerialize: + code = kSECSizeExceed; + domain = IError_base::kEDSerializer; + break; + + case kXMPErr_BadFileFormat: + case kXMPErr_NoFileHandler: + case kXMPErr_TooLargeForJPEG: + case kXMPErr_NoFile: + case kXMPErr_FilePermission: + case kXMPErr_DiskSpace: + case kXMPErr_ReadError: + case kXMPErr_WriteError: + case kXMPErr_BadBlockFormat: + case kXMPErr_FilePathNotAFile: + case kXMPErr_RejectedFileExtension: + code = kGECNotImplemented; + domain = IError_base::kEDGeneral; + break; + + case kXMPErr_BadXML: + code = kPECBadXML; + domain = IError_base::kEDParser; + break; + + case kXMPErr_BadRDF: + code = kPECBadRDF; + domain = IError_base::kEDParser; + break; + + case kXMPErr_BadXMP: + code = kPECBadXMP; + domain = IError_base::kEDParser; + break; + + case kXMPErr_EmptyIterator: + code = kDMECEmptyIterator; + domain = IError_base::kEDDataModel; + break; + + case kXMPErr_BadUnicode: + code = kDMECBadUnicode; + domain = IError_base::kEDDataModel; + break; + + case kXMPErr_BadTIFF: + case kXMPErr_BadJPEG: + case kXMPErr_BadPSD: + case kXMPErr_BadPSIR: + case kXMPErr_BadIPTC: + case kXMPErr_BadMPEG: + default: + code = kGECNotImplemented; + domain = IError_base::kEDGeneral; + break; + + } +} + +#endif // ================================================================================================= diff --git a/XMPCore/source/XMPUtils.hpp b/XMPCore/source/XMPUtils.hpp index f9cfce1..a669e7f 100644 --- a/XMPCore/source/XMPUtils.hpp +++ b/XMPCore/source/XMPUtils.hpp @@ -15,175 +15,234 @@ #include "XMPCore/source/XMPMeta.hpp" #include "XMPCore/source/XMPCore_Impl.hpp" #include "public/include/client-glue/WXMPUtils.hpp" +#include "XMPCore/XMPCoreDefines.h" + +#if ENABLE_CPP_DOM_MODEL +#include "XMPCommon/Interfaces/IError.h" +#include "XMPCore/XMPCoreFwdDeclarations.h" +#include "XMPCore/source/XMPMeta2.hpp" +#endif + +#include "XMPCore/source/XMPCore_Impl.hpp" +#include "source/XMLParserAdapter.hpp" +#include "XMPCore/source/XMPMeta.hpp" +#include "third-party/zuid/interfaces/MD5.h" + + + + // ------------------------------------------------------------------------------------------------- class XMPUtils { public: - + static bool - Initialize(); // ! For internal use only! - + Initialize(); // ! For internal use only! + static void - Terminate() RELEASE_NO_THROW; // ! For internal use only! + Terminate() RELEASE_NO_THROW; // ! For internal use only! + + // --------------------------------------------------------------------------------------------- + +#if ENABLE_CPP_DOM_MODEL + static void SetNode(const AdobeXMPCore::spINode & node, XMP_StringPtr value, XMP_OptionBits options); + static XMP_OptionBits ConvertNewArrayFormToOldArrayForm(const AdobeXMPCore::spcIArrayNode & arrayNode); + static AdobeXMPCore::spINode CreateArrayChildNode(const AdobeXMPCore::spIArrayNode & arrayNode, XMP_OptionBits options); + static void DoSetArrayItem(const AdobeXMPCore::spIArrayNode & arrayNode, XMP_Index itemIndex, XMP_StringPtr itemValue, XMP_OptionBits options); + static void SetImplicitNodeInformation(bool & firstImplicitNodeFound, AdobeXMPCore::spINode & implicitNodeRoot, AdobeXMPCore::spINode & destNode, + XMP_Index & implicitNodeIndex, XMP_Index index = 0); + static void GetNameSpaceAndNameFromStepValue(const XMP_VarString & stepStr, const AdobeXMPCore::spcINameSpacePrefixMap & defaultMap, + XMP_VarString & stepNameSpace, XMP_VarString & stepName); + static bool FindNode(const AdobeXMPCore::spIMetadata & mDOM, XMP_ExpandedXPath & expPath, bool createNodes, XMP_OptionBits leafOptions, + AdobeXMPCore::spINode & retNode, XMP_Index * nodeIndex = 0, bool ignoreLastStep = 0); + static bool FindCnstNode(const AdobeXMPCore::spIMetadata & mDOM, XMP_ExpandedXPath & expPath, AdobeXMPCore::spINode & destNode, XMP_OptionBits * options = 0, + XMP_Index * arrayIndex = 0); + static AdobeXMPCore::spINode FindChildNode(const AdobeXMPCore::spINode & parent, XMP_StringPtr childName, XMP_StringPtr childNameSpace, bool createNodes, size_t * pos /* = 0 */); + static size_t GetNodeChildCount(const AdobeXMPCore::spcINode & node); + static AdobeXMPCore::spcINodeIterator GetNodeChildIterator(const AdobeXMPCore::spcINode & node); + static std::vector< AdobeXMPCore::spcINode > GetChildVector(const AdobeXMPCore::spINode & node); + static XMP_OptionBits GetIXMPOptions(const AdobeXMPCore::spcINode & node); + static bool HandleConstAliasStep(const AdobeXMPCore::spIMetadata & mDOM, AdobeXMPCore::spINode & destNode, const XMP_ExpandedXPath & expandedXPath, + XMP_Index * nodeIndex = 0); + static bool HandleAliasStep(const AdobeXMPCore::spIMetadata & mDOM, XMP_ExpandedXPath & expandedXPath, bool createNodes, XMP_OptionBits leafOptions, + AdobeXMPCore::spINode & destNode, XMP_Index * nodeIndex, bool ignoreLastStep); + static AdobeXMPCommon::spcIUTF8String GetNodeValue(const AdobeXMPCore::spINode & node); + static XMP_Index LookupFieldSelector_v2(const AdobeXMPCore::spIArrayNode & arrayNode, XMP_VarString fieldName, XMP_VarString fieldValue); + static AdobeXMPCore::spINode CreateTerminalNode(const char* nameSpace, const char * name, XMP_OptionBits options); + +#endif - // --------------------------------------------------------------------------------------------- static void - ComposeArrayItemPath ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_VarString * fullPath ); + ComposeArrayItemPath(XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_Index itemIndex, + XMP_VarString * fullPath); static void - ComposeStructFieldPath ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_VarString * fullPath ); + ComposeStructFieldPath(XMP_StringPtr schemaNS, + XMP_StringPtr structName, + XMP_StringPtr fieldNS, + XMP_StringPtr fieldName, + XMP_VarString * fullPath); static void - ComposeQualifierPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_VarString * fullPath ); + ComposeQualifierPath(XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_StringPtr qualNS, + XMP_StringPtr qualName, + XMP_VarString * fullPath); static void - ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr langName, - XMP_VarString * fullPath ); + ComposeLangSelector(XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr langName, + XMP_VarString * fullPath); static void - ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_VarString * fullPath ); + ComposeFieldSelector(XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr fieldNS, + XMP_StringPtr fieldName, + XMP_StringPtr fieldValue, + XMP_VarString * fullPath); // --------------------------------------------------------------------------------------------- static void - ConvertFromBool ( bool binValue, - XMP_VarString * strValue ); + ConvertFromBool(bool binValue, + XMP_VarString * strValue); static void - ConvertFromInt ( XMP_Int32 binValue, - XMP_StringPtr format, - XMP_VarString * strValue ); + ConvertFromInt(XMP_Int32 binValue, + XMP_StringPtr format, + XMP_VarString * strValue); static void - ConvertFromInt64 ( XMP_Int64 binValue, - XMP_StringPtr format, - XMP_VarString * strValue ); + ConvertFromInt64(XMP_Int64 binValue, + XMP_StringPtr format, + XMP_VarString * strValue); static void - ConvertFromFloat ( double binValue, - XMP_StringPtr format, - XMP_VarString * strValue ); + ConvertFromFloat(double binValue, + XMP_StringPtr format, + XMP_VarString * strValue); static void - ConvertFromDate ( const XMP_DateTime & binValue, - XMP_VarString * strValue ); + ConvertFromDate(const XMP_DateTime & binValue, + XMP_VarString * strValue); // --------------------------------------------------------------------------------------------- static bool - ConvertToBool ( XMP_StringPtr strValue ); + ConvertToBool(XMP_StringPtr strValue); static XMP_Int32 - ConvertToInt ( XMP_StringPtr strValue ); + ConvertToInt(XMP_StringPtr strValue); static XMP_Int64 - ConvertToInt64 ( XMP_StringPtr strValue ); + ConvertToInt64(XMP_StringPtr strValue); static double - ConvertToFloat ( XMP_StringPtr strValue ); + ConvertToFloat(XMP_StringPtr strValue); static void - ConvertToDate ( XMP_StringPtr strValue, - XMP_DateTime * binValue ); + ConvertToDate(XMP_StringPtr strValue, + XMP_DateTime * binValue); // --------------------------------------------------------------------------------------------- static void - CurrentDateTime ( XMP_DateTime * time ); + CurrentDateTime(XMP_DateTime * time); static void - SetTimeZone ( XMP_DateTime * time ); + SetTimeZone(XMP_DateTime * time); static void - ConvertToUTCTime ( XMP_DateTime * time ); + ConvertToUTCTime(XMP_DateTime * time); static void - ConvertToLocalTime ( XMP_DateTime * time ); + ConvertToLocalTime(XMP_DateTime * time); static int - CompareDateTime ( const XMP_DateTime & left, - const XMP_DateTime & right ); + CompareDateTime(const XMP_DateTime & left, + const XMP_DateTime & right); // --------------------------------------------------------------------------------------------- static void - EncodeToBase64 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - XMP_VarString * encodedStr ); + EncodeToBase64(XMP_StringPtr rawStr, + XMP_StringLen rawLen, + XMP_VarString * encodedStr); static void - DecodeFromBase64 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - XMP_VarString * rawStr ); + DecodeFromBase64(XMP_StringPtr encodedStr, + XMP_StringLen encodedLen, + XMP_VarString * rawStr); // --------------------------------------------------------------------------------------------- static void - PackageForJPEG ( const XMPMeta & xmpObj, - XMP_VarString * stdStr, - XMP_VarString * extStr, - XMP_VarString * digestStr ); + PackageForJPEG(const XMPMeta & xmpObj, + XMP_VarString * stdStr, + XMP_VarString * extStr, + XMP_VarString * digestStr); + +#if ENABLE_CPP_DOM_MODEL static void - MergeFromJPEG ( XMPMeta * fullXMP, - const XMPMeta & extendedXMP ); + PackageForJPEG(const XMPMeta2 & xmpObj, + XMP_VarString * stdStr, + XMP_VarString * extStr, + XMP_VarString * digestStr); +#endif + static void + MergeFromJPEG(XMPMeta * fullXMP, + const XMPMeta & extendedXMP); + + + // --------------------------------------------------------------------------------------------- static void - CatenateArrayItems ( const XMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr separator, - XMP_StringPtr quotes, - XMP_OptionBits options, - XMP_VarString * catedStr ); + CatenateArrayItems(const XMPMeta & xmpObj, + XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr separator, + XMP_StringPtr quotes, + XMP_OptionBits options, + XMP_VarString * catedStr); static void - SeparateArrayItems ( XMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr ); + SeparateArrayItems(XMPMeta * xmpObj, + XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_OptionBits options, + XMP_StringPtr catedStr); static void - ApplyTemplate ( XMPMeta * workingXMP, - const XMPMeta & templateXMP, - XMP_OptionBits actions ); + ApplyTemplate(XMPMeta * workingXMP, + const XMPMeta & templateXMP, + XMP_OptionBits actions); + static void - RemoveProperties ( XMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ); + RemoveProperties(XMPMeta * xmpObj, + XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_OptionBits options); + static void - DuplicateSubtree ( const XMPMeta & source, - XMPMeta * dest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS, - XMP_StringPtr destRoot, - XMP_OptionBits options ); + DuplicateSubtree(const XMPMeta & source, + XMPMeta * dest, + XMP_StringPtr sourceNS, + XMP_StringPtr sourceRoot, + XMP_StringPtr destNS, + XMP_StringPtr destRoot, + XMP_OptionBits options); + // --------------------------------------------------------------------------------------------- @@ -191,6 +250,56 @@ public: static std::string * WhiteSpaceStrPtr; +#if ENABLE_CPP_DOM_MODEL + static void MapXMPErrorToIError(XMP_Int32 xmpErrorCodes, AdobeXMPCommon::IError::eErrorDomain & domain, AdobeXMPCommon::IError::eErrorCode & code); + static bool SerializeExtensionAsJSON(const AdobeXMPCore::spINode & extensionNode, std::string & key, std::string & value); + static bool IsExtensionValidForBackwardCompatibility(const AdobeXMPCore::spINode & extensionNode); + static bool CreateExtensionNode(const AdobeXMPCore::spIStructureNode & xmpNode, const XMP_VarString & serializedJSON, const XMP_VarString & doubleQuotesStr); + + + static void + CatenateArrayItems_v2(const XMPMeta & xmpObj, + XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_StringPtr separator, + XMP_StringPtr quotes, + XMP_OptionBits options, + XMP_VarString * catedStr); + static void + SeparateArrayItems_v2(XMPMeta * xmpObj, + XMP_StringPtr schemaNS, + XMP_StringPtr arrayName, + XMP_OptionBits options, + XMP_StringPtr catedStr); + + static void + RemoveProperties_v2(XMPMeta * xmpMetaPtr, + XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_OptionBits options); + + static void + ApplyTemplate_v2(XMPMeta * workingXMP, + const XMPMeta & templateXMP, + XMP_OptionBits actions); + + static void + DuplicateSubtree_v2(const XMPMeta & source, + XMPMeta * dest, + XMP_StringPtr sourceNS, + XMP_StringPtr sourceRoot, + XMP_StringPtr destNS, + XMP_StringPtr destRoot, + XMP_OptionBits options); + +#endif + + static bool CreateExtensionNode(XMP_Node ** xmpNode, const XMP_VarString & serializedJSON, const XMP_VarString & doubleQuotesString); + + static bool GetSerializedJSONForExtensionNode(const XMP_Node * xmpNode, XMP_VarString &extensionAsKey, XMP_VarString & serializedJSON); + + static bool IsSuitableForJSONSerialization(const XMP_Node * xmpNode); + }; // XMPUtils // ================================================================================================= diff --git a/XMPCore/source/XMPUtils2.cpp b/XMPCore/source/XMPUtils2.cpp new file mode 100644 index 0000000..9d88cd3 --- /dev/null +++ b/XMPCore/source/XMPUtils2.cpp @@ -0,0 +1,921 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2014 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= + +#include "public/include/XMP_Environment.h" // ! This must be the first include! +#include "XMPCore/source/XMPCore_Impl.hpp" +#include "XMPCore/XMPCoreDefines.h" +#if ENABLE_CPP_DOM_MODEL + +#include "XMPCore/source/XMPUtils.hpp" +#include "source/UnicodeInlines.incl_cpp" +#include "source/UnicodeConversions.hpp" +#include "source/ExpatAdapter.hpp" +#include "third-party/zuid/interfaces/MD5.h" +#include "XMPCore/Interfaces/IMetadata_I.h" +#include "XMPCore/Interfaces/IArrayNode_I.h" +#include "XMPCore/Interfaces/ISimpleNode_I.h" +#include "XMPCore/Interfaces/INodeIterator.h" +#include "XMPCore/Interfaces/IPathSegment_I.h" +#include "XMPCore/Interfaces/IPath_I.h" +#include "XMPCore/Interfaces/INameSpacePrefixMap_I.h" +#include "XMPCore/Interfaces/IDOMImplementationRegistry_I.h" + +#include "XMPCommon/Interfaces/IUTF8String_I.h" + +const XMP_VarString xmlNameSpace = "http://www.w3.org/XML/1998/namespace"; +extern bool IsInternalProperty(const XMP_VarString & schema, const XMP_VarString & prop); +extern const char * sListProps[]; +extern const char * sDateProps[]; + +using namespace AdobeXMPCommon; +using namespace AdobeXMPCore; + +// ================================================================================================= +// CloneSubtree +// ============ + +void +CloneIXMPSubtree(const spcINode & origRoot, const spINode & cloneParent, bool skipEmpty /* = false */) +{ + spINode clonedRoot = origRoot->Clone(skipEmpty, true); + if (!clonedRoot) return; + if (cloneParent->GetNodeType() == INode::kNTArray) { + cloneParent->ConvertToArrayNode()->AppendNode( clonedRoot ); + } else if (cloneParent->GetNodeType() == INode::kNTStructure) { + cloneParent->ConvertToStructureNode()->InsertNode( cloneParent ); + } + +} // CloneSubtree + +// ================================================================================================= +// LookupLangItem +// ============== +// +// ! Assumes that the language value is already normalized. + +XMP_Index +LookupIXMPLangItem(const spcIArrayNode & arrayNode, XMP_VarString & lang) +{ + XMP_OptionBits arrayOptions = XMPUtils::GetIXMPOptions(arrayNode); + if (!(arrayOptions & kXMP_PropValueIsArray)) { // *** Check for alt-text? + XMP_Throw("Language item must be used on array", kXMPErr_BadXPath); + } + + XMP_Index index = 1; + XMP_Index itemLim = arrayNode->ChildCount(); + + for (; index <= itemLim; ++index) { + spcINode currItem = arrayNode->GetNodeAtIndex(index); + + if (!currItem->HasQualifiers()) continue; + spcINode langQual = currItem->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if (!langQual) continue; + if (langQual->GetNodeType() != INode::kNTSimple) continue; + XMP_VarString langQualValue = langQual->ConvertToSimpleNode()->GetValue()->c_str(); + if (langQualValue == lang) break; + } + + if (index == itemLim + 1) index = -1; + return index; + +} // LookupLangItem +// ================================================================================================= + + +// CompareSubtrees +// =============== +// +// Compare 2 subtrees for semantic equality. The comparison includes value, qualifiers, and form. +// Schemas, top level properties, struct fields, and qualifiers are allowed to have differing order, +// the appropriate right node is found from the left node's name. Alt-text arrays are allowed to be +// in differing language order, other arrays are compared in order. + +// *** Might someday consider sorting unordered arrays. +// *** Should expose this through XMPUtils. + + +bool +CompareSubtrees(spcINode leftNode, spcINode rightNode) +{ + // Don't compare the names here, we want to allow the outermost roots to have different names. + XMP_OptionBits leftNodeOptions = XMPUtils::GetIXMPOptions(leftNode), rightNodeOptions = XMPUtils::GetIXMPOptions(rightNode); + if (leftNode->GetNodeType() != rightNode->GetNodeType()) return false; + if (leftNode->GetNodeType() == INode::kNTSimple) { + if ( strcmp( leftNode->ConvertToSimpleNode()->GetValue()->c_str(), rightNode->ConvertToSimpleNode()->GetValue()->c_str() ) ) { + return false; + } + } + if (XMPUtils::GetNodeChildCount(leftNode) != XMPUtils::GetNodeChildCount(rightNode)) return false; + if (leftNode->HasQualifiers() != rightNode->HasQualifiers() ) return false; + if (leftNode->HasQualifiers()) { + for (auto leftQualIter = leftNode->QualifiersIterator(); leftQualIter; leftQualIter = leftQualIter->Next()) { + spcINode leftQualNode = leftQualIter->GetNode(); + spcINode righQualNode = rightNode->GetINode_I()->GetQualifier( leftQualNode->GetNameSpace(), leftQualNode->GetName() ); + if (!righQualNode || !CompareSubtrees(leftQualNode, righQualNode)){ + return false; + } + + } + } + + if (leftNode->GetNodeType() == INode::kNTStructure ) { + for ( auto leftChildIter = XMPUtils::GetNodeChildIterator(leftNode); leftChildIter; leftChildIter = leftChildIter->Next()) { + spcINode leftChildNode = leftChildIter->GetNode(); + spcINode rightChildNode = XMPUtils::FindChildNode( AdobeXMPCore_Int::const_pointer_cast<INode>(rightNode), leftChildNode->GetName()->c_str(), leftChildNode->GetNameSpace()->c_str(), false, 0); + if (!rightChildNode || !CompareSubtrees(leftChildNode, rightChildNode)) { + return false; + } + } + } + + + else if (leftNodeOptions & kXMP_PropArrayIsAltText) { + // The parent node is an alt-text array. + auto leftNodeAsArray = leftNode->ConvertToArrayNode(); + auto rightNodeAsArray = rightNode->ConvertToArrayNode(); + + size_t leftNodeChildCount = XMPUtils::GetNodeChildCount(leftNode); + for (size_t idx = 1; idx <= leftNodeChildCount; ++idx) { + spcINode leftChild = leftNodeAsArray->GetNodeAtIndex(idx); + spcINode leftChildFirstQualifier = leftChild->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if (leftChildFirstQualifier) { + XMP_VarString leftChildFirstQualifierValue = leftChildFirstQualifier->ConvertToSimpleNode()->GetValue()->c_str(); + size_t rightIdx = LookupIXMPLangItem( rightNodeAsArray, leftChildFirstQualifierValue ); + if (rightIdx == -1) { + return false; + } + spcINode rightChild = rightNodeAsArray->GetNodeAtIndex( rightIdx ); + if (!CompareSubtrees(leftChild, rightChild)) { + return false; + } + } + + } + + + } + else { + + // The parent must be simple or some other (not alt-text) kind of array. + XMP_Assert((!(leftNodeOptions & kXMP_PropCompositeMask)) || (leftNodeOptions & kXMP_PropValueIsArray)); + auto leftNodeAsArray = leftNode->ConvertToArrayNode(); + auto rightNodeAsArray = rightNode->ConvertToArrayNode(); + + size_t leftNodeChildCount = XMPUtils::GetNodeChildCount(leftNode); + for (size_t idx = 1; idx <= leftNodeChildCount; ++idx) { + spcINode leftChild = leftNodeAsArray->GetNodeAtIndex(idx); + spcINode rightChild = rightNodeAsArray->GetNodeAtIndex(idx); + if (!CompareSubtrees(leftChild, rightChild)) { + return false; + } + } + + } + return true; +}// CompareSubtrees + +// ------------------------------------------------------------------------------------------------- +// MergeArrayItems +// --------------- + +static void +MergeArrayItems(spINode newArray, spINode mergedArray) +{ + XMP_Assert(newArray->GetNodeType() == INode::kNTArray); + XMP_Assert(mergedArray->GetNodeType() == INode::kNTArray); + + auto newArrayAsArrayNode = newArray->ConvertToArrayNode(); + auto mergedArrayAsArrayNode = mergedArray->ConvertToArrayNode(); + + for (size_t newNum = 1, newLim = XMPUtils::GetNodeChildCount(newArray); newNum <= newLim; ++newNum) { + + spcINode newItem = newArrayAsArrayNode->GetNodeAtIndex(newNum); + size_t mergedNum, mergedLim; + for (mergedNum = 1, mergedLim = XMPUtils::GetNodeChildCount(mergedArray) + 1; mergedNum < mergedLim; ++mergedNum) { + spcINode mergedItem = mergedArrayAsArrayNode->GetNodeAtIndex(mergedNum); + if (CompareSubtrees(newItem, mergedItem)) break; + } + + if (mergedNum == mergedLim) CloneIXMPSubtree(newItem, mergedArray, false); + + } + +} // MergeArrayItems +static bool +ItemValuesMatch(spcINode leftNode, spcINode rightNode) +{ + if (!leftNode && !rightNode) return true; + if (!leftNode || !rightNode) return false; + const XMP_OptionBits leftNodeOptions = XMPUtils::GetIXMPOptions(leftNode); + const XMP_OptionBits rightNodeOptions = XMPUtils::GetIXMPOptions(rightNode); + const XMP_OptionBits leftForm = leftNodeOptions & kXMP_PropCompositeMask; + const XMP_OptionBits rightForm = rightNodeOptions & kXMP_PropCompositeMask; + + if (leftForm != rightForm) return false; + + if (leftForm == 0) { + + // Simple nodes, check the values and xml:lang qualifiers. + XMP_VarString leftValue = leftNode->ConvertToSimpleNode()->GetValue()->c_str(); + XMP_VarString rightValue = rightNode->ConvertToSimpleNode()->GetValue()->c_str(); + if (leftValue != rightValue) return false; + if ((leftNodeOptions & kXMP_PropHasLang) != (rightNodeOptions & kXMP_PropHasLang)) return false; + if (leftNodeOptions & kXMP_PropHasLang) { + spcINode leftDefaultQualifier = leftNode->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + spcINode rightDefaultQualifier = rightNode->GetQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if (!leftDefaultQualifier && !rightDefaultQualifier) return true; + if (!leftDefaultQualifier || !rightDefaultQualifier) return false; + + XMP_VarString leftFirstQualValue = leftDefaultQualifier->ConvertToSimpleNode()->GetValue()->c_str(); + XMP_VarString rightFirstQualValue = rightDefaultQualifier->ConvertToSimpleNode()->GetValue()->c_str(); + if (leftFirstQualValue != rightFirstQualValue) { + return false; + } + } + + } + else if (leftForm == kXMP_PropValueIsStruct) { + + // Struct nodes, see if all fields match, ignoring order. + size_t leftNodeChildCount = XMPUtils::GetNodeChildCount(leftNode); + size_t rightNodeChildCount = XMPUtils::GetNodeChildCount(rightNode); + if (leftNodeChildCount != rightNodeChildCount) return false; + + auto leftNodeChildIter = XMPUtils::GetNodeChildIterator(leftNode); + auto rightNodeChildIter = XMPUtils::GetNodeChildIterator(rightNode); + for (; leftNodeChildIter; leftNodeChildIter = leftNodeChildIter->Next(), rightNodeChildIter = rightNodeChildIter->Next()) { + spcINode leftField = leftNodeChildIter->GetNode(); + spINode rightField = XMPUtils::FindChildNode( AdobeXMPCore_Int::const_pointer_cast<INode>(rightNode), + leftField->GetNameSpace()->c_str(), leftField->GetName()->c_str(), kXMP_ExistingOnly, 0); + if (!rightField || !ItemValuesMatch(leftField, rightField)) { + return false; + } + + } + + } + else { + + // Array nodes, see if the "leftNode" values are present in the "rightNode", ignoring order, duplicates, + // and extra values in the rightNode-> The rightNode is the destination for AppendProperties. + + XMP_Assert(leftForm & kXMP_PropValueIsArray); + size_t leftNodeChildCount = XMPUtils::GetNodeChildCount(leftNode); + size_t rightNodeChildCount = XMPUtils::GetNodeChildCount(rightNode); + auto leftNodeAsArrayNode = leftNode->ConvertToArrayNode(); + auto rightNodeAsArrayNode = rightNode->ConvertToArrayNode(); + for (size_t leftNum = 1; leftNum <= leftNodeChildCount; ++leftNum) { + + spcINode leftItem = leftNodeAsArrayNode->GetNodeAtIndex(leftNum); + bool leftItemFound = false; + for (size_t rightNum = 1; rightNum <= rightNodeChildCount; ++rightNum) { + + spcINode rightItem = rightNodeAsArrayNode->GetNodeAtIndex(rightNum); + + if (ItemValuesMatch(leftItem, rightItem)) { + leftItemFound = true; + break; + } + } + if (!leftItemFound) return false; + + } + + } + + return true; // All of the checks passed. + +} // ItemValuesMatch + + +static void +AppendSubtree(spcINode sourceNode, spINode &destParent, +const bool mergeCompound, const bool replaceOld, const bool deleteEmpty) +{ + + XMP_VarString sourceName = sourceNode->GetName()->c_str(); + XMP_VarString sourceNamespace = sourceNode->GetNameSpace()->c_str(); + + XMP_VarString destName = destParent->GetName()->c_str(); + XMP_VarString destNamespace = destParent->GetNameSpace()->c_str(); + if (sourceName.find("UserComment") != XMP_VarString::npos) { + int y = 1; + y++; + } + // Need clone non empty only + // to do lang alt append + // to do lang alt + size_t destPos = 0; + spINode destNode = XMPUtils::FindChildNode(destParent, sourceNode->GetName()->c_str(), sourceNode->GetNameSpace()->c_str(), kXMP_ExistingOnly, &destPos); + + bool valueIsEmpty = false; + XMP_OptionBits sourceNodeOptions = XMPUtils::GetIXMPOptions(sourceNode); + + if (sourceNode->GetNodeType() == INode::kNTSimple) { + valueIsEmpty = sourceNode->ConvertToSimpleNode()->GetValue()->empty(); + } + else { + + valueIsEmpty = XMPUtils::GetNodeChildCount(sourceNode) == 0; + } + + + if (valueIsEmpty) { + if (sourceNode && deleteEmpty) { + destParent->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( sourceNode->GetNameSpace(), sourceNode->GetName() ); + } + return; // ! Done, empty values are either ignored or cause deletions. + } + + if (!destNode) { + // The one easy case, the destination does not exist. + destNode = sourceNode->Clone(true, true); // TO DO need to skip empty nodes + if (!destNode) { + if (destParent->GetNodeType() == INode::kNTStructure) { + destParent->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( sourceNode->GetNameSpace(), sourceNode->GetName() ); + } + else if (destParent->GetNodeType() == INode::kNTArray) { + destParent->ConvertToArrayNode()->RemoveNodeAtIndex( destPos ); + } + return; + } + if (destParent->GetNodeType() == INode::kNTStructure) { + destParent->ConvertToStructureNode()->InsertNode( destNode ); + } + else if (destParent->GetNodeType() == INode::kNTArray) { + destParent->ConvertToArrayNode()->InsertNodeAtIndex( destNode, destPos ); + } + // XMP_Assert ( (!destNode) || (! 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)); + + XMP_OptionBits sourceForm = XMPUtils::GetIXMPOptions(sourceNode) & kXMP_PropCompositeMask; + XMP_OptionBits destForm = XMPUtils::GetIXMPOptions(destNode) & kXMP_PropCompositeMask; + + bool replaceThis = replaceOld; // ! Don't modify replaceOld, it gets passed to inner calls. + if (mergeCompound && (!XMP_PropIsSimple(sourceForm))) replaceThis = false; + + if (replaceThis) { + if (destNode) { + destParent->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( destNode->GetNameSpace(), destNode->GetName() ); + } + destNode = sourceNode->Clone(true, true); + if (!destNode) return; + if ( destNode->GetParent() != destParent && destParent->GetNodeType() == INode::kNTStructure ) + destParent->ConvertToStructureNode()->AppendNode( destNode ); + else if (destNode->GetParent() != destParent && destParent->GetNodeType() == INode::kNTArray) { + destParent->ConvertToArrayNode()->InsertNodeAtIndex( destNode, destPos ); + } + if (!XMP_PropIsSimple(XMPUtils::GetIXMPOptions(destNode)) && !XMPUtils::GetNodeChildCount(destNode)) { + // 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. + if (destParent->GetNodeType() == INode::kNTStructure) { + destParent->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( destNode->GetNameSpace(), destNode->GetName() ); + } + else if (destParent->GetNodeType() == INode::kNTArray) { + destParent->ConvertToArrayNode()->RemoveNodeAtIndex( destPos ); + } + } + + return; + + } + + // From here on are cases for merging arrays or structs. + + if (XMP_PropIsSimple(sourceForm) || (sourceForm != destForm)) return; + + if (sourceForm == kXMP_PropValueIsStruct) { + + auto sourceChildIter = XMPUtils::GetNodeChildIterator(sourceNode); + for (; sourceChildIter; sourceChildIter = sourceChildIter->Next()) { + spcINode sourceField = sourceChildIter->GetNode(); + AppendSubtree(sourceField, destNode, mergeCompound, replaceOld, deleteEmpty); + if (deleteEmpty && !XMPUtils::GetNodeChildCount(destNode)) { + destParent->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( destNode->GetNameSpace(), destNode->GetName() ); + } + } + + + } + else if (sourceForm & kXMP_PropArrayIsAltText) { + + XMP_Assert(mergeCompound); + spcIArrayNode sourceArrayNode = sourceNode->ConvertToArrayNode(); + for (size_t sourceNum = 1, sourceLim = XMPUtils::GetNodeChildCount(sourceNode); sourceNum <= sourceLim && destNode; ++sourceNum) { + + spcINode sourceItem = sourceArrayNode->GetNodeAtIndex(sourceNum); + spcIUTF8String sourceItemValue = sourceItem->ConvertToSimpleNode()->GetValue(); + if (!sourceItem->HasQualifiers()) continue; + spcINode langQualNode = sourceItem->GetQualifier(xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if (!langQualNode || langQualNode->GetNodeType() != INode::kNTSimple) continue; + XMP_VarString langValue = langQualNode->ConvertToSimpleNode()->GetValue()->c_str(); + size_t destIndex = LookupIXMPLangItem( destNode->ConvertToArrayNode(), langValue ); + + if (sourceItemValue->empty()) { + + if (deleteEmpty && (destIndex != -1)) { + //delete ( destNode->children[destIndex] ); + //destNode->children.erase ( destNode->children.begin() + destIndex ); + destNode->ConvertToArrayNode()->RemoveNodeAtIndex(destIndex); + if (!XMPUtils::GetNodeChildCount(destNode)) { + + if (destParent->GetNodeType() == INode::kNTStructure) { + destParent->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( destNode->GetNameSpace(), destNode->GetName() ); + } + else if (destParent->GetNodeType() == INode::kNTArray) { + destParent->ConvertToArrayNode()->RemoveNodeAtIndex( destPos ); + } + } + } + + } + else { + + if (destIndex != -1) { + + // The source and dest arrays both have this language item. + + if (replaceOld) { + auto temp = destNode->ConvertToArrayNode()->GetNodeAtIndex( destIndex ); + temp->ConvertToSimpleNode()->SetValue(sourceItemValue->c_str(), sourceItemValue->size() ); + } + + } + else { + + + spcISimpleNode firstQualifier = sourceItem->GetSimpleQualifier( xmlNameSpace.c_str(), xmlNameSpace.size(), "lang", AdobeXMPCommon::npos ); + if ((!XMP_LitMatch(firstQualifier->GetValue()->c_str(), "x-default")) || !XMPUtils::GetNodeChildCount(destNode)) { + + CloneIXMPSubtree(sourceItem, destNode, true); + } + else { + + spINode destItem = AdobeXMPCore_Int::ISimpleNode_I::CreateSimpleNode( sourceItem->GetNameSpace(), sourceItem->GetName(), sourceItemValue ); + destNode->ConvertToArrayNode()->InsertNodeAtIndex(destItem, 1); + } + + } + + } + + } + + } + + else if (sourceForm & kXMP_PropValueIsArray) { + auto sourceNodeChildIter = XMPUtils::GetNodeChildIterator(sourceNode); + for (; sourceNodeChildIter; sourceNodeChildIter = sourceNodeChildIter->Next()) { + spcINode sourceItem = sourceNodeChildIter->GetNode(); + + spIArrayNode arrayNode = destNode->ConvertToArrayNode(); + size_t arrayChildCount = arrayNode->ChildCount(); + size_t foundIndex = arrayChildCount + 1; + for (size_t arrayIdx = 1; arrayIdx <= arrayChildCount; arrayIdx++) { + spINode destItem = arrayNode->GetNodeAtIndex(arrayIdx); + //XMP_VarString destValue = INode_I::AdaptConstNodeTo_I<ISimpleNode, INode::kNTSimple>(destItem)->GetValue_I()->c_str(); + if (ItemValuesMatch(destItem, sourceItem)) { + foundIndex = arrayIdx; + break; + } + + } + if (foundIndex == arrayChildCount + 1) { + + CloneIXMPSubtree(sourceItem, destNode, true); + + } + + } + + + } + +} // AppendSubtree_v2 + +// ------------------------------------------------------------------------------------------------- +// ApplyTemplate +// ------------- + +/* class static */ void +XMPUtils::ApplyTemplate_v2( XMPMeta * workingXMPBasePtr, + const XMPMeta & templateXMPBasePtr, + XMP_OptionBits actions) +{ + XMPMeta2 * workingXMP = dynamic_cast<XMPMeta2 *>(workingXMPBasePtr); + if (!workingXMPBasePtr) return; + const XMPMeta2 & templateXMP = dynamic_cast<const XMPMeta2 &> (templateXMPBasePtr); + 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); + + auto defaultMap = INameSpacePrefixMap::GetDefaultNameSpacePrefixMap()->GetINameSpacePrefixMap_I(); + + if (doClear) { + + // Visit the top level working properties, delete if not in the template. + auto topLevelPropIter = XMPUtils::GetNodeChildIterator(workingXMP->mDOM); + std::vector<spcINode> propsToBeDeleted; // needed to avoid problems related with deletion and invalid const iterator + + for (; topLevelPropIter; topLevelPropIter = topLevelPropIter->Next()) { + spcINode topLevelProp = topLevelPropIter->GetNode(); + XMP_VarString currNameSpace = defaultMap->GetPrefix(topLevelProp->GetNameSpace())->c_str(); + XMP_VarString nodeFullName = currNameSpace + ":" + topLevelProp->GetName()->c_str(); + if (doAll || !IsInternalProperty(topLevelProp->GetNameSpace()->c_str(), nodeFullName)) { + if (!templateXMP.mDOM->GetIStructureNode_I()->GetNode(topLevelProp->GetNameSpace(), topLevelProp->GetName())) { + propsToBeDeleted.push_back(topLevelProp); + } + } + + } + for (size_t idx = 0; idx < propsToBeDeleted.size(); idx++) { + workingXMP->mDOM->GetIStructureNode_I()->RemoveNode(propsToBeDeleted[idx]->GetNameSpace(), propsToBeDeleted[idx]->GetName()); + } + + } + + if (doAdd | doReplace) { + + auto templateTopPropIter = XMPUtils::GetNodeChildIterator(templateXMP.mDOM); + for (; templateTopPropIter; templateTopPropIter = templateTopPropIter->Next()) { + spcINode currentTemplateTopProp = templateTopPropIter->GetNode(); + XMP_VarString currNameSpace = defaultMap->GetPrefix(currentTemplateTopProp->GetNameSpace())->c_str(); + XMP_VarString nodeFullName = currNameSpace + ":" + currentTemplateTopProp->GetName()->c_str(); + XMP_ExpandedXPath expPath; + ExpandXPath(currentTemplateTopProp->GetNameSpace()->c_str(), nodeFullName.c_str(), &expPath); + spINode destNode; + spINode templateXMPRoot = workingXMP->mDOM; + if (!currentTemplateTopProp) continue; + if (doAll || !IsInternalProperty(currentTemplateTopProp->GetNameSpace()->c_str(), nodeFullName)){ + AppendSubtree ( currentTemplateTopProp, templateXMPRoot, doAdd, doReplace, deleteEmpty ); + } + } + } + + +} // ApplyTemplate_v2 + +// ------------------------------------------------------------------------------------------------- +// DuplicateSubtree +// ---------------- + + +void CloneContents(spINode sourceNode, spINode &destNode) { + + + if (sourceNode->GetNodeType() == INode::kNTSimple) { + + spISimpleNode sourceSimpleNode = sourceNode->ConvertToSimpleNode(); + spISimpleNode destSimpleNode = AdobeXMPCore_Int::ISimpleNode_I::CreateSimpleNode(destNode->GetNameSpace(), destNode->GetName(), sourceSimpleNode->GetValue() ); + destNode = destSimpleNode; + } + else if (sourceNode->GetNodeType() == INode::kNTArray) + { + spIArrayNode arraySourceNode = sourceNode->ConvertToArrayNode(); + spIArrayNode destArrayNode = AdobeXMPCore_Int::IArrayNode_I::CreateArrayNode(destNode->GetNameSpace(), destNode->GetName(), arraySourceNode->GetArrayForm()); + destNode = destArrayNode; + for (auto childIter = arraySourceNode->Iterator(); childIter; childIter = childIter->Next()) { + + spINode childCloned = childIter->GetNode()->Clone(); + destArrayNode->AppendNode(childCloned); + } + + destNode = destArrayNode; + + } + else { + + spIStructureNode arraySourceNode = sourceNode->ConvertToStructureNode(); + + spIStructureNode destArrayNode = destNode->ConvertToStructureNode(); + for (auto childIter = arraySourceNode->Iterator(); childIter; childIter = childIter->Next()) { + + spINode childCloned = childIter->GetNode()->Clone(); + destArrayNode->AppendNode(childCloned); + } + + destNode = destArrayNode; + + } + + if (sourceNode->HasQualifiers()) { + + + for (auto qualIter = sourceNode->QualifiersIterator(); qualIter; qualIter = qualIter->Next()) { + + spINode clonedQual = qualIter->GetNode()->Clone(); + destNode->InsertQualifier(clonedQual); + } + } +} + +/* class static */ void +XMPUtils::DuplicateSubtree_v2(const XMPMeta & sourceBasePtr, +XMPMeta * destBasePtr, +XMP_StringPtr sourceNS, +XMP_StringPtr sourceRoot, +XMP_StringPtr destNS, +XMP_StringPtr destRoot, +XMP_OptionBits options) +{ + + XMPMeta2 * dest = dynamic_cast<XMPMeta2 *>(destBasePtr); + + if (!dest) return; + const XMPMeta2 & source = dynamic_cast<const XMPMeta2 &> (sourceBasePtr); + + IgnoreParam(options); + // TODO : Use of testnode == soucenode seems slightly dodgy, verify if it works in null case, simple case, subtree case + bool fullSourceTree = false; + bool fullDestTree = false; + + XMP_ExpandedXPath sourcePath, destPath; + + spINode sourceNode; + spINode destNode; + + XMP_Assert((sourceNS != 0) && (*sourceNS != 0)); + XMP_Assert((sourceRoot != 0) && (*sourceRoot != 0)); + XMP_Assert((dest != 0) && (destNS != 0) && (destRoot != 0)); + + if (*destNS == 0) destNS = sourceNS; + if (*destRoot == 0) destRoot = sourceRoot; + + if (XMP_LitMatch(sourceNS, "*")) fullSourceTree = true; + if (XMP_LitMatch(destNS, "*")) fullDestTree = true; + + if ((&source == dest) && (fullSourceTree | fullDestTree)) { + XMP_Throw("Can't duplicate tree onto itself", kXMPErr_BadParam); + } + + if (fullSourceTree & fullDestTree) XMP_Throw("Use Clone for full tree to full tree", kXMPErr_BadParam); + + if (fullSourceTree) { + + // The destination must be an existing empty struct, copy all of the source top level as fields. + + ExpandXPath(destNS, destRoot, &destPath); + + XMP_OptionBits destOptions = 0; + if (!XMPUtils::FindCnstNode(dest->mDOM, destPath, destNode, &destOptions)) { + XMP_Throw("Destination must be an existing struct", kXMPErr_BadXPath); + } + if (!XMP_PropIsStruct(destOptions)) { + XMP_Throw("Destination must be an existing struct", kXMPErr_BadXPath); + } + + if (XMPUtils::GetNodeChildCount(destNode)) { + if (options & kXMP_DeleteExisting) { + destNode->Clear(); + } + else { + XMP_Throw("Destination must be an empty struct", kXMPErr_BadXPath); + } + } + sourceNode = source.mDOM; + CloneContents(sourceNode, destNode); + + } + else if (fullDestTree) { + + // The source node must be an existing struct, copy all of the fields to the dest top level. + + XMP_ExpandedXPath srcPath; + ExpandXPath(sourceNS, sourceRoot, &srcPath); + spINode sourceNode; + XMP_OptionBits sourceNodeOptions = 0; + XMPUtils::FindCnstNode(source.mDOM, srcPath, sourceNode, &sourceNodeOptions); + + if ((!sourceNode) || (!XMP_PropIsStruct(sourceNodeOptions))) { + XMP_Throw("Source must be an existing struct", kXMPErr_BadXPath); + } + + destNode = dest->mDOM; + + if (XMPUtils::GetNodeChildCount(destNode)) { + if (options & kXMP_DeleteExisting) { + destNode->Clear(); + } + else { + XMP_Throw("Destination tree must be empty", kXMPErr_BadXPath); + } + } + + + for (auto sourceChildIter = XMPUtils::GetNodeChildIterator(sourceNode); sourceChildIter; sourceChildIter = sourceChildIter->Next()) { + + spINode copyNode = sourceChildIter->GetNode()->Clone(); + if (destNode->GetNodeType() == INode::kNTStructure){ + destNode->ConvertToStructureNode()->AppendNode(copyNode); + } + + } + } + else { + + // Find the root nodes for the source and destination subtrees. + + ExpandXPath(sourceNS, sourceRoot, &sourcePath); + ExpandXPath(destNS, destRoot, &destPath); + spINode destNodeCopy; + if (!XMPUtils::FindCnstNode(source.mDOM, sourcePath, sourceNode)) { + XMP_Throw("Can't find source subtree", kXMPErr_BadXPath); + } + if (XMPUtils::FindCnstNode(dest->mDOM, destPath, destNode)) { + XMP_Throw("Destination subtree must not exist", kXMPErr_BadXPath); + } + + + if (!XMPUtils::FindNode(dest->mDOM, destPath, kXMP_CreateNodes, 0, destNode)) { // Now create the dest. + XMP_Throw("Can't create destination root node", kXMPErr_BadXPath); + } + + // Make sure the destination is not within the source! The source can't be inside the destination + // because the source already existed and the destination was just created. + + if (&source == dest) { + for (spINode testNode = destNode; testNode; testNode = testNode->GetParent()){ + if (testNode.get() == sourceNode.get()) { + + XMP_Throw("Destination subtree is within the source subtree", kXMPErr_BadXPath); + } + } + } + + // *** Could use a CloneTree util here and maybe elsewhere. + //destNode = sourceNode->Clone(); + + if (sourceNode->GetNodeType() == INode::kNTSimple) { + + spISimpleNode sourceSimpleNode = sourceNode->ConvertToSimpleNode(); + spISimpleNode destSimpleNode = AdobeXMPCore_Int::ISimpleNode_I::CreateSimpleNode(destNode->GetNameSpace(), destNode->GetName(), + sourceSimpleNode->GetValue() ); + destNodeCopy = destSimpleNode; + } + else if (sourceNode->GetNodeType() == INode::kNTArray) + { + spIArrayNode arraySourceNode = sourceNode->ConvertToArrayNode(); + spIArrayNode destArrayNode = AdobeXMPCore_Int::IArrayNode_I::CreateArrayNode(destNode->GetNameSpace(), destNode->GetName(), arraySourceNode->GetArrayForm()); + destNodeCopy = destArrayNode; + for (auto childIter = arraySourceNode->Iterator(); childIter; childIter = childIter->Next()) { + + spINode childCloned = childIter->GetNode()->Clone(); + destArrayNode->AppendNode(childCloned); + } + + destNodeCopy = destArrayNode; + + } + else { + + spIStructureNode arraySourceNode = sourceNode->ConvertToStructureNode(); + spIStructureNode destArrayNode = AdobeXMPCore_Int::IStructureNode_I::CreateStructureNode(destNode->GetNameSpace(), destNode->GetName()); + destNodeCopy = destArrayNode; + for (auto childIter = arraySourceNode->Iterator(); childIter; childIter = childIter->Next()) { + + spINode childCloned = childIter->GetNode()->Clone(); + destArrayNode->AppendNode(childCloned); + } + + destNodeCopy = destArrayNode; + + } + + if (sourceNode->HasQualifiers()) { + + + for (auto qualIter = sourceNode->QualifiersIterator(); qualIter; qualIter = qualIter->Next()) { + + spINode clonedQual = qualIter->GetNode()->Clone(); + destNodeCopy->InsertQualifier(clonedQual); + } + } + + dest->mDOM->ReplaceNode(destNodeCopy); + } + +} // DuplicateSubtree_v2 + +// ------------------------------------------------------------------------------------------------- +// RemoveProperties +// ---------------- + +/* class static */ void +XMPUtils::RemoveProperties_v2(XMPMeta * xmpMetaPtr, + XMP_StringPtr schemaNS, + XMP_StringPtr propName, + XMP_OptionBits options) +{ + using namespace AdobeXMPCommon; + using namespace AdobeXMPCore; + XMPMeta2 * xmpObj = dynamic_cast<XMPMeta2 *> (xmpMetaPtr); + if (!xmpObj) { + return; + } + // Handle aliases in remove properties + XMP_Assert((schemaNS != 0) && (propName != 0)); // ! Enforced by wrapper. + + const bool doAll = XMP_TestOption(options, kXMPUtil_DoAllProperties); + const bool includeAliases = XMP_TestOption(options, kXMPUtil_IncludeAliases); + + if (*propName != 0) { + + // Remove just the one indicated property. This might be an alias, the named schema might + // not actually exist. So don't lookup the schema node. + + if (*schemaNS == 0) XMP_Throw("Property name requires schema namespace", kXMPErr_BadParam); + + XMP_ExpandedXPath expPath; + + ExpandXPath(schemaNS, propName, &expPath); + XMP_Index propIndex = 0; + spINode propNode; + if (XMPUtils::FindNode(xmpObj->mDOM, expPath, kXMP_ExistingOnly, kXMP_NoOptions, propNode, &propIndex)) { + if (doAll || !IsInternalProperty(expPath[kSchemaStep].step, expPath[kRootPropStep].step)) { + spINode parentNode = propNode->GetParent(); // *** Should have XMP_Node::RemoveChild(pos). + + if (parentNode->GetNodeType() == INode::kNTStructure) { + parentNode->ConvertToStructureNode()->GetIStructureNode_I()->RemoveNode( propNode->GetNameSpace(), propNode->GetName() ); + } + else if (parentNode->GetNodeType() == INode::kNTArray) { + parentNode->ConvertToArrayNode()->RemoveNodeAtIndex(propIndex); + } + } + } + + } + else if (*schemaNS != 0) { + std::vector<spINode> topLevelNodesToBeDeleted; + for (auto topLevelIter = xmpObj->mDOM->Iterator(); topLevelIter; topLevelIter = topLevelIter->Next()) { + spINode topLevelProp = topLevelIter->GetNode(); + if (XMP_LitMatch(topLevelProp->GetNameSpace()->c_str(), schemaNS)) { + topLevelNodesToBeDeleted.push_back(topLevelProp); + } + } + for (size_t propIdx = 0; propIdx < topLevelNodesToBeDeleted.size(); ++propIdx) { + + xmpObj->mDOM->GetIStructureNode_I()->RemoveNode(topLevelNodesToBeDeleted[propIdx]->GetNameSpace(), topLevelNodesToBeDeleted[propIdx]->GetName()); + } + if (includeAliases) { + // Removing Aliases + XMP_StringPtr nsPrefix; + XMP_StringLen nsLen; + (void)XMPMeta::GetNamespacePrefix(schemaNS, &nsPrefix, &nsLen); + + XMP_AliasMapPos currAlias = sRegisteredAliasMap->begin(); + XMP_AliasMapPos endAlias = sRegisteredAliasMap->end(); + + for (; currAlias != endAlias; ++currAlias) { + if (strncmp(currAlias->first.c_str(), nsPrefix, nsLen) == 0) { + spINode destNode; + XMP_Index actualPos = 0; + size_t colonPos = currAlias->first.find_first_of(":"); + + xmpObj->mDOM->RemoveNode( schemaNS, AdobeXMPCommon::npos, currAlias->first.substr( colonPos + 1 ).c_str(), AdobeXMPCommon::npos ); + /*if (!XMPUtils::FindCnstNode(xmpObj->mDOM, currAlias->second, destNode, 0, &actualPos)) continue; + if (!destNode) continue; + spINode rootProp = destNode; + while (rootProp && rootProp->GetParent() != xmpObj->mDOM) { + rootProp = rootProp->GetParent(); + } + if (doAll || !IsInternalProperty(rootProp->GetNameSpace()->c_str(), rootProp->GetName()->c_str())) { + spINode parentNode = destNode->GetParent(); + if (destNode->IsArrayItem()){ + INode_I::AdaptNodeTo_I<IArrayNode, INode::kNTArray>(parentNode)->RemoveNode_I(actualPos); + } + else { + INode_I::AdaptNodeTo_I<IStructureNode, INode::kNTStructure>(parentNode)->RemoveNode_I(destNode->GetNameSpace()->c_str(), destNode->GetName()->c_str()); + } + }*/ + + } + } + + } + + } + else { + + xmpObj->mDOM->Clear(); + } + +} // RemoveProperties_v2 +#endif + |