summaryrefslogtreecommitdiff
path: root/XMPCore
diff options
context:
space:
mode:
Diffstat (limited to 'XMPCore')
-rw-r--r--XMPCore/ImplHeaders/ArrayNodeImpl.h71
-rw-r--r--XMPCore/ImplHeaders/ClientDOMParserWrapperImpl.h50
-rw-r--r--XMPCore/ImplHeaders/ClientDOMSerializerWrapperImpl.h50
-rw-r--r--XMPCore/ImplHeaders/CompositeNodeImpl.h56
-rw-r--r--XMPCore/ImplHeaders/CoreConfigurationManagerImpl.h50
-rw-r--r--XMPCore/ImplHeaders/CoreObjectFactoryImpl.h65
-rw-r--r--XMPCore/ImplHeaders/DOMImplementationRegistryImpl.h62
-rw-r--r--XMPCore/ImplHeaders/DOMParserImpl.h64
-rw-r--r--XMPCore/ImplHeaders/DOMSerializerImpl.h60
-rw-r--r--XMPCore/ImplHeaders/MetadataImpl.h82
-rw-r--r--XMPCore/ImplHeaders/NameSpacePrefixMapImpl.h79
-rw-r--r--XMPCore/ImplHeaders/NodeImpl.h111
-rw-r--r--XMPCore/ImplHeaders/PathImpl.h66
-rw-r--r--XMPCore/ImplHeaders/PathSegmentImpl.h66
-rw-r--r--XMPCore/ImplHeaders/RDFDOMParserImpl.h53
-rw-r--r--XMPCore/ImplHeaders/RDFDOMSerializerImpl.h53
-rw-r--r--XMPCore/ImplHeaders/SimpleNodeImpl.h66
-rw-r--r--XMPCore/ImplHeaders/StructureNodeImpl.h87
-rw-r--r--XMPCore/ImplHeaders/TNodeIteratorImpl.h81
-rw-r--r--XMPCore/Interfaces/IArrayNode_I.h90
-rw-r--r--XMPCore/Interfaces/ICompositeNode_I.h73
-rw-r--r--XMPCore/Interfaces/ICoreConfigurationManager_I.h75
-rw-r--r--XMPCore/Interfaces/ICoreObjectFactory_I.h65
-rw-r--r--XMPCore/Interfaces/IDOMImplementationRegistry_I.h108
-rw-r--r--XMPCore/Interfaces/IDOMParser_I.h92
-rw-r--r--XMPCore/Interfaces/IDOMSerializer_I.h82
-rw-r--r--XMPCore/Interfaces/IMetadata_I.h68
-rw-r--r--XMPCore/Interfaces/INameSpacePrefixMap_I.h106
-rw-r--r--XMPCore/Interfaces/INodeIterator_I.h61
-rw-r--r--XMPCore/Interfaces/INode_I.h223
-rw-r--r--XMPCore/Interfaces/IPathSegment_I.h125
-rw-r--r--XMPCore/Interfaces/IPath_I.h72
-rw-r--r--XMPCore/Interfaces/ISimpleNode_I.h83
-rw-r--r--XMPCore/Interfaces/IStructureNode_I.h189
-rw-r--r--XMPCore/Interfaces/IXMPLanguageAlternative_I.h30
-rw-r--r--XMPCore/XMPCoreDefines_I.h39
-rw-r--r--XMPCore/XMPCoreFwdDeclarations_I.h82
-rw-r--r--XMPCore/build/CMakeLists.txt9
-rw-r--r--XMPCore/build/CMakeListsCommon.txt162
-rw-r--r--XMPCore/resource/linux/XMPCore.exp1
-rw-r--r--XMPCore/resource/mac/XMPCore.exp1
-rw-r--r--XMPCore/resource/win/XMPCore.def3
-rw-r--r--XMPCore/source/ArrayNodeImpl.cpp227
-rw-r--r--XMPCore/source/ClientDOMParserWrapperImpl.cpp90
-rw-r--r--XMPCore/source/ClientDOMSerializerWrapperImpl.cpp106
-rw-r--r--XMPCore/source/CompositeNodeImpl.cpp154
-rw-r--r--XMPCore/source/CoreConfigurationManagerImpl.cpp56
-rw-r--r--XMPCore/source/CoreObjectFactoryImpl.cpp158
-rw-r--r--XMPCore/source/DOMImplementationRegistryImpl.cpp96
-rw-r--r--XMPCore/source/DOMParserImpl.cpp325
-rw-r--r--XMPCore/source/DOMSerializerImpl.cpp54
-rw-r--r--XMPCore/source/ExpatAdapter.cpp9
-rw-r--r--XMPCore/source/IArrayNode_I.cpp85
-rw-r--r--XMPCore/source/ICompositeNode_I.cpp92
-rw-r--r--XMPCore/source/ICoreConfigurationManager_I.cpp54
-rw-r--r--XMPCore/source/ICoreObjectFactory_I.cpp62
-rw-r--r--XMPCore/source/IDOMImplementationRegistry_I.cpp84
-rw-r--r--XMPCore/source/IDOMParser_I.cpp66
-rw-r--r--XMPCore/source/IDOMSerializer_I.cpp62
-rw-r--r--XMPCore/source/IMetadata_I.cpp59
-rw-r--r--XMPCore/source/INameSpacePrefixMap_I.cpp84
-rw-r--r--XMPCore/source/INodeIterator_I.cpp78
-rw-r--r--XMPCore/source/INode_I.cpp183
-rw-r--r--XMPCore/source/IPathSegment_I.cpp70
-rw-r--r--XMPCore/source/IPath_I.cpp82
-rw-r--r--XMPCore/source/ISimpleNode_I.cpp74
-rw-r--r--XMPCore/source/IStructureNode_I.cpp78
-rw-r--r--XMPCore/source/MetadataImpl.cpp445
-rw-r--r--XMPCore/source/NameSpacePrefixMapImpl.cpp311
-rw-r--r--XMPCore/source/NodeImpl.cpp479
-rw-r--r--XMPCore/source/PathImpl.cpp186
-rw-r--r--XMPCore/source/PathSegmentImpl.cpp145
-rw-r--r--XMPCore/source/RDFDOMParserImpl.cpp156
-rw-r--r--XMPCore/source/RDFDOMSerializerImpl.cpp508
-rw-r--r--XMPCore/source/SimpleNodeImpl.cpp105
-rw-r--r--XMPCore/source/StructureNodeImpl.cpp231
-rw-r--r--XMPCore/source/WXMPIterator.cpp7
-rw-r--r--XMPCore/source/WXMPMeta.cpp81
-rw-r--r--XMPCore/source/WXMPUtils.cpp33
-rw-r--r--XMPCore/source/XMPCore_Impl.cpp92
-rw-r--r--XMPCore/source/XMPCore_Impl.hpp34
-rw-r--r--XMPCore/source/XMPIterator.cpp11
-rw-r--r--XMPCore/source/XMPIterator.hpp4
-rw-r--r--XMPCore/source/XMPIterator2.cpp542
-rw-r--r--XMPCore/source/XMPIterator2.hpp153
-rw-r--r--XMPCore/source/XMPMeta-GetSet.cpp75
-rw-r--r--XMPCore/source/XMPMeta-Parse.cpp18
-rw-r--r--XMPCore/source/XMPMeta-Serialize.cpp15
-rw-r--r--XMPCore/source/XMPMeta.cpp142
-rw-r--r--XMPCore/source/XMPMeta.hpp54
-rw-r--r--XMPCore/source/XMPMeta2-GetSet.cpp1356
-rw-r--r--XMPCore/source/XMPMeta2.hpp190
-rw-r--r--XMPCore/source/XMPUtils-FileInfo.cpp454
-rw-r--r--XMPCore/source/XMPUtils.cpp1760
-rw-r--r--XMPCore/source/XMPUtils.hpp293
-rw-r--r--XMPCore/source/XMPUtils2.cpp921
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
+