From c2a0354cc8abf0e0f790d038aae74b8982a8b1fa Mon Sep 17 00:00:00 2001 From: Sergey Hovakimyan Date: Wed, 10 Jul 2024 11:50:40 +0400 Subject: [PATCH 1/6] adds XMP-Toolkit-SDK as a submodule --- .gitmodules | 3 + src/CMakeLists.txt | 6 +- xmpsdk/CMakeLists.txt | 144 ++++++++++++++++++++++++++++++----------- xmpsdk/XMP-Toolkit-SDK | 1 + 4 files changed, 114 insertions(+), 40 deletions(-) create mode 100644 .gitmodules create mode 160000 xmpsdk/XMP-Toolkit-SDK diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..2a87d44862 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "xmpsdk/XMP-Toolkit-SDK"] + path = xmpsdk/XMP-Toolkit-SDK + url = https://github.com/adobe/XMP-Toolkit-SDK.git diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6b321bac94..ea8268cbf1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -210,7 +210,9 @@ if(EXIV2_ENABLE_XMP OR EXIV2_ENABLE_EXTERNAL_XMP) endif() if(EXIV2_ENABLE_XMP) - target_sources(exiv2lib PRIVATE $) +# target_sources(exiv2lib PRIVATE $) + target_link_libraries(exiv2lib PRIVATE exiv2-xmp) + target_compile_definitions(exiv2lib PUBLIC EXV_ADOBE_XMPSDK=2016) elseif(EXIV2_ENABLE_EXTERNAL_XMP) target_link_libraries(exiv2lib PUBLIC ${XMPSDK_LIBRARY}) target_include_directories(exiv2lib PUBLIC ${XMPSDK_INCLUDE_DIR}) @@ -307,7 +309,7 @@ set(requires_private_for_pc_file write_basic_package_version_file(exiv2ConfigVersion.cmake COMPATIBILITY ExactVersion) -install(TARGETS exiv2lib EXPORT exiv2Export) +install(TARGETS exiv2lib exiv2-xmp EXPORT exiv2Export) include(CMakePackageConfigHelpers) configure_package_config_file( diff --git a/xmpsdk/CMakeLists.txt b/xmpsdk/CMakeLists.txt index 0156317d10..3cef5699fa 100644 --- a/xmpsdk/CMakeLists.txt +++ b/xmpsdk/CMakeLists.txt @@ -1,46 +1,114 @@ add_library( - exiv2-xmp OBJECT - src/ExpatAdapter.cpp - src/MD5.cpp - src/ParseRDF.cpp - src/UnicodeConversions.cpp - src/WXMPIterator.cpp - src/WXMPMeta.cpp - src/WXMPUtils.cpp - src/XML_Node.cpp - src/XMPCore_Impl.cpp - src/XMPIterator.cpp - src/XMPMeta-GetSet.cpp - src/XMPMeta-Parse.cpp - src/XMPMeta-Serialize.cpp - src/XMPMeta.cpp - src/XMPUtils-FileInfo.cpp - src/XMPUtils.cpp - include/MD5.h - include/TXMPIterator.hpp - include/TXMPMeta.hpp - include/TXMPUtils.hpp - include/XMP_Const.h - include/XMP_Environment.h - include/XMP.incl_cpp - include/XMPSDK.hpp - include/XMP_Version.h + exiv2-xmp OBJECT + XMP-Toolkit-SDK/public/include/XMP_Const.h + XMP-Toolkit-SDK/public/include/XMP_Environment.h + XMP-Toolkit-SDK/public/include/XMP_Version.h + XMP-Toolkit-SDK/public/include/TXMPFiles.hpp + XMP-Toolkit-SDK/public/include/TXMPIterator.hpp + XMP-Toolkit-SDK/public/include/TXMPMeta.hpp + XMP-Toolkit-SDK/public/include/TXMPUtils.hpp + XMP-Toolkit-SDK/public/include/XMP.hpp + XMP-Toolkit-SDK/public/include/XMP_IO.hpp + + XMP-Toolkit-SDK/source/Endian.h + XMP-Toolkit-SDK/source/EndianUtils.hpp + XMP-Toolkit-SDK/source/ExpatAdapter.hpp + XMP-Toolkit-SDK/source/Host_IO.hpp + XMP-Toolkit-SDK/source/IOUtils.cpp + XMP-Toolkit-SDK/source/IOUtils.hpp + XMP-Toolkit-SDK/source/PerfUtils.cpp + XMP-Toolkit-SDK/source/PerfUtils.hpp + XMP-Toolkit-SDK/source/SafeStringAPIs.cpp + XMP-Toolkit-SDK/source/SafeStringAPIs.h + XMP-Toolkit-SDK/source/SafeTypes.h + XMP-Toolkit-SDK/source/SuppressSAL.h + XMP-Toolkit-SDK/source/UnicodeConversions.cpp + XMP-Toolkit-SDK/source/UnicodeConversions.hpp + XMP-Toolkit-SDK/source/UnicodeInlines.incl_cpp + XMP-Toolkit-SDK/source/XIO.cpp + XMP-Toolkit-SDK/source/XIO.hpp + XMP-Toolkit-SDK/source/XML_Node.cpp + XMP-Toolkit-SDK/source/XMLParserAdapter.hpp + XMP-Toolkit-SDK/source/XMPFiles_IO.cpp + XMP-Toolkit-SDK/source/XMPFiles_IO.hpp + XMP-Toolkit-SDK/source/XMP_LibUtils.cpp + XMP-Toolkit-SDK/source/XMP_LibUtils.hpp + XMP-Toolkit-SDK/source/XMP_ProgressTracker.cpp + XMP-Toolkit-SDK/source/XMP_ProgressTracker.hpp + + XMP-Toolkit-SDK/XMPCore/source/ExpatAdapter.cpp + XMP-Toolkit-SDK/XMPCore/source/ParseRDF.cpp + XMP-Toolkit-SDK/XMPCore/source/WXMPMeta.cpp + XMP-Toolkit-SDK/XMPCore/source/WXMPUtils.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPCore_Impl.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPIterator.cpp + XMP-Toolkit-SDK/XMPCore/source/WXMPIterator.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPMeta.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPMeta-GetSet.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPMeta-Parse.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPMeta-Serialize.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPUtils.cpp + XMP-Toolkit-SDK/XMPCore/source/XMPUtils-FileInfo.cpp + + XMP-Toolkit-SDK/third-party/zuid/interfaces/MD5.cpp ) -target_include_directories(exiv2-xmp SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/xmpsdk/include ${EXPAT_INCLUDE_DIRS}) +target_compile_features(exiv2-xmp PUBLIC cxx_std_20) + +# there is an include for /third-party/expat/lib/expat.h in XMP-Toolkit-SDK +# we do these shenanigans to create a fake /third-party/expat/ in build directory +if (NOT EXISTS ${CMAKE_BINARY_DIR}/fake_expat/third-party/expat/lib) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/fake_expat/third-party/expat/lib) +endif () +file(GLOB_RECURSE EXPAT_H ${EXPAT_INCLUDE_DIRS}*/expat.h) +list(LENGTH EXPAT_H EXPAT_H_ITEM_CNT) +if(EXPAT_H_ITEM_CNT EQUAL 1) + list(GET EXPAT_H 0 EXPAT_H) + message(STATUS "The list contains one item: ${EXPAT_H}") + file(COPY_FILE ${EXPAT_H} ${CMAKE_BINARY_DIR}/fake_expat/third-party/expat/lib/expat.h) +else() + message(FATAL_ERROR "Cannot find expat.h") +endif() + +target_include_directories(exiv2-xmp PRIVATE + $ + $ + $ + $ + ${EXPAT_INCLUDE_DIRS} + ${CMAKE_BINARY_DIR}/fake_expat # this is the fake include directory needed for expat +) # Prevent a denial-service-attack related to XML entity expansion ("billion laughs attack"). See https://bugzilla.redhat.com/show_bug.cgi?id=888769 -target_compile_definitions(exiv2-xmp PRIVATE BanAllEntityUsage=1) +target_compile_definitions(exiv2-xmp PUBLIC BanAllEntityUsage=1) -if(WIN32) - target_compile_definitions(exiv2-xmp PRIVATE XML_STATIC) -endif() +# need to be careful not to expose any xmp includes in exiv2 headers +target_include_directories(exiv2-xmp PUBLIC + $ # md5.h seems to need this + $ + $ +) -if(MINGW) - # https://stackoverflow.com/questions/18551409/localtime-r-support-on-mingw - target_compile_definitions(exiv2-xmp PRIVATE _POSIX_THREAD_SAFE_FUNCTIONS) -endif() +if (WIN32) + target_sources(exiv2-xmp PRIVATE XMP-Toolkit-SDK/source/Host_IO-Win.cpp) + target_compile_definitions(exiv2-xmp PRIVATE XML_STATIC) + target_compile_definitions(exiv2-xmp PUBLIC WIN_ENV) + target_compile_definitions(exiv2-xmp PRIVATE WIN32 UNICODE _UNICODE _CRT_SECURE_NO_WARNINGS _SCL_SECURE_NO_WARNINGS) +endif () -if(BUILD_SHARED_LIBS) - set_property(TARGET exiv2-xmp PROPERTY POSITION_INDEPENDENT_CODE ON) -endif() +if (MINGW) + # https://stackoverflow.com/questions/18551409/localtime-r-support-on-mingw + target_compile_definitions(exiv2-xmp PRIVATE _POSIX_THREAD_SAFE_FUNCTIONS) +endif () + +if (APPLE) + target_sources(exiv2-xmp PRIVATE XMP-Toolkit-SDK/source/Host_IO-POSIX.cpp) + target_compile_definitions(exiv2-xmp PUBLIC MAC_ENV) +elseif (UNIX) + target_sources(exiv2-xmp PRIVATE XMP-Toolkit-SDK/source/Host_IO-POSIX.cpp) + target_compile_definitions(exiv2-xmp PUBLIC UNIX_ENV) +endif () + +if (BUILD_SHARED_LIBS) + set_property(TARGET exiv2-xmp PROPERTY POSITION_INDEPENDENT_CODE ON) +endif () diff --git a/xmpsdk/XMP-Toolkit-SDK b/xmpsdk/XMP-Toolkit-SDK new file mode 160000 index 0000000000..5f6fe44f19 --- /dev/null +++ b/xmpsdk/XMP-Toolkit-SDK @@ -0,0 +1 @@ +Subproject commit 5f6fe44f19842ae43dedc3da3fd5d5dafb29e501 From 71d57fdf65650df19367c02e60584d7a6de5ebd4 Mon Sep 17 00:00:00 2001 From: Sergey Hovakimyan Date: Wed, 10 Jul 2024 11:55:55 +0400 Subject: [PATCH 2/6] removes in source copy of XMP-Toolkit-sdk --- xmpsdk/include/MD5.h | 49 - xmpsdk/include/TXMPIterator.hpp | 235 -- xmpsdk/include/TXMPMeta.hpp | 1803 -------------- xmpsdk/include/TXMPUtils.hpp | 965 -------- xmpsdk/include/XMP.incl_cpp | 63 - xmpsdk/include/XMPSDK.hpp | 89 - xmpsdk/include/XMP_Const.h | 1311 ---------- xmpsdk/include/XMP_Environment.h | 164 -- xmpsdk/include/XMP_Version.h | 45 - .../include/client-glue/TXMPIterator.incl_cpp | 226 -- xmpsdk/include/client-glue/TXMPMeta.incl_cpp | 935 ------- xmpsdk/include/client-glue/TXMPUtils.incl_cpp | 493 ---- xmpsdk/include/client-glue/WXMPFiles.hpp | 167 -- xmpsdk/include/client-glue/WXMPIterator.hpp | 83 - xmpsdk/include/client-glue/WXMPMeta.hpp | 622 ----- xmpsdk/include/client-glue/WXMPUtils.hpp | 322 --- xmpsdk/include/client-glue/WXMP_Common.hpp | 123 - xmpsdk/src/ExpatAdapter.cpp | 507 ---- xmpsdk/src/ExpatAdapter.hpp | 50 - xmpsdk/src/MD5.cpp | 235 -- xmpsdk/src/ParseRDF.cpp | 1296 ---------- xmpsdk/src/UnicodeConversions.cpp | 1665 ------------- xmpsdk/src/UnicodeConversions.hpp | 121 - xmpsdk/src/UnicodeInlines.incl_cpp | 129 - xmpsdk/src/WXMPIterator.cpp | 188 -- xmpsdk/src/WXMPMeta.cpp | 1310 ---------- xmpsdk/src/WXMPUtils.cpp | 626 ----- xmpsdk/src/XMLParserAdapter.hpp | 140 -- xmpsdk/src/XML_Node.cpp | 463 ---- xmpsdk/src/XMPCore_Impl.cpp | 1468 ----------- xmpsdk/src/XMPCore_Impl.hpp | 534 ---- xmpsdk/src/XMPIterator.cpp | 736 ------ xmpsdk/src/XMPIterator.hpp | 148 -- xmpsdk/src/XMPMeta-GetSet.cpp | 1212 --------- xmpsdk/src/XMPMeta-Parse.cpp | 1306 ---------- xmpsdk/src/XMPMeta-Serialize.cpp | 1342 ---------- xmpsdk/src/XMPMeta.cpp | 1653 ------------- xmpsdk/src/XMPMeta.hpp | 418 ---- xmpsdk/src/XMPUtils-FileInfo.cpp | 1346 ---------- xmpsdk/src/XMPUtils.cpp | 2157 ----------------- xmpsdk/src/XMPUtils.hpp | 221 -- xmpsdk/src/XMP_BuildInfo.h | 22 - 42 files changed, 26988 deletions(-) delete mode 100644 xmpsdk/include/MD5.h delete mode 100644 xmpsdk/include/TXMPIterator.hpp delete mode 100644 xmpsdk/include/TXMPMeta.hpp delete mode 100644 xmpsdk/include/TXMPUtils.hpp delete mode 100644 xmpsdk/include/XMP.incl_cpp delete mode 100644 xmpsdk/include/XMPSDK.hpp delete mode 100644 xmpsdk/include/XMP_Const.h delete mode 100644 xmpsdk/include/XMP_Environment.h delete mode 100644 xmpsdk/include/XMP_Version.h delete mode 100644 xmpsdk/include/client-glue/TXMPIterator.incl_cpp delete mode 100644 xmpsdk/include/client-glue/TXMPMeta.incl_cpp delete mode 100644 xmpsdk/include/client-glue/TXMPUtils.incl_cpp delete mode 100644 xmpsdk/include/client-glue/WXMPFiles.hpp delete mode 100644 xmpsdk/include/client-glue/WXMPIterator.hpp delete mode 100644 xmpsdk/include/client-glue/WXMPMeta.hpp delete mode 100644 xmpsdk/include/client-glue/WXMPUtils.hpp delete mode 100644 xmpsdk/include/client-glue/WXMP_Common.hpp delete mode 100644 xmpsdk/src/ExpatAdapter.cpp delete mode 100644 xmpsdk/src/ExpatAdapter.hpp delete mode 100644 xmpsdk/src/MD5.cpp delete mode 100644 xmpsdk/src/ParseRDF.cpp delete mode 100644 xmpsdk/src/UnicodeConversions.cpp delete mode 100644 xmpsdk/src/UnicodeConversions.hpp delete mode 100644 xmpsdk/src/UnicodeInlines.incl_cpp delete mode 100644 xmpsdk/src/WXMPIterator.cpp delete mode 100644 xmpsdk/src/WXMPMeta.cpp delete mode 100644 xmpsdk/src/WXMPUtils.cpp delete mode 100644 xmpsdk/src/XMLParserAdapter.hpp delete mode 100644 xmpsdk/src/XML_Node.cpp delete mode 100644 xmpsdk/src/XMPCore_Impl.cpp delete mode 100644 xmpsdk/src/XMPCore_Impl.hpp delete mode 100644 xmpsdk/src/XMPIterator.cpp delete mode 100644 xmpsdk/src/XMPIterator.hpp delete mode 100644 xmpsdk/src/XMPMeta-GetSet.cpp delete mode 100644 xmpsdk/src/XMPMeta-Parse.cpp delete mode 100644 xmpsdk/src/XMPMeta-Serialize.cpp delete mode 100644 xmpsdk/src/XMPMeta.cpp delete mode 100644 xmpsdk/src/XMPMeta.hpp delete mode 100644 xmpsdk/src/XMPUtils-FileInfo.cpp delete mode 100644 xmpsdk/src/XMPUtils.cpp delete mode 100644 xmpsdk/src/XMPUtils.hpp delete mode 100644 xmpsdk/src/XMP_BuildInfo.h diff --git a/xmpsdk/include/MD5.h b/xmpsdk/include/MD5.h deleted file mode 100644 index 5556049b2f..0000000000 --- a/xmpsdk/include/MD5.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __MD5_h__ -#define __MD5_h__ - -/* - * This is the header file for the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5_CTX structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' - * header definitions; now uses stuff from dpkg's config.h - * - Ian Jackson . - * Still in the public domain. - */ - -#include - -#include - -/* MSVC doesn't provide C99 types, but it has MS specific variants */ -#ifdef _MSC_VER -typedef unsigned __int32 uint32_t; -#endif - -typedef unsigned char md5byte; -typedef uint32_t UWORD32; - -struct MD5_CTX { - UWORD32 buf[4]; - UWORD32 bytes[2]; - UWORD32 in[16]; -}; - -extern void MD5Init(struct MD5_CTX *context); -extern void MD5Update(struct MD5_CTX *context, md5byte const *buf, unsigned len); -extern void MD5Final(unsigned char digest[16], struct MD5_CTX *context); -extern void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]); - -#endif diff --git a/xmpsdk/include/TXMPIterator.hpp b/xmpsdk/include/TXMPIterator.hpp deleted file mode 100644 index 33c73a1fbb..0000000000 --- a/xmpsdk/include/TXMPIterator.hpp +++ /dev/null @@ -1,235 +0,0 @@ -#ifndef __TXMPIterator_hpp__ -#define __TXMPIterator_hpp__ 1 - -#if ( ! __XMP_hpp__ ) - #error "Do not directly include, use XMPSDK.hpp" -#endif - -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2007 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. -// ================================================================================================= - -// ================================================================================================= -/// \file TXMPIterator.hpp -/// \brief API for access to the XMP Toolkit iteration services. -/// -/// \c TXMPIterator is the template class providing iteration services for the XMP Toolkit. It must -/// be instantiated with a string class such as \c std::string. See the instructions in XMPSDK.hpp, and -/// the Overview for a discussion of the overall architecture of the XMP API. -// ================================================================================================= - -// ================================================================================================= -/// \class TXMPIterator TXMPIterator.hpp -/// @brief API for access to the XMP Toolkit iteration services. -/// -/// \c TXMPIterator provides a uniform means to iterate over the schema and properties within an XMP -/// object. \c TXMPIterator is a template class which must be instantiated with a string class such -/// as \c std::string. See the instructions in XMPSDK.hpp, and the Overview for a discussion of the -/// overall architecture of the XMP API. Access these functions through the concrete class, -/// \c SXMPIterator. -/// -/// @note Only XMP object iteration is currently available. Future development may include iteration -/// over global tables, such as registered namespaces. -/// -/// To understand how iteration works, you should have a thorough understanding of the XMP data -/// tree, as described in the XMP Specification Part 1. You might also find it helpful to create -/// some complex XMP and examine the output of \c TXMPMeta::DumpObject(). -/// -/// \li The top of the XMP data tree is a single root node. This does not explicitly appear in the -/// dump and is never visited by an iterator; that is, it is never returned from -/// \c TXMPIterator::Next(). -/// -/// \li Beneath the root are schema nodes; these collect the top-level properties in the same -/// namespace. They are created and destroyed implicitly. -/// -/// \li Beneath the schema nodes are the property nodes. The nodes below a property node depend on -/// its type (simple, struct, or array) and whether it has qualifiers. -/// -/// A \c TXMPIterator constructor defines a starting point for the iteration, and options that -/// control how it proceeds. By default, iteration starts at the root and visits all nodes beneath -/// it in a depth-first manner. The root node iteself is not visited; the first visited node is a -/// schema node. You can provide a schema name or property path to select a different starting node. -/// By default, this visits the named root node first then all nodes beneath it in a depth-first -/// manner. -/// -/// The function \c TXMPIterator::Next() delivers the schema URI, path, and option flags for the -/// node being visited. If the node is simple, it also delivers the value. Qualifiers for this node -/// are visited next. The fields of a struct or items of an array are visited after the qualifiers -/// of the parent. -/// -/// You can specify options when constructing the iteration object to control how the iteration is -/// performed. -/// -/// \li \c #kXMP_IterJustChildren - Visit just the immediate children of the root. Skip the root -/// itself and all nodes below the immediate children. This omits the qualifiers of the immediate -/// children, the qualifier nodes being below what they qualify. -/// \li \c #kXMP_IterJustLeafNodes - Visit just the leaf property nodes and their qualifiers. -/// \li \c #kXMP_IterJustLeafName - Return just the leaf component of the node names. The default -/// is to return the full path name. -/// \li \c #kXMP_IterIncludeAliases - Include aliases as part of the iteration. Since aliases are -/// not actual nodes the default iteration does not visit them. -/// \li \c #kXMP_IterOmitQualifiers - Do not visit the qualifiers of a node. -// ================================================================================================= - -#include "client-glue/WXMPIterator.hpp" - -template class TXMPIterator { - -public: - - // --------------------------------------------------------------------------------------------- - /// @brief Assignment operator, assigns the internal ref and increments the ref count. - /// - /// Assigns the internal reference from an existing object and increments the reference count on - /// the underlying internal XMP iterator. - /// - /// @param rhs An existing iteration object. - - void operator= ( const TXMPIterator & rhs ); - - // --------------------------------------------------------------------------------------------- - /// @brief Copy constructor, creates a client object refering to the same internal object. - /// - /// Creates a new client iterator that refers to the same underlying iterator as an existing object. - /// - /// @param original An existing iteration object to copy. - - TXMPIterator ( const TXMPIterator & original ); - - // --------------------------------------------------------------------------------------------- - /// @brief Constructs an iterator for properties within a schema in an XMP object. - /// - /// See the class description for the general operation of an XMP object iterator. - /// Overloaded forms are provided to iterate the entire data tree, - /// a subtree rooted at a specific node, or properties within a specific schema. - /// - /// @param xmpObj The XMP object over which to iterate. - /// - /// @param schemaNS Optional schema namespace URI to restrict the iteration. To visit all of the - /// schema, pass 0 or the empty string "". - /// - /// @param propName Optional property name to restrict the iteration. May be an arbitrary path - /// expression. If provided, a schema URI must also be provided. To visit all properties, pass 0 - /// or the empty string "". - /// - /// @param options Option flags to control the iteration. A logical OR of these bit flag constants: - /// \li \c #kXMP_IterJustChildren - Visit only the immediate children of the root; default visits subtrees. - /// \li \c #kXMP_IterJustLeafNodes - Visit only the leaf nodes; default visits all nodes. - /// \li \c #kXMP_IterJustLeafName - Return just the leaf part of the path; default returns the full path. - /// \li \c #kXMP_IterOmitQualifiers - Omit all qualifiers. - /// - /// @return The new TXMPIterator object. - - TXMPIterator ( const TXMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief Constructs an iterator for a subtree of properties within an XMP object. - /// - /// See the class description for the general operation of an XMP object iterator. Overloaded - /// forms are provided to iterate the entire data tree, a subtree rooted at a specific node, or - /// properties within a specific schema. - /// - /// @param xmpObj The XMP object over which to iterate. - /// - /// @param schemaNS Optional schema namespace URI to restrict the iteration. To visit all of the - /// schema, pass 0 or the empty string "". - /// - /// @param options Option flags to control the iteration. A logical OR of these bit flag constants: - /// \li \c #kXMP_IterJustChildren - Visit only the immediate children of the root; default visits subtrees. - /// \li \c #kXMP_IterJustLeafNodes - Visit only the leaf nodes; default visits all nodes. - /// \li \c #kXMP_IterJustLeafName - Return just the leaf part of the path; default returns the full path. - /// \li \c #kXMP_IterOmitQualifiers - Omit all qualifiers. - /// - /// @return The new TXMPIterator object. - - TXMPIterator ( const TXMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief Constructs an iterator for the entire data tree within an XMP object. - /// - /// See the class description for the general operation of an XMP object iterator. Overloaded - /// forms are provided to iterate the entire data tree, a subtree rooted at a specific node, or - /// properties within a specific schema. - /// - /// @param xmpObj The XMP object over which to iterate. - /// - /// @param options Option flags to control the iteration. A logical OR of these bit flag constants: - /// \li \c #kXMP_IterJustChildren - Visit only the immediate children of the root; default visits subtrees. - /// \li \c #kXMP_IterJustLeafNodes - Visit only the leaf nodes; default visits all nodes. - /// \li \c #kXMP_IterJustLeafName - Return just the leaf part of the path; default returns the full path. - /// \li \c #kXMP_IterOmitQualifiers - Omit all qualifiers. - /// - /// @return The new \c TXMPIterator object. - - TXMPIterator ( const TXMPMeta & xmpObj, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief Constructs an iterator for the global tables of the XMP toolkit. Not implemented. - - TXMPIterator ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - /// @brief Destructor, typical virtual destructor. - - virtual ~TXMPIterator() throw(); - - // --------------------------------------------------------------------------------------------- - /// @brief \c Next() visits the next node in the iteration. - /// - /// Proceeds to the next node according to the options specified on creation of this object, and - /// delivers the schema URI, path, and option flags for the node being visited. If the node is - /// simple, it also delivers the value. - /// - /// @param schemaNS [out] A string object in which to return the assigned the schema namespace - /// URI of the current property. Can be null if the value is not wanted. - /// - /// @param propPath [out] A string object in which to return the XPath name of the current - /// property. Can be null if the value is not wanted. - /// - /// @param propValue [out] A string object in which to return the value of the current - /// property. Can be null if the value is not wanted. - /// - /// @param options [out] A buffer in which to return the flags describing the current property, - /// which are a logical OR of \c #XMP_OptionBits bit-flag constants. - /// - /// @return True if there was another node to visit, false if the iteration is complete. - - bool Next ( tStringObj * schemaNS = 0, - tStringObj * propPath = 0, - tStringObj * propValue = 0, - XMP_OptionBits * options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c Skip() skips some portion of the remaining iterations. - /// - /// @param options Option flags to control the iteration, a logical OR of these bit-flag - /// constants: - /// \li \c #kXMP_IterSkipSubtree - Skip the subtree below the current node. - /// \li \c #kXMP_IterSkipSiblings - Skip the subtree below and remaining siblings of the current node. - - void Skip ( XMP_OptionBits options ); - -private: - - XMPIteratorRef iterRef; - - TXMPIterator(); // ! Hidden, must choose property or table iteration. - -}; // class TXMPIterator - -// ================================================================================================= - -#endif // __TXMPIterator_hpp__ diff --git a/xmpsdk/include/TXMPMeta.hpp b/xmpsdk/include/TXMPMeta.hpp deleted file mode 100644 index 0bf04e15ac..0000000000 --- a/xmpsdk/include/TXMPMeta.hpp +++ /dev/null @@ -1,1803 +0,0 @@ -#ifndef __TXMPMeta_hpp__ -#define __TXMPMeta_hpp__ 1 - -#if ( ! __XMP_hpp__ ) - #error "Do not directly include, use XMPSDK.hpp" -#endif - -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2008 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. -// ================================================================================================= - -// ================================================================================================= -/// \file TXMPMeta.hpp -/// \brief API for access to the XMP Toolkit core services. -/// -/// \c TXMPMeta is the template class providing the core services of the XMP Toolkit. It must be -/// instantiated with a string class such as \c std::string. Read the Toolkit Overview for -/// information about the overall architecture of the XMP API, and the documentation for \c XMPSDK.hpp -/// for specific instantiation instructions. -/// -/// Access these functions through the concrete class, \c SXMPMeta. -// ================================================================================================= - -// ================================================================================================= -/// \class TXMPMeta TXMPMeta.hpp -/// \brief API for access to the XMP Toolkit core services. -/// -/// \c TXMPMeta is the template class providing the core services of the XMP Toolkit. It should be -/// instantiated with a string class such as \c std::string. Read the Toolkit Overview for -/// information about the overall architecture of the XMP API, and the documentation for \c XMPSDK.hpp -/// for specific instantiation instructions. -/// -/// Access these functions through the concrete class, \c SXMPMeta. -/// -/// You can create \c TXMPMeta objects (also called XMP objects) from metadata that you construct, -/// or that you obtain from files using the XMP Toolkit's XMPFiles component; see \c TXMPFiles.hpp. -// ================================================================================================= - -template class TXMPIterator; -template class TXMPUtils; - -// ------------------------------------------------------------------------------------------------- - -template class TXMPMeta { - -public: - - // ============================================================================================= - // Initialization and termination - // ============================== - - // --------------------------------------------------------------------------------------------- - /// \name Initialization and termination - /// - /// @{ - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetVersionInfo() retrieves runtime version information. - /// - /// The header \c XMPVersion.hpp defines a static version number for the XMP Toolkit, which - /// describes the version of the API used at client compile time. It is not necessarily the same - /// as the runtime version. Do not base runtime decisions on the static version alone; you can, - /// however, compare the runtime and static versions. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). The - /// function can be called before calling \c TXMPMeta::Initialize(). - /// - /// @param info [out] A buffer in which to return the version information. - - static void GetVersionInfo ( XMP_VersionInfo * info ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c Initialize() explicitly initializes the XMP Toolkit before use. */ - - /// Initializes the XMP Toolkit. - /// - /// Call this function before making any other calls to the \c TXMPMeta functions, except - /// \c TXMPMeta::GetVersionInfo(). - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @return True on success. */ - static bool Initialize(); - // --------------------------------------------------------------------------------------------- - /// @brief \c Terminate() explicitly terminates usage of the XMP Toolkit. - /// - /// Frees structures created on initialization. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - - static void Terminate(); - - /// @} - - // ============================================================================================= - // Constuctors and destructor - // ========================= - - // --------------------------------------------------------------------------------------------- - /// \name Constructors and destructor - /// @{ - - // --------------------------------------------------------------------------------------------- - /// @brief Default constructor, creates an empty object. - /// - /// The default constructor creates a new empty \c TXMPMeta object. - /// - /// @return The new object. */ - TXMPMeta(); - - // --------------------------------------------------------------------------------------------- - /// @brief Copy constructor, creates a client object refering to the same internal object. - /// - /// The copy constructor creates a new \c TXMPMeta object that refers to the same internal XMP - /// object. as an existing \c TXMPMeta object. - /// - /// @param original The object to copy. - /// - /// @return The new object. */ - - TXMPMeta ( const TXMPMeta & original ); - - // --------------------------------------------------------------------------------------------- - /// @brief Assignment operator, assigns the internal reference and increments the reference count. - /// - /// The assignment operator assigns the internal ref from the rhs object and increments the - /// reference count on the underlying internal XMP object. - - void operator= ( const TXMPMeta & rhs ); - - // --------------------------------------------------------------------------------------------- - /// @brief Reconstructs an XMP object from an internal reference. - /// - /// This constructor creates a new \c TXMPMeta object that refers to the underlying reference object - /// of an existing \c TXMPMeta object. Use to safely pass XMP objects across DLL boundaries. - /// - /// @param xmpRef The underlying reference object, obtained from some other XMP object with - /// \c TXMPMeta::GetInternalRef(). - /// - /// @return The new object. - - TXMPMeta ( XMPMetaRef xmpRef ); - - // --------------------------------------------------------------------------------------------- - /// @brief Constructs an object and parse one buffer of RDF into it. - /// - /// This constructor creates a new \c TXMPMeta object and populates it with metadata from a - /// buffer containing serialized RDF. This buffer must be a complete RDF parse stream. - /// - /// The result of passing serialized data to this function is identical to creating an empty - /// object then calling \c TXMPMeta::ParseFromBuffer(). To use the constructor, however, the RDF - /// must be complete. If you need to parse data from multiple buffers, create an empty object - /// and use \c TXMPMeta::ParseFromBuffer(). - /// - /// @param buffer A pointer to the buffer of RDF to be parsed. Can be null if the length is 0; - /// in this case, the function creates an empty object. - /// - /// @param xmpSize The length in bytes of the buffer. - /// - /// @return The new object. - - TXMPMeta ( XMP_StringPtr buffer, - XMP_StringLen xmpSize ); - - // --------------------------------------------------------------------------------------------- - /// @brief Destructor, typical virtual destructor. */ - virtual ~TXMPMeta() throw(); - - /// @} - - // ============================================================================================= - // Global state functions - // ====================== - - // --------------------------------------------------------------------------------------------- - /// \name Global option flags - /// @{ - /// Global option flags affect the overall behavior of the XMP Toolkit. The available options - /// will be declared in \c XMP_Const.h. There are none in this version of the Toolkit. - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetGlobalOptions() retrieves the set of global option flags. There are none in - /// this version of the Toolkit. - /// - /// This function is static; you can make the call from the class without instantiating it. - /// - /// @return A logical OR of global option bit-flag constants. - - static XMP_OptionBits GetGlobalOptions(); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetGlobalOptions() updates the set of global option flags. There are none in this - /// version of the Toolkit. - /// - /// The entire set is replaced with the new values. If only one flag is to be modified, use - /// \c TXMPMeta::GetGlobalOptions() to obtain the current set, modify the desired flag, then use - /// this function to reset the value. - /// - /// This function is static; you can make the call from the class without instantiating it. - /// - /// @param options A logical OR of global option bit-flag constants. - - static void SetGlobalOptions ( XMP_OptionBits options ); - - /// @} - - // --------------------------------------------------------------------------------------------- - /// \name Internal data structure dump utilities - /// @{ - /// - /// These are debugging utilities that dump internal data structures, to be handled by - /// client-defined callback described in \c XMP_Const.h. - /// - /// @see Member function \c TXMPMeta::DumpObject() - - // --------------------------------------------------------------------------------------------- - /// @brief \c DumpNamespaces() sends the list of registered namespace URIs and prefixes to a handler. - /// - /// For debugging. Invokes a client-defined callback for each line of output. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param outProc The client-defined procedure to handle each line of output. - /// - /// @param clientData A pointer to client-defined data to pass to the handler. - /// - /// @return A success-fail status value, returned from the handler. Zero is success, failure - /// values are client-defined. - - static XMP_Status DumpNamespaces ( XMP_TextOutputProc outProc, - void * clientData ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DumpAliases() sends the list of registered aliases and corresponding actuals to a handler. - /// - /// For debugging. Invokes a client-defined callback for each line of output. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param outProc The client-defined procedure to handle each line of output. - /// - /// @param clientData A pointer to client-defined data to pass to the handler. - /// - /// @return A success-fail status value, returned from the handler. Zero is success, failure - /// values are client-defined. - - static XMP_Status DumpAliases ( XMP_TextOutputProc outProc, - void * clientData ); - - /// @} - - // --------------------------------------------------------------------------------------------- - /// \name Namespace Functions - /// @{ - /// - /// Namespaces must be registered before use in namespace URI parameters or path expressions. - /// Within the XMP Toolkit the registered namespace URIs and prefixes must be unique. Additional - /// namespaces encountered when parsing RDF are automatically registered. - /// - /// The namespace URI should always end in an XML name separator such as '/' or '#'. This is - /// because some forms of RDF shorthand catenate a namespace URI with an element name to form a - /// new URI. - - // --------------------------------------------------------------------------------------------- - /// @brief \c RegisterNamespace() registers a namespace URI with a prefix. - /// - /// If the the prefix is in use, the URI of the existing prefix is overwritten. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param namespaceURI The URI for the namespace. Must be a valid XML URI. - /// - /// @param prefix The prefix to be used. Must be a valid XML name. - /// - /// @note No checking is done on either the URI or the prefix. */ - - static void RegisterNamespace ( XMP_StringPtr namespaceURI, - XMP_StringPtr prefix ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetNamespacePrefix() obtains the prefix for a registered namespace URI, and - /// reports whether the URI is registered. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param namespaceURI The URI for the namespace. Must not be null or the empty string. It is - /// not an error if the namespace URI is not registered. - /// - /// @param namespacePrefix [out] A string object in which to return the prefix registered for - /// this URI, with a terminating colon character, ':'. If the namespace is not registered, this - /// string is not modified. - /// - /// @return True if the namespace URI is registered. - - static bool GetNamespacePrefix ( XMP_StringPtr namespaceURI, - tStringObj * namespacePrefix ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetNamespaceURI() obtains the URI for a registered namespace prefix, and reports - /// whether the prefix is registered. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param namespacePrefix The prefix for the namespace. Must not be null or the empty string. - /// It is not an error if the namespace prefix is not registered. - /// - /// @param namespaceURI [out] A string object in which to return the URI registered for this - /// prefix. If the prefix is not registered, this string is not modified. - /// - /// @return True if the namespace prefix is registered. - - static bool GetNamespaceURI ( XMP_StringPtr namespacePrefix, - tStringObj * namespaceURI ); - - // --------------------------------------------------------------------------------------------- - /// @brief Not implemented. - /// - /// Deletes a namespace from the registry. Does nothing if the URI is not registered, or if the - /// parameter is null or the empty string. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param namespaceURI The URI for the namespace. - - static void DeleteNamespace ( XMP_StringPtr namespaceURI ); - - /// @} - - // --------------------------------------------------------------------------------------------- - /// \name Alias functions - /// @{ - /// - /// Aliases in XMP serve the same purpose as Windows file shortcuts, Mac OS file aliases, or - /// UNIX file symbolic links. The aliases are multiple names for the same property. One - /// distinction of XMP aliases is that they are ordered. An alias name points to an actual name; - /// the primary significance of the actual name is that it is the preferred name for output, - /// generally the most widely recognized name. - /// - /// XMP restricts the names that can be aliased. The alias must be a top-level property name, - /// not a field within a structure or an element within an array. The actual can be a top-level - /// property name, the first element within a top-level array, or the default element in an - /// alt-text array. This does not mean the alias can only be a simple property; you can alias a - /// top-level structure or array to an identical top-level structure or array, or to the first - /// item of an array of structures. - - // --------------------------------------------------------------------------------------------- - /// @brief \c RegisterAlias() associates an alias name with an actual name. - /// - /// Defines an alias mapping from one namespace/property to another. Both property names must be - /// simple names. An alias can be a direct mapping, where the alias and actual have the same - /// data type. It is also possible to map a simple alias to an item in an array. This can either - /// be to the first item in the array, or to the 'x-default' item in an alt-text array. Multiple - /// alias names can map to the same actual, as long as the forms match. It is a no-op to - /// reregister an alias in an identical fashion. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param aliasNS The namespace URI for the alias. Must not be null or the empty string. - /// - /// @param aliasProp The name of the alias. Must be a simple name, not null or the empty string - /// and not a general path expression. - /// - /// @param actualNS The namespace URI for the actual. Must not be null or the empty string. - /// - /// @param actualProp The name of the actual. Must be a simple name, not null or the empty string - /// and not a general path expression. - /// - /// @param arrayForm Provides the array form for simple aliases to an array item. This is needed - /// to know what kind of array to create if set for the first time via the simple alias. Pass - /// \c #kXMP_NoOptions, the default value, for all direct aliases regardless of whether the actual - /// data type is an array or not. One of these constants: - /// - /// \li \c #kXMP_NoOptions - This is a direct mapping. The actual data type does not matter. - /// \li \c #kXMP_PropValueIsArray - The actual is an unordered array, the alias is to the - /// first element of the array. - /// \li \c #kXMP_PropArrayIsOrdered - The actual is an ordered array, the alias is to the - /// first element of the array. - /// \li \c #kXMP_PropArrayIsAlternate - The actual is an alternate array, the alias is to the - /// first element of the array. - /// \li \c #kXMP_PropArrayIsAltText - The actual is an alternate text array, the alias is to - /// the 'x-default' element of the array. */ - - static void RegisterAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr actualNS, - XMP_StringPtr actualProp, - XMP_OptionBits arrayForm = kXMP_NoOptions ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ResolveAlias() reports whether a name is an alias, and what it is aliased to. - /// - /// Output strings are not written until return, so you can use this to - /// "reduce" a path to the base form as follows: - ///
-    ///   isAlias = SXMPMeta::ResolveAlias ( ns.c_str(), path.c_str(), &ns, &path, 0 );
-    /// 
- /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param aliasNS The namespace URI for the alias. Must not be null or the empty string. - /// - /// @param aliasProp The name of the alias. Can be an arbitrary path expression path, must not - /// null or the empty string. - /// - /// @param actualNS [out] A string object in which to return the namespace URI for the actual. - /// Not modified if the given name is not an alias. Can be null if the namespace URI is not wanted. - /// - /// @param actualProp [out] A string object in which to return the path of the actual. - /// Not modified if the given name is not an alias. Can be null if the actual's path is not wanted. - /// - /// @param arrayForm [out] A string object in which to return the array form of the actual. This - /// is 0 (\c #kXMP_NoOptions) if the alias and actual forms match, otherwise it is the options - /// passed to \c TXMPMeta::RegisterAlias(). Not modified if the given name is not an alias. Can - /// be null if the actual's array form is not wanted. - /// - /// @return True if the provided name is an alias. - - static bool ResolveAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - tStringObj * actualNS, - tStringObj * actualProp, - XMP_OptionBits * arrayForm ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DeleteAlias() deletes an alias. - /// - /// This deletes only the registration of the alias, it does not delete the actual property. - /// It deletes any view of the property through the alias name. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param aliasNS The namespace URI for the alias. Must not be null or the empty string. - /// - /// @param aliasProp The name of the alias. Must be a simple name, not null or the empty string - /// and not a general path expression. It is not an error to provide - /// a name that has not been registered as an alias. - - static void DeleteAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c RegisterStandardAliases() registers all of the built-in aliases for a standard namespace. - /// - /// The built-in aliases are documented in the XMP Specification. This function registers the - /// aliases in the given namespace; that is, it creates the aliases from this namespace to - /// actuals in other namespaces. - /// - /// This function is static; make the call directly from the concrete class (\c SXMPMeta). - /// - /// @param schemaNS The namespace URI for the aliases. Must not be null or the empty string. - - static void RegisterStandardAliases ( XMP_StringPtr schemaNS ); - - /// @} - - // ============================================================================================= - // Basic property manipulation functions - // ===================================== - - // *** Should add discussion of schemaNS and propName prefix usage. - - // --------------------------------------------------------------------------------------------- - /// \name Accessing property values - /// @{ - /// - /// The property value accessors all take a property specification; the top level namespace URI - /// (the "schema" namespace) and the basic name of the property being referenced. See the - /// introductory discussion of path expression usage for more information. - /// - /// The accessor functions return true if the specified property exists. If it does, output - /// parameters return the value (if any) and option flags describing the property. The option - /// bit-flag constants that describe properties are \c kXMP_PropXx and - /// \c kXMP_ArrayIsXx. See \c #kXMP_PropValueIsURI and following, and macros \c #XMP_PropIsSimple - /// and following in \c XMP_Const.h. If the property exists and has a value, it is returned as a - /// Unicode string in UTF-8 encoding. Arrays and the non-leaf levels of structs do not have - /// values. - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetProperty() reports whether a property exists, and retrieves its value. - /// - /// This is the simplest property accessor. Use this to retrieve the values of top-level simple - /// properties, or after using the path composition functions in \c TXMPUtils. - /// - /// When specifying a namespace and path (in this and all other accessors): - /// \li If a namespace URI is specified, it must be for a registered namespace. - /// \li If the namespace is specified only by a prefix in the property name path, - /// it must be a registered prefix. - /// \li If both a URI and path prefix are present, they must be corresponding - /// parts of a registered namespace. - /// - /// @param schemaNS The namespace URI for the property. The URI must be for a registered - /// namespace. Can be null or the empty string if the first component of the \c propName path - /// contains a namespace prefix. - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string. The first component can be a namespace prefix; if present without a - /// \c schemaNS value, the prefix specifies the namespace. The prefix must be for a registered - /// namespace, and if a namespace URI is specified, must match the registered prefix for that - /// namespace. - /// - /// @param propValue [out] A string object in which to return the value of the property, if the - /// property exists and has a value. Arrays and non-leaf levels of structs do not have values. - /// Can be null if the value is not wanted. - /// - /// @param options A buffer in which to return option flags describing the property. Can be null - /// if the flags are not wanted. - /// - /// @return True if the property exists. - - bool GetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - tStringObj * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetArrayItem() provides access to items within an array. - /// - /// Reports whether the item exists; if it does, and if it has a value, the function retrieves - /// the value. Items are accessed by an integer index, where the first item has index 1. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem - /// to specify the last existing array item. - /// - /// @param itemValue [out] A string object in which to return the value of the array item, if it - /// has a value. Arrays and non-leaf levels of structs do not have values. Can be null if the - /// value is not wanted. - /// - /// @param options [out] A buffer in which to return the option flags describing the array item. - /// Can be null if the flags are not wanted. - /// - /// @return True if the array item exists. - - bool GetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - tStringObj * itemValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetStructField() provides access to fields within a nested structure. - /// - /// Reports whether the field exists; if it does, and if it has a value, the function retrieves - /// the value. - /// - /// @param schemaNS The namespace URI for the struct; see \c GetProperty(). - /// - /// @param structName The name of the struct. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field. Same URI and prefix usage as the \c schemaNS - /// and \c structName parameters. - /// - /// @param fieldName The name of the field. Must be a single XML name, must not be null or the - /// empty string. Same URI and prefix usage as the \c schemaNS and \c structName parameters. - /// - /// @param fieldValue [out] A string object in which to return the value of the field, if the - /// field has a value. Arrays and non-leaf levels of structs do not have values. Can be null if - /// the value is not wanted. - /// - /// @param options [out] A buffer in which to return the option flags describing the field. Can - /// be null if the flags are not wanted. - /// - /// @return True if the field exists. - - bool GetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - tStringObj * fieldValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetQualifier() provides access to a qualifier attached to a property. - /// - /// @note In this version of the Toolkit, qualifiers are supported only for simple leaf properties. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property to which the qualifier is attached. Can be a - /// general path expression, must not be null or the empty string; see \c GetProperty() for - /// namespace prefix usage. - /// - /// @param qualNS The namespace URI for the qualifier. Same URI and prefix usage as the - /// \c schemaNS and \c propName parameters. - /// - /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or - /// the empty string. Same URI and prefix usage as the \c schemaNS and \c propName parameters. - /// - /// @param qualValue [out] A string object in which to return the value of the qualifier, if the - /// qualifier has a value. Arrays and non-leaf levels of structs do not have values. Can be null - /// if the value is not wanted. - /// - /// @param options [out] A buffer in which to return the option flags describing the qualifier. - /// Can be null if the flags are not wanted. - /// - /// @return True if the qualifier exists. - - bool GetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - tStringObj * qualValue, - XMP_OptionBits * options ) const; - - /// @} - - // ============================================================================================= - - // --------------------------------------------------------------------------------------------- - /// \name Creating properties and setting their values - /// @{ - /// - /// These functions all take a property specification; the top level namespace URI (the "schema" - /// namespace) and the basic name of the property being referenced. See the introductory - /// discussion of path expression usage for more information. - /// - /// All of the functions take a UTF-8 encoded Unicode string for the property value. Arrays and - /// non-leaf levels of structs do not have values. The value can be passed as an - /// \c #XMP_StringPtr (a pointer to a null-terminated string), or as a string object - /// (\c tStringObj). - - /// Each function takes an options flag that describes the property. You can use these functions - /// to create empty arrays and structs by setting appropriate option flags. When you assign a - /// value, all levels of a struct that are implicit in the assignment are created if necessary. - /// \c TXMPMeta::AppendArrayItem() implicitly creates the named array if necessary. - /// - /// The allowed option bit-flags include: - /// \li \c #kXMP_PropValueIsStruct - Can be used to create an empty struct. - /// A struct is implicitly created when the first field is set. - /// \li \c #kXMP_PropValueIsArray - By default, a general unordered array (bag). - /// \li \c #kXMP_PropArrayIsOrdered - An ordered array. - /// \li \c #kXMP_PropArrayIsAlternate - An alternative array. - /// \li \c #kXMP_PropArrayIsAltText - An alt-text array. Each array element must - /// be a simple property with an \c xml:lang attribute. - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty() creates or sets a property value. - /// - /// This is the simplest property setter. Use it for top-level simple properties, or after using - /// the path composition functions in \c TXMPUtils. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue The new value, a pointer to a null terminated UTF-8 string. Must be null - /// for arrays and non-leaf levels of structs that do not have values. - /// - /// @param options Option flags describing the property; a logical OR of allowed bit-flag - /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property - /// that already exists. - - void SetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr propValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty() creates or sets a property value using a string object. - /// - /// Overloads the basic form of the function, allowing you to pass a string object - /// for the item value. It is otherwise identical; see details in the canonical form. - - void SetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const tStringObj & propValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetArrayItem() creates or sets the value of an item within an array. - /// - /// Items are accessed by an integer index, where the first item has index 1. This function - /// creates the item if necessary, but the array itself must already exist Use - /// \c AppendArrayItem() to create arrays. A new item is automatically appended if the index is the - /// array size plus 1. To insert a new item before or after an existing item, use option flags. - /// - /// Use \c TXMPUtils::ComposeArrayItemPath() to create a complex path. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem - /// to specify the last existing array item. - /// - /// @param itemValue The new item value, a null-terminated UTF-8 string, if the array item has a - /// value. - /// - /// @param options Option flags describing the array type and insertion location for a new item; - /// a logical OR of allowed bit-flag constants. The type, if specified, must match the existing - /// array type, \c #kXMP_PropArrayIsOrdered, \c #kXMP_PropArrayIsAlternate, or - /// \c #kXMP_PropArrayIsAltText. Default (0 or \c #kXMP_NoOptions) matches the existing array type. - /// - /// To insert a new item before or after the specified index, set flag \c #kXMP_InsertBeforeItem - /// or \c #kXMP_InsertAfterItem. - - void SetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr itemValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetArrayItem() creates or sets the value of an item within an array using a string object. - /// - /// Overloads the basic form of the function, allowing you to pass a string object in which to - /// return the item value. It is otherwise identical; see details in the canonical form. - - void SetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - const tStringObj & itemValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c AppendArrayItem() adds an item to an array, creating the array if necessary. - /// - /// This function simplifies construction of an array by not requiring that you pre-create an - /// empty array. The array that is assigned is created automatically if it does not yet exist. - /// If the array exists, it must have the form specified by the options. Each call appends a new - /// item to the array. - /// - /// Use \c TXMPUtils::ComposeArrayItemPath() to create a complex path. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param arrayOptions Option flags describing the array type to create; a logical OR of - /// allowed bit-flag constants, \c #kXMP_PropArrayIsOrdered, \c #kXMP_PropArrayIsAlternate, or - /// \c #kXMP_PropArrayIsAltText. If the array exists, must match the existing array type or be - /// null (0 or \c #kXMP_NoOptions). - /// - /// @param itemValue The new item value, a null-terminated UTF-8 string, if the array item has a - /// value. - /// - /// @param itemOptions Option flags describing the item type to create; one of the bit-flag - /// constants \c #kXMP_PropValueIsArray or \c #kXMP_PropValueIsStruct to create a complex array - /// item. - - void AppendArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - XMP_StringPtr itemValue, - XMP_OptionBits itemOptions = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c AppendArrayItem() adds an item to an array using a string object value, creating - /// the array if necessary. - /// - /// Overloads the basic form of the function, allowing you to pass a string object in which to - /// return the item value. It is otherwise identical; see details in the canonical form. - - void AppendArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - const tStringObj & itemValue, - XMP_OptionBits itemOptions = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetStructField() creates or sets the value of a field within a nested structure. - /// - /// Use this to set a value within an existing structure, create a new field within an existing - /// structure, or create an empty structure of any depth. If you set a field in a structure that - /// does not exist, the structure is automatically created. - /// - /// Use \c TXMPUtils::ComposeStructFieldPath() to create a complex path. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param structName The name of the struct. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field. Same namespace and prefix usage as - /// \c GetProperty(). - /// - /// @param fieldName The name of the field. Must be a single XML name, must not be null or the - /// empty string. Same namespace and prefix usage as \c GetProperty(). - /// - /// @param fieldValue The new value, a null-terminated UTF-8 string, if the field has a value. - /// Null to create a new, empty struct or empty field in an existing struct. - /// - /// @param options Option flags describing the property, in which the bit-flag - /// \c #kXMP_PropValueIsStruct must be set to create a struct. - - void SetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetStructField() creates or sets the value of a field within a nested structure, - /// using a string object. - /// - /// Overloads the basic form of the function, allowing you to pass a string object in which to - /// return the field value. It is otherwise identical; see details in the canonical form. - - void SetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - const tStringObj & fieldValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetQualifier() creates or sets a qualifier attached to a property. - /// - /// Use this to set a value for an existing qualifier, or create a new qualifier. <> Use - /// \c TXMPUtils::ComposeQualifierPath() to create a complex path. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property to which the qualifier is attached. Can be a - /// general path expression, must not be null or the empty string; see \c GetProperty() for - /// namespace prefix usage. - /// - /// @param qualNS The namespace URI for the qualifier. Same namespace and prefix usage as - /// \c GetProperty(). - /// - /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or - /// the empty string. Same namespace and prefix usage as \c GetProperty(). - /// - /// @param qualValue The new value, a null-terminated UTF-8 string, if the qualifier has a - /// value. Null to create a new, empty qualifier. - /// - /// @param options Option flags describing the <>, a logical OR - /// of property-type bit-flag constants. Use the macro \c #XMP_PropIsQualifier to create a - /// qualifier. <> - - void SetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr qualValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetQualifier() creates or sets a qualifier attached to a property using a string object. - /// - /// Overloads the basic form of the function, allowing you to pass a string object - /// for the qualifier value. It is otherwise identical; see details in the canonical form. - - void SetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - const tStringObj & qualValue, - XMP_OptionBits options = 0 ); - - /// @} - - // ============================================================================================= - - // --------------------------------------------------------------------------------------------- - /// \name Detecting and deleting properties. - /// @{ - /// - /// The namespace URI and prefix usage for property specifiers in these functions is the same as - /// for \c TXMPMeta::GetProperty(). - - // --------------------------------------------------------------------------------------------- - /// @brief \c DeleteProperty() deletes an XMP subtree rooted at a given property. - /// - /// It is not an error if the property does not exist. - /// - /// @param schemaNS The namespace URI for the property; see \c GetProperty(). - /// - /// @param propName The name of the property; see \c GetProperty(). - - void DeleteProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DeleteArrayItem() deletes an XMP subtree rooted at a given array item. - /// - /// It is not an error if the array item does not exist. Use - /// \c TXMPUtils::ComposeArrayItemPath() to create a complex path. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem - /// to specify the last existing array item. - - void DeleteArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DeleteStructField() deletes an XMP subtree rooted at a given struct field. - /// - /// It is not an error if the field does not exist. - /// - /// @param schemaNS The namespace URI for the struct; see \c GetProperty(). - /// - /// @param structName The name of the struct. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field. Same namespace and prefix usage as - /// \c GetProperty(). - /// - /// @param fieldName The name of the field. Must be a single XML name, must not be null or the - /// empty string. Same namespace and prefix usage as \c GetProperty(). - - void DeleteStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DeleteQualifier() deletes an XMP subtree rooted at a given qualifier. - /// - /// It is not an error if the qualifier does not exist. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property to which the qualifier is attached. Can be a - /// general path expression, must not be null or the empty string; see \c GetProperty() for - /// namespace prefix usage. - /// - /// @param qualNS The namespace URI for the qualifier. Same namespace and prefix usage as - /// \c GetProperty(). - /// - /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or - /// the empty string. Same namespace and prefix usage as \c GetProperty(). - - void DeleteQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DoesPropertyExist() reports whether a property currently exists. - /// - /// @param schemaNS The namespace URI for the property; see \c GetProperty(). - /// - /// @param propName The name of the property; see \c GetProperty(). - /// - /// @return True if the property exists. - - bool DoesPropertyExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c DoesArrayItemExist() reports whether an array item currently exists. - /// - /// Use \c TXMPUtils::ComposeArrayItemPath() to create a complex path. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem - /// to specify the last existing array item. - /// - /// @return True if the array item exists. - - bool DoesArrayItemExist ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c DoesStructFieldExist() reports whether a struct field currently exists. - /// - /// Use \c TXMPUtils::ComposeStructFieldPath() to create a complex path. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param structName The name of the struct. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field. Same namespace and prefix usage as - /// \c GetProperty(). - /// - /// @param fieldName The name of the field. Must be a single XML name, must not be null or the - /// empty string. Same namespace and prefix usage as \c GetProperty(). - /// - /// @return True if the field exists. - - bool DoesStructFieldExist ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c DoesQualifierExist() reports whether a qualifier currently exists. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property to which the qualifier is attached. Can be a - /// general path expression, must not be null or the empty string; see \c GetProperty() for - /// namespace prefix usage. - /// - /// @param qualNS The namespace URI for the qualifier. Same namespace and prefix usage as - /// \c GetProperty(). - /// - /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or - /// the empty string. Same namespace and prefix usage as \c GetProperty(). - /// - /// @return True if the qualifier exists. - - bool DoesQualifierExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ) const; - - /// @} - - // ============================================================================================= - // Specialized Get and Set functions - // ============================================================================================= - - // --------------------------------------------------------------------------------------------- - /// \name Accessing properties as binary values. - /// @{ - /// - /// These are very similar to \c TXMPMeta::GetProperty() and \c TXMPMeta::SetProperty(), except - /// that the value is returned or provided in binary form instead of as a UTF-8 string. - /// \c TXMPUtils provides functions for converting between binary and string values. - /// Use the path composition functions in \c TXMPUtils to compose complex path expressions - /// for fields or items in nested structures or arrays, or for qualifiers. - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetProperty_Bool() retrieves the value of a Boolean property as a C++ bool. - /// - /// Reports whether a property exists, and retrieves its binary value and property type information. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue [out] A buffer in which to return the binary value. Can be null if the - /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have - /// values. - /// - /// @param options [out] A buffer in which to return the option flags describing the property, a - /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can - /// be null if flags are not wanted. - /// - /// @return True if the property exists. - - bool GetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetProperty_Int() retrieves the value of an integer property as a C long integer. - /// - /// Reports whether a property exists, and retrieves its binary value and property type information. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue [out] A buffer in which to return the binary value. Can be null if the - /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have - /// values. - /// - /// @param options [out] A buffer in which to return the option flags describing the property, a - /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can - /// be null if flags are not wanted. - /// - /// @return True if the property exists. - - bool GetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetProperty_Int64() retrieves the value of an integer property as a C long long integer. - /// - /// Reports whether a property exists, and retrieves its binary value and property type information. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue [out] A buffer in which to return the binary value. Can be null if the - /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have - /// values. - /// - /// @param options [out] A buffer in which to return the option flags describing the property, a - /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can - /// be null if flags are not wanted. - /// - /// @return True if the property exists. - - bool GetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long long * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetProperty_Float() retrieves the value of a floating-point property as a C double float. - /// - /// Reports whether a property exists, and retrieves its binary value and property type information. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue [out] A buffer in which to return the binary value. Can be null if the - /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have - /// values. - /// - /// @param options [out] A buffer in which to return the option flags describing the property, a - /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can - /// be null if flags are not wanted. - /// - /// @return True if the property exists. - - bool GetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetProperty_Date() retrieves the value of a date-time property as an \c #XMP_DateTime structure. - /// - /// Reports whether a property exists, and retrieves its binary value and property type information. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue [out] A buffer in which to return the binary value. Can be null if the - /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have - /// values. - /// - /// @param options [out] A buffer in which to return the option flags describing the property, a - /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can - /// be null if flags are not wanted. - /// - /// @return True if the property exists. - - bool GetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_DateTime * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty_Bool() sets the value of a Boolean property using a C++ bool. - /// - /// Sets a property with a binary value, creating it if necessary. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue The new binary value. Can be null if creating the property. Must be null - /// for arrays and non-leaf levels of structs that do not have values. - /// - /// @param options Option flags describing the property; a logical OR of allowed bit-flag - /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property - /// that already exists. - - void SetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool propValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty_Int() sets the value of an integer property using a C long integer. - /// - /// Sets a property with a binary value, creating it if necessary. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue The new binary value. Can be null if creating the property. Must be null - /// for arrays and non-leaf levels of structs that do not have values. - /// - /// @param options Option flags describing the property; a logical OR of allowed bit-flag - /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property - /// that already exists. - - void SetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long propValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty_Int64() sets the value of an integer property using a C long long integer. - /// - /// Sets a property with a binary value, creating it if necessary. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue The new binary value. Can be null if creating the property. Must be null - /// for arrays and non-leaf levels of structs that do not have values. - /// - /// @param options Option flags describing the property; a logical OR of allowed bit-flag - /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property - /// that already exists. - - void SetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long long propValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty_Float() sets the value of a floating-point property using a C double float. - /// - /// Sets a property with a binary value, creating it if necessary. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue The new binary value. Can be null if creating the property. Must be null - /// for arrays and non-leaf levels of structs that do not have values. - /// - /// @param options Option flags describing the property; a logical OR of allowed bit-flag - /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property - /// that already exists. - - void SetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double propValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetProperty_Date() sets the value of a date/time property using an \c #XMP_DateTime structure. - /// - /// Sets a property with a binary value, creating it if necessary. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param propValue The new binary value. Can be null if creating the property. Must be null - /// for arrays and non-leaf levels of structs that do not have values. - /// - /// @param options Option flags describing the property; a logical OR of allowed bit-flag - /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property - /// that already exists. - - void SetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const XMP_DateTime & propValue, - XMP_OptionBits options = 0 ); - - /// @} - // ============================================================================================= - /// \name Accessing localized text (alt-text) properties. - /// @{ - /// - /// Localized text properties are stored in alt-text arrays. They allow multiple concurrent - /// localizations of a property value, for example a document title or copyright in several - /// languages. - /// - /// These functions provide convenient support for localized text properties, including a - /// number of special and obscure aspects. The most important aspect of these functions is that - /// they select an appropriate array item based on one or two RFC 3066 language tags. One of - /// these languages, the "specific" language, is preferred and selected if there is an exact - /// match. For many languages it is also possible to define a "generic" language that can be - /// used if there is no specific language match. The generic language must be a valid RFC 3066 - /// primary subtag, or the empty string. - /// - /// For example, a specific language of "en-US" should be used in the US, and a specific - /// language of "en-UK" should be used in England. It is also appropriate to use "en" as the - /// generic language in each case. If a US document goes to England, the "en-US" title is - /// selected by using the "en" generic language and the "en-UK" specific language. - /// - /// It is considered poor practice, but allowed, to pass a specific language that is just an - /// RFC 3066 primary tag. For example "en" is not a good specific language, it should only be - /// used as a generic language. Passing "i" or "x" as the generic language is also considered - /// poor practice but allowed. - /// - /// Advice from the W3C about the use of RFC 3066 language tags can be found at: - /// \li http://www.w3.org/International/articles/language-tags/ - /// - /// \note RFC 3066 language tags must be treated in a case insensitive manner. The XMP toolkit - /// does this by normalizing their capitalization: - /// \li The primary subtag is lower case, the suggested practice of ISO 639. - /// \li All 2 letter secondary subtags are upper case, the suggested practice of ISO 3166. - /// \li All other subtags are lower case. - /// - /// The XMP specification defines an artificial language, "x-default", that is used to - /// explicitly denote a default item in an alt-text array. The XMP toolkit normalizes alt-text - /// arrays such that the x-default item is the first item. The \c SetLocalizedText() function - /// has several special features related to the x-default item, see its description for details. - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetLocalizedText() retrieves information about a selected item in an alt-text array. - /// - /// The array item is selected according to these rules: - /// \li Look for an exact match with the specific language. - /// \li If a generic language is given, look for a partial match. - /// \li Look for an x-default item. - /// \li Choose the first item. - /// - /// A partial match with the generic language is where the start of the item's language matches - /// the generic string and the next character is '-'. An exact match is also recognized as a - /// degenerate case. - /// - /// You can pass "x-default" as the specific language. In this case, selection of an - /// \c x-default item is an exact match by the first rule, not a selection by the 3rd rule. The - /// last 2 rules are fallbacks used when the specific and generic languages fail to produce a - /// match. - /// - /// The return value reports whether a match was successfully made. - /// - /// @param schemaNS The namespace URI for the alt-text array; see \c GetProperty(). - /// - /// @param altTextName The name of the alt-text array. Can be a general path expression, must - /// not be null or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param genericLang The name of the generic language as an RFC 3066 primary subtag. Can be - /// null or the empty string if no generic language is wanted. - /// - /// @param specificLang The name of the specific language as an RFC 3066 tag, or "x-default". - /// Must not be null or the empty string. - /// - /// @param actualLang [out] A string object in which to return the language of the selected - /// array item, if an appropriate array item is found. Can be null if the language is not wanted. - /// - /// @param itemValue [out] A string object in which to return the value of the array item, if an - /// appropriate array item is found. Can be null if the value is not wanted. - /// - /// @param options A buffer in which to return the option flags that describe the array item, if - /// an appropriate array item is found. Can be null if the flags are not wanted. - /// - /// @return True if an appropriate array item exists. - - bool GetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - tStringObj * actualLang, - tStringObj * itemValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetLocalizedText() modifies the value of a selected item in an alt-text array. - /// - /// Creates an appropriate array item if necessary, and handles special cases for the x-default - /// item. - /// - /// The array item is selected according to these rules: - /// \li Look for an exact match with the specific language. - /// \li If a generic language is given, look for a partial match. - /// \li Look for an x-default item. - /// \li Choose the first item. - /// - /// A partial match with the generic language is where the start of the item's language matches - /// the generic string and the next character is '-'. An exact match is also recognized as a - /// degenerate case. - /// - /// You can pass "x-default" as the specific language. In this case, selection of an - /// \c x-default item is an exact match by the first rule, not a selection by the 3rd rule. The - /// last 2 rules are fallbacks used when the specific and generic languages fail to produce a - /// match. - /// - /// Item values are modified according to these rules: - /// - /// \li If the selected item is from a match with the specific language, the value of that - /// item is modified. If the existing value of that item matches the existing value of the - /// x-default item, the x-default item is also modified. If the array only has 1 existing item - /// (which is not x-default), an x-default item is added with the given value. - /// - /// \li If the selected item is from a match with the generic language and there are no other - /// generic matches, the value of that item is modified. If the existing value of that item - /// matches the existing value of the x-default item, the x-default item is also modified. If - /// the array only has 1 existing item (which is not x-default), an x-default item is added - /// with the given value. - /// - /// \li If the selected item is from a partial match with the generic language and there are - /// other partial matches, a new item is created for the specific language. The x-default item - /// is not modified. - /// - /// \li If the selected item is from the last 2 rules then a new item is created for the - /// specific language. If the array only had an x-default item, the x-default item is also - /// modified. If the array was empty, items are created for the specific language and - /// x-default. - /// - /// @param schemaNS The namespace URI for the alt-text array; see \c GetProperty(). - /// - /// @param altTextName The name of the alt-text array. Can be a general path expression, must - /// not be null or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param genericLang The name of the generic language as an RFC 3066 primary subtag. Can be - /// null or the empty string if no generic language is wanted. - /// - /// @param specificLang The name of the specific language as an RFC 3066 tag, or "x-default". - /// Must not be null or the empty string. - /// - /// @param itemValue The new value for the matching array item, specified as a null-terminated - /// UTF-8 string. - /// - /// @param options Option flags, none currently defined. - - void SetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - XMP_StringPtr itemValue, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetLocalizedText() modifies the value of a selected item in an alt-text array using - /// a string object. - /// - /// Creates an appropriate array item if necessary, and handles special cases for the x-default - /// item. - /// - /// The array item is selected according to these rules: - /// \li Look for an exact match with the specific language. - /// \li If a generic language is given, look for a partial match. - /// \li Look for an x-default item. - /// \li Choose the first item. - /// - /// A partial match with the generic language is where the start of the item's language matches - /// the generic string and the next character is '-'. An exact match is also recognized as a - /// degenerate case. - /// - /// You can pass "x-default" as the specific language. In this case, selection of an \c x-default - /// item is an exact match by the first rule, not a selection by the 3rd rule. The last 2 rules - /// are fallbacks used when the specific and generic languages fail to produce a match. - /// - /// Item values are modified according to these rules: - /// - /// \li If the selected item is from a match with the specific language, the value of that - /// item is modified. If the existing value of that item matches the existing value of the - /// x-default item, the x-default item is also modified. If the array only has 1 existing item - /// (which is not x-default), an x-default item is added with the given value. - /// - /// \li If the selected item is from a match with the generic language and there are no other - /// generic matches, the value of that item is modified. If the existing value of that item - /// matches the existing value of the x-default item, the x-default item is also modified. If - /// the array only has 1 existing item (which is not x-default), an x-default item is added - /// with the given value. - /// - /// \li If the selected item is from a partial match with the generic language and there are - /// other partial matches, a new item is created for the specific language. The x-default item - /// is not modified. - /// - /// \li If the selected item is from the last 2 rules then a new item is created for the - /// specific language. If the array only had an x-default item, the x-default item is also - /// modified. If the array was empty, items are created for the specific language and - /// x-default. - /// - /// @param schemaNS The namespace URI for the alt-text array; see \c GetProperty(). - /// - /// @param altTextName The name of the alt-text array. Can be a general path expression, must - /// not be null or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param genericLang The name of the generic language as an RFC 3066 primary subtag. Can be - /// null or the empty string if no generic language is wanted. - /// - /// @param specificLang The name of the specific language as an RFC 3066 tag, or "x-default". - /// Must not be null or the empty string. - /// - /// @param itemValue The new value for the matching array item, specified as a string object. - /// - /// @param options Option flags, none currently defined. - - void SetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - const tStringObj & itemValue, - XMP_OptionBits options = 0 ); - - /// @} - - // ============================================================================================= - /// \name Creating and reading serialized RDF. - /// @{ - /// - /// The metadata contained in an XMP object must be serialized as RDF for storage in an XMP - /// packet and output to a file. Similarly, metadata in the form of serialized RDF (such as - /// metadata read from a file using \c TXMPFiles) must be parsed into an XMP object for - /// manipulation with the XMP Toolkit. - /// - /// These functions support parsing serialized RDF into an XMP object, and serializing an XMP - /// object into RDF. The input for parsing can be any valid Unicode encoding. ISO Latin-1 is - /// also recognized, but its use is strongly discouraged. Serialization is always as UTF-8. - - // --------------------------------------------------------------------------------------------- - /// @brief \c ParseFromBuffer() parses RDF from a series of input buffers into this XMP object. - /// - /// Use this to convert metadata from serialized RDF form (as, for example, read from an XMP - /// packet embedded in a file) into an XMP object that you can manipulate with the XMP Toolkit. - /// If this XMP object is empty and the input buffer contains a complete XMP packet, this is the - /// same as creating a new XMP object from that buffer with the constructor. - /// - /// You can use this function to combine multiple buffers into a single metadata tree. To - /// terminate an input loop conveniently, pass the option \c #kXMP_ParseMoreBuffers for all - /// real input, then make a final call with a zero length and \c #kXMP_NoOptions. The buffers - /// can be any length. The buffer boundaries need not respect XML tokens or even Unicode - /// characters. - /// - /// @param buffer A pointer to a buffer of input. Can be null if \c bufferSize is 0. - /// - /// @param bufferSize The length of the input buffer in bytes. Zero is a valid value. - /// - /// @param options An options flag that controls how the parse operation is performed. A logical - /// OR of these bit-flag constants: - /// \li \c #kXMP_ParseMoreBuffers - This is not the last buffer of input, more calls follow. - /// \li \c #kXMP_RequireXMPMeta - The \c x:xmpmeta XML element is required around \c rdf:RDF. - /// - /// @see \c TXMPFiles::GetXMP() - - void ParseFromBuffer ( XMP_StringPtr buffer, - XMP_StringLen bufferSize, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SerializeToBuffer() serializes metadata in this XMP object into a string as RDF. - /// - /// Use this to prepare metadata for storage as an XMP packet embedded in a file. See \c TXMPFiles::PutXMP(). - /// - /// @param rdfString [out] A string object in which to return the serialized RDF. Must not be null. - /// - /// @param options An options flag that controls how the serialization operation is performed. - /// The specified options must be logically consistent; an exception is thrown if they are not. - /// A logical OR of these bit-flag constants: - /// \li \c kXMP_OmitPacketWrapper - Do not include an XML packet wrapper. This cannot be - /// specified together with \c #kXMP_ReadOnlyPacket, \c #kXMP_IncludeThumbnailPad, or - /// \c #kXMP_ExactPacketLength. - /// \li \c kXMP_ReadOnlyPacket - Create a read-only XML packet wapper. Cannot be specified - /// together with \c kXMP_OmitPacketWrapper. - /// \li \c kXMP_UseCompactFormat - Use a highly compact RDF syntax and layout. - /// \li \c kXMP_WriteAliasComments - Include XML comments for aliases. - /// \li \c kXMP_IncludeThumbnailPad - Include typical space for a JPEG thumbnail in the - /// padding if no \c xmp:Thumbnails property is present. Cannot be specified together with - /// \c kXMP_OmitPacketWrapper. - /// \li \c kXMP_ExactPacketLength - The padding parameter provides the overall packet length. - /// The actual amount of padding is computed. An exception is thrown if the packet exceeds - /// this length with no padding. Cannot be specified together with - /// \c kXMP_OmitPacketWrapper. - /// - /// In addition to the above options, you can include one of the following encoding options: - /// \li \c #kXMP_EncodeUTF8 - Encode as UTF-8, the default. - /// \li \c #kXMP_EncodeUTF16Big - Encode as big-endian UTF-16. - /// \li \c #kXMP_EncodeUTF16Little - Encode as little-endian UTF-16. - /// \li \c #kXMP_EncodeUTF32Big - Encode as big-endian UTF-32. - /// \li \c #kXMP_EncodeUTF32Little - Encode as little-endian UTF-32. - /// - /// @param padding The amount of padding to be added if a writeable XML packet is created. If - /// zero (the default) an appropriate amount of padding is computed. - /// - /// @param newline The string to be used as a line terminator. If empty, defaults to linefeed, - /// U+000A, the standard XML newline. - /// - /// @param indent The string to be used for each level of indentation in the serialized RDF. If - /// empty, defaults to two ASCII spaces, U+0020. - /// - /// @param baseIndent The number of levels of indentation to be used for the outermost XML - /// element in the serialized RDF. This is convenient when embedding the RDF in other text. - - void SerializeToBuffer ( tStringObj * rdfString, - XMP_OptionBits options, - XMP_StringLen padding, - XMP_StringPtr newline, - XMP_StringPtr indent = "", - XMP_Index baseIndent = 0 ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c SerializeToBuffer() serializes metadata in this XMP object into a string as RDF. - /// - /// This simpler form of the function uses default values for the \c newline, \c indent, and - /// \c baseIndent parameters. - /// - /// @param rdfString [out] A string object in which to return the serialized RDF. Must not be null. - /// - /// @param options An options flag that controls how the serialization operation is performed. - /// The specified options must be logically consistent; an exception is thrown if they are not. - /// A logical OR of these bit-flag constants: - /// \li \c kXMP_OmitPacketWrapper - Do not include an XML packet wrapper. This cannot be - /// specified together with \c #kXMP_ReadOnlyPacket, \c #kXMP_IncludeThumbnailPad, or - /// \c #kXMP_ExactPacketLength. - /// \li \c kXMP_ReadOnlyPacket - Create a read-only XML packet wapper. Cannot be specified - /// together with \c kXMP_OmitPacketWrapper. - /// \li \c kXMP_UseCompactFormat - Use a highly compact RDF syntax and layout. - /// \li \c kXMP_WriteAliasComments - Include XML comments for aliases. - /// \li \c kXMP_IncludeThumbnailPad - Include typical space for a JPEG thumbnail in the - /// padding if no \c xmp:Thumbnails property is present. Cannot be specified together with - /// \c kXMP_OmitPacketWrapper. - /// \li \c kXMP_ExactPacketLength - The padding parameter provides the overall packet length. - /// The actual amount of padding is computed. An exception is thrown if the packet exceeds - /// this length with no padding. Cannot be specified together with - /// \c kXMP_OmitPacketWrapper. - /// - /// In addition to the above options, you can include one of the following encoding options: - /// \li \c #kXMP_EncodeUTF8 - Encode as UTF-8, the default. - /// \li \c #kXMP_EncodeUTF16Big - Encode as big-endian UTF-16. - /// \li \c #kXMP_EncodeUTF16Little - Encode as little-endian UTF-16. - /// \li \c #kXMP_EncodeUTF32Big - Encode as big-endian UTF-32. - /// \li \c #kXMP_EncodeUTF32Little - Encode as little-endian UTF-32. - /// - /// @param padding The amount of padding to be added if a writeable XML packet is created. - /// If zero (the default) an appropriate amount of padding is computed. - - void SerializeToBuffer ( tStringObj * rdfString, - XMP_OptionBits options = 0, - XMP_StringLen padding = 0 ) const; - - /// @} - // ============================================================================================= - // Miscellaneous Member Functions - // ============================== - - // --------------------------------------------------------------------------------------------- - /// \name Helper functions. - /// @{ - - // --------------------------------------------------------------------------------------------- - /// @brief Retrieves an internal reference that can be safely passed across DLL boundaries and - /// reconstructed. - /// - /// The \c TXMPMeta class is a normal C++ template, it is instantiated and local to each client - /// executable, as are the other \c TXMP* classes. Different clients might not use the same - /// string type to instantiate \c TXMPMeta. - /// - /// Because of this you should not pass \c SXMPMeta objects, or pointers to \c SXMPMeta objects, - /// across DLL boundaries. Use this function to obtain a safe internal reference that you can - /// pass, then construct a local object on the callee side. This construction does not create a - /// cloned XMP tree, it is the same underlying XMP object safely wrapped in each client's - /// \c SXMPMeta object. - /// - /// Use this function and the associated constructor like this: - /// \li The callee's header contains: - ///
-    /// CalleeMethod ( XMPMetaRef xmpRef );
-    /// 
- /// - /// \li The caller's code contains: - ///
-    /// SXMPMeta callerXMP;
-    /// CalleeMethod ( callerXMP.GetInternalRef() );
-    /// 
- /// - /// \li The callee's code contains: - ///
-    /// SXMPMeta calleeXMP ( xmpRef );
-    /// 
- /// - /// @return The reference object. - - XMPMetaRef GetInternalRef() const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c GetObjectName() retrieves the client-assigned name of this XMP object. - /// - /// Assign this name with \c SetObjectName(). - /// - /// @param name [out] A string object in which to return the name. - - void GetObjectName ( tStringObj * name ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetObjectName() assigns a name to this XMP object. - /// - /// Retrieve this client-assigned name with \c GetObjectName(). - /// - /// @param name The name as a null-terminated UTF-8 string. - - void SetObjectName ( XMP_StringPtr name ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetObjectName() assigns a name to this XMP object. - /// - /// Retrieve this client-assigned name with \c GetObjectName(). - /// - /// @param name The name as a string object. - - void SetObjectName ( tStringObj name ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c Sort() sorts the data model tree of an XMP object. - /// - /// Use this function to sort the data model of an XMP object into a canonical order. This can - /// be convenient when comparing data models, (e.g. by text comparison of DumpObject output). - /// - /// At the top level the namespaces are sorted by their prefixes. Within a namespace, the top - /// level properties are sorted by name. Within a struct, the fields are sorted by their - /// qualified name, i.e. their XML prefix:local form. Unordered arrays of simple items are - /// sorted by value. Language Alternative arrays are sorted by the xml:lang qualifiers, with - /// the "x-default" item placed first. - - void Sort(); - - // --------------------------------------------------------------------------------------------- - /// @brief \c Erase() restores the object to a "just constructed" state. - - void Erase(); - - // --------------------------------------------------------------------------------------------- - /// @brief \c Clone() creates a deep copy of an XMP object. - /// - /// Use this function to copy an entire XMP metadata tree. Assignment and copy constructors only - /// increment a reference count, they do not do a deep copy. This function returns an object, - /// not a pointer. The following shows correct usage: - /// - ///
-    /// SXMPMeta * clone1 = new SXMPMeta ( sourceXMP.Clone() );  // This works.
-    /// SXMPMeta   clone2 ( sourceXMP.Clone );  	// This works also. (Not a pointer.)
-    /// 
- /// The \c clone2 example does not use an explicit pointer. - /// This is good for local usage, protecting against memory leaks. - /// - /// This is an example of incorrect usage: - ///
-    /// SXMPMeta * clone3 = &sourceXMP.Clone();		// ! This does not work!
-    /// 
- /// The assignment to \c clone3 creates a temporary object, initializes it with the clone, - /// assigns the address of the temporary to \c clone3, then deletes the temporary. - /// - /// @param options Option flags, not currently defined.. - /// - /// @return An XMP object cloned from the original. - - TXMPMeta Clone ( XMP_OptionBits options = 0 ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c CountArrayItems() reports the number of items currently defined in an array. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @return The number of items. - - XMP_Index CountArrayItems ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief \c DumpObject() outputs the content of an XMP object to a callback handler for debugging. - /// - /// Invokes a client-defined callback for each line of output. - /// - /// @param outProc The client-defined procedure to handle each line of output. - /// - /// @param clientData A pointer to client-defined data to pass to the handler. - /// - /// @return A success-fail status value, returned from the handler. Zero is success, failure - /// values are client-defined. - /// - /// @see Static functions \c DumpNamespaces() and \c DumpAliases() - - XMP_Status DumpObject ( XMP_TextOutputProc outProc, - void * clientData ) const; - - // --------------------------------------------------------------------------------------------- - /// @brief Not implemented - XMP_OptionBits GetObjectOptions() const; - - // --------------------------------------------------------------------------------------------- - /// \brief Not implemented - void SetObjectOptions ( XMP_OptionBits options ); - - /// @} - - // ============================================================================================= - - XMPMetaRef xmpRef; // *** Should be private, see below. - -private: - -#if 0 // *** VS.Net and gcc seem to not handle the friend declarations properly. - friend class TXMPIterator ; - friend class TXMPUtils ; -#endif - -}; // class TXMPMeta - -#endif // __TXMPMeta_hpp__ diff --git a/xmpsdk/include/TXMPUtils.hpp b/xmpsdk/include/TXMPUtils.hpp deleted file mode 100644 index d7189770db..0000000000 --- a/xmpsdk/include/TXMPUtils.hpp +++ /dev/null @@ -1,965 +0,0 @@ -#ifndef __TXMPUtils_hpp__ -#define __TXMPUtils_hpp__ 1 - -#if ( ! __XMP_hpp__ ) - #error "Do not directly include, use XMPSDK.hpp" -#endif - -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2008 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. -// ================================================================================================= - -// ================================================================================================= -/// \file TXMPUtils.hpp -/// \brief API for access to the XMP Toolkit utility services. -/// -/// \c TXMPUtils is the template class providing utility services for the XMP Toolkit. It must be -/// instantiated with a string class such as \c std::string. See the instructions in XMPSDK.hpp, and -/// the Overview for a discussion of the overall architecture of the XMP API. -// ================================================================================================= - -// ================================================================================================= -/// \class TXMPUtils TXMPUtils.hpp -/// @brief API for access to the XMP Toolkit utility services. -/// -/// \c TXMPUtils is a template class which must be instantiated with a string class such as -/// \c std::string. See the instructions in XMPSDK.hpp, and the Overview for a discussion of the overall -/// architecture of the XMP API. -/// -/// This class defines helper functions that support the basic metadata manipulation provided by -/// \c TXMPMeta. All of the functions are static; that is, you call them directly from the concrete -/// class (\c SXMPUtils), which is never itself instantiated. -/// -/// General categories of utilities include: -/// -/// \li Composing complex path expressions, which you can then pass to the property access -/// functions in \c TXMPMeta -/// \li Converting between binary and string forms of property values -/// \li Manipulating date/time values -/// \li Encoding and decoding base-64 strings -/// \li JPEG file handling -/// \li Editing aids for creating a user interface for the XMP Toolkit -// ================================================================================================= - -template class TXMPUtils { - -public: - - // ============================================================================================= - // No constructors or destructor declared or needed - // ================================================ - - // ============================================================================================ - /// \name Path composition - /// @{ - /// - /// These functions provide support for composing path expressions to deeply nested properties. - /// The functions in \c TXMPMeta such as \c TXMPMeta::GetProperty(), - /// \c TXMPMeta::GetArrayItem(), and \c TXMPMeta::GetStructField() provide easy access to top level - /// simple properties, items in top level arrays, and fields of top level structs. They are - /// not as convenient for more complex things, such as fields several levels deep in a complex - /// struct, or fields within an array of structs, or items of an array that is a field of a - /// struct. You can use these utility functions to compose these paths, which you can then pass - /// to the property access functions. You can also compose paths to top-level array items or - /// struct fields so that you can use the binary accessors such as - /// \c TXMPMeta::GetProperty_Int(). - /// - /// You can use these functions is to compose a complete path expression, or all but the last - /// component. For example, suppose you have a property that is an array of integers within a - /// struct. You can access one of the array items like this: - /// - ///
-    ///   SXMPUtils::ComposeStructFieldPath ( schemaNS, "Struct", fieldNS, "Array", &path );
-    ///   SXMPUtils::ComposeArrayItemPath ( schemaNS, path, index, &path );
-    ///   exists = xmpObj.GetProperty_Int ( schemaNS, path, &value, &options );
-    /// 
- /// - /// You could also use this code if you want the string form of the integer: - /// - ///
-    ///   SXMPUtils::ComposeStructFieldPath ( schemaNS, "Struct", fieldNS, "Array", &path );
-    ///   xmpObj.GetArrayItem ( schemaNS, path, index, &value, &options );
-    /// 
- /// - /// \note It might look confusing that the \c schemaNS is passed in all of the calls above. This - /// is because the XMP Toolkit keeps the top-level "schema" namespace separate from the rest of - /// the path expression. - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeArrayItemPath() composes the path expression for an item in an array. - /// - /// The returned string is in the form ns:arrayName[i], where "ns" is the prefix for - /// the specified namespace, and "i" is the decimal representation of specified item index. - /// If the last item was specified, the path is ns:arrayName[last()]. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param itemIndex The 1-based index of the desired item. Use the macro - /// \c #kXMP_ArrayLastItem to specify the last existing array item. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeArrayItemPath ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - tStringObj * fullPath ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeStructFieldPath() composes the path expression for a field in a struct. - /// - /// The returned string is in the form ns:structName/fNS:fieldName, where "ns" is the - /// prefix for the schema namespace, and "fNS" is the prefix for field namespace. - /// - /// @param schemaNS The namespace URI for the struct; see \c GetProperty(). - /// - /// @param structName The name of the struct. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field. Same URI and prefix usage as the - /// \c schemaNS and \c structName parameters. - /// - /// @param fieldName The name of the field. Must be a single XML name, must not be null or the - /// empty string. Same URI and prefix usage as the \c schemaNS and \c structName parameters. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeStructFieldPath ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - tStringObj * fullPath ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeQualifierPath() composes the path expression for a qualifier. - /// - /// The returned string is in the form ns:propName/?qNS:qualName, where "ns" is the - /// prefix for the schema namespace, and "qNS" is the prefix for the qualifier namespace. - /// - /// @param schemaNS The namespace URI; see \c GetProperty(). - /// - /// @param propName The name of the property to which the qualifier is attached. Can be a - /// general path expression, must not be null or the empty string; see \c GetProperty() for - /// namespace prefix usage. - /// - /// @param qualNS The namespace URI for the qualifier. Same URI and prefix usage as the - /// \c schemaNS and \c propName parameters. - /// - /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or the - /// empty string. Same URI and prefix usage as the \c schemaNS and \c propName parameters. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeQualifierPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - tStringObj * fullPath ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeLangSelector() composes the path expression to select an alternate item by language. - /// - /// Path syntax allows two forms of "content addressing" to select an item in an array of - /// alternatives. The form used in this function lets you select an item in an alt-text array - /// based on the value of its \c xml:lang qualifier. The other form of content addressing is - /// shown in \c ComposeFieldSelector(). - /// - /// The returned string is in the form ns:arrayName[\@xml:lang='langName'], where - /// "ns" is the prefix for the schema namespace - /// - /// This function provides a path expression that is explicitly and only for a specific - /// language. In most cases, \c TXMPMeta::SetLocalizedText() and \c TXMPMeta::GetLocalizedText() - /// are preferred, because they provide extra logic to choose the appropriate language and - /// maintain consistency with the 'x-default' value. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param langName The RFC 3066 code for the desired language, as a null-terminated UTF-8 string. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr langName, - tStringObj * fullPath ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeLangSelector() composes a path expression to select an alternate item by language. - /// - /// Path syntax allows two forms of "content addressing" to select an item in an array of - /// alternatives. The form used in this function lets you select an item in an alt-text array - /// based on the value of its \c xml:lang qualifier. The other form of content addressing is - /// shown in \c ComposeFieldSelector(). - /// - /// The returned string is in the form ns:arrayName[\@xml:lang='langName'], where - /// "ns" is the prefix for the schema namespace - /// - /// This function provides a path expression that is explicitly and only for a specific - /// language. In most cases, \c TXMPMeta::SetLocalizedText() and \c TXMPMeta::GetLocalizedText() - /// are preferred, because they provide extra logic to choose the appropriate language and - /// maintain consistency with the 'x-default' value. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param langName The RFC 3066 code for the desired language, as a string object. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - const tStringObj & langName, - tStringObj * fullPath ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeFieldSelector() composes a path expression to select an alternate item by a field's value. - /// - /// Path syntax allows two forms of "content addressing" to select an item in an array of - /// alternatives. The form used in this function lets you select an item in an array of structs - /// based on the value of one of the fields in the structs. The other form of content addressing - /// is shown in \c ComposeLangSelector(). - /// - /// For example, consider a simple struct that has two fields, the name of a city and the URI of - /// an FTP site in that city. Use this to create an array of download alternatives. You can show - /// the user a popup built from the values of the city fields, then get the corresponding URI as - /// follows: - ///
-    ///   ComposeFieldSelector ( schemaNS, "Downloads", fieldNS, "City", chosenCity, &path );
-    ///   exists = GetStructField ( schemaNS, path, fieldNS, "URI", &uri );
-    /// 
- /// - /// The returned string is in the form ns:arrayName[fNS:fieldName='fieldValue'], where - /// "ns" is the prefix for the schema namespace and "fNS" is the prefix for the field namespace. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field used as the selector. Same URI and prefix - /// usage as the \c schemaNS and \c arrayName parameters. - /// - /// @param fieldName The name of the field used as the selector. Must be a single XML name, must - /// not be null or the empty string. It must be the name of a field that is itself simple. - /// - /// @param fieldValue The desired value of the field, specified as a null-terminated UTF-8 string. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - tStringObj * fullPath ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ComposeFieldSelector() composes a path expression to select an alternate item by a field's value. - /// - /// Path syntax allows two forms of "content addressing" to select an item in an array of - /// alternatives. The form used in this function lets you select an item in an array of structs - /// based on the value of one of the fields in the structs. The other form of content addressing - /// is shown in \c ComposeLangSelector(). - /// - /// For example, consider a simple struct that has two fields, the name of a city and the URI of - /// an FTP site in that city. Use this to create an array of download alternatives. You can show - /// the user a popup built from the values of the city fields, then get the corresponding URI as - /// follows: - ///
-    ///   ComposeFieldSelector ( schemaNS, "Downloads", fieldNS, "City", chosenCity, &path );
-    ///   exists = GetStructField ( schemaNS, path, fieldNS, "URI", &uri );
-    /// 
- /// - /// The returned string is in the form ns:arrayName[fNS:fieldName='fieldValue'], where - /// "ns" is the prefix for the schema namespace and "fNS" is the prefix for the field namespace. - /// - /// @param schemaNS The namespace URI for the array; see \c GetProperty(). - /// - /// @param arrayName The name of the array. Can be a general path expression, must not be null - /// or the empty string; see \c GetProperty() for namespace prefix usage. - /// - /// @param fieldNS The namespace URI for the field used as the selector. Same URI and prefix - /// usage as the \c schemaNS and \c arrayName parameters. - /// - /// @param fieldName The name of the field used as the selector. Must be a single XML name, must - /// not be null or the empty string. It must be the name of a field that is itself simple. - /// - /// @param fieldValue The desired value of the field, specified as a string object. - /// - /// @param fullPath [out] A string in which to return the composed path. - - static void ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - const tStringObj & fieldValue, - tStringObj * fullPath ); - - /// @} - - // ============================================================================================= - /// \name Conversion between binary types and strings - /// @{ - /// - /// The main accessors in \c TXMPMeta set and retrieve property values as strings. additional - /// functions, such as \c TXMPMeta::SetPropertyInt(), set and retrieve property values as - /// explicit binary data types. Use these functions to convert between binary and string - /// values. - /// - /// Strings can be specified as null-terminated UTF-8 (\c #XMP_StringPtr), or as string - /// objects (\c tStringObj) of the type declared when instantiating the XMP classes; see - /// \c XMPSDK.hpp. Alternate forms of each conversion function allow either type of string. - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertFromBool() converts a Boolean value to a string. - /// - /// The string values of Booleans are returned by the macros \c #kXMP_TrueStr and - /// \c #kXMP_FalseStr in \c XMP_Const.h. - /// - /// @param binValue The Boolean value to be converted. - /// - /// @param strValue [out] A buffer in which to return the string representation of the value. - - static void ConvertFromBool ( bool binValue, - tStringObj * strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertFromInt() converts a 32-bit integer value to a string. - /// - /// @param binValue The integer value to be converted. - /// - /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d". - /// - /// @param strValue [out] A buffer in which to return the string representation of the value. - - static void ConvertFromInt ( long binValue, - XMP_StringPtr format, - tStringObj * strValue ); - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertFromInt64() converts a 64-bit integer value to a string. - /// - /// @param binValue The integer value to be converted. - /// - /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d". - /// - /// @param strValue [out] A buffer in which to return the string representation of the value. - - static void ConvertFromInt64 ( long long binValue, - XMP_StringPtr format, - tStringObj * strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertFromFloat() converts a floating-point value to a string. - /// - /// @param binValue The floating-point value to be converted. - /// - /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d". - /// - /// @param strValue [out] A buffer in which to return the string representation of the value. - - static void ConvertFromFloat ( double binValue, - XMP_StringPtr format, - tStringObj * strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertFromDate() converts a date/time value to a string. - /// - /// Formats a date according to the ISO 8601 profile in http://www.w3.org/TR/NOTE-datetime: - ///
-    ///   YYYY
-    ///   YYYY-MM
-    ///   YYYY-MM-DD
-    ///   YYYY-MM-DDThh:mmTZD
-    ///   YYYY-MM-DDThh:mm:ssTZD
-    ///   YYYY-MM-DDThh:mm:ss.sTZD
-    /// 
- /// - /// \c YYYY = four-digit year, formatted as "%.4d"
- /// \c MM = two-digit month (01=January)
- /// \c DD = two-digit day of month (01 through 31)
- /// \c hh = two digits of hour (00 through 23)
- /// \c mm = two digits of minute (00 through 59)
- /// \c ss = two digits of second (00 through 59)
- /// \c s = one or more digits representing a decimal fraction of a second
- /// \c TZD = time zone designator (Z or +hh:mm or -hh:mm) - /// - /// Time-only input is allowed where the year, month, and day are all zero. This is output as - /// "0000-00-00...". - /// - /// @note ISO 8601 does not allow years less than 1000 or greater than 9999. This API allows - /// any year, even negative ones. - /// - /// @param binValue The date/time value to be converted. - /// - /// @param strValue [out] A buffer in which to return the ISO 8601 string representation of the date/time. - - static void ConvertFromDate ( const XMP_DateTime & binValue, - tStringObj * strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToBool() converts a string to a Boolean value. - /// - /// The preferred strings are those returned by the macros \c #kXMP_TrueStr and \c #kXMP_FalseStr. - /// If these do not match, the function does a case insensitive comparison, then simply 't' or 'f', - /// and finally non-zero and zero integer representations. - /// - /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. - /// - /// @return The appropriate C++ bool value for the string. - - static bool ConvertToBool ( XMP_StringPtr strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToBool() converts a string to a Boolean value. - /// - /// Overloads the basic form of the function, allowing you to pass a string object, - /// rather than a const * char. It is otherwise identical; see details in the canonical form. - /// - /// @param strValue The string representation of the value, specified as a string object. - /// - /// @return The appropriate C++ bool value for the string. - - static bool ConvertToBool ( const tStringObj & strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToInt() converts a string to a 32-bit integer value. - /// - /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. - /// - /// @return The 32-bit integer value. - - static long ConvertToInt ( XMP_StringPtr strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToInt() converts a string to a 32-bit integer value. - /// - /// Overloads the basic form of the function, allowing you to pass a string object, - /// rather than a const * char. It is otherwise identical. - /// - /// @param strValue The string representation of the value, specified as a string object. - /// - /// @return The 32-bit integer value. - - static long ConvertToInt ( const tStringObj & strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToInt64() converts a string to a 64-bit integer value. - /// - /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. - /// - /// @return The 64-bit integer value. - - static long long ConvertToInt64 ( XMP_StringPtr strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToInt64() converts a string to a 64-bit integer value. - /// - /// Overloads the basic form of the function, allowing you to pass a string object, - /// rather than a const * char. It is otherwise identical. - /// - /// @param strValue The string representation of the value, specified as a string object. - /// - /// @return The 64-bit integer value. - - static long long ConvertToInt64 ( const tStringObj & strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToFloat() converts a string to a floating-point value. - /// - /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string. - /// - /// @return The floating-point value. - - static double ConvertToFloat ( XMP_StringPtr strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToFloat() converts a string to a floating-point value. - /// - /// Overloads the basic form of the function, allowing you to pass a string object, - /// rather than a const * char. It is otherwise identical. - /// - /// @param strValue The string representation of the value, specified as a string object. - /// - /// @return The floating-point value. - - static double ConvertToFloat ( const tStringObj & strValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToDate() converts a string to a date/time value. - /// - /// Parses a date according to the ISO 8601 profile in http://www.w3.org/TR/NOTE-datetime: - ///
-    ///   YYYY
-    ///   YYYY-MM
-    ///   YYYY-MM-DD
-    ///   YYYY-MM-DDThh:mmTZD
-    ///   YYYY-MM-DDThh:mm:ssTZD
-    ///   YYYY-MM-DDThh:mm:ss.sTZD
-    /// 
- /// - /// \c YYYY = four-digit year, formatted as "%.4d"
- /// \c MM = two-digit month (01=January)
- /// \c DD = two-digit day of month (01 through 31)
- /// \c hh = two digits of hour (00 through 23)
- /// \c mm = two digits of minute (00 through 59)
- /// \c ss = two digits of second (00 through 59)
- /// \c s = one or more digits representing a decimal fraction of a second
- /// \c TZD = time zone designator (Z or +hh:mm or -hh:mm) - /// - /// A missing date portion or missing TZD are tolerated. A missing date value can begin with - /// "Thh:" or "hh:"; the year, month, and day are all set to zero in the \c #XMP_DateTime value. - /// A missing TZD is assumed to be UTC. - /// - /// @note ISO 8601 does not allow years less than 1000 or greater than 9999. This API allows - /// any year, even negative ones. - /// - /// @param strValue The ISO 8601 string representation of the date/time, specified as a - /// null-terminated UTF-8 string. - /// - /// @param binValue [out] A buffer in which to return the binary date/time value. - - static void ConvertToDate ( XMP_StringPtr strValue, - XMP_DateTime * binValue ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToDate() converts a string to a date/time value. - /// - /// Overloads the basic form of the function, allowing you to pass a string object, - /// rather than a const * char. It is otherwise identical. - /// See details for the canonical form. - /// - /// - /// @param strValue The ISO 8601 string representation of the date/time, specified as a string - /// object. - /// - /// @param binValue [out] A buffer in which to return the binary date/time value. - - static void ConvertToDate ( const tStringObj & strValue, - XMP_DateTime * binValue ); - - /// @} - - // ============================================================================================= - /// \name Date-time manipulation - /// @{ - /// - /// In addition to the type-conversion functions that convert between strings and binary - /// date-time values, these functions create, manipulate, and compare date-time values. - - // --------------------------------------------------------------------------------------------- - /// @brief \c CurrentDateTime() obtains the current date and time. - /// - /// Creates and returns a binary \c #XMP_DateTime value. The returned time is UTC, properly - /// adjusted for the local time zone. The resolution of the time is not guaranteed to be finer - /// than seconds. - /// - /// @param time [out] A buffer in which to return the date/time value. - - static void CurrentDateTime ( XMP_DateTime * time ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SetTimeZone() sets the time zone in a date/time value to the local time zone. - /// - /// Any existing time zone value is replaced. The other date/time fields are not adjusted in any way. - /// - /// @param time A pointer to the date-time value, which is modified in place. - - static void SetTimeZone ( XMP_DateTime * time ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToUTCTime() ensures that a time is UTC. - /// - /// If the time zone is not UTC, the time is adjusted and the time zone set to be UTC. If the - /// time zone is already UTC, the value is not modified. - /// - /// @param time A pointer to the date-time value, which is modified in place. - - static void ConvertToUTCTime ( XMP_DateTime * time ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c ConvertToLocalTime() ensures that a time is local. - /// - /// If the time zone is not the local zone, the time is adjusted and the time zone set to be local. - /// If the time zone is already the local zone, the value is not modified. - /// - /// @param time A pointer to the date-time value, which is modified in place. - - static void ConvertToLocalTime ( XMP_DateTime * time ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c CompareDateTime() compares the order of two date/time values. - /// - /// @param left The left-side date/time value. - /// - /// @param right The right-side date/time value. - /// - /// @return An integer indicating the order: - /// \li -1 if left is earlier than right - /// \li 0 if left matches right - /// \li +1 if left is later than right - - static int CompareDateTime ( const XMP_DateTime & left, - const XMP_DateTime & right ); - - /// @} - - // ============================================================================================= - /// \name Base64 encoding and decoding - /// @{ - /// - /// These functions convert between raw data values and Base64-encoded strings. - - // --------------------------------------------------------------------------------------------- - /// @brief \c EncodeToBase64() converts a raw data value to a Base64-encoded string. - /// - /// @param rawStr An \c #XMP_StringPtr (char *) string containing the raw data to be converted. - /// - /// @param rawLen The number of characters of raw data to be converted. - /// - /// @param encodedStr [out] A string object in which to return the encoded string. - - static void EncodeToBase64 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - tStringObj * encodedStr ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c EncodeToBase64() converts a raw data value passed in a string object to a Base64-encoded string. - /// - /// Overloads the basic form of the function, allowing you to pass a string object as input. - /// It is otherwise identical. - /// - /// @param rawStr A string object containing the raw data to be converted. - /// - /// @param encodedStr [out] A string object in which to return the encoded string. - - static void EncodeToBase64 ( const tStringObj & rawStr, - tStringObj * encodedStr ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DecodeFromBase64() Decodes a Base64-encoded string to raw data. - /// - /// @param encodedStr An \c #XMP_StringPtr (char *) string containing the encoded data to be converted. - /// - /// @param encodedLen The number of characters of raw data to be converted. - /// - /// @param rawStr [out] A string object in which to return the decoded data. - - static void DecodeFromBase64 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - tStringObj * rawStr ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DecodeFromBase64() Decodes a Base64-encoded string, passed as a string object, to raw data. - /// - /// Overloads the basic form of the function, allowing you to pass a string object as input. - /// It is otherwise identical. - /// - /// @param encodedStr An string object containing the encoded data to be converted. - /// - /// @param rawStr [out] A string object in which to return the decoded data. - - static void DecodeFromBase64 ( const tStringObj & encodedStr, - tStringObj * rawStr ); - - /// @} - - // ============================================================================================= - // ============================================================================================= - /// \name JPEG file handling - /// @{ - /// - /// These functions support the partitioning of XMP in JPEG files into standard and extended - /// portions in order to work around the 64KB size limit of JPEG marker segments. - /// - /// @note (Doc note) Add detail about how to write out and read back extended data - - // --------------------------------------------------------------------------------------------- - /// @brief \c PackageForJPEG() creates XMP serializations appropriate for a JPEG file. - /// - /// The standard XMP in a JPEG file is limited to 64K bytes. This function serializes the XMP - /// metadata in an XMP object into a string of RDF (see \c TXMPMeta::SerializeToBuffer()). If - /// the data does not fit into the 64K byte limit, it creates a second packet string with the - /// extended data. - /// - /// @param xmpObj The XMP object containing the metadata. - /// - /// @param standardXMP [out] A string object in which to return the full standard XMP packet. - /// - /// @param extendedXMP [out] A string object in which to return the serialized extended XMP, - /// empty if not needed. - /// - /// @param extendedDigest [out] A string object in which to return an MD5 digest of the serialized - /// extended XMP, empty if not needed. - /// - /// @see \c MergeFromJPEG() - - static void PackageForJPEG ( const TXMPMeta & xmpObj, - tStringObj * standardXMP, - tStringObj * extendedXMP, - tStringObj * extendedDigest ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c MergeFromJPEG() merges standard and extended XMP retrieved from a JPEG file. - /// - /// When an extended partition stores properties that do not fit into the JPEG file limitation - /// of 64K bytes, this function integrates those properties back into the same XMP object with - /// those from the standard XMP packet. - /// - /// @param fullXMP [in, out] An XMP object which the caller has initialized from the standard - /// XMP packet in a JPEG file. The extended XMP is added to this object. - /// - /// @param extendedXMP An XMP object which the caller has initialized from the extended XMP - /// packet in a JPEG file. - /// - /// @see \c PackageForJPEG() - - static void MergeFromJPEG ( TXMPMeta * fullXMP, - const TXMPMeta & extendedXMP ); - - /// @} - - // ============================================================================================= - /// \name Editing utilities - /// @{ - /// - /// These functions are useful in implementing a user interface for editing XMP. They - /// convert sets of property values to and from displayable and manipulable strings, and perform - /// operations on sets of metadata, such as those available from the File Info dialog box. - - // --------------------------------------------------------------------------------------------- - /// @brief \c CatenateArrayItems() creates a single edit string from a set of array item values. - /// - /// Collects the values of all items in an array into a single string, using a specified - /// separation string. Each item in the specified array must be a simple string value. - /// - /// @param xmpObj The XMP object containing the array to be catenated. - /// - /// @param schemaNS The schema namespace URI for the array. Must not be null or the empty string. - /// - /// @param arrayName The name of the array. May be a general path expression, must not be null - /// or the empty string. - /// - /// @param separator The string with which to separate the items in the catenated string. - /// Defaults to "; ", ASCII semicolon and space (U+003B, U+0020). - /// - /// @param quotes The character or characters to use as quotes around array items that contain a - /// separator. Defaults to the double-quote character ("), ASCII quote (U+0022). - /// - /// @param options Option flags to control the catenation. <> - /// - /// @param catedStr [out] A string object in which to return the catenated array items. - /// - /// @see \c SeparateArrayItems() - - static void CatenateArrayItems ( const TXMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr separator, - XMP_StringPtr quotes, - XMP_OptionBits options, - tStringObj * catedStr ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SeparateArrayItems() updates an array from a concatenated edit string of values. - /// - /// This reverses the action of \c CatenateArrayItems(), separating out individual array items - /// from the edit string and updating the array with the new values. Each item in the array must - /// be a simple string value. - /// - /// @param xmpObj The XMP object containing the array to be updated. - /// - /// @param schemaNS The schema namespace URI for the array. Must not be null or the empty string. - /// - /// @param arrayName The name of the array. May be a general path expression, must not be null - /// or the empty string. - /// - /// @param options Option flags to control the separation. <> - /// - /// @param catedStr The concatenated array items, as created by \c CatenateArrayItems(), - /// specified as a null-terminated UTF-8 string. - - static void SeparateArrayItems ( TXMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c SeparateArrayItems() updates an array from a concatenated edit string of values. - /// - /// Overloads the basic form of the function, allowing you to pass a string object in which - /// to return the concatenated string. It is otherwise identical; see details for the canonical form. - /// - - static void SeparateArrayItems ( TXMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - const tStringObj & catedStr ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c RemoveProperties() removes multiple properties from an XMP object. - /// - /// The operation depends on how the namespace and property are specified: - /// - /// \li Non-empty \c schemaNS and \c propName - The named property is removed if it is an - /// external property, or if the \c #kXMPUtil_DoAllProperties option flag is set. It does not - /// matter whether the named property is an actual property or an alias. - /// - /// \li Non-empty \c schemaNS and empty \c propName - All external properties in the named - /// schema are removed. Internal properties are also removed if the - /// \c #kXMPUtil_DoAllProperties option flag is set. In addition, aliases from the named schema - /// are removed if the \c #kXMPUtil_IncludeAliases option flag is set. - /// - /// \li Empty \c schemaNS and empty \c propName - All external properties in all schemas are - /// removed. Internal properties are also removed if the \c #kXMPUtil_DoAllProperties option - /// flag is set. Aliases are handled implicitly, because the associated actuals are removed or - /// not. - /// - /// \li It is an error to pass an empty \c schemaNS and non-empty \c propName. - /// - /// @param xmpObj The XMP object containing the properties to be removed. - /// - /// @param schemaNS Optional schema namespace URI for the properties to be removed. - /// - /// @param propName Optional path expression for the property to be removed. - /// - /// @param options Option flags to control the deletion operation. A logical OR of these - /// bit-flag constants: - /// \li \c #kXMPUtil_DoAllProperties - Delete internal properties in addition to external properties. - /// \li \c #kXMPUtil_IncludeAliases - Include aliases if the schema is explicitly specified. - - static void RemoveProperties ( TXMPMeta * xmpObj, - XMP_StringPtr schemaNS = 0, - XMP_StringPtr propName = 0, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c AppendProperties() adds or moves properties from one XMP object to another. - /// - /// The default operation is to append only external properties that do not already exist in the - /// destination. Option flags allow you to add internal properties, and to merge values of - /// properties that exist in both the source and destination. - /// - /// \li \c #kXMPUtil_DoAllProperties: Operate on all top-level properties, external and - /// internal. You can use this flag together with \c #kXMPUtil_ReplaceOldValues to replace the - /// values of existing top-level properties. - /// - /// \li \c #kXMPUtil_ReplaceOldValues: Propagate all top-level properties from the source to - /// the destination, replacing any existing values. The values of properties in the - /// destination that are not in the source are not modified.
- /// The keep-or-replace-old notion also applies within structs and arrays. Top-level - /// properties are added to the destination if they do not already exist. If they do exist but - /// differ in form (simple/struct/array) then the destination is not modified. If the forms - /// match, simple properties are left unchanged, while structs and arrays are merged.
- /// Do not use this option when the processing is more complicated. <> - /// - /// \li \c #kXMPUtil_DeleteEmptyValues: An empty value in the source XMP causes the - /// corresponding destination property to be deleted. By default, empty values are treated in - /// the same way as non-empty values. An empty value is a simple empty string, an array with - /// no items,or a struct with no fields. Qualifiers are ignored. - /// - /// The detailed behavior is defined by the following pseudo-code: - /// - ///
-    /// AppendProperties ( sourceXMP, destXMP, options ):
-    ///    doAll = options & kXMPUtil_DoAllProperties
-    ///    replaceOld = options & kXMPUtil_ReplaceOldValues
-    ///    deleteEmpty = options & kXMPUtil_DeleteEmptyValues
-    ///    for all source schema (top level namespaces):
-    ///    for all top level properties in sourceSchema:
-    ///    if doAll or prop is external:
-    ///       AppendSubtree ( sourceNode, destSchema, replaceOld, deleteEmpty )
-    ///
-    /// AppendSubtree ( sourceNode, destParent, replaceOld, deleteEmpty ):
-    ///    if deleteEmpty and source value is empty:
-    ///       delete the corresponding child from destParent
-    ///    else if sourceNode not in destParent (by name):
-    ///       copy sourceNode's subtree to destParent
-    ///    else if replaceOld:
-    ///       delete subtree from destParent
-    ///       copy sourceNode's subtree to destParent
-    ///    else: // (Already exists in dest and not replacing, merge structs and arrays)
-    ///       if sourceNode and destNode forms differ:
-    ///          return, leave the destNode alone
-    ///       else if form is a struct:
-    ///          for each field in sourceNode:
-    ///             AppendSubtree ( sourceNode.field, destNode, replaceOld )
-    ///       else if form is an alt-text array:
-    ///          copy new items by xml:lang value into the destination
-    ///       else if form is an array:
-    ///          copy new items by value into the destination, ignoring order and duplicates
-    /// 
- /// - /// Array item checking is n-squared; this can be time-intensive if the replace-old options is - /// not specified. Each source item is checked to see if it already exists in the destination, - /// without regard to order or duplicates. Simple items are compared by value and \c xml:lang - /// qualifier; other qualifiers are ignored. Structs are recursively compared by field names, - /// without regard to field order. Arrays are compared by recursively comparing all items. - /// - /// @param source The source XMP object. - /// - /// @param dest The destination XMP object. - /// - /// @param options Option flags to control the copying. A logical OR of these bit-flag constants: - /// \li \c kXMPUtil_DoAllProperties - Operate on internal properties in addition to external properties. - /// \li \c kXMPUtil_ReplaceOldValues - Replace the values of existing properties. - /// \li \c kXMPUtil_DeleteEmptyValues - Delete properties if the new value is empty. - - static void AppendProperties ( const TXMPMeta & source, - TXMPMeta * dest, - XMP_OptionBits options = 0 ); - - // --------------------------------------------------------------------------------------------- - /// @brief \c DuplicateSubtree() replicates a subtree from one XMP object into another. - /// - /// The destination can be a different namespace and root location in the same object, or the - /// same or a different location in another XMP object. - /// - /// @param source The source XMP object. - /// - /// @param dest The destination XMP object. - /// - /// @param sourceNS The schema namespace URI for the source subtree. - /// - /// @param sourceRoot The root location for the source subtree. Can be a general path expression, - /// must not be null or the empty string. - /// - /// @param destNS The schema namespace URI for the destination. Defaults to the source namespace. - /// - /// @param destRoot The root location for the destination. Can be a general path expression. - /// Defaults to the source location. - /// - /// @param options Option flags to control the operation. <> - - static void DuplicateSubtree ( const TXMPMeta & source, - TXMPMeta * dest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS = 0, - XMP_StringPtr destRoot = 0, - XMP_OptionBits options = 0 ); - - /// @} - - // ============================================================================================= - - // ============================================================================================= - -}; // class TXMPUtils - -// ================================================================================================= - -#endif // __TXMPUtils_hpp__ diff --git a/xmpsdk/include/XMP.incl_cpp b/xmpsdk/include/XMP.incl_cpp deleted file mode 100644 index 6501be9c73..0000000000 --- a/xmpsdk/include/XMP.incl_cpp +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef __XMP_incl_cpp__ -#define __XMP_incl_cpp__ 1 - -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2007 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. -// ================================================================================================= - -// ================================================================================================ -/// \file XMP.incl_cpp -/// \brief Overall client glue file for the XMP toolkit. -/// -/// This is an overall client source file of XMP toolkit glue, the only XMP-specific one that -/// clients should build in projects. This ensures that all of the client-side glue code for the -/// XMP toolkit gets compiled. -/// -/// You cannot compile this file directly, because the template's string type must be declared and -/// only the client can do that. Instead, include this in some other source file. For example, -/// to use std::string you only need these two lines: -/// -/// \code -/// #include -/// #include "XMP.incl_cpp" -/// \endcode - - -#include "XMPSDK.hpp" // ! This must be the first include! - -#define XMP_ClientBuild 1 - -#ifdef _MSC_VER - #if XMP_DebugBuild - #pragma warning ( push, 4 ) - #else - #pragma warning ( push, 3 ) - #endif - #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced - #pragma warning ( disable : 4702 ) // unreachable code - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) -#endif - -#if defined ( TXMP_STRING_TYPE ) && (! TXMP_EXPAND_INLINE) - - // We're using a single out of line instantiation. Do it here. - - #include "client-glue/TXMPMeta.incl_cpp" - #include "client-glue/TXMPIterator.incl_cpp" - #include "client-glue/TXMPUtils.incl_cpp" - template class TXMPMeta ; - template class TXMPIterator ; - template class TXMPUtils ; - -#endif - -#ifdef _MSC_VER - #pragma warning ( pop ) -#endif - -#endif // __XMP_incl_cpp__ diff --git a/xmpsdk/include/XMPSDK.hpp b/xmpsdk/include/XMPSDK.hpp deleted file mode 100644 index 229714f8d8..0000000000 --- a/xmpsdk/include/XMPSDK.hpp +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef __XMP_hpp__ -#define __XMP_hpp__ 1 - -// ================================================================================================= -// Copyright 2002-2007 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. -// ================================================================================================= - -// ================================================================================================ -/// \file XMPSDK.hpp -/// \brief Overall header file for the XMP Toolkit -/// -/// This is an overall header file, the only one that C++ clients should include. -/// -/// The full client API is in the \c TXMPMeta.hpp, \c TXMPIterator.hpp, \c TXMPUtils.hpp headers. -/// Read these for information, but do not include them directly. The \c TXMP... classes are C++ -/// template classes that must be instantiated with a string class such as \c std::string. The -/// string class is used to return text strings for property values, serialized XMP, and so on. -/// Clients must also compile \c XMP.incl_cpp to ensure that all client-side glue code is generated. -/// This should be done by including it in exactly one client source file. -/// -/// There are two C preprocessor macros that simplify use of the templates: -/// -/// \li \c TXMP_STRING_TYPE - Define this as the string class to use with the template. You will get -/// the template headers included and typedefs (\c SXMPMeta, and so on) to use in your code. -/// -/// \li \c TXMP_EXPAND_INLINE - Define this as 1 if you want to have the template functions expanded -/// inline in your code. Leave it undefined, or defined as 0, to use out-of-line instantiations of -/// the template functions. Compiling \c XMP.incl_cpp generates explicit out-of-line -/// instantiations if \c TXMP_EXPAND_INLINE is off. -/// -/// The template parameter, class \c tStringObj, must have the following member functions (which -/// match those for \c std::string): -/// -///
-///  tStringObj& assign ( const char * str, size_t len )
-///  size_t size() const
-///  const char * c_str() const
-/// 
-/// -/// The string class must be suitable for at least UTF-8. This is the encoding used for all general -/// values, and is the default encoding for serialized XMP. The string type must also be suitable -/// for UTF-16 or UTF-32 if those serialization encodings are used. This mainly means tolerating -/// embedded 0 bytes, which \c std::string does. -// ================================================================================================ - -/// /c XMP_Environment.h must be the first included header. -#include "XMP_Environment.h" - -#include "XMP_Version.h" -#include "XMP_Const.h" - -#ifdef _MSC_VER - #if XMP_DebugBuild - #pragma warning ( push, 4 ) - #else - #pragma warning ( push, 3 ) - #endif - #pragma warning ( disable : 4702 ) // unreachable code - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) -#endif - -#if defined ( TXMP_STRING_TYPE ) - - #include "TXMPMeta.hpp" - #include "TXMPIterator.hpp" - #include "TXMPUtils.hpp" - typedef class TXMPMeta SXMPMeta; // For client convenience. - typedef class TXMPIterator SXMPIterator; - typedef class TXMPUtils SXMPUtils; - #if TXMP_EXPAND_INLINE - #error "TXMP_EXPAND_INLINE is not working at present. Please don't use it." - #include "client-glue/TXMPMeta.incl_cpp" - #include "client-glue/TXMPIterator.incl_cpp" - #include "client-glue/TXMPUtils.incl_cpp" - #endif - -#endif // TXMP_STRING_TYPE - -#ifdef _MSC_VER - #pragma warning ( pop ) -#endif - -// ================================================================================================= - -#endif // __XMP_hpp__ diff --git a/xmpsdk/include/XMP_Const.h b/xmpsdk/include/XMP_Const.h deleted file mode 100644 index e84e18fd0d..0000000000 --- a/xmpsdk/include/XMP_Const.h +++ /dev/null @@ -1,1311 +0,0 @@ -#ifndef __XMP_Const_h__ -#define __XMP_Const_h__ 1 - -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" - -#include -#include - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= -/// \file XMP_Const.h -/// \brief Common C/C++ types and constants for the XMP toolkit. -// ================================================================================================= - -// ================================================================================================= -// Basic types and constants -// ========================= - -// The XMP_... types are used on the off chance that the ..._t types present a problem. In that -// case only the declarations of the XMP_... types needs to change, not all of the uses. These -// types are used where fixed sizes are required in order to have a known ABI for a DLL build. - -typedef int8_t XMP_Int8; -typedef int16_t XMP_Int16; -typedef int32_t XMP_Int32; -typedef int64_t XMP_Int64; - -typedef uint8_t XMP_Uns8; -typedef uint16_t XMP_Uns16; -typedef uint32_t XMP_Uns32; -typedef uint64_t XMP_Uns64; - -typedef XMP_Uns8 XMP_Bool; - -/// An "ABI safe" pointer to the internal part of an XMP object. Use to pass an XMP object across -/// client DLL boundaries. See \c TXMPMeta::GetInternalRef(). -typedef struct __XMPMeta__ * XMPMetaRef; - -/// An "ABI safe" pointer to the internal part of an XMP iteration object. Use to pass an XMP -/// iteration object across client DLL boundaries. See \c TXMPIterator. -typedef struct __XMPIterator__ * XMPIteratorRef; - -/// An "ABI safe" pointer to the internal part of an XMP document operations object. Use to pass an -/// XMP document operations object across client DLL boundaries. See \c TXMPDocOps. -typedef struct __XMPDocOps__ * XMPDocOpsRef; - -/// An "ABI safe" pointer to the internal part of an XMP file-handling object. Use to pass an XMP -/// file-handling object across client DLL boundaries. See \c TXMPFiles. -typedef struct __XMPFiles__ * XMPFilesRef; - -// ================================================================================================= - -/// \name General scalar types and constants -/// @{ - -/// \typedef XMP_StringPtr -/// \brief The type for input string parameters. A const char *, a null-terminated UTF-8 -/// string. - -/// \typedef XMP_StringLen -/// \brief The type for string length parameters. A 32-bit unsigned integer, as big as will be -/// practically needed. - -/// \typedef XMP_Index -/// \brief The type for offsets and indices. A 32-bit signed integer. It is signed to allow -1 for -/// loop termination. - -/// \typedef XMP_OptionBits -/// \brief The type for a collection of 32 flag bits. Individual flags are defined as enum value bit -/// masks; see \c #kXMP_PropValueIsURI and following. A number of macros provide common set or set -/// operations, such as \c XMP_PropIsSimple. For other tests use an expression like options & -/// kXMP_. When passing multiple option flags use the bitwise-OR operator. '|', -/// not the arithmatic plus, '+'. - -typedef const char * XMP_StringPtr; // Points to a null terminated UTF-8 string. -typedef XMP_Uns32 XMP_StringLen; -typedef XMP_Int32 XMP_Index; // Signed, sometimes -1 is handy. -typedef XMP_Uns32 XMP_OptionBits; // Used as 32 individual bits. - -/// \def kXMP_TrueStr -/// \brief The canonical true string value for Booleans in serialized XMP. -/// -/// Code that converts from string to bool should be case insensitive, and also allow "1". - -/// \def kXMP_FalseStr -/// \brief The canonical false string value for Booleans in serialized XMP. -/// -/// Code that converts from string to bool should be case insensitive, and also allow "0". - -#define kXMP_TrueStr "True" // Serialized XMP spellings, not for the type bool. -#define kXMP_FalseStr "False" - -/// Type for yes/no/maybe answers. The values are picked to allow Boolean-like usage. The yes and -/// values are true (non-zero), the no value is false (zero). -enum { - /// The part or parts have definitely changed. - kXMPTS_Yes = 1, - /// The part or parts have definitely not changed. - kXMPTS_No = 0, - /// The part or parts might, or might not, have changed. - kXMPTS_Maybe = -1 -}; -typedef XMP_Int8 XMP_TriState; - -/// @} - -// ================================================================================================= - -/// \struct XMP_DateTime -/// \brief The expanded type for a date and time. -/// -/// Dates and time in the serialized XMP are ISO 8601 strings. The \c XMP_DateTime struct allows -/// easy conversion with other formats. -/// -/// All of the fields are 32 bit, even though most could be 8 bit. This avoids overflow when doing -/// carries for arithmetic or normalization. All fields have signed values for the same reasons. -/// -/// Date-time values are occasionally used with only a date or only a time component. A date without -/// a time has zeros in the \c XMP_DateTime struct for all time fields. A time without a date has -/// zeros for all date fields (year, month, and day). -/// -/// \c TXMPUtils provides utility functions for manipulating date-time values. -/// -/// @see \c TXMPUtils::ConvertToDate(), \c TXMPUtils::ConvertFromDate(), -/// \c TXMPUtils::CompareDateTime(), \c TXMPUtils::ConvertToLocalTime(), -/// \c TXMPUtils::ConvertToUTCTime(), \c TXMPUtils::CurrentDateTime(), -/// \c TXMPUtils::SetTimeZone() - -struct XMP_DateTime { - - /// The year, can be negative. - XMP_Int32 year; - - /// The month in the range 1..12. - XMP_Int32 month; - - /// The day of the month in the range 1..31. - XMP_Int32 day; - - /// The hour in the range 0..23. - XMP_Int32 hour; - - /// The minute in the range 0..59. - XMP_Int32 minute; - - /// The second in the range 0..59. - XMP_Int32 second; - - /// The "sign" of the time zone, \c #kXMP_TimeIsUTC (0) means UTC, \c #kXMP_TimeWestOfUTC (-1) - /// is west, \c #kXMP_TimeEastOfUTC (+1) is east. - XMP_Int32 tzSign; - - /// The time zone hour in the range 0..23. - XMP_Int32 tzHour; - - /// The time zone minute in the range 0..59. - XMP_Int32 tzMinute; - - /// Nanoseconds within a second, often left as zero. - XMP_Int32 nanoSecond; - -}; - -/// Constant values for \c XMP_DateTime::tzSign field. -enum { - /// Time zone is west of UTC. - kXMP_TimeWestOfUTC = -1, - /// UTC time. - kXMP_TimeIsUTC = 0, - /// Time zone is east of UTC. - kXMP_TimeEastOfUTC = +1 -}; - -// ================================================================================================= -// Standard namespace URI constants -// ================================ - -/// \name XML namespace constants for standard XMP schema. -/// @{ -/// -/// \def kXMP_NS_XMP -/// \brief The XML namespace for the XMP "basic" schema. -/// -/// \def kXMP_NS_XMP_Rights -/// \brief The XML namespace for the XMP copyright schema. -/// -/// \def kXMP_NS_XMP_MM -/// \brief The XML namespace for the XMP digital asset management schema. -/// -/// \def kXMP_NS_XMP_BJ -/// \brief The XML namespace for the job management schema. -/// -/// \def kXMP_NS_XMP_T -/// \brief The XML namespace for the XMP text document schema. -/// -/// \def kXMP_NS_XMP_T_PG -/// \brief The XML namespace for the XMP paged document schema. -/// -/// \def kXMP_NS_PDF -/// \brief The XML namespace for the PDF schema. -/// -/// \def kXMP_NS_Photoshop -/// \brief The XML namespace for the Photoshop custom schema. -/// -/// \def kXMP_NS_EXIF -/// \brief The XML namespace for Adobe's EXIF schema. -/// -/// \def kXMP_NS_TIFF -/// \brief The XML namespace for Adobe's TIFF schema. -/// -/// @} - -#define kXMP_NS_XMP "http://ns.adobe.com/xap/1.0/" - -#define kXMP_NS_XMP_Rights "http://ns.adobe.com/xap/1.0/rights/" -#define kXMP_NS_XMP_MM "http://ns.adobe.com/xap/1.0/mm/" -#define kXMP_NS_XMP_BJ "http://ns.adobe.com/xap/1.0/bj/" - -#define kXMP_NS_PDF "http://ns.adobe.com/pdf/1.3/" -#define kXMP_NS_Photoshop "http://ns.adobe.com/photoshop/1.0/" -#define kXMP_NS_PSAlbum "http://ns.adobe.com/album/1.0/" -#define kXMP_NS_EXIF "http://ns.adobe.com/exif/1.0/" -#define kXMP_NS_EXIF_Aux "http://ns.adobe.com/exif/1.0/aux/" -#define kXMP_NS_TIFF "http://ns.adobe.com/tiff/1.0/" -#define kXMP_NS_PNG "http://ns.adobe.com/png/1.0/" -#define kXMP_NS_SWF "http://ns.adobe.com/swf/1.0/" -#define kXMP_NS_JPEG "http://ns.adobe.com/jpeg/1.0/" -#define kXMP_NS_JP2K "http://ns.adobe.com/jp2k/1.0/" -#define kXMP_NS_CameraRaw "http://ns.adobe.com/camera-raw-settings/1.0/" -#define kXMP_NS_DM "http://ns.adobe.com/xmp/1.0/DynamicMedia/" -#define kXMP_NS_ASF "http://ns.adobe.com/asf/1.0/" -#define kXMP_NS_WAV "http://ns.adobe.com/xmp/wav/1.0/" - -#define kXMP_NS_XMP_Note "http://ns.adobe.com/xmp/note/" - -#define kXMP_NS_AdobeStockPhoto "http://ns.adobe.com/StockPhoto/1.0/" -#define kXMP_NS_CreatorAtom "http://ns.adobe.com/creatorAtom/1.0/" - -/// \name XML namespace constants for qualifiers and structured property fields. -/// @{ -/// -/// \def kXMP_NS_XMP_IdentifierQual -/// \brief The XML namespace for qualifiers of the xmp:Identifier property. -/// -/// \def kXMP_NS_XMP_Dimensions -/// \brief The XML namespace for fields of the Dimensions type. -/// -/// \def kXMP_NS_XMP_Image -/// \brief The XML namespace for fields of a graphical image. Used for the Thumbnail type. -/// -/// \def kXMP_NS_XMP_ResourceEvent -/// \brief The XML namespace for fields of the ResourceEvent type. -/// -/// \def kXMP_NS_XMP_ResourceRef -/// \brief The XML namespace for fields of the ResourceRef type. -/// -/// \def kXMP_NS_XMP_ST_Version -/// \brief The XML namespace for fields of the Version type. -/// -/// \def kXMP_NS_XMP_ST_Job -/// \brief The XML namespace for fields of the JobRef type. -/// -/// @} - -#define kXMP_NS_XMP_IdentifierQual "http://ns.adobe.com/xmp/Identifier/qual/1.0/" -#define kXMP_NS_XMP_Dimensions "http://ns.adobe.com/xap/1.0/sType/Dimensions#" -#define kXMP_NS_XMP_Text "http://ns.adobe.com/xap/1.0/t/" -#define kXMP_NS_XMP_PagedFile "http://ns.adobe.com/xap/1.0/t/pg/" -#define kXMP_NS_XMP_Graphics "http://ns.adobe.com/xap/1.0/g/" -#define kXMP_NS_XMP_Image "http://ns.adobe.com/xap/1.0/g/img/" -#define kXMP_NS_XMP_Font "http://ns.adobe.com/xap/1.0/sType/Font#" -#define kXMP_NS_XMP_ResourceEvent "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" -#define kXMP_NS_XMP_ResourceRef "http://ns.adobe.com/xap/1.0/sType/ResourceRef#" -#define kXMP_NS_XMP_ST_Version "http://ns.adobe.com/xap/1.0/sType/Version#" -#define kXMP_NS_XMP_ST_Job "http://ns.adobe.com/xap/1.0/sType/Job#" -#define kXMP_NS_XMP_ManifestItem "http://ns.adobe.com/xap/1.0/sType/ManifestItem#" - -// Deprecated XML namespace constants -#define kXMP_NS_XMP_T "http://ns.adobe.com/xap/1.0/t/" -#define kXMP_NS_XMP_T_PG "http://ns.adobe.com/xap/1.0/t/pg/" -#define kXMP_NS_XMP_G_IMG "http://ns.adobe.com/xap/1.0/g/img/" - -/// \name XML namespace constants from outside Adobe. -/// @{ -/// -/// \def kXMP_NS_DC -/// \brief The XML namespace for the Dublin Core schema. -/// -/// \def kXMP_NS_IPTCCore -/// \brief The XML namespace for the IPTC Core schema. -/// -/// \def kXMP_NS_RDF -/// \brief The XML namespace for RDF. -/// -/// \def kXMP_NS_XML -/// \brief The XML namespace for XML. -/// -/// @} - -#define kXMP_NS_DC "http://purl.org/dc/elements/1.1/" - -#define kXMP_NS_IPTCCore "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" - -#define kXMP_NS_DICOM "http://ns.adobe.com/DICOM/" - -#define kXMP_NS_PDFA_Schema "http://www.aiim.org/pdfa/ns/schema#" -#define kXMP_NS_PDFA_Property "http://www.aiim.org/pdfa/ns/property#" -#define kXMP_NS_PDFA_Type "http://www.aiim.org/pdfa/ns/type#" -#define kXMP_NS_PDFA_Field "http://www.aiim.org/pdfa/ns/field#" -#define kXMP_NS_PDFA_ID "http://www.aiim.org/pdfa/ns/id/" -#define kXMP_NS_PDFA_Extension "http://www.aiim.org/pdfa/ns/extension/" - -#define kXMP_NS_PDFX "http://ns.adobe.com/pdfx/1.3/" -#define kXMP_NS_PDFX_ID "http://www.npes.org/pdfx/ns/id/" - -#define kXMP_NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#" -#define kXMP_NS_XML "http://www.w3.org/XML/1998/namespace" - -// ================================================================================================= -// Enums and macros used for option bits -// ===================================== - -/// \name Macros for standard option selections. -/// @{ -/// -/// \def kXMP_ArrayLastItem -/// \brief Options macro accesses last array item. -/// -/// \def kXMP_UseNullTermination -/// \brief Options macro sets string style. -/// -/// \def kXMP_NoOptions -/// \brief Options macro clears all property-type bits. -/// -/// @} - -#define kXMP_ArrayLastItem ((XMP_Index)(-1L)) -#define kXMP_UseNullTermination ((XMP_StringLen)(~0UL)) -#define kXMP_NoOptions ((XMP_OptionBits)0UL) - -/// \name Macros for setting and testing general option bits. -/// @{ -/// -/// \def XMP_SetOption -/// \brief Macro sets an option flag bit. -/// \param var A variable storing an options flag. -/// \param opt The bit-flag constant to set. -/// -/// \def XMP_ClearOption -/// \brief Macro clears an option flag bit. -/// \param var A variable storing an options flag. -/// \param opt The bit-flag constant to clear. -/// -/// \def XMP_TestOption -/// \brief Macro reports whether an option flag bit is set. -/// \param var A variable storing an options flag. -/// \param opt The bit-flag constant to test. -/// \return True if the bit is set. -/// -/// \def XMP_OptionIsSet -/// \brief Macro reports whether an option flag bit is set. -/// \param var A variable storing an options flag. -/// \param opt The bit-flag constant to test. -/// \return True if the bit is set. -/// -/// \def XMP_OptionIsClear -/// \brief Macro reports whether an option flag bit is clear. -/// \param var A variable storing an options flag. -/// \param opt The bit-flag constant to test. -/// \return True if the bit is clear. -/// -/// @} - -#define XMP_SetOption(var,opt) var |= (opt) -#define XMP_ClearOption(var,opt) var &= ~(opt) -#define XMP_TestOption(var,opt) (((var) & (opt)) != 0) -#define XMP_OptionIsSet(var,opt) (((var) & (opt)) != 0) -#define XMP_OptionIsClear(var,opt) (((var) & (opt)) == 0) - -/// \name Macros for setting and testing specific option bits. -/// @{ -/// -/// \def XMP_PropIsSimple -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_PropIsStruct -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_PropIsArray -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_ArrayIsUnordered -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_ArrayIsOrdered -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_ArrayIsAlternate -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_ArrayIsAltText -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_PropHasQualifiers -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_PropIsQualifier -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_PropHasLang -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_NodeIsSchema -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// \def XMP_PropIsAlias -/// \brief Macro reports the property type specified by an options flag. -/// \param opt The options flag to check. -/// -/// @} - -#define XMP_PropIsSimple(opt) (((opt) & kXMP_PropCompositeMask) == 0) -#define XMP_PropIsStruct(opt) (((opt) & kXMP_PropValueIsStruct) != 0) -#define XMP_PropIsArray(opt) (((opt) & kXMP_PropValueIsArray) != 0) - -#define XMP_ArrayIsUnordered(opt) (((opt) & kXMP_PropArrayIsOrdered) == 0) -#define XMP_ArrayIsOrdered(opt) (((opt) & kXMP_PropArrayIsOrdered) != 0) -#define XMP_ArrayIsAlternate(opt) (((opt) & kXMP_PropArrayIsAlternate) != 0) -#define XMP_ArrayIsAltText(opt) (((opt) & kXMP_PropArrayIsAltText) != 0) - -#define XMP_PropHasQualifiers(opt) (((opt) & kXMP_PropHasQualifiers) != 0) -#define XMP_PropIsQualifier(opt) (((opt) & kXMP_PropIsQualifier) != 0) -#define XMP_PropHasLang(opt) (((opt) & kXMP_PropHasLang) != 0) - -#define XMP_NodeIsSchema(opt) (((opt) & kXMP_SchemaNode) != 0) -#define XMP_PropIsAlias(opt) (((opt) & kXMP_PropIsAlias) != 0) - -// ------------------------------------------------------------------------------------------------- - -/// Option bit flags for the \c TXMPMeta property accessor functions. -enum { - - /// The XML string form of the property value is a URI, use rdf:resource attribute. DISCOURAGED - kXMP_PropValueIsURI = 0x00000002UL, - - // ------------------------------------------------------ - // Options relating to qualifiers attached to a property. - - /// The property has qualifiers, includes \c rdf:type and \c xml:lang. - kXMP_PropHasQualifiers = 0x00000010UL, - - /// This is a qualifier for some other property, includes \c rdf:type and \c xml:lang. - /// Qualifiers can have arbitrary structure, and can themselves have qualifiers. If the - /// qualifier itself has a structured value, this flag is only set for the top node of the - /// qualifier's subtree. - kXMP_PropIsQualifier = 0x00000020UL, - - /// Implies \c #kXMP_PropHasQualifiers, property has \c xml:lang. - kXMP_PropHasLang = 0x00000040UL, - - /// Implies \c #kXMP_PropHasQualifiers, property has \c rdf:type. - kXMP_PropHasType = 0x00000080UL, - - // -------------------------------------------- - // Options relating to the data structure form. - - /// The value is a structure with nested fields. - kXMP_PropValueIsStruct = 0x00000100UL, - - /// The value is an array (RDF alt/bag/seq). The "ArrayIs..." flags identify specific types - /// of array; default is a general unordered array, serialized using an \c rdf:Bag container. - kXMP_PropValueIsArray = 0x00000200UL, - - /// The item order does not matter. - kXMP_PropArrayIsUnordered = kXMP_PropValueIsArray, - - /// Implies \c #kXMP_PropValueIsArray, item order matters. It is serialized using an \c rdf:Seq container. - kXMP_PropArrayIsOrdered = 0x00000400UL, - - /// Implies \c #kXMP_PropArrayIsOrdered, items are alternates. It is serialized using an \c rdf:Alt container. - kXMP_PropArrayIsAlternate = 0x00000800UL, - - // ------------------------------------ - // Additional struct and array options. - - /// Implies \c #kXMP_PropArrayIsAlternate, items are localized text. Each array element is a - /// simple property with an \c xml:lang attribute. - kXMP_PropArrayIsAltText = 0x00001000UL, - - // kXMP_InsertBeforeItem = 0x00004000UL, ! Used by SetXyz functions. - // kXMP_InsertAfterItem = 0x00008000UL, ! Used by SetXyz functions. - - // ---------------------------- - // Other miscellaneous options. - - /// This property is an alias name for another property. This is only returned by - /// \c TXMPMeta::GetProperty() and then only if the property name is simple, not an path expression. - kXMP_PropIsAlias = 0x00010000UL, - - /// This property is the base value (actual) for a set of aliases.This is only returned by - /// \c TXMPMeta::GetProperty() and then only if the property name is simple, not an path expression. - kXMP_PropHasAliases = 0x00020000UL, - - /// The value of this property is "owned" by the application, and should not generally be editable in a UI. - kXMP_PropIsInternal = 0x00040000UL, - - /// The value of this property is not derived from the document content. - kXMP_PropIsStable = 0x00100000UL, - - /// The value of this property is derived from the document content. - kXMP_PropIsDerived = 0x00200000UL, - - // kXMPUtil_AllowCommas = 0x10000000UL, ! Used by TXMPUtils::CatenateArrayItems and ::SeparateArrayItems. - // kXMP_DeleteExisting = 0x20000000UL, ! Used by TXMPMeta::SetXyz functions to delete any pre-existing property. - // kXMP_SchemaNode = 0x80000000UL, ! Returned by iterators - #define to avoid warnings - - // ------------------------------ - // Masks that are multiple flags. - - /// Property type bit-flag mask for all array types - kXMP_PropArrayFormMask = kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText, - - /// Property type bit-flag mask for composite types (array and struct) - kXMP_PropCompositeMask = kXMP_PropValueIsStruct | kXMP_PropArrayFormMask, - - /// Mask for bits that are reserved for transient use by the implementation. - kXMP_ImplReservedMask = 0x70000000L - -}; - -#define kXMP_SchemaNode ((XMP_OptionBits)0x80000000UL) - -/// Option bit flags for the \c TXMPMeta property setting functions. These option bits are shared -/// with the accessor functions: -/// \li \c #kXMP_PropValueIsURI -/// \li \c #kXMP_PropValueIsStruct -/// \li \c #kXMP_PropValueIsArray -/// \li \c #kXMP_PropArrayIsOrdered -/// \li \c #kXMP_PropArrayIsAlternate -/// \li \c #kXMP_PropArrayIsAltText -enum { - - /// Option for array item location: Insert a new item before the given index. - kXMP_InsertBeforeItem = 0x00004000UL, - - /// Option for array item location: Insert a new item after the given index. - kXMP_InsertAfterItem = 0x00008000UL, - - /// Delete any pre-existing property. - kXMP_DeleteExisting = 0x20000000UL, - - /// Bit-flag mask for property-value option bits - kXMP_PropValueOptionsMask = kXMP_PropValueIsURI, - - /// Bit-flag mask for array-item location bits - kXMP_PropArrayLocationMask = kXMP_InsertBeforeItem | kXMP_InsertAfterItem - -}; - -// ------------------------------------------------------------------------------------------------- - -/// Option bit flags for \c TXMPMeta::ParseFromBuffer(). -enum { - - /// Require a surrounding \c x:xmpmeta element. - kXMP_RequireXMPMeta = 0x0001UL, - - /// This is the not last input buffer for this parse stream. - kXMP_ParseMoreBuffers = 0x0002UL, - - /// Do not reconcile alias differences, throw an exception. - kXMP_StrictAliasing = 0x0004UL - -}; - -/// Option bit flags for \c TXMPMeta::SerializeToBuffer(). -enum { - - // *** Option to remove empty struct/array, or leaf with empty value? - - /// Omit the XML packet wrapper. - kXMP_OmitPacketWrapper = 0x0010UL, - - /// Default is a writeable packet. - kXMP_ReadOnlyPacket = 0x0020UL, - - /// Use a compact form of RDF. - kXMP_UseCompactFormat = 0x0040UL, - - /// Include a padding allowance for a thumbnail image. - kXMP_IncludeThumbnailPad = 0x0100UL, - - /// The padding parameter is the overall packet length. - kXMP_ExactPacketLength = 0x0200UL, - - /// Show aliases as XML comments. - kXMP_WriteAliasComments = 0x0400UL, - - /// Omit all formatting whitespace. - kXMP_OmitAllFormatting = 0x0800UL, - - /// Omit the x:xmpmeta element surrounding the rdf:RDF element. - kXMP_OmitXMPMetaElement = 0x1000UL, - - _XMP_LittleEndian_Bit = 0x0001UL, // ! Don't use directly, see the combined values below! - _XMP_UTF16_Bit = 0x0002UL, - _XMP_UTF32_Bit = 0x0004UL, - - /// Bit-flag mask for encoding-type bits - kXMP_EncodingMask = 0x0007UL, - - /// Use UTF8 encoding - kXMP_EncodeUTF8 = 0UL, - - /// Use UTF16 big-endian encoding - kXMP_EncodeUTF16Big = _XMP_UTF16_Bit, - - /// Use UTF16 little-endian encoding - kXMP_EncodeUTF16Little = _XMP_UTF16_Bit | _XMP_LittleEndian_Bit, - - /// Use UTF32 big-endian encoding - kXMP_EncodeUTF32Big = _XMP_UTF32_Bit, - - /// Use UTF13 little-endian encoding - kXMP_EncodeUTF32Little = _XMP_UTF32_Bit | _XMP_LittleEndian_Bit - -}; - -// ------------------------------------------------------------------------------------------------- - -/// Option bit flags for \c TXMPIterator construction. -enum { - - /// The low 8 bits are an enum of what data structure to iterate. - kXMP_IterClassMask = 0x00FFUL, - - /// Iterate the property tree of a TXMPMeta object. - kXMP_IterProperties = 0x0000UL, - - /// Iterate the global alias table. - kXMP_IterAliases = 0x0001UL, - - /// Iterate the global namespace table. - kXMP_IterNamespaces = 0x0002UL, - - /// Just do the immediate children of the root, default is subtree. - kXMP_IterJustChildren = 0x0100UL, - - /// Just do the leaf nodes, default is all nodes in the subtree. - kXMP_IterJustLeafNodes = 0x0200UL, - - /// Return just the leaf part of the path, default is the full path. - kXMP_IterJustLeafName = 0x0400UL, - - /// Include aliases, default is just actual properties. - kXMP_IterIncludeAliases = 0x0800UL, - - /// Omit all qualifiers. - kXMP_IterOmitQualifiers = 0x1000UL - -}; - -/// Option bit flags for \c TXMPIterator::Skip(). -enum { - - /// Skip the subtree below the current node. - kXMP_IterSkipSubtree = 0x0001UL, - - /// Skip the subtree below and remaining siblings of the current node. - kXMP_IterSkipSiblings = 0x0002UL - -}; - -// ------------------------------------------------------------------------------------------------- -/// Option bit flags for \c TXMPUtils::CatenateArrayItems() and \c TXMPUtils::SeparateArrayItems(). -/// These option bits are shared with the accessor functions: -/// \li \c #kXMP_PropValueIsArray, -/// \li \c #kXMP_PropArrayIsOrdered, -/// \li \c #kXMP_PropArrayIsAlternate, -/// \li \c #kXMP_PropArrayIsAltText -enum { - - /// Allow commas in item values, default is separator. - kXMPUtil_AllowCommas = 0x10000000UL - -}; - -/// Option bit flags for \c TXMPUtils::RemoveProperties() and \c TXMPUtils::AppendProperties(). -enum { - - /// Do all properties, default is just external properties. - kXMPUtil_DoAllProperties = 0x0001UL, - - /// Replace existing values, default is to leave them. - kXMPUtil_ReplaceOldValues = 0x0002UL, - - /// Delete properties if the new value is empty. - kXMPUtil_DeleteEmptyValues = 0x0004UL, - - /// Include aliases, default is just actual properties. - kXMPUtil_IncludeAliases = 0x0800UL - -}; - -// ================================================================================================= -// Types and Constants for XMPFiles -// ================================ - -/// File format constants for use with XMPFiles. -enum { - - // ! Hex used to avoid gcc warnings. Leave the constants so the text reads big endian. There - // ! seems to be no decent way on UNIX to determine the target endianness at compile time. - // ! Forcing it on the client isn't acceptable. - - // -------------------- - // Public file formats. - - /// Public file format constant: 'PDF ' - kXMP_PDFFile = 0x50444620UL, - /// Public file format constant: 'PS ', general PostScript following DSC conventions - kXMP_PostScriptFile = 0x50532020UL, - /// Public file format constant: 'EPS ', encapsulated PostScript - kXMP_EPSFile = 0x45505320UL, - - /// Public file format constant: 'JPEG' - kXMP_JPEGFile = 0x4A504547UL, - /// Public file format constant: 'JPX ', JPEG 2000, ISO 15444-1 - kXMP_JPEG2KFile = 0x4A505820UL, - /// Public file format constant: 'TIFF' - kXMP_TIFFFile = 0x54494646UL, - /// Public file format constant: 'GIF ' - kXMP_GIFFile = 0x47494620UL, - /// Public file format constant: 'PNG ' - kXMP_PNGFile = 0x504E4720UL, - - /// Public file format constant: 'SWF ' - kXMP_SWFFile = 0x53574620UL, - /// Public file format constant: 'FLA ' - kXMP_FLAFile = 0x464C4120UL, - /// Public file format constant: 'FLV ' - kXMP_FLVFile = 0x464C5620UL, - - /// Public file format constant: 'MOV ', Quicktime - kXMP_MOVFile = 0x4D4F5620UL, - /// Public file format constant: 'AVI ' - kXMP_AVIFile = 0x41564920UL, - /// Public file format constant: 'CIN ', Cineon - kXMP_CINFile = 0x43494E20UL, - /// Public file format constant: 'WAV ' - kXMP_WAVFile = 0x57415620UL, - /// Public file format constant: 'MP3 ' - kXMP_MP3File = 0x4D503320UL, - /// Public file format constant: 'SES ', Audition session - kXMP_SESFile = 0x53455320UL, - /// Public file format constant: 'CEL ', Audition loop - kXMP_CELFile = 0x43454C20UL, - /// Public file format constant: 'MPEG' - kXMP_MPEGFile = 0x4D504547UL, - /// Public file format constant: 'MP2 ' - kXMP_MPEG2File = 0x4D503220UL, - /// Public file format constant: 'MP4 ', ISO 14494-12 and -14 - kXMP_MPEG4File = 0x4D503420UL, - /// Public file format constant: 'WMAV', Windows Media Audio and Video - kXMP_WMAVFile = 0x574D4156UL, - /// Public file format constant: 'AIFF' - kXMP_AIFFFile = 0x41494646UL, - /// Public file format constant: 'P2 ', a collection not really a single file - kXMP_P2File = 0x50322020UL, - /// Public file format constant: 'XDCF', a collection not really a single file - kXMP_XDCAM_FAMFile = 0x58444346UL, - /// Public file format constant: 'XDCS', a collection not really a single file - kXMP_XDCAM_SAMFile = 0x58444353UL, - /// Public file format constant: 'XDCX', a collection not really a single file - kXMP_XDCAM_EXFile = 0x58444358UL, - /// Public file format constant: 'AVHD', a collection not really a single file - kXMP_AVCHDFile = 0x41564844UL, - /// Public file format constant: 'SHDV', a collection not really a single file - kXMP_SonyHDVFile = 0x53484456UL, - - /// Public file format constant: 'HTML' - kXMP_HTMLFile = 0x48544D4CUL, - /// Public file format constant: 'XML ' - kXMP_XMLFile = 0x584D4C20UL, - /// Public file format constant: 'text' - kXMP_TextFile = 0x74657874UL, - - // ------------------------------- - // Adobe application file formats. - - /// Adobe application file format constant: 'PSD ' - kXMP_PhotoshopFile = 0x50534420UL, - /// Adobe application file format constant: 'AI ' - kXMP_IllustratorFile = 0x41492020UL, - /// Adobe application file format constant: 'INDD' - kXMP_InDesignFile = 0x494E4444UL, - /// Adobe application file format constant: 'AEP ' - kXMP_AEProjectFile = 0x41455020UL, - /// Adobe application file format constant: 'AET ', After Effects Project Template - kXMP_AEProjTemplateFile = 0x41455420UL, - /// Adobe application file format constant: 'FFX ' - kXMP_AEFilterPresetFile = 0x46465820UL, - /// Adobe application file format constant: 'NCOR' - kXMP_EncoreProjectFile = 0x4E434F52UL, - /// Adobe application file format constant: 'PRPJ' - kXMP_PremiereProjectFile = 0x5052504AUL, - /// Adobe application file format constant: 'PRTL' - kXMP_PremiereTitleFile = 0x5052544CUL, - /// Adobe application file format constant: 'UCF ', Universal Container Format - kXMP_UCFFile = 0x55434620UL, - - // ------- - // Others. - - /// Unknown file format constant: ' ' - kXMP_UnknownFile = 0x20202020UL - -}; - -/// Type for file format identification constants. See \c #kXMP_PDFFile and following. -typedef XMP_Uns32 XMP_FileFormat; - -// ------------------------------------------------------------------------------------------------- - -/// Byte-order masks, do not use directly -enum { - kXMP_CharLittleEndianMask = 1, - kXMP_Char16BitMask = 2, - kXMP_Char32BitMask = 4 -}; - -/// Constants to allow easy testing for 16/32 bit and big/little endian. -enum { - /// 8-bit - kXMP_Char8Bit = 0, - /// 16-bit big-endian - kXMP_Char16BitBig = kXMP_Char16BitMask, - /// 16-bit little-endian - kXMP_Char16BitLittle = kXMP_Char16BitMask | kXMP_CharLittleEndianMask, - /// 32-bit big-endian - kXMP_Char32BitBig = kXMP_Char32BitMask, - /// 32-bit little-endian - kXMP_Char32BitLittle = kXMP_Char32BitMask | kXMP_CharLittleEndianMask, - /// Variable or not-yet-known cases - kXMP_CharUnknown = 1 -}; - -/// \name Macros to test components of the character form mask -/// @{ -/// -/// \def XMP_CharFormIs16Bit -/// \brief Macro reports the encoding of a character. -/// \param f The character to check. -/// -/// \def XMP_CharFormIs32Bit -/// \brief Macro reports the encoding of a character. -/// \param f The character to check. -/// -/// \def XMP_CharFormIsBigEndian -/// \brief Macro reports the byte-order of a character. -/// \param f The character to check. -/// -/// \def XMP_CharFormIsLittleEndian -/// \brief Macro reports the byte-order of a character. -/// \param f The character to check. -/// -/// \def XMP_GetCharSize -/// \brief Macro reports the byte-size of a character. -/// \param f The character to check. -/// -/// \def XMP_CharToSerializeForm -/// \brief Macro converts \c XMP_Uns8 to \c XMP_OptionBits. -/// \param cf The character to convert. -/// -/// \def XMP_CharFromSerializeForm -/// \brief Macro converts \c XMP_OptionBits to \c XMP_Uns8. -/// \param sf The character to convert. -/// -/// @} - -#define XMP_CharFormIs16Bit(f) ( ((int)(f) & kXMP_Char16BitMask) != 0 ) -#define XMP_CharFormIs32Bit(f) ( ((int)(f) & kXMP_Char32BitMask) != 0 ) -#define XMP_CharFormIsBigEndian(f) ( ((int)(f) & kXMP_CharLittleEndianMask) == 0 ) -#define XMP_CharFormIsLittleEndian(f) ( ((int)(f) & kXMP_CharLittleEndianMask) != 0 ) -#define XMP_GetCharSize(f) ( ((int)(f)&6) == 0 ? 1 : (int)(f)&6 ) -#define XMP_CharToSerializeForm(cf) ( (XMP_OptionBits)(cf) ) -#define XMP_CharFromSerializeForm(sf) ( (XMP_Uns8)(sf) ) - -/// \def kXMPFiles_UnknownOffset -/// \brief Constant for an unknown packet offset within a file. -#define kXMPFiles_UnknownOffset ((XMP_Int64)-1) - -/// \def kXMPFiles_UnknownLength -/// \brief Constant for an unknown packet length within a file. -#define kXMPFiles_UnknownLength ((XMP_Int32)-1) - -/// XMP packet description -struct XMP_PacketInfo { - - /// Packet offset in the file in bytes, -1 if unknown. - XMP_Int64 offset; - /// Packet length in the file in bytes, -1 if unknown. - XMP_Int32 length; - /// Packet padding size in bytes, zero if unknown. - XMP_Int32 padSize; // Zero if unknown. - - /// Character format using the values \c kXMP_Char8Bit, \c kXMP_Char16BitBig, etc. - XMP_Uns8 charForm; - /// True if there is a packet wrapper and the trailer says writeable by dumb packet scanners. - XMP_Bool writeable; - /// True if there is a packet wrapper, the "" XML processing instructions. - XMP_Bool hasWrapper; - - /// Padding to make the struct's size be a multiple 4. - XMP_Uns8 pad; - - /// Default constructor. - XMP_PacketInfo() : offset(kXMPFiles_UnknownOffset), length(kXMPFiles_UnknownLength), - padSize(0), charForm(0), writeable(0), hasWrapper(0), pad(0) {}; - -}; - -/// Version of the XMP_PacketInfo type -enum { - /// Version of the XMP_PacketInfo type - kXMP_PacketInfoVersion = 3 -}; - -// ------------------------------------------------------------------------------------------------- - -/// Values for \c XMP_ThumbnailInfo::tnailFormat. -enum { - /// The thumbnail data has an unknown format. - kXMP_UnknownTNail = 0, - /// The thumbnail data is a JPEG stream, presumably compressed. - kXMP_JPEGTNail = 1, - /// The thumbnail data is a TIFF stream, presumably uncompressed. - kXMP_TIFFTNail = 2, - /// The thumbnail data is in the format of Photoshop Image Resource 1036. - kXMP_PShopTNail = 3 -}; - -/// Thumbnail descriptor -struct XMP_ThumbnailInfo { - - /// The format of the containing file. - XMP_FileFormat fileFormat; - /// Full image size in pixels. - XMP_Uns32 fullWidth, fullHeight; - /// Thumbnail image size in pixels. - XMP_Uns32 tnailWidth, tnailHeight; - /// Orientation of full image and thumbnail, as defined by Exif for tag 274. - - XMP_Uns16 fullOrientation, tnailOrientation; - /// Raw image data from the host file, valid for life of the owning \c XMPFiles object. Do not modify! - const XMP_Uns8 * tnailImage; - /// The size in bytes of the thumbnail image data. - XMP_Uns32 tnailSize; - /// The format of the thumbnail image data. - XMP_Uns8 tnailFormat; - - /// Padding to make the struct's size be a multiple 4. - XMP_Uns8 pad1, pad2, pad3; - - /// Default constructor. - XMP_ThumbnailInfo() : fileFormat(kXMP_UnknownFile), fullWidth(0), fullHeight(0), - tnailWidth(0), tnailHeight(0), fullOrientation(0), tnailOrientation(0), - tnailImage(0), tnailSize(0), tnailFormat(kXMP_UnknownTNail) {}; - -}; - -/// Version of the XMP_ThumbnailInfo type -enum { - /// Version of the XMP_ThumbnailInfo type - kXMP_ThumbnailInfoVersion = 1 -}; - -// ------------------------------------------------------------------------------------------------- - -/// Option bit flags for \c TXMPFiles::Initialize(). -enum { - /// Do not initialize QuickTime, the client will. - kXMPFiles_NoQuickTimeInit = 0x0001 -}; - -/// Option bit flags for \c TXMPFiles::GetFormatInfo(). -enum { - - /// Can inject first-time XMP into an existing file. - kXMPFiles_CanInjectXMP = 0x00000001, - - /// Can expand XMP or other metadata in an existing file. - kXMPFiles_CanExpand = 0x00000002, - - /// Can copy one file to another, writing new metadata. - kXMPFiles_CanRewrite = 0x00000004, - - /// Can expand, but prefers in-place update. - kXMPFiles_PrefersInPlace = 0x00000008, - - /// Supports reconciliation between XMP and other forms. - kXMPFiles_CanReconcile = 0x00000010, - - /// Allows access to just the XMP, ignoring other forms. - kXMPFiles_AllowsOnlyXMP = 0x00000020, - - /// File handler returns raw XMP packet information. - kXMPFiles_ReturnsRawPacket = 0x00000040, - - /// File handler returns native thumbnail. - kXMPFiles_ReturnsTNail = 0x00000080, - - /// The file handler does the file open and close. - kXMPFiles_HandlerOwnsFile = 0x00000100, - - /// The file handler allows crash-safe file updates. - kXMPFiles_AllowsSafeUpdate = 0x00000200, - - /// The file format needs the XMP packet to be read-only. - kXMPFiles_NeedsReadOnlyPacket = 0x00000400, - - /// The file handler uses a "sidecar" file for the XMP. - kXMPFiles_UsesSidecarXMP = 0x00000800, - - /// The format is folder oriented, for example the P2 video format. - kXMPFiles_FolderBasedFormat = 0x00001000 - -}; - -/// Option bit flags for \c TXMPFiles::OpenFile(). -enum { - - /// Open for read-only access. - kXMPFiles_OpenForRead = 0x00000001, - - /// Open for reading and writing. - kXMPFiles_OpenForUpdate = 0x00000002, - - /// Only the XMP is wanted, allows space/time optimizations. - kXMPFiles_OpenOnlyXMP = 0x00000004, - - /// Cache thumbnail if possible, \c TXMPFiles::GetThumbnail() will be called. - kXMPFiles_OpenCacheTNail = 0x00000008, - - /// Be strict about locating XMP and reconciling with other forms. - kXMPFiles_OpenStrictly = 0x00000010, - - /// Require the use of a smart handler. - kXMPFiles_OpenUseSmartHandler = 0x00000020, - - /// Force packet scanning, do not use a smart handler. - kXMPFiles_OpenUsePacketScanning = 0x00000040, - - /// Only packet scan files "known" to need scanning. - kXMPFiles_OpenLimitedScanning = 0x00000080, - - /// Attempt to repair a file opened for update, default is to not open (throw an exception). - kXMPFiles_OpenRepairFile = 0x00000100, - - /// Set if calling from background thread. - kXMPFiles_OpenInBackground = 0x10000000 - -}; - -// A note about kXMPFiles_OpenInBackground. The XMPFiles handler for .mov files currently uses -// QuickTime. On Macintosh, calls to Enter/ExitMovies versus Enter/ExitMoviesOnThread must be made. -// This option is used to signal background use so that the .mov handler can behave appropriately. - -/// Option bit flags for \c TXMPFiles::CloseFile(). -enum { - /// Write into a temporary file and swap for crash safety. - kXMPFiles_UpdateSafely = 0x0001 -}; - -// ================================================================================================= -// Exception codes -// =============== - -/// \name Errors Exception handling -/// @{ -/// -/// XMP Tookit errors result in throwing an \c XMP_Error exception. Any exception thrown within the -/// XMP Toolkit is caught in the toolkit and rethrown as an \c XMP_Error. -/// -/// The \c XMP_Error class contains a numeric code and an English explanation. New numeric codes may -/// be added at any time. There are typically many possible explanations for each numeric code. The -/// explanations try to be precise about the specific circumstances causing the error. -/// -/// \note The explanation string is for debugging use only. It must not be shown to users in a -/// final product. It is written for developers not users, and never localized. -/// - -/// XMP Toolkit error, associates an error code with a descriptive error string. -class XMP_Error { -public: - - /// @brief Constructor for an XMP_Error. - /// - /// @param _id The numeric code. - /// - /// @param _errMsg The descriptive string, for debugging use only. It must not be shown to users - /// in a final product. It is written for developers, not users, and never localized. - XMP_Error ( XMP_Int32 _id, XMP_StringPtr _errMsg ) : id(_id), errMsg(_errMsg) {}; - - /// Retrieves the numeric code from an XMP_Error. - inline XMP_Int32 GetID() const { return id; }; - - /// Retrieves the descriptive string from an XMP_Error. - inline XMP_StringPtr GetErrMsg() const { return errMsg; }; - -private: - /// Exception code. See constants \c #kXMPErr_Unknown and following. - XMP_Int32 id; - /// Descriptive string, for debugging use only. It must not be shown to users in a final - /// product. It is written for developers, not users, and never localized. - XMP_StringPtr errMsg; -}; - -/// Exception code constants -enum { - - // -------------------- - // Generic error codes. - - /// Generic unknown error - kXMPErr_Unknown = 0, - /// Generic undefined error - kXMPErr_TBD = 1, - /// Generic unavailable error - kXMPErr_Unavailable = 2, - /// Generic bad object error - kXMPErr_BadObject = 3, - /// Generic bad parameter error - kXMPErr_BadParam = 4, - /// Generic bad value error - kXMPErr_BadValue = 5, - /// Generic assertion failure - kXMPErr_AssertFailure = 6, - /// Generic enforcement failure - kXMPErr_EnforceFailure = 7, - /// Generic unimplemented error - kXMPErr_Unimplemented = 8, - /// Generic internal failure - kXMPErr_InternalFailure = 9, - /// Generic deprecated error - kXMPErr_Deprecated = 10, - /// Generic external failure - kXMPErr_ExternalFailure = 11, - /// Generic user abort error - kXMPErr_UserAbort = 12, - /// Generic standard exception - kXMPErr_StdException = 13, - /// Generic unknown exception - kXMPErr_UnknownException = 14, - /// Generic out-of-memory error - kXMPErr_NoMemory = 15, - - // ------------------------------------ - // More specific parameter error codes. - - /// Bad schema parameter - kXMPErr_BadSchema = 101, - /// Bad XPath parameter - kXMPErr_BadXPath = 102, - /// Bad options parameter - kXMPErr_BadOptions = 103, - /// Bad index parameter - kXMPErr_BadIndex = 104, - /// Bad iteration position - kXMPErr_BadIterPosition = 105, - /// XML parsing error - kXMPErr_BadParse = 106, - /// Serialization error - kXMPErr_BadSerialize = 107, - /// File format error - kXMPErr_BadFileFormat = 108, - /// No file handler found for format - kXMPErr_NoFileHandler = 109, - /// Data too large for JPEG file format - kXMPErr_TooLargeForJPEG = 110, - - // ----------------------------------------------- - // File format and internal structure error codes. - - /// XML format error - kXMPErr_BadXML = 201, - /// RDF format error - kXMPErr_BadRDF = 202, - /// XMP format error - kXMPErr_BadXMP = 203, - /// Empty iterator - kXMPErr_EmptyIterator = 204, - /// Unicode error - kXMPErr_BadUnicode = 205, - /// TIFF format error - kXMPErr_BadTIFF = 206, - /// JPEG format error - kXMPErr_BadJPEG = 207, - /// PSD format error - kXMPErr_BadPSD = 208, - /// PSIR format error - kXMPErr_BadPSIR = 209, - /// IPTC format error - kXMPErr_BadIPTC = 210, - /// MPEG format error - kXMPErr_BadMPEG = 211 - -}; - -/// @} - -// ================================================================================================= -// Client callbacks -// ================ - -// ------------------------------------------------------------------------------------------------- -/// \name Special purpose callback functions -/// @{ - -/// A signed 32-bit integer used as a status result for the output callback routine, -/// \c XMP_TextOutputProc. Zero means no error, all other values except -1 are private to the callback. -/// The callback is wrapped to prevent exceptions being thrown across DLL boundaries. Any exceptions -/// thrown out of the callback cause a return status of -1. - -typedef XMP_Int32 XMP_Status; - -// ------------------------------------------------------------------------------------------------- -/// The signature of a client-defined callback for text output from XMP Toolkit debugging -/// operations. The callback is invoked one or more times for each line of output. The end of a line -/// is signaled by a '\\n' character at the end of the buffer. Formatting newlines are never present -/// in the middle of a buffer, but values of properties might contain any UTF-8 characters. -/// -/// @param refCon A pointer to client-defined data passed to the TextOutputProc. -/// -/// @param buffer A string containing one line of output. -/// -/// @param bufferSize The number of characters in the output buffer. -/// -/// @return A success/fail status value. Any failure result aborts the output. -/// -/// @see \c TXMPMeta::DumpObject() - -typedef XMP_Status (* XMP_TextOutputProc) ( void * refCon, - XMP_StringPtr buffer, - XMP_StringLen bufferSize ); - -// ------------------------------------------------------------------------------------------------- -/// The signature of a client-defined callback to check for a user request to abort a time-consuming -/// operation within XMPFiles. -/// -/// @param arg A pointer to caller-defined data passed from the registration call. -/// -/// @return True to abort the current operation, which results in an exception being thrown. -/// -/// @see \c TXMPFiles::SetAbortProc() - -typedef bool (* XMP_AbortProc) ( void * arg ); // Used by . - -/// @} - -// ================================================================================================= -// Stuff with no better place to be -// ================================ - -/// XMP Toolkit version information -typedef struct XMP_VersionInfo { - /// The primary release number, the "1" in version "1.2.3". - XMP_Uns8 major; - /// The secondary release number, the "2" in version "1.2.3". - XMP_Uns8 minor; - /// The tertiary release number, the "3" in version "1.2.3". - XMP_Uns8 micro; - /// A 0/1 boolean value, true if this is a debug build. - XMP_Bool isDebug; - /// A rolling build number, monotonically increasing in a release. - XMP_Uns32 build; - /// Individual feature implementation flags. - XMP_Uns32 flags; - /// A comprehensive version information string. - XMP_StringPtr message; -} XMP_VersionInfo; - -// ================================================================================================= - -#if __cplusplus -} // extern "C" -#endif - -#endif // __XMP_Const_h__ diff --git a/xmpsdk/include/XMP_Environment.h b/xmpsdk/include/XMP_Environment.h deleted file mode 100644 index 42635deca5..0000000000 --- a/xmpsdk/include/XMP_Environment.h +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef __XMP_Environment_h__ -#define __XMP_Environment_h__ 1 - -// ================================================================================================= -// XMP_Environment.h - Build environment flags for the XMP toolkit. -// ================================================================ -// -// This header is just C preprocessor macro definitions to set up the XMP toolkit build environment. -// It must be the first #include in any chain since it might affect things in other #includes. -// -// ================================================================================================= - -// ================================================================================================= -// Copyright 2002-2007 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. -// ================================================================================================= - -// ================================================================================================= -// Determine the Platform -// ====================== - -// One of MAC_ENV, WIN_ENV, or UNIX_ENV must be defined by the client. Since some other code -// requires these to be defined without values, they are only used here to define XMP-specific -// macros with 0 or 1 values. - - -#if !defined(_FILE_OFFSET_BITS) -#define _FILE_OFFSET_BITS 64 -#endif - -#if __LP64__ -# ifdef _WIN64 -# undef _WIN64 -# endif -# define _WIN64 1 -#endif - -#if defined _WIN32 -# define WIN_ENV 1 -/* Todo: How to correctly recognize a Mac platform? */ -#elif defined macintosh || defined MACOS_CLASSIC || defined MACOS_X_UNIX || defined MACOS_X || defined MACOS || defined(__APPLE__) -# define MAC_ENV 1 -#else -# define UNIX_ENV 1 -#endif - -// ! Tempting though it might be to have a standard macro for big or little endian, there seems to -// ! be no decent way to do that on our own in UNIX. Forcing it on the client isn't acceptable. - -#if defined ( MAC_ENV ) - - #if 0 // ! maybe someday - ! MAC_ENV - #error "MAC_ENV must be defined so that \"#if MAC_ENV\" is true" - #endif - - #if defined ( WIN_ENV ) || defined ( UNIX_ENV ) - #error "XMP environment error - must define only one of MAC_ENV, WIN_ENV, or UNIX_ENV" - #endif - - #define XMP_MacBuild 1 - #define XMP_WinBuild 0 - #define XMP_UNIXBuild 0 - -#elif defined ( WIN_ENV ) - - #if 0 // ! maybe someday - ! WIN_ENV - #error "WIN_ENV must be defined so that \"#if WIN_ENV\" is true" - #endif - - #if defined ( UNIX_ENV ) - #error "XMP environment error - must define only one of MAC_ENV, WIN_ENV, or UNIX_ENV" - #endif - - #define XMP_MacBuild 0 - #define XMP_WinBuild 1 - #define XMP_UNIXBuild 0 - -#elif defined ( UNIX_ENV ) - - #if 0 // ! maybe someday - ! UNIX_ENV - #error "UNIX_ENV must be defined so that \"#if UNIX_ENV\" is true" - #endif - - #define XMP_MacBuild 0 - #define XMP_WinBuild 0 - #define XMP_UNIXBuild 1 - -#else - - #error "XMP environment error - must define one of MAC_ENV, WIN_ENV, or UNIX_ENV" - -#endif - -// ================================================================================================= -// Common Macros -// ============= - -#if defined ( DEBUG ) - #if defined ( NDEBUG ) - #undef NDEBUG - #warning - #warning "XMP environment - DEBUG and NDEBUG defined. NDEBUG has been undefined" - #warning - #endif - #define XMP_DebugBuild 1 -#endif - -#if defined ( NDEBUG ) - #define XMP_DebugBuild 0 -#endif - -#ifndef XMP_DebugBuild - #define XMP_DebugBuild 0 -#endif - -#if XMP_DebugBuild - #include // The assert macro needs printf. -#endif - -#ifndef XMP_64 - #if _WIN64 - #define XMP_64 1 - #else - #define XMP_64 0 - #endif -#endif - -#define UNUSED(x) (void)(x) - -// ================================================================================================= -// Macintosh Specific Settings -// =========================== - -// ================================================================================================= -// Windows Specific Settings -// ========================= - -// ================================================================================================= -// UNIX Specific Settings -// ====================== - -// ================================================================================================= - -#endif // __XMP_Environment_h__ - -/* - If you're using Solaris and the Solaris Studio compiler, then you really - do need to use -library=stdcxx4 along with these inclusions below -*/ -#if defined(OS_SOLARIS) -#include -#include -#include -#include -#include -#if defined(__cplusplus) -#include -#include -#endif -#endif - diff --git a/xmpsdk/include/XMP_Version.h b/xmpsdk/include/XMP_Version.h deleted file mode 100644 index f8b0ea8104..0000000000 --- a/xmpsdk/include/XMP_Version.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __XMP_Version_h__ -#define __XMP_Version_h__ 1 - -/* --------------------------------------------------------------------------------------------- */ -/* ** IMPORTANT ** This file must be usable by strict ANSI C compilers. No "//" comments, etc. */ -/* --------------------------------------------------------------------------------------------- */ - -/* -// ================================================================================================= -// Copyright 2002-2008 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. -// ================================================================================================= -*/ - -/* ============================================================================================= */ -/** -XMP Toolkit Version Information - -Version information for the XMP toolkit is stored in the executable and available through a runtime -call, SXMPMeta::GetVersionInfo. In addition a static version number is defined in this -header. The information in the executable or returned by SXMPMeta::GetVersionInfo is about -the implementation internals, it is runtime version information. The values defined in this header -describe the version of the API used at client compile time. They do not necessarily relate to the -runtime version. - -Important: Do not display the static values defined here to users as the version of XMP in use. Do -not base runtime decisions on just this static version. It is OK to compare the static and runtime -versions. - -*/ -/* ============================================================================================= */ - -#define XMP_API_VERSION_MAJOR 4 -#define XMP_API_VERSION_MINOR 4 -#define XMP_API_VERSION_MICRO 0 - -#define XMP_API_VERSION 4.4 -#define XMP_API_VERSION_STRING "4.4.0-Exiv2" - -/* ============================================================================================= */ - -#endif /* __XMP_Version_h__ */ diff --git a/xmpsdk/include/client-glue/TXMPIterator.incl_cpp b/xmpsdk/include/client-glue/TXMPIterator.incl_cpp deleted file mode 100644 index 672203e27e..0000000000 --- a/xmpsdk/include/client-glue/TXMPIterator.incl_cpp +++ /dev/null @@ -1,226 +0,0 @@ -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2007 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. -// ================================================================================================= - -// ================================================================================================ -/// \file TXMPIterator.incl_cpp -/// \brief The implementation of the TXMPIterator template class. - -#include "XMPSDK.hpp" -#include "client-glue/WXMP_Common.hpp" -#include "client-glue/WXMPIterator.hpp" - -// ================================================================================================= -// Implementation Guidelines -// ========================= -// -// The implementations of the template functions are very stylized. The jobs done in this code are: -// -// 1. Set up the xmpIter template data member in the constructors. -// 2. Call through to the appropriate WXMPIterator function. -// 3. Copy returned strings and release the threading lock. -// -// The various kinds of functions follow similar patterns, first assuming no returned string: -// -// Constructors - Use an initializer for the xmpIter data member to call the WXMPIterator constructor. -// Destructor - Let the WXMPIterator destructor be implicitly called for the xmpIter data member. -// Static function - Simply call the corresponding WXMPIterator static function. -// Non-static function - Simply call the corresponding WXMPIterator function using xmpIter. -// -// If a member function has returned strings the code looks roughly like this: -// -// <<>> -// <<>> -// if ( <<>> ) { -// if ( outStr != 0 ) outStr->assign ( outPtr, outLen ); -// <<>> -// } -// return result; -// -// The <<>> is the call to the wrapper, and <<>> is the check and throw -// if the wrapper reports failure. The <<>> check is used to determine if the string -// should actually be assigned. For example, GetProperty can't assign the value if the property -// does not exist. There is no <<>> check if it isn't, well, appropriate. Outputs are -// always passed as explicit pointers, and null can be passed if the string is not wanted. The -// inner implementation holds the threading lock if an output string is returned, regardless of -// whether the client wants it or not (which the implementation does not know). -// -// ================================================================================================= - -#ifndef XMP_TraceCTorDTor - #define XMP_TraceCTorDTor 0 -#endif - -#if XMP_TraceCTorDTor - class XIPeek { // Hack to peek at the client ref count in the internal object. - public: - XIPeek(); - virtual ~XIPeek(); - XMP_Int32 clientRefs; - }; -#endif - -// ------------------------------------------------------------------------------------------------- - -#define PropIterCTor(xmpRef,schemaNS,propName,options) \ - WrapCheckIterRef ( newRef, zXMPIterator_PropCTor_1 ( xmpRef, schemaNS, propName, options ) ); \ - this->iterRef = newRef - -// ------------------------------------------------------------------------------------------------- - -#define TableIterCTor(schemaNS,propName,options) \ - WrapCheckIterRef ( newRef, zXMPIterator_TableCTor_1 ( schemaNS, propName, options ) ); \ - this->iterRef = newRef - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -TXMPIterator ( const TXMPIterator & original ) : iterRef(original.iterRef) -{ - WXMPIterator_IncrementRefCount_1 ( this->iterRef ); - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Copy construct TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPIterator,void):: -operator= ( const TXMPIterator & rhs ) -{ - #if XMP_TraceCTorDTor - XIPeek* xiLHS = (XIPeek*)this->iterRef; - XIPeek* xiRHS = (XIPeek*)rhs.iterRef; - printf ( "Assign TXMPIterator, lhs @ %.8X, rhs @ %.8X\n", this, &rhs ); - printf ( " original lhs ref = %.8X, count = %d\n", xiLHS, xiLHS->clientRefs ); - printf ( " original rhs ref = %.8X, count = %d\n", xiRHS, xiRHS->clientRefs ); - #endif - XMPIteratorRef oldRef = this->iterRef; // ! Decrement last so errors leave client object OK. - this->iterRef = rhs.iterRef; - WXMPIterator_IncrementRefCount_1 ( this->iterRef ); - WXMPIterator_DecrementRefCount_1 ( oldRef ); - #if XMP_TraceCTorDTor - printf ( " result lhs ref = %.8X, count = %d\n", xiLHS, xiLHS->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -TXMPIterator() : iterRef(0) -{ - throw XMP_Error ( kXMPErr_Unavailable, "No default construction for XMP iterators" ); - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Default construct TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -TXMPIterator ( const TXMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options /* = 0 */ ) : iterRef(0) -{ - PropIterCTor ( xmpObj.GetInternalRef(), schemaNS, propName, options ); - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Construct property TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -TXMPIterator ( const TXMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_OptionBits options /* = 0 */ ) : iterRef(0) -{ - PropIterCTor ( xmpObj.GetInternalRef(), schemaNS, "", options ); - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Construct schema TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -TXMPIterator ( const TXMPMeta & xmpObj, - XMP_OptionBits options /* = 0 */ ) : iterRef(0) -{ - PropIterCTor ( xmpObj.GetInternalRef(), "", "", options ); - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Construct tree TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -TXMPIterator ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ) : iterRef(0) -{ - TableIterCTor ( schemaNS, propName, options ); - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Construct table TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPIterator):: -~TXMPIterator () throw() -{ - #if XMP_TraceCTorDTor - XIPeek* xiPtr = (XIPeek*)this->iterRef; - printf ( "Destruct TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs ); - #endif - WXMPIterator_DecrementRefCount_1 ( this->iterRef ); - this->iterRef = 0; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPIterator,bool):: -Next ( tStringObj * schemaNS /* = 0 */, - tStringObj * propPath /* = 0 */, - tStringObj * propValue /* = 0 */, - XMP_OptionBits * options /* = 0 */ ) -{ - XMP_StringPtr schemaPtr = 0; - XMP_StringLen schemaLen = 0; - XMP_StringPtr pathPtr = 0; - XMP_StringLen pathLen = 0; - XMP_StringPtr valuePtr = 0; - XMP_StringLen valueLen = 0; - WrapCheckBool ( found, zXMPIterator_Next_1 ( &schemaPtr, &schemaLen, &pathPtr, &pathLen, &valuePtr, &valueLen, options ) ); - if ( found ) { - if ( schemaNS != 0 ) schemaNS->assign ( schemaPtr, schemaLen ); - if ( propPath != 0 ) propPath->assign ( pathPtr, pathLen ); - if ( propValue != 0 ) propValue->assign ( valuePtr, valueLen ); - WXMPUtils_UnlockIter_1 ( this->iterRef, 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPIterator,void):: -Skip ( XMP_OptionBits options ) -{ - WrapCheckVoid ( zXMPIterator_Skip_1 ( options ) ); -} - -// ================================================================================================= diff --git a/xmpsdk/include/client-glue/TXMPMeta.incl_cpp b/xmpsdk/include/client-glue/TXMPMeta.incl_cpp deleted file mode 100644 index 0131aa50ef..0000000000 --- a/xmpsdk/include/client-glue/TXMPMeta.incl_cpp +++ /dev/null @@ -1,935 +0,0 @@ -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2008 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. -// ================================================================================================= - -// ================================================================================================ -/// \file TXMPMeta.incl_cpp -/// \brief The implementation of the TXMPMeta template class. - -#include "XMPSDK.hpp" -#include "client-glue/WXMP_Common.hpp" -#include "client-glue/WXMPMeta.hpp" - -// ================================================================================================= -// Implementation Guidelines -// ========================= -// -// The implementations of the template functions are very stylized. ... -// -// ================================================================================================= - -#ifndef XMP_TraceCTorDTor - #define XMP_TraceCTorDTor 0 -#endif - -#if XMP_TraceCTorDTor - class XMPeek { // Hack to peek at the client ref count in the internal object. - public: - XMPeek(); - virtual ~XMPeek(); - XMP_Int32 clientRefs; - }; -#endif - -// ================================================================================================= -// Local utilities -// =============== - -// ------------------------------------------------------------------------------------------------- - -class TOPW_Info { -public: - XMP_TextOutputProc clientProc; - void * clientRefCon; - TOPW_Info ( XMP_TextOutputProc proc, void * refCon ) : clientProc(proc), clientRefCon(refCon) {}; -private: - TOPW_Info() {}; // ! Hide default constructor. -}; - -static XMP_Status TextOutputProcWrapper ( void * refCon, - XMP_StringPtr buffer, - XMP_StringLen bufferSize ) -{ - try { // Don't let client callback exceptions propagate across DLL boundaries. - TOPW_Info * info = (TOPW_Info*)refCon; - return info->clientProc ( info->clientRefCon, buffer, bufferSize ); - } catch ( ... ) { - return -1; - } -} - -// ================================================================================================= -// Initialization and termination -// ============================== - -XMP_MethodIntro(TXMPMeta,void):: -GetVersionInfo ( XMP_VersionInfo * info ) -{ - WrapNoCheckVoid ( zXMPMeta_GetVersionInfo_1 ( info ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -Initialize() -{ - WrapCheckBool ( ok, zXMPMeta_Initialize_1() ); - return ok; -} -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -Terminate() -{ - WrapNoCheckVoid ( zXMPMeta_Terminate_1() ); -} - -// ================================================================================================= -// Constuctors, destructor, operators -// ================================== - -static XMPMetaRef DefaultCTor() -{ - WrapCheckMetaRef ( newRef, zXMPMeta_CTor_1() ); - return newRef; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPMeta):: -TXMPMeta() : xmpRef(DefaultCTor()) -{ - #if XMP_TraceCTorDTor - XMPeek* xmPtr = (XMPeek*)this->xmpRef; - printf ( "Default construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPMeta):: -TXMPMeta ( const TXMPMeta & original ) : xmpRef(original.xmpRef) -{ - WXMPMeta_IncrementRefCount_1 ( this->xmpRef ); - #if XMP_TraceCTorDTor - XMPeek* xmPtr = (XMPeek*)this->xmpRef; - printf ( "Copy construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -operator= ( const TXMPMeta & rhs ) -{ - #if XMP_TraceCTorDTor - XMPeek* xmLHS = (XMPeek*)this->xmpRef; - XMPeek* xmRHS = (XMPeek*)rhs.xmpRef; - printf ( "Assign TXMPMeta, lhs @ %.8X, rhs @ %.8X\n", this, &rhs ); - printf ( " original lhs ref = %.8X, count = %d\n", xmLHS, xmLHS->clientRefs ); - printf ( " original rhs ref = %.8X, count = %d\n", xmRHS, xmRHS->clientRefs ); - #endif - XMPMetaRef oldRef = this->xmpRef; // ! Decrement last so errors leave client object OK. - this->xmpRef = rhs.xmpRef; - WXMPMeta_IncrementRefCount_1 ( this->xmpRef ); // Increment the count on the new ref. - WXMPMeta_DecrementRefCount_1 ( oldRef ); // Decrement the count on the old ref. - #if XMP_TraceCTorDTor - printf ( " result lhs ref = %.8X, count = %d\n", xmLHS, xmLHS->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPMeta):: -TXMPMeta ( XMPMetaRef _xmpRef ) : xmpRef(_xmpRef) -{ - WXMPMeta_IncrementRefCount_1 ( this->xmpRef ); - #if XMP_TraceCTorDTor - XMPeek* xmPtr = (XMPeek*)this->xmpRef; - printf ( "Ref construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs ); - #endif -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPMeta):: -TXMPMeta ( XMP_StringPtr buffer, - XMP_StringLen xmpSize ) : xmpRef(DefaultCTor()) -{ - #if XMP_TraceCTorDTor - XMPeek* xmPtr = (XMPeek*)this->xmpRef; - printf ( "Parse construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs ); - #endif - try { - this->ParseFromBuffer ( buffer, xmpSize ); - } catch ( ... ) { - WXMPMeta_DecrementRefCount_1 ( this->xmpRef ); - this->xmpRef = 0; - throw; - } -} - -// ------------------------------------------------------------------------------------------------- - -XMP_CTorDTorIntro(TXMPMeta):: -~TXMPMeta() throw() -{ - #if XMP_TraceCTorDTor - XMPeek* xmPtr = (XMPeek*)this->xmpRef; - printf ( "Destruct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs ); - #endif - WXMPMeta_DecrementRefCount_1 ( this->xmpRef ); - this->xmpRef = 0; - -} // ~TXMPMeta () - -// ================================================================================================= -// Global state functions -// ====================== - -XMP_MethodIntro(TXMPMeta,XMP_OptionBits):: -GetGlobalOptions() -{ - WrapCheckOptions ( options, zXMPMeta_GetGlobalOptions_1() ); - return options; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetGlobalOptions ( XMP_OptionBits options ) -{ - WrapCheckVoid ( zXMPMeta_SetGlobalOptions_1 ( options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,XMP_Status):: -DumpNamespaces ( XMP_TextOutputProc outProc, - void * refCon ) -{ - TOPW_Info info ( outProc, refCon ); - WrapCheckStatus ( status, zXMPMeta_DumpNamespaces_1 ( TextOutputProcWrapper, &info ) ); - return status; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,XMP_Status):: -DumpAliases ( XMP_TextOutputProc outProc, - void * refCon ) -{ - TOPW_Info info ( outProc, refCon ); - WrapCheckStatus ( status, zXMPMeta_DumpAliases_1 ( TextOutputProcWrapper, &info ) ); - return status; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -RegisterNamespace ( XMP_StringPtr namespaceURI, - XMP_StringPtr prefix ) -{ - WrapCheckVoid ( zXMPMeta_RegisterNamespace_1 ( namespaceURI, prefix ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetNamespacePrefix ( XMP_StringPtr namespaceURI, - tStringObj * namespacePrefix ) -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckBool ( found, zXMPMeta_GetNamespacePrefix_1 ( namespaceURI, &resultPtr, &resultLen ) ); - if ( found ) { - if ( namespacePrefix != 0 ) namespacePrefix->assign ( resultPtr, resultLen ); - WXMPMeta_Unlock_1 ( 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetNamespaceURI ( XMP_StringPtr namespacePrefix, - tStringObj * namespaceURI ) -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckBool ( found, zXMPMeta_GetNamespaceURI_1 ( namespacePrefix, &resultPtr, &resultLen ) ); - if ( found ) { - if ( namespaceURI != 0 ) namespaceURI->assign ( resultPtr, resultLen ); - WXMPMeta_Unlock_1 ( 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -DeleteNamespace ( XMP_StringPtr namespaceURI ) -{ - WrapCheckVoid ( zXMPMeta_DeleteNamespace_1 ( namespaceURI ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -RegisterAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr actualNS, - XMP_StringPtr actualProp, - XMP_OptionBits arrayForm ) -{ - WrapCheckVoid ( zXMPMeta_RegisterAlias_1 ( aliasNS, aliasProp, actualNS, actualProp, arrayForm ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -ResolveAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - tStringObj * actualNS, - tStringObj * actualProp, - XMP_OptionBits * arrayForm ) -{ - XMP_StringPtr nsPtr = 0; - XMP_StringLen nsLen = 0; - XMP_StringPtr propPtr = 0; - XMP_StringLen propLen = 0; - WrapCheckBool ( found, zXMPMeta_ResolveAlias_1 ( aliasNS, aliasProp, &nsPtr, &nsLen, &propPtr, &propLen, arrayForm ) ); - if ( found ) { - if ( actualNS != 0 ) actualNS->assign ( nsPtr, nsLen ); - if ( actualProp != 0 ) actualProp->assign ( propPtr, propLen ); - WXMPMeta_Unlock_1 ( 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -DeleteAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp ) -{ - WrapCheckVoid ( zXMPMeta_DeleteAlias_1 ( aliasNS, aliasProp ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -RegisterStandardAliases ( XMP_StringPtr schemaNS ) -{ - WrapCheckVoid ( zXMPMeta_RegisterStandardAliases_1 ( schemaNS ) ); -} - -// ================================================================================================= -// Basic property manipulation functions -// ===================================== - -XMP_MethodIntro(TXMPMeta,bool):: -GetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - tStringObj * propValue, - XMP_OptionBits * options ) const -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckBool ( found, zXMPMeta_GetProperty_1 ( schemaNS, propName, &resultPtr, &resultLen, options ) ); - if ( found ) { - if ( propValue != 0 ) propValue->assign ( resultPtr, resultLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - tStringObj * itemValue, - XMP_OptionBits * options ) const -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckBool ( found, zXMPMeta_GetArrayItem_1 ( schemaNS, arrayName, itemIndex, &resultPtr, &resultLen, options ) ); - if ( found ) { - if ( itemValue != 0 ) itemValue->assign ( resultPtr, resultLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - tStringObj * fieldValue, - XMP_OptionBits * options ) const -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckBool ( found, zXMPMeta_GetStructField_1 ( schemaNS, structName, fieldNS, fieldName, &resultPtr, &resultLen, options ) ); - if ( found ) { - if ( fieldValue != 0 ) fieldValue->assign ( resultPtr, resultLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - tStringObj * qualValue, - XMP_OptionBits * options ) const -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckBool ( found, zXMPMeta_GetQualifier_1 ( schemaNS, propName, qualNS, qualName, &resultPtr, &resultLen, options ) ); - if ( found ) { - if ( qualValue != 0 ) qualValue->assign ( resultPtr, resultLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 ); - } - return found; -} //GetQualifier () - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr propValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetProperty_1 ( schemaNS, propName, propValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const tStringObj & propValue, - XMP_OptionBits options /* = 0 */ ) -{ - this->SetProperty ( schemaNS, propName, propValue.c_str(), options ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr itemValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetArrayItem_1 ( schemaNS, arrayName, itemIndex, itemValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - const tStringObj & itemValue, - XMP_OptionBits options /* = 0 */ ) -{ - this->SetArrayItem ( schemaNS, arrayName, itemIndex, itemValue.c_str(), options ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -AppendArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - XMP_StringPtr itemValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_AppendArrayItem_1 ( schemaNS, arrayName, arrayOptions, itemValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -AppendArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - const tStringObj & itemValue, - XMP_OptionBits options /* = 0 */ ) -{ - this->AppendArrayItem ( schemaNS, arrayName, arrayOptions, itemValue.c_str(), options ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetStructField_1 ( schemaNS, structName, fieldNS, fieldName, fieldValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - const tStringObj & fieldValue, - XMP_OptionBits options /* = 0 */ ) -{ - this->SetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue.c_str(), options ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr qualValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetQualifier_1 ( schemaNS, propName, qualNS, qualName, qualValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - const tStringObj & qualValue, - XMP_OptionBits options /* = 0 */ ) -{ - this->SetQualifier ( schemaNS, propName, qualNS, qualName, qualValue.c_str(), options ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -DeleteProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ) -{ - WrapCheckVoid ( zXMPMeta_DeleteProperty_1 ( schemaNS, propName ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -DeleteArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ) -{ - WrapCheckVoid ( zXMPMeta_DeleteArrayItem_1 ( schemaNS, arrayName, itemIndex ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -DeleteStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ) -{ - WrapCheckVoid ( zXMPMeta_DeleteStructField_1 ( schemaNS, structName, fieldNS, fieldName ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -DeleteQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ) -{ - WrapCheckVoid ( zXMPMeta_DeleteQualifier_1 ( schemaNS, propName, qualNS, qualName ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -DoesPropertyExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ) const -{ - WrapCheckBool ( exists, zXMPMeta_DoesPropertyExist_1 ( schemaNS, propName ) ); - return exists; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -DoesArrayItemExist ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ) const -{ - WrapCheckBool ( exists, zXMPMeta_DoesArrayItemExist_1 ( schemaNS, arrayName, itemIndex ) ); - return exists; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -DoesStructFieldExist ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ) const -{ - WrapCheckBool ( exists, zXMPMeta_DoesStructFieldExist_1 ( schemaNS, structName, fieldNS, fieldName ) ); - return exists; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -DoesQualifierExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ) const -{ - WrapCheckBool ( exists, zXMPMeta_DoesQualifierExist_1 ( schemaNS, propName, qualNS, qualName ) ); - return exists; -} - -// ================================================================================================= -// Specialized Get and Set functions -// ================================= - -XMP_MethodIntro(TXMPMeta,bool):: -GetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - tStringObj * actualLang, - tStringObj * itemValue, - XMP_OptionBits * options ) const -{ - XMP_StringPtr langPtr = 0; - XMP_StringLen langLen = 0; - XMP_StringPtr itemPtr = 0; - XMP_StringLen itemLen = 0; - WrapCheckBool ( found, zXMPMeta_GetLocalizedText_1 ( schemaNS, altTextName, genericLang, specificLang, - &langPtr, &langLen, &itemPtr, &itemLen, options ) ); - if ( found ) { - if ( actualLang != 0 ) actualLang->assign ( langPtr, langLen ); - if ( itemValue != 0 ) itemValue->assign ( itemPtr, itemLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, kXMP_NoOptions ); - } - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - XMP_StringPtr itemValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetLocalizedText_1 ( schemaNS, altTextName, genericLang, specificLang, itemValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - const tStringObj & itemValue, - XMP_OptionBits options /* = 0 */ ) -{ - this->SetLocalizedText ( schemaNS, altTextName, genericLang, specificLang, itemValue.c_str(), options ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool * propValue, - XMP_OptionBits * options ) const -{ - XMP_Bool binValue; - WrapCheckBool ( found, zXMPMeta_GetProperty_Bool_1 ( schemaNS, propName, &binValue, options ) ); - if ( found && (propValue != 0) ) *propValue = binValue; - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long * propValue, - XMP_OptionBits * options ) const -{ - XMP_Int32 abiValue; - WrapCheckBool ( found, zXMPMeta_GetProperty_Int_1 ( schemaNS, propName, &abiValue, options ) ); - if ( found && (propValue != 0) ) *propValue = abiValue; - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long long * propValue, - XMP_OptionBits * options ) const -{ - XMP_Int64 abiValue; - WrapCheckBool ( found, zXMPMeta_GetProperty_Int64_1 ( schemaNS, propName, &abiValue, options ) ); - if ( found && (propValue != 0) ) *propValue = abiValue; - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double * propValue, - XMP_OptionBits * options ) const -{ - WrapCheckBool ( found, zXMPMeta_GetProperty_Float_1 ( schemaNS, propName, propValue, options ) ); - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,bool):: -GetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_DateTime * propValue, - XMP_OptionBits * options ) const -{ - WrapCheckBool ( found, zXMPMeta_GetProperty_Date_1 ( schemaNS, propName, propValue, options ) ); - return found; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool propValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetProperty_Bool_1 ( schemaNS, propName, propValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long propValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetProperty_Int_1 ( schemaNS, propName, propValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - long long propValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetProperty_Int64_1 ( schemaNS, propName, propValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double propValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetProperty_Float_1 ( schemaNS, propName, propValue, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const XMP_DateTime & propValue, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_SetProperty_Date_1 ( schemaNS, propName, propValue, options ) ); -} - -// ================================================================================================= -// Miscellaneous Member Functions -// ============================== - -XMP_MethodIntro(TXMPMeta,XMPMetaRef):: -GetInternalRef() const -{ - return this->xmpRef; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -GetObjectName ( tStringObj * name ) const -{ - XMP_StringPtr namePtr = 0; - XMP_StringLen nameLen = 0; - WrapCheckVoid ( zXMPMeta_GetObjectName_1 ( &namePtr, &nameLen ) ); - if ( name != 0 ) name->assign ( namePtr, nameLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetObjectName ( XMP_StringPtr name ) -{ - WrapCheckVoid ( zXMPMeta_SetObjectName_1 ( name ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetObjectName ( tStringObj name ) -{ - this->SetObjectName ( name.c_str() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,XMP_OptionBits):: -GetObjectOptions() const -{ - WrapCheckOptions ( options, zXMPMeta_GetObjectOptions_1() ); - return options; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SetObjectOptions ( XMP_OptionBits options ) -{ - WrapCheckVoid ( zXMPMeta_SetObjectOptions_1 ( options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -Sort() -{ - WrapCheckVoid ( zXMPMeta_Sort_1() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -Erase() -{ - WrapCheckVoid ( zXMPMeta_Erase_1() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,TXMPMeta):: -Clone ( XMP_OptionBits options ) const -{ - WrapCheckMetaRef ( cloneRef, zXMPMeta_Clone_1 ( options ) ); - return TXMPMeta ( cloneRef ); // Ref construct will increment the clientRefs. -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,XMP_Index):: -CountArrayItems ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName ) const -{ - WrapCheckIndex ( count, zXMPMeta_CountArrayItems_1 ( schemaNS, arrayName ) ); - return count; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,XMP_Status):: -DumpObject ( XMP_TextOutputProc outProc, - void * refCon ) const -{ - TOPW_Info info ( outProc, refCon ); - WrapCheckStatus ( status, zXMPMeta_DumpObject_1 ( TextOutputProcWrapper, &info ) ); - return status; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -ParseFromBuffer ( XMP_StringPtr buffer, - XMP_StringLen bufferSize, - XMP_OptionBits options /* = 0 */ ) -{ - WrapCheckVoid ( zXMPMeta_ParseFromBuffer_1 ( buffer, bufferSize, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SerializeToBuffer ( tStringObj * pktString, - XMP_OptionBits options, - XMP_StringLen padding, - XMP_StringPtr newline, - XMP_StringPtr indent, - XMP_Index baseIndent /* = 0 */ ) const -{ - XMP_StringPtr resultPtr = 0; - XMP_StringLen resultLen = 0; - WrapCheckVoid ( zXMPMeta_SerializeToBuffer_1 ( &resultPtr, &resultLen, options, padding, newline, indent, baseIndent ) ); - if ( pktString != 0 ) pktString->assign ( resultPtr, resultLen ); - WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPMeta,void):: -SerializeToBuffer ( tStringObj * pktString, - XMP_OptionBits options /* = 0 */, - XMP_StringLen padding /* = 0 */ ) const -{ - this->SerializeToBuffer ( pktString, options, padding, "", "", 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -// ================================================================================================= diff --git a/xmpsdk/include/client-glue/TXMPUtils.incl_cpp b/xmpsdk/include/client-glue/TXMPUtils.incl_cpp deleted file mode 100644 index 6898be73bc..0000000000 --- a/xmpsdk/include/client-glue/TXMPUtils.incl_cpp +++ /dev/null @@ -1,493 +0,0 @@ -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2008 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. -// ================================================================================================= - -// ================================================================================================ -/// \file TXMPUtils.incl_cpp -/// \brief The implementation of the TXMPUtils template class. - -#include "XMPSDK.hpp" -#include "client-glue/WXMP_Common.hpp" -#include "client-glue/WXMPUtils.hpp" - -// ================================================================================================= -// Implementation Guidelines -// ========================= -// -// The implementations of the template functions are very stylized. ... -// -// ================================================================================================= - -XMP_MethodIntro(TXMPUtils,void):: -ComposeArrayItemPath ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - tStringObj * fullPath ) -{ - XMP_StringPtr pathPtr = 0; - XMP_StringLen pathLen = 0; - WrapCheckVoid ( zXMPUtils_ComposeArrayItemPath_1 ( schemaNS, arrayName, itemIndex, &pathPtr, &pathLen ) ); - if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ComposeStructFieldPath ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - tStringObj * fullPath ) -{ - XMP_StringPtr pathPtr = 0; - XMP_StringLen pathLen = 0; - WrapCheckVoid ( zXMPUtils_ComposeStructFieldPath_1 ( schemaNS, structName, fieldNS, fieldName, &pathPtr, &pathLen ) ); - if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ComposeQualifierPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - tStringObj * fullPath ) -{ - XMP_StringPtr pathPtr = 0; - XMP_StringLen pathLen = 0; - WrapCheckVoid ( zXMPUtils_ComposeQualifierPath_1 ( schemaNS, propName, qualNS, qualName, &pathPtr, &pathLen ) ); - if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr langName, - tStringObj * fullPath ) -{ - XMP_StringPtr pathPtr = 0; - XMP_StringLen pathLen = 0; - WrapCheckVoid ( zXMPUtils_ComposeLangSelector_1 ( schemaNS, arrayName, langName, &pathPtr, &pathLen ) ); - if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - const tStringObj & langName, - tStringObj * fullPath ) -{ - TXMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName.c_str(), fullPath ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - tStringObj * fullPath ) -{ - XMP_StringPtr pathPtr = 0; - XMP_StringLen pathLen = 0; - WrapCheckVoid ( zXMPUtils_ComposeFieldSelector_1 ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, - &pathPtr, &pathLen ) ); - if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - const tStringObj & fieldValue, - tStringObj * fullPath ) -{ - TXMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue.c_str(), fullPath ); -} - -// ------------------------------------------------------------------------------------------------- -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertFromBool ( bool binValue, - tStringObj * strValue ) -{ - XMP_StringPtr strPtr = 0; - XMP_StringLen strLen = 0; - WrapCheckVoid ( zXMPUtils_ConvertFromBool_1 ( binValue, &strPtr, &strLen ) ); - if ( strValue != 0 ) strValue->assign ( strPtr, strLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertFromInt ( long binValue, - XMP_StringPtr format, - tStringObj * strValue ) -{ - XMP_StringPtr strPtr = 0; - XMP_StringLen strLen = 0; - WrapCheckVoid ( zXMPUtils_ConvertFromInt_1 ( binValue, format, &strPtr, &strLen ) ); - if ( strValue != 0 ) strValue->assign ( strPtr, strLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertFromInt64 ( long long binValue, - XMP_StringPtr format, - tStringObj * strValue ) -{ - XMP_StringPtr strPtr = 0; - XMP_StringLen strLen = 0; - WrapCheckVoid ( zXMPUtils_ConvertFromInt64_1 ( binValue, format, &strPtr, &strLen ) ); - if ( strValue != 0 ) strValue->assign ( strPtr, strLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertFromFloat ( double binValue, - XMP_StringPtr format, - tStringObj * strValue ) -{ - XMP_StringPtr strPtr = 0; - XMP_StringLen strLen = 0; - WrapCheckVoid ( zXMPUtils_ConvertFromFloat_1 ( binValue, format, &strPtr, &strLen ) ); - if ( strValue != 0 ) strValue->assign ( strPtr, strLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertFromDate ( const XMP_DateTime & binValue, - tStringObj * strValue ) -{ - XMP_StringPtr strPtr = 0; - XMP_StringLen strLen = 0; - WrapCheckVoid ( zXMPUtils_ConvertFromDate_1 ( binValue, &strPtr, &strLen ) ); - if ( strValue != 0 ) strValue->assign ( strPtr, strLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,bool):: -ConvertToBool ( XMP_StringPtr strValue ) -{ - WrapCheckBool ( value, zXMPUtils_ConvertToBool_1 ( strValue ) ); - return value; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,bool):: -ConvertToBool ( const tStringObj & strValue ) -{ - return TXMPUtils::ConvertToBool ( strValue.c_str() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,long):: -ConvertToInt ( XMP_StringPtr strValue ) -{ - WrapCheckInt32 ( value, zXMPUtils_ConvertToInt_1 ( strValue ) ); - return value; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,long):: -ConvertToInt ( const tStringObj & strValue ) -{ - return TXMPUtils::ConvertToInt ( strValue.c_str() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,long long):: -ConvertToInt64 ( XMP_StringPtr strValue ) -{ - WrapCheckInt64 ( value, zXMPUtils_ConvertToInt64_1 ( strValue ) ); - return value; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,long long):: -ConvertToInt64 ( const tStringObj & strValue ) -{ - return TXMPUtils::ConvertToInt64 ( strValue.c_str() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,double):: -ConvertToFloat ( XMP_StringPtr strValue ) -{ - WrapCheckFloat ( value, zXMPUtils_ConvertToFloat_1 ( strValue ) ); - return value; -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,double):: -ConvertToFloat ( const tStringObj & strValue ) -{ - return TXMPUtils::ConvertToFloat ( strValue.c_str() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertToDate ( XMP_StringPtr strValue, - XMP_DateTime * binValue ) -{ - WrapCheckVoid ( zXMPUtils_ConvertToDate_1 ( strValue, binValue ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertToDate ( const tStringObj & strValue, - XMP_DateTime * binValue ) -{ - TXMPUtils::ConvertToDate ( strValue.c_str(), binValue ); -} - -// ------------------------------------------------------------------------------------------------- -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -CurrentDateTime ( XMP_DateTime * time ) -{ - WrapCheckVoid ( zXMPUtils_CurrentDateTime_1 ( time ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -SetTimeZone ( XMP_DateTime * time ) -{ - WrapCheckVoid ( zXMPUtils_SetTimeZone_1 ( time ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertToUTCTime ( XMP_DateTime * time ) -{ - WrapCheckVoid ( zXMPUtils_ConvertToUTCTime_1 ( time ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -ConvertToLocalTime ( XMP_DateTime * time ) -{ - WrapCheckVoid ( zXMPUtils_ConvertToLocalTime_1 ( time ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,int):: -CompareDateTime ( const XMP_DateTime & left, - const XMP_DateTime & right ) -{ - WrapCheckInt32 ( result, zXMPUtils_CompareDateTime_1 ( left, right ) ); - return result; -} - -// ------------------------------------------------------------------------------------------------- -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -EncodeToBase64 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - tStringObj * encodedStr ) -{ - XMP_StringPtr encPtr = 0; - XMP_StringLen encLen = 0; - WrapCheckVoid ( zXMPUtils_EncodeToBase64_1 ( rawStr, rawLen, &encPtr, &encLen ) ); - if ( encodedStr != 0 ) encodedStr->assign ( encPtr, encLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -EncodeToBase64 ( const tStringObj & rawStr, - tStringObj * encodedStr ) -{ - TXMPUtils::EncodeToBase64 ( rawStr.c_str(), (XMP_StringLen)rawStr.size(), encodedStr ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -DecodeFromBase64 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - tStringObj * rawStr ) -{ - XMP_StringPtr rawPtr = 0; - XMP_StringLen rawLen = 0; - WrapCheckVoid ( zXMPUtils_DecodeFromBase64_1 ( encodedStr, encodedLen, &rawPtr, &rawLen ) ); - if ( rawStr != 0 ) rawStr->assign ( rawPtr, rawLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -DecodeFromBase64 ( const tStringObj & encodedStr, - tStringObj * rawStr ) -{ - TXMPUtils::DecodeFromBase64 ( encodedStr.c_str(), (XMP_StringLen)encodedStr.size(), rawStr ); -} - -// ------------------------------------------------------------------------------------------------- -// ------------------------------------------------------------------------------------------------- - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -PackageForJPEG ( const TXMPMeta & xmpObj, - tStringObj * standardXMP, - tStringObj * extendedXMP, - tStringObj * extendedDigest ) -{ - XMP_StringPtr stdStr = 0; - XMP_StringLen stdLen = 0; - XMP_StringPtr extStr = 0; - XMP_StringLen extLen = 0; - XMP_StringPtr digestStr = 0; - XMP_StringLen digestLen = 0; - WrapCheckVoid ( zXMPUtils_PackageForJPEG_1 ( xmpObj.GetInternalRef(), - &stdStr, &stdLen, &extStr, &extLen, &digestStr, &digestLen ) ); - if ( standardXMP != 0 ) standardXMP->assign ( stdStr, stdLen ); - if ( extendedXMP != 0 ) extendedXMP->assign ( extStr, extLen ); - if ( extendedDigest != 0 ) extendedDigest->assign ( digestStr, digestLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -MergeFromJPEG ( TXMPMeta * fullXMP, - const TXMPMeta & extendedXMP ) -{ - WrapCheckVoid ( zXMPUtils_MergeFromJPEG_1 ( fullXMP->GetInternalRef(), extendedXMP.GetInternalRef() ) ); -} - -// ------------------------------------------------------------------------------------------------- -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -CatenateArrayItems ( const TXMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr separator, - XMP_StringPtr quotes, - XMP_OptionBits options, - tStringObj * catedStr ) -{ - XMP_StringPtr catedPtr = 0; - XMP_StringLen catedLen = 0; - WrapCheckVoid ( zXMPUtils_CatenateArrayItems_1 ( xmpObj.GetInternalRef(), schemaNS, arrayName, - separator, quotes, options, &catedPtr, &catedLen ) ); - if ( catedStr != 0 ) catedStr->assign ( catedPtr, catedLen ); - WXMPUtils_Unlock_1 ( 0 ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -SeparateArrayItems ( TXMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr ) -{ - if ( xmpObj == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" ); - WrapCheckVoid ( zXMPUtils_SeparateArrayItems_1 ( xmpObj->GetInternalRef(), schemaNS, arrayName, options, catedStr ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -SeparateArrayItems ( TXMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - const tStringObj & catedStr ) -{ - TXMPUtils::SeparateArrayItems ( xmpObj, schemaNS, arrayName, options, catedStr.c_str() ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -RemoveProperties ( TXMPMeta * xmpObj, - XMP_StringPtr schemaNS /* = 0 */, - XMP_StringPtr propName /* = 0 */, - XMP_OptionBits options /* = 0 */ ) -{ - if ( xmpObj == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" ); - WrapCheckVoid ( zXMPUtils_RemoveProperties_1 ( xmpObj->GetInternalRef(), schemaNS, propName, options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -AppendProperties ( const TXMPMeta & source, - TXMPMeta * dest, - XMP_OptionBits options /* = 0 */ ) -{ - if ( dest == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" ); - WrapCheckVoid ( zXMPUtils_AppendProperties_1 ( source.GetInternalRef(), dest->GetInternalRef(), options ) ); -} - -// ------------------------------------------------------------------------------------------------- - -XMP_MethodIntro(TXMPUtils,void):: -DuplicateSubtree ( const TXMPMeta & source, - TXMPMeta * dest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS /*= 0 */, - XMP_StringPtr destRoot /* = 0 */, - XMP_OptionBits options /* = 0 */ ) -{ - if ( dest == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" ); - WrapCheckVoid ( zXMPUtils_DuplicateSubtree_1 ( source.GetInternalRef(), dest->GetInternalRef(), - sourceNS, sourceRoot, destNS, destRoot, options ) ); -} - -// ================================================================================================= - -// ================================================================================================= diff --git a/xmpsdk/include/client-glue/WXMPFiles.hpp b/xmpsdk/include/client-glue/WXMPFiles.hpp deleted file mode 100644 index cdc510ce89..0000000000 --- a/xmpsdk/include/client-glue/WXMPFiles.hpp +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef __WXMPFiles_hpp__ -#define __WXMPFiles_hpp__ 1 - -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2002-2007 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 "client-glue/WXMP_Common.hpp" - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= -/// \file WXMPFiles.h -/// \brief High level support to access metadata in files of interest to Adobe applications. -/// -/// This header ... -/// -// ================================================================================================= - -// ================================================================================================= - -#define WrapCheckXMPFilesRef(result,WCallProto) \ - WXMP_Result wResult; \ - WCallProto; \ - PropagateException ( wResult ); \ - XMPFilesRef result = XMPFilesRef(wResult.ptrResult) - -// ================================================================================================= - -#define zXMPFiles_GetVersionInfo_1(versionInfo) \ - WXMPFiles_GetVersionInfo_1 ( versionInfo /* no wResult */ ) - -#define zXMPFiles_Initialize_1() \ - WXMPFiles_Initialize_1 ( &wResult ) - -#define zXMPFiles_Initialize_2(options) \ - WXMPFiles_Initialize_2 ( options, &wResult ) - -#define zXMPFiles_Terminate_1() \ - WXMPFiles_Terminate_1 ( /* no wResult */ ) - -#define zXMPFiles_CTor_1() \ - WXMPFiles_CTor_1 ( &wResult ) - -#define zXMPFiles_GetFormatInfo_1(format,flags) \ - WXMPFiles_GetFormatInfo_1 ( format, flags, &wResult ) - -#define zXMPFiles_CheckFileFormat_1(filePath) \ - WXMPFiles_CheckFileFormat_1 ( filePath, &wResult ) - -#define zXMPFiles_CheckPackageFormat_1(folderPath) \ - WXMPFiles_CheckPackageFormat_1 ( folderPath, &wResult ) - -#define zXMPFiles_OpenFile_1(filePath,format,openFlags) \ - WXMPFiles_OpenFile_1 ( this->xmpFilesRef, filePath, format, openFlags, &wResult ) - -#define zXMPFiles_CloseFile_1(closeFlags) \ - WXMPFiles_CloseFile_1 ( this->xmpFilesRef, closeFlags, &wResult ) - -#define zXMPFiles_GetFileInfo_1(filePath,filePathLen,openFlags,format,handlerFlags) \ - WXMPFiles_GetFileInfo_1 ( this->xmpFilesRef, filePath, filePathLen, openFlags, format, handlerFlags, &wResult ) - -#define zXMPFiles_SetAbortProc_1(abortProc,abortArg) \ - WXMPFiles_SetAbortProc_1 ( this->xmpFilesRef, abortProc, abortArg, &wResult ) - -#define zXMPFiles_GetXMP_1(xmpRef,xmpPacket,xmpPacketLen,packetInfo) \ - WXMPFiles_GetXMP_1 ( this->xmpFilesRef, xmpRef, xmpPacket, xmpPacketLen, packetInfo, &wResult ) - -#define zXMPFiles_GetThumbnail_1(tnailInfo) \ - WXMPFiles_GetThumbnail_1 ( this->xmpFilesRef, tnailInfo, &wResult ) - -#define zXMPFiles_PutXMP_1(xmpRef,xmpPacket,xmpPacketLen) \ - WXMPFiles_PutXMP_1 ( this->xmpFilesRef, xmpRef, xmpPacket, xmpPacketLen, &wResult ) - -#define zXMPFiles_CanPutXMP_1(xmpRef,xmpPacket,xmpPacketLen) \ - WXMPFiles_CanPutXMP_1 ( this->xmpFilesRef, xmpRef, xmpPacket, xmpPacketLen, &wResult ) - -// ================================================================================================= - -extern void WXMPFiles_GetVersionInfo_1 ( XMP_VersionInfo * versionInfo ); - -extern void WXMPFiles_Initialize_1 ( WXMP_Result * result ); - -extern void WXMPFiles_Initialize_2 ( XMP_OptionBits options, WXMP_Result * result ); - -extern void WXMPFiles_Terminate_1(); - -extern void WXMPFiles_CTor_1 ( WXMP_Result * result ); - -extern void WXMPFiles_UnlockLib_1(); - -extern void WXMPFiles_UnlockObj_1 ( XMPFilesRef xmpFilesRef ); - -extern void WXMPFiles_IncrementRefCount_1 ( XMPFilesRef xmpFilesRef ); - -extern void WXMPFiles_DecrementRefCount_1 ( XMPFilesRef xmpFilesRef ); - -extern void WXMPFiles_GetFormatInfo_1 ( XMP_FileFormat format, - XMP_OptionBits * flags, // ! Can be null. - WXMP_Result * result ); - -extern void WXMPFiles_CheckFileFormat_1 ( XMP_StringPtr filePath, - WXMP_Result * result ); - -extern void WXMPFiles_CheckPackageFormat_1 ( XMP_StringPtr folderPath, - WXMP_Result * result ); - -extern void WXMPFiles_OpenFile_1 ( XMPFilesRef xmpFilesRef, - XMP_StringPtr filePath, - XMP_FileFormat format, - XMP_OptionBits openFlags, - WXMP_Result * result ); - -extern void WXMPFiles_CloseFile_1 ( XMPFilesRef xmpFilesRef, - XMP_OptionBits closeFlags, - WXMP_Result * result ); - -extern void WXMPFiles_GetFileInfo_1 ( XMPFilesRef xmpFilesRef, - XMP_StringPtr * filePath, - XMP_StringLen * filePathLen, - XMP_OptionBits * openFlags, // ! Can be null. - XMP_FileFormat * format, // ! Can be null. - XMP_OptionBits * handlerFlags, // ! Can be null. - WXMP_Result * result ); - -extern void WXMPFiles_SetAbortProc_1 ( XMPFilesRef xmpFilesRef, - XMP_AbortProc abortProc, - void * abortArg, - WXMP_Result * result ); - -extern void WXMPFiles_GetXMP_1 ( XMPFilesRef xmpFilesRef, - XMPMetaRef xmpRef, // ! Can be null. - XMP_StringPtr * xmpPacket, - XMP_StringLen * xmpPacketLen, - XMP_PacketInfo * packetInfo, // ! Can be null. - WXMP_Result * result ); - -extern void WXMPFiles_GetThumbnail_1 ( XMPFilesRef xmpFilesRef, - XMP_ThumbnailInfo * tnailInfo, // ! Can be null. - WXMP_Result * result ); - -extern void WXMPFiles_PutXMP_1 ( XMPFilesRef xmpFilesRef, - XMPMetaRef xmpRef, // ! Only one of the XMP object or packet are passed. - XMP_StringPtr xmpPacket, - XMP_StringLen xmpPacketLen, - WXMP_Result * result ); - -extern void WXMPFiles_CanPutXMP_1 ( XMPFilesRef xmpFilesRef, - XMPMetaRef xmpRef, // ! Only one of the XMP object or packet are passed. - XMP_StringPtr xmpPacket, - XMP_StringLen xmpPacketLen, - WXMP_Result * result ); - -// ================================================================================================= - -#if __cplusplus -} -#endif - -#endif // __WXMPFiles_hpp__ diff --git a/xmpsdk/include/client-glue/WXMPIterator.hpp b/xmpsdk/include/client-glue/WXMPIterator.hpp deleted file mode 100644 index c5e9e26d2c..0000000000 --- a/xmpsdk/include/client-glue/WXMPIterator.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#if ! __WXMPIterator_hpp__ -#define __WXMPIterator_hpp__ 1 - -// ================================================================================================= -// Copyright 2002-2007 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 "client-glue/WXMP_Common.hpp" - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= - -#define zXMPIterator_PropCTor_1(xmpRef,schemaNS,propName,options) \ - WXMPIterator_PropCTor_1 ( xmpRef, schemaNS, propName, options, &wResult ); - -#define zXMPIterator_TableCTor_1(schemaNS,propName,options) \ - WXMPIterator_TableCTor_1 ( schemaNS, propName, options, &wResult ); - - -#define zXMPIterator_Next_1(schemaNS,nsSize,propPath,pathSize,propValue,valueSize,options) \ - WXMPIterator_Next_1 ( this->iterRef, schemaNS, nsSize, propPath, pathSize, propValue, valueSize, options, &wResult ); - -#define zXMPIterator_Skip_1(options) \ - WXMPIterator_Skip_1 ( this->iterRef, options, &wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPIterator_PropCTor_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPIterator_TableCTor_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPIterator_IncrementRefCount_1 ( XMPIteratorRef iterRef ); - -extern void -WXMPIterator_DecrementRefCount_1 ( XMPIteratorRef iterRef ); - -extern void -WXMPIterator_Unlock_1 ( XMP_OptionBits options ); - -extern void -WXMPIterator_Next_1 ( XMPIteratorRef iterRef, - XMP_StringPtr * schemaNS, - XMP_StringLen * nsSize, - XMP_StringPtr * propPath, - XMP_StringLen * pathSize, - XMP_StringPtr * propValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ); - -extern void -WXMPIterator_Skip_1 ( XMPIteratorRef iterRef, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPUtils_UnlockIter_1 ( XMPIteratorRef iterRef, - XMP_OptionBits options ); - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif - -#endif // __WXMPIterator_hpp__ diff --git a/xmpsdk/include/client-glue/WXMPMeta.hpp b/xmpsdk/include/client-glue/WXMPMeta.hpp deleted file mode 100644 index ca94374258..0000000000 --- a/xmpsdk/include/client-glue/WXMPMeta.hpp +++ /dev/null @@ -1,622 +0,0 @@ -#if ! __WXMPMeta_hpp__ -#define __WXMPMeta_hpp__ 1 - -// ================================================================================================= -// Copyright 2002-2008 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 "client-glue/WXMP_Common.hpp" - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= -#define zXMPMeta_GetVersionInfo_1(info) \ - WXMPMeta_GetVersionInfo_1 ( info /* no wResult */ ) - -#define zXMPMeta_Initialize_1() \ - WXMPMeta_Initialize_1 ( &wResult ) -#define zXMPMeta_Terminate_1() \ - WXMPMeta_Terminate_1 ( /* no wResult */ ) - -#define zXMPMeta_CTor_1() \ - WXMPMeta_CTor_1 ( &wResult ) - -#define zXMPMeta_GetGlobalOptions_1() \ - WXMPMeta_GetGlobalOptions_1 ( &wResult ) - -#define zXMPMeta_SetGlobalOptions_1(options) \ - WXMPMeta_SetGlobalOptions_1 ( options, &wResult ) - -#define zXMPMeta_DumpNamespaces_1(outProc,refCon) \ - WXMPMeta_DumpNamespaces_1 ( outProc, refCon, &wResult ) - -#define zXMPMeta_DumpAliases_1(outProc,refCon) \ - WXMPMeta_DumpAliases_1 ( outProc, refCon, &wResult ) - -#define zXMPMeta_RegisterNamespace_1(namespaceURI,prefix) \ - WXMPMeta_RegisterNamespace_1 ( namespaceURI, prefix, &wResult ) - -#define zXMPMeta_GetNamespacePrefix_1(namespaceURI,namespacePrefix,prefixSize) \ - WXMPMeta_GetNamespacePrefix_1 ( namespaceURI, namespacePrefix, prefixSize, &wResult ) - -#define zXMPMeta_GetNamespaceURI_1(namespacePrefix,namespaceURI,uriSize) \ - WXMPMeta_GetNamespaceURI_1 ( namespacePrefix, namespaceURI, uriSize, &wResult ) - -#define zXMPMeta_DeleteNamespace_1(namespaceURI) \ - WXMPMeta_DeleteNamespace_1 ( namespaceURI, &wResult ) - -#define zXMPMeta_RegisterAlias_1(aliasNS,aliasProp,actualNS,actualProp,arrayForm) \ - WXMPMeta_RegisterAlias_1 ( aliasNS, aliasProp, actualNS, actualProp, arrayForm, &wResult ) - -#define zXMPMeta_ResolveAlias_1(aliasNS,aliasProp,actualNS,nsSize,actualProp,propSize,arrayForm) \ - WXMPMeta_ResolveAlias_1 ( aliasNS, aliasProp, actualNS, nsSize, actualProp, propSize, arrayForm, &wResult ) - -#define zXMPMeta_DeleteAlias_1(aliasNS,aliasProp) \ - WXMPMeta_DeleteAlias_1 ( aliasNS, aliasProp, &wResult ) - -#define zXMPMeta_RegisterStandardAliases_1(schemaNS) \ - WXMPMeta_RegisterStandardAliases_1 ( schemaNS, &wResult ) - -#define zXMPMeta_GetProperty_1(schemaNS,propName,propValue,valueSize,options) \ - WXMPMeta_GetProperty_1 ( this->xmpRef, schemaNS, propName, propValue, valueSize, options, &wResult ) - -#define zXMPMeta_GetArrayItem_1(schemaNS,arrayName,itemIndex,itemValue,valueSize,options) \ - WXMPMeta_GetArrayItem_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, itemValue, valueSize, options, &wResult ) - -#define zXMPMeta_GetStructField_1(schemaNS,structName,fieldNS,fieldName,fieldValue,valueSize,options) \ - WXMPMeta_GetStructField_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, fieldValue, valueSize, options, &wResult ) - -#define zXMPMeta_GetQualifier_1(schemaNS,propName,qualNS,qualName,qualValue,valueSize,options) \ - WXMPMeta_GetQualifier_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, qualValue, valueSize, options, &wResult ) - -#define zXMPMeta_SetProperty_1(schemaNS,propName,propValue,options) \ - WXMPMeta_SetProperty_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_SetArrayItem_1(schemaNS,arrayName,itemIndex,itemValue,options) \ - WXMPMeta_SetArrayItem_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, itemValue, options, &wResult ) - -#define zXMPMeta_AppendArrayItem_1(schemaNS,arrayName,arrayOptions,itemValue,options) \ - WXMPMeta_AppendArrayItem_1 ( this->xmpRef, schemaNS, arrayName, arrayOptions, itemValue, options, &wResult ) - -#define zXMPMeta_SetStructField_1(schemaNS,structName,fieldNS,fieldName,fieldValue,options) \ - WXMPMeta_SetStructField_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, fieldValue, options, &wResult ) - -#define zXMPMeta_SetQualifier_1(schemaNS,propName,qualNS,qualName,qualValue,options) \ - WXMPMeta_SetQualifier_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, qualValue, options, &wResult ) - -#define zXMPMeta_DeleteProperty_1(schemaNS,propName) \ - WXMPMeta_DeleteProperty_1 ( this->xmpRef, schemaNS, propName, &wResult ) - -#define zXMPMeta_DeleteArrayItem_1(schemaNS,arrayName,itemIndex) \ - WXMPMeta_DeleteArrayItem_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, &wResult ) - -#define zXMPMeta_DeleteStructField_1(schemaNS,structName,fieldNS,fieldName) \ - WXMPMeta_DeleteStructField_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, &wResult ) - -#define zXMPMeta_DeleteQualifier_1(schemaNS,propName,qualNS,qualName) \ - WXMPMeta_DeleteQualifier_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, &wResult ) - -#define zXMPMeta_DoesPropertyExist_1(schemaNS,propName) \ - WXMPMeta_DoesPropertyExist_1 ( this->xmpRef, schemaNS, propName, &wResult ) - -#define zXMPMeta_DoesArrayItemExist_1(schemaNS,arrayName,itemIndex) \ - WXMPMeta_DoesArrayItemExist_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, &wResult ) - -#define zXMPMeta_DoesStructFieldExist_1(schemaNS,structName,fieldNS,fieldName) \ - WXMPMeta_DoesStructFieldExist_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, &wResult ) - -#define zXMPMeta_DoesQualifierExist_1(schemaNS,propName,qualNS,qualName) \ - WXMPMeta_DoesQualifierExist_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, &wResult ) - -#define zXMPMeta_GetLocalizedText_1(schemaNS,altTextName,genericLang,specificLang,actualLang,langSize,itemValue,valueSize,options) \ - WXMPMeta_GetLocalizedText_1 ( this->xmpRef, schemaNS, altTextName, genericLang, specificLang, actualLang, langSize, itemValue, valueSize, options, &wResult ) - -#define zXMPMeta_SetLocalizedText_1(schemaNS,altTextName,genericLang,specificLang,itemValue,options) \ - WXMPMeta_SetLocalizedText_1 ( this->xmpRef, schemaNS, altTextName, genericLang, specificLang, itemValue, options, &wResult ) - -#define zXMPMeta_GetProperty_Bool_1(schemaNS,propName,propValue,options) \ - WXMPMeta_GetProperty_Bool_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_GetProperty_Int_1(schemaNS,propName,propValue,options) \ - WXMPMeta_GetProperty_Int_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_GetProperty_Int64_1(schemaNS,propName,propValue,options) \ - WXMPMeta_GetProperty_Int64_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_GetProperty_Float_1(schemaNS,propName,propValue,options) \ - WXMPMeta_GetProperty_Float_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_GetProperty_Date_1(schemaNS,propName,propValue,options) \ - WXMPMeta_GetProperty_Date_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_SetProperty_Bool_1(schemaNS,propName,propValue,options) \ - WXMPMeta_SetProperty_Bool_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_SetProperty_Int_1(schemaNS,propName,propValue,options) \ - WXMPMeta_SetProperty_Int_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_SetProperty_Int64_1(schemaNS,propName,propValue,options) \ - WXMPMeta_SetProperty_Int64_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_SetProperty_Float_1(schemaNS,propName,propValue,options) \ - WXMPMeta_SetProperty_Float_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_SetProperty_Date_1(schemaNS,propName,propValue,options) \ - WXMPMeta_SetProperty_Date_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult ) - -#define zXMPMeta_GetObjectName_1(namePtr,nameLen) \ - WXMPMeta_GetObjectName_1 ( this->xmpRef, namePtr, nameLen, &wResult ) - -#define zXMPMeta_SetObjectName_1(name) \ - WXMPMeta_SetObjectName_1 ( this->xmpRef, name, &wResult ) - -#define zXMPMeta_GetObjectOptions_1() \ - WXMPMeta_GetObjectOptions_1 ( this->xmpRef, &wResult ) - -#define zXMPMeta_SetObjectOptions_1(options) \ - WXMPMeta_SetObjectOptions_1 ( this->xmpRef, options, &wResult ) - -#define zXMPMeta_Sort_1() \ - WXMPMeta_Sort_1 ( this->xmpRef, &wResult ) - -#define zXMPMeta_Erase_1() \ - WXMPMeta_Erase_1 ( this->xmpRef, &wResult ) - -#define zXMPMeta_Clone_1(options) \ - WXMPMeta_Clone_1 ( this->xmpRef, options, &wResult ) - -#define zXMPMeta_CountArrayItems_1(schemaNS,arrayName) \ - WXMPMeta_CountArrayItems_1 ( this->xmpRef, schemaNS, arrayName, &wResult ) - -#define zXMPMeta_DumpObject_1(outProc,refCon) \ - WXMPMeta_DumpObject_1 ( this->xmpRef, outProc, refCon, &wResult ) - -#define zXMPMeta_ParseFromBuffer_1(buffer,bufferSize,options) \ - WXMPMeta_ParseFromBuffer_1 ( this->xmpRef, buffer, bufferSize, options, &wResult ) - -#define zXMPMeta_SerializeToBuffer_1(pktString,pktSize,options,padding,newline,indent,baseIndent) \ - WXMPMeta_SerializeToBuffer_1 ( this->xmpRef, pktString, pktSize, options, padding, newline, indent, baseIndent, &wResult ) - -// ================================================================================================= - -extern void -WXMPMeta_GetVersionInfo_1 ( XMP_VersionInfo * info ); - -extern void -WXMPMeta_Initialize_1 ( WXMP_Result * wResult ); -extern void -WXMPMeta_Terminate_1(); - -extern void -WXMPMeta_Unlock_1 ( XMP_OptionBits options ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_CTor_1 ( WXMP_Result * wResult ); - -extern void -WXMPMeta_IncrementRefCount_1 ( XMPMetaRef xmpRef ); - -extern void -WXMPMeta_DecrementRefCount_1 ( XMPMetaRef xmpRef ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_GetGlobalOptions_1 ( WXMP_Result * wResult ); - -extern void -WXMPMeta_SetGlobalOptions_1 ( XMP_OptionBits options, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_DumpNamespaces_1 ( XMP_TextOutputProc outProc, - void * refCon, - WXMP_Result * wResult ); - -extern void -WXMPMeta_DumpAliases_1 ( XMP_TextOutputProc outProc, - void * refCon, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_RegisterNamespace_1 ( XMP_StringPtr namespaceURI, - XMP_StringPtr prefix, - WXMP_Result * wResult ); - -extern void -WXMPMeta_GetNamespacePrefix_1 ( XMP_StringPtr namespaceURI, - XMP_StringPtr * namespacePrefix, - XMP_StringLen * prefixSize, - WXMP_Result * wResult ); - -extern void -WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr namespacePrefix, - XMP_StringPtr * namespaceURI, - XMP_StringLen * uriSize, - WXMP_Result * wResult ); - -extern void -WXMPMeta_DeleteNamespace_1 ( XMP_StringPtr namespaceURI, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_RegisterAlias_1 ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr actualNS, - XMP_StringPtr actualProp, - XMP_OptionBits arrayForm, - WXMP_Result * wResult ); - -extern void -WXMPMeta_ResolveAlias_1 ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr * actualNS, - XMP_StringLen * nsSize, - XMP_StringPtr * actualProp, - XMP_StringLen * propSize, - XMP_OptionBits * arrayForm, - WXMP_Result * wResult ); - -extern void -WXMPMeta_DeleteAlias_1 ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - WXMP_Result * wResult ); - -extern void -WXMPMeta_RegisterStandardAliases_1 ( XMP_StringPtr schemaNS, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_UnlockObject_1 ( XMPMetaRef xmpRef, - XMP_OptionBits options ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_GetProperty_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr * propValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * itemValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetStructField_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fieldValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetQualifier_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * qualValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_SetProperty_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr propValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr itemValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_AppendArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - XMP_StringPtr itemValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetStructField_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetQualifier_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr qualValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_DeleteProperty_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - WXMP_Result * wResult ); - -extern void -WXMPMeta_DeleteArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - WXMP_Result * wResult ); - -extern void -WXMPMeta_DeleteStructField_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - WXMP_Result * wResult ); - -extern void -WXMPMeta_DeleteQualifier_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_DoesPropertyExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_DoesArrayItemExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_DoesStructFieldExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_DoesQualifierExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - WXMP_Result * wResult ) /* const */ ; - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_GetLocalizedText_1 ( XMPMetaRef xmpRef, - 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, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_SetLocalizedText_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - XMP_StringPtr itemValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Bool * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetProperty_Int_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetProperty_Float_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_GetProperty_Date_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_DateTime * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_SetProperty_Bool_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Bool propValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetProperty_Int_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 propValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetProperty_Int64_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 propValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetProperty_Float_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double propValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SetProperty_Date_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const XMP_DateTime & propValue, - XMP_OptionBits options, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_GetObjectName_1 ( XMPMetaRef xmpRef, - XMP_StringPtr * namePtr, - XMP_StringLen * nameLen, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_SetObjectName_1 ( XMPMetaRef xmpRef, - XMP_StringPtr name, - WXMP_Result * wResult ); - -extern void -WXMPMeta_GetObjectOptions_1 ( XMPMetaRef xmpRef, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_SetObjectOptions_1 ( XMPMetaRef xmpRef, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_Sort_1 ( XMPMetaRef xmpRef, - WXMP_Result * wResult ); - -extern void -WXMPMeta_Erase_1 ( XMPMetaRef xmpRef, - WXMP_Result * wResult ); - -extern void -WXMPMeta_Clone_1 ( XMPMetaRef xmpRef, - XMP_OptionBits options, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_CountArrayItems_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - WXMP_Result * wResult ) /* const */ ; - -extern void -WXMPMeta_DumpObject_1 ( XMPMetaRef xmpRef, - XMP_TextOutputProc outProc, - void * refCon, - WXMP_Result * wResult ) /* const */ ; - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPMeta_ParseFromBuffer_1 ( XMPMetaRef xmpRef, - XMP_StringPtr buffer, - XMP_StringLen bufferSize, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef xmpRef, - XMP_StringPtr * pktString, - XMP_StringLen * pktSize, - XMP_OptionBits options, - XMP_StringLen padding, - XMP_StringPtr newline, - XMP_StringPtr indent, - XMP_Index baseIndent, - WXMP_Result * wResult ) /* const */ ; - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif - -#endif // __WXMPMeta_hpp__ diff --git a/xmpsdk/include/client-glue/WXMPUtils.hpp b/xmpsdk/include/client-glue/WXMPUtils.hpp deleted file mode 100644 index 55890fc5d8..0000000000 --- a/xmpsdk/include/client-glue/WXMPUtils.hpp +++ /dev/null @@ -1,322 +0,0 @@ -#if ! __WXMPUtils_hpp__ -#define __WXMPUtils_hpp__ 1 - -// ================================================================================================= -// Copyright 2002-2008 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 "client-glue/WXMP_Common.hpp" - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= - -#define zXMPUtils_ComposeArrayItemPath_1(schemaNS,arrayName,itemIndex,fullPath,pathSize) \ - WXMPUtils_ComposeArrayItemPath_1 ( schemaNS, arrayName, itemIndex, fullPath, pathSize, &wResult ); - -#define zXMPUtils_ComposeStructFieldPath_1(schemaNS,structName,fieldNS,fieldName,fullPath,pathSize) \ - WXMPUtils_ComposeStructFieldPath_1 ( schemaNS, structName, fieldNS, fieldName, fullPath, pathSize, &wResult ); - -#define zXMPUtils_ComposeQualifierPath_1(schemaNS,propName,qualNS,qualName,fullPath,pathSize) \ - WXMPUtils_ComposeQualifierPath_1 ( schemaNS, propName, qualNS, qualName, fullPath, pathSize, &wResult ); - -#define zXMPUtils_ComposeLangSelector_1(schemaNS,arrayName,langName,fullPath,pathSize) \ - WXMPUtils_ComposeLangSelector_1 ( schemaNS, arrayName, langName, fullPath, pathSize, &wResult ); - -#define zXMPUtils_ComposeFieldSelector_1(schemaNS,arrayName,fieldNS,fieldName,fieldValue,fullPath,pathSize) \ - WXMPUtils_ComposeFieldSelector_1 ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, fullPath, pathSize, &wResult ); - -#define zXMPUtils_ConvertFromBool_1(binValue,strValue,strSize) \ - WXMPUtils_ConvertFromBool_1 ( binValue, strValue, strSize, &wResult ); - -#define zXMPUtils_ConvertFromInt_1(binValue,format,strValue,strSize) \ - WXMPUtils_ConvertFromInt_1 ( binValue, format, strValue, strSize, &wResult ); - -#define zXMPUtils_ConvertFromInt64_1(binValue,format,strValue,strSize) \ - WXMPUtils_ConvertFromInt64_1 ( binValue, format, strValue, strSize, &wResult ); - -#define zXMPUtils_ConvertFromFloat_1(binValue,format,strValue,strSize) \ - WXMPUtils_ConvertFromFloat_1 ( binValue, format, strValue, strSize, &wResult ); - -#define zXMPUtils_ConvertFromDate_1(binValue,strValue,strSize) \ - WXMPUtils_ConvertFromDate_1 ( binValue, strValue, strSize, &wResult ); - -#define zXMPUtils_ConvertToBool_1(strValue) \ - WXMPUtils_ConvertToBool_1 ( strValue, &wResult ); - -#define zXMPUtils_ConvertToInt_1(strValue) \ - WXMPUtils_ConvertToInt_1 ( strValue, &wResult ); - -#define zXMPUtils_ConvertToInt64_1(strValue) \ - WXMPUtils_ConvertToInt64_1 ( strValue, &wResult ); - -#define zXMPUtils_ConvertToFloat_1(strValue) \ - WXMPUtils_ConvertToFloat_1 ( strValue, &wResult ); - -#define zXMPUtils_ConvertToDate_1(strValue,binValue) \ - WXMPUtils_ConvertToDate_1 ( strValue, binValue, &wResult ); - -#define zXMPUtils_CurrentDateTime_1(time) \ - WXMPUtils_CurrentDateTime_1 ( time, &wResult ); - -#define zXMPUtils_SetTimeZone_1(time) \ - WXMPUtils_SetTimeZone_1 ( time, &wResult ); - -#define zXMPUtils_ConvertToUTCTime_1(time) \ - WXMPUtils_ConvertToUTCTime_1 ( time, &wResult ); - -#define zXMPUtils_ConvertToLocalTime_1(time) \ - WXMPUtils_ConvertToLocalTime_1 ( time, &wResult ); - -#define zXMPUtils_CompareDateTime_1(left,right) \ - WXMPUtils_CompareDateTime_1 ( left, right, &wResult ); - -#define zXMPUtils_EncodeToBase64_1(rawStr,rawLen,encodedStr,encodedLen) \ - WXMPUtils_EncodeToBase64_1 ( rawStr, rawLen, encodedStr, encodedLen, &wResult ); - -#define zXMPUtils_DecodeFromBase64_1(encodedStr,encodedLen,rawStr,rawLen) \ - WXMPUtils_DecodeFromBase64_1 ( encodedStr, encodedLen, rawStr, rawLen, &wResult ); - -#define zXMPUtils_PackageForJPEG_1(xmpObj,stdStr,stdLen,extStr,extLen,digestStr,digestLen) \ - WXMPUtils_PackageForJPEG_1 ( xmpObj, stdStr, stdLen, extStr, extLen, digestStr, digestLen, &wResult ); - -#define zXMPUtils_MergeFromJPEG_1(fullXMP,extendedXMP) \ - WXMPUtils_MergeFromJPEG_1 ( fullXMP, extendedXMP, &wResult ); - -#define zXMPUtils_CatenateArrayItems_1(xmpObj,schemaNS,arrayName,separator,quotes,options,catedPtr,catedLen) \ - WXMPUtils_CatenateArrayItems_1 ( xmpObj, schemaNS, arrayName, separator, quotes, options, catedPtr, catedLen, &wResult ); - -#define zXMPUtils_SeparateArrayItems_1(xmpObj,schemaNS,arrayName,options,catedStr) \ - WXMPUtils_SeparateArrayItems_1 ( xmpObj, schemaNS, arrayName, options, catedStr, &wResult ); - -#define zXMPUtils_RemoveProperties_1(xmpObj,schemaNS,propName,options) \ - WXMPUtils_RemoveProperties_1 ( xmpObj, schemaNS, propName, options, &wResult ); - -#define zXMPUtils_AppendProperties_1(source,dest,options) \ - WXMPUtils_AppendProperties_1 ( source, dest, options, &wResult ); - -#define zXMPUtils_DuplicateSubtree_1(source,dest,sourceNS,sourceRoot,destNS,destRoot,options) \ - WXMPUtils_DuplicateSubtree_1 ( source, dest, sourceNS, sourceRoot, destNS, destRoot, options, &wResult ); - -// ================================================================================================= - -extern void -WXMPUtils_Unlock_1 ( XMP_OptionBits options ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_ComposeArrayItemPath_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ComposeStructFieldPath_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ComposeQualifierPath_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ComposeLangSelector_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr langName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ComposeFieldSelector_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_ConvertFromBool_1 ( XMP_Bool binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertFromInt_1 ( XMP_Int32 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertFromInt64_1 ( XMP_Int64 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertFromFloat_1 ( double binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertFromDate_1 ( const XMP_DateTime & binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_ConvertToBool_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertToInt_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertToInt64_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertToFloat_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertToDate_1 ( XMP_StringPtr strValue, - XMP_DateTime * binValue, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_CurrentDateTime_1 ( XMP_DateTime * time, - WXMP_Result * wResult ); - -extern void -WXMPUtils_SetTimeZone_1 ( XMP_DateTime * time, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertToUTCTime_1 ( XMP_DateTime * time, - WXMP_Result * wResult ); - -extern void -WXMPUtils_ConvertToLocalTime_1 ( XMP_DateTime * time, - WXMP_Result * wResult ); - -extern void -WXMPUtils_CompareDateTime_1 ( const XMP_DateTime & left, - const XMP_DateTime & right, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - XMP_StringPtr * encodedStr, - XMP_StringLen * encodedLen, - WXMP_Result * wResult ); - -extern void -WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - XMP_StringPtr * rawStr, - XMP_StringLen * rawLen, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_PackageForJPEG_1 ( XMPMetaRef xmpObj, - XMP_StringPtr * stdStr, - XMP_StringLen * stdLen, - XMP_StringPtr * extStr, - XMP_StringLen * extLen, - XMP_StringPtr * digestStr, - XMP_StringLen * digestLen, - WXMP_Result * wResult ); - -extern void -WXMPUtils_MergeFromJPEG_1 ( XMPMetaRef fullXMP, - XMPMetaRef extendedXMP, - WXMP_Result * wResult ); - -// ------------------------------------------------------------------------------------------------- - -extern void -WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr separator, - XMP_StringPtr quotes, - XMP_OptionBits options, - XMP_StringPtr * catedStr, - XMP_StringLen * catedLen, - WXMP_Result * wResult ); - -extern void -WXMPUtils_SeparateArrayItems_1 ( XMPMetaRef xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr, - WXMP_Result * wResult ); - -extern void -WXMPUtils_RemoveProperties_1 ( XMPMetaRef xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPUtils_AppendProperties_1 ( XMPMetaRef source, - XMPMetaRef dest, - XMP_OptionBits options, - WXMP_Result * wResult ); - -extern void -WXMPUtils_DuplicateSubtree_1 ( XMPMetaRef source, - XMPMetaRef dest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS, - XMP_StringPtr destRoot, - XMP_OptionBits options, - WXMP_Result * wResult ); - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif - -#endif // __WXMPUtils_hpp__ diff --git a/xmpsdk/include/client-glue/WXMP_Common.hpp b/xmpsdk/include/client-glue/WXMP_Common.hpp deleted file mode 100644 index 4d6eaab429..0000000000 --- a/xmpsdk/include/client-glue/WXMP_Common.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#if ! __WXMP_Common_hpp__ -#define __WXMP_Common_hpp__ 1 - -// ================================================================================================= -// Copyright 2002-2007 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. -// ================================================================================================= - -#ifndef XMP_Inline - #if TXMP_EXPAND_INLINE - #define XMP_Inline inline - #else - #define XMP_Inline /* not inline */ - #endif -#endif - -#define XMP_CTorDTorIntro(Class) template XMP_Inline Class -#define XMP_MethodIntro(Class,ResultType) template XMP_Inline ResultType Class - -struct WXMP_Result { - XMP_StringPtr errMessage; - void * ptrResult; - double floatResult; - XMP_Uns64 int64Result; - XMP_Uns32 int32Result; - WXMP_Result() : errMessage(0) {}; -}; - -#if __cplusplus -extern "C" { -#endif - -#define PropagateException(res) \ - if ( res.errMessage != 0 ) throw XMP_Error ( res.int32Result, res.errMessage ); - -#ifndef TraceXMPCalls - #define TraceXMPCalls 0 -#endif - -#if ! TraceXMPCalls - #define InvokeCheck(WCallProto) \ - WXMP_Result wResult; \ - WCallProto; \ - PropagateException ( wResult ) -#else - #define InvokeCheck(WCallProto) \ - WXMP_Result wResult; \ - fprintf ( stderr, "WXMP calling: %s\n", #WCallProto ); fflush ( stderr ); \ - WCallProto; \ - if ( wResult.errMessage == 0 ) { \ - fprintf ( stderr, "WXMP back, no error\n" ); fflush ( stderr ); \ - } else { \ - fprintf ( stderr, "WXMP back, error: %s\n", wResult.errMessage ); fflush ( stderr ); \ - } \ - PropagateException ( wResult ) -#endif - -// ------------------------------------------------------------------------------------------------- - -#define WrapNoCheckVoid(WCallProto) \ - WCallProto; - -#define WrapCheckVoid(WCallProto) \ - InvokeCheck(WCallProto) - -#define WrapCheckMetaRef(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMPMetaRef result = XMPMetaRef(wResult.ptrResult) - -#define WrapCheckIterRef(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMPIteratorRef result = XMPIteratorRef(wResult.ptrResult) - -#define WrapCheckDocOpsRef(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMPDocOpsRef result = XMPDocOpsRef(wResult.ptrResult) - -#define WrapCheckBool(result,WCallProto) \ - InvokeCheck(WCallProto); \ - bool result = bool(wResult.int32Result) - -#define WrapCheckTriState(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_TriState result = XMP_TriState(wResult.int32Result) - -#define WrapCheckOptions(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_OptionBits result = XMP_OptionBits(wResult.int32Result) - -#define WrapCheckStatus(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_Status result = XMP_Status(wResult.int32Result) - -#define WrapCheckIndex(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_Index result = XMP_Index(wResult.int32Result) - -#define WrapCheckInt32(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_Int32 result = wResult.int32Result - -#define WrapCheckInt64(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_Int64 result = wResult.int64Result - -#define WrapCheckFloat(result,WCallProto) \ - InvokeCheck(WCallProto); \ - double result = wResult.floatResult - -#define WrapCheckFormat(result,WCallProto) \ - InvokeCheck(WCallProto); \ - XMP_FileFormat result = wResult.int32Result - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif - -#endif // __WXMP_Common_hpp__ diff --git a/xmpsdk/src/ExpatAdapter.cpp b/xmpsdk/src/ExpatAdapter.cpp deleted file mode 100644 index 09117c7511..0000000000 --- a/xmpsdk/src/ExpatAdapter.cpp +++ /dev/null @@ -1,507 +0,0 @@ -// ================================================================================================= -// Copyright 2005-2008 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 "XMP_Environment.h" // ! Must be the first #include! -#include "XMPCore_Impl.hpp" - -#include "ExpatAdapter.hpp" -#include "XMPMeta.hpp" - -#include "expat.h" - -#include - -using namespace std; - -#if XMP_WinBuild -# ifdef _MSC_VER - #pragma warning ( disable : 4996 ) // '...' was declared deprecated -# endif -#endif - -// *** Set memory handlers. - -#ifndef DumpXMLParseEvents - #define DumpXMLParseEvents 0 -#endif - -#define FullNameSeparator '@' - -// ================================================================================================= - -static void StartNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix, XMP_StringPtr uri ); -static void EndNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix ); - -static void StartElementHandler ( void * userData, XMP_StringPtr name, XMP_StringPtr* attrs ); -static void EndElementHandler ( void * userData, XMP_StringPtr name ); - -static void CharacterDataHandler ( void * userData, XMP_StringPtr cData, int len ); -static void StartCdataSectionHandler ( void * userData ); -static void EndCdataSectionHandler ( void * userData ); - -static void ProcessingInstructionHandler ( void * userData, XMP_StringPtr target, XMP_StringPtr data ); -static void CommentHandler ( void * userData, XMP_StringPtr comment ); - -#if BanAllEntityUsage - - // For now we do this by banning DOCTYPE entirely. This is easy and consistent with what is - // available in recent Java XML parsers. Another, somewhat less drastic, approach would be to - // ban all entity declarations. We can't allow declarations and ban references, Expat does not - // call the SkippedEntityHandler for references in attribute values. - - // ! Standard entities (&, <, >, ", ', and numeric character references) are - // ! not banned. Expat handles them transparently no matter what. - - static void StartDoctypeDeclHandler ( void * userData, XMP_StringPtr doctypeName, - XMP_StringPtr sysid, XMP_StringPtr pubid, int has_internal_subset ); - -#endif - -// ================================================================================================= - -extern "C" ExpatAdapter * XMP_NewExpatAdapter() -{ - return new ExpatAdapter; -} // XMP_NewExpatAdapter - -// ================================================================================================= - -ExpatAdapter::ExpatAdapter() : parser(0) -{ - - #if XMP_DebugBuild - this->elemNesting = 0; - #if DumpXMLParseEvents - if ( this->parseLog == 0 ) this->parseLog = stdout; - #endif - #endif - - this->parser = XML_ParserCreateNS ( 0, FullNameSeparator ); - if ( this->parser == 0 ) XMP_Throw ( "Failure creating Expat parser", kXMPErr_ExternalFailure ); - - XML_SetUserData ( this->parser, this ); - - XML_SetNamespaceDeclHandler ( this->parser, StartNamespaceDeclHandler, EndNamespaceDeclHandler ); - XML_SetElementHandler ( this->parser, StartElementHandler, EndElementHandler ); - - XML_SetCharacterDataHandler ( this->parser, CharacterDataHandler ); - XML_SetCdataSectionHandler ( this->parser, StartCdataSectionHandler, EndCdataSectionHandler ); - - XML_SetProcessingInstructionHandler ( this->parser, ProcessingInstructionHandler ); - XML_SetCommentHandler ( this->parser, CommentHandler ); - - #if BanAllEntityUsage - XML_SetStartDoctypeDeclHandler ( this->parser, StartDoctypeDeclHandler ); - isAborted = false; - #endif - - this->parseStack.push_back ( &this->tree ); // Push the XML root node. - -} // ExpatAdapter::ExpatAdapter - -// ================================================================================================= - -ExpatAdapter::~ExpatAdapter() -{ - - if ( this->parser != 0 ) XML_ParserFree ( this->parser ); - this->parser = 0; - -} // ExpatAdapter::~ExpatAdapter - -// ================================================================================================= - -#if XMP_DebugBuild - static XMP_VarString sExpatMessage; -#endif - -static const char * kOneSpace = " "; - -void ExpatAdapter::ParseBuffer ( const void * buffer, size_t length, bool last /* = true */ ) -{ - enum XML_Status status; - - if ( length == 0 ) { // Expat does not like empty buffers. - if ( ! last ) return; - buffer = kOneSpace; - length = 1; - } - - status = XML_Parse ( this->parser, (const char *)buffer, length, last ); - - #if BanAllEntityUsage - if ( this->isAborted ) XMP_Throw ( "DOCTYPE is not allowed", kXMPErr_BadXML ); - #endif - - if ( status != XML_STATUS_OK ) { - - XMP_StringPtr errMsg = "XML parsing failure"; - - #if 0 // XMP_DebugBuild // Disable for now to make test output uniform. Restore later with thread safety. - - // *** This is a good candidate for a callback error notification mechanism. - // *** This code is not thread safe, the sExpatMessage isn't locked. But that's OK for debug usage. - - enum XML_Error expatErr = XML_GetErrorCode ( this->parser ); - const char * expatMsg = XML_ErrorString ( expatErr ); - int errLine = XML_GetCurrentLineNumber ( this->parser ); - - char msgBuffer[1000]; - // AUDIT: Use of sizeof(msgBuffer) for snprintf length is safe. - snprintf ( msgBuffer, sizeof(msgBuffer), "# Expat error %d at line %d, \"%s\"", expatErr, errLine, expatMsg ); - sExpatMessage = msgBuffer; - errMsg = sExpatMessage.c_str(); - - #if DumpXMLParseEvents - if ( this->parseLog != 0 ) fprintf ( this->parseLog, "%s\n", errMsg, expatErr, errLine, expatMsg ); - #endif - - #endif - - XMP_Throw ( errMsg, kXMPErr_BadXML ); - - } - -} // ExpatAdapter::ParseBuffer - -// ================================================================================================= -// ================================================================================================= - -#if XMP_DebugBuild & DumpXMLParseEvents - - static inline void PrintIndent ( FILE * file, size_t count ) - { - for ( ; count > 0; --count ) fprintf ( file, " " ); - } - -#endif - -// ================================================================================================= - -static void SetQualName ( XMP_StringPtr fullName, XML_Node * node ) -{ - // Expat delivers the full name as a catenation of namespace URI, separator, and local name. - - // As a compatibility hack, an "about" or "ID" attribute of an rdf:Description element is - // changed to "rdf:about" or rdf:ID. Easier done here than in the RDF recognizer. - - // As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/. - // Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace. - - // ! This code presumes the RDF namespace prefix is "rdf". - - size_t sepPos = strlen(fullName); - for ( --sepPos; sepPos > 0; --sepPos ) { - if ( fullName[sepPos] == FullNameSeparator ) break; - } - - if ( fullName[sepPos] == FullNameSeparator ) { - - XMP_StringPtr prefix; - XMP_StringLen prefixLen; - XMP_StringPtr localPart = fullName + sepPos + 1; - - node->ns.assign ( fullName, sepPos ); - if ( node->ns == "http://purl.org/dc/1.1/" ) node->ns = "http://purl.org/dc/elements/1.1/"; - - bool found = XMPMeta::GetNamespacePrefix ( node->ns.c_str(), &prefix, &prefixLen ); - if ( ! found ) XMP_Throw ( "Unknown URI in Expat full name", kXMPErr_ExternalFailure ); - node->nsPrefixLen = prefixLen; // ! Includes the ':'. - - node->name = prefix; - node->name += localPart; - - } else { - - node->name = fullName; // The name is not in a namespace. - - if ( node->parent->name == "rdf:Description" ) { - if ( node->name == "about" ) { - node->ns = kXMP_NS_RDF; - node->name = "rdf:about"; - node->nsPrefixLen = 4; // ! Include the ':'. - } else if ( node->name == "ID" ) { - node->ns = kXMP_NS_RDF; - node->name = "rdf:ID"; - node->nsPrefixLen = 4; // ! Include the ':'. - } - } - - } - -} // SetQualName - -// ================================================================================================= - -static void StartNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix, XMP_StringPtr uri ) -{ - IgnoreParam(userData); - - // As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/. - // Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace. - - #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning. - ExpatAdapter * thiz = (ExpatAdapter*)userData; - #endif - - if ( prefix == 0 ) prefix = "_dflt_"; // Have default namespace. - if ( uri == 0 ) return; // Ignore, have xmlns:pre="", no URI to register. - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "StartNamespace: %s - \"%s\"\n", prefix, uri ); - } - #endif - - if ( XMP_LitMatch ( uri, "http://purl.org/dc/1.1/" ) ) uri = "http://purl.org/dc/elements/1.1/"; - XMPMeta::RegisterNamespace ( uri, prefix ); - -} // StartNamespaceDeclHandler - -// ================================================================================================= - -static void EndNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix ) -{ - IgnoreParam(userData); - - #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning. - ExpatAdapter * thiz = (ExpatAdapter*)userData; - #endif - - if ( prefix == 0 ) prefix = "_dflt_"; // Have default namespace. - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "EndNamespace: %s\n", prefix ); - } - #endif - - // ! Nothing to do, Expat has done all of the XML processing. - -} // EndNamespaceDeclHandler - -// ================================================================================================= - -static void StartElementHandler ( void * userData, XMP_StringPtr name, XMP_StringPtr* attrs ) -{ - XMP_Assert ( attrs != 0 ); - ExpatAdapter * thiz = (ExpatAdapter*)userData; - - size_t attrCount = 0; - for ( XMP_StringPtr* a = attrs; *a != 0; ++a ) ++attrCount; - if ( (attrCount & 1) != 0 ) XMP_Throw ( "Expat attribute info has odd length", kXMPErr_ExternalFailure ); - attrCount = attrCount/2; // They are name/value pairs. - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "StartElement: %s, %d attrs", name, attrCount ); - for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) { - XMP_StringPtr attrName = *attr; - XMP_StringPtr attrValue = *(attr+1); - fprintf ( thiz->parseLog, ", %s = \"%s\"", attrName, attrValue ); - } - fprintf ( thiz->parseLog, "\n" ); - } - #endif - - XML_Node * parentNode = thiz->parseStack.back(); - XML_Node * elemNode = new XML_Node ( parentNode, "", kElemNode ); - - SetQualName ( name, elemNode ); - - for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) { - - XMP_StringPtr attrName = *attr; - XMP_StringPtr attrValue = *(attr+1); - XML_Node * attrNode = new XML_Node ( elemNode, "", kAttrNode ); - - SetQualName ( attrName, attrNode ); - attrNode->value = attrValue; - if ( attrNode->name == "xml:lang" ) NormalizeLangValue ( &attrNode->value ); - elemNode->attrs.push_back ( attrNode ); - - } - - parentNode->content.push_back ( elemNode ); - thiz->parseStack.push_back ( elemNode ); - - if ( elemNode->name == "rdf:RDF" ) { - thiz->rootNode = elemNode; - ++thiz->rootCount; - } - #if XMP_DebugBuild - ++thiz->elemNesting; - #endif - -} // StartElementHandler - -// ================================================================================================= - -static void EndElementHandler ( void * userData, XMP_StringPtr name ) -{ - IgnoreParam(name); - - ExpatAdapter * thiz = (ExpatAdapter*)userData; - - #if XMP_DebugBuild - --thiz->elemNesting; - #endif - (void) thiz->parseStack.pop_back(); - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "EndElement: %s\n", name ); - } - #endif - -} // EndElementHandler - -// ================================================================================================= - -static void CharacterDataHandler ( void * userData, XMP_StringPtr cData, int len ) -{ - ExpatAdapter * thiz = (ExpatAdapter*)userData; - - if ( (cData == 0) || (len == 0) ) { cData = ""; len = 0; } - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "CharContent: \"" ); - for ( int i = 0; i < len; ++i ) fprintf ( thiz->parseLog, "%c", cData[i] ); - fprintf ( thiz->parseLog, "\"\n" ); - } - #endif - - XML_Node * parentNode = thiz->parseStack.back(); - XML_Node * cDataNode = new XML_Node ( parentNode, "", kCDataNode ); - - cDataNode->value.assign ( cData, len ); - parentNode->content.push_back ( cDataNode ); - -} // CharacterDataHandler - -// ================================================================================================= - -static void StartCdataSectionHandler ( void * userData ) -{ - IgnoreParam(userData); - - #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning. - ExpatAdapter * thiz = (ExpatAdapter*)userData; - #endif - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "StartCDATA\n" ); - } - #endif - - // *** Since markup isn't recognized inside CDATA, this affects XMP's double escaping. - -} // StartCdataSectionHandler - -// ================================================================================================= - -static void EndCdataSectionHandler ( void * userData ) -{ - IgnoreParam(userData); - - #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning. - ExpatAdapter * thiz = (ExpatAdapter*)userData; - #endif - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "EndCDATA\n" ); - } - #endif - -} // EndCdataSectionHandler - -// ================================================================================================= - -static void ProcessingInstructionHandler ( void * userData, XMP_StringPtr target, XMP_StringPtr data ) -{ - XMP_Assert ( target != 0 ); - ExpatAdapter * thiz = (ExpatAdapter*)userData; - - if ( ! XMP_LitMatch ( target, "xpacket" ) ) return; // Ignore all PIs except the XMP packet wrapper. - if ( data == 0 ) data = ""; - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "PI: %s - \"%s\"\n", target, data ); - } - #endif - - XML_Node * parentNode = thiz->parseStack.back(); - XML_Node * piNode = new XML_Node ( parentNode, target, kPINode ); - - piNode->value.assign ( data ); - parentNode->content.push_back ( piNode ); - -} // ProcessingInstructionHandler - -// ================================================================================================= - -static void CommentHandler ( void * userData, XMP_StringPtr comment ) -{ - IgnoreParam(userData); - - #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning. - ExpatAdapter * thiz = (ExpatAdapter*)userData; - #endif - - if ( comment == 0 ) comment = ""; - - #if XMP_DebugBuild & DumpXMLParseEvents - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "Comment: \"%s\"\n", comment ); - } - #endif - - // ! Comments are ignored. - -} // CommentHandler - -// ================================================================================================= - -#if BanAllEntityUsage -static void StartDoctypeDeclHandler ( void * userData, XMP_StringPtr doctypeName, - XMP_StringPtr sysid, XMP_StringPtr pubid, int has_internal_subset ) -{ - IgnoreParam(doctypeName); - IgnoreParam(sysid); - IgnoreParam(pubid); - IgnoreParam(has_internal_subset); - - ExpatAdapter * thiz = (ExpatAdapter*)userData; - - #if XMP_DebugBuild & DumpXMLParseEvents // Avoid unused variable warning. - if ( thiz->parseLog != 0 ) { - PrintIndent ( thiz->parseLog, thiz->elemNesting ); - fprintf ( thiz->parseLog, "DocType: \"%s\"\n", doctypeName ); - } - #endif - - thiz->isAborted = true; // ! Can't throw an exception across the plain C Expat frames. - (void) XML_StopParser ( thiz->parser, XML_FALSE /* not resumable */ ); - -} // StartDoctypeDeclHandler -#endif - -// ================================================================================================= diff --git a/xmpsdk/src/ExpatAdapter.hpp b/xmpsdk/src/ExpatAdapter.hpp deleted file mode 100644 index 9d6c9ec4be..0000000000 --- a/xmpsdk/src/ExpatAdapter.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef __ExpatAdapter_hpp__ -#define __ExpatAdapter_hpp__ - -// ================================================================================================= -// Copyright 2005-2008 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 "XMP_Environment.h" // ! Must be the first #include! -#include "XMLParserAdapter.hpp" - -// ================================================================================================= -// Derived XML parser adapter for Expat. -// ================================================================================================= - -#ifndef BanAllEntityUsage - #define BanAllEntityUsage 0 -#endif - -struct XML_ParserStruct; // ! Hack to avoid exposing expat.h to all clients. -typedef struct XML_ParserStruct *XML_Parser; - -class ExpatAdapter : public XMLParserAdapter { -public: - - XML_Parser parser; - - #if BanAllEntityUsage - bool isAborted; - #endif - - #if XMP_DebugBuild - size_t elemNesting; - #endif - - ExpatAdapter(); - virtual ~ExpatAdapter(); - - void ParseBuffer ( const void * buffer, size_t length, bool last = true ); - -}; - -extern "C" ExpatAdapter * XMP_NewExpatAdapter(); - -// ================================================================================================= - -#endif // __ExpatAdapter_hpp__ diff --git a/xmpsdk/src/MD5.cpp b/xmpsdk/src/MD5.cpp deleted file mode 100644 index b040bd2c20..0000000000 --- a/xmpsdk/src/MD5.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, declare an - * MD5_CTX structure, pass it to MD5Init, call MD5Update as - * needed on buffers full of bytes, and then call MD5Final, which - * will fill a supplied 16-byte array with the digest. - * - * Changed so as no longer to depend on Colin Plumb's `usual.h' header - * definitions; now uses stuff from dpkg's config.h. - * - Ian Jackson . - * Still in the public domain. - */ - -#include - -#include "MD5.h" - -using namespace std; - -static void -byteSwap(UWORD32 *buf, unsigned words) -{ - const uint32_t byteOrderTest = 0x1; - if (((char *)&byteOrderTest)[0] == 0) { - md5byte *p = (md5byte *)buf; - - do { - *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 | - ((unsigned)p[1] << 8 | p[0]); - p += 4; - } while (--words); - } -} - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -void -MD5Init(struct MD5_CTX *ctx) -{ - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - - ctx->bytes[0] = 0; - ctx->bytes[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -void -MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len) -{ - UWORD32 t; - - /* Update byte count */ - - t = ctx->bytes[0]; - if ((ctx->bytes[0] = t + len) < t) - ctx->bytes[1]++; /* Carry from low to high */ - - t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ - if (t > len) { - memcpy((md5byte *)ctx->in + 64 - t, buf, len); - return; - } - /* First chunk is an odd size */ - memcpy((md5byte *)ctx->in + 64 - t, buf, t); - byteSwap(ctx->in, 16); - MD5Transform(ctx->buf, ctx->in); - buf += t; - len -= t; - - /* Process data in 64-byte chunks */ - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteSwap(ctx->in, 16); - MD5Transform(ctx->buf, ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -void -MD5Final(md5byte digest[16], struct MD5_CTX *ctx) -{ - int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */ - md5byte *p = (md5byte *)ctx->in + count; - - /* Set the first char of padding to 0x80. There is always room. */ - *p++ = 0x80; - - /* Bytes of padding needed to make 56 bytes (-8..55) */ - count = 56 - 1 - count; - - if (count < 0) { /* Padding forces an extra block */ - memset(p, 0, count + 8); - byteSwap(ctx->in, 16); - MD5Transform(ctx->buf, ctx->in); - p = (md5byte *)ctx->in; - count = 56; - } - memset(p, 0, count); - byteSwap(ctx->in, 14); - - /* Append length in bits and transform */ - ctx->in[14] = ctx->bytes[0] << 3; - ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; - MD5Transform(ctx->buf, ctx->in); - - byteSwap(ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ -} - -/* The four core functions - F1 is optimized somewhat */ - -/* #define F1(x, y, z) (x & y | ~x & z) */ -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f,w,x,y,z,in,s) \ - (w += f(x,y,z) + in, w = (w<>(32-s)) + x) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -void -MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) -{ - UWORD32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} diff --git a/xmpsdk/src/ParseRDF.cpp b/xmpsdk/src/ParseRDF.cpp deleted file mode 100644 index a92257c204..0000000000 --- a/xmpsdk/src/ParseRDF.cpp +++ /dev/null @@ -1,1296 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" -#include "ExpatAdapter.hpp" - -#include - -#if DEBUG - #include -#endif - -using namespace std; - -#if XMP_WinBuild -# ifdef _MSC_VER - #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced - #pragma warning ( disable : 4505 ) // unreferenced local function has been removed -# endif -#endif - -// ================================================================================================= - -// *** This might be faster and use less memory as a state machine. A big advantage of building an -// *** XML tree though is easy lookahead during the recursive descent processing. - -// *** It would be nice to give a line number or byte offset in the exception messages. - - -// 7 RDF/XML Grammar (from http://www.w3.org/TR/rdf-syntax-grammar/#section-Infoset-Grammar) -// -// 7.1 Grammar summary -// -// 7.2.2 coreSyntaxTerms -// rdf:RDF | rdf:ID | rdf:about | rdf:parseType | rdf:resource | rdf:nodeID | rdf:datatype -// -// 7.2.3 syntaxTerms -// coreSyntaxTerms | rdf:Description | rdf:li -// -// 7.2.4 oldTerms -// rdf:aboutEach | rdf:aboutEachPrefix | rdf:bagID -// -// 7.2.5 nodeElementURIs -// anyURI - ( coreSyntaxTerms | rdf:li | oldTerms ) -// -// 7.2.6 propertyElementURIs -// anyURI - ( coreSyntaxTerms | rdf:Description | oldTerms ) -// -// 7.2.7 propertyAttributeURIs -// anyURI - ( coreSyntaxTerms | rdf:Description | rdf:li | oldTerms ) -// -// 7.2.8 doc -// root ( document-element == RDF, children == list ( RDF ) ) -// -// 7.2.9 RDF -// start-element ( URI == rdf:RDF, attributes == set() ) -// nodeElementList -// end-element() -// -// 7.2.10 nodeElementList -// ws* ( nodeElement ws* )* -// -// 7.2.11 nodeElement -// start-element ( URI == nodeElementURIs, -// attributes == set ( ( idAttr | nodeIdAttr | aboutAttr )?, propertyAttr* ) ) -// propertyEltList -// end-element() -// -// 7.2.12 ws -// A text event matching white space defined by [XML] definition White Space Rule [3] S in section Common Syntactic Constructs. -// -// 7.2.13 propertyEltList -// ws* ( propertyElt ws* )* -// -// 7.2.14 propertyElt -// resourcePropertyElt | literalPropertyElt | parseTypeLiteralPropertyElt | -// parseTypeResourcePropertyElt | parseTypeCollectionPropertyElt | parseTypeOtherPropertyElt | emptyPropertyElt -// -// 7.2.15 resourcePropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr? ) ) -// ws* nodeElement ws* -// end-element() -// -// 7.2.16 literalPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, datatypeAttr?) ) -// text() -// end-element() -// -// 7.2.17 parseTypeLiteralPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseLiteral ) ) -// literal -// end-element() -// -// 7.2.18 parseTypeResourcePropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseResource ) ) -// propertyEltList -// end-element() -// -// 7.2.19 parseTypeCollectionPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseCollection ) ) -// nodeElementList -// end-element() -// -// 7.2.20 parseTypeOtherPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseOther ) ) -// propertyEltList -// end-element() -// -// 7.2.21 emptyPropertyElt -// start-element ( URI == propertyElementURIs, -// attributes == set ( idAttr?, ( resourceAttr | nodeIdAttr )?, propertyAttr* ) ) -// end-element() -// -// 7.2.22 idAttr -// attribute ( URI == rdf:ID, string-value == rdf-id ) -// -// 7.2.23 nodeIdAttr -// attribute ( URI == rdf:nodeID, string-value == rdf-id ) -// -// 7.2.24 aboutAttr -// attribute ( URI == rdf:about, string-value == URI-reference ) -// -// 7.2.25 propertyAttr -// attribute ( URI == propertyAttributeURIs, string-value == anyString ) -// -// 7.2.26 resourceAttr -// attribute ( URI == rdf:resource, string-value == URI-reference ) -// -// 7.2.27 datatypeAttr -// attribute ( URI == rdf:datatype, string-value == URI-reference ) -// -// 7.2.28 parseLiteral -// attribute ( URI == rdf:parseType, string-value == "Literal") -// -// 7.2.29 parseResource -// attribute ( URI == rdf:parseType, string-value == "Resource") -// -// 7.2.30 parseCollection -// attribute ( URI == rdf:parseType, string-value == "Collection") -// -// 7.2.31 parseOther -// attribute ( URI == rdf:parseType, string-value == anyString - ("Resource" | "Literal" | "Collection") ) -// -// 7.2.32 URI-reference -// An RDF URI Reference. -// -// 7.2.33 literal -// Any XML element content that is allowed according to [XML] definition Content of Elements Rule [43] content -// in section 3.1 Start-Tags, End-Tags, and Empty-Element Tags. -// -// 7.2.34 rdf-id -// An attribute string-value matching any legal [XML-NS] token NCName. - - -// ================================================================================================= -// Primary Parsing Functions -// ========================= -// -// Each of these is responsible for recognizing an RDF syntax production and adding the appropriate -// structure to the XMP tree. They simply return for success, failures will throw an exception. - -static void -RDF_RDF ( XMP_Node * xmpTree, const XML_Node & xmlNode ); - -static void -RDF_NodeElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel ); - -static void -RDF_NodeElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_NodeElementAttrs ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_PropertyElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel ); -enum { kIsTopLevel = true, kNotTopLevel = false }; - -static void -RDF_PropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_ResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_LiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_ParseTypeLiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_ParseTypeResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_ParseTypeCollectionPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_ParseTypeOtherPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - -static void -RDF_EmptyPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ); - - -// ================================================================================================= - -typedef XMP_Uns8 RDFTermKind; - -// *** Logic might be safer with just masks. - -enum { - kRDFTerm_Other = 0, - kRDFTerm_RDF = 1, // Start of coreSyntaxTerms. - kRDFTerm_ID = 2, - kRDFTerm_about = 3, - kRDFTerm_parseType = 4, - kRDFTerm_resource = 5, - kRDFTerm_nodeID = 6, - kRDFTerm_datatype = 7, // End of coreSyntaxTerms. - kRDFTerm_Description = 8, // Start of additions for syntaxTerms. - kRDFTerm_li = 9, // End of of additions for syntaxTerms. - kRDFTerm_aboutEach = 10, // Start of oldTerms. - kRDFTerm_aboutEachPrefix = 11, - kRDFTerm_bagID = 12, // End of oldTerms. - - kRDFTerm_FirstCore = kRDFTerm_RDF, - kRDFTerm_LastCore = kRDFTerm_datatype, - kRDFTerm_FirstSyntax = kRDFTerm_FirstCore, // ! Yes, the syntax terms include the core terms. - kRDFTerm_LastSyntax = kRDFTerm_li, - kRDFTerm_FirstOld = kRDFTerm_aboutEach, - kRDFTerm_LastOld = kRDFTerm_bagID -}; - -enum { - kRDFMask_Other = 1 << kRDFTerm_Other, - kRDFMask_RDF = 1 << kRDFTerm_RDF, - kRDFMask_ID = 1 << kRDFTerm_ID, - kRDFMask_about = 1 << kRDFTerm_about, - kRDFMask_parseType = 1 << kRDFTerm_parseType, - kRDFMask_resource = 1 << kRDFTerm_resource, - kRDFMask_nodeID = 1 << kRDFTerm_nodeID, - kRDFMask_datatype = 1 << kRDFTerm_datatype, - kRDFMask_Description = 1 << kRDFTerm_Description, - kRDFMask_li = 1 << kRDFTerm_li, - kRDFMask_aboutEach = 1 << kRDFTerm_aboutEach, - kRDFMask_aboutEachPrefix = 1 << kRDFTerm_aboutEachPrefix, - kRDFMask_bagID = 1 << kRDFTerm_bagID -}; - -enum { - kRDF_HasValueElem = 0x10000000UL // ! Contains rdf:value child. Must fit within kXMP_ImplReservedMask! -}; - -// ------------------------------------------------------------------------------------------------- -// GetRDFTermKind -// -------------- - -static RDFTermKind -GetRDFTermKind ( const XMP_VarString & name ) -{ - RDFTermKind term = kRDFTerm_Other; - - // Arranged to hopefully minimize the parse time for large XMP. - - if ( (name.size() > 4) && (strncmp ( name.c_str(), "rdf:", 4 ) == 0) ) { - - if ( name == "rdf:li" ) { - term = kRDFTerm_li; - } else if ( name == "rdf:parseType" ) { - term = kRDFTerm_parseType; - } else if ( name == "rdf:Description" ) { - term = kRDFTerm_Description; - } else if ( name == "rdf:about" ) { - term = kRDFTerm_about; - } else if ( name == "rdf:resource" ) { - term = kRDFTerm_resource; - } else if ( name == "rdf:RDF" ) { - term = kRDFTerm_RDF; - } else if ( name == "rdf:ID" ) { - term = kRDFTerm_ID; - } else if ( name == "rdf:nodeID" ) { - term = kRDFTerm_nodeID; - } else if ( name == "rdf:datatype" ) { - term = kRDFTerm_datatype; - } else if ( name == "rdf:aboutEach" ) { - term = kRDFTerm_aboutEach; - } else if ( name == "rdf:aboutEachPrefix" ) { - term = kRDFTerm_aboutEachPrefix; - } else if ( name == "rdf:bagID" ) { - term = kRDFTerm_bagID; - } - - } - - return term; - -} // GetRDFTermKind - - -// ================================================================================================= - - -// ------------------------------------------------------------------------------------------------- -// IsCoreSyntaxTerm -// ---------------- -// -// 7.2.2 coreSyntaxTerms -// rdf:RDF | rdf:ID | rdf:about | rdf:parseType | rdf:resource | rdf:nodeID | rdf:datatype - -static bool -IsCoreSyntaxTerm ( RDFTermKind term ) -{ - - if ( (kRDFTerm_FirstCore <= term) && (term <= kRDFTerm_LastCore) ) return true; - return false; - -} // IsCoreSyntaxTerm - - -// ------------------------------------------------------------------------------------------------- -// IsOldTerm -// --------- -// -// 7.2.4 oldTerms -// rdf:aboutEach | rdf:aboutEachPrefix | rdf:bagID - -static bool -IsOldTerm ( RDFTermKind term ) -{ - - if ( (kRDFTerm_FirstOld <= term) && (term <= kRDFTerm_LastOld) ) return true; - return false; - -} // IsOldTerm - -// ------------------------------------------------------------------------------------------------- -// IsPropertyElementName -// --------------------- -// -// 7.2.6 propertyElementURIs -// anyURI - ( coreSyntaxTerms | rdf:Description | oldTerms ) - -static bool -IsPropertyElementName ( RDFTermKind term ) -{ - - if ( (term == kRDFTerm_Description) || IsOldTerm ( term ) ) return false; - return (! IsCoreSyntaxTerm ( term )); - -} // IsPropertyElementName - -// ================================================================================================= -// AddChildNode -// ============ - -static XMP_Node * -AddChildNode ( XMP_Node * xmpParent, const XML_Node & xmlNode, const XMP_StringPtr value, bool isTopLevel ) -{ - #if 0 - cout << "AddChildNode, parent = " << xmpParent->name << ", child = " << xmlNode.name; - cout << ", value = \"" << value << '"'; - if ( isTopLevel ) cout << ", top level"; - cout << endl; - #endif - - if ( xmlNode.ns.empty() ) { - XMP_Throw ( "XML namespace required for all elements and attributes", kXMPErr_BadRDF ); - } - - XMP_StringPtr childName = xmlNode.name.c_str(); - const bool isArrayItem = (xmlNode.name == "rdf:li"); - const bool isValueNode = (xmlNode.name == "rdf:value"); - XMP_OptionBits childOptions = 0; - - 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, xmlNode.ns.c_str(), kXMP_CreateNodes ); - 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. - if ( sRegisteredAliasMap->find ( xmlNode.name ) != sRegisteredAliasMap->end() ) { - childOptions |= kXMP_PropIsAlias; - schemaNode->parent->options |= kXMP_PropHasAliases; - } - - } - - // Make sure that this is not a duplicate of a named node. - if ( ! (isArrayItem | isValueNode) ) { - if ( FindChildNode ( xmpParent, childName, kXMP_ExistingOnly ) != 0 ) { - XMP_Throw ( "Duplicate property or field node", kXMPErr_BadXMP ); - } - - } - - // Add the new child to the XMP parent node. - XMP_Node * newChild = new XMP_Node ( xmpParent, childName, value, childOptions ); - if ( (! isValueNode) || xmpParent->children.empty() ) { - xmpParent->children.push_back ( newChild ); - } else { - xmpParent->children.insert ( xmpParent->children.begin(), newChild ); - } - if ( isValueNode ) { - if ( isTopLevel || (! (xmpParent->options & kXMP_PropValueIsStruct)) ) XMP_Throw ( "Misplaced rdf:value element", kXMPErr_BadRDF ); - xmpParent->options |= kRDF_HasValueElem; - } - - if ( isArrayItem ) { - if ( ! (xmpParent->options & kXMP_PropValueIsArray) ) XMP_Throw ( "Misplaced rdf:li element", kXMPErr_BadRDF ); - newChild->name = kXMP_ArrayItemName; - #if 0 // *** XMP_DebugBuild - newChild->_namePtr = newChild->name.c_str(); - #endif - } - - return newChild; - -} // AddChildNode - - -// ================================================================================================= -// AddQualifierNode -// ================ - -static XMP_Node * -AddQualifierNode ( XMP_Node * xmpParent, const XMP_VarString & name, const XMP_VarString & value ) -{ - - #if 0 - cout << "AddQualifierNode, parent = " << xmpParent->name << ", name = " << name; - cout << ", value = \"" << value << '"' << endl; - #endif - - const bool isLang = (name == "xml:lang"); - const bool isType = (name == "rdf:type"); - - XMP_Node * newQual = 0; - - newQual = new XMP_Node ( xmpParent, name, 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; - -} // AddQualifierNode - - -// ================================================================================================= -// AddQualifierNode -// ================ - -static XMP_Node * -AddQualifierNode ( XMP_Node * xmpParent, const XML_Node & attr ) -{ - if ( attr.ns.empty() ) { - XMP_Throw ( "XML namespace required for all elements and attributes", kXMPErr_BadRDF ); - } - - return AddQualifierNode ( xmpParent, attr.name, attr.value ); - -} // AddQualifierNode - - -// ================================================================================================= -// FixupQualifiedNode -// ================== -// -// The parent is an RDF pseudo-struct containing an rdf:value field. Fix the XMP data model. The -// rdf:value node must be the first child, the other children are qualifiers. The form, value, and -// children of the rdf:value node are the real ones. The rdf:value node's qualifiers must be added -// to the others. - -static void -FixupQualifiedNode ( XMP_Node * xmpParent ) -{ - size_t qualNum, qualLim; - size_t childNum, childLim; - - XMP_Enforce ( (xmpParent->options & kXMP_PropValueIsStruct) && (! xmpParent->children.empty()) ); - - XMP_Node * valueNode = xmpParent->children[0]; - XMP_Enforce ( valueNode->name == "rdf:value" ); - - xmpParent->qualifiers.reserve ( xmpParent->qualifiers.size() + xmpParent->children.size() + valueNode->qualifiers.size() ); - - // Move the qualifiers on the value node to the parent. Make sure an xml:lang qualifier stays at - // the front. Check for duplicate names between the value node's qualifiers and the parent's - // children. The parent's children are about to become qualifiers. Check here, between the - // groups. Intra-group duplicates are caught by AddChildNode. - - qualNum = 0; - qualLim = valueNode->qualifiers.size(); - - if ( valueNode->options & kXMP_PropHasLang ) { - - if ( xmpParent->options & kXMP_PropHasLang ) XMP_Throw ( "Redundant xml:lang for rdf:value element", kXMPErr_BadXMP ); - - XMP_Node * langQual = valueNode->qualifiers[0]; - - XMP_Assert ( langQual->name == "xml:lang" ); - langQual->parent = xmpParent; - xmpParent->options |= kXMP_PropHasLang; - - if ( xmpParent->qualifiers.empty() ) { - xmpParent->qualifiers.push_back ( langQual ); // *** Should use utilities to add qual & set parent. - } else { - xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), langQual ); - } - valueNode->qualifiers[0] = 0; // We just moved it to the parent. - - qualNum = 1; // Start the remaining copy after the xml:lang qualifier. - - } - - for ( ; qualNum != qualLim; ++qualNum ) { - - XMP_Node * currQual = valueNode->qualifiers[qualNum]; - if ( FindChildNode ( xmpParent, currQual->name.c_str(), kXMP_ExistingOnly ) != 0 ) { - XMP_Throw ( "Duplicate qualifier node", kXMPErr_BadXMP ); - } - - currQual->parent = xmpParent; - xmpParent->qualifiers.push_back ( currQual ); - valueNode->qualifiers[qualNum] = 0; // We just moved it to the parent. - - } - - valueNode->qualifiers.clear(); // ! There should be nothing but null pointers. - - // Change the parent's other children into qualifiers. This loop starts at 1, child 0 is the - // rdf:value node. Put xml:lang at the front, append all others. - - for ( childNum = 1, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) { - - XMP_Node * currQual = xmpParent->children[childNum]; - - bool isLang = (currQual->name == "xml:lang"); - - currQual->options |= kXMP_PropIsQualifier; - currQual->parent = xmpParent; - - if ( isLang ) { - if ( xmpParent->options & kXMP_PropHasLang ) XMP_Throw ( "Duplicate xml:lang qualifier", kXMPErr_BadXMP ); - xmpParent->options |= kXMP_PropHasLang; - } else if ( currQual->name == "rdf:type" ) { - xmpParent->options |= kXMP_PropHasType; - } - - if ( (! isLang) || xmpParent->qualifiers.empty() ) { - xmpParent->qualifiers.push_back ( currQual ); - } else { - xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), currQual ); - } - xmpParent->children[childNum] = 0; // We just moved it to the qualifers. - - } - - if ( ! xmpParent->qualifiers.empty() ) xmpParent->options |= kXMP_PropHasQualifiers; - - // Move the options and value last, other checks need the parent's original options. Move the - // value node's children to be the parent's children. Delete the now useless value node. - - XMP_Assert ( xmpParent->options & (kXMP_PropValueIsStruct | kRDF_HasValueElem) ); - xmpParent->options &= ~ (static_cast(kXMP_PropValueIsStruct) | static_cast(kRDF_HasValueElem)); - xmpParent->options |= valueNode->options; - - xmpParent->value.swap ( valueNode->value ); - #if 0 // *** XMP_DebugBuild - xmpParent->_valuePtr = xmpParent->value.c_str(); - #endif - - xmpParent->children[0] = 0; // ! Remove the value node itself before the swap. - xmpParent->children.swap ( valueNode->children ); - - for ( size_t childNum = 0, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) { - XMP_Node * currChild = xmpParent->children[childNum]; - currChild->parent = xmpParent; - } - - delete valueNode; - -} // FixupQualifiedNode - - -// ================================================================================================= -// ProcessRDF -// ========== -// -// Parse the XML tree of the RDF and build the corresponding XMP tree. - -// *** Throw an exception if no XMP is found? By option? -// *** Do parsing exceptions cause the partial tree to be deleted? - -void ProcessRDF ( XMP_Node * xmpTree, const XML_Node & rdfNode, XMP_OptionBits options ) -{ - IgnoreParam(options); - - RDF_RDF ( xmpTree, rdfNode ); - -} // ProcessRDF - - -// ================================================================================================= -// RDF_RDF -// ======= -// -// 7.2.9 RDF -// start-element ( URI == rdf:RDF, attributes == set() ) -// nodeElementList -// end-element() -// -// The top level rdf:RDF node. It can only have xmlns attributes, which have already been removed -// during construction of the XML tree. - -static void -RDF_RDF ( XMP_Node * xmpTree, const XML_Node & xmlNode ) -{ - - if ( ! xmlNode.attrs.empty() ) XMP_Throw ( "Invalid attributes of rdf:RDF element", kXMPErr_BadRDF ); - RDF_NodeElementList ( xmpTree, xmlNode, kIsTopLevel ); - -} // RDF_RDF - - -// ================================================================================================= -// RDF_NodeElementList -// =================== -// -// 7.2.10 nodeElementList -// ws* ( nodeElement ws* )* - -static void -RDF_NodeElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel ) -{ - XMP_Assert ( isTopLevel ); - - XML_cNodePos currChild = xmlParent.content.begin(); // *** Change these loops to the indexed pattern. - XML_cNodePos endChild = xmlParent.content.end(); - - for ( ; currChild != endChild; ++currChild ) { - if ( (*currChild)->IsWhitespaceNode() ) continue; - RDF_NodeElement ( xmpParent, **currChild, isTopLevel ); - } - -} // RDF_NodeElementList - - -// ================================================================================================= -// RDF_NodeElement -// =============== -// -// 7.2.5 nodeElementURIs -// anyURI - ( coreSyntaxTerms | rdf:li | oldTerms ) -// -// 7.2.11 nodeElement -// start-element ( URI == nodeElementURIs, -// attributes == set ( ( idAttr | nodeIdAttr | aboutAttr )?, propertyAttr* ) ) -// propertyEltList -// end-element() -// -// A node element URI is rdf:Description or anything else that is not an RDF term. - -static void -RDF_NodeElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - RDFTermKind nodeTerm = GetRDFTermKind ( xmlNode.name ); - if ( (nodeTerm != kRDFTerm_Description) && (nodeTerm != kRDFTerm_Other) ) { - XMP_Throw ( "Node element must be rdf:Description or typedNode", kXMPErr_BadRDF ); - } - - if ( isTopLevel && (nodeTerm == kRDFTerm_Other) ) { - XMP_Throw ( "Top level typedNode not allowed", kXMPErr_BadXMP ); - } else { - RDF_NodeElementAttrs ( xmpParent, xmlNode, isTopLevel ); - RDF_PropertyElementList ( xmpParent, xmlNode, isTopLevel ); - } - -} // RDF_NodeElement - - -// ================================================================================================= -// RDF_NodeElementAttrs -// ==================== -// -// 7.2.7 propertyAttributeURIs -// anyURI - ( coreSyntaxTerms | rdf:Description | rdf:li | oldTerms ) -// -// 7.2.11 nodeElement -// start-element ( URI == nodeElementURIs, -// attributes == set ( ( idAttr | nodeIdAttr | aboutAttr )?, propertyAttr* ) ) -// propertyEltList -// end-element() -// -// Process the attribute list for an RDF node element. A property attribute URI is anything other -// than an RDF term. The rdf:ID and rdf:nodeID attributes are simply ignored, as are rdf:about -// attributes on inner nodes. - -static const XMP_OptionBits kExclusiveAttrMask = (kRDFMask_ID | kRDFMask_nodeID | kRDFMask_about); - -static void -RDF_NodeElementAttrs ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - XMP_OptionBits exclusiveAttrs = 0; // Used to detect attributes that are mutually exclusive. - - XML_cNodePos currAttr = xmlNode.attrs.begin(); - XML_cNodePos endAttr = xmlNode.attrs.end(); - - for ( ; currAttr != endAttr; ++currAttr ) { - - RDFTermKind attrTerm = GetRDFTermKind ( (*currAttr)->name ); - - switch ( attrTerm ) { - - case kRDFTerm_ID : - case kRDFTerm_nodeID : - case kRDFTerm_about : - - if ( exclusiveAttrs & kExclusiveAttrMask ) XMP_Throw ( "Mutally exclusive about, ID, nodeID attributes", kXMPErr_BadRDF ); - exclusiveAttrs |= (1 << attrTerm); - - if ( isTopLevel && (attrTerm == kRDFTerm_about) ) { - // This is the rdf:about attribute on a top level node. Set the XMP tree name if - // it doesn't have a name yet. Make sure this name matches the XMP tree name. - XMP_Assert ( xmpParent->parent == 0 ); // Must be the tree root node. - if ( xmpParent->name.empty() ) { - xmpParent->name = (*currAttr)->value; - } else if ( ! (*currAttr)->value.empty() ) { - if ( xmpParent->name != (*currAttr)->value ) XMP_Throw ( "Mismatched top level rdf:about values", kXMPErr_BadXMP ); - } - } - - break; - - case kRDFTerm_Other : - AddChildNode ( xmpParent, **currAttr, (*currAttr)->value.c_str(), isTopLevel ); - break; - - default : - XMP_Throw ( "Invalid nodeElement attribute", kXMPErr_BadRDF ); - - } - - } - -} // RDF_NodeElementAttrs - - -// ================================================================================================= -// RDF_PropertyElementList -// ======================= -// -// 7.2.13 propertyEltList -// ws* ( propertyElt ws* )* - -static void -RDF_PropertyElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel ) -{ - XML_cNodePos currChild = xmlParent.content.begin(); - XML_cNodePos endChild = xmlParent.content.end(); - - for ( ; currChild != endChild; ++currChild ) { - if ( (*currChild)->IsWhitespaceNode() ) continue; - if ( (*currChild)->kind != kElemNode ) { - XMP_Throw ( "Expected property element node not found", kXMPErr_BadRDF ); - } - RDF_PropertyElement ( xmpParent, **currChild, isTopLevel ); - } - -} // RDF_PropertyElementList - - -// ================================================================================================= -// RDF_PropertyElement -// =================== -// -// 7.2.14 propertyElt -// resourcePropertyElt | literalPropertyElt | parseTypeLiteralPropertyElt | -// parseTypeResourcePropertyElt | parseTypeCollectionPropertyElt | parseTypeOtherPropertyElt | emptyPropertyElt -// -// 7.2.15 resourcePropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr? ) ) -// ws* nodeElement ws* -// end-element() -// -// 7.2.16 literalPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, datatypeAttr?) ) -// text() -// end-element() -// -// 7.2.17 parseTypeLiteralPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseLiteral ) ) -// literal -// end-element() -// -// 7.2.18 parseTypeResourcePropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseResource ) ) -// propertyEltList -// end-element() -// -// 7.2.19 parseTypeCollectionPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseCollection ) ) -// nodeElementList -// end-element() -// -// 7.2.20 parseTypeOtherPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseOther ) ) -// propertyEltList -// end-element() -// -// 7.2.21 emptyPropertyElt -// start-element ( URI == propertyElementURIs, -// attributes == set ( idAttr?, ( resourceAttr | nodeIdAttr )?, propertyAttr* ) ) -// end-element() -// -// The various property element forms are not distinguished by the XML element name, but by their -// attributes for the most part. The exceptions are resourcePropertyElt and literalPropertyElt. They -// are distinguished by their XML element content. -// -// NOTE: The RDF syntax does not explicitly include the xml:lang attribute although it can appear in -// many of these. We have to allow for it in the attribute counts below. - -static void -RDF_PropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - RDFTermKind nodeTerm = GetRDFTermKind ( xmlNode.name ); - if ( ! IsPropertyElementName ( nodeTerm ) ) XMP_Throw ( "Invalid property element name", kXMPErr_BadRDF ); - - if ( xmlNode.attrs.size() > 3 ) { - - // Only an emptyPropertyElt can have more than 3 attributes. - RDF_EmptyPropertyElement ( xmpParent, xmlNode, isTopLevel ); - - } else { - - // Look through the attributes for one that isn't rdf:ID or xml:lang, it will usually tell - // what we should be dealing with. The called routines must verify their specific syntax! - - XML_cNodePos currAttr = xmlNode.attrs.begin(); - XML_cNodePos endAttr = xmlNode.attrs.end(); - XMP_VarString * attrName = 0; - - for ( ; currAttr != endAttr; ++currAttr ) { - attrName = &((*currAttr)->name); - if ( (*attrName != "xml:lang") && (*attrName != "rdf:ID") ) break; - } - - if ( currAttr != endAttr ) { - - XMP_Assert ( attrName != 0 ); - XMP_VarString& attrValue = (*currAttr)->value; - - if ( *attrName == "rdf:datatype" ) { - RDF_LiteralPropertyElement ( xmpParent, xmlNode, isTopLevel ); - } else if ( *attrName != "rdf:parseType" ) { - RDF_EmptyPropertyElement ( xmpParent, xmlNode, isTopLevel ); - } else if ( attrValue == "Literal" ) { - RDF_ParseTypeLiteralPropertyElement ( xmpParent, xmlNode, isTopLevel ); - } else if ( attrValue == "Resource" ) { - RDF_ParseTypeResourcePropertyElement ( xmpParent, xmlNode, isTopLevel ); - } else if ( attrValue == "Collection" ) { - RDF_ParseTypeCollectionPropertyElement ( xmpParent, xmlNode, isTopLevel ); - } else { - RDF_ParseTypeOtherPropertyElement ( xmpParent, xmlNode, isTopLevel ); - } - - } else { - - // Only rdf:ID and xml:lang, could be a resourcePropertyElt, a literalPropertyElt, or an. - // emptyPropertyElt. Look at the child XML nodes to decide which. - - if ( xmlNode.content.empty() ) { - - RDF_EmptyPropertyElement ( xmpParent, xmlNode, isTopLevel ); - - } else { - - XML_cNodePos currChild = xmlNode.content.begin(); - XML_cNodePos endChild = xmlNode.content.end(); - - for ( ; currChild != endChild; ++currChild ) { - if ( (*currChild)->kind != kCDataNode ) break; - } - - if ( currChild == endChild ) { - RDF_LiteralPropertyElement ( xmpParent, xmlNode, isTopLevel ); - } else { - RDF_ResourcePropertyElement ( xmpParent, xmlNode, isTopLevel ); - } - - } - - } - - } - -} // RDF_PropertyElement - - -// ================================================================================================= -// RDF_ResourcePropertyElement -// =========================== -// -// 7.2.15 resourcePropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr? ) ) -// ws* nodeElement ws* -// end-element() -// -// This handles structs using an rdf:Description node, arrays using rdf:Bag/Seq/Alt, and typedNodes. -// It also catches and cleans up qualified properties written with rdf:Description and rdf:value. - -static void -RDF_ResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - if ( isTopLevel && (xmlNode.name == "iX:changes") ) return; // Strip old "punchcard" chaff. - - XMP_Node * newCompound = AddChildNode ( xmpParent, xmlNode, "", isTopLevel ); - - XML_cNodePos currAttr = xmlNode.attrs.begin(); - XML_cNodePos endAttr = xmlNode.attrs.end(); - - for ( ; currAttr != endAttr; ++currAttr ) { - XMP_VarString & attrName = (*currAttr)->name; - if ( attrName == "xml:lang" ) { - AddQualifierNode ( newCompound, **currAttr ); - } else if ( attrName == "rdf:ID" ) { - continue; // Ignore all rdf:ID attributes. - } else { - XMP_Throw ( "Invalid attribute for resource property element", kXMPErr_BadRDF ); - } - } - - XML_cNodePos currChild = xmlNode.content.begin(); - XML_cNodePos endChild = xmlNode.content.end(); - - for ( ; currChild != endChild; ++currChild ) { - if ( ! (*currChild)->IsWhitespaceNode() ) break; - } - if ( currChild == endChild ) XMP_Throw ( "Missing child of resource property element", kXMPErr_BadRDF ); - if ( (*currChild)->kind != kElemNode ) XMP_Throw ( "Children of resource property element must be XML elements", kXMPErr_BadRDF ); - - if ( (*currChild)->name == "rdf:Bag" ) { - newCompound->options |= kXMP_PropValueIsArray; - } else if ( (*currChild)->name == "rdf:Seq" ) { - newCompound->options |= kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered; - } else if ( (*currChild)->name == "rdf:Alt" ) { - newCompound->options |= kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate; - } else { - newCompound->options |= kXMP_PropValueIsStruct; - if ( (*currChild)->name != "rdf:Description" ) { - XMP_VarString typeName ( (*currChild)->ns ); - size_t colonPos = (*currChild)->name.find_first_of(':'); - if ( colonPos == XMP_VarString::npos ) XMP_Throw ( "All XML elements must be in a namespace", kXMPErr_BadXMP ); - typeName.append ( (*currChild)->name, colonPos, XMP_VarString::npos ); - AddQualifierNode ( newCompound, XMP_VarString("rdf:type"), typeName ); - } - } - - RDF_NodeElement ( newCompound, **currChild, kNotTopLevel ); - if ( newCompound->options & kRDF_HasValueElem ) { - FixupQualifiedNode ( newCompound ); - } else if ( newCompound->options & kXMP_PropArrayIsAlternate ) { - DetectAltText ( newCompound ); - } - - for ( ++currChild; currChild != endChild; ++currChild ) { - if ( ! (*currChild)->IsWhitespaceNode() ) XMP_Throw ( "Invalid child of resource property element", kXMPErr_BadRDF ); - } - -} // RDF_ResourcePropertyElement - - -// ================================================================================================= -// RDF_LiteralPropertyElement -// ========================== -// -// 7.2.16 literalPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, datatypeAttr?) ) -// text() -// end-element() -// -// Add a leaf node with the text value and qualifiers for the attributes. - -static void -RDF_LiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - XMP_Node * newChild = AddChildNode ( xmpParent, xmlNode, "", isTopLevel ); - - XML_cNodePos currAttr = xmlNode.attrs.begin(); - XML_cNodePos endAttr = xmlNode.attrs.end(); - - for ( ; currAttr != endAttr; ++currAttr ) { - XMP_VarString & attrName = (*currAttr)->name; - if ( attrName == "xml:lang" ) { - AddQualifierNode ( newChild, **currAttr ); - } else if ( (attrName == "rdf:ID") || (attrName == "rdf:datatype") ) { - continue; // Ignore all rdf:ID and rdf:datatype attributes. - } else { - XMP_Throw ( "Invalid attribute for literal property element", kXMPErr_BadRDF ); - } - } - - XML_cNodePos currChild = xmlNode.content.begin(); - XML_cNodePos endChild = xmlNode.content.end(); - size_t textSize = 0; - - for ( ; currChild != endChild; ++currChild ) { - if ( (*currChild)->kind != kCDataNode ) XMP_Throw ( "Invalid child of literal property element", kXMPErr_BadRDF ); - textSize += (*currChild)->value.size(); - } - - newChild->value.reserve ( textSize ); - - for ( currChild = xmlNode.content.begin(); currChild != endChild; ++currChild ) { - newChild->value += (*currChild)->value; - } - - #if 0 // *** XMP_DebugBuild - newChild->_valuePtr = newChild->value.c_str(); - #endif - -} // RDF_LiteralPropertyElement - - -// ================================================================================================= -// RDF_ParseTypeLiteralPropertyElement -// =================================== -// -// 7.2.17 parseTypeLiteralPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseLiteral ) ) -// literal -// end-element() - -static void -RDF_ParseTypeLiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - IgnoreParam(xmpParent); IgnoreParam(xmlNode); IgnoreParam(isTopLevel); - - XMP_Throw ( "ParseTypeLiteral property element not allowed", kXMPErr_BadXMP ); - -} // RDF_ParseTypeLiteralPropertyElement - - -// ================================================================================================= -// RDF_ParseTypeResourcePropertyElement -// ==================================== -// -// 7.2.18 parseTypeResourcePropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseResource ) ) -// propertyEltList -// end-element() -// -// Add a new struct node with a qualifier for the possible rdf:ID attribute. Then process the XML -// child nodes to get the struct fields. - -static void -RDF_ParseTypeResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - - XMP_Node * newStruct = AddChildNode ( xmpParent, xmlNode, "", isTopLevel ); - newStruct->options |= kXMP_PropValueIsStruct; - - XML_cNodePos currAttr = xmlNode.attrs.begin(); - XML_cNodePos endAttr = xmlNode.attrs.end(); - - for ( ; currAttr != endAttr; ++currAttr ) { - XMP_VarString & attrName = (*currAttr)->name; - if ( attrName == "rdf:parseType" ) { - continue; // ! The caller ensured the value is "Resource". - } else if ( attrName == "xml:lang" ) { - AddQualifierNode ( newStruct, **currAttr ); - } else if ( attrName == "rdf:ID" ) { - continue; // Ignore all rdf:ID attributes. - } else { - XMP_Throw ( "Invalid attribute for ParseTypeResource property element", kXMPErr_BadRDF ); - } - } - - RDF_PropertyElementList ( newStruct, xmlNode, kNotTopLevel ); - - if ( newStruct->options & kRDF_HasValueElem ) FixupQualifiedNode ( newStruct ); - - // *** Need to look for arrays using rdf:Description and rdf:type. - -} // RDF_ParseTypeResourcePropertyElement - - -// ================================================================================================= -// RDF_ParseTypeCollectionPropertyElement -// ====================================== -// -// 7.2.19 parseTypeCollectionPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseCollection ) ) -// nodeElementList -// end-element() - -static void -RDF_ParseTypeCollectionPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - IgnoreParam(xmpParent); IgnoreParam(xmlNode); IgnoreParam(isTopLevel); - - XMP_Throw ( "ParseTypeCollection property element not allowed", kXMPErr_BadXMP ); - -} // RDF_ParseTypeCollectionPropertyElement - - -// ================================================================================================= -// RDF_ParseTypeOtherPropertyElement -// ================================= -// -// 7.2.20 parseTypeOtherPropertyElt -// start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseOther ) ) -// propertyEltList -// end-element() - -static void -RDF_ParseTypeOtherPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - IgnoreParam(xmpParent); IgnoreParam(xmlNode); IgnoreParam(isTopLevel); - - XMP_Throw ( "ParseTypeOther property element not allowed", kXMPErr_BadXMP ); - -} // RDF_ParseTypeOtherPropertyElement - - -// ================================================================================================= -// RDF_EmptyPropertyElement -// ======================== -// -// 7.2.21 emptyPropertyElt -// start-element ( URI == propertyElementURIs, -// attributes == set ( idAttr?, ( resourceAttr | nodeIdAttr )?, propertyAttr* ) ) -// end-element() -// -// -// -// -// -// -// An emptyPropertyElt is an element with no contained content, just a possibly empty set of -// attributes. An emptyPropertyElt can represent three special cases of simple XMP properties: a -// simple property with an empty value (ns:Prop1), a simple property whose value is a URI -// (ns:Prop2), or a simple property with simple qualifiers (ns:Prop3). An emptyPropertyElt can also -// represent an XMP struct whose fields are all simple and unqualified (ns:Prop4). -// -// It is an error to use both rdf:value and rdf:resource - that can lead to invalid RDF in the -// verbose form written using a literalPropertyElt. -// -// The XMP mapping for an emptyPropertyElt is a bit different from generic RDF, partly for -// design reasons and partly for historical reasons. The XMP mapping rules are: -// 1. If there is an rdf:value attribute then this is a simple property with a text value. -// All other attributes are qualifiers. -// 2. If there is an rdf:resource attribute then this is a simple property with a URI value. -// All other attributes are qualifiers. -// 3. If there are no attributes other than xml:lang, rdf:ID, or rdf:nodeID then this is a simple -// property with an empty value. -// 4. Otherwise this is a struct, the attributes other than xml:lang, rdf:ID, or rdf:nodeID are fields. - -static void -RDF_EmptyPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel ) -{ - bool hasPropertyAttrs = false; - bool hasResourceAttr = false; - bool hasNodeIDAttr = false; - bool hasValueAttr = false; - - const XML_Node * valueNode = 0; // ! Can come from rdf:value or rdf:resource. - - if ( ! xmlNode.content.empty() ) XMP_Throw ( "Nested content not allowed with rdf:resource or property attributes", kXMPErr_BadRDF ); - - // First figure out what XMP this maps to and remember the XML node for a simple value. - - XML_cNodePos currAttr = xmlNode.attrs.begin(); - XML_cNodePos endAttr = xmlNode.attrs.end(); - - for ( ; currAttr != endAttr; ++currAttr ) { - - RDFTermKind attrTerm = GetRDFTermKind ( (*currAttr)->name ); - - switch ( attrTerm ) { - - case kRDFTerm_ID : - // Nothing to do. - break; - - case kRDFTerm_resource : - if ( hasNodeIDAttr ) XMP_Throw ( "Empty property element can't have both rdf:resource and rdf:nodeID", kXMPErr_BadRDF ); - if ( hasValueAttr ) XMP_Throw ( "Empty property element can't have both rdf:value and rdf:resource", kXMPErr_BadXMP ); - hasResourceAttr = true; - if ( ! hasValueAttr ) valueNode = *currAttr; - break; - - case kRDFTerm_nodeID : - if ( hasResourceAttr ) XMP_Throw ( "Empty property element can't have both rdf:resource and rdf:nodeID", kXMPErr_BadRDF ); - hasNodeIDAttr = true; - break; - - case kRDFTerm_Other : - if ( (*currAttr)->name == "rdf:value" ) { - if ( hasResourceAttr ) XMP_Throw ( "Empty property element can't have both rdf:value and rdf:resource", kXMPErr_BadXMP ); - hasValueAttr = true; - valueNode = *currAttr; - } else if ( (*currAttr)->name != "xml:lang" ) { - hasPropertyAttrs = true; - } - break; - - default : - XMP_Throw ( "Unrecognized attribute of empty property element", kXMPErr_BadRDF ); - break; - - } - - } - - // Create the right kind of child node and visit the attributes again to add the fields or qualifiers. - // ! Because of implementation vagaries, the xmpParent is the tree root for top level properties. - // ! The schema is found, created if necessary, by AddChildNode. - - XMP_Node * childNode = AddChildNode ( xmpParent, xmlNode, "", isTopLevel ); - bool childIsStruct = false; - - if ( hasValueAttr | hasResourceAttr ) { - childNode->value = valueNode->value; - if ( ! hasValueAttr ) childNode->options |= kXMP_PropValueIsURI; // ! Might have both rdf:value and rdf:resource. - } else if ( hasPropertyAttrs ) { - childNode->options |= kXMP_PropValueIsStruct; - childIsStruct = true; - } - - currAttr = xmlNode.attrs.begin(); - endAttr = xmlNode.attrs.end(); - - for ( ; currAttr != endAttr; ++currAttr ) { - - if ( *currAttr == valueNode ) continue; // Skip the rdf:value or rdf:resource attribute holding the value. - RDFTermKind attrTerm = GetRDFTermKind ( (*currAttr)->name ); - - switch ( attrTerm ) { - - case kRDFTerm_ID : - case kRDFTerm_nodeID : - break; // Ignore all rdf:ID and rdf:nodeID attributes.w - - case kRDFTerm_resource : - AddQualifierNode ( childNode, **currAttr ); - break; - - case kRDFTerm_Other : - if ( (! childIsStruct) || (*currAttr)->name == "xml:lang" ) { - AddQualifierNode ( childNode, **currAttr ); - } else { - AddChildNode ( childNode, **currAttr, (*currAttr)->value.c_str(), false ); - } - break; - - default : - XMP_Throw ( "Unrecognized attribute of empty property element", kXMPErr_BadRDF ); - break; - - } - - } - -} // RDF_EmptyPropertyElement - - -// ================================================================================================= diff --git a/xmpsdk/src/UnicodeConversions.cpp b/xmpsdk/src/UnicodeConversions.cpp deleted file mode 100644 index 123c502b00..0000000000 --- a/xmpsdk/src/UnicodeConversions.cpp +++ /dev/null @@ -1,1665 +0,0 @@ -// ================================================================================================= -// Copyright 2004-2007 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 "XMP_Const.h" - -#if UnicodeTestBuild - #include - #include - #define UC_Assert assert - #define UC_Throw(m,k) throw std::logic_error ( m ) -#else - #define UC_Assert(cond) /* Nothing for now, should be XMP_Assert. */ - #define UC_Throw(msg,id) throw XMP_Error ( id, msg ) -#endif - -#include "UnicodeConversions.hpp" - -using namespace std; - -// ================================================================================================= - -// *** Look into using asm inlines, e.g. count-leading bits for multi-byte UTF-8. - -CodePoint_to_UTF16_Proc CodePoint_to_UTF16BE = 0; -CodePoint_to_UTF16_Proc CodePoint_to_UTF16LE = 0; - -CodePoint_from_UTF16_Proc CodePoint_from_UTF16BE = 0; -CodePoint_from_UTF16_Proc CodePoint_from_UTF16LE = 0; - -UTF8_to_UTF16_Proc UTF8_to_UTF16BE = 0; -UTF8_to_UTF16_Proc UTF8_to_UTF16LE = 0; -UTF8_to_UTF32_Proc UTF8_to_UTF32BE = 0; -UTF8_to_UTF32_Proc UTF8_to_UTF32LE = 0; - -UTF16_to_UTF8_Proc UTF16BE_to_UTF8 = 0; -UTF16_to_UTF8_Proc UTF16LE_to_UTF8 = 0; -UTF32_to_UTF8_Proc UTF32BE_to_UTF8 = 0; -UTF32_to_UTF8_Proc UTF32LE_to_UTF8 = 0; - -UTF8_to_UTF16_Proc UTF8_to_UTF16Native = 0; -UTF8_to_UTF32_Proc UTF8_to_UTF32Native = 0; -UTF16_to_UTF8_Proc UTF16Native_to_UTF8 = 0; -UTF32_to_UTF8_Proc UTF32Native_to_UTF8 = 0; - -UTF16_to_UTF32_Proc UTF16BE_to_UTF32BE = 0; -UTF16_to_UTF32_Proc UTF16BE_to_UTF32LE = 0; -UTF16_to_UTF32_Proc UTF16LE_to_UTF32BE = 0; -UTF16_to_UTF32_Proc UTF16LE_to_UTF32LE = 0; - -UTF32_to_UTF16_Proc UTF32BE_to_UTF16BE = 0; -UTF32_to_UTF16_Proc UTF32BE_to_UTF16LE = 0; -UTF32_to_UTF16_Proc UTF32LE_to_UTF16BE = 0; -UTF32_to_UTF16_Proc UTF32LE_to_UTF16LE = 0; - -// ------------------------------------------------------------------------------------------------- - -static size_t swap32to16Offset = 0; // Offset to "convert" a swapped UTF32 pointer into a swapped UTF16 pointer. - -// ------------------------------------------------------------------------------------------------- - -static void CodePoint_to_UTF16Nat ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ); -static void CodePoint_to_UTF16Swp ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ); - -static void CodePoint_from_UTF16Nat ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ); -static void CodePoint_from_UTF16Swp ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ); - -// ------------------------------------------------------------------------------------------------- - -static void UTF8_to_UTF16Nat ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf8Read, size_t * utf16Written ); - -static void UTF8_to_UTF16Swp ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf8Read, size_t * utf16Written ); - -static void UTF8_to_UTF32Nat ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf8Read, size_t * utf32Written ); - -static void UTF8_to_UTF32Swp ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf8Read, size_t * utf32Written ); - -// ------------------------------------------------------------------------------------------------- - -static void UTF16Nat_to_UTF8 ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf16Read, size_t * utf8Written ); - -static void UTF16Swp_to_UTF8 ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf16Read, size_t * utf8Written ); - -static void UTF32Nat_to_UTF8 ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf32Read, size_t * utf8Written ); - -static void UTF32Swp_to_UTF8 ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf32Read, size_t * utf8Written ); - -// ------------------------------------------------------------------------------------------------- - -static void UTF16Nat_to_UTF32Nat ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ); - -static void UTF16Nat_to_UTF32Swp ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ); - -static void UTF16Swp_to_UTF32Nat ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ); - -static void UTF16Swp_to_UTF32Swp ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ); - -// ------------------------------------------------------------------------------------------------- - -static void UTF32Nat_to_UTF16Nat ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ); - -static void UTF32Nat_to_UTF16Swp ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ); - -static void UTF32Swp_to_UTF16Nat ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ); - -static void UTF32Swp_to_UTF16Swp ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ); - -// ================================================================================================= - -void InitializeUnicodeConversions() -{ - UC_Assert ( (sizeof(UTF8Unit) == 1) && (sizeof(UTF16Unit) == 2) && (sizeof(UTF32Unit) == 4) ); - - UTF16Unit u16 = 0x00FF; - bool bigEndian = (*((UTF8Unit*)&u16) == 0); - - UTF8_to_UTF16Native = UTF8_to_UTF16Nat; - UTF8_to_UTF32Native = UTF8_to_UTF32Nat; - UTF16Native_to_UTF8 = UTF16Nat_to_UTF8; - UTF32Native_to_UTF8 = UTF32Nat_to_UTF8; - - if ( bigEndian ) { - - swap32to16Offset = 0; - - CodePoint_to_UTF16BE = CodePoint_to_UTF16Nat; - CodePoint_to_UTF16LE = CodePoint_to_UTF16Swp; - - CodePoint_from_UTF16BE = CodePoint_from_UTF16Nat; - CodePoint_from_UTF16LE = CodePoint_from_UTF16Swp; - - UTF8_to_UTF16BE = UTF8_to_UTF16Nat; - UTF8_to_UTF16LE = UTF8_to_UTF16Swp; - UTF8_to_UTF32BE = UTF8_to_UTF32Nat; - UTF8_to_UTF32LE = UTF8_to_UTF32Swp; - - UTF16BE_to_UTF8 = UTF16Nat_to_UTF8; - UTF16LE_to_UTF8 = UTF16Swp_to_UTF8; - UTF32BE_to_UTF8 = UTF32Nat_to_UTF8; - UTF32LE_to_UTF8 = UTF32Swp_to_UTF8; - - UTF16BE_to_UTF32BE = UTF16Nat_to_UTF32Nat; - UTF16BE_to_UTF32LE = UTF16Nat_to_UTF32Swp; - UTF16LE_to_UTF32BE = UTF16Swp_to_UTF32Nat; - UTF16LE_to_UTF32LE = UTF16Swp_to_UTF32Swp; - - UTF32BE_to_UTF16BE = UTF32Nat_to_UTF16Nat; - UTF32BE_to_UTF16LE = UTF32Nat_to_UTF16Swp; - UTF32LE_to_UTF16BE = UTF32Swp_to_UTF16Nat; - UTF32LE_to_UTF16LE = UTF32Swp_to_UTF16Swp; - - } else { - - swap32to16Offset = 1; // ! Offset in UTF16 units! - - CodePoint_to_UTF16BE = CodePoint_to_UTF16Swp; - CodePoint_to_UTF16LE = CodePoint_to_UTF16Nat; - - CodePoint_from_UTF16BE = CodePoint_from_UTF16Swp; - CodePoint_from_UTF16LE = CodePoint_from_UTF16Nat; - - UTF8_to_UTF16BE = UTF8_to_UTF16Swp; - UTF8_to_UTF16LE = UTF8_to_UTF16Nat; - UTF8_to_UTF32BE = UTF8_to_UTF32Swp; - UTF8_to_UTF32LE = UTF8_to_UTF32Nat; - - UTF16BE_to_UTF8 = UTF16Swp_to_UTF8; - UTF16LE_to_UTF8 = UTF16Nat_to_UTF8; - UTF32BE_to_UTF8 = UTF32Swp_to_UTF8; - UTF32LE_to_UTF8 = UTF32Nat_to_UTF8; - - UTF16BE_to_UTF32BE = UTF16Swp_to_UTF32Swp; - UTF16BE_to_UTF32LE = UTF16Swp_to_UTF32Nat; - UTF16LE_to_UTF32BE = UTF16Nat_to_UTF32Swp; - UTF16LE_to_UTF32LE = UTF16Nat_to_UTF32Nat; - - UTF32BE_to_UTF16BE = UTF32Swp_to_UTF16Swp; - UTF32BE_to_UTF16LE = UTF32Swp_to_UTF16Nat; - UTF32LE_to_UTF16BE = UTF32Nat_to_UTF16Swp; - UTF32LE_to_UTF16LE = UTF32Nat_to_UTF16Nat; - - } - -} // InitializeUnicodeConversions - -// ================================================================================================= - -#if XMP_MacBuild && __MWERKS__ - - #define UTF16InSwap(inPtr) UTF16Unit ( __lhbrx ( (void*)(inPtr), 0 ) ) - #define UTF32InSwap(inPtr) UTF32Unit ( __lwbrx ( (void*)(inPtr), 0 ) ) - - #define UTF16OutSwap(outPtr,value) __sthbrx ( value, (void*)(outPtr), 0 ) - #define UTF32OutSwap(outPtr,value) __stwbrx ( value, (void*)(outPtr), 0 ) - -#else - - static inline UTF16Unit UTF16InSwap ( const UTF16Unit * inPtr ) - { - UTF16Unit inUnit = *inPtr; - return (inUnit << 8) | (inUnit >> 8); - } - - static inline UTF32Unit UTF32InSwap ( const UTF32Unit * inPtr ) - { - UTF32Unit inUnit = *inPtr; - return (inUnit << 24) | ((inUnit << 8) & 0x00FF0000) | ((inUnit >> 8) & 0x0000FF00) | (inUnit >> 24); - } - - static inline void UTF16OutSwap ( UTF16Unit * outPtr, const UTF16Unit value ) - { - UTF16Unit outUnit = (value << 8) | (value >> 8); - *outPtr = outUnit; - } - - static inline void UTF32OutSwap ( UTF32Unit * outPtr, const UTF32Unit value ) - { - UTF32Unit outUnit = (value << 24) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0x0000FF00) | (value >> 24); - *outPtr = outUnit; - } - -#endif - -// ================================================================================================= - -void SwapUTF16 ( const UTF16Unit * utf16In, UTF16Unit * utf16Out, const size_t utf16Len ) -{ - for ( size_t i = 0; i < utf16Len; ++i ) utf16Out[i] = UTF16InSwap(utf16In+i); -} - -void SwapUTF32 ( const UTF32Unit * utf32In, UTF32Unit * utf32Out, const size_t utf32Len ) { - for ( size_t i = 0; i < utf32Len; ++i ) utf32Out[i] = UTF32InSwap(utf32In+i); -} - -// ================================================================================================= - -extern void ToUTF16 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str, bool bigEndian ) -{ - UTF8_to_UTF16_Proc Converter = UTF8_to_UTF16LE; - if ( bigEndian ) Converter = UTF8_to_UTF16BE; - - enum { kBufferSize = 8*1024 }; - UTF16Unit u16Buffer[kBufferSize]; // 16K bytes - size_t readCount, writeCount; - - utf16Str->erase(); - utf16Str->reserve ( 2*utf8Len ); // As good a guess as any. - - while ( utf8Len > 0 ) { - Converter ( utf8In, utf8Len, u16Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf16Str->append ( (const char *)u16Buffer, writeCount*2 ); - utf8In += readCount; - utf8Len -= readCount; - } - -} // ToUTF16 - -// ================================================================================================= - -extern void ToUTF16Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str ) -{ - enum { kBufferSize = 8*1024 }; - UTF16Unit u16Buffer[kBufferSize]; // 16K bytes - size_t readCount, writeCount; - - utf16Str->erase(); - utf16Str->reserve ( 2*utf8Len ); // As good a guess as any. - - while ( utf8Len > 0 ) { - UTF8_to_UTF16Nat ( utf8In, utf8Len, u16Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf16Str->append ( (const char *)u16Buffer, writeCount*2 ); - utf8In += readCount; - utf8Len -= readCount; - } - -} // ToUTF16Native - -// ================================================================================================= - -extern void ToUTF32 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str, bool bigEndian ) -{ - UTF8_to_UTF32_Proc Converter = UTF8_to_UTF32LE; - if ( bigEndian ) Converter = UTF8_to_UTF32BE; - - enum { kBufferSize = 4*1024 }; - UTF32Unit u32Buffer[kBufferSize]; // 16K bytes - size_t readCount, writeCount; - - utf32Str->erase(); - utf32Str->reserve ( 4*utf8Len ); // As good a guess as any. - - while ( utf8Len > 0 ) { - Converter ( utf8In, utf8Len, u32Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf32Str->append ( (const char *)u32Buffer, writeCount*4 ); - utf8In += readCount; - utf8Len -= readCount; - } - -} // ToUTF32 - -// ================================================================================================= - -extern void ToUTF32Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str ) -{ - enum { kBufferSize = 4*1024 }; - UTF32Unit u32Buffer[kBufferSize]; // 16K bytes - size_t readCount, writeCount; - - utf32Str->erase(); - utf32Str->reserve ( 4*utf8Len ); // As good a guess as any. - - while ( utf8Len > 0 ) { - UTF8_to_UTF32Nat ( utf8In, utf8Len, u32Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf32Str->append ( (const char *)u32Buffer, writeCount*4 ); - utf8In += readCount; - utf8Len -= readCount; - } - -} // ToUTF32Native - -// ================================================================================================= - -extern void FromUTF16 ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str, bool bigEndian ) -{ - UTF16_to_UTF8_Proc Converter = UTF16LE_to_UTF8; - if ( bigEndian ) Converter = UTF16BE_to_UTF8; - - enum { kBufferSize = 16*1024 }; - UTF8Unit u8Buffer[kBufferSize]; - size_t readCount, writeCount; - - utf8Str->erase(); - utf8Str->reserve ( 2*utf16Len ); // As good a guess as any. - - while ( utf16Len > 0 ) { - Converter ( utf16In, utf16Len, u8Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf8Str->append ( (const char *)u8Buffer, writeCount ); - utf16In += readCount; - utf16Len -= readCount; - } - -} // FromUTF16 - -// ================================================================================================= - -extern void FromUTF16Native ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str ) -{ - enum { kBufferSize = 16*1024 }; - UTF8Unit u8Buffer[kBufferSize]; - size_t readCount, writeCount; - - utf8Str->erase(); - utf8Str->reserve ( 2*utf16Len ); // As good a guess as any. - - while ( utf16Len > 0 ) { - UTF16Nat_to_UTF8 ( utf16In, utf16Len, u8Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf8Str->append ( (const char *)u8Buffer, writeCount ); - utf16In += readCount; - utf16Len -= readCount; - } - -} // FromUTF16Native - -// ================================================================================================= - -extern void FromUTF32 ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str, bool bigEndian ) -{ - UTF32_to_UTF8_Proc Converter = UTF32LE_to_UTF8; - if ( bigEndian ) Converter = UTF32BE_to_UTF8; - - enum { kBufferSize = 16*1024 }; - UTF8Unit u8Buffer[kBufferSize]; - size_t readCount, writeCount; - - utf8Str->erase(); - utf8Str->reserve ( 2*utf32Len ); // As good a guess as any. - - while ( utf32Len > 0 ) { - Converter ( utf32In, utf32Len, u8Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf8Str->append ( (const char *)u8Buffer, writeCount ); - utf32In += readCount; - utf32Len -= readCount; - } - -} // FromUTF32 - -// ================================================================================================= - -extern void FromUTF32Native ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str ) -{ - enum { kBufferSize = 16*1024 }; - UTF8Unit u8Buffer[kBufferSize]; - size_t readCount, writeCount; - - utf8Str->erase(); - utf8Str->reserve ( 2*utf32Len ); // As good a guess as any. - - while ( utf32Len > 0 ) { - UTF32Nat_to_UTF8 ( utf32In, utf32Len, u8Buffer, kBufferSize, &readCount, &writeCount ); - if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML ); - utf8Str->append ( (const char *)u8Buffer, writeCount ); - utf32In += readCount; - utf32Len -= readCount; - } - -} // FromUTF32Native - -// ================================================================================================= - -static void CodePoint_to_UTF8_Multi ( const UTF32Unit cpIn, UTF8Unit * utf8Out, const size_t utf8Len, size_t * utf8Written ) -{ - size_t unitCount = 0; - - if ( cpIn > 0x10FFFF ) UC_Throw ( "Bad UTF-32 - out of range", kXMPErr_BadParam ); - if ( (0xD800 <= cpIn) && (cpIn <= 0xDFFF) ) UC_Throw ( "Bad UTF-32 - surrogate code point", kXMPErr_BadParam ); - - // Compute the number of bytes using 6 data bits each. Then see if the highest order bits will - // fit into the leading byte. Write the UTF-8 sequence if there is enough room. - - UTF32Unit temp, mask; - size_t bytesNeeded = 0; - for ( temp = cpIn; temp != 0; temp = temp >> 6 ) ++bytesNeeded; - - temp = cpIn >> ((bytesNeeded-1)*6); // The highest order data bits. - mask = (0x80 >> bytesNeeded) - 1; // Available data bits in the leading byte. - if ( temp > mask ) ++bytesNeeded; - - if ( bytesNeeded > utf8Len ) goto Done; // Not enough room for the output. - unitCount = bytesNeeded; - - temp = cpIn; - for ( --bytesNeeded; bytesNeeded > 0; --bytesNeeded ) { - utf8Out[bytesNeeded] = 0x80 | UTF8Unit ( temp & 0x3F ); - temp = temp >> 6; - } - - mask = ~((1 << (8-unitCount)) - 1); - utf8Out[0] = UTF8Unit ( mask | temp ); - -Done: - *utf8Written = unitCount; - return; - -} // CodePoint_to_UTF8_Multi - -// ================================================================================================= - -void CodePoint_to_UTF8 ( const UTF32Unit cpIn, UTF8Unit * utf8Out, const size_t utf8Len, size_t * utf8Written ) -{ - size_t unitCount = 0; - - UC_Assert ( (utf8Out != 0) && (utf8Written != 0) ); - if ( utf8Len == 0 ) goto Done; - if ( cpIn > 0x7F ) goto MultiByte; // ! Force linear execution path for ASCII. - - if ( utf8Len == 0 ) goto Done; - unitCount = 1; - *utf8Out = UTF8Unit(cpIn); - -Done: - *utf8Written = unitCount; - return; - -MultiByte: - CodePoint_to_UTF8_Multi( cpIn, utf8Out, utf8Len, utf8Written ); - return; - -} // CodePoint_to_UTF8 - -// ================================================================================================= - -static void CodePoint_from_UTF8_Multi ( const UTF8Unit * utf8In, const size_t utf8Len, UTF32Unit * cpOut, size_t * utf8Read ) -{ - UTF8Unit inUnit = *utf8In; - size_t unitCount = 0; - UTF32Unit cp; // ! Avoid gcc complaints about declarations after goto's. - const UTF8Unit * utf8Pos; - - // ------------------------------------------------------------------------------------- - // We've got a multibyte UTF-8 character. The first byte has the number of bytes and the - // highest order data bits. The other bytes each add 6 more data bits. - - #if 0 // This might be a more effcient way to count the bytes. - static XMP_Uns8 kByteCounts[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 4 }; - size_t bytesNeeded = kByteCounts [ inUnit >> 4 ]; - if ( (bytesNeeded < 2) || ((bytesNeeded == 4) && ((inUnit & 0x08) != 0)) ) { - UC_Throw ( "Invalid UTF-8 sequence length", kXMPErr_BadParam ); - } - #endif - - size_t bytesNeeded = 0; // Count the leading 1 bits in the first byte. - for ( UTF8Unit temp = inUnit; temp > 0x7F; temp = temp << 1 ) ++bytesNeeded; - // *** Consider CPU-specific assembly inline, e.g. cntlzw on PowerPC. - - if ( (bytesNeeded < 2) || (bytesNeeded > 4) ) UC_Throw ( "Invalid UTF-8 sequence length", kXMPErr_BadParam ); - if ( bytesNeeded > utf8Len ) goto Done; // Not enough input in this buffer. - unitCount = bytesNeeded; - - cp = inUnit & ((1 << (7-unitCount)) - 1); // Isolate the initial data bits in the bottom of cp. - - utf8Pos = utf8In + 1; // We've absorbed the first byte. - for ( --bytesNeeded; bytesNeeded > 0; --bytesNeeded, ++utf8Pos ) { - inUnit = *utf8Pos; - if ( (inUnit & UTF8Unit(0xC0)) != UTF8Unit(0x80) ) UC_Throw ( "Invalid UTF-8 data byte", kXMPErr_BadParam ); - cp = (cp << 6) | (inUnit & 0x3F); - } - - if ( cp >= 0xD800 ) { // Skip the next comparisons most of the time. - if ( (0xD800 <= cp) && (cp <= 0xDFFF) ) UC_Throw ( "Bad UTF-8 - surrogate code point", kXMPErr_BadParam ); - if ( cp > 0x10FFFF ) UC_Throw ( "Bad UTF-8 - out of range", kXMPErr_BadParam ); - } - - *cpOut = cp; // ! Don't put after Done, don't write if no input. - -Done: - *utf8Read = unitCount; - return; - -} // CodePoint_from_UTF8_Multi - -// ================================================================================================= - -void CodePoint_from_UTF8 ( const UTF8Unit * utf8In, const size_t utf8Len, UTF32Unit * cpOut, size_t * utf8Read ) -{ - UTF8Unit inUnit; // ! Don't read until we know there is input. - size_t unitCount = 0; - - UC_Assert ( (utf8In != 0) && (cpOut != 0) && (utf8Read != 0) ); - if ( utf8Len == 0 ) goto Done; - inUnit = *utf8In; - if ( inUnit >= 0x80 ) goto MultiByte; // ! Force linear execution path for ASCII. - - unitCount = 1; - *cpOut = inUnit; // ! Don't put after Done, don't write if no input. - -Done: - *utf8Read = unitCount; - return; - -MultiByte: - CodePoint_from_UTF8_Multi ( utf8In, utf8Len, cpOut, utf8Read ); - return; - -} // CodePoint_from_UTF8 - -// ================================================================================================= - -static void CodePoint_to_UTF16Nat_Surrogate ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ) -{ - size_t unitCount = 0; - UTF32Unit temp; // ! Avoid gcc complaints about declarations after goto's. - - if ( cpIn > 0x10FFFF ) UC_Throw ( "Bad UTF-32 - out of range", kXMPErr_BadParam ); - if ( utf16Len < 2 ) goto Done; // Not enough room for the output. - - unitCount = 2; - temp = cpIn - 0x10000; - utf16Out[0] = 0xD800 | UTF16Unit ( temp >> 10 ); - utf16Out[1] = 0xDC00 | UTF16Unit ( temp & 0x3FF ); - -Done: - *utf16Written = unitCount; - return; - -} // CodePoint_to_UTF16Nat_Surrogate - -// ================================================================================================= - -static void CodePoint_to_UTF16Nat ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ) -{ - size_t unitCount = 0; - - UC_Assert ( (utf16Out != 0) && (utf16Written != 0) ); - if ( utf16Len == 0 ) goto Done; - if ( cpIn >= 0xD800 ) goto CheckSurrogate; // ! Force linear execution path for the BMP. - -InBMP: - unitCount = 1; - *utf16Out = UTF16Unit(cpIn); - -Done: - *utf16Written = unitCount; - return; - -CheckSurrogate: - if ( cpIn > 0xFFFF ) goto SurrogatePair; - if ( cpIn > 0xDFFF ) goto InBMP; - UC_Throw ( "Bad UTF-32 - surrogate code point", kXMPErr_BadParam ); - -SurrogatePair: - CodePoint_to_UTF16Nat_Surrogate ( cpIn, utf16Out, utf16Len, utf16Written ); - return; - -} // CodePoint_to_UTF16Nat - -// ================================================================================================= - -static void CodePoint_from_UTF16Nat_Surrogate ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ) -{ - UTF16Unit hiUnit = *utf16In; - size_t unitCount = 0; - UTF16Unit loUnit; // ! Avoid gcc complaints about declarations after goto's. - UTF32Unit cp; - - // ---------------------------------- - // We've got a UTF-16 surrogate pair. - - if ( hiUnit > 0xDBFF ) UC_Throw ( "Bad UTF-16 - leading low surrogate", kXMPErr_BadParam ); - if ( utf16Len < 2 ) goto Done; // Not enough input in this buffer. - - loUnit = *(utf16In+1); - if ( (loUnit < 0xDC00) || (0xDFFF < loUnit) ) UC_Throw ( "Bad UTF-16 - missing low surrogate", kXMPErr_BadParam ); - - unitCount = 2; - cp = (((hiUnit & 0x3FF) << 10) | (loUnit & 0x3FF)) + 0x10000; - - *cpOut = cp; // ! Don't put after Done, don't write if no input. - -Done: - *utf16Read = unitCount; - return; - -} // CodePoint_from_UTF16Nat_Surrogate - -// ================================================================================================= - -static void CodePoint_from_UTF16Nat ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ) -{ - UTF16Unit inUnit; // ! Don't read until we know there is input. - size_t unitCount = 0; - - UC_Assert ( (utf16In != 0) && (cpOut != 0) && (utf16Read != 0) ); - if ( utf16Len == 0 ) goto Done; - inUnit = *utf16In; - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) goto SurrogatePair; // ! Force linear execution path for the BMP. - - unitCount = 1; - *cpOut = inUnit; // ! Don't put after Done, don't write if no input. - -Done: - *utf16Read = unitCount; - return; - -SurrogatePair: - CodePoint_from_UTF16Nat_Surrogate ( utf16In, utf16Len, cpOut, utf16Read ); - return; - -} // CodePoint_from_UTF16Nat - -// ================================================================================================= - -static void UTF8_to_UTF16Nat ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf8Read, size_t * utf16Written ) -{ - const UTF8Unit * utf8Pos = utf8In; - UTF16Unit * utf16Pos = utf16Out; - - size_t utf8Left = utf8Len; - size_t utf16Left = utf16Len; - - UC_Assert ( (utf8In != 0) && (utf16Out != 0) && (utf8Read != 0) && (utf16Written != 0) ); - - while ( (utf8Left > 0) && (utf16Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf8Left; - if ( limit > utf16Left ) limit = utf16Left; - for ( i = 0; i < limit; ++i ) { - UTF8Unit inUnit = *utf8Pos; - if ( inUnit > 0x7F ) break; - *utf16Pos = inUnit; - ++utf8Pos; - ++utf16Pos; - } - utf8Left -= i; - utf16Left -= i; - - // Do a run of non-ASCII, it copies multiple input units into 1 or 2 output units. - while ( (utf8Left > 0) && (utf16Left > 0) ) { - UTF32Unit cp; - size_t len8, len16; - UTF8Unit inUnit = *utf8Pos; - if ( inUnit <= 0x7F ) break; - CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, &cp, &len8 ); - if ( len8 == 0 ) goto Done; // The input buffer ends in the middle of a character. - if ( cp <= 0xFFFF ) { - *utf16Pos = UTF16Unit(cp); - len16 = 1; - } else { - CodePoint_to_UTF16Nat_Surrogate ( cp, utf16Pos, utf16Left, &len16 ); - if ( len16 == 0 ) goto Done; // Not enough room in the output buffer. - } - utf8Left -= len8; - utf8Pos += len8; - utf16Left -= len16; - utf16Pos += len16; - } - - } - -Done: // Set the output lengths. - *utf8Read = utf8Len - utf8Left; - *utf16Written = utf16Len - utf16Left; - -} // UTF8_to_UTF16Nat - -// ================================================================================================= - -static void UTF8_to_UTF32Nat ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf8Read, size_t * utf32Written ) -{ - const UTF8Unit * utf8Pos = utf8In; - UTF32Unit * utf32Pos = utf32Out; - - size_t utf8Left = utf8Len; - size_t utf32Left = utf32Len; - - UC_Assert ( (utf8In != 0) && (utf32Out != 0) && (utf8Read != 0) && (utf32Written != 0) ); - - while ( (utf8Left > 0) && (utf32Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf8Left; - if ( limit > utf32Left ) limit = utf32Left; - for ( i = 0; i < limit; ++i ) { - UTF8Unit inUnit = *utf8Pos; - if ( inUnit > 0x7F ) break; - *utf32Pos = inUnit; - ++utf8Pos; - ++utf32Pos; - } - utf8Left -= i; - utf32Left -= i; - - // Do a run of non-ASCII, it copies variable input into 1 output unit. - while ( (utf8Left > 0) && (utf32Left > 0) ) { - size_t len; - UTF8Unit inUnit = *utf8Pos; - if ( inUnit <= 0x7F ) break; - CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, utf32Pos, &len ); - if ( len == 0 ) goto Done; // The input buffer ends in the middle of a character. - utf8Left -= len; - utf8Pos += len; - utf32Left -= 1; - utf32Pos += 1; - } - - } - -Done: // Set the output lengths. - *utf8Read = utf8Len - utf8Left; - *utf32Written = utf32Len - utf32Left; - -} // UTF8_to_UTF32Nat - -// ================================================================================================= - -static void UTF16Nat_to_UTF8 ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf16Read, size_t * utf8Written ) -{ - const UTF16Unit * utf16Pos = utf16In; - UTF8Unit * utf8Pos = utf8Out; - - size_t utf16Left = utf16Len; - size_t utf8Left = utf8Len; - - UC_Assert ( (utf16In != 0) && (utf8Out != 0) && (utf16Read != 0) && (utf8Written != 0) ); - - while ( (utf16Left > 0) && (utf8Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf16Left; - if ( limit > utf8Left ) limit = utf8Left; - for ( i = 0; i < limit; ++i ) { - UTF16Unit inUnit = *utf16Pos; - if ( inUnit > 0x7F ) break; - *utf8Pos = UTF8Unit(inUnit); - ++utf16Pos; - ++utf8Pos; - } - utf16Left -= i; - utf8Left -= i; - - // Do a run of non-ASCII inside the BMP, it copies 1 input unit into multiple output units. - while ( (utf16Left > 0) && (utf8Left > 0) ) { - size_t len8; - UTF16Unit inUnit = *utf16Pos; - if ( inUnit <= 0x7F ) break; - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break; - CodePoint_to_UTF8_Multi ( inUnit, utf8Pos, utf8Left, &len8 ); - if ( len8 == 0 ) goto Done; // Not enough room in the output buffer. - utf16Left -= 1; - utf16Pos += 1; - utf8Left -= len8; - utf8Pos += len8; - } - - // Do a run of surrogate pairs, it copies 2 input units into multiple output units. - while ( (utf16Left > 0) && (utf8Left > 0) ) { - UTF32Unit cp; - size_t len16, len8; - UTF16Unit inUnit = *utf16Pos; - if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break; - CodePoint_from_UTF16Nat_Surrogate ( utf16Pos, utf16Left, &cp, &len16 ); - if ( len16 == 0 ) goto Done; // The input buffer ends in the middle of a surrogate pair. - UC_Assert ( len16 == 2 ); - CodePoint_to_UTF8_Multi ( cp, utf8Pos, utf8Left, &len8 ); - if ( len8 == 0 ) goto Done; // Not enough room in the output buffer. - utf16Left -= len16; - utf16Pos += len16; - utf8Left -= len8; - utf8Pos += len8; - } - - } - -Done: // Set the output lengths. - *utf16Read = utf16Len - utf16Left; - *utf8Written = utf8Len - utf8Left; - -} // UTF16Nat_to_UTF8 - -// ================================================================================================= - -static void UTF32Nat_to_UTF8 ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf32Read, size_t * utf8Written ) -{ - const UTF32Unit * utf32Pos = utf32In; - UTF8Unit * utf8Pos = utf8Out; - - size_t utf32Left = utf32Len; - size_t utf8Left = utf8Len; - - UC_Assert ( (utf32In != 0) && (utf8Out != 0) && (utf32Read != 0) && (utf8Written != 0) ); - - while ( (utf32Left > 0) && (utf8Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf32Left; - if ( limit > utf8Left ) limit = utf8Left; - for ( i = 0; i < limit; ++i ) { - UTF32Unit inUnit = *utf32Pos; - if ( inUnit > 0x7F ) break; - *utf8Pos = UTF8Unit(inUnit); - ++utf32Pos; - ++utf8Pos; - } - utf32Left -= i; - utf8Left -= i; - - // Do a run of non-ASCII, it copies 1 input unit into multiple output units. - while ( (utf32Left > 0) && (utf8Left > 0) ) { - size_t len; - UTF32Unit inUnit = *utf32Pos; - if ( inUnit <= 0x7F ) break; - CodePoint_to_UTF8_Multi ( inUnit, utf8Pos, utf8Left, &len ); - if ( len == 0 ) goto Done; // Not enough room in the output buffer. - utf32Left -= 1; - utf32Pos += 1; - utf8Left -= len; - utf8Pos += len; - } - - } - -Done: // Set the output lengths. - *utf32Read = utf32Len - utf32Left; - *utf8Written = utf8Len - utf8Left; - -} // UTF32Nat_to_UTF8 - -// ================================================================================================= - -static void UTF16Nat_to_UTF32Nat ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ) -{ - const UTF16Unit * utf16Pos = utf16In; - UTF32Unit * utf32Pos = utf32Out; - - size_t utf16Left = utf16Len; - size_t utf32Left = utf32Len; - - UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) ); - - while ( (utf16Left > 0) && (utf32Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf16Left; - if ( limit > utf32Left ) limit = utf32Left; - for ( i = 0; i < limit; ++i ) { - UTF16Unit inUnit = *utf16Pos; - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break; - *utf32Pos = inUnit; - ++utf16Pos; - ++utf32Pos; - } - utf16Left -= i; - utf32Left -= i; - - // Do a run of surrogate pairs, it copies 2 input units into 1 output unit. - while ( (utf16Left > 0) && (utf32Left > 0) ) { - size_t len; - UTF16Unit inUnit = *utf16Pos; - if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break; - CodePoint_from_UTF16Nat_Surrogate ( utf16Pos, utf16Left, utf32Pos, &len ); - if ( len == 0 ) goto Done; // The input buffer ends in the middle of a surrogate pair. - UC_Assert ( len == 2 ); - utf16Left -= len; - utf16Pos += len; - utf32Left -= 1; - utf32Pos += 1; - } - - } - -Done: // Set the output lengths. - *utf16Read = utf16Len - utf16Left; - *utf32Written = utf32Len - utf32Left; - -} // UTF16Nat_to_UTF32Nat - -// ================================================================================================= - -static void UTF32Nat_to_UTF16Nat ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ) -{ - const UTF32Unit * utf32Pos = utf32In; - UTF16Unit * utf16Pos = utf16Out; - - size_t utf32Left = utf32Len; - size_t utf16Left = utf16Len; - - UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) ); - - while ( (utf32Left > 0) && (utf16Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf32Left; - if ( limit > utf16Left ) limit = utf16Left; - for ( i = 0; i < limit; ++i ) { - UTF32Unit inUnit = *utf32Pos; - if ( inUnit > 0xFFFF ) break; - *utf16Pos = UTF16Unit(inUnit); - ++utf32Pos; - ++utf16Pos; - } - utf32Left -= i; - utf16Left -= i; - - // Do a run of non-BMP, it copies 1 input unit into 2 output units. - while ( (utf32Left > 0) && (utf16Left > 0) ) { - size_t len; - UTF32Unit inUnit = *utf32Pos; - if ( inUnit <= 0xFFFF ) break; - CodePoint_to_UTF16Nat_Surrogate ( inUnit, utf16Pos, utf16Left, &len ); - if ( len == 0 ) goto Done; // Not enough room in the output buffer. - UC_Assert ( len == 2 ); - utf32Left -= 1; - utf32Pos += 1; - utf16Left -= 2; - utf16Pos += 2; - } - - } - -Done: // Set the output lengths. - *utf32Read = utf32Len - utf32Left; - *utf16Written = utf16Len - utf16Left; - -} // UTF32Nat_to_UTF16Nat - -// ================================================================================================= - -static void CodePoint_to_UTF16Swp_Surrogate ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ) -{ - size_t unitCount = 0; - UTF32Unit temp; // ! Avoid gcc complaints about declarations after goto's. - - if ( cpIn > 0x10FFFF ) UC_Throw ( "Bad UTF-32 - out of range", kXMPErr_BadParam ); - if ( utf16Len < 2 ) goto Done; // Not enough room for the output. - - unitCount = 2; - temp = cpIn - 0x10000; - UTF16OutSwap ( &utf16Out[0], (0xD800 | UTF16Unit ( temp >> 10 )) ); - UTF16OutSwap ( &utf16Out[1], (0xDC00 | UTF16Unit ( temp & 0x3FF)) ); - -Done: - *utf16Written = unitCount; - return; - -} // CodePoint_to_UTF16Swp_Surrogate - -// ================================================================================================= - -static void CodePoint_to_UTF16Swp ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ) -{ - size_t unitCount = 0; - - UC_Assert ( (utf16Out != 0) && (utf16Written != 0) ); - if ( utf16Len == 0 ) goto Done; - if ( cpIn >= 0xD800 ) goto CheckSurrogate; // ! Force linear execution path for the BMP. - -InBMP: - unitCount = 1; - UTF16OutSwap ( utf16Out, UTF16Unit(cpIn) ); - -Done: - *utf16Written = unitCount; - return; - -CheckSurrogate: - if ( cpIn > 0xFFFF ) goto SurrogatePair; - if ( cpIn > 0xDFFF ) goto InBMP; - UC_Throw ( "Bad UTF-32 - surrogate code point", kXMPErr_BadParam ); - -SurrogatePair: - CodePoint_to_UTF16Swp_Surrogate ( cpIn, utf16Out, utf16Len, utf16Written ); - return; - -} // CodePoint_to_UTF16Swp - -// ================================================================================================= - -static void CodePoint_from_UTF16Swp_Surrogate ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ) -{ - UTF16Unit hiUnit = UTF16InSwap(utf16In); - size_t unitCount = 0; - UTF16Unit loUnit; // ! Avoid gcc complaints about declarations after goto's. - UTF32Unit cp; - - // ---------------------------------- - // We've got a UTF-16 surrogate pair. - - if ( hiUnit > 0xDBFF ) UC_Throw ( "Bad UTF-16 - leading low surrogate", kXMPErr_BadParam ); - if ( utf16Len < 2 ) goto Done; // Not enough input in this buffer. - - loUnit = UTF16InSwap(utf16In+1); - if ( (loUnit < 0xDC00) || (0xDFFF < loUnit) ) UC_Throw ( "Bad UTF-16 - missing low surrogate", kXMPErr_BadParam ); - - unitCount = 2; - cp = (((hiUnit & 0x3FF) << 10) | (loUnit & 0x3FF)) + 0x10000; - - *cpOut = cp; // ! Don't put after Done, don't write if no input. - -Done: - *utf16Read = unitCount; - return; - -} // CodePoint_from_UTF16Swp_Surrogate - -// ================================================================================================= - -static void CodePoint_from_UTF16Swp ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ) -{ - UTF16Unit inUnit; // ! Don't read until we know there is input. - size_t unitCount = 0; - - UC_Assert ( (utf16In != 0) && (cpOut != 0) && (utf16Read != 0) ); - if ( utf16Len == 0 ) goto Done; - inUnit = UTF16InSwap(utf16In); - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) goto SurrogatePair; // ! Force linear execution path for the BMP. - - unitCount = 1; - *cpOut = inUnit; // ! Don't put after Done, don't write if no input. - -Done: - *utf16Read = unitCount; - return; - -SurrogatePair: - CodePoint_from_UTF16Swp_Surrogate ( utf16In, utf16Len, cpOut, utf16Read ); - return; - -} // CodePoint_from_UTF16Swp - -// ================================================================================================= - -static void UTF8_to_UTF16Swp ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf8Read, size_t * utf16Written ) -{ - const UTF8Unit * utf8Pos = utf8In; - UTF16Unit * utf16Pos = utf16Out; - - size_t utf8Left = utf8Len; - size_t utf16Left = utf16Len; - - UC_Assert ( (utf8In != 0) && (utf16Out != 0) && (utf8Read != 0) && (utf16Written != 0) ); - - while ( (utf8Left > 0) && (utf16Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf8Left; - if ( limit > utf16Left ) limit = utf16Left; - for ( i = 0; i < limit; ++i ) { - UTF8Unit inUnit = *utf8Pos; - if ( inUnit > 0x7F ) break; - *utf16Pos = UTF16Unit(inUnit) << 8; // Better than: UTF16OutSwap ( utf16Pos, inUnit ); - ++utf8Pos; - ++utf16Pos; - } - utf8Left -= i; - utf16Left -= i; - - // Do a run of non-ASCII, it copies multiple input units into 1 or 2 output units. - while ( (utf8Left > 0) && (utf16Left > 0) ) { - UTF32Unit cp; - size_t len8, len16; - UTF8Unit inUnit = *utf8Pos; - if ( inUnit <= 0x7F ) break; - CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, &cp, &len8 ); - if ( len8 == 0 ) goto Done; // The input buffer ends in the middle of a character. - if ( cp <= 0xFFFF ) { - UTF16OutSwap ( utf16Pos, UTF16Unit(cp) ); - len16 = 1; - } else { - CodePoint_to_UTF16Swp_Surrogate ( cp, utf16Pos, utf16Left, &len16 ); - if ( len16 == 0 ) goto Done; // Not enough room in the output buffer. - } - utf8Left -= len8; - utf8Pos += len8; - utf16Left -= len16; - utf16Pos += len16; - } - - } - -Done: // Set the output lengths. - *utf8Read = utf8Len - utf8Left; - *utf16Written = utf16Len - utf16Left; - -} // UTF8_to_UTF16Swp - -// ================================================================================================= - -static void UTF8_to_UTF32Swp ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf8Read, size_t * utf32Written ) -{ - const UTF8Unit * utf8Pos = utf8In; - UTF32Unit * utf32Pos = utf32Out; - - size_t utf8Left = utf8Len; - size_t utf32Left = utf32Len; - - UC_Assert ( (utf8In != 0) && (utf32Out != 0) && (utf8Read != 0) && (utf32Written != 0) ); - - while ( (utf8Left > 0) && (utf32Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf8Left; - if ( limit > utf32Left ) limit = utf32Left; - for ( i = 0; i < limit; ++i ) { - UTF8Unit inUnit = *utf8Pos; - if ( inUnit > 0x7F ) break; - *utf32Pos = UTF32Unit(inUnit) << 24; // Better than: UTF32OutSwap ( utf32Pos, inUnit ); - ++utf8Pos; - ++utf32Pos; - } - utf8Left -= i; - utf32Left -= i; - - // Do a run of non-ASCII, it copies variable input into 1 output unit. - while ( (utf8Left > 0) && (utf32Left > 0) ) { - size_t len; - UTF32Unit cp; - UTF8Unit inUnit = *utf8Pos; - if ( inUnit <= 0x7F ) break; - CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, &cp, &len ); - if ( len == 0 ) goto Done; // The input buffer ends in the middle of a character. - UTF32OutSwap ( utf32Pos, cp ); - utf8Left -= len; - utf8Pos += len; - utf32Left -= 1; - utf32Pos += 1; - } - - } - -Done: // Set the output lengths. - *utf8Read = utf8Len - utf8Left; - *utf32Written = utf32Len - utf32Left; - -} // UTF8_to_UTF32Swp - -// ================================================================================================= - -static void UTF16Swp_to_UTF8 ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf16Read, size_t * utf8Written ) -{ - const UTF16Unit * utf16Pos = utf16In; - UTF8Unit * utf8Pos = utf8Out; - - size_t utf16Left = utf16Len; - size_t utf8Left = utf8Len; - - UC_Assert ( (utf16In != 0) && (utf8Out != 0) && (utf16Read != 0) && (utf8Written != 0) ); - - while ( (utf16Left > 0) && (utf8Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf16Left; - if ( limit > utf8Left ) limit = utf8Left; - for ( i = 0; i < limit; ++i ) { - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( inUnit > 0x7F ) break; - *utf8Pos = UTF8Unit(inUnit); - ++utf16Pos; - ++utf8Pos; - } - utf16Left -= i; - utf8Left -= i; - - // Do a run of non-ASCII inside the BMP, it copies 1 input unit into multiple output units. - while ( (utf16Left > 0) && (utf8Left > 0) ) { - size_t len8; - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( inUnit <= 0x7F ) break; - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break; - CodePoint_to_UTF8_Multi ( inUnit, utf8Pos, utf8Left, &len8 ); - if ( len8 == 0 ) goto Done; // Not enough room in the output buffer. - utf16Left -= 1; - utf16Pos += 1; - utf8Left -= len8; - utf8Pos += len8; - } - - // Do a run of surrogate pairs, it copies 2 input units into multiple output units. - while ( (utf16Left > 0) && (utf8Left > 0) ) { - UTF32Unit cp; - size_t len16, len8; - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break; - CodePoint_from_UTF16Swp_Surrogate ( utf16Pos, utf16Left, &cp, &len16 ); - if ( len16 == 0 ) goto Done; // The input buffer ends in the middle of a surrogate pair. - UC_Assert ( len16 == 2 ); - CodePoint_to_UTF8_Multi ( cp, utf8Pos, utf8Left, &len8 ); - if ( len8 == 0 ) goto Done; // Not enough room in the output buffer. - utf16Left -= len16; - utf16Pos += len16; - utf8Left -= len8; - utf8Pos += len8; - } - - } - -Done: // Set the output lengths. - *utf16Read = utf16Len - utf16Left; - *utf8Written = utf8Len - utf8Left; - -} // UTF16Swp_to_UTF8 - -// ================================================================================================= - -static void UTF32Swp_to_UTF8 ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf32Read, size_t * utf8Written ) -{ - const UTF32Unit * utf32Pos = utf32In; - UTF8Unit * utf8Pos = utf8Out; - - size_t utf32Left = utf32Len; - size_t utf8Left = utf8Len; - - UC_Assert ( (utf32In != 0) && (utf8Out != 0) && (utf32Read != 0) && (utf8Written != 0) ); - - while ( (utf32Left > 0) && (utf8Left > 0) ) { - - // Do a run of ASCII, it copies 1 input unit into 1 output unit. - size_t i, limit = utf32Left; - if ( limit > utf8Left ) limit = utf8Left; - for ( i = 0; i < limit; ++i ) { - UTF32Unit cp = UTF32InSwap(utf32Pos); - if ( cp > 0x7F ) break; - *utf8Pos = UTF8Unit(cp); - ++utf32Pos; - ++utf8Pos; - } - utf32Left -= i; - utf8Left -= i; - - // Do a run of non-ASCII, it copies 1 input unit into multiple output units. - while ( (utf32Left > 0) && (utf8Left > 0) ) { - size_t len; - UTF32Unit cp = UTF32InSwap(utf32Pos); - if ( cp <= 0x7F ) break; - CodePoint_to_UTF8_Multi ( cp, utf8Pos, utf8Left, &len ); - if ( len == 0 ) goto Done; // Not enough room in the output buffer. - utf32Left -= 1; - utf32Pos += 1; - utf8Left -= len; - utf8Pos += len; - } - - } - -Done: // Set the output lengths. - *utf32Read = utf32Len - utf32Left; - *utf8Written = utf8Len - utf8Left; - -} // UTF32Swp_to_UTF8 - -// ================================================================================================= - -static void UTF16Swp_to_UTF32Swp ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ) -{ - const UTF16Unit * utf16Pos = utf16In; - UTF32Unit * utf32Pos = utf32Out; - - size_t utf16Left = utf16Len; - size_t utf32Left = utf32Len; - - UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) ); - - while ( (utf16Left > 0) && (utf32Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf16Left; - if ( limit > utf32Left ) limit = utf32Left; - for ( i = 0; i < limit; ++i ) { - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break; - *utf32Pos = UTF32Unit(*utf16Pos) << 16; // Better than: UTF32OutSwap ( utf32Pos, inUnit ); - ++utf16Pos; - ++utf32Pos; - } - utf16Left -= i; - utf32Left -= i; - - // Do a run of surrogate pairs, it copies 2 input units into 1 output unit. - while ( (utf16Left > 0) && (utf32Left > 0) ) { - size_t len; - UTF32Unit cp; - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break; - CodePoint_from_UTF16Swp_Surrogate ( utf16Pos, utf16Left, &cp, &len ); - if ( len == 0 ) goto Done; // The input buffer ends in the middle of a surrogate pair. - UTF32OutSwap ( utf32Pos, cp ); - UC_Assert ( len == 2 ); - utf16Left -= len; - utf16Pos += len; - utf32Left -= 1; - utf32Pos += 1; - } - - } - -Done: // Set the output lengths. - *utf16Read = utf16Len - utf16Left; - *utf32Written = utf32Len - utf32Left; - -} // UTF16Swp_to_UTF32Swp - -// ================================================================================================= - -static void UTF32Swp_to_UTF16Swp ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ) -{ - const UTF32Unit * utf32Pos = utf32In; - UTF16Unit * utf16Pos = utf16Out; - - size_t utf32Left = utf32Len; - size_t utf16Left = utf16Len; - - const size_t k32to16Offset = swap32to16Offset; // ! Make sure compiler treats as an invariant. - - UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) ); - - while ( (utf32Left > 0) && (utf16Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf32Left; - if ( limit > utf16Left ) limit = utf16Left; - for ( i = 0; i < limit; ++i ) { - UTF32Unit inUnit = UTF32InSwap(utf32Pos); - if ( inUnit > 0xFFFF ) break; - *utf16Pos = *(((UTF16Unit*)utf32Pos) + k32to16Offset); // Better than: UTF16OutSwap ( utf16Pos, UTF16Unit(inUnit) ); - ++utf32Pos; - ++utf16Pos; - } - utf32Left -= i; - utf16Left -= i; - - // Do a run of non-BMP, it copies 1 input unit into 2 output units. - while ( (utf32Left > 0) && (utf16Left > 0) ) { - size_t len; - UTF32Unit inUnit = UTF32InSwap(utf32Pos); - if ( inUnit <= 0xFFFF ) break; - CodePoint_to_UTF16Swp_Surrogate ( inUnit, utf16Pos, utf16Left, &len ); - if ( len == 0 ) goto Done; // Not enough room in the output buffer. - UC_Assert ( len == 2 ); - utf32Left -= 1; - utf32Pos += 1; - utf16Left -= 2; - utf16Pos += 2; - } - - } - -Done: // Set the output lengths. - *utf32Read = utf32Len - utf32Left; - *utf16Written = utf16Len - utf16Left; - -} // UTF32Swp_to_UTF16Swp - -// ================================================================================================= - -static void UTF16Nat_to_UTF32Swp ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ) -{ - const UTF16Unit * utf16Pos = utf16In; - UTF32Unit * utf32Pos = utf32Out; - - size_t utf16Left = utf16Len; - size_t utf32Left = utf32Len; - - UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) ); - - while ( (utf16Left > 0) && (utf32Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf16Left; - if ( limit > utf32Left ) limit = utf32Left; - for ( i = 0; i < limit; ++i ) { - UTF16Unit inUnit = *utf16Pos; - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break; - UTF32OutSwap ( utf32Pos, inUnit ); - ++utf16Pos; - ++utf32Pos; - } - utf16Left -= i; - utf32Left -= i; - - // Do a run of surrogate pairs, it copies 2 input units into 1 output unit. - while ( (utf16Left > 0) && (utf32Left > 0) ) { - size_t len; - UTF32Unit cp; - UTF16Unit inUnit = *utf16Pos; - if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break; - CodePoint_from_UTF16Nat_Surrogate ( utf16Pos, utf16Left, &cp, &len ); - if ( len == 0 ) goto Done; // The input buffer ends in the middle of a surrogate pair. - UC_Assert ( len == 2 ); - UTF32OutSwap ( utf32Pos, cp ); - utf16Left -= len; - utf16Pos += len; - utf32Left -= 1; - utf32Pos += 1; - } - - } - -Done: // Set the output lengths. - *utf16Read = utf16Len - utf16Left; - *utf32Written = utf32Len - utf32Left; - -} // UTF16Nat_to_UTF32Swp - -// ================================================================================================= - -static void UTF16Swp_to_UTF32Nat ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ) -{ - const UTF16Unit * utf16Pos = utf16In; - UTF32Unit * utf32Pos = utf32Out; - - size_t utf16Left = utf16Len; - size_t utf32Left = utf32Len; - - UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) ); - - while ( (utf16Left > 0) && (utf32Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf16Left; - if ( limit > utf32Left ) limit = utf32Left; - for ( i = 0; i < limit; ++i ) { - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break; - *utf32Pos = inUnit; - ++utf16Pos; - ++utf32Pos; - } - utf16Left -= i; - utf32Left -= i; - - // Do a run of surrogate pairs, it copies 2 input units into 1 output unit. - while ( (utf16Left > 0) && (utf32Left > 0) ) { - size_t len; - UTF16Unit inUnit = UTF16InSwap(utf16Pos); - if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break; - CodePoint_from_UTF16Swp_Surrogate ( utf16Pos, utf16Left, utf32Pos, &len ); - if ( len == 0 ) goto Done; // The input buffer ends in the middle of a surrogate pair. - UC_Assert ( len == 2 ); - utf16Left -= len; - utf16Pos += len; - utf32Left -= 1; - utf32Pos += 1; - } - - } - -Done: // Set the output lengths. - *utf16Read = utf16Len - utf16Left; - *utf32Written = utf32Len - utf32Left; - -} // UTF16Swp_to_UTF32Nat - -// ================================================================================================= - -static void UTF32Nat_to_UTF16Swp ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ) -{ - const UTF32Unit * utf32Pos = utf32In; - UTF16Unit * utf16Pos = utf16Out; - - size_t utf32Left = utf32Len; - size_t utf16Left = utf16Len; - - UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) ); - - while ( (utf32Left > 0) && (utf16Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf32Left; - if ( limit > utf16Left ) limit = utf16Left; - for ( i = 0; i < limit; ++i ) { - UTF32Unit inUnit = *utf32Pos; - if ( inUnit > 0xFFFF ) break; - UTF16OutSwap ( utf16Pos, UTF16Unit(inUnit) ); - ++utf32Pos; - ++utf16Pos; - } - utf32Left -= i; - utf16Left -= i; - - // Do a run of non-BMP, it copies 1 input unit into 2 output units. - while ( (utf32Left > 0) && (utf16Left > 0) ) { - size_t len; - UTF32Unit inUnit = *utf32Pos; - if ( inUnit <= 0xFFFF ) break; - CodePoint_to_UTF16Swp_Surrogate ( inUnit, utf16Pos, utf16Left, &len ); - if ( len == 0 ) goto Done; // Not enough room in the output buffer. - UC_Assert ( len == 2 ); - utf32Left -= 1; - utf32Pos += 1; - utf16Left -= 2; - utf16Pos += 2; - } - - } - -Done: // Set the output lengths. - *utf32Read = utf32Len - utf32Left; - *utf16Written = utf16Len - utf16Left; - -} // UTF32Nat_to_UTF16Swp - -// ================================================================================================= - -static void UTF32Swp_to_UTF16Nat ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ) -{ - const UTF32Unit * utf32Pos = utf32In; - UTF16Unit * utf16Pos = utf16Out; - - size_t utf32Left = utf32Len; - size_t utf16Left = utf16Len; - - UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) ); - - while ( (utf32Left > 0) && (utf16Left > 0) ) { - - // Do a run of BMP, it copies 1 input unit into 1 output unit. - size_t i, limit = utf32Left; - if ( limit > utf16Left ) limit = utf16Left; - for ( i = 0; i < limit; ++i ) { - UTF32Unit inUnit = UTF32InSwap(utf32Pos); - if ( inUnit > 0xFFFF ) break; - *utf16Pos = UTF16Unit(inUnit); - ++utf32Pos; - ++utf16Pos; - } - utf32Left -= i; - utf16Left -= i; - - // Do a run of non-BMP, it copies 1 input unit into 2 output units. - while ( (utf32Left > 0) && (utf16Left > 0) ) { - size_t len; - UTF32Unit inUnit = UTF32InSwap(utf32Pos); - if ( inUnit <= 0xFFFF ) break; - CodePoint_to_UTF16Nat_Surrogate ( inUnit, utf16Pos, utf16Left, &len ); - if ( len == 0 ) goto Done; // Not enough room in the output buffer. - UC_Assert ( len == 2 ); - utf32Left -= 1; - utf32Pos += 1; - utf16Left -= 2; - utf16Pos += 2; - } - - } - -Done: // Set the output lengths. - *utf32Read = utf32Len - utf32Left; - *utf16Written = utf16Len - utf16Left; - -} // UTF32Swp_to_UTF16Nat - -// ================================================================================================= diff --git a/xmpsdk/src/UnicodeConversions.hpp b/xmpsdk/src/UnicodeConversions.hpp deleted file mode 100644 index 08883000bc..0000000000 --- a/xmpsdk/src/UnicodeConversions.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef __UnicodeConversions_h__ -#define __UnicodeConversions_h__ - -// ================================================================================================= -// Copyright 2004-2007 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 - -// ================================================================================================= - -#if UnicodeTestBuild - typedef unsigned char UTF8Unit; - typedef unsigned short UTF16Unit; - typedef unsigned long UTF32Unit; -#else - typedef XMP_Uns8 UTF8Unit; - typedef XMP_Uns16 UTF16Unit; - typedef XMP_Uns32 UTF32Unit; -#endif - -// ------------------------------------------------------------------------------------------------- - -// ! The UTF16 and UTF32 counts are in storage units, not bytes! CodePoint values are always native. - -// *** MIght be better to return a status than throw an exception for errors? - -typedef void (*CodePoint_to_UTF16_Proc) ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written ); - -typedef void (*CodePoint_from_UTF16_Proc) ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read ); - -typedef void (*UTF8_to_UTF16_Proc) ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf8Read, size_t * utf16Written ); - -typedef void (*UTF8_to_UTF32_Proc) ( const UTF8Unit * utf8In, const size_t utf8Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf8Read, size_t * utf32Written ); - -typedef void (*UTF16_to_UTF8_Proc) ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf16Read, size_t * utf8Written ); - -typedef void (*UTF32_to_UTF8_Proc) ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF8Unit * utf8Out, const size_t utf8Len, - size_t * utf32Read, size_t * utf8Written ); - -typedef void (*UTF16_to_UTF32_Proc) ( const UTF16Unit * utf16In, const size_t utf16Len, - UTF32Unit * utf32Out, const size_t utf32Len, - size_t * utf16Read, size_t * utf32Written ); - -typedef void (*UTF32_to_UTF16_Proc) ( const UTF32Unit * utf32In, const size_t utf32Len, - UTF16Unit * utf16Out, const size_t utf16Len, - size_t * utf32Read, size_t * utf16Written ); - -// ------------------------------------------------------------------------------------------------- - -extern void CodePoint_to_UTF8 ( const UTF32Unit cpIn, UTF8Unit * utf8Out, const size_t utf8Len, size_t * utf8Written ); - -extern void CodePoint_from_UTF8 ( const UTF8Unit * utf8In, const size_t utf8Len, UTF32Unit * cpOut, size_t * utf8Read ); - -extern CodePoint_to_UTF16_Proc CodePoint_to_UTF16BE; -extern CodePoint_to_UTF16_Proc CodePoint_to_UTF16LE; - -extern CodePoint_from_UTF16_Proc CodePoint_from_UTF16BE; -extern CodePoint_from_UTF16_Proc CodePoint_from_UTF16LE; - -extern UTF8_to_UTF16_Proc UTF8_to_UTF16BE; -extern UTF8_to_UTF16_Proc UTF8_to_UTF16LE; - -extern UTF8_to_UTF32_Proc UTF8_to_UTF32BE; -extern UTF8_to_UTF32_Proc UTF8_to_UTF32LE; - -extern UTF16_to_UTF8_Proc UTF16BE_to_UTF8; -extern UTF16_to_UTF8_Proc UTF16LE_to_UTF8; - -extern UTF32_to_UTF8_Proc UTF32BE_to_UTF8; -extern UTF32_to_UTF8_Proc UTF32LE_to_UTF8; - -extern UTF8_to_UTF16_Proc UTF8_to_UTF16Native; -extern UTF8_to_UTF32_Proc UTF8_to_UTF32Native; - -extern UTF16_to_UTF8_Proc UTF16Native_to_UTF8; -extern UTF32_to_UTF8_Proc UTF32Native_to_UTF8; - -extern UTF16_to_UTF32_Proc UTF16BE_to_UTF32BE; -extern UTF16_to_UTF32_Proc UTF16BE_to_UTF32LE; - -extern UTF16_to_UTF32_Proc UTF16LE_to_UTF32BE; -extern UTF16_to_UTF32_Proc UTF16LE_to_UTF32LE; - -extern UTF32_to_UTF16_Proc UTF32BE_to_UTF16BE; -extern UTF32_to_UTF16_Proc UTF32BE_to_UTF16LE; - -extern UTF32_to_UTF16_Proc UTF32LE_to_UTF16BE; -extern UTF32_to_UTF16_Proc UTF32LE_to_UTF16LE; - -extern void SwapUTF16 ( const UTF16Unit * utf16In, UTF16Unit * utf16Out, const size_t utf16Len ); -extern void SwapUTF32 ( const UTF32Unit * utf32In, UTF32Unit * utf32Out, const size_t utf32Len ); - -extern void ToUTF16 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str, bool bigEndian ); -extern void ToUTF32 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str, bool bigEndian ); - -extern void FromUTF16 ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str, bool bigEndian ); -extern void FromUTF32 ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str, bool bigEndian ); - -extern void ToUTF16Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str ); -extern void ToUTF32Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str ); - -extern void FromUTF16Native ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str ); -extern void FromUTF32Native ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str ); - -extern void InitializeUnicodeConversions(); - -// ================================================================================================= - -#endif // __UnicodeConversions_h__ diff --git a/xmpsdk/src/UnicodeInlines.incl_cpp b/xmpsdk/src/UnicodeInlines.incl_cpp deleted file mode 100644 index 8d55bad319..0000000000 --- a/xmpsdk/src/UnicodeInlines.incl_cpp +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef __UnicodeInlines_incl_cpp__ -#define __UnicodeInlines_incl_cpp__ - -// ================================================================================================= -// Copyright 2002-2007 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 "UnicodeConversions.hpp" - -// ================================================================================================= -// Inner loop utilities that need to be inlined. -// ================================================================================================= - -static inline XMP_Uns32 GetCodePoint ( const XMP_Uns8 ** utf8Str_io ) -{ - const XMP_Uns8 * u8Ptr = *utf8Str_io; - XMP_Uns32 cp; - size_t u8Len; - CodePoint_from_UTF8 ( u8Ptr, 4, &cp, &u8Len ); // Throws an exception for errors. - *utf8Str_io = u8Ptr + u8Len; - return cp; -} - -// ================================================================================================= - -static inline bool IsStartChar_ASCII ( XMP_Uns32 cp ) -{ - // ASCII starting characters for an XML name. - if ( (('a' <= cp) && (cp <= 'z')) || (('A' <= cp) && (cp <= 'Z')) || (cp == '_') ) return true; - return false; -} - -// ------------------------------------------------------------------------------------------------- - -static inline bool IsStartChar_NonASCII ( XMP_Uns32 cp ) -{ - // Non-ASCII starting characters for an XML name. - - if ( ((0xC0 <= cp) && (cp <= 0xD6)) || ((0xD8 <= cp) && (cp <= 0xF6)) ) return true; - if ( ((0xF8 <= cp) && (cp <= 0x2FF)) || ((0x370 <= cp) && (cp <= 0x37D)) ) return true; - - if ( ((0x37F <= cp) && (cp <= 0x1FFF)) || ((0x200C <= cp) && (cp <= 0x200D)) ) return true; - if ( ((0x2070 <= cp) && (cp <= 0x218F)) || ((0x2C00 <= cp) && (cp <= 0x2FEF)) ) return true; - if ( ((0x3001 <= cp) && (cp <= 0xD7FF)) || ((0xF900 <= cp) && (cp <= 0xFDCF)) ) return true; - if ( ((0xFDF0 <= cp) && (cp <= 0xFFFD)) || ((0x10000 <= cp) && (cp <= 0xEFFFF)) ) return true; - - return false; - -} - -// ------------------------------------------------------------------------------------------------- - -static inline bool IsOtherChar_ASCII ( XMP_Uns32 cp ) -{ - // ASCII following characters for an XML name. - if ( (('0' <= cp) && (cp <= '9')) || (cp == '-') || (cp == '.') ) return true; - return false; -} - -// ------------------------------------------------------------------------------------------------- - -static inline bool IsOtherChar_NonASCII ( XMP_Uns32 cp ) -{ - // Non-ASCII following characters for an XML name. - if ( (cp == 0xB7) || ((0x300 <= cp) && (cp <= 0x36F)) || ((0x203F <= cp) && (cp <= 0x2040)) ) return true; - return false; -} - -// ------------------------------------------------------------------------------------------------- - -static inline void VerifyUTF8 ( XMP_StringPtr str ) -{ - const XMP_Uns8 * utf8Str = (XMP_Uns8*)str; - while ( *utf8Str != 0 ) { - while ( (*utf8Str != 0) && (*utf8Str < 0x80) ) ++utf8Str; - if ( *utf8Str >= 0x80 ) (void) GetCodePoint ( &utf8Str ); // Throws for bad UTF-8. - } -} - -// ------------------------------------------------------------------------------------------------- - -static inline void VerifySimpleXMLName ( XMP_StringPtr _nameStart, XMP_StringPtr _nameEnd ) -{ - - const XMP_Uns8 * nameStart = (const XMP_Uns8 *) _nameStart; - const XMP_Uns8 * nameEnd = (const XMP_Uns8 *) _nameEnd; - const XMP_Uns8 * namePos = nameStart; - XMP_Uns32 cp; - - // The first character is more restricted. - - if ( nameStart >= nameEnd ) XMP_Throw ( "Empty XML name", kXMPErr_BadXPath ); - - cp = *namePos; - if ( cp < 0x80 ) { - ++namePos; - if ( ! IsStartChar_ASCII(cp) ) goto NameError; - } else { - cp = GetCodePoint ( &namePos ); - if ( ! IsStartChar_NonASCII(cp) ) goto NameError; - } - - // Check the rest of the name. - - while ( namePos < nameEnd ) { - cp = *namePos; - if ( cp < 0x80 ) { - ++namePos; - if ( (! IsStartChar_ASCII(cp)) && (! IsOtherChar_ASCII(cp)) ) goto NameError; - } else { - cp = GetCodePoint ( &namePos ); - if ( (! IsStartChar_NonASCII(cp)) && (! IsOtherChar_NonASCII(cp)) ) goto NameError; - } - } - - return; - -NameError: - XMP_Throw ( "Bad XML name", kXMPErr_BadXPath ); - -} // VerifySimpleXMLName - -// ================================================================================================= - -#endif // __UnicodeInlines_incl_cpp__ diff --git a/xmpsdk/src/WXMPIterator.cpp b/xmpsdk/src/WXMPIterator.cpp deleted file mode 100644 index 4c47b0d31e..0000000000 --- a/xmpsdk/src/WXMPIterator.cpp +++ /dev/null @@ -1,188 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2007 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPIterator.hpp" -#include "client-glue/WXMPIterator.hpp" - -#if XMP_WinBuild -# ifdef _MSC_VER - #pragma warning ( disable : 4101 ) // unreferenced local variable - #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) - #if XMP_DebugBuild - #pragma warning ( disable : 4297 ) // function assumed not to throw an exception but does -# endif -# endif -#endif - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= -// CTor/DTor Wrappers -// ================== - -void -WXMPIterator_PropCTor_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPIterator_PropCTor_1" ) - - if ( schemaNS == 0 ) schemaNS = ""; - if ( propName == 0 ) propName = ""; - - const XMPMeta & xmpObj = WtoXMPMeta_Ref ( xmpRef ); - XMPIterator * iter = new XMPIterator ( xmpObj, schemaNS, propName, options ); - ++iter->clientRefs; - XMP_Assert ( iter->clientRefs == 1 ); - wResult->ptrResult = XMPIteratorRef ( iter ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPIterator_TableCTor_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPIterator_TableCTor_1" ) - - if ( schemaNS == 0 ) schemaNS = ""; - if ( propName == 0 ) propName = ""; - - XMPIterator * iter = new XMPIterator ( schemaNS, propName, options ); - ++iter->clientRefs; - XMP_Assert ( iter->clientRefs == 1 ); - wResult->ptrResult = XMPIteratorRef ( iter ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPIterator_IncrementRefCount_1 ( XMPIteratorRef iterRef ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER ( "WXMPIterator_IncrementRefCount_1" ) - - XMPIterator * thiz = (XMPIterator*)iterRef; - - ++thiz->clientRefs; - XMP_Assert ( thiz->clientRefs > 1 ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPIterator_DecrementRefCount_1 ( XMPIteratorRef iterRef ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER ( "WXMPIterator_DecrementRefCount_1" ) - - XMPIterator * thiz = (XMPIterator*)iterRef; - - XMP_Assert ( thiz->clientRefs > 0 ); - --thiz->clientRefs; - if ( thiz->clientRefs <= 0 ) delete ( thiz ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPIterator_Unlock_1 ( XMP_OptionBits options ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPIterator_Unlock_1" ) - - XMPIterator::Unlock ( options ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ================================================================================================= -// Class Method Wrappers -// ===================== - -void -WXMPIterator_Next_1 ( XMPIteratorRef iterRef, - XMP_StringPtr * schemaNS, - XMP_StringLen * nsSize, - XMP_StringPtr * propPath, - XMP_StringLen * pathSize, - XMP_StringPtr * propValue, - XMP_StringLen * valueSize, - XMP_OptionBits * propOptions, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPIterator_Next_1" ) - - if ( schemaNS == 0 ) schemaNS = &voidStringPtr; - if ( nsSize == 0 ) nsSize = &voidStringLen; - if ( propPath == 0 ) propPath = &voidStringPtr; - if ( pathSize == 0 ) pathSize = &voidStringLen; - if ( propValue == 0 ) propValue = &voidStringPtr; - if ( valueSize == 0 ) valueSize = &voidStringLen; - if ( propOptions == 0 ) propOptions = &voidOptionBits; - - XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef ); - XMP_Bool found = iter->Next ( schemaNS, nsSize, propPath, pathSize, propValue, valueSize, propOptions ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPIterator_Skip_1 ( XMPIteratorRef iterRef, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPIterator_Skip_1" ) - - XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef ); - iter->Skip ( options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_UnlockIter_1 ( XMPIteratorRef iterRef, - XMP_OptionBits options ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_UnlockIter_1" ) - - XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef ); - iter->UnlockIter ( options ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif diff --git a/xmpsdk/src/WXMPMeta.cpp b/xmpsdk/src/WXMPMeta.cpp deleted file mode 100644 index 7969233885..0000000000 --- a/xmpsdk/src/WXMPMeta.cpp +++ /dev/null @@ -1,1310 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPMeta.hpp" -#include "client-glue/WXMPMeta.hpp" - -#if XMP_WinBuild - #ifdef _MSC_VER - #pragma warning ( disable : 4101 ) // unreferenced local variable - #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced - #pragma warning ( disable : 4702 ) // unreachable code - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) - #if XMP_DebugBuild - #pragma warning ( disable : 4297 ) // function assumed not to throw an exception but does - #endif - #endif -#endif - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= -// Init/Term Wrappers -// ================== - -/* class static */ void -WXMPMeta_GetVersionInfo_1 ( XMP_VersionInfo * info ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_GetVersionInfo_1" ) - - XMPMeta::GetVersionInfo ( info ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_Initialize_1 ( WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Initialize_1" ) - - bool ok = XMPMeta::Initialize(); - wResult->int32Result = ok; - - XMP_EXIT_WRAPPER -} -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_Terminate_1() -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Terminate_1" ) - - XMPMeta::Terminate(); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ================================================================================================= -// CTor/DTor Wrappers -// ================== - -void -WXMPMeta_CTor_1 ( WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_CTor_1" ) - - XMPMeta * xmpObj = new XMPMeta(); - ++xmpObj->clientRefs; - XMP_Assert ( xmpObj->clientRefs == 1 ); - wResult->ptrResult = XMPMetaRef ( xmpObj ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_IncrementRefCount_1 ( XMPMetaRef xmpRef ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER ( "WXMPMeta_IncrementRefCount_1" ) - - XMPMeta * thiz = (XMPMeta*)xmpRef; - - ++thiz->clientRefs; - XMP_Assert ( thiz->clientRefs > 0 ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DecrementRefCount_1 ( XMPMetaRef xmpRef ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER ( "WXMPMeta_DecrementRefCount_1" ) - - XMPMeta * thiz = (XMPMeta*)xmpRef; - - XMP_Assert ( thiz->clientRefs > 0 ); - --thiz->clientRefs; - if ( thiz->clientRefs <= 0 ) delete ( thiz ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ================================================================================================= -// Class Static Wrappers -// ===================== -// -// These are DLL-entry wrappers for class-static functions. They all follow a simple pattern: -// -// try -// acquire toolbox lock -// validate parameters -// call through to the implementation -// retain toolbox lock if necessary -// catch anything and return an appropriate XMP_Error object -// return null (no error if we get to here) -// -// The toolbox lock is acquired through a local wrapper object that automatically unlocks when the -// try-block is exited. The lock must be retained if the function is returning a string result. The -// output string is owned by the toolkit, the client must copy the string then release the lock. -// The lock used here is the overall toolkit lock. For simplicity at this time the lock is a simple -// mutual exclusion lock, we do not allow multiple concurrent readers. -// -// The one exception to this model is UnlockToolkit. It does not acquire the toolkit lock since this -// is the function the client calls to release the lock after copying an output string! -// -// ================================================================================================= - -/* class static */ void -WXMPMeta_GetGlobalOptions_1 ( WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetGlobalOptions_1" ) - - XMP_OptionBits options = XMPMeta::GetGlobalOptions(); - wResult->int32Result = options; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_SetGlobalOptions_1 ( XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetGlobalOptions_1" ) - - XMPMeta::SetGlobalOptions ( options ); - - XMP_EXIT_WRAPPER -} -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_DumpNamespaces_1 ( XMP_TextOutputProc outProc, - void * refCon, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DumpNamespaces_1" ) - - if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam ); - - XMP_Status status = XMPMeta::DumpNamespaces ( outProc, refCon ); - wResult->int32Result = status; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_DumpAliases_1 ( XMP_TextOutputProc outProc, - void * refCon, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DumpAliases_1" ) - - if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam ); - - XMP_Status status = XMPMeta::DumpAliases ( outProc, refCon ); - wResult->int32Result = status; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_Unlock_1 ( XMP_OptionBits options ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Unlock_1" ) - - XMPMeta::Unlock ( options ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_RegisterNamespace_1 ( XMP_StringPtr namespaceURI, - XMP_StringPtr prefix, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterNamespace_1" ) - - if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema ); - if ( (prefix == 0) || (*prefix == 0) ) XMP_Throw ( "Empty prefix", kXMPErr_BadSchema ); - - XMPMeta::RegisterNamespace ( namespaceURI, prefix ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_GetNamespacePrefix_1 ( XMP_StringPtr namespaceURI, - XMP_StringPtr * namespacePrefix, - XMP_StringLen * prefixSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetNamespacePrefix_1" ) - - if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema ); - - if ( namespacePrefix == 0 ) namespacePrefix = &voidStringPtr; - if ( prefixSize == 0 ) prefixSize = &voidStringLen; - - bool found = XMPMeta::GetNamespacePrefix ( namespaceURI, namespacePrefix, prefixSize ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr namespacePrefix, - XMP_StringPtr * namespaceURI, - XMP_StringLen * uriSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetNamespaceURI_1" ) - - if ( (namespacePrefix == 0) || (*namespacePrefix == 0) ) XMP_Throw ( "Empty namespace prefix", kXMPErr_BadSchema ); - - if ( namespaceURI == 0 ) namespaceURI = &voidStringPtr; - if ( uriSize == 0 ) uriSize = &voidStringLen; - - bool found = XMPMeta::GetNamespaceURI ( namespacePrefix, namespaceURI, uriSize ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_DeleteNamespace_1 ( XMP_StringPtr namespaceURI, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteNamespace_1" ) - - if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema ); - - XMPMeta::DeleteNamespace ( namespaceURI ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_RegisterAlias_1 ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr actualNS, - XMP_StringPtr actualProp, - XMP_OptionBits arrayForm, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterAlias_1" ) - - if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema ); - if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath ); - if ( (actualNS == 0) || (*actualNS == 0) ) XMP_Throw ( "Empty actual namespace URI", kXMPErr_BadSchema ); - if ( (actualProp == 0) || (*actualProp == 0) ) XMP_Throw ( "Empty actual property name", kXMPErr_BadXPath ); - - XMPMeta::RegisterAlias ( aliasNS, aliasProp, actualNS, actualProp, arrayForm ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_ResolveAlias_1 ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr * actualNS, - XMP_StringLen * nsSize, - XMP_StringPtr * actualProp, - XMP_StringLen * propSize, - XMP_OptionBits * arrayForm, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_ResolveAlias_1" ) - - if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema ); - if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath ); - - if ( actualNS == 0 ) actualNS = &voidStringPtr; - if ( nsSize == 0 ) nsSize = &voidStringLen; - if ( actualProp == 0 ) actualProp = &voidStringPtr; - if ( propSize == 0 ) propSize = &voidStringLen; - if ( arrayForm == 0 ) arrayForm = &voidOptionBits; - - bool found = XMPMeta::ResolveAlias ( aliasNS, aliasProp, actualNS, nsSize, actualProp, propSize, arrayForm ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_DeleteAlias_1 ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteAlias_1" ) - - if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema ); - if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath ); - - XMPMeta::DeleteAlias ( aliasNS, aliasProp ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -/* class static */ void -WXMPMeta_RegisterStandardAliases_1 ( XMP_StringPtr schemaNS, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterStandardAliases_1" ) - - if ( schemaNS == 0 ) schemaNS = ""; - - XMPMeta::RegisterStandardAliases ( schemaNS ); - - XMP_EXIT_WRAPPER -} - -// ================================================================================================= -// Class Method Wrappers -// ===================== -// -// These are DLL-entry wrappers for the methods. They all follow a simple pattern: -// -// validate parameters -// try -// acquire object lock -// call through to the implementation -// retain object lock if necessary -// catch anything and return an appropriate XMP_Error object -// return null (no error if we get to here) -// -// The object lock is acquired through a local wrapper object that automatically unlocks when the -// try-block is exited. The lock must be retained if the function is returning a string result. The -// output string is owned by the object, the client must copy the string then release the lock. The -// lock used here is the per-object lock. For simplicity at this time the lock is a simple mutual -// exclusion lock, we do not allow multiple concurrent readers. -// -// The one exception to this model is UnlockObject. It does not acquire the object lock since this -// is the function the client calls to release the lock after copying an output string! -// -// ================================================================================================= - -void -WXMPMeta_GetProperty_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr * propValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - if ( propValue == 0 ) propValue = &voidStringPtr; - if ( valueSize == 0 ) valueSize = &voidStringLen; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetProperty ( schemaNS, propName, propValue, valueSize, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * itemValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetArrayItem_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - if ( itemValue == 0 ) itemValue = &voidStringPtr; - if ( valueSize == 0 ) valueSize = &voidStringLen; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, valueSize, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetStructField_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fieldValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetStructField_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath ); - if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema ); - if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath ); - - if ( fieldValue == 0 ) fieldValue = &voidStringPtr; - if ( valueSize == 0 ) valueSize = &voidStringLen; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, valueSize, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetQualifier_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * qualValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetQualifier_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema ); - if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath ); - - if ( qualValue == 0 ) qualValue = &voidStringPtr; - if ( valueSize == 0 ) valueSize = &voidStringLen; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, valueSize, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetProperty_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr propValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetProperty ( schemaNS, propName, propValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr itemValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetArrayItem_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_AppendArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - XMP_StringPtr itemValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_AppendArrayItem_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->AppendArrayItem ( schemaNS, arrayName, arrayOptions, itemValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetStructField_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetStructField_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath ); - if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema ); - if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetQualifier_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr qualValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetQualifier_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema ); - if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DeleteProperty_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteProperty_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->DeleteProperty ( schemaNS, propName ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DeleteArrayItem_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteArrayItem_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->DeleteArrayItem ( schemaNS, arrayName, itemIndex ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DeleteStructField_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteStructField_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath ); - if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema ); - if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->DeleteStructField ( schemaNS, structName, fieldNS, fieldName ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DeleteQualifier_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteQualifier_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema ); - if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->DeleteQualifier ( schemaNS, propName, qualNS, qualName ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DoesPropertyExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DoesPropertyExist_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.DoesPropertyExist ( schemaNS, propName ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DoesArrayItemExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DoesArrayItemExist_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.DoesArrayItemExist ( schemaNS, arrayName, itemIndex ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DoesStructFieldExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DoesStructFieldExist_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath ); - if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema ); - if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath ); - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.DoesStructFieldExist ( schemaNS, structName, fieldNS, fieldName ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DoesQualifierExist_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DoesQualifierExist_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema ); - if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath ); - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.DoesQualifierExist ( schemaNS, propName, qualNS, qualName ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetLocalizedText_1 ( XMPMetaRef xmpRef, - 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, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetLocalizedText_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - if ( genericLang == 0 ) genericLang = ""; - if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam ); - - if ( actualLang == 0 ) actualLang = &voidStringPtr; - if ( langSize == 0 ) langSize = &voidStringLen; - if ( itemValue == 0 ) itemValue = &voidStringPtr; - if ( valueSize == 0 ) valueSize = &voidStringLen; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetLocalizedText ( schemaNS, arrayName, genericLang, specificLang, - actualLang, langSize, itemValue, valueSize, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER_KEEP_LOCK ( found ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetLocalizedText_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - XMP_StringPtr itemValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetLocalizedText_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - if ( genericLang == 0 ) genericLang = ""; - if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam ); - if ( itemValue == 0 ) itemValue = ""; - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetLocalizedText ( schemaNS, arrayName, genericLang, specificLang, itemValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Bool * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Bool_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - if ( propValue == 0 ) propValue = &voidByte; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool value; - bool found = meta.GetProperty_Bool ( schemaNS, propName, &value, options ); - if ( propValue != 0 ) *propValue = value; - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetProperty_Int_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Int_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - if ( propValue == 0 ) propValue = &voidInt32; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetProperty_Int ( schemaNS, propName, propValue, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Int64_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - if ( propValue == 0 ) propValue = &voidInt64; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetProperty_Int64 ( schemaNS, propName, propValue, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetProperty_Float_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Float_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - if ( propValue == 0 ) propValue = &voidDouble; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetProperty_Float ( schemaNS, propName, propValue, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetProperty_Date_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_DateTime * propValue, - XMP_OptionBits * options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Date_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - if ( propValue == 0 ) propValue = &voidDateTime; - if ( options == 0 ) options = &voidOptionBits; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - bool found = meta.GetProperty_Date ( schemaNS, propName, propValue, options ); - wResult->int32Result = found; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetProperty_Bool_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Bool propValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Bool_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetProperty_Bool ( schemaNS, propName, propValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetProperty_Int_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 propValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Int_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetProperty_Int ( schemaNS, propName, propValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetProperty_Int64_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 propValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Int64_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetProperty_Int64 ( schemaNS, propName, propValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetProperty_Float_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double propValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Float_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetProperty_Float ( schemaNS, propName, propValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetProperty_Date_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const XMP_DateTime & propValue, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Date_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetProperty_Date ( schemaNS, propName, propValue, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_DumpObject_1 ( XMPMetaRef xmpRef, - XMP_TextOutputProc outProc, - void * refCon, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_DumpObject_1" ) - - if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam ); - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - XMP_Status status = meta.DumpObject ( outProc, refCon ); - wResult->int32Result = status; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_Sort_1 ( XMPMetaRef xmpRef, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_Sort_1" ) - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->Sort(); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_Erase_1 ( XMPMetaRef xmpRef, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_Erase_1" ) - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->Erase(); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_Clone_1 ( XMPMetaRef xmpRef, - XMP_OptionBits options, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_Clone_1" ) - - const XMPMeta & xOriginal = WtoXMPMeta_Ref ( xmpRef ); - XMPMeta * xClone = new XMPMeta; - xOriginal.Clone ( xClone, options ); - XMP_Assert ( xClone->clientRefs == 0 ); // ! Gets incremented in TXMPMeta::Clone. - wResult->ptrResult = xClone; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_CountArrayItems_1 ( XMPMetaRef xmpRef, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_CountArrayItems_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - XMP_Index count = meta.CountArrayItems ( schemaNS, arrayName ); - wResult->int32Result = count; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_UnlockObject_1 ( XMPMetaRef xmpRef, - XMP_OptionBits options ) /* const */ -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_UnlockObject_1" ) - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - meta.UnlockObject ( options ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetObjectName_1 ( XMPMetaRef xmpRef, - XMP_StringPtr * namePtr, - XMP_StringLen * nameLen, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetObjectName_1" ) - - if ( namePtr == 0 ) namePtr = &voidStringPtr; - if ( nameLen == 0 ) nameLen = &voidStringLen; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - meta.GetObjectName ( namePtr, nameLen ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned! -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetObjectName_1 ( XMPMetaRef xmpRef, - XMP_StringPtr name, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetObjectName_1" ) - - if ( name == 0 ) name = ""; - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetObjectName ( name ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_GetObjectOptions_1 ( XMPMetaRef xmpRef, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_GetObjectOptions_1" ) - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - XMP_OptionBits options = meta.GetObjectOptions(); - wResult->int32Result = options; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SetObjectOptions_1 ( XMPMetaRef xmpRef, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SetObjectOptions_1" ) - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->SetObjectOptions ( options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_ParseFromBuffer_1 ( XMPMetaRef xmpRef, - XMP_StringPtr buffer, - XMP_StringLen bufferSize, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_ParseFromBuffer_1" ) - - XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef ); - meta->ParseFromBuffer ( buffer, bufferSize, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef xmpRef, - XMP_StringPtr * rdfString, - XMP_StringLen * rdfSize, - XMP_OptionBits options, - XMP_StringLen padding, - XMP_StringPtr newline, - XMP_StringPtr indent, - XMP_Index baseIndent, - WXMP_Result * wResult ) /* const */ -{ - XMP_ENTER_WRAPPER ( "WXMPMeta_SerializeToBuffer_1" ) - - if ( rdfString == 0 ) rdfString = &voidStringPtr; - if ( rdfSize == 0 ) rdfSize = &voidStringLen; - - if ( newline == 0 ) newline = ""; - if ( indent == 0 ) indent = ""; - - const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef ); - meta.SerializeToBuffer ( rdfString, rdfSize, options, padding, newline, indent, baseIndent ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned! -} - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif diff --git a/xmpsdk/src/WXMPUtils.cpp b/xmpsdk/src/WXMPUtils.cpp deleted file mode 100644 index e3ce4375ba..0000000000 --- a/xmpsdk/src/WXMPUtils.cpp +++ /dev/null @@ -1,626 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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. -// ================================================================================================= - -// *** Should change "type * inParam" to "type & inParam" - -#include "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPUtils.hpp" -#include "client-glue/WXMPUtils.hpp" - -#if XMP_WinBuild - #ifdef _MSC_VER - #pragma warning ( disable : 4101 ) // unreferenced local variable - #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) - #if XMP_DebugBuild - #pragma warning ( disable : 4297 ) // function assumed not to throw an exception but does - #endif - #endif -#endif - -#if __cplusplus -extern "C" { -#endif - -// ================================================================================================= -// Class Static Wrappers -// ===================== - -void -WXMPUtils_Unlock_1 ( XMP_OptionBits options ) -{ - WXMP_Result * wResult = &void_wResult; // ! Needed to "fool" the EnterWrapper macro. - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_Unlock_1" ) - - XMPUtils::Unlock ( options ); - - XMP_EXIT_WRAPPER_NO_THROW -} - -// ================================================================================================= - -void -WXMPUtils_ComposeArrayItemPath_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeArrayItemPath_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - if ( fullPath == 0 ) fullPath = &voidStringPtr; - if ( pathSize == 0 ) pathSize = &voidStringLen; - - XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, fullPath, pathSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ComposeStructFieldPath_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeStructFieldPath_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath ); - if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema ); - if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath ); - - if ( fullPath == 0 ) fullPath = &voidStringPtr; - if ( pathSize == 0 ) pathSize = &voidStringLen; - - XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, fullPath, pathSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ComposeQualifierPath_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeQualifierPath_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath ); - if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema ); - if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath ); - - if ( fullPath == 0 ) fullPath = &voidStringPtr; - if ( pathSize == 0 ) pathSize = &voidStringLen; - - XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, fullPath, pathSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ComposeLangSelector_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr langName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeLangSelector_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - if ( (langName == 0) || (*langName == 0) ) XMP_Throw ( "Empty language name", kXMPErr_BadParam ); - - if ( fullPath == 0 ) fullPath = &voidStringPtr; - if ( pathSize == 0 ) pathSize = &voidStringLen; - - XMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName, fullPath, pathSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ComposeFieldSelector_1 ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeFieldSelector_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema ); - if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath ); - if ( fieldValue == 0 ) fieldValue = ""; - - if ( fullPath == 0 ) fullPath = &voidStringPtr; - if ( pathSize == 0 ) pathSize = &voidStringLen; - - XMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, fullPath, pathSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ================================================================================================= - -void -WXMPUtils_ConvertFromBool_1 ( XMP_Bool binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromBool_1" ) - - if ( strValue == 0 ) strValue = &voidStringPtr; - if ( strSize == 0 ) strSize = &voidStringLen; - - XMPUtils::ConvertFromBool ( binValue, strValue, strSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertFromInt_1 ( XMP_Int32 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromInt_1" ) - - if ( format == 0 ) format = ""; - - if ( strValue == 0 ) strValue = &voidStringPtr; - if ( strSize == 0 ) strSize = &voidStringLen; - - XMPUtils::ConvertFromInt ( binValue, format, strValue, strSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertFromInt64_1 ( XMP_Int64 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromInt64_1" ) - - if ( format == 0 ) format = ""; - - if ( strValue == 0 ) strValue = &voidStringPtr; - if ( strSize == 0 ) strSize = &voidStringLen; - - XMPUtils::ConvertFromInt64 ( binValue, format, strValue, strSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertFromFloat_1 ( double binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromFloat_1" ) - - if ( format == 0 ) format = ""; - - if ( strValue == 0 ) strValue = &voidStringPtr; - if ( strSize == 0 ) strSize = &voidStringLen; - - XMPUtils::ConvertFromFloat ( binValue, format, strValue, strSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertFromDate_1 ( const XMP_DateTime & binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromDate_1" ) - - if ( strValue == 0 ) strValue = &voidStringPtr; - if ( strSize == 0 ) strSize = &voidStringLen; - - XMPUtils::ConvertFromDate( binValue, strValue, strSize ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ================================================================================================= - -void -WXMPUtils_ConvertToBool_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToBool_1" ) - - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam); - XMP_Bool result = XMPUtils::ConvertToBool ( strValue ); - wResult->int32Result = result; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertToInt_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToInt_1" ) - - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam); - XMP_Int32 result = XMPUtils::ConvertToInt ( strValue ); - wResult->int32Result = result; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertToInt64_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToInt64_1" ) - - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam); - XMP_Int64 result = XMPUtils::ConvertToInt64 ( strValue ); - wResult->int64Result = result; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertToFloat_1 ( XMP_StringPtr strValue, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToFloat_1") - - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam); - double result = XMPUtils::ConvertToFloat ( strValue ); - wResult->floatResult = result; - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertToDate_1 ( XMP_StringPtr strValue, - XMP_DateTime * binValue, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToDate_1" ) - - if ( binValue == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); // ! Pointer is from the client. - XMPUtils::ConvertToDate ( strValue, binValue ); - - XMP_EXIT_WRAPPER -} - -// ================================================================================================= - -void -WXMPUtils_CurrentDateTime_1 ( XMP_DateTime * time, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_CurrentDateTime_1" ) - - if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); - XMPUtils::CurrentDateTime ( time ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_SetTimeZone_1 ( XMP_DateTime * time, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_SetTimeZone_1" ) - - if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); - XMPUtils::SetTimeZone ( time ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertToUTCTime_1 ( XMP_DateTime * time, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToUTCTime_1" ) - - if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); - XMPUtils::ConvertToUTCTime ( time ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_ConvertToLocalTime_1 ( XMP_DateTime * time, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToLocalTime_1" ) - - if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); - XMPUtils::ConvertToLocalTime ( time ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_CompareDateTime_1 ( const XMP_DateTime & left, - const XMP_DateTime & right, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_CompareDateTime_1" ) - - int result = XMPUtils::CompareDateTime ( left, right ); - wResult->int32Result = result; - - XMP_EXIT_WRAPPER -} - -// ================================================================================================= - -void -WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - XMP_StringPtr * encodedStr, - XMP_StringLen * encodedLen, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_EncodeToBase64_1" ) - - if ( encodedStr == 0 ) encodedStr = &voidStringPtr; - if ( encodedLen == 0 ) encodedLen = &voidStringLen; - - XMPUtils::EncodeToBase64 ( rawStr, rawLen, encodedStr, encodedLen ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - XMP_StringPtr * rawStr, - XMP_StringLen * rawLen, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_DecodeFromBase64_1" ) - - if ( rawStr == 0 ) rawStr = &voidStringPtr; - if ( rawLen == 0 ) rawLen = &voidStringLen; - - XMPUtils::DecodeFromBase64 ( encodedStr, encodedLen, rawStr, rawLen ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ================================================================================================= - -void -WXMPUtils_PackageForJPEG_1 ( XMPMetaRef wxmpObj, - XMP_StringPtr * stdStr, - XMP_StringLen * stdLen, - XMP_StringPtr * extStr, - XMP_StringLen * extLen, - XMP_StringPtr * digestStr, - XMP_StringLen * digestLen, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_PackageForJPEG_1" ) - - if ( stdStr == 0 ) stdStr = &voidStringPtr; - if ( stdLen == 0 ) stdLen = &voidStringLen; - if ( extStr == 0 ) extStr = &voidStringPtr; - if ( extLen == 0 ) extLen = &voidStringLen; - if ( digestStr == 0 ) digestStr = &voidStringPtr; - if ( digestLen == 0 ) digestLen = &voidStringLen; - - const XMPMeta & xmpObj = WtoXMPMeta_Ref ( wxmpObj ); - XMPUtils::PackageForJPEG ( xmpObj, stdStr, stdLen, extStr, extLen, digestStr, digestLen ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_MergeFromJPEG_1 ( XMPMetaRef wfullXMP, - XMPMetaRef wextendedXMP, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_MergeFromJPEG_1" ) - - if ( wfullXMP == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam ); - - XMPMeta * fullXMP = WtoXMPMeta_Ptr ( wfullXMP ); - const XMPMeta & extendedXMP = WtoXMPMeta_Ref ( wextendedXMP ); - XMPUtils::MergeFromJPEG ( fullXMP, extendedXMP ); - - XMP_EXIT_WRAPPER -} - -// ================================================================================================= - -void -WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef wxmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr separator, - XMP_StringPtr quotes, - XMP_OptionBits options, - XMP_StringPtr * catedStr, - XMP_StringLen * catedLen, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_CatenateArrayItems_1" ) - - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - - if ( separator == 0 ) separator = "; "; - if ( quotes == 0 ) quotes = "\""; - - if ( catedStr == 0 ) catedStr = &voidStringPtr; - if ( catedLen == 0 ) catedLen = &voidStringLen; - - const XMPMeta & xmpObj = WtoXMPMeta_Ref ( wxmpObj ); - XMPUtils::CatenateArrayItems ( xmpObj, schemaNS, arrayName, separator, quotes, options, catedStr, catedLen ); - - XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_SeparateArrayItems_1 ( XMPMetaRef wxmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_SeparateArrayItems_1" ) - - if ( wxmpObj == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam ); - if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema ); - if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath ); - if ( catedStr == 0 ) catedStr = ""; - - XMPMeta * xmpObj = WtoXMPMeta_Ptr ( wxmpObj ); - XMPUtils::SeparateArrayItems ( xmpObj, schemaNS, arrayName, options, catedStr ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_RemoveProperties_1 ( XMPMetaRef wxmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_RemoveProperties_1" ) - - if ( wxmpObj == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam ); - if ( schemaNS == 0 ) schemaNS = ""; - if ( propName == 0 ) propName = ""; - - XMPMeta * xmpObj = WtoXMPMeta_Ptr ( wxmpObj ); - XMPUtils::RemoveProperties ( xmpObj, schemaNS, propName, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_AppendProperties_1 ( XMPMetaRef wSource, - XMPMetaRef wDest, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_AppendProperties_1" ) - - if ( wDest == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam ); - - const XMPMeta & source = WtoXMPMeta_Ref ( wSource ); - XMPMeta * dest = WtoXMPMeta_Ptr ( wDest ); - XMPUtils::AppendProperties ( source, dest, options ); - - XMP_EXIT_WRAPPER -} - -// ------------------------------------------------------------------------------------------------- - -void -WXMPUtils_DuplicateSubtree_1 ( XMPMetaRef wSource, - XMPMetaRef wDest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS, - XMP_StringPtr destRoot, - XMP_OptionBits options, - WXMP_Result * wResult ) -{ - XMP_ENTER_WRAPPER ( "WXMPUtils_DuplicateSubtree_1" ) - - if ( wDest == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam ); - if ( (sourceNS == 0) || (*sourceNS == 0) ) XMP_Throw ( "Empty source schema URI", kXMPErr_BadSchema ); - if ( (sourceRoot == 0) || (*sourceRoot == 0) ) XMP_Throw ( "Empty source root name", kXMPErr_BadXPath ); - if ( destNS == 0 ) destNS = sourceNS; - if ( destRoot == 0 ) destRoot = sourceRoot; - - const XMPMeta & source = WtoXMPMeta_Ref ( wSource ); - XMPMeta * dest = WtoXMPMeta_Ptr ( wDest ); - XMPUtils::DuplicateSubtree ( source, dest, sourceNS, sourceRoot, destNS, destRoot, options ); - - XMP_EXIT_WRAPPER -} - -// ================================================================================================= - -#if __cplusplus -} /* extern "C" */ -#endif diff --git a/xmpsdk/src/XMLParserAdapter.hpp b/xmpsdk/src/XMLParserAdapter.hpp deleted file mode 100644 index 55d53cadbf..0000000000 --- a/xmpsdk/src/XMLParserAdapter.hpp +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef __XMLParserAdapter_hpp__ -#define __XMLParserAdapter_hpp__ - -// ================================================================================================= -// Copyright 2005-2007 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 "XMP_Environment.h" // ! Must be the first #include! -#include "XMP_Const.h" - -#include -#include - -// ================================================================================================= -// XML_Node details -// -// The XML_Nodes are used only during the XML/RDF parsing process. This presently uses an XML parser -// to create an XML tree, then a recursive descent RDF recognizer to build the corresponding XMP. -// This makes it easier to swap XML parsers and provides a clean separation of XML and RDF issues. -// The overall parsing would be faster and use less memory if the RDF recognition were done on the -// fly using a state machine. But it was much easier to write the recursive descent version. The -// current implementation is pretty fast in absolute terms, so being faster might not be crucial. -// -// Like the XMP tree, the XML tree contains vectors of pointers for down links, and offspring have -// a pointer to their parent. Unlike the XMP tree, this is an exact XML document tree. There are no -// introduced top level namespace nodes or rearrangement of the nodes.. -// -// The exact state of namespaces can vary during the XML parsing, depending on the parser in use. -// By the time the RDF recognition is done though, the namespaces must be normalized. All of the -// used namespaces must be registered, this is done automatically if necessary. All of the "live" -// namespace prefixes will be unique. The ns field of an XML_Node is the namespace URI, the name -// field contains a qualified name (prefix:local). This includes default namespace mapping, the -// URI and prefix will be missing only for elements and attributes in no namespace. - -class XML_Node; - -typedef XML_Node * XML_NodePtr; // Handy for things like: XML_Node * a, b; - b is XML_Node, not XML_Node*! - -enum { kRootNode = 0, kElemNode = 1, kAttrNode = 2, kCDataNode = 3, kPINode = 4 }; - -#define IsWhitespaceChar(ch) ( ((ch) == ' ') || ((ch) == 0x09) || ((ch) == 0x0A) || ((ch) == 0x0D) ) - -typedef std::vector XML_NodeVector; -typedef XML_NodeVector::iterator XML_NodePos; -typedef XML_NodeVector::const_iterator XML_cNodePos; - -#if 0 // Pattern for iterating over the children or attributes: - for ( size_t xxNum = 0, xxLim = _node_->_offspring_.size(); xxNum < xxLim; ++xxNum ) { - const XML_NodePtr _curr_ = _node_->_offspring_[xxNum]; - } -#endif - -class XML_Node { -public: - - // Intended for lightweight internal use. Clients are expected to use the data directly. - - XMP_Uns8 kind; - std::string ns, name, value; - size_t nsPrefixLen; - XML_NodePtr parent; - XML_NodeVector attrs; - XML_NodeVector content; - - bool IsWhitespaceNode() const; - bool IsLeafContentNode() const; // An empty element or one with a single character data child node. - bool IsEmptyLeafNode() const; - - XMP_StringPtr GetAttrValue ( XMP_StringPtr attrName ) const; - void SetAttrValue ( XMP_StringPtr attrName, XMP_StringPtr attrValue ); - - XMP_StringPtr GetLeafContentValue() const; - void SetLeafContentValue ( XMP_StringPtr value ); - - size_t CountNamedElements ( XMP_StringPtr nsURI, XMP_StringPtr localName ) const; // Number of child elements with this name. - XML_NodePtr GetNamedElement ( XMP_StringPtr nsURI, XMP_StringPtr localName, size_t which = 0 ); - - void Dump ( std::string * buffer ); - void Serialize ( std::string * buffer ); - - void RemoveAttrs(); - void RemoveContent(); - void ClearNode(); - - XML_Node ( XML_NodePtr _parent, XMP_StringPtr _name, XMP_Uns8 _kind ) - : kind(_kind), name(_name), nsPrefixLen(0), parent(_parent) {}; - - XML_Node ( XML_NodePtr _parent, const std::string & _name, XMP_Uns8 _kind ) - : kind(_kind), name(_name), nsPrefixLen(0), parent(_parent) {}; - - virtual ~XML_Node() { RemoveAttrs(); RemoveContent(); }; - -private: - - XML_Node() : kind(0), parent(0) {}; // ! Hidden to make sure parent pointer is always set. - -}; - -// ================================================================================================= -// Abstract base class for XML parser adapters used by the XMP toolkit. - -enum { kXMLPendingInputMax = 16 }; - -class XMLParserAdapter { -public: - - XMLParserAdapter() - : tree(0,"",kRootNode), rootNode(0), rootCount(0), charEncoding(XMP_OptionBits(-1)), pendingCount(0) - { - #if XMP_DebugBuild - parseLog = 0; - #endif - }; - - virtual ~XMLParserAdapter() {}; - - virtual void ParseBuffer ( const void * buffer, size_t length, bool last ) = 0; - - XML_Node tree; - XML_NodeVector parseStack; - XML_NodePtr rootNode; - size_t rootCount; - - XMP_OptionBits charEncoding; - size_t pendingCount; - unsigned char pendingInput[kXMLPendingInputMax]; // Buffered input for character encoding checks. - - #if XMP_DebugBuild - FILE * parseLog; - #endif - -}; - -// ================================================================================================= - -#endif // __XMLParserAdapter_hpp__ diff --git a/xmpsdk/src/XML_Node.cpp b/xmpsdk/src/XML_Node.cpp deleted file mode 100644 index 5f20358ec7..0000000000 --- a/xmpsdk/src/XML_Node.cpp +++ /dev/null @@ -1,463 +0,0 @@ -// ================================================================================================= -// Copyright 2005-2007 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 "XMP_Environment.h" // ! Must be the first #include! -#include "XMLParserAdapter.hpp" - -#include -#include -#include - -// ! Can't include XMP..._Impl.hpp - used by both Core and Files. -#define XMP_LitNMatch(s,l,n) (std::strncmp((s),(l),(n)) == 0) - -#if XMP_WinBuild -#ifdef _MSC_VER - #define snprintf _snprintf - #pragma warning ( disable : 4996 ) // snprintf is safe -#endif -#endif - -// ================================================================================================= - -#if 0 // Pattern for iterating over the children or attributes: - for ( size_t xxNum = 0, xxLim = _node_->_offspring_->size(); xxNum < xxLim; ++xxNum ) { - const XML_NodePtr _curr_ = _node_->_offspring_[xxNum]; - } -#endif - -// ================================================================================================= -// XML_Node::IsWhitespaceNode -//=========================== - -bool XML_Node::IsWhitespaceNode() const -{ - if ( this->kind != kCDataNode ) return false; - - for ( size_t i = 0; i < this->value.size(); ++i ) { - unsigned char ch = this->value[i]; - if ( IsWhitespaceChar ( ch ) ) continue; - // *** Add checks for other whitespace characters. - return false; // All the checks failed, this isn't whitespace. - } - - return true; - -} // XML_Node::IsWhitespaceNode - -// ================================================================================================= -// XML_Node::IsLeafContentNode -//============================ - -bool XML_Node::IsLeafContentNode() const -{ - if ( this->kind != kElemNode ) return false; - if ( this->content.size() == 0 ) return true; - if ( this->content.size() > 1 ) return false; - if ( this->content[0]->kind != kCDataNode ) return false; - - return true; - -} // XML_Node::IsLeafContentNode - -// ================================================================================================= -// XML_Node::IsEmptyLeafNode -//========================== - -bool XML_Node::IsEmptyLeafNode() const -{ - - if ( (this->kind != kElemNode) || (this->content.size() != 0) ) return false; - return true; - -} // XML_Node::IsEmptyLeafNode - -// ================================================================================================= -// XML_Node::GetAttrValue -//======================= - -XMP_StringPtr XML_Node::GetAttrValue ( XMP_StringPtr attrName ) const -{ - - for ( size_t i = 0, aLim = this->attrs.size(); i < aLim; ++i ) { - XML_Node * attrPtr = this->attrs[i]; - if ( ! attrPtr->ns.empty() ) continue; // This form of GetAttrValue is for attrs in no namespace. - if ( attrPtr->name == attrName ) return attrPtr->value.c_str(); - } - - return 0; // Not found. - -} // XML_Node::GetAttrValue - -// ================================================================================================= -// XML_Node::SetAttrValue -//======================= - -void XML_Node::SetAttrValue ( XMP_StringPtr attrName, XMP_StringPtr attrValue ) -{ - - for ( size_t i = 0, aLim = this->attrs.size(); i < aLim; ++i ) { - XML_Node * attrPtr = this->attrs[i]; - if ( ! attrPtr->ns.empty() ) continue; // This form of SetAttrValue is for attrs in no namespace. - if ( attrPtr->name == attrName ) { - attrPtr->value = attrValue; - return; - } - } - -} // XML_Node::SetAttrValue - -// ================================================================================================= -// XML_Node::GetLeafContentValue -//============================== - -XMP_StringPtr XML_Node::GetLeafContentValue() const -{ - if ( (! this->IsLeafContentNode()) || this->content.empty() ) return ""; - - return this->content[0]->value.c_str(); - -} // XML_Node::GetLeafContentValue - -// ================================================================================================= -// XML_Node::SetLeafContentValue -//============================== - -void XML_Node::SetLeafContentValue ( XMP_StringPtr newValue ) -{ - XML_Node * valueNode; - - if ( ! this->content.empty() ) { - valueNode = this->content[0]; - } else { - valueNode = new XML_Node ( this, "", kCDataNode ); - this->content.push_back ( valueNode ); - } - - valueNode->value = newValue; - -} // XML_Node::SetLeafContentValue - -// ================================================================================================= -// XML_Node::CountNamedElements -//============================= - -size_t XML_Node::CountNamedElements ( XMP_StringPtr nsURI, XMP_StringPtr localName ) const -{ - size_t count = 0; - - for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) { - const XML_Node & child = *this->content[i]; - if ( child.ns != nsURI ) continue; - if ( strcmp ( localName, child.name.c_str()+child.nsPrefixLen ) != 0 ) continue; - ++count; - } - - return count; - -} // XML_Node::CountNamedElements - -// ================================================================================================= -// XML_Node::GetNamedElement -//========================== - -XML_NodePtr XML_Node::GetNamedElement ( XMP_StringPtr nsURI, XMP_StringPtr localName, size_t which /* = 0 */ ) -{ - - for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) { - XML_Node * childPtr = this->content[i]; - if ( childPtr->ns != nsURI ) continue; - if ( strcmp ( localName, childPtr->name.c_str()+childPtr->nsPrefixLen ) != 0 ) continue; - if ( which == 0 ) return childPtr; - --which; - } - - return 0; /// Not found. - -} // XML_Node::GetNamedElement - -// ================================================================================================= -// DumpNodeList -// ============ - -static const char * kNodeKinds[] = { "root", "elem", "attr", "cdata", "pi" }; - -static void DumpNodeList ( std::string * buffer, const XML_NodeVector & list, int indent ) -{ - - for ( size_t i = 0, limit = list.size(); i < limit; ++i ) { - - const XML_Node * node = list[i]; - - for ( int t = indent; t > 0; --t ) *buffer += " "; - if ( node->IsWhitespaceNode() ) { - *buffer += "-- whitespace --\n"; - continue; - } - - *buffer += node->name; - *buffer += " - "; - *buffer += kNodeKinds[node->kind]; - if ( ! node->value.empty() ) { - *buffer += ", value=\""; - *buffer += node->value; - *buffer += "\""; - } - if ( ! node->ns.empty() ) { - *buffer += ", ns=\""; - *buffer += node->ns; - *buffer += "\""; - } - if ( node->nsPrefixLen != 0 ) { - *buffer += ", prefixLen="; - char numBuf [20]; - snprintf ( numBuf, sizeof(numBuf), "%lu", (unsigned long)node->nsPrefixLen ); - *buffer += numBuf; - } - *buffer += "\n"; - - if ( ! node->attrs.empty() ) { - for ( int t = indent+1; t > 0; --t ) *buffer += " "; - *buffer += "attrs:\n"; - DumpNodeList ( buffer, node->attrs, indent+2 ); - } - - if ( ! node->content.empty() ) { - DumpNodeList ( buffer, node->content, indent+1 ); - } - - } - -} // DumpNodeList - -// ================================================================================================= -// XML_Node::Dump -//=============== - -void XML_Node::Dump ( std::string * buffer ) -{ - - *buffer = "Dump of XML_Node tree\n"; - - *buffer += "Root info: name=\""; - *buffer += this->name; - *buffer += "\", value=\""; - *buffer += this->value; - *buffer += "\", ns=\""; - *buffer += this->ns; - *buffer += "\", kind="; - *buffer += kNodeKinds[this->kind]; - *buffer += "\n"; - - if ( ! this->attrs.empty() ) { - *buffer += " attrs:\n"; - DumpNodeList ( buffer, this->attrs, 2 ); - } - *buffer += "\n"; - - DumpNodeList ( buffer, this->content, 0 ); - -} // XML_Node::Dump - -// ================================================================================================= -// SerializeOneNode -// ================ - -static void SerializeOneNode ( std::string * buffer, const XML_Node & node ) -{ - size_t i, limit; - XMP_StringPtr namePtr = node.name.c_str(); - if ( XMP_LitNMatch ( namePtr, "_dflt_:", 7 ) ) namePtr += 7; // Hack for default namespaces. - - switch ( node.kind ) { - - case kElemNode: - *buffer += '<'; - *buffer += namePtr; - for ( i = 0, limit = node.attrs.size(); i < limit; ++i ) { - SerializeOneNode ( buffer, *node.attrs[i] ); - } - if ( node.content.empty() ) { - *buffer += "/>"; - } else { - *buffer += '>'; - for ( i = 0, limit = node.content.size(); i < limit; ++i ) { - SerializeOneNode ( buffer, *node.content[i] ); - } - *buffer += "'; - } - break; - - case kAttrNode: - *buffer += ' '; - *buffer += namePtr; - *buffer += "=\""; - *buffer += node.value; - *buffer += '"'; - break; - - case kCDataNode: - *buffer += node.value; - break; - - case kPINode: - *buffer += node.value; // *** Note that we're dropping PIs during the Expat parse. - break; - - } - -} // SerializeOneNode - -// ================================================================================================= -// CollectNamespaceDecls -// ===================== - -typedef std::map < std::string, std::string > NamespaceMap; - -static void CollectNamespaceDecls ( NamespaceMap * nsMap, const XML_Node & node ) -{ - size_t i, limit; - - if ( ! node.ns.empty() ) { - size_t nameMid = 0; - while ( node.name[nameMid] != ':' ) ++nameMid; - std::string prefix = node.name.substr ( 0, nameMid ); - (*nsMap)[prefix] = node.ns; - } - - if ( node.kind == kElemNode ) { - - for ( i = 0, limit = node.attrs.size(); i < limit; ++i ) { - CollectNamespaceDecls ( nsMap, *node.attrs[i] ); - } - - for ( i = 0, limit = node.content.size(); i < limit; ++i ) { - const XML_Node & content = *node.content[i]; - if ( content.kind == kElemNode ) CollectNamespaceDecls ( nsMap, content ); - } - - } - -} // CollectNamespaceDecls - -// ================================================================================================= -// XML_Node::Serialize -//==================== - -void XML_Node::Serialize ( std::string * buffer ) -{ - buffer->erase(); - - if ( this->kind != kRootNode ) { - - SerializeOneNode ( buffer, *this ); - - } else { - - // Do the outermost level here, in order to add the XML version and namespace declarations. - - *buffer += "\n"; - - for ( size_t outer = 0, oLimit = this->content.size(); outer < oLimit; ++outer ) { - - const XML_Node & node = *this->content[outer]; - - if ( node.kind != kElemNode ) { - - SerializeOneNode ( buffer, node ); - - } else { - - XMP_StringPtr namePtr = node.name.c_str(); - if ( XMP_LitNMatch ( namePtr, "_dflt_:", 7 ) ) namePtr += 7; // Hack for default namespaces. - - *buffer += '<'; - *buffer += namePtr; - - NamespaceMap nsMap; - CollectNamespaceDecls ( &nsMap, node ); - NamespaceMap::iterator nsDecl = nsMap.begin(); - NamespaceMap::iterator nsEnd = nsMap.end(); - for ( ; nsDecl != nsEnd; ++nsDecl ) { - const std::string & prefix = nsDecl->first; - *buffer += " xmlns"; - if ( prefix != "_dflt_" ) { *buffer += ':'; *buffer += prefix; } - *buffer += "=\""; - *buffer += nsDecl->second; - *buffer += '"'; - } - - for ( size_t attr = 0, aLimit = node.attrs.size(); attr < aLimit; ++attr ) { - SerializeOneNode ( buffer, *node.attrs[attr] ); - } - - if ( node.content.empty() ) { - *buffer += "/>"; - } else { - *buffer += '>'; - for ( size_t child = 0, cLimit = node.content.size(); child < cLimit; ++child ) { - SerializeOneNode ( buffer, *node.content[child] ); - } - *buffer += "'; - } - - } - - } - - } - - -} // XML_Node::Serialize - -// ================================================================================================= -// XML_Node::RemoveAttrs -//====================== - -void XML_Node::RemoveAttrs() -{ - - for ( size_t i = 0, vLim = this->attrs.size(); i < vLim; ++i ) delete this->attrs[i]; - this->attrs.clear(); - -} // XML_Node::RemoveAttrs - -// ================================================================================================= -// XML_Node::RemoveContent -//======================== - -void XML_Node::RemoveContent() -{ - - for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) delete this->content[i]; - this->content.clear(); - -} // XML_Node::RemoveContent - -// ================================================================================================= -// XML_Node::ClearNode -//==================== - -void XML_Node::ClearNode() -{ - - this->kind = 0; - this->ns.erase(); - this->name.erase(); - this->value.erase(); - - this->RemoveAttrs(); - this->RemoveContent(); - -} // XML_Node::ClearNode - -// ================================================================================================= diff --git a/xmpsdk/src/XMPCore_Impl.cpp b/xmpsdk/src/XMPCore_Impl.cpp deleted file mode 100644 index b810bfe929..0000000000 --- a/xmpsdk/src/XMPCore_Impl.cpp +++ /dev/null @@ -1,1468 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2007 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMP_Version.h" -#include "XMPCore_Impl.hpp" -#include "XMPMeta.hpp" // *** For use of GetNamespacePrefix in FindSchemaNode. - -#include "UnicodeInlines.incl_cpp" - -#include - -using namespace std; - -#if XMP_WinBuild - #ifdef _MSC_VER - #pragma warning ( disable : 4290 ) // C++ exception specification ignored except ... not __declspec(nothrow) - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) - #endif -#endif - -// *** Add debug codegen checks, e.g. that typical masking operations really work -// *** Make option constants 0x...UL. - -// Internal code should be using #if with XMP_MacBuild, XMP_WinBuild, or XMP_UNIXBuild. -// This is a sanity check in case of accidental use of *_ENV. Some clients use the poor -// practice of defining the *_ENV macro with an empty value. -#if defined ( MAC_ENV ) - #if ! MAC_ENV - #error "MAC_ENV must be defined so that \"#if MAC_ENV\" is true" - #endif -#elif defined ( WIN_ENV ) - #if ! WIN_ENV - #error "WIN_ENV must be defined so that \"#if WIN_ENV\" is true" - #endif -#elif defined ( UNIX_ENV ) - #if ! UNIX_ENV - #error "UNIX_ENV must be defined so that \"#if UNIX_ENV\" is true" - #endif -#endif - -// ================================================================================================= -// Static Variables -// ================ - -XMP_Int32 sXMP_InitCount = 0; - -XMP_StringMap * sNamespaceURIToPrefixMap = 0; -XMP_StringMap * sNamespacePrefixToURIMap = 0; - -XMP_AliasMap * sRegisteredAliasMap = 0; // Needed by XMPIterator. - -XMP_VarString * sOutputNS = 0; -XMP_VarString * sOutputStr = 0; -XMP_VarString * sExceptionMessage = 0; - -XMP_Mutex sXMPCoreLock; -int sLockCount = 0; - -#if TraceXMPCalls - FILE * xmpOut = stderr; -#endif - -void * voidVoidPtr = 0; // Used to backfill null output parameters. -XMP_StringPtr voidStringPtr = 0; -XMP_StringLen voidStringLen = 0; -XMP_OptionBits voidOptionBits = 0; -XMP_Uns8 voidByte = 0; -bool voidBool = 0; -XMP_Int32 voidInt32 = 0; -XMP_Int64 voidInt64 = 0; -double voidDouble = 0.0; -XMP_DateTime voidDateTime; -WXMP_Result void_wResult; - -// ================================================================================================= -// Mutex Utilities -// =============== - -// ! Note that the mutex need not be "recursive", allowing the same thread to acquire it multiple -// ! times. There is a single XMP lock which is acquired in the wrapper classes. Internal calls -// ! never go back out to the wrappers. - -#if XMP_WinBuild - - bool XMP_InitMutex ( XMP_Mutex * mutex ) { - InitializeCriticalSection ( mutex ); - return true; - } - - void XMP_TermMutex ( XMP_Mutex & mutex ) { - DeleteCriticalSection ( &mutex ); - } - - void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ) { - EnterCriticalSection ( &mutex ); - } - - void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ) { - LeaveCriticalSection ( &mutex ); - } - -#else - - // Use pthread for both Mac and generic UNIX. - // ! Would be nice to specify PTHREAD_MUTEX_ERRORCHECK, but the POSIX documentation is useless. - // ! Would be OK but overkill to specify PTHREAD_MUTEX_RECURSIVE. - - bool XMP_InitMutex ( XMP_Mutex * mutex ) { - int err = pthread_mutex_init ( mutex, 0 ); - return (err == 0 ); - } - - void XMP_TermMutex ( XMP_Mutex & mutex ) { - (void) pthread_mutex_destroy ( &mutex ); - } - - void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ) { - int err = pthread_mutex_lock ( &mutex ); - if ( err != 0 ) XMP_Throw ( "XMP_EnterCriticalRegion - pthread_mutex_lock failure", kXMPErr_ExternalFailure ); - } - - void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ) { - int err = pthread_mutex_unlock ( &mutex ); - if ( err != 0 ) XMP_Throw ( "XMP_ExitCriticalRegion - pthread_mutex_unlock failure", kXMPErr_ExternalFailure ); - } - -#endif - -// ================================================================================================= -// Local Utilities -// =============== - -// ------------------------------------------------------------------------------------------------- -// VerifyXPathRoot -// --------------- -// -// Set up the first 2 components of the expanded XPath. Normalizes the various cases of using the -// full schema URI and/or a qualified root property name. Returns true for normal processing. If -// allowUnknownSchemaNS is true and the schema namespace is not registered, false is returned. If -// allowUnknownSchemaNS is false and the schema namespace is not registered, an exception is thrown. - -// *** Should someday check the full syntax. - -static void -VerifyXPathRoot ( XMP_StringPtr schemaURI, - XMP_StringPtr propName, - XMP_ExpandedXPath * expandedXPath ) -{ - // Do some basic checks on the URI and name. Try to lookup the URI. See if the name is qualified. - - XMP_Assert ( (schemaURI != 0) && (propName != 0) && (*propName != 0) ); - XMP_Assert ( (expandedXPath != 0) && (expandedXPath->empty()) ); - - if ( *schemaURI == 0 ) XMP_Throw ( "Schema namespace URI is required", kXMPErr_BadSchema ); - - if ( (*propName == '?') || (*propName == '@') ) { - XMP_Throw ( "Top level name must not be a qualifier", kXMPErr_BadXPath ); - } - for ( XMP_StringPtr ch = propName; *ch != 0; ++ch ) { - if ( (*ch == '/') || (*ch == '[') ) { - XMP_Throw ( "Top level name must be simple", kXMPErr_BadXPath ); - } - } - - XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( XMP_VarString ( schemaURI ) ); - if ( uriPos == sNamespaceURIToPrefixMap->end() ) { - XMP_Throw ( "Unregistered schema namespace URI", kXMPErr_BadSchema ); - } - - XMP_StringPtr colonPos = propName; - while ( (*colonPos != 0) && (*colonPos != ':') ) ++colonPos; - VerifySimpleXMLName ( propName, colonPos ); // Verify the part before any colon. - - // Verify the various URI and prefix combinations. Initialize the expanded XPath. - - if ( *colonPos == 0 ) { - - // The propName is unqualified, use the schemaURI and associated prefix. - - expandedXPath->push_back ( XPathStepInfo ( schemaURI, kXMP_SchemaNode ) ); - expandedXPath->push_back ( XPathStepInfo ( uriPos->second, 0 ) ); - (*expandedXPath)[kRootPropStep].step += propName; - - } else { - - // The propName is qualified. Make sure the prefix is legit. Use the associated URI and qualified name. - - size_t prefixLen = colonPos - propName + 1; // ! Include the colon. - VerifySimpleXMLName ( colonPos+1, colonPos+strlen(colonPos) ); - - XMP_VarString prefix ( propName, prefixLen ); - XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( prefix ); - if ( prefixPos == sNamespacePrefixToURIMap->end() ) { - XMP_Throw ( "Unknown schema namespace prefix", kXMPErr_BadSchema ); - } - if ( prefix != uriPos->second ) { - XMP_Throw ( "Schema namespace URI and prefix mismatch", kXMPErr_BadSchema ); - } - - expandedXPath->push_back ( XPathStepInfo ( schemaURI, kXMP_SchemaNode ) ); - expandedXPath->push_back ( XPathStepInfo ( propName, 0 ) ); - - } - -} // VerifyXPathRoot - -// ------------------------------------------------------------------------------------------------- -// VerifyQualName -// -------------- - -static void -VerifyQualName ( XMP_StringPtr qualName, XMP_StringPtr nameEnd ) -{ - if ( qualName >= nameEnd ) XMP_Throw ( "Empty qualified name", kXMPErr_BadXPath ); - - XMP_StringPtr colonPos = qualName; - while ( (colonPos < nameEnd) && (*colonPos != ':') ) ++colonPos; - if ( (colonPos == qualName) || (colonPos >= nameEnd) ) XMP_Throw ( "Ill-formed qualified name", kXMPErr_BadXPath ); - - VerifySimpleXMLName ( qualName, colonPos ); - VerifySimpleXMLName ( colonPos+1, nameEnd ); - - size_t prefixLen = colonPos - qualName + 1; // ! Include the colon. - XMP_VarString prefix ( qualName, prefixLen ); - XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( prefix ); - if ( prefixPos == sNamespacePrefixToURIMap->end() ) { - XMP_Throw ( "Unknown namespace prefix for qualified name", kXMPErr_BadXPath ); - } - -} // VerifyQualName - -// ------------------------------------------------------------------------------------------------- -// FindIndexedItem -// --------------- -// -// [index] An element of an array. -// -// Support the implicit creation of a new last item. - -static XMP_Index -FindIndexedItem ( XMP_Node * arrayNode, const XMP_VarString & indexStep, bool createNodes ) -{ - XMP_Index index = 0; - size_t chLim = indexStep.size() - 1; - - XMP_Assert ( (chLim >= 2) && (indexStep[0] == '[') && (indexStep[chLim] == ']') ); - - for ( size_t chNum = 1; chNum != chLim; ++chNum ) { - XMP_Assert ( ('0' <= indexStep[chNum]) && (indexStep[chNum] <= '9') ); - index = (index * 10) + (indexStep[chNum] - '0'); - if ( index < 0 ) { - XMP_Throw ( "Array index overflow", kXMPErr_BadXPath ); // ! Overflow, not truly negative. - } - } - - --index; // Change to a C-style, zero based index. - if ( index < 0 ) XMP_Throw ( "Array index must be larger than zero", kXMPErr_BadXPath ); - - if ( (index == (XMP_Index)arrayNode->children.size()) && createNodes ) { // Append a new last+1 node. - XMP_Node * newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, kXMP_NewImplicitNode ); - arrayNode->children.push_back ( newItem ); - } - - // ! Don't throw here for a too large index. SetProperty will throw, GetProperty will not. - if ( index >= (XMP_Index)arrayNode->children.size() ) index = -1; - return index; - -} // FindIndexedItem - -// ------------------------------------------------------------------------------------------------- -// SplitNameAndValue -// ----------------- -// -// Split the name and value parts for field and qualifier selectors: -// -// [qualName="value"] An element in an array of structs, chosen by a field value. -// [?qualName="value"] An element in an array, chosen by a qualifier value. -// -// 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 -SplitNameAndValue ( const XMP_VarString & selStep, XMP_VarString * nameStr, XMP_VarString * valueStr ) -{ - XMP_StringPtr partBegin = selStep.c_str(); - XMP_StringPtr partEnd; - - const XMP_StringPtr valueEnd = partBegin + (selStep.size() - 2); - const char quote = *valueEnd; - - XMP_Assert ( (*partBegin == '[') && (*(valueEnd+1) == ']') ); - XMP_Assert ( (selStep.size() >= 6) && ((quote == '"') || (quote == '\'')) ); - - // Extract the name part. - - ++partBegin; // Skip the opening '['. - if ( *partBegin == '?' ) ++partBegin; - for ( partEnd = partBegin+1; *partEnd != '='; ++partEnd ) {}; - - nameStr->assign ( partBegin, (partEnd - partBegin) ); - - // Extract the value part, reducing doubled quotes. - - XMP_Assert ( *(partEnd+1) == quote ); - - partBegin = partEnd + 2; - valueStr->erase(); - valueStr->reserve ( valueEnd - partBegin ); // Maximum length, don't optimize doubled quotes. - - for ( partEnd = partBegin; partEnd < valueEnd; ++partEnd ) { - if ( (*partEnd == quote) && (*(partEnd+1) == quote) ) { - ++partEnd; - valueStr->append ( partBegin, (partEnd - partBegin) ); - partBegin = partEnd+1; // ! Loop will increment partEnd again. - } - } - - valueStr->append ( partBegin, (partEnd - partBegin) ); // ! The loop does not add the last part. - -} // SplitNameAndValue - -// ------------------------------------------------------------------------------------------------- -// LookupQualSelector -// ------------------ -// -// [?qualName="value"] An element in an array, chosen by a qualifier value. -// -// Note that we don't create implicit nodes for qualifier selectors, so no CreateNodes parameter. - -static XMP_Index -LookupQualSelector ( XMP_Node * arrayNode, const XMP_VarString & qualName, XMP_VarString & qualValue ) -{ - XMP_Index index; - - if ( qualName == "xml:lang" ) { - - // *** Should check that the value is legit RFC 1766/3066. - NormalizeLangValue ( &qualValue ); - index = LookupLangItem ( arrayNode, qualValue ) ; - - } else { - - XMP_Index itemLim; - for ( index = 0, itemLim = arrayNode->children.size(); index != itemLim; ++index ) { - - const XMP_Node * currItem = arrayNode->children[index]; - XMP_Assert ( currItem->parent == arrayNode ); - - size_t q, qualLim; - for ( q = 0, qualLim = currItem->qualifiers.size(); q != qualLim; ++q ) { - const XMP_Node * currQual = currItem->qualifiers[q]; - XMP_Assert ( currQual->parent == currItem ); - if ( currQual->name != qualName ) continue; - if ( currQual->value == qualValue ) break; // Exit qual loop. - } - if ( q != qualLim ) break; // Exit child loop, found an item with a matching qualifier. - - } - if ( index == itemLim ) index = -1; - - } - - return index; - -} // LookupQualSelector - -// ------------------------------------------------------------------------------------------------- -// FollowXPathStep -// --------------- -// -// After processing by ExpandXPath, a step can be of these forms: -// qualName A top level property or struct field. -// [index] An element of an array. -// [last()] The last element of an array. -// [qualName="value"] An element in an array of structs, chosen by a field value. -// [?qualName="value"] An element in an array, chosen by a qualifier value. -// ?qualName A general qualifier. -// -// Find the appropriate child node, resolving aliases, and optionally creating nodes. - -static XMP_Node * -FollowXPathStep ( XMP_Node * parentNode, - const XMP_ExpandedXPath & fullPath, - size_t stepNum, - bool createNodes, - XMP_NodePtrPos * ptrPos, - bool aliasedArrayItem = false ) -{ - XMP_Node * nextNode = 0; - const XPathStepInfo & nextStep = fullPath[stepNum]; - XMP_Index index = 0; - XMP_OptionBits stepKind = nextStep.options & kXMP_StepKindMask; - - XMP_Assert ( (kXMP_StructFieldStep <= stepKind) && (stepKind <= kXMP_FieldSelectorStep) ); - - if ( stepKind == kXMP_StructFieldStep ) { - - nextNode = FindChildNode ( parentNode, nextStep.step.c_str(), createNodes, ptrPos ); - - } else if ( stepKind == kXMP_QualifierStep ) { - - XMP_StringPtr qualStep = nextStep.step.c_str(); - XMP_Assert ( *qualStep == '?' ); - ++qualStep; - nextNode = FindQualifierNode ( parentNode, qualStep, createNodes, ptrPos ); - - } else { - - // This is an array indexing step. First get the index, then get the node. - - if ( ! (parentNode->options & kXMP_PropValueIsArray) ) { - XMP_Throw ( "Indexing applied to non-array", kXMPErr_BadXPath ); - } - - if ( stepKind == kXMP_ArrayIndexStep ) { - index = FindIndexedItem ( parentNode, nextStep.step, createNodes ); - } else if ( stepKind == kXMP_ArrayLastStep ) { - index = parentNode->children.size() - 1; - } else if ( stepKind == kXMP_FieldSelectorStep ) { - XMP_VarString fieldName, fieldValue; - SplitNameAndValue ( nextStep.step, &fieldName, &fieldValue ); - index = LookupFieldSelector ( parentNode, fieldName.c_str(), fieldValue.c_str() ); - } else if ( stepKind == kXMP_QualSelectorStep ) { - XMP_VarString qualName, qualValue; - SplitNameAndValue ( nextStep.step, &qualName, &qualValue ); - index = LookupQualSelector ( parentNode, qualName, qualValue ); - } else { - XMP_Throw ( "Unknown array indexing step in FollowXPathStep", kXMPErr_InternalFailure ); - } - - if ( (0 <= index) && (index <= (XMP_Index)parentNode->children.size()) ) nextNode = parentNode->children[index]; - - if ( (index == -1) && createNodes && aliasedArrayItem && (stepKind == kXMP_QualSelectorStep) ) { - - // An ugly special case without an obvious better place to be. We have an alias to the - // x-default item of an alt-text array. A simple reference via SetProperty must create - // the x-default item if it does not yet exist. - - XMP_Assert ( parentNode->options & kXMP_PropArrayIsAltText ); - XMP_Assert ( (stepNum == 2) && (nextStep.step == "[?xml:lang=\"x-default\"]") ); - - nextNode = new XMP_Node ( parentNode, kXMP_ArrayItemName, - (kXMP_PropHasQualifiers | kXMP_PropHasLang | kXMP_NewImplicitNode) ); - - XMP_Node * langQual = new XMP_Node ( nextNode, "xml:lang", "x-default", kXMP_PropIsQualifier ); - nextNode->qualifiers.push_back ( langQual ); - - if ( parentNode->children.empty() ) { - parentNode->children.push_back ( nextNode ); - } else { - parentNode->children.insert ( parentNode->children.begin(), nextNode ); - } - - index = 0; // ! C-style index! The x-default item is always first. - - } - - if ( (nextNode != 0) && (ptrPos != 0) ) *ptrPos = parentNode->children.begin() + index; - - } - - if ( (nextNode != 0) && (nextNode->options & kXMP_NewImplicitNode) ) { - nextNode->options |= (nextStep.options & kXMP_PropArrayFormMask); - } - - XMP_Assert ( (ptrPos == 0) || (nextNode == 0) || (nextNode == **ptrPos) ); - XMP_Assert ( (nextNode != 0) || (! createNodes) ); - return nextNode; - -} // FollowXPathStep - -// ------------------------------------------------------------------------------------------------- -// CheckImplicitStruct -// ------------------- - -static inline void -CheckImplicitStruct ( XMP_Node * node, - const XMP_ExpandedXPath & expandedXPath, - size_t stepNum, - size_t stepLim ) -{ - - if ( (stepNum < stepLim) && - ((node->options & kXMP_PropCompositeMask) == 0) && - (GetStepKind ( expandedXPath[stepNum].options ) == kXMP_StructFieldStep) ) { - - node->options |= kXMP_PropValueIsStruct; - - } - -} // CheckImplicitStruct - -// ------------------------------------------------------------------------------------------------- -// DeleteSubtree -// ------------- - -// *** Might be useful elsewhere? - -static void -DeleteSubtree ( XMP_NodePtrPos rootNodePos ) -{ - XMP_Node * rootNode = *rootNodePos; - XMP_Node * rootParent = rootNode->parent; - - if ( ! (rootNode->options & kXMP_PropIsQualifier) ) { - - rootParent->children.erase ( rootNodePos ); - - } else { - - rootParent->qualifiers.erase ( rootNodePos ); - - XMP_Assert ( rootParent->options & kXMP_PropHasQualifiers); - if ( rootParent->qualifiers.empty() ) rootParent->options ^= kXMP_PropHasQualifiers; - - if ( rootNode->name == "xml:lang" ) { - XMP_Assert ( rootParent->options & kXMP_PropHasLang); - rootParent->options ^= kXMP_PropHasLang; - } else if ( rootNode->name == "rdf:type" ) { - XMP_Assert ( rootParent->options & kXMP_PropHasType); - rootParent->options ^= kXMP_PropHasType; - } - - } - - delete rootNode; - -} // DeleteSubtree - -// ================================================================================================= -// ================================================================================================= - -// ================================================================================================= -// VerifySetOptions -// ================ -// -// Normalize and verify the option flags for SetProperty and similar functions. The allowed options -// here are just those that apply to the property, that would be kept in the XMP_Node. Others that -// affect the selection of the node or other processing must be removed by now. These are: -// kXMP_InsertBeforeItem -// kXMP_InsertAfterItem -// kXMP_KeepQualifiers -// kXMPUtil_AllowCommas - -enum { - kXMP_AllSetOptionsMask = (kXMP_PropValueIsURI | - kXMP_PropValueIsStruct | - kXMP_PropValueIsArray | - kXMP_PropArrayIsOrdered | - kXMP_PropArrayIsAlternate | - kXMP_PropArrayIsAltText | - kXMP_DeleteExisting) -}; - -XMP_OptionBits -VerifySetOptions ( XMP_OptionBits options, XMP_StringPtr propValue ) -{ - - if ( options & kXMP_PropArrayIsAltText ) options |= kXMP_PropArrayIsAlternate; - if ( options & kXMP_PropArrayIsAlternate ) options |= kXMP_PropArrayIsOrdered; - if ( options & kXMP_PropArrayIsOrdered ) options |= kXMP_PropValueIsArray; - - if ( options & ~kXMP_AllSetOptionsMask ) { - XMP_Throw ( "Unrecognized option flags", kXMPErr_BadOptions ); - } - - if ( (options & kXMP_PropValueIsStruct) && (options & kXMP_PropValueIsArray) ) { - XMP_Throw ( "IsStruct and IsArray options are mutually exclusive", kXMPErr_BadOptions ); - } - - if ( (options & kXMP_PropValueOptionsMask) && (options & kXMP_PropCompositeMask) ) { - XMP_Throw ( "Structs and arrays can't have \"value\" options", kXMPErr_BadOptions ); - } - - if ( (propValue != 0) && (options & kXMP_PropCompositeMask) ) { - XMP_Throw ( "Structs and arrays can't have string values", kXMPErr_BadOptions ); - } - - return options; - -} // VerifySetOptions - -// ================================================================================================= -// ComposeXPath -// ============ -// -// Compose the canonical string form of an expanded XPath expression. - -extern void -ComposeXPath ( const XMP_ExpandedXPath & expandedXPath, - XMP_VarString * stringXPath ) -{ - *stringXPath = expandedXPath[kRootPropStep].step; - - for ( size_t index = kRootPropStep+1; index < expandedXPath.size(); ++index ) { - const XPathStepInfo & currStep = expandedXPath[index]; - - switch ( currStep.options & kXMP_StepKindMask ) { - - case kXMP_StructFieldStep : - case kXMP_QualifierStep : - *stringXPath += '/'; - *stringXPath += currStep.step; - break; - - case kXMP_ArrayIndexStep : - case kXMP_ArrayLastStep : - case kXMP_QualSelectorStep : - case kXMP_FieldSelectorStep : - *stringXPath += currStep.step; - break; - - default: - XMP_Throw ( "Unexpected", kXMPErr_InternalFailure ); - - } - - } - -} // ComposeXPath - -// ================================================================================================= -// ExpandXPath -// =========== -// -// Split an XPath expression apart at the conceptual steps, adding the root namespace prefix to the -// first property component. The schema URI is put in the first (0th) slot in the expanded XPath. -// Check if the top level component is an alias, but don't resolve it. -// -// In the most verbose case steps are separated by '/', and each step can be of these forms: -// -// qualName A top level property or struct field. -// *[index] An element of an array. -// *[last()] The last element of an array. -// *[fieldName="value"] An element in an array of structs, chosen by a field value. -// *[@xml:lang="value"] An element in an alt-text array, chosen by the xml:lang qualifier. -// *[?qualName="value"] An element in an array, chosen by a qualifier value. -// @xml:lang An xml:lang qualifier. -// ?qualName A general qualifier. -// -// The logic is complicated though by shorthand for arrays, the separating '/' and leading '*' -// are optional. These are all equivalent: array/*[2] array/[2] array*[2] array[2] -// All of these are broken into the 2 steps "array" and "[2]". -// -// The value portion in the array selector forms is a string quoted by ''' or '"'. The value -// may contain any character including a doubled quoting character. The value may be empty. -// -// The syntax isn't checked, but an XML name begins with a letter or '_', and contains letters, -// digits, '.', '-', '_', and a bunch of special non-ASCII Unicode characters. An XML qualified -// name is a pair of names separated by a colon. - -void -ExpandXPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propPath, - XMP_ExpandedXPath * expandedXPath ) -{ - XMP_Assert ( (schemaNS != 0) && (propPath != 0) && (*propPath != 0) && (expandedXPath != 0) ); - - XMP_StringPtr stepBegin, stepEnd; - XMP_StringPtr qualName, nameEnd; - XMP_VarString currStep; - - qualName = nameEnd = NULL; - size_t resCount = 2; // Guess at the number of steps. At least 2, plus 1 for each '/' or '['. - for ( stepEnd = propPath; *stepEnd != 0; ++stepEnd ) { - if ( (*stepEnd == '/') || (*stepEnd == '[') ) ++resCount; - } - - expandedXPath->clear(); - expandedXPath->reserve ( resCount ); - - // ------------------------------------------------------------------------------------------- - // Pull out the first component and do some special processing on it: add the schema namespace - // prefix and see if it is an alias. The start must be a qualName. - - stepBegin = propPath; - stepEnd = stepBegin; - while ( (*stepEnd != 0) && (*stepEnd != '/') && (*stepEnd != '[') && (*stepEnd != '*') ) ++stepEnd; - if ( stepEnd == stepBegin ) XMP_Throw ( "Empty initial XPath step", kXMPErr_BadXPath ); - currStep.assign ( stepBegin, (stepEnd - stepBegin) ); - - VerifyXPathRoot ( schemaNS, currStep.c_str(), expandedXPath ); - - XMP_OptionBits stepFlags = kXMP_StructFieldStep; - if ( sRegisteredAliasMap->find ( (*expandedXPath)[kRootPropStep].step ) != sRegisteredAliasMap->end() ) { - stepFlags |= kXMP_StepIsAlias; - } - (*expandedXPath)[kRootPropStep].options |= stepFlags; - - // ----------------------------------------------------- - // Now continue to process the rest of the XPath string. - - while ( *stepEnd != 0 ) { - - stepBegin = stepEnd; - if ( *stepBegin == '/' ) ++stepBegin; - if ( *stepBegin == '*' ) { - ++stepBegin; - if ( *stepBegin != '[' ) XMP_Throw ( "Missing '[' after '*'", kXMPErr_BadXPath ); - } - stepEnd = stepBegin; - - if ( *stepBegin != '[' ) { - - // A struct field or qualifier. - qualName = stepBegin; - while ( (*stepEnd != 0) && (*stepEnd != '/') && (*stepEnd != '[') && (*stepEnd != '*') ) ++stepEnd; - nameEnd = stepEnd; - stepFlags = kXMP_StructFieldStep; // ! Touch up later, also changing '@' to '?'. - - } else { - - // One of the array forms. - - ++stepEnd; // Look at the character after the leading '['. - - if ( ('0' <= *stepEnd) && (*stepEnd <= '9') ) { - - // A numeric (decimal integer) array index. - while ( (*stepEnd != 0) && ('0' <= *stepEnd) && (*stepEnd <= '9') ) ++stepEnd; - if ( *stepEnd != ']' ) XMP_Throw ( "Missing ']' for integer array index", kXMPErr_BadXPath ); - stepFlags = kXMP_ArrayIndexStep; - - } else { - - // Could be "[last()]" or one of the selector forms. Find the ']' or '='. - - while ( (*stepEnd != 0) && (*stepEnd != ']') && (*stepEnd != '=') ) ++stepEnd; - if ( *stepEnd == 0 ) XMP_Throw ( "Missing ']' or '=' for array index", kXMPErr_BadXPath ); - - if ( *stepEnd == ']' ) { - - if ( strncmp ( "[last()", stepBegin, (stepEnd - stepBegin) ) != 0 ) { - XMP_Throw ( "Invalid non-numeric array index", kXMPErr_BadXPath ); - } - stepFlags = kXMP_ArrayLastStep; - - } else { - - qualName = stepBegin+1; - nameEnd = stepEnd; - ++stepEnd; // Absorb the '=', remember the quote. - const char quote = *stepEnd; - if ( (quote != '\'') && (quote != '"') ) { - XMP_Throw ( "Invalid quote in array selector", kXMPErr_BadXPath ); - } - - ++stepEnd; // Absorb the leading quote. - while ( *stepEnd != 0 ) { - if ( *stepEnd == quote ) { - if ( *(stepEnd+1) != quote ) break; - ++stepEnd; - } - ++stepEnd; - } - if ( *stepEnd == 0 ) { - XMP_Throw ( "No terminating quote for array selector", kXMPErr_BadXPath ); - } - ++stepEnd; // Absorb the trailing quote. - - stepFlags = kXMP_FieldSelectorStep; // ! Touch up later, also changing '@' to '?'. - - } - - } - - if ( *stepEnd != ']' ) XMP_Throw ( "Missing ']' for array index", kXMPErr_BadXPath ); - ++stepEnd; - - } - - if ( stepEnd == stepBegin ) XMP_Throw ( "Empty XPath step", kXMPErr_BadXPath ); - currStep.assign ( stepBegin, (stepEnd - stepBegin) ); - - if ( GetStepKind ( stepFlags ) == kXMP_StructFieldStep ) { - - if ( currStep[0] == '@' ) { - currStep[0] = '?'; - if ( currStep != "?xml:lang" ) XMP_Throw ( "Only xml:lang allowed with '@'", kXMPErr_BadXPath ); - } - if ( currStep[0] == '?' ) { - ++qualName; - stepFlags = kXMP_QualifierStep; - } - VerifyQualName ( qualName, nameEnd ); - - } else if ( GetStepKind ( stepFlags ) == kXMP_FieldSelectorStep ) { - - if ( currStep[1] == '@' ) { - currStep[1] = '?'; - if ( strncmp ( currStep.c_str(), "[?xml:lang=", 11 ) != 0 ) { - XMP_Throw ( "Only xml:lang allowed with '@'", kXMPErr_BadXPath ); - } - } - if ( currStep[1] == '?' ) { - ++qualName; - stepFlags = kXMP_QualSelectorStep; - } - VerifyQualName ( qualName, nameEnd ); - - } - - expandedXPath->push_back ( XPathStepInfo ( currStep, stepFlags ) ); - - } - -} // ExpandXPath - -// ================================================================================================= -// FindSchemaNode -// ============== -// -// Find or create a schema node. Returns a pointer to the node, and optionally an iterator for the -// node's position in the top level vector of schema nodes. The iterator is unchanged if no schema -// node (null) is returned. - -XMP_Node * -FindSchemaNode ( XMP_Node * xmpTree, - XMP_StringPtr nsURI, - bool createNodes, - XMP_NodePtrPos * ptrPos /* = 0 */ ) -{ - XMP_Node * schemaNode = 0; - - XMP_Assert ( xmpTree->parent == 0 ); - - for ( size_t schemaNum = 0, schemaLim = xmpTree->children.size(); schemaNum != schemaLim; ++schemaNum ) { - XMP_Node * currSchema = xmpTree->children[schemaNum]; - XMP_Assert ( currSchema->parent == xmpTree ); - if ( currSchema->name == nsURI ) { - schemaNode = currSchema; - if ( ptrPos != 0 ) *ptrPos = xmpTree->children.begin() + schemaNum; - break; - } - } - - if ( (schemaNode == 0) && createNodes ) { - - schemaNode = new XMP_Node ( xmpTree, nsURI, (kXMP_SchemaNode | kXMP_NewImplicitNode) ); - XMP_StringPtr prefixPtr; - XMP_StringLen prefixLen; - bool found = XMPMeta::GetNamespacePrefix ( nsURI, &prefixPtr, &prefixLen ); // *** Use map directly? - XMP_Assert ( found ); - UNUSED(found); - - schemaNode->value.assign ( prefixPtr, prefixLen ); - xmpTree->children.push_back ( schemaNode ); - if ( ptrPos != 0 ) *ptrPos = xmpTree->children.end() - 1; - - #if 0 // *** XMP_DebugBuild - schemaNode->_valuePtr = schemaNode->value.c_str(); - #endif - - } - - XMP_Assert ( (ptrPos == 0) || (schemaNode == 0) || (schemaNode == **ptrPos) ); - XMP_Assert ( (schemaNode != 0) || (! createNodes) ); - return schemaNode; - -} // FindSchemaNode - -// ================================================================================================= -// FindChildNode -// ============= -// -// Find or create a child node under a given parent node. Returns a pointer to the child node, and -// optionally an iterator for the node's position in the parent's vector of children. The iterator -// is unchanged if no child node (null) is returned. - -XMP_Node * -FindChildNode ( XMP_Node * parent, - XMP_StringPtr childName, - bool createNodes, - XMP_NodePtrPos * ptrPos /* = 0 */ ) -{ - XMP_Node * childNode = 0; - - if ( ! (parent->options & (kXMP_SchemaNode | kXMP_PropValueIsStruct)) ) { - if ( ! (parent->options & kXMP_NewImplicitNode) ) { - XMP_Throw ( "Named children only allowed for schemas and structs", kXMPErr_BadXPath ); - } - if ( parent->options & kXMP_PropValueIsArray ) { - XMP_Throw ( "Named children not allowed for arrays", kXMPErr_BadXPath ); - } - if ( ! createNodes ) { // *** Should be assert? If !createNodes, why is the parent a new implicit node? - XMP_Throw ( "Parent is new implicit node, but createNodes is false", kXMPErr_InternalFailure ); - } - parent->options |= kXMP_PropValueIsStruct; - } - - for ( size_t childNum = 0, childLim = parent->children.size(); childNum != childLim; ++childNum ) { - XMP_Node * currChild = parent->children[childNum]; - XMP_Assert ( currChild->parent == parent ); - if ( currChild->name == childName ) { - childNode = currChild; - if ( ptrPos != 0 ) *ptrPos = parent->children.begin() + childNum; - break; - } - } - - if ( (childNode == 0) && createNodes ) { - childNode = new XMP_Node ( parent, childName, kXMP_NewImplicitNode ); - parent->children.push_back ( childNode ); - if ( ptrPos != 0 ) *ptrPos = parent->children.end() - 1; - } - - XMP_Assert ( (ptrPos == 0) || (childNode == 0) || (childNode == **ptrPos) ); - XMP_Assert ( (childNode != 0) || (! createNodes) ); - return childNode; - -} // FindChildNode - -// ================================================================================================= -// FindQualifierNode -// ================= -// -// Find or create a qualifier node under a given parent node. Returns a pointer to the qualifier node, -// and optionally an iterator for the node's position in the parent's vector of qualifiers. The iterator -// is unchanged if no qualifier node (null) is returned. -// -// ! On entry, the qualName parameter must not have the leading '?' from the XPath step. - -XMP_Node * -FindQualifierNode ( XMP_Node * parent, - XMP_StringPtr qualName, - bool createNodes, - XMP_NodePtrPos * ptrPos /* = 0 */ ) // *** Require ptrPos internally & remove checks? -{ - XMP_Node * qualNode = 0; - - XMP_Assert ( *qualName != '?' ); - - for ( size_t qualNum = 0, qualLim = parent->qualifiers.size(); qualNum != qualLim; ++qualNum ) { - XMP_Node * currQual = parent->qualifiers[qualNum]; - XMP_Assert ( currQual->parent == parent ); - if ( currQual->name == qualName ) { - qualNode = currQual; - if ( ptrPos != 0 ) *ptrPos = parent->qualifiers.begin() + qualNum; - break; - } - } - - if ( (qualNode == 0) && createNodes ) { - - qualNode = new XMP_Node ( parent, qualName, (static_cast(kXMP_PropIsQualifier) | static_cast(kXMP_NewImplicitNode)) ); - parent->options |= kXMP_PropHasQualifiers; - - const bool isLang = XMP_LitMatch ( qualName, "xml:lang" ); - const bool isType = XMP_LitMatch ( qualName, "rdf:type" ); - const bool isSpecial = isLang | isType; - - if ( isLang ) { - parent->options |= kXMP_PropHasLang; - } else if ( isType ) { - parent->options |= kXMP_PropHasType; - } - - if ( parent->qualifiers.empty() || (! isSpecial) ) { - parent->qualifiers.push_back ( qualNode ); - if ( ptrPos != 0 ) *ptrPos = parent->qualifiers.end() - 1; - } else { - XMP_NodePtrPos insertPos = parent->qualifiers.begin(); // ! Lang goes first, type after. - if ( isType && (parent->options & kXMP_PropHasLang) ) ++insertPos; // *** Does insert at end() work? - insertPos = parent->qualifiers.insert ( insertPos, qualNode ); - if ( ptrPos != 0 ) *ptrPos = insertPos; - } - - } - - XMP_Assert ( (ptrPos == 0) || (qualNode == 0) || (qualNode == **ptrPos) ); - XMP_Assert ( (qualNode != 0) || (! createNodes) ); - return qualNode; - -} // FindQualifierNode - -// ================================================================================================= -// LookupFieldSelector -// =================== -// -// [fieldName="value"] An element in an array of structs, chosen by a field value. -// -// Note that we don't create implicit nodes for field selectors, so no CreateNodes parameter. - -XMP_Index -LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_StringPtr fieldValue ) -{ - XMP_Index index, itemLim; - - for ( index = 0, itemLim = arrayNode->children.size(); index != itemLim; ++index ) { - - const XMP_Node * currItem = arrayNode->children[index]; - XMP_Assert ( currItem->parent == arrayNode ); - - if ( ! (currItem->options & kXMP_PropValueIsStruct) ) { - XMP_Throw ( "Field selector must be used on array of struct", kXMPErr_BadXPath ); - } - - size_t f, fieldLim; - for ( f = 0, fieldLim = currItem->children.size(); f != fieldLim; ++f ) { - const XMP_Node * currField = currItem->children[f]; - XMP_Assert ( currField->parent == currItem ); - if ( currField->name != fieldName ) continue; - if ( currField->value == fieldValue ) break; // Exit qual loop. - } - if ( f != fieldLim ) break; // Exit child loop, found an item with a matching qualifier. - - } - - if ( index == itemLim ) index = -1; - return index; - -} // LookupFieldSelector - -// ================================================================================================= -// LookupLangItem -// ============== -// -// ! Assumes that the language value is already normalized. - -XMP_Index -LookupLangItem ( const XMP_Node * arrayNode, XMP_VarString & lang ) -{ - if ( ! (arrayNode->options & kXMP_PropValueIsArray) ) { // *** Check for alt-text? - XMP_Throw ( "Language item must be used on array", kXMPErr_BadXPath ); - } - - XMP_Index index = 0; - XMP_Index itemLim = arrayNode->children.size(); - - for ( ; index != itemLim; ++index ) { - const XMP_Node * currItem = arrayNode->children[index]; - XMP_Assert ( currItem->parent == arrayNode ); - if ( currItem->qualifiers.empty() || (currItem->qualifiers[0]->name != "xml:lang") ) continue; - if ( currItem->qualifiers[0]->value == lang ) break; - } - - if ( index == itemLim ) index = -1; - return index; - -} // LookupLangItem - -// ================================================================================================= -// 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. - -XMP_Node * -FindNode ( XMP_Node * xmpTree, - const XMP_ExpandedXPath & expandedXPath, - bool createNodes, - XMP_OptionBits leafOptions /* = 0 */, - XMP_NodePtrPos * ptrPos /* = 0 */ ) -{ - XMP_Node * currNode = 0; - XMP_NodePtrPos currPos; - XMP_NodePtrPos newSubPos; // Root of implicitly created subtree. Valid only if leaf is new. - bool leafIsNew = false; - - XMP_Assert ( (leafOptions == 0) || createNodes ); - - if ( expandedXPath.empty() ) XMP_Throw ( "Empty XPath", kXMPErr_BadXPath ); - - size_t stepNum = 1; // By default start calling FollowXPathStep for the top level property step. - size_t stepLim = expandedXPath.size(); - - // The start of processing deals with the schema node and top level alias. If the top level step - // is not an alias, lookup the expanded path's schema URI. Otherwise, lookup the expanded path - // for the actual. While tempting, don't substitute the actual's path into the local one, don't - // risk messing with the caller's use of that. Also don't call FindNode recursively, we need to - // keep track of the root of the implicitly created subtree as we move down the path. - - if ( ! (expandedXPath[kRootPropStep].options & kXMP_StepIsAlias) ) { - - currNode = FindSchemaNode ( xmpTree, expandedXPath[kSchemaStep].step.c_str(), createNodes, &currPos ); - if ( currNode == 0 ) return 0; - - if ( currNode->options & kXMP_NewImplicitNode ) { - currNode->options ^= kXMP_NewImplicitNode; // Clear the implicit node bit. - if ( ! leafIsNew ) newSubPos = currPos; // Save the top most implicit node. - leafIsNew = true; // If any parent is new, the leaf will be new also. - } - - } else { - - stepNum = 2; // ! Continue processing the original path at the second level step. - - XMP_AliasMapPos aliasPos = sRegisteredAliasMap->find ( expandedXPath[kRootPropStep].step ); - XMP_Assert ( aliasPos != sRegisteredAliasMap->end() ); - - currNode = FindSchemaNode ( xmpTree, aliasPos->second[kSchemaStep].step.c_str(), createNodes, &currPos ); - if ( currNode == 0 ) goto EXIT; - if ( currNode->options & kXMP_NewImplicitNode ) { - currNode->options ^= kXMP_NewImplicitNode; // Clear the implicit node bit. - if ( ! leafIsNew ) newSubPos = currPos; // Save the top most implicit node. - leafIsNew = true; // If any parent is new, the leaf will be new also. - } - - currNode = FollowXPathStep ( currNode, aliasPos->second, 1, createNodes, &currPos ); - if ( currNode == 0 ) goto EXIT; - if ( currNode->options & kXMP_NewImplicitNode ) { - currNode->options ^= kXMP_NewImplicitNode; // Clear the implicit node bit. - CheckImplicitStruct ( currNode, expandedXPath, 2, stepLim ); - if ( ! leafIsNew ) newSubPos = currPos; // Save the top most implicit node. - leafIsNew = true; // If any parent is new, the leaf will be new also. - } - - XMP_OptionBits arrayForm = aliasPos->second[kRootPropStep].options & kXMP_PropArrayFormMask; - XMP_Assert ( (arrayForm == 0) || (arrayForm & kXMP_PropValueIsArray) ); - XMP_Assert ( (arrayForm == 0) ? (aliasPos->second.size() == 2) : (aliasPos->second.size() == 3) ); - - if ( arrayForm != 0 ) { - currNode = FollowXPathStep ( currNode, aliasPos->second, 2, createNodes, &currPos, true ); - if ( currNode == 0 ) goto EXIT; - if ( currNode->options & kXMP_NewImplicitNode ) { - currNode->options ^= kXMP_NewImplicitNode; // Clear the implicit node bit. - CheckImplicitStruct ( currNode, expandedXPath, 2, stepLim ); - if ( ! leafIsNew ) newSubPos = currPos; // Save the top most implicit node. - leafIsNew = true; // If any parent is new, the leaf will be new also. - } - } - - } - - // Now follow the remaining steps of the original XPath. - - // *** ??? Change all the num/lim loops back to numoptions & kXMP_NewImplicitNode ) { - currNode->options ^= kXMP_NewImplicitNode; // Clear the implicit node bit. - CheckImplicitStruct ( currNode, expandedXPath, stepNum+1, stepLim ); - if ( ! leafIsNew ) newSubPos = currPos; // Save the top most implicit node. - leafIsNew = true; // If any parent is new, the leaf will be new also. - } - } - } catch ( ... ) { - if ( leafIsNew ) DeleteSubtree ( newSubPos ); - throw; - } - - // Done. Delete the implicitly created subtree if the eventual node was not found. - -EXIT: - - XMP_Assert ( (currNode == 0) || (currNode == *currPos) ); - XMP_Assert ( (currNode != 0) || (! createNodes) ); - - if ( leafIsNew ) { - if ( currNode != 0 ) { - currNode->options |= leafOptions; - } else { - DeleteSubtree ( newSubPos ); - } - } - - if ( (currNode != 0) && (ptrPos != 0) ) *ptrPos = currPos; - return currNode; - -} // FindNode - -// ================================================================================================= -// CloneOffspring -// ============== - -void -CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent ) -{ - size_t qualCount = origParent->qualifiers.size(); - size_t childCount = origParent->children.size(); - - if ( qualCount > 0 ) { - - cloneParent->qualifiers.reserve ( qualCount ); - - for ( size_t qualNum = 0, qualLim = qualCount; qualNum != qualLim; ++qualNum ) { - const XMP_Node * origQual = origParent->qualifiers[qualNum]; - XMP_Node * cloneQual = new XMP_Node ( cloneParent, origQual->name, origQual->value, origQual->options ); - CloneOffspring ( origQual, cloneQual ); - cloneParent->qualifiers.push_back ( cloneQual ); - } - - } - - if ( childCount > 0 ) { - - cloneParent->children.reserve ( childCount ); - - for ( size_t childNum = 0, childLim = childCount; childNum != childLim; ++childNum ) { - const XMP_Node * origChild = origParent->children[childNum]; - XMP_Node * cloneChild = new XMP_Node ( cloneParent, origChild->name, origChild->value, origChild->options ); - CloneOffspring ( origChild, cloneChild ); - cloneParent->children.push_back ( cloneChild ); - } - - } - -} // CloneOffspring - -// ================================================================================================= -// CloneSubtree -// ============ - -XMP_Node * -CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent ) -{ - #if XMP_DebugBuild - if ( cloneParent->parent == 0 ) { - XMP_Assert ( origRoot->options & kXMP_SchemaNode ); - XMP_Assert ( FindConstSchema ( cloneParent, origRoot->name.c_str() ) == 0 ); - } else { - XMP_Assert ( ! (origRoot->options & kXMP_SchemaNode) ); - if ( cloneParent->options & kXMP_PropValueIsStruct ) { // Might be an array. - XMP_Assert ( FindConstChild ( cloneParent, origRoot->name.c_str() ) == 0 ); - } - } - #endif - - XMP_Node * cloneRoot = new XMP_Node ( cloneParent, origRoot->name, origRoot->value, origRoot->options ); - CloneOffspring ( origRoot, cloneRoot ) ; - cloneParent->children.push_back ( cloneRoot ); - - return cloneRoot; - -} // CloneSubtree - -// ================================================================================================= -// 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 ( const XMP_Node & leftNode, const XMP_Node & rightNode ) -{ - // Don't compare the names here, we want to allow the outermost roots to have different names. - if ( (leftNode.value != rightNode.value) || - (leftNode.options != rightNode.options) || - (leftNode.children.size() != rightNode.children.size()) || - (leftNode.qualifiers.size() != rightNode.qualifiers.size()) ) return false; - - // Compare the qualifiers, allowing them to be out of order. - for ( size_t qualNum = 0, qualLim = leftNode.qualifiers.size(); qualNum != qualLim; ++qualNum ) { - const XMP_Node * leftQual = leftNode.qualifiers[qualNum]; - const XMP_Node * rightQual = FindConstQualifier ( &rightNode, leftQual->name.c_str() ); - if ( (rightQual == 0) || (! CompareSubtrees ( *leftQual, *rightQual )) ) return false; - } - - if ( (leftNode.parent == 0) || (leftNode.options & (kXMP_SchemaNode | kXMP_PropValueIsStruct)) ) { - - // The parent node is a tree root, a schema, or a struct. - for ( size_t childNum = 0, childLim = leftNode.children.size(); childNum != childLim; ++childNum ) { - const XMP_Node * leftChild = leftNode.children[childNum]; - const XMP_Node * rightChild = FindConstChild ( &rightNode, leftChild->name.c_str() ); - if ( (rightChild == 0) || (! CompareSubtrees ( *leftChild, *rightChild )) ) return false; - } - - } else if ( leftNode.options & kXMP_PropArrayIsAltText ) { - - // The parent node is an alt-text array. - for ( size_t childNum = 0, childLim = leftNode.children.size(); childNum != childLim; ++childNum ) { - const XMP_Node * leftChild = leftNode.children[childNum]; - XMP_Assert ( (! leftChild->qualifiers.empty()) && (leftChild->qualifiers[0]->name == "xml:lang") ); - XMP_Index rightIndex = LookupLangItem ( &rightNode, leftChild->qualifiers[0]->value ); - if ( rightIndex == -1 ) return false; - const XMP_Node * rightChild = rightNode.children[rightIndex]; - if ( ! CompareSubtrees ( *leftChild, *rightChild ) ) return false; - } - - } else { - - // The parent must be simple or some other (not alt-text) kind of array. - XMP_Assert ( (! (leftNode.options & kXMP_PropCompositeMask)) || (leftNode.options & kXMP_PropValueIsArray) ); - for ( size_t childNum = 0, childLim = leftNode.children.size(); childNum != childLim; ++childNum ) { - const XMP_Node * leftChild = leftNode.children[childNum]; - const XMP_Node * rightChild = rightNode.children[childNum]; - if ( ! CompareSubtrees ( *leftChild, *rightChild ) ) return false; - } - - } - - return true; - -} // CompareSubtrees - -// ================================================================================================= -// DeleteEmptySchema -// ================= - -void -DeleteEmptySchema ( XMP_Node * schemaNode ) -{ - - if ( XMP_NodeIsSchema ( schemaNode->options ) && schemaNode->children.empty() ) { - - XMP_Node * xmpTree = schemaNode->parent; - - size_t schemaNum = 0; - size_t schemaLim = xmpTree->children.size(); - while ( (schemaNum < schemaLim) && (xmpTree->children[schemaNum] != schemaNode) ) ++schemaNum; - XMP_Assert ( schemaNum < schemaLim ); - - XMP_NodePtrPos schemaPos = xmpTree->children.begin() + schemaNum; - XMP_Assert ( *schemaPos == schemaNode ); - - xmpTree->children.erase ( schemaPos ); - delete schemaNode; - - } - -} // DeleteEmptySchema - -// ================================================================================================= -// NormalizeLangValue -// ================== -// -// Normalize an xml:lang value so that comparisons are effectively case insensitive as required by -// RFC 3066 (which superceeds RFC 1766). The normalization rules: -// -// - The primary subtag is lower case, the suggested practice of ISO 639. -// - All 2 letter secondary subtags are upper case, the suggested practice of ISO 3166. -// - All other subtags are lower case. - -void -NormalizeLangValue ( XMP_VarString * value ) -{ - char * tagStart; - char * tagEnd; - - // Find and process the primary subtag. - - tagStart = (char*) value->c_str(); - for ( tagEnd = tagStart; (*tagEnd != 0) && (*tagEnd != '-'); ++tagEnd ) { - if ( ('A' <= *tagEnd) && (*tagEnd <= 'Z') ) *tagEnd += 0x20; - } - - // Find and process the secondary subtag. - - tagStart = tagEnd; - if ( *tagStart == '-' ) ++tagStart; - for ( tagEnd = tagStart; (*tagEnd != 0) && (*tagEnd != '-'); ++tagEnd ) { - if ( ('A' <= *tagEnd) && (*tagEnd <= 'Z') ) *tagEnd += 0x20; - } - if ( tagEnd == tagStart+2 ) { - if ( ('a' <= *tagStart) && (*tagStart <= 'z') ) *tagStart -= 0x20; - ++tagStart; - if ( ('a' <= *tagStart) && (*tagStart <= 'z') ) *tagStart -= 0x20; - } - - // Find and process the remaining subtags. - - while ( true ) { - tagStart = tagEnd; - if ( *tagStart == '-' ) ++tagStart; - if ( *tagStart == 0 ) break; - for ( tagEnd = tagStart; (*tagEnd != 0) && (*tagEnd != '-'); ++tagEnd ) { - if ( ('A' <= *tagEnd) && (*tagEnd <= 'Z') ) *tagEnd += 0x20; - } - } - -} // NormalizeLangValue - -// ================================================================================================= -// NormalizeLangArray -// ================== -// -// Make sure the x-default item is first. Touch up "single value" arrays that have a default plus -// one real language. This case should have the same value for both items. Older Adobe apps were -// hardwired to only use the 'x-default' item, so we copy that value to the other item. - -void -NormalizeLangArray ( XMP_Node * array ) -{ - XMP_Assert ( XMP_ArrayIsAltText(array->options) ); - - size_t itemNum; - size_t itemLim = array->children.size(); - bool hasDefault = false; - - for ( itemNum = 0; itemNum < itemLim; ++itemNum ) { - - if ( array->children[itemNum]->qualifiers.empty() || - (array->children[itemNum]->qualifiers[0]->name != "xml:lang") ) { - XMP_Throw ( "AltText array items must have an xml:lang qualifier", kXMPErr_BadXMP ); - } - - if ( array->children[itemNum]->qualifiers[0]->value == "x-default" ) { - hasDefault = true; - break; - } - - } - - if ( hasDefault ) { - - if ( itemNum != 0 ) { - XMP_Node * temp = array->children[0]; - array->children[0] = array->children[itemNum]; - array->children[itemNum] = temp; - } - -// 09-Oct-07, ahu: disabled to avoid unexpected behaviour -// if ( itemLim == 2 ) array->children[1]->value = array->children[0]->value; - - } - -} // NormalizeLangArray - -// ================================================================================================= -// DetectAltText -// ============= -// -// See if an array is an alt-text array. If so, make sure the x-default item is first. - -void -DetectAltText ( XMP_Node * xmpParent ) -{ - XMP_Assert ( XMP_ArrayIsAlternate(xmpParent->options) ); - - size_t itemNum, itemLim; - - for ( itemNum = 0, itemLim = xmpParent->children.size(); itemNum < itemLim; ++itemNum ) { - XMP_OptionBits currOptions = xmpParent->children[itemNum]->options; - if ( (currOptions & kXMP_PropCompositeMask) || (! (currOptions & kXMP_PropHasLang)) ) break; - } - - if ( (itemLim != 0) && (itemNum == itemLim) ) { - xmpParent->options |= kXMP_PropArrayIsAltText; - NormalizeLangArray ( xmpParent ); - } - -} // DetectAltText - -// ================================================================================================= -// SortNamedNodes -// ============== -// -// Sort the pointers in an XMP_NodeOffspring vector by name. - -static inline bool Compare ( const XMP_Node * left, const XMP_Node * right ) -{ - return (left->name < right->name); -} - -void -SortNamedNodes ( XMP_NodeOffspring & nodeVector ) -{ - sort ( nodeVector.begin(), nodeVector.end(), Compare ); -} // SortNamedNodes - -// ================================================================================================= diff --git a/xmpsdk/src/XMPCore_Impl.hpp b/xmpsdk/src/XMPCore_Impl.hpp deleted file mode 100644 index 3473c5dbc2..0000000000 --- a/xmpsdk/src/XMPCore_Impl.hpp +++ /dev/null @@ -1,534 +0,0 @@ -#ifndef __XMPCore_Impl_hpp__ -#define __XMPCore_Impl_hpp__ - -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! Must be the first #include! -#include "XMP_Const.h" -#include "XMP_BuildInfo.h" - -#include "client-glue/WXMPMeta.hpp" - -#include -#include -#include - -#include -#include - -#if XMP_WinBuild - #include -#else - // Use pthread for both Mac and generic UNIX. - #include -#endif - -#if XMP_WinBuild -# ifdef _MSC_VER - #pragma warning ( disable : 4244 ) // possible loss of data (temporary for 64 bit builds) - #pragma warning ( disable : 4267 ) // possible loss of data (temporary for 64 bit builds) -# endif -#endif - -// ================================================================================================= -// Primary internal types - -class XMP_Node; -class XML_Node; -class XPathStepInfo; - -typedef XMP_Node * XMP_NodePtr; - -typedef std::vector XMP_NodeOffspring; -typedef XMP_NodeOffspring::iterator XMP_NodePtrPos; - -typedef std::string XMP_VarString; -typedef XMP_VarString::iterator XMP_VarStringPos; -typedef XMP_VarString::const_iterator XMP_cVarStringPos; - -typedef std::pair < XMP_VarString, XMP_VarString > XMP_StringPair; - -typedef std::map < XMP_VarString, XMP_VarString > XMP_StringMap; -typedef XMP_StringMap::iterator XMP_StringMapPos; -typedef XMP_StringMap::const_iterator XMP_cStringMapPos; - -typedef std::vector < XPathStepInfo > XMP_ExpandedXPath; -typedef XMP_ExpandedXPath::iterator XMP_ExpandedXPathPos; -typedef XMP_ExpandedXPath::const_iterator XMP_cExpandedXPathPos; - -typedef std::map < XMP_VarString, XMP_ExpandedXPath > XMP_AliasMap; // Alias name to actual path. -typedef XMP_AliasMap::iterator XMP_AliasMapPos; -typedef XMP_AliasMap::const_iterator XMP_cAliasMapPos; - -// ================================================================================================= -// General global variables and macros - -extern XMP_Int32 sXMP_InitCount; - -extern XMP_AliasMap * sRegisteredAliasMap; - -extern XMP_StringMap * sNamespaceURIToPrefixMap; -extern XMP_StringMap * sNamespacePrefixToURIMap; - -extern XMP_VarString * sOutputNS; -extern XMP_VarString * sOutputStr; - -extern void * voidVoidPtr; // Used to backfill null output parameters. -extern XMP_StringPtr voidStringPtr; -extern XMP_StringLen voidStringLen; -extern XMP_OptionBits voidOptionBits; -extern XMP_Bool voidByte; -extern bool voidBool; -extern XMP_Int32 voidInt32; -extern XMP_Int64 voidInt64; -extern double voidDouble; -extern XMP_DateTime voidDateTime; -extern WXMP_Result void_wResult; - -#define kHexDigits "0123456789ABCDEF" - -#define XMP_LitMatch(s,l) (std::strcmp((s),(l)) == 0) -#define XMP_LitNMatch(s,l,n) (std::strncmp((s),(l),(n)) == 0) - // *** Use the above macros! - -#define kTab ((char)0x09) -#define kLF ((char)0x0A) -#define kCR ((char)0x0D) - -#if XMP_WinBuild - #define snprintf _snprintf -#endif - -#define WtoXMPMeta_Ref(xmpRef) *((const XMPMeta *)(xmpRef)) -#define WtoXMPMeta_Ptr(xmpRef) (((xmpRef) == 0) ? 0 : (XMPMeta *)(xmpRef)) - -#define WtoXMPIterator_Ref(iterRef) *((const XMPIterator *)(iterRef)) -#define WtoXMPIterator_Ptr(iterRef) (((iterRef) == 0) ? 0 : (XMPIterator *)(iterRef)) - -#define WtoXMPDocOps_Ref(docRef) *((const XMPDocOps *)(docRef)) -#define WtoXMPDocOps_Ptr(docRef) (((docRef) == 0) ? 0 : (XMPDocOps *)(docRef)) - -#define IgnoreParam(p) (void)p - -// ================================================================================================= -// Version info - -#if XMP_DebugBuild - #define kXMPCore_DebugFlag 1 -#else - #define kXMPCore_DebugFlag 0 -#endif - -#define kXMPCore_VersionNumber ( (kXMPCore_DebugFlag << 31) | \ - (XMP_API_VERSION_MAJOR << 24) | \ - (XMP_API_VERSION_MINOR << 16) | \ - (XMP_API_VERSION_MICRO << 8) ) - - #define kXMPCoreName "XMP Core" - #define kXMPCore_VersionMessage kXMPCoreName " " XMP_API_VERSION_STRING -// ================================================================================================= -// Support for asserts - -#define _MakeStr(p) #p -#define _NotifyMsg(n,c,f,l) #n " failed: " #c " in " f " at line " _MakeStr(l) - -#if ! XMP_DebugBuild - #define XMP_Assert(c) ((void) 0) -#else - #define XMP_Assert(c) assert ( c ) -#endif - - #define XMP_Enforce(c) \ - if ( ! (c) ) { \ - const char * assert_msg = _NotifyMsg ( XMP_Enforce, (c), __FILE__, __LINE__ ); \ - XMP_Throw ( assert_msg , kXMPErr_EnforceFailure ); \ - } -// ================================================================================================= -// Support for exceptions and thread locking - -#ifndef TraceXMPCalls - #define TraceXMPCalls 0 -#endif - -#if ! TraceXMPCalls - - #define AnnounceThrow(msg) /* Do nothing. */ - #define AnnounceCatch(msg) /* Do nothing. */ - - #define AnnounceEntry(proc) /* Do nothing. */ - #define AnnounceNoLock(proc) /* Do nothing. */ - #define AnnounceExit() /* Do nothing. */ - - #define ReportLock() ++sLockCount - #define ReportUnlock() --sLockCount - #define ReportKeepLock() /* Do nothing. */ - -#else - - extern FILE * xmpCoreOut; - - #define AnnounceThrow(msg) \ - fprintf ( xmpCoreOut, "XMP_Throw: %s\n", msg ); fflush ( xmpOut ) - #define AnnounceCatch(msg) \ - fprintf ( xmpCoreOut, "Catch in %s: %s\n", procName, msg ); fflush ( xmpOut ) - - #define AnnounceEntry(proc) \ - const char * procName = proc; \ - fprintf ( xmpCoreOut, "Entering %s\n", procName ); fflush ( xmpOut ) - #define AnnounceNoLock(proc) \ - const char * procName = proc; \ - fprintf ( xmpCoreOut, "Entering %s (no lock)\n", procName ); fflush ( xmpOut ) - #define AnnounceExit() \ - fprintf ( xmpCoreOut, "Exiting %s\n", procName ); fflush ( xmpOut ) - - #define ReportLock() \ - ++sLockCount; fprintf ( xmpCoreOut, " Auto lock, count = %d\n", sLockCount ); fflush ( xmpOut ) - #define ReportUnlock() \ - --sLockCount; fprintf ( xmpCoreOut, " Auto unlock, count = %d\n", sLockCount ); fflush ( xmpOut ) - #define ReportKeepLock() \ - fprintf ( xmpCoreOut, " Keeping lock, count = %d\n", sLockCount ); fflush ( xmpOut ) - -#endif - -#define XMP_Throw(msg,id) { AnnounceThrow ( msg ); throw XMP_Error ( id, msg ); } - -// ------------------------------------------------------------------------------------------------- - -#if XMP_WinBuild - typedef CRITICAL_SECTION XMP_Mutex; -#else - // Use pthread for both Mac and generic UNIX. - typedef pthread_mutex_t XMP_Mutex; -#endif - -extern XMP_Mutex sXMPCoreLock; -extern int sLockCount; // Keep signed to catch unlock errors. -extern XMP_VarString * sExceptionMessage; - -extern bool XMP_InitMutex ( XMP_Mutex * mutex ); -extern void XMP_TermMutex ( XMP_Mutex & mutex ); - -extern void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ); -extern void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ); - -class XMP_AutoMutex { -public: - XMP_AutoMutex() : mutex(&sXMPCoreLock) { XMP_EnterCriticalRegion ( *mutex ); ReportLock(); }; - ~XMP_AutoMutex() { if ( mutex != 0 ) { ReportUnlock(); XMP_ExitCriticalRegion ( *mutex ); mutex = 0; } }; - void KeepLock() { ReportKeepLock(); mutex = 0; }; -private: - XMP_Mutex * mutex; -}; - -// *** Switch to XMPEnterObjectWrapper & XMPEnterStaticWrapper, to allow for per-object locks. - -// ! Don't do the initialization check (sXMP_InitCount > 0) for the no-lock case. That macro is used -// ! by WXMPMeta_Initialize_1. - -#define XMP_ENTER_WRAPPER_NO_LOCK(proc) \ - AnnounceNoLock ( proc ); \ - XMP_Assert ( (0 <= sLockCount) && (sLockCount <= 1) ); \ - try { \ - wResult->errMessage = 0; - -#define XMP_ENTER_WRAPPER(proc) \ - AnnounceEntry ( proc ); \ - XMP_Assert ( sXMP_InitCount > 0 ); \ - XMP_Assert ( (0 <= sLockCount) && (sLockCount <= 1) ); \ - try { \ - XMP_AutoMutex mutex; \ - wResult->errMessage = 0; - -#define XMP_EXIT_WRAPPER \ - XMP_CATCH_EXCEPTIONS \ - AnnounceExit(); - -#define XMP_EXIT_WRAPPER_KEEP_LOCK(keep) \ - if ( keep ) mutex.KeepLock(); \ - XMP_CATCH_EXCEPTIONS \ - AnnounceExit(); - -#define XMP_EXIT_WRAPPER_NO_THROW \ - } catch ( ... ) { \ - AnnounceCatch ( "no-throw catch-all" ); \ - /* Do nothing. */ \ - } \ - AnnounceExit(); - -#define XMP_CATCH_EXCEPTIONS \ - } catch ( XMP_Error & xmpErr ) { \ - wResult->int32Result = xmpErr.GetID(); \ - wResult->ptrResult = (void*)"XMP"; \ - wResult->errMessage = xmpErr.GetErrMsg(); \ - if ( wResult->errMessage == 0 ) wResult->errMessage = ""; \ - AnnounceCatch ( wResult->errMessage ); \ - } catch ( std::exception & stdErr ) { \ - wResult->int32Result = kXMPErr_StdException; \ - wResult->errMessage = stdErr.what(); \ - if ( wResult->errMessage == 0 ) wResult->errMessage = ""; \ - AnnounceCatch ( wResult->errMessage ); \ - } catch ( ... ) { \ - wResult->int32Result = kXMPErr_UnknownException; \ - wResult->errMessage = "Caught unknown exception"; \ - AnnounceCatch ( wResult->errMessage ); \ - } - -#if XMP_DebugBuild - #define RELEASE_NO_THROW /* empty */ -#else - #define RELEASE_NO_THROW throw() -#endif - -// ================================================================================================= -// ExpandXPath, FindNode, and related support - -// *** Normalize the use of "const xx &" for input params - -#define kXMP_ArrayItemName "[]" - -#define kXMP_CreateNodes true -#define kXMP_ExistingOnly false - -#define FindConstSchema(t,u) FindSchemaNode ( const_cast(t), u, kXMP_ExistingOnly, 0 ) -#define FindConstChild(p,c) FindChildNode ( const_cast(p), c, kXMP_ExistingOnly, 0 ) -#define FindConstQualifier(p,c) FindQualifierNode ( const_cast(p), c, kXMP_ExistingOnly, 0 ) -#define FindConstNode(t,p) FindNode ( const_cast(t), p, kXMP_ExistingOnly, 0 ) - -extern XMP_OptionBits -VerifySetOptions ( XMP_OptionBits options, XMP_StringPtr propValue ); - -extern void -ComposeXPath ( const XMP_ExpandedXPath & expandedXPath, - XMP_VarString * stringXPath ); - -extern void -ExpandXPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propPath, - XMP_ExpandedXPath * expandedXPath ); - -extern XMP_Node * -FindSchemaNode ( XMP_Node * xmpTree, - XMP_StringPtr nsURI, - bool createNodes, - XMP_NodePtrPos * ptrPos = 0 ); - -extern XMP_Node * -FindChildNode ( XMP_Node * parent, - XMP_StringPtr childName, - bool createNodes, - XMP_NodePtrPos * ptrPos = 0 ); - -extern XMP_Node * -FindQualifierNode ( XMP_Node * parent, - XMP_StringPtr qualName, - bool createNodes, - XMP_NodePtrPos * ptrPos = 0 ); - -extern XMP_Node * -FindNode ( XMP_Node * xmpTree, - const XMP_ExpandedXPath & expandedXPath, - bool createNodes, - XMP_OptionBits leafOptions = 0, - XMP_NodePtrPos * ptrPos = 0 ); - -extern XMP_Index -LookupLangItem ( const XMP_Node * arrayNode, XMP_VarString & lang ); // ! Lang must be normalized! - -extern XMP_Index -LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_StringPtr fieldValue ); - -extern void -CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent ); - -extern XMP_Node * -CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent ); - -extern bool -CompareSubtrees ( const XMP_Node & leftNode, const XMP_Node & rightNode ); - -extern void -DeleteEmptySchema ( XMP_Node * schemaNode ); - -extern void -NormalizeLangValue ( XMP_VarString * value ); - -extern void -NormalizeLangArray ( XMP_Node * array ); - -extern void -DetectAltText ( XMP_Node * xmpParent ); - -extern void -SortNamedNodes ( XMP_NodeOffspring & nodeVector ); - -static inline bool -IsPathPrefix ( XMP_StringPtr fullPath, XMP_StringPtr prefix ) -{ - bool isPrefix = false; - XMP_StringLen prefixLen = std::strlen(prefix); - if ( XMP_LitNMatch ( prefix, fullPath, prefixLen ) ) { - char separator = fullPath[prefixLen]; - if ( (separator == 0) || (separator == '/') || - (separator == '[') || (separator == '*') ) isPrefix = true; - } - return isPrefix; -} - -// ------------------------------------------------------------------------------------------------- - -class XPathStepInfo { -public: - XMP_VarString step; - XMP_OptionBits options; - XPathStepInfo ( XMP_StringPtr _step, XMP_OptionBits _options ) : step(_step), options(_options) {}; - XPathStepInfo ( XMP_VarString _step, XMP_OptionBits _options ) : step(_step), options(_options) {}; -private: - XPathStepInfo() : options(0) {}; // ! Hide the default constructor. -}; - -enum { kSchemaStep = 0, kRootPropStep = 1, kAliasIndexStep = 2 }; - -enum { // Bits for XPathStepInfo options. // *** Add mask check to init code. - kXMP_StepKindMask = 0x0F, // ! The step kinds are mutually exclusive numbers. - kXMP_StructFieldStep = 0x01, // Also for top level nodes (schema "fields"). - kXMP_QualifierStep = 0x02, // ! Order is significant to separate struct/qual from array kinds! - kXMP_ArrayIndexStep = 0x03, // ! The kinds must not overlay array form bits! - kXMP_ArrayLastStep = 0x04, - kXMP_QualSelectorStep = 0x05, - kXMP_FieldSelectorStep = 0x06, - kXMP_StepIsAlias = 0x10 -}; - -#define GetStepKind(f) ((f) & kXMP_StepKindMask) - -#define kXMP_NewImplicitNode kXMP_InsertAfterItem - -// ================================================================================================= -// XMP_Node details - -#if 0 // Pattern for iterating over the children or qualifiers: - for ( size_t xxNum = 0, xxLim = _node_->_offspring_.size(); xxNum < xxLim; ++xxNum ) { - const XMP_Node * _curr_ = _node_->_offspring_[xxNum]; - } -#endif - -class XMP_Node { -public: - - XMP_OptionBits options; - XMP_VarString name, value; - XMP_Node * parent; - XMP_NodeOffspring children; - XMP_NodeOffspring qualifiers; - #if XMP_DebugBuild - // *** XMP_StringPtr _namePtr, _valuePtr; // *** Not working, need operator=? - #endif - - XMP_Node ( XMP_Node * _parent, XMP_StringPtr _name, XMP_OptionBits _options ) - : options(_options), name(_name), parent(_parent) - { - #if XMP_DebugBuild - XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) || - (options & kXMP_SchemaNode) || (parent == 0) ); - // *** _namePtr = name.c_str(); - // *** _valuePtr = value.c_str(); - #endif - }; - - XMP_Node ( XMP_Node * _parent, const XMP_VarString & _name, XMP_OptionBits _options ) - : options(_options), name(_name), parent(_parent) - { - #if XMP_DebugBuild - XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) || - (options & kXMP_SchemaNode) || (parent == 0) ); - // *** _namePtr = name.c_str(); - // *** _valuePtr = value.c_str(); - #endif - }; - - XMP_Node ( XMP_Node * _parent, XMP_StringPtr _name, XMP_StringPtr _value, XMP_OptionBits _options ) - : options(_options), name(_name), value(_value), parent(_parent) - { - #if XMP_DebugBuild - XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) || - (options & kXMP_SchemaNode) || (parent == 0) ); - // *** _namePtr = name.c_str(); - // *** _valuePtr = value.c_str(); - #endif - }; - - XMP_Node ( XMP_Node * _parent, const XMP_VarString & _name, const XMP_VarString & _value, XMP_OptionBits _options ) - : options(_options), name(_name), value(_value), parent(_parent) - { - #if XMP_DebugBuild - XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) || - (options & kXMP_SchemaNode) || (parent == 0) ); - // *** _namePtr = name.c_str(); - // *** _valuePtr = value.c_str(); - #endif - }; - - void RemoveChildren() - { - for ( size_t i = 0, vLim = children.size(); i < vLim; ++i ) { - if ( children[i] != 0 ) delete children[i]; - } - children.clear(); - } - - void RemoveQualifiers() - { - for ( size_t i = 0, vLim = qualifiers.size(); i < vLim; ++i ) { - if ( qualifiers[i] != 0 ) delete qualifiers[i]; - } - qualifiers.clear(); - } - - void ClearNode() - { - options = 0; - name.erase(); - value.erase(); - this->RemoveChildren(); - this->RemoveQualifiers(); - } - - virtual ~XMP_Node() { RemoveChildren(); RemoveQualifiers(); }; - -private: - XMP_Node() : options(0), parent(0) // ! Make sure parent pointer is always set. - { - #if XMP_DebugBuild - // *** _namePtr = name.c_str(); - // *** _valuePtr = value.c_str(); - #endif - }; - -}; - -class XMP_AutoNode { // Used to hold a child during subtree construction. -public: - XMP_Node * nodePtr; - XMP_AutoNode() : nodePtr(0) {}; - ~XMP_AutoNode() { if ( nodePtr != 0 ) delete ( nodePtr ); nodePtr = 0; }; - XMP_AutoNode ( XMP_Node * _parent, XMP_StringPtr _name, XMP_OptionBits _options ) - : nodePtr ( new XMP_Node ( _parent, _name, _options ) ) {}; - XMP_AutoNode ( XMP_Node * _parent, const XMP_VarString & _name, XMP_OptionBits _options ) - : nodePtr ( new XMP_Node ( _parent, _name, _options ) ) {}; - XMP_AutoNode ( XMP_Node * _parent, XMP_StringPtr _name, XMP_StringPtr _value, XMP_OptionBits _options ) - : nodePtr ( new XMP_Node ( _parent, _name, _value, _options ) ) {}; - XMP_AutoNode ( XMP_Node * _parent, const XMP_VarString & _name, const XMP_VarString & _value, XMP_OptionBits _options ) - : nodePtr ( new XMP_Node ( _parent, _name, _value, _options ) ) {}; -}; - -extern void ProcessRDF ( XMP_Node * xmpTree, const XML_Node & xmlTree, XMP_OptionBits options ); - -// ================================================================================================= - -#endif // __XMPCore_Impl_hpp__ diff --git a/xmpsdk/src/XMPIterator.cpp b/xmpsdk/src/XMPIterator.cpp deleted file mode 100644 index ea39602a5c..0000000000 --- a/xmpsdk/src/XMPIterator.cpp +++ /dev/null @@ -1,736 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2007 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPIterator.hpp" - -#include -#include // For snprintf. - -#if XMP_WinBuild - #ifdef _MSC_VER - #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 -#endif - -// ================================================================================================= -// Support Routines -// ================================================================================================= - - -#ifndef TraceIterators - #define TraceIterators 0 -#endif - -#if TraceIterators - static const char * sStageNames[] = { "before", "self", "qualifiers", "children" }; -#endif - -static XMP_Node * sDummySchema = 0; // ! Used for some ugliness with aliases. - -// ------------------------------------------------------------------------------------------------- -// AddSchemaProps -// -------------- -// -// Add the top level properties to the IterNode for a schema. - -static void -AddSchemaProps ( IterInfo & info, IterNode & iterSchema, const XMP_Node * xmpSchema ) -{ - UNUSED(info); - #if TraceIterators - printf ( " Adding properties of %s\n", xmpSchema->name.c_str() ); - #endif - - for ( size_t propNum = 0, propLim = xmpSchema->children.size(); propNum != propLim; ++propNum ) { - const XMP_Node * xmpProp = xmpSchema->children[propNum]; - // *** set the has-aliases bit when appropriate - iterSchema.children.push_back ( IterNode ( xmpProp->options, xmpProp->name, 0 ) ); - #if TraceIterators - printf ( " %s\n", xmpProp->name.c_str() ); - #endif - } - -} // AddSchemaProps - -// ------------------------------------------------------------------------------------------------- -// AddSchemaAliases -// ---------------- -// -// Add the aliases to the IterNode for a schema, if the corresponding actual exists. - -static void -AddSchemaAliases ( IterInfo & info, IterNode & iterSchema, XMP_StringPtr schemaURI ) -{ - - // We're showing the aliases also. Look them up by their namespace prefix. Yes, the alias map is - // sorted so we could process just that portion. But that takes more code and the extra speed - // isn't worth it. (Plus this way we avoid a dependence on the map implementation.) Lookup the - // XMP node from the alias, to make sure the actual exists. - - #if TraceIterators - printf ( " Adding aliases\n", schemaURI ); - #endif - - XMP_StringPtr nsPrefix; - XMP_StringLen nsLen; - bool found = XMPMeta::GetNamespacePrefix ( schemaURI, &nsPrefix, &nsLen ); - if ( ! found ) XMP_Throw ( "Unknown iteration namespace", kXMPErr_BadSchema ); - - XMP_AliasMapPos currAlias = sRegisteredAliasMap->begin(); - XMP_AliasMapPos endAlias = sRegisteredAliasMap->end(); - - for ( ; currAlias != endAlias; ++currAlias ) { - if ( XMP_LitNMatch ( currAlias->first.c_str(), nsPrefix, nsLen ) ) { - const XMP_Node * actualProp = FindConstNode ( &info.xmpObj->tree, currAlias->second ); - if ( actualProp != 0 ) { - iterSchema.children.push_back ( IterNode ( (actualProp->options | kXMP_PropIsAlias), currAlias->first, 0 ) ); - #if TraceIterators - printf ( " %s => %s\n", currAlias->first.c_str(), actualProp->name.c_str() ); - #endif - } - } - } - -} // AddSchemaAliases - -// ------------------------------------------------------------------------------------------------- -// AddNodeOffspring -// ---------------- -// -// Add the immediate children and qualifiers to an IterNode. - -static void -AddNodeOffspring ( IterInfo & info, IterNode & iterParent, const XMP_Node * xmpParent ) -{ - XMP_VarString currPath ( iterParent.fullPath ); - size_t leafOffset = iterParent.fullPath.size(); - - if ( (! xmpParent->qualifiers.empty()) && (! (info.options & kXMP_IterOmitQualifiers)) ) { - - #if TraceIterators - printf ( " Adding qualifiers of %s\n", currPath.c_str() ); - #endif - - currPath += "/?"; // All qualifiers are named and use paths like "Prop/?Qual". - leafOffset += 2; - - for ( size_t qualNum = 0, qualLim = xmpParent->qualifiers.size(); qualNum != qualLim; ++qualNum ) { - const XMP_Node * xmpQual = xmpParent->qualifiers[qualNum]; - currPath += xmpQual->name; - iterParent.qualifiers.push_back ( IterNode ( xmpQual->options, currPath, leafOffset ) ); - currPath.erase ( leafOffset ); - #if TraceIterators - printf ( " %s\n", xmpQual->name.c_str() ); - #endif - } - - leafOffset -= 2; - currPath.erase ( leafOffset ); - - } - - if ( ! xmpParent->children.empty() ) { - - #if TraceIterators - printf ( " Adding children of %s\n", currPath.c_str() ); - #endif - - XMP_Assert ( xmpParent->options & kXMP_PropCompositeMask ); - - if ( xmpParent->options & kXMP_PropValueIsStruct ) { - currPath += '/'; - leafOffset += 1; - } - - for ( size_t childNum = 0, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) { - const XMP_Node * xmpChild = xmpParent->children[childNum]; - if ( ! (xmpParent->options & kXMP_PropValueIsArray) ) { - currPath += xmpChild->name; - } else { - char buffer [32]; // AUDIT: Using sizeof(buffer) below for snprintf length is safe. - snprintf ( buffer, sizeof(buffer), "[%lu]", static_cast(childNum+1) ); // ! XPath indices are one-based. - currPath += buffer; - } - iterParent.children.push_back ( IterNode ( xmpChild->options, currPath, leafOffset ) ); - currPath.erase ( leafOffset ); - #if TraceIterators - printf ( " %s\n", (iterParent.children.back().fullPath.c_str() + leafOffset) ); - #endif - } - - } - -} // AddNodeOffspring - -// ------------------------------------------------------------------------------------------------- -// SetCurrSchema -// ------------- - -static inline void -SetCurrSchema ( IterInfo & info, XMP_StringPtr schemaName ) -{ - - info.currSchema = schemaName; - #if 0 // *** XMP_DebugBuild - info._schemaPtr = info.currSchema.c_str(); - #endif - -} // SetCurrSchema - -static inline void -SetCurrSchema ( IterInfo & info, XMP_VarString & schemaName ) -{ - - info.currSchema = schemaName; - #if 0 // *** XMP_DebugBuild - info._schemaPtr = info.currSchema.c_str(); - #endif - -} // SetCurrSchema - -// ------------------------------------------------------------------------------------------------- -// AdvanceIterPos -// -------------- -// -// Adjust currPos and possibly endPos for the next step in a pre-order depth-first traversal. The -// current node has just been visited, move on to its qualifiers, children, then siblings, or back -// up to an ancestor. AdvanceIterPos either moves to a property or qualifier node that can be -// visited, or to the end of the entire iteration. - -static void -AdvanceIterPos ( IterInfo & info ) -{ - // ------------------------------------------------------------------------------------------- - // Keep looking until we find a node to visit or the end of everything. The first time through - // the current node will exist, we just visited it. But we have to keep looking if the current - // node was the last of its siblings or is an empty schema. - - // ! It is possible that info.currPos == info.endPos on entry. Don't dereference info.currPos yet! - - while ( true ) { - - if ( info.currPos == info.endPos ) { - - // ------------------------------------------------------------------------------------ - // At the end of a set of siblings, move up to an ancestor. We've either just finished - // the qualifiers and will move to the children, or have just finished the children and - // will move on to the next sibling. - - if ( info.ancestors.empty() ) break; // We're at the end of the schema list. - - IterPosPair & parent = info.ancestors.back(); - info.currPos = parent.first; - info.endPos = parent.second; - info.ancestors.pop_back(); - - #if TraceIterators - printf ( " Moved up to %s, stage = %s\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] ); - #endif - - } else { - - // ------------------------------------------------------------------------------------------- - // Decide what to do with this iteration node based on its state. Don't use a switch statement, - // some of the cases want to break from the loop. A break in a switch just exits the case. - - #if TraceIterators - printf ( " Moving from %s, stage = %s\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] ); - #endif - - if ( info.currPos->visitStage == kIter_BeforeVisit ) { // Visit this node now. - if ( info.currPos->options & kXMP_SchemaNode ) SetCurrSchema ( info, info.currPos->fullPath ); - break; - } - - if ( info.currPos->visitStage == kIter_VisitSelf ) { // Just finished visiting the value portion. - info.currPos->visitStage = kIter_VisitQualifiers; // Start visiting the qualifiers. - if ( ! info.currPos->qualifiers.empty() ) { - info.ancestors.push_back ( IterPosPair ( info.currPos, info.endPos ) ); - info.endPos = info.currPos->qualifiers.end(); // ! Set the parent's endPos before changing currPos! - info.currPos = info.currPos->qualifiers.begin(); - break; - } - } - - if ( info.currPos->visitStage == kIter_VisitQualifiers ) { // Just finished visiting the qualifiers. - info.currPos->qualifiers.clear(); - info.currPos->visitStage = kIter_VisitChildren; // Start visiting the children. - if ( ! info.currPos->children.empty() ) { - info.ancestors.push_back ( IterPosPair ( info.currPos, info.endPos ) ); - info.endPos = info.currPos->children.end(); // ! Set the parent's endPos before changing currPos! - info.currPos = info.currPos->children.begin(); - break; - } - } - - if ( info.currPos->visitStage == kIter_VisitChildren ) { // Just finished visiting the children. - info.currPos->children.clear(); - ++info.currPos; // Move to the next sibling. - continue; - } - - #if TraceIterators - if ( info.currPos != info.endPos ) { - printf ( " Moved to %s, stage = %s\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] ); - } - #endif - - } - - } // Loop to find the next node. - - XMP_Assert ( (info.currPos == info.endPos) || (info.currPos->visitStage == kIter_BeforeVisit) ); - -} // AdvanceIterPos - -// ------------------------------------------------------------------------------------------------- -// GetNextXMPNode -// -------------- -// -// Used by XMPIterator::Next to obtain the next XMP node, ignoring the kXMP_IterJustLeafNodes flag. -// This isolates some messy code, allowing a clean loop in Next if kXMP_IterJustLeafNodes is set. - -static const XMP_Node * -GetNextXMPNode ( IterInfo & info ) -{ - const XMP_Node * xmpNode = 0; - - // ---------------------------------------------------------------------------------------------- - // On entry currPos points to an iteration node whose state is either before-visit or visit-self. - // If it is before-visit then we will return that node's value part now. If it is visit-self it - // means the previous iteration returned the value portion of that node, so we can advance to the - // next node in the iteration tree. Then we find the corresponding XMP node, allowing for the XMP - // tree to have been modified since that part of the iteration tree was constructed. - - // ! NOTE: Supporting aliases throws in some nastiness with schemas. There might not be any XMP - // ! node for the schema, but we still have to visit it because of possible aliases. The static - // ! sDummySchema is returned if there is no real schema node. - - if ( info.currPos->visitStage != kIter_BeforeVisit ) AdvanceIterPos ( info ); - - bool isSchemaNode = false; - XMP_ExpandedXPath expPath; // Keep outside the loop to avoid constant construct/destruct. - - while ( info.currPos != info.endPos ) { - - isSchemaNode = XMP_NodeIsSchema ( info.currPos->options ); - if ( isSchemaNode ) { - SetCurrSchema ( info, info.currPos->fullPath ); - xmpNode = FindConstSchema ( &info.xmpObj->tree, info.currPos->fullPath.c_str() ); - if ( xmpNode == 0 ) xmpNode = sDummySchema; - } else { - ExpandXPath ( info.currSchema.c_str(), info.currPos->fullPath.c_str(), &expPath ); - xmpNode = FindConstNode ( &info.xmpObj->tree, expPath ); - } - if ( xmpNode != 0 ) break; // Exit the loop, we found a live XMP node. - - info.currPos->visitStage = kIter_VisitChildren; // Make AdvanceIterPos move to the next sibling. - info.currPos->children.clear(); - info.currPos->qualifiers.clear(); - AdvanceIterPos ( info ); - - } - - if ( info.currPos == info.endPos ) return 0; - - // ------------------------------------------------------------------------------------------- - // Now we've got the iteration node and corresponding XMP node. Add the iteration children for - // structs and arrays. The children of schema were added when the iterator was constructed. - - XMP_Assert ( info.currPos->visitStage == kIter_BeforeVisit ); - - if ( info.currPos->visitStage == kIter_BeforeVisit ) { - if ( (! isSchemaNode) && (! (info.options & kXMP_IterJustChildren)) ) { - AddNodeOffspring ( info, *info.currPos, xmpNode ); - } - info.currPos->visitStage = kIter_VisitSelf; - } - - return xmpNode; - -} // GetNextXMPNode - -// ================================================================================================= -// Init/Term -// ================================================================================================= - -// ------------------------------------------------------------------------------------------------- -// Initialize -// ---------- - -/* class static */ bool -XMPIterator::Initialize() -{ - sDummySchema = new XMP_Node ( 0, "dummy:schema/", kXMP_SchemaNode); - return true; - -} // Initialize - -// ------------------------------------------------------------------------------------------------- -// Terminate -// ---------- - -/* class static */ void -XMPIterator::Terminate() RELEASE_NO_THROW -{ - delete ( sDummySchema ); - sDummySchema = 0; - return; - -} // Terminate - -// ------------------------------------------------------------------------------------------------- -// Unlock -// ------ - -void -XMPIterator::Unlock ( XMP_OptionBits options ) -{ - UNUSED(options); - - XMPMeta::Unlock ( 0 ); - -} // Unlock - -// ================================================================================================= -// 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. - -XMPIterator::XMPIterator ( const XMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,&xmpObj)) -{ - if ( (options & kXMP_IterClassMask) != kXMP_IterProperties ) { - XMP_Throw ( "Unsupported iteration kind", kXMPErr_BadOptions ); - } - - // *** Lock the XMPMeta object if we ever stop using a full DLL lock. - - if ( *propName != 0 ) { - - // An iterator rooted at a specific node. - - #if TraceIterators - printf ( "\nNew XMP property iterator for \"%s\", options = %X\n Schema = %s, root = %s\n", - xmpObj.tree.name.c_str(), options, schemaNS, propName ); - #endif - - XMP_ExpandedXPath propPath; - ExpandXPath ( schemaNS, propName, &propPath ); - XMP_Node * propNode = FindConstNode ( &xmpObj.tree, propPath ); // If not found get empty iteration. - - if ( propNode != 0 ) { - - 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.children.push_back ( IterNode ( propNode->options, propName, leafOffset ) ); - SetCurrSchema ( info, propPath[kSchemaStep].step.c_str() ); - if ( info.options & kXMP_IterJustChildren ) { - AddNodeOffspring ( info, info.tree.children.back(), propNode ); - } - - } - - } else if ( *schemaNS != 0 ) { - - // An iterator for all properties in one schema. - - #if TraceIterators - printf ( "\nNew XMP schema iterator for \"%s\", options = %X\n Schema = %s\n", - xmpObj.tree.name.c_str(), options, schemaNS ); - #endif - - info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaNS, 0 ) ); - IterNode & iterSchema = info.tree.children.back(); - - XMP_Node * xmpSchema = FindConstSchema ( &xmpObj.tree, schemaNS ); - if ( xmpSchema != 0 ) AddSchemaProps ( info, iterSchema, xmpSchema ); - - if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, schemaNS ); - - if ( iterSchema.children.empty() ) { - info.tree.children.pop_back(); // No properties, remove the schema node. - } else { - SetCurrSchema ( info, schemaNS ); - } - - } else { - - // An iterator for all properties in all schema. First add schema that exist (have children), - // adding aliases from them if appropriate. Then add schema that have no actual properties - // but do have aliases to existing properties, if we're including aliases in the iteration. - - #if TraceIterators - printf ( "\nNew XMP tree iterator for \"%s\", options = %X\n", - xmpObj.tree.name.c_str(), options ); - #endif - - // First pick up the schema that exist. - - for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum != schemaLim; ++schemaNum ) { - - const XMP_Node * xmpSchema = xmpObj.tree.children[schemaNum]; - info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, xmpSchema->name, 0 ) ); - IterNode & iterSchema = info.tree.children.back(); - - if ( ! (info.options & kXMP_IterJustChildren) ) { - AddSchemaProps ( info, iterSchema, xmpSchema ); - if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, xmpSchema->name.c_str() ); - if ( iterSchema.children.empty() ) info.tree.children.pop_back(); // No properties, remove the schema node. - } - - } - - if ( info.options & kXMP_IterIncludeAliases ) { - - // Add the schema that only have aliases. The most convenient, and safest way, is to go - // through the registered namespaces, see if it exists, and let AddSchemaAliases do its - // thing if not. Don't combine with the above loop, it is nicer to have the "real" stuff - // be in storage order (not subject to the namespace map order). - - // ! We don't do the kXMP_IterJustChildren handing in the same way here as above. The - // ! existing schema (presumably) have actual children. We need to call AddSchemaAliases - // ! here to determine if the namespace has any aliases to existing properties. We then - // ! strip the children if necessary. - - XMP_cStringMapPos currNS = sNamespaceURIToPrefixMap->begin(); - XMP_cStringMapPos endNS = sNamespaceURIToPrefixMap->end(); - for ( ; currNS != endNS; ++currNS ) { - XMP_StringPtr schemaName = currNS->first.c_str(); - if ( FindConstSchema ( &xmpObj.tree, schemaName ) != 0 ) continue; - info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaName, 0 ) ); - IterNode & iterSchema = info.tree.children.back(); - AddSchemaAliases ( info, iterSchema, schemaName ); - if ( iterSchema.children.empty() ) { - info.tree.children.pop_back(); // No aliases, remove the schema node. - } else if ( info.options & kXMP_IterJustChildren ) { - iterSchema.children.clear(); // Get rid of the children. - } - } - - } - - } - - // Set the current iteration position to the first node to be visited. - - info.currPos = info.tree.children.begin(); - info.endPos = info.tree.children.end(); - - if ( (info.options & kXMP_IterJustChildren) && (info.currPos != info.endPos) && (*schemaNS != 0) ) { - info.currPos->visitStage = kIter_VisitSelf; - } - - #if TraceIterators - if ( info.currPos == info.endPos ) { - printf ( " ** Empty iteration **\n" ); - } else { - printf ( " Initial node %s, stage = %s, iterator @ %.8X\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this ); - } - #endif - -} // XMPIterator for XMPMeta objects - -// ------------------------------------------------------------------------------------------------- -// XMPIterator -// ----------- -// -// Constructor for iterations over global tables such as registered namespaces or aliases. - -XMPIterator::XMPIterator ( XMP_StringPtr /*schemaNS*/, - XMP_StringPtr /*propName*/, - XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,0)) -{ - - XMP_Throw ( "Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented ); - -} // XMPIterator for global tables - -// ------------------------------------------------------------------------------------------------- -// ~XMPIterator -// ----------- - -XMPIterator::~XMPIterator() RELEASE_NO_THROW -{ - XMP_Assert ( this->clientRefs <= 0 ); - // 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 -XMPIterator::Next ( XMP_StringPtr * schemaNS, - XMP_StringLen * nsSize, - XMP_StringPtr * propPath, - XMP_StringLen * pathSize, - XMP_StringPtr * propValue, - XMP_StringLen * valueSize, - XMP_OptionBits * propOptions ) -{ - // *** Lock the XMPMeta object if we ever stop using a full DLL lock. - - // ! NOTE: Supporting aliases throws in some nastiness with schemas. There might not be any XMP - // ! node for the schema, but we still have to visit it because of possible aliases. - - if ( info.currPos == info.endPos ) return false; // Happens at the start of an empty iteration. - - #if TraceIterators - printf ( "Next iteration from %s, stage = %s, iterator @ %.8X\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this ); - #endif - - const XMP_Node * xmpNode = GetNextXMPNode ( info ); - if ( xmpNode == 0 ) return false; - bool isSchemaNode = XMP_NodeIsSchema ( info.currPos->options ); - - if ( info.options & kXMP_IterJustLeafNodes ) { - while ( isSchemaNode || (! xmpNode->children.empty()) ) { - info.currPos->visitStage = kIter_VisitQualifiers; // Skip to this node's children. - xmpNode = GetNextXMPNode ( info ); - if ( xmpNode == 0 ) 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 ( ! (*propOptions & kXMP_PropCompositeMask) ) { - *propValue = xmpNode->value.c_str(); - *valueSize = xmpNode->value.size(); - } - - } - - #if TraceIterators - printf ( " Next node %s, stage = %s\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] ); - #endif - - 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 -XMPIterator::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 TraceIterators - printf ( "Skipping from %s, stage = %s, iterator @ %.8X", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this ); - #endif - - if ( iterOptions & kXMP_IterSkipSubtree ) { - #if TraceIterators - printf ( ", mode = subtree\n" ); - #endif - info.currPos->visitStage = kIter_VisitChildren; - } else if ( iterOptions & kXMP_IterSkipSiblings ) { - #if TraceIterators - printf ( ", mode = siblings\n" ); - #endif - info.currPos = info.endPos; - AdvanceIterPos ( info ); - } - #if TraceIterators - printf ( " Skipped to %s, stage = %s\n", - info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] ); - #endif - - -} // Skip - -// ------------------------------------------------------------------------------------------------- -// UnlockIter -// ---------- - -void -XMPIterator::UnlockIter ( XMP_OptionBits options ) -{ - UNUSED(options); - - XMPMeta::Unlock ( 0 ); - -} // UnlockIter - -// ================================================================================================= diff --git a/xmpsdk/src/XMPIterator.hpp b/xmpsdk/src/XMPIterator.hpp deleted file mode 100644 index b72b975350..0000000000 --- a/xmpsdk/src/XMPIterator.hpp +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef __XMPIterator_hpp__ -#define __XMPIterator_hpp__ - -// ================================================================================================= -// Copyright 2002-2007 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 "XMP_Environment.h" -#include "XMP_Const.h" -#include "XMPMeta.hpp" - -// ================================================================================================= - -struct IterNode; -typedef std::vector < IterNode > IterOffspring; -typedef IterOffspring::iterator IterPos; - -typedef std::pair < IterPos, IterPos > IterPosPair; -typedef std::vector < IterPosPair > IterPosStack; - -enum { // Values for the visitStage field, used to decide how to proceed past a node. - kIter_BeforeVisit = 0, // Have not visited this node at all. - kIter_VisitSelf = 1, // Have visited this node and returned its value/options portion. - kIter_VisitQualifiers = 2, // In the midst of visiting this node's qualifiers. - kIter_VisitChildren = 3 // In the midst of visiting this node's children. -}; - -struct IterNode { - - XMP_OptionBits options; - XMP_VarString fullPath; - size_t leafOffset; - IterOffspring children, qualifiers; - XMP_Uns8 visitStage; - #if 0 // *** XMP_DebugBuild - XMP_StringPtr _pathPtr, _leafPtr; // *** Not working, need operator=? - #endif - - IterNode() : options(0), leafOffset(0), visitStage(kIter_BeforeVisit) - { - #if 0 // *** XMP_DebugBuild - _pathPtr = _leafPtr = 0; - #endif - }; - - IterNode ( XMP_OptionBits _options, const XMP_VarString& _fullPath, size_t _leafOffset ) - : options(_options), fullPath(_fullPath), leafOffset(_leafOffset), visitStage(kIter_BeforeVisit) - { - #if 0 // *** XMP_DebugBuild - _pathPtr = fullPath.c_str(); - _leafPtr = _pathPtr + leafOffset; - #endif - }; - -}; - -struct IterInfo { - - XMP_OptionBits options; - const XMPMeta * xmpObj; - XMP_VarString currSchema; - IterPos currPos, endPos; - IterPosStack ancestors; - IterNode tree; - #if 0 // *** XMP_DebugBuild - XMP_StringPtr _schemaPtr; // *** Not working, need operator=? - #endif - - IterInfo() : options(0), xmpObj(0) - { - #if 0 // *** XMP_DebugBuild - _schemaPtr = 0; - #endif - }; - - IterInfo ( XMP_OptionBits _options, const XMPMeta * _xmpObj ) : options(_options), xmpObj(_xmpObj) - { - #if 0 // *** XMP_DebugBuild - _schemaPtr = 0; - #endif - }; - -}; - -// ================================================================================================= - -class XMPIterator { -public: - - static bool - Initialize(); // ! For internal use only! - - static void - Terminate() RELEASE_NO_THROW; // ! For internal use only! - - static void - Unlock ( XMP_OptionBits options ); - - XMPIterator ( const XMPMeta & xmpObj, // Construct a property iterator. - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ); - - XMPIterator ( XMP_StringPtr schemaNS, // Construct a table iterator. - XMP_StringPtr propName, - XMP_OptionBits options ); - - virtual ~XMPIterator() 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 ); - - void - UnlockIter ( XMP_OptionBits options ); - - // ! Expose so that wrappers and file static functions can see the data. - - XMP_Int32 clientRefs; // ! Must be signed to allow decrement from 0. - IterInfo info; - -private: - - // ! These are hidden on purpose: - XMPIterator() : clientRefs(0) - { XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); }; - XMPIterator ( const XMPIterator & /* original */ ) : clientRefs(0) - { XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); }; - void operator= ( const XMPIterator & /* rhs */ ) - { XMP_Throw ( "Call to hidden operator=", kXMPErr_InternalFailure ); }; - -}; - -// ================================================================================================= - -#endif // __XMPIterator_hpp__ diff --git a/xmpsdk/src/XMPMeta-GetSet.cpp b/xmpsdk/src/XMPMeta-GetSet.cpp deleted file mode 100644 index 9972f9e6e6..0000000000 --- a/xmpsdk/src/XMPMeta-GetSet.cpp +++ /dev/null @@ -1,1212 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPMeta.hpp" -#include "XMPIterator.hpp" -#include "XMPUtils.hpp" - -#include "XMP_Version.h" -#include "UnicodeInlines.incl_cpp" -#include "UnicodeConversions.hpp" -#include "ExpatAdapter.hpp" - -#if XMP_DebugBuild - #include -#endif - -using namespace std; - -#if XMP_WinBuild - #ifdef _MSC_VER - #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 -#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 -}; - - -// ================================================================================================= -// Static Variables -// ================ - - -// ================================================================================================= -// Local Utilities -// =============== - - -// ------------------------------------------------------------------------------------------------- -// SetNodeValue -// ------------ - -static inline void -SetNodeValue ( XMP_Node * node, 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" ); - } - #endif - - node->value = value; - - XMP_Uns8* chPtr = (XMP_Uns8*) node->value.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 ) (void) GetCodePoint ( (const XMP_Uns8 **) &chPtr ); // Throws for bad UTF-8. - } - - if ( XMP_PropIsQualifier(node->options) && (node->name == "xml:lang") ) NormalizeLangValue ( &node->value ); - - #if 0 // *** XMP_DebugBuild - node->_valuePtr = node->value.c_str(); - #endif - -} // SetNodeValue - - -// ------------------------------------------------------------------------------------------------- -// SetNode -// ------- -// -// The internals for SetProperty and related calls, used after the node is found or created. - -static void -SetNode ( XMP_Node * node, XMP_StringPtr value, XMP_OptionBits options ) -{ - if ( options & kXMP_DeleteExisting ) { - XMP_ClearOption ( options, kXMP_DeleteExisting ); - node->options = options; - node->value.erase(); - node->RemoveChildren(); - node->RemoveQualifiers(); - } - - node->options |= options; // Keep options set by FindNode when creating a new node. - - if ( value != 0 ) { - - // This is setting the value of a leaf node. - if ( node->options & kXMP_PropCompositeMask ) XMP_Throw ( "Composite nodes can't have values", kXMPErr_BadXPath ); - XMP_Assert ( node->children.empty() ); - SetNodeValue ( node, value ); - - } else { - - // This is setting up an array or struct. - if ( ! node->value.empty() ) XMP_Throw ( "Composite nodes can't have values", kXMPErr_BadXPath ); - if ( node->options & kXMP_PropCompositeMask ) { // Can't change an array to a struct, or vice versa. - if ( (options & kXMP_PropCompositeMask) != (node->options & kXMP_PropCompositeMask) ) { - XMP_Throw ( "Requested and existing composite form mismatch", kXMPErr_BadXPath ); - } - } - node->RemoveChildren(); - - } - -} // SetNode - - -// ------------------------------------------------------------------------------------------------- -// DoSetArrayItem -// -------------- - -static void -DoSetArrayItem ( XMP_Node * arrayNode, - XMP_Index itemIndex, - XMP_StringPtr itemValue, - XMP_OptionBits options ) -{ - XMP_OptionBits itemLoc = options & kXMP_PropArrayLocationMask; - XMP_Index arraySize = arrayNode->children.size(); - - 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. - - XMP_Node * itemNode = 0; - - 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 != 0 ) XMP_Throw ( "Can't insert before or after implicit new item", kXMPErr_BadIndex ); - itemNode = new XMP_Node ( arrayNode, kXMP_ArrayItemName, 0 ); - arrayNode->children.push_back ( itemNode ); - - } else { - - if ( (itemIndex < 1) || (itemIndex > arraySize) ) XMP_Throw ( "Array index out of bounds", kXMPErr_BadIndex ); - --itemIndex; // ! Convert the index to a C zero-based value! - if ( itemLoc == 0 ) { - itemNode = arrayNode->children[itemIndex]; - } else { - XMP_NodePtrPos itemPos = arrayNode->children.begin() + itemIndex; - if ( itemLoc == kXMP_InsertAfterItem ) ++itemPos; - itemNode = new XMP_Node ( arrayNode, kXMP_ArrayItemName, 0 ); - itemPos = arrayNode->children.insert ( itemPos, itemNode ); - } - - } - - SetNode ( itemNode, itemValue, options ); - -} // DoSetArrayItem - - -// ------------------------------------------------------------------------------------------------- -// 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 -ChooseLocalizedText ( const XMP_Node * arrayNode, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - const XMP_Node * * itemNode ) -{ - const XMP_Node * currItem = 0; - const size_t itemLim = arrayNode->children.size(); - size_t itemNum; - - // 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(arrayNode->options) || - (arrayNode->children.empty() && XMP_ArrayIsAlternate(arrayNode->options)) ) ) { - XMP_Throw ( "Localized text array is not alt-text", kXMPErr_BadXPath ); - } - if ( arrayNode->children.empty() ) { - *itemNode = 0; - return kXMP_CLT_NoValues; - } - - for ( itemNum = 0; itemNum < itemLim; ++itemNum ) { - currItem = arrayNode->children[itemNum]; - if ( currItem->options & kXMP_PropCompositeMask ) { - XMP_Throw ( "Alt-text array item is not simple", kXMPErr_BadXPath ); - } - if ( currItem->qualifiers.empty() || (currItem->qualifiers[0]->name != "xml:lang") ) { - XMP_Throw ( "Alt-text array item has no language qualifier", kXMPErr_BadXPath ); - } - } - - // Look for an exact match with the specific language. - for ( itemNum = 0; itemNum < itemLim; ++itemNum ) { - currItem = arrayNode->children[itemNum]; - if ( currItem->qualifiers[0]->value == 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 = 0; itemNum < itemLim; ++itemNum ) { - currItem = arrayNode->children[itemNum]; - XMP_StringPtr currLang = currItem->qualifiers[0]->value.c_str(); - const size_t currLangSize = currItem->qualifiers[0]->value.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->children[itemNum]; - XMP_StringPtr currLang = currItem->qualifiers[0]->value.c_str(); - const size_t currLangSize = currItem->qualifiers[0]->value.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 = 0; itemNum < itemLim; ++itemNum ) { - currItem = arrayNode->children[itemNum]; - if ( currItem->qualifiers[0]->value == "x-default" ) { - *itemNode = currItem; - return kXMP_CLT_XDefault; - } - } - - // Everything failed, choose the first item. - *itemNode = arrayNode->children[0]; - return kXMP_CLT_FirstItem; - -} // ChooseLocalizedText - - -// ------------------------------------------------------------------------------------------------- -// AppendLangItem -// -------------- - -static void -AppendLangItem ( XMP_Node * arrayNode, XMP_StringPtr itemLang, XMP_StringPtr itemValue ) -{ - XMP_Node * newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, itemValue, (kXMP_PropHasQualifiers | kXMP_PropHasLang) ); - XMP_Node * langQual = new XMP_Node ( newItem, "xml:lang", itemLang, kXMP_PropIsQualifier ); - newItem->qualifiers.push_back ( langQual ); - - if ( (arrayNode->children.empty()) || (langQual->value != "x-default") ) { - arrayNode->children.push_back ( newItem ); - } else { - arrayNode->children.insert ( arrayNode->children.begin(), newItem ); - } - -} // AppendLangItem - - -// ================================================================================================= -// Class Methods -// ============= -// -// -// ================================================================================================= - - -// ------------------------------------------------------------------------------------------------- -// GetProperty -// ----------- - -bool -XMPMeta::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 ); - - XMP_Node * propNode = FindConstNode ( &tree, expPath ); - if ( propNode == 0 ) return false; - - *propValue = propNode->value.c_str(); - *valueSize = propNode->value.size(); - *options = propNode->options; - - return true; - -} // GetProperty - - -// ------------------------------------------------------------------------------------------------- -// GetArrayItem -// ------------ - -bool -XMPMeta::GetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * itemValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. - XMP_Assert ( (itemValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr itemPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen ); - return GetProperty ( schemaNS, itemPath, itemValue, valueSize, options ); - -} // GetArrayItem - - -// ------------------------------------------------------------------------------------------------- -// GetStructField -// -------------- - -bool -XMPMeta::GetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fieldValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper. - XMP_Assert ( (fieldValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr fieldPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen ); - return GetProperty ( schemaNS, fieldPath, fieldValue, valueSize, options ); - -} // GetStructField - - -// ------------------------------------------------------------------------------------------------- -// GetQualifier -// ------------ - -bool -XMPMeta::GetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * qualValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper. - XMP_Assert ( (qualValue != 0) && (valueSize != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr qualPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen ); - return GetProperty ( schemaNS, qualPath, qualValue, valueSize, options ); - -} // GetQualifier - - -// ------------------------------------------------------------------------------------------------- -// SetProperty -// ----------- - -// *** Should handle array items specially, calling SetArrayItem. - -void -XMPMeta::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 ); - - XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_CreateNodes, options ); - if ( propNode == 0 ) XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath ); - - SetNode ( propNode, propValue, options ); - -} // SetProperty - - -// ------------------------------------------------------------------------------------------------- -// SetArrayItem -// ------------ - -void -XMPMeta::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 ); - XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_ExistingOnly ); // Just lookup, don't try to create. - if ( arrayNode == 0 ) XMP_Throw ( "Specified array does not exist", kXMPErr_BadXPath ); - - DoSetArrayItem ( arrayNode, itemIndex, itemValue, options ); - -} // SetArrayItem - - -// ------------------------------------------------------------------------------------------------- -// AppendArrayItem -// --------------- - -void -XMPMeta::AppendArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - XMP_StringPtr itemValue, - XMP_OptionBits options ) -{ - 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 ); - } - - // Locate or create the array. If it already exists, make sure the array form from the options - // parameter is compatible with the current state. - - XMP_ExpandedXPath arrayPath; - ExpandXPath ( schemaNS, arrayName, &arrayPath ); - XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_ExistingOnly ); // Just lookup, don't try to create. - - if ( arrayNode != 0 ) { - // The array exists, make sure the form is compatible. Zero arrayForm means take what exists. - if ( ! (arrayNode->options & kXMP_PropValueIsArray) ) { - XMP_Throw ( "The named property is not an array", kXMPErr_BadXPath ); - } - #if 0 - // *** Disable for now. Need to do some general rethinking of semantic checks. - if ( (arrayOptions != 0) && (arrayOptions != (arrayNode->options & kXMP_PropArrayFormMask)) ) { - XMP_Throw ( "Mismatch of existing and specified array form", kXMPErr_BadOptions ); - } - #endif - } else { - // The array does not exist, try to create it. - if ( arrayOptions == 0 ) XMP_Throw ( "Explicit arrayOptions required to create new array", kXMPErr_BadOptions ); - arrayNode = FindNode ( &tree, arrayPath, kXMP_CreateNodes, arrayOptions ); - if ( arrayNode == 0 ) XMP_Throw ( "Failure creating array node", kXMPErr_BadXPath ); - } - - DoSetArrayItem ( arrayNode, kXMP_ArrayLastItem, itemValue, (options | kXMP_InsertAfterItem) ); - -} // AppendArrayItem - - -// ------------------------------------------------------------------------------------------------- -// SetStructField -// -------------- - -void -XMPMeta::SetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_OptionBits options ) -{ - XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper. - - XMP_StringPtr fieldPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen ); - SetProperty ( schemaNS, fieldPath, fieldValue, options ); - -} // SetStructField - - -// ------------------------------------------------------------------------------------------------- -// SetQualifier -// ------------ - -void -XMPMeta::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_StringPtr qualPath; - XMP_StringLen pathLen; - - XMP_ExpandedXPath expPath; - ExpandXPath ( schemaNS, propName, &expPath ); - XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_ExistingOnly ); - if ( propNode == 0 ) XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath ); - - XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen ); - SetProperty ( schemaNS, qualPath, qualValue, options ); - -} // SetQualifier - - -// ------------------------------------------------------------------------------------------------- -// DeleteProperty -// -------------- - -void -XMPMeta::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; - XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_ExistingOnly, kXMP_NoOptions, &ptrPos ); - if ( propNode == 0 ) return; - XMP_Node * parentNode = propNode->parent; - - // Erase the pointer from the parent's vector, then delete the node and all below it. - - if ( ! (propNode->options & kXMP_PropIsQualifier) ) { - - parentNode->children.erase ( ptrPos ); - DeleteEmptySchema ( parentNode ); - - } else { - - if ( propNode->name == "xml:lang" ) { - XMP_Assert ( parentNode->options & kXMP_PropHasLang ); // *** &= ~flag would be safer - parentNode->options ^= kXMP_PropHasLang; - } else if ( propNode->name == "rdf:type" ) { - XMP_Assert ( parentNode->options & kXMP_PropHasType ); - parentNode->options ^= kXMP_PropHasType; - } - - parentNode->qualifiers.erase ( ptrPos ); - XMP_Assert ( parentNode->options & kXMP_PropHasQualifiers ); - if ( parentNode->qualifiers.empty() ) parentNode->options ^= kXMP_PropHasQualifiers; - - } - - delete propNode; // ! The destructor takes care of the whole subtree. - -} // DeleteProperty - - -// ------------------------------------------------------------------------------------------------- -// DeleteArrayItem -// --------------- - -void -XMPMeta::DeleteArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ) -{ - XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. - - XMP_StringPtr itemPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen ); - DeleteProperty ( schemaNS, itemPath ); - -} // DeleteArrayItem - - -// ------------------------------------------------------------------------------------------------- -// DeleteStructField -// ----------------- - -void -XMPMeta::DeleteStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ) -{ - XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper. - - XMP_StringPtr fieldPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen ); - DeleteProperty ( schemaNS, fieldPath ); - -} // DeleteStructField - - -// ------------------------------------------------------------------------------------------------- -// DeleteQualifier -// --------------- - -void -XMPMeta::DeleteQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ) -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper. - - XMP_StringPtr qualPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen ); - DeleteProperty ( schemaNS, qualPath ); - -} // DeleteQualifier - - -// ------------------------------------------------------------------------------------------------- -// DoesPropertyExist -// ----------------- - -bool -XMPMeta::DoesPropertyExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; - ExpandXPath ( schemaNS, propName, &expPath ); - - XMP_Node * propNode = FindConstNode ( &tree, expPath ); - return (propNode != 0); - -} // DoesPropertyExist - - -// ------------------------------------------------------------------------------------------------- -// DoesArrayItemExist -// ------------------ - -bool -XMPMeta::DoesArrayItemExist ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ) const -{ - XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. - - XMP_StringPtr itemPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen ); - return DoesPropertyExist ( schemaNS, itemPath ); - -} // DoesArrayItemExist - - -// ------------------------------------------------------------------------------------------------- -// DoesStructFieldExist -// -------------------- - -bool -XMPMeta::DoesStructFieldExist ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ) const -{ - XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) ); // Enforced by wrapper. - - XMP_StringPtr fieldPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen ); - return DoesPropertyExist ( schemaNS, fieldPath ); - -} // DoesStructFieldExist - - -// ------------------------------------------------------------------------------------------------- -// DoesQualifierExist -// ------------------ - -bool -XMPMeta::DoesQualifierExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) ); // Enforced by wrapper. - - XMP_StringPtr qualPath; - XMP_StringLen pathLen; - - XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen ); - return DoesPropertyExist ( schemaNS, qualPath ); - -} // DoesQualifierExist - - -// ------------------------------------------------------------------------------------------------- -// GetLocalizedText -// ---------------- - -bool -XMPMeta::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 -{ - 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 ); - - const XMP_Node * arrayNode = FindConstNode ( &tree, arrayPath ); // *** This expand/find idiom is used in 3 Getters. - if ( arrayNode == 0 ) return false; // *** Should extract it into a local utility. - - XMP_CLTMatch match; - const XMP_Node * itemNode; - - match = ChooseLocalizedText ( arrayNode, genericLang, specificLang, &itemNode ); - if ( match == kXMP_CLT_NoValues ) return false; - - *actualLang = itemNode->qualifiers[0]->value.c_str(); - *langSize = itemNode->qualifiers[0]->value.size(); - *itemValue = itemNode->value.c_str(); - *valueSize = itemNode->value.size(); - *options = itemNode->options; - - return true; - -} // GetLocalizedText - - -// ------------------------------------------------------------------------------------------------- -// SetLocalizedText -// ---------------- - -void -XMPMeta::SetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr _genericLang, - XMP_StringPtr _specificLang, - XMP_StringPtr itemValue, - XMP_OptionBits options ) -{ - UNUSED(options); // Avoid unused parameter warning. - - 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. - XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_CreateNodes, - (kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate) ); - if ( arrayNode == 0 ) XMP_Throw ( "Failed to find or create array node", kXMPErr_BadXPath ); - if ( ! XMP_ArrayIsAltText(arrayNode->options) ) { - if ( arrayNode->children.empty() && XMP_ArrayIsAlternate(arrayNode->options) ) { - arrayNode->options |= 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; - XMP_Node * xdItem = 0; - bool haveXDefault = false; - - for ( itemNum = 0, itemLim = arrayNode->children.size(); itemNum < itemLim; ++itemNum ) { - XMP_Node * currItem = arrayNode->children[itemNum]; - XMP_Assert ( XMP_PropHasLang(currItem->options) ); - if ( currItem->qualifiers.empty() || (currItem->qualifiers[0]->name != "xml:lang") ) { - XMP_Throw ( "Language qualifier must be first", kXMPErr_BadXPath ); - } - if ( currItem->qualifiers[0]->value == "x-default" ) { - xdItem = currItem; - haveXDefault = true; - break; - } - } - - if ( haveXDefault && (itemNum != 0) ) { - XMP_Assert ( arrayNode->children[itemNum]->qualifiers[0]->value == "x-default" ); - XMP_Node * temp = arrayNode->children[0]; - arrayNode->children[0] = arrayNode->children[itemNum]; - arrayNode->children[itemNum] = temp; - } - - // Find the appropriate item. ChooseLocalizedText will make sure the array is a language alternative. - - const XMP_Node * cItemNode; // ! ChooseLocalizedText returns a pointer to a const node. - XMP_CLTMatch match = ChooseLocalizedText ( arrayNode, genericLang, specificLang, &cItemNode ); - XMP_Node * itemNode = const_cast ( cItemNode ); - - 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. - AppendLangItem ( arrayNode, "x-default", itemValue ); - haveXDefault = true; - if ( ! specificXDefault ) AppendLangItem ( arrayNode, specificLang, itemValue ); - break; - - case kXMP_CLT_SpecificMatch : - - if ( ! specificXDefault ) { - // Update the specific item, update x-default if it matches the old value. - if ( haveXDefault && (xdItem != itemNode) && (xdItem->value == itemNode->value) ) { - SetNodeValue ( xdItem, itemValue ); - } - SetNodeValue ( itemNode, itemValue ); // ! Do this after the x-default check! - } else { - // Update all items whose values match the old x-default value. - XMP_Assert ( haveXDefault && (xdItem == itemNode) ); - for ( itemNum = 0, itemLim = arrayNode->children.size(); itemNum < itemLim; ++itemNum ) { - XMP_Node * currItem = arrayNode->children[itemNum]; - if ( (currItem == xdItem) || (currItem->value != xdItem->value) ) continue; - SetNodeValue ( currItem, itemValue ); - } - SetNodeValue ( xdItem, itemValue ); // And finally do the x-default item. - } - break; - - case kXMP_CLT_SingleGeneric : - - // Update the generic item, update x-default if it matches the old value. - if ( haveXDefault && (xdItem != itemNode) && (xdItem->value == itemNode->value) ) { - SetNodeValue ( xdItem, itemValue ); - } - SetNodeValue ( itemNode, itemValue ); // ! Do this after the x-default check! - break; - - case kXMP_CLT_MultipleGeneric : - - // Create the specific language, ignore x-default. - AppendLangItem ( 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->children.size() == 1 ) SetNodeValue ( xdItem, itemValue ); - AppendLangItem ( arrayNode, specificLang, itemValue ); - break; - - case kXMP_CLT_FirstItem : - - // Create the specific language, don't add an x-default item. - AppendLangItem ( 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->children.size() == 1) ) { - AppendLangItem ( arrayNode, "x-default", itemValue ); - } - -} // SetLocalizedText - - -// ------------------------------------------------------------------------------------------------- -// GetProperty_Bool -// ---------------- - -bool -XMPMeta::GetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool * propValue, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - XMP_Assert ( (propValue != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options ); - if ( found ) { - if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath ); - *propValue = XMPUtils::ConvertToBool ( valueStr ); - } - return found; - -} // GetProperty_Bool - - -// ------------------------------------------------------------------------------------------------- -// GetProperty_Int -// --------------- - -bool -XMPMeta::GetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 * propValue, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - XMP_Assert ( (propValue != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options ); - if ( found ) { - if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath ); - *propValue = XMPUtils::ConvertToInt ( valueStr ); - } - return found; - -} // GetProperty_Int - - -// ------------------------------------------------------------------------------------------------- -// GetProperty_Int64 -// ----------------- - -bool -XMPMeta::GetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 * propValue, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - XMP_Assert ( (propValue != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options ); - if ( found ) { - if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath ); - *propValue = XMPUtils::ConvertToInt64 ( valueStr ); - } - return found; - -} // GetProperty_Int64 - - -// ------------------------------------------------------------------------------------------------- -// GetProperty_Float -// ----------------- - -bool -XMPMeta::GetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double * propValue, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - XMP_Assert ( (propValue != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options ); - if ( found ) { - if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath ); - *propValue = XMPUtils::ConvertToFloat ( valueStr ); - } - return found; - -} // GetProperty_Float - - -// ------------------------------------------------------------------------------------------------- -// GetProperty_Date -// ---------------- - -bool -XMPMeta::GetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_DateTime * propValue, - XMP_OptionBits * options ) const -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - XMP_Assert ( (propValue != 0) && (options != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options ); - if ( found ) { - if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath ); - XMPUtils::ConvertToDate ( valueStr, propValue ); - } - return found; - -} // GetProperty_Date - - -// ------------------------------------------------------------------------------------------------- -// SetProperty_Bool -// ---------------- - -void -XMPMeta::SetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool propValue, - XMP_OptionBits options ) -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - XMPUtils::ConvertFromBool ( propValue, &valueStr, &valueLen ); - SetProperty ( schemaNS, propName, valueStr, options ); - -} // SetProperty_Bool - - -// ------------------------------------------------------------------------------------------------- -// SetProperty_Int -// --------------- - -void -XMPMeta::SetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 propValue, - XMP_OptionBits options ) -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - XMPUtils::ConvertFromInt ( propValue, "", &valueStr, &valueLen ); - SetProperty ( schemaNS, propName, valueStr, options ); - -} // SetProperty_Int - - -// ------------------------------------------------------------------------------------------------- -// SetProperty_Int64 -// ----------------- - -void -XMPMeta::SetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 propValue, - XMP_OptionBits options ) -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - XMPUtils::ConvertFromInt64 ( propValue, "", &valueStr, &valueLen ); - SetProperty ( schemaNS, propName, valueStr, options ); - -} // SetProperty_Int64 - - -// ------------------------------------------------------------------------------------------------- -// SetProperty_Float -// ----------------- - -void -XMPMeta::SetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double propValue, - XMP_OptionBits options ) -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - XMPUtils::ConvertFromFloat ( propValue, "", &valueStr, &valueLen ); - SetProperty ( schemaNS, propName, valueStr, options ); - -} // SetProperty_Float - - -// ------------------------------------------------------------------------------------------------- -// SetProperty_Date -// ---------------- - -void -XMPMeta::SetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const XMP_DateTime & propValue, - XMP_OptionBits options ) -{ - XMP_Assert ( (schemaNS != 0) && (propName != 0) ); // Enforced by wrapper. - - XMP_StringPtr valueStr; - XMP_StringLen valueLen; - - XMPUtils::ConvertFromDate ( propValue, &valueStr, &valueLen ); - SetProperty ( schemaNS, propName, valueStr, options ); - -} // SetProperty_Date - -// ================================================================================================= - diff --git a/xmpsdk/src/XMPMeta-Parse.cpp b/xmpsdk/src/XMPMeta-Parse.cpp deleted file mode 100644 index 69596934ea..0000000000 --- a/xmpsdk/src/XMPMeta-Parse.cpp +++ /dev/null @@ -1,1306 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPMeta.hpp" -#include "XMPUtils.hpp" - -#include "UnicodeInlines.incl_cpp" -#include "UnicodeConversions.hpp" -#include "ExpatAdapter.hpp" - -#if XMP_DebugBuild - #include -#endif - -using namespace std; - -#if XMP_WinBuild -#ifdef _MSC_VER - #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) - #pragma warning ( disable : 4996 ) // '...' was declared deprecated -#endif -#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 -// ========================= - - -// ================================================================================================= -// Static Variables -// ================ - -#ifndef Trace_ParsingHackery - #define Trace_ParsingHackery 0 -#endif - -static const char * kReplaceLatin1[128] = - { - - // The 0x80..0x9F range is undefined in Latin-1, but is defined in Windows code page 1252. - // The bytes 0x81, 0x8D, 0x8F, 0x90, and 0x9D are formally undefined by Windows 1252, but - // their conversion API maps them to U+0081, etc. These are in XML's RestrictedChar set, so - // we map them to a space. - - "\xE2\x82\xAC", " ", "\xE2\x80\x9A", "\xC6\x92", // 0x80 .. 0x83 - "\xE2\x80\x9E", "\xE2\x80\xA6", "\xE2\x80\xA0", "\xE2\x80\xA1", // 0x84 .. 0x87 - "\xCB\x86", "\xE2\x80\xB0", "\xC5\xA0", "\xE2\x80\xB9", // 0x88 .. 0x8B - "\xC5\x92", " ", "\xC5\xBD", " ", // 0x8C .. 0x8F - - " ", "\xE2\x80\x98", "\xE2\x80\x99", "\xE2\x80\x9C", // 0x90 .. 0x93 - "\xE2\x80\x9D", "\xE2\x80\xA2", "\xE2\x80\x93", "\xE2\x80\x94", // 0x94 .. 0x97 - "\xCB\x9C", "\xE2\x84\xA2", "\xC5\xA1", "\xE2\x80\xBA", // 0x98 .. 0x9B - "\xC5\x93", " ", "\xC5\xBE", "\xC5\xB8", // 0x9C .. 0x9F - - // These are the UTF-8 forms of the official Latin-1 characters in the range 0xA0..0xFF. Not - // too surprisingly these map to U+00A0, etc. Which is the Unicode Latin Supplement range. - - "\xC2\xA0", "\xC2\xA1", "\xC2\xA2", "\xC2\xA3", "\xC2\xA4", "\xC2\xA5", "\xC2\xA6", "\xC2\xA7", // 0xA0 .. 0xA7 - "\xC2\xA8", "\xC2\xA9", "\xC2\xAA", "\xC2\xAB", "\xC2\xAC", "\xC2\xAD", "\xC2\xAE", "\xC2\xAF", // 0xA8 .. 0xAF - - "\xC2\xB0", "\xC2\xB1", "\xC2\xB2", "\xC2\xB3", "\xC2\xB4", "\xC2\xB5", "\xC2\xB6", "\xC2\xB7", // 0xB0 .. 0xB7 - "\xC2\xB8", "\xC2\xB9", "\xC2\xBA", "\xC2\xBB", "\xC2\xBC", "\xC2\xBD", "\xC2\xBE", "\xC2\xBF", // 0xB8 .. 0xBF - - "\xC3\x80", "\xC3\x81", "\xC3\x82", "\xC3\x83", "\xC3\x84", "\xC3\x85", "\xC3\x86", "\xC3\x87", // 0xC0 .. 0xC7 - "\xC3\x88", "\xC3\x89", "\xC3\x8A", "\xC3\x8B", "\xC3\x8C", "\xC3\x8D", "\xC3\x8E", "\xC3\x8F", // 0xC8 .. 0xCF - - "\xC3\x90", "\xC3\x91", "\xC3\x92", "\xC3\x93", "\xC3\x94", "\xC3\x95", "\xC3\x96", "\xC3\x97", // 0xD0 .. 0xD7 - "\xC3\x98", "\xC3\x99", "\xC3\x9A", "\xC3\x9B", "\xC3\x9C", "\xC3\x9D", "\xC3\x9E", "\xC3\x9F", // 0xD8 .. 0xDF - - "\xC3\xA0", "\xC3\xA1", "\xC3\xA2", "\xC3\xA3", "\xC3\xA4", "\xC3\xA5", "\xC3\xA6", "\xC3\xA7", // 0xE0 .. 0xE7 - "\xC3\xA8", "\xC3\xA9", "\xC3\xAA", "\xC3\xAB", "\xC3\xAC", "\xC3\xAD", "\xC3\xAE", "\xC3\xAF", // 0xE8 .. 0xEF - - "\xC3\xB0", "\xC3\xB1", "\xC3\xB2", "\xC3\xB3", "\xC3\xB4", "\xC3\xB5", "\xC3\xB6", "\xC3\xB7", // 0xF0 .. 0xF7 - "\xC3\xB8", "\xC3\xB9", "\xC3\xBA", "\xC3\xBB", "\xC3\xBC", "\xC3\xBD", "\xC3\xBE", "\xC3\xBF", // 0xF8 .. 0xFF - - }; - - -// ================================================================================================= -// Local Utilities -// =============== - - -#define IsHexDigit(ch) ( (('0' <= (ch)) && ((ch) <= '9')) || (('A' <= (ch)) && ((ch) <= 'F')) ) -#define HexDigitValue(ch) ( (((ch) - '0') < 10) ? ((ch) - '0') : ((ch) - 'A' + 10) ) - - -// ------------------------------------------------------------------------------------------------- -// PickBestRoot -// ------------ -static const XML_Node * PickBestRoot ( const XML_Node & xmlParent, XMP_OptionBits options ) -{ - - // Look among this parent's content for x:xmpmeta. The recursion for x:xmpmeta is broader than - // the strictly defined choice, but gives us smaller code. - for ( size_t childNum = 0, childLim = xmlParent.content.size(); childNum < childLim; ++childNum ) { - const XML_Node * childNode = xmlParent.content[childNum]; - if ( childNode->kind != kElemNode ) continue; - if ( (childNode->name == "x:xmpmeta") || (childNode->name == "x:xapmeta") ) return PickBestRoot ( *childNode, 0 ); - } - // Look among this parent's content for a bare rdf:RDF if that is allowed. - if ( ! (options & kXMP_RequireXMPMeta) ) { - for ( size_t childNum = 0, childLim = xmlParent.content.size(); childNum < childLim; ++childNum ) { - const XML_Node * childNode = xmlParent.content[childNum]; - if ( childNode->kind != kElemNode ) continue; - if ( childNode->name == "rdf:RDF" ) return childNode; - } - } - - // Recurse into the content. - for ( size_t childNum = 0, childLim = xmlParent.content.size(); childNum < childLim; ++childNum ) { - const XML_Node * foundRoot = PickBestRoot ( *xmlParent.content[childNum], options ); - if ( foundRoot != 0 ) return foundRoot; - } - - return 0; - -} // PickBestRoot - -// ------------------------------------------------------------------------------------------------- -// FindRootNode -// ------------ -// -// Find the XML node that is the root of the XMP data tree. Generally this will be an outer node, -// but it could be anywhere if a general XML document is parsed (e.g. SVG). The XML parser counted -// all possible root nodes, and kept a pointer to the last one. If there is more than one possible -// root use PickBestRoot to choose among them. -// -// If there is a root node, try to extract the version of the previous XMP toolkit. - -static const XML_Node * FindRootNode ( XMPMeta * thiz, const XMLParserAdapter & xmlParser, XMP_OptionBits options ) -{ - const XML_Node * rootNode = xmlParser.rootNode; - - if ( xmlParser.rootCount > 1 ) rootNode = PickBestRoot ( xmlParser.tree, options ); - if ( rootNode == 0 ) return 0; - - // We have a root node. Try to extract previous toolkit version number. - - XMP_StringPtr verStr = ""; - - XMP_Assert ( rootNode->name == "rdf:RDF" ); - - if ( (options & kXMP_RequireXMPMeta) && - ((rootNode->parent == 0) || - ((rootNode->parent->name != "x:xmpmeta") && (rootNode->parent->name != "x:xapmeta"))) ) return 0; - - for ( size_t attrNum = 0, attrLim = rootNode->parent->attrs.size(); attrNum < attrLim; ++attrNum ) { - const XML_Node * currAttr =rootNode->parent->attrs[attrNum]; - if ( (currAttr->name == "x:xmptk") || (currAttr->name == "x:xaptk") ) { - verStr = currAttr->value.c_str(); - break; - } - } - - // Decode the version number into MMmmuubbb digits. If any part is too big, peg it at 99 or 999. - - unsigned long part; - while ( (*verStr != 0) && ((*verStr < '0') || (*verStr > '9')) ) ++verStr; - - part = 0; - while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) { - part = (part * 10) + (*verStr - '0'); - ++verStr; - } - if ( part > 99 ) part = 99; - thiz->prevTkVer = part * 100*100*1000; - - part = 0; - if ( *verStr == '.' ) ++verStr; - while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) { - part = (part * 10) + (*verStr - '0'); - ++verStr; - } - if ( part > 99 ) part = 99; - thiz->prevTkVer += part * 100*1000; - - part = 0; - if ( *verStr == '.' ) ++verStr; - while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) { - part = (part * 10) + (*verStr - '0'); - ++verStr; - } - if ( part > 99 ) part = 99; - thiz->prevTkVer += part * 1000; - - part = 0; - if ( *verStr == '-' ) ++verStr; - while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) { - part = (part * 10) + (*verStr - '0'); - ++verStr; - } - if ( part > 999 ) part = 999; - thiz->prevTkVer += part; - - return rootNode; - -} // FindRootNode - -// ------------------------------------------------------------------------------------------------- -// NormalizeDCArrays -// ----------------- -// -// Undo the denormalization performed by the XMP used in Acrobat 5. If a Dublin Core array had only -// one item, it was serialized as a simple property. The xml:lang attribute was dropped from an -// alt-text item if the language was x-default. - -// *** This depends on the dc: namespace prefix. - -static void -NormalizeDCArrays ( XMP_Node * xmpTree ) -{ - XMP_Node * dcSchema = FindSchemaNode ( xmpTree, kXMP_NS_DC, kXMP_ExistingOnly ); - if ( dcSchema == 0 ) return; - - for ( size_t propNum = 0, propLimit = dcSchema->children.size(); propNum < propLimit; ++propNum ) { - XMP_Node * currProp = dcSchema->children[propNum]; - XMP_OptionBits arrayForm = 0; - - if ( ! XMP_PropIsSimple ( currProp->options ) ) continue; // Nothing to do if not simple. - - if ( (currProp->name == "dc:creator" ) || // See if it is supposed to be an array. - (currProp->name == "dc:date" ) ) { // *** Think about an array of char* and a loop. - arrayForm = kXMP_PropArrayIsOrdered; - } else if ( - (currProp->name == "dc:description" ) || - (currProp->name == "dc:rights" ) || - (currProp->name == "dc:title" ) ) { - arrayForm = kXMP_PropArrayIsAltText; - } else if ( - (currProp->name == "dc:contributor" ) || - (currProp->name == "dc:language" ) || - (currProp->name == "dc:publisher" ) || - (currProp->name == "dc:relation" ) || - (currProp->name == "dc:subject" ) || - (currProp->name == "dc:type" ) ) { - arrayForm = kXMP_PropValueIsArray; - } - if ( arrayForm == 0 ) continue; // Nothing to do if it isn't supposed to be an array. - - arrayForm = VerifySetOptions ( arrayForm, 0 ); // Set the implicit array bits. - XMP_Node * newArray = new XMP_Node ( dcSchema, currProp->name.c_str(), arrayForm ); - dcSchema->children[propNum] = newArray; - newArray->children.push_back ( currProp ); - currProp->parent = newArray; - currProp->name = kXMP_ArrayItemName; - - if ( XMP_ArrayIsAltText ( arrayForm ) && (! (currProp->options & kXMP_PropHasLang)) ) { - XMP_Node * newLang = new XMP_Node ( currProp, "xml:lang", "x-default", kXMP_PropIsQualifier ); - currProp->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang); - if ( currProp->qualifiers.empty() ) { // *** Need a util? - currProp->qualifiers.push_back ( newLang ); - } else { - currProp->qualifiers.insert ( currProp->qualifiers.begin(), newLang ); - } - } - - } - -} // NormalizeDCArrays - - -// ------------------------------------------------------------------------------------------------- -// CompareAliasedSubtrees -// ---------------------- - -// *** Change to do some alias-specific setup, then use CompareSubtrees. One special case for -// *** aliases is a simple to x-default alias, the options and qualifiers obviously differ. - -static void -CompareAliasedSubtrees ( XMP_Node * aliasNode, XMP_Node * baseNode, bool outerCall = true ) -{ - // ! The outermost call is special. The names almost certainly differ. The qualifiers (and - // ! hence options) will differ for an alias to the x-default item of a langAlt array. - if ( (aliasNode->value != baseNode->value) || - (aliasNode->children.size() != baseNode->children.size()) ) { - XMP_Throw ( "Mismatch between alias and base nodes", kXMPErr_BadXMP ); - } - if ( ! outerCall ) { - if ( (aliasNode->name != baseNode->name) || - (aliasNode->options != baseNode->options) || - (aliasNode->qualifiers.size() != baseNode->qualifiers.size()) ) { - XMP_Throw ( "Mismatch between alias and base nodes", kXMPErr_BadXMP ); - } - } - - for ( size_t childNum = 0, childLim = aliasNode->children.size(); childNum < childLim; ++childNum ) { - XMP_Node * aliasChild = aliasNode->children[childNum]; - XMP_Node * baseChild = baseNode->children[childNum]; - CompareAliasedSubtrees ( aliasChild, baseChild, false ); - } - - for ( size_t qualNum = 0, qualLim = aliasNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - XMP_Node * aliasQual = aliasNode->qualifiers[qualNum]; - XMP_Node * baseQual = baseNode->qualifiers[qualNum]; - CompareAliasedSubtrees ( aliasQual, baseQual, false ); - } - -} // CompareAliasedSubtrees - - -// ------------------------------------------------------------------------------------------------- -// TransplantArrayItemAlias -// ------------------------ - -static void -TransplantArrayItemAlias ( XMP_Node * oldParent, size_t oldNum, XMP_Node * newParent ) -{ - XMP_Node * childNode = oldParent->children[oldNum]; - - if ( newParent->options & kXMP_PropArrayIsAltText ) { - if ( childNode->options & kXMP_PropHasLang ) { - XMP_Throw ( "Alias to x-default already has a language qualifier", kXMPErr_BadXMP ); // *** Allow x-default. - } - childNode->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang); - XMP_Node * langQual = new XMP_Node ( childNode, "xml:lang", "x-default", kXMP_PropIsQualifier ); // *** AddLangQual util? - if ( childNode->qualifiers.empty() ) { - childNode->qualifiers.push_back ( langQual ); - } else { - childNode->qualifiers.insert ( childNode->qualifiers.begin(), langQual ); - } - } - - oldParent->children.erase ( oldParent->children.begin() + oldNum ); - childNode->name = kXMP_ArrayItemName; - childNode->parent = newParent; - if ( newParent->children.empty() ) { - newParent->children.push_back ( childNode ); - } else { - newParent->children.insert ( newParent->children.begin(), childNode ); - } - -} // TransplantArrayItemAlias - - -// ------------------------------------------------------------------------------------------------- -// TransplantNamedAlias -// -------------------- - -static void -TransplantNamedAlias ( XMP_Node * oldParent, size_t oldNum, XMP_Node * newParent, XMP_VarString & newName ) -{ - XMP_Node * childNode = oldParent->children[oldNum]; - - oldParent->children.erase ( oldParent->children.begin() + oldNum ); - childNode->name = newName; - childNode->parent = newParent; - newParent->children.push_back ( childNode ); - -} // TransplantNamedAlias - - -// ------------------------------------------------------------------------------------------------- -// MoveExplicitAliases -// ------------------- - -static void -MoveExplicitAliases ( XMP_Node * tree, XMP_OptionBits parseOptions ) -{ - tree->options ^= kXMP_PropHasAliases; - const bool strictAliasing = ((parseOptions & kXMP_StrictAliasing) != 0); - - // Visit all of the top level nodes looking for aliases. If there is no base, transplant the - // alias subtree. If there is a base and strict aliasing is on, make sure the alias and base - // subtrees match. - - // ! Use "while" loops not "for" loops since both the schema and property loops can remove the - // ! current item from the vector being traversed. And don't increment the counter for a delete. - - size_t schemaNum = 0; - while ( schemaNum < tree->children.size() ) { - XMP_Node * currSchema = tree->children[schemaNum]; - - size_t propNum = 0; - while ( propNum < currSchema->children.size() ) { - XMP_Node * currProp = currSchema->children[propNum]; - if ( ! (currProp->options & kXMP_PropIsAlias) ) { - ++propNum; - continue; - } - currProp->options ^= kXMP_PropIsAlias; - - // Find the base path, look for the base schema and root node. - - XMP_AliasMapPos aliasPos = sRegisteredAliasMap->find ( currProp->name ); - XMP_Assert ( aliasPos != sRegisteredAliasMap->end() ); - XMP_ExpandedXPath & basePath = aliasPos->second; - XMP_OptionBits arrayOptions = (basePath[kRootPropStep].options & kXMP_PropArrayFormMask); - - XMP_Node * baseSchema = FindSchemaNode ( tree, basePath[kSchemaStep].step.c_str(), kXMP_CreateNodes ); - if ( baseSchema->options & kXMP_NewImplicitNode ) baseSchema->options ^= kXMP_NewImplicitNode; - XMP_Node * baseNode = FindChildNode ( baseSchema, basePath[kRootPropStep].step.c_str(), kXMP_ExistingOnly ); - - if ( baseNode == 0 ) { - - if ( basePath.size() == 2 ) { - // A top-to-top alias, transplant the property. - TransplantNamedAlias ( currSchema, propNum, baseSchema, basePath[kRootPropStep].step ); - } else { - // An alias to an array item, create the array and transplant the property. - baseNode = new XMP_Node ( baseSchema, basePath[kRootPropStep].step.c_str(), arrayOptions ); - baseSchema->children.push_back ( baseNode ); - TransplantArrayItemAlias ( currSchema, propNum, baseNode ); - } - - } else if ( basePath.size() == 2 ) { - - // The base node does exist and this is a top-to-top alias. Check for conflicts if - // strict aliasing is on. Remove and delete the alias subtree. - if ( strictAliasing ) CompareAliasedSubtrees ( currProp, baseNode ); - currSchema->children.erase ( currSchema->children.begin() + propNum ); - delete currProp; - - } else { - - // This is an alias to an array item and the array exists. Look for the aliased item. - // Then transplant or check & delete as appropriate. - - XMP_Node * itemNode = 0; - if ( arrayOptions & kXMP_PropArrayIsAltText ) { - XMP_Index xdIndex = LookupLangItem ( baseNode, *xdefaultName ); - if ( xdIndex != -1 ) itemNode = baseNode->children[xdIndex]; - } else if ( ! baseNode->children.empty() ) { - itemNode = baseNode->children[0]; - } - - if ( itemNode == 0 ) { - TransplantArrayItemAlias ( currSchema, propNum, baseNode ); - } else { - if ( strictAliasing ) CompareAliasedSubtrees ( currProp, itemNode ); - currSchema->children.erase ( currSchema->children.begin() + propNum ); - delete currProp; - } - - } - - } // Property loop - - // Increment the counter or remove an empty schema node. - if ( currSchema->children.size() > 0 ) { - ++schemaNum; - } else { - delete tree->children[schemaNum]; // ! Delete the schema node itself. - tree->children.erase ( tree->children.begin() + schemaNum ); - } - - } // Schema loop - -} // MoveExplicitAliases - - -// ------------------------------------------------------------------------------------------------- -// FixGPSTimeStamp -// --------------- - -static void -FixGPSTimeStamp ( XMP_Node * exifSchema, XMP_Node * gpsDateTime ) -{ - XMP_DateTime binGPSStamp; - try { - XMPUtils::ConvertToDate ( gpsDateTime->value.c_str(), &binGPSStamp ); - } catch ( ... ) { - return; // Don't let a bad date stop other things. - } - if ( (binGPSStamp.year != 0) || (binGPSStamp.month != 0) || (binGPSStamp.day != 0) ) return; - - XMP_Node * otherDate = FindChildNode ( exifSchema, "exif:DateTimeOriginal", kXMP_ExistingOnly ); - if ( otherDate == 0 ) otherDate = FindChildNode ( exifSchema, "exif:DateTimeDigitized", kXMP_ExistingOnly ); - if ( otherDate == 0 ) return; - - XMP_DateTime binOtherDate; - try { - XMPUtils::ConvertToDate ( otherDate->value.c_str(), &binOtherDate ); - } catch ( ... ) { - return; // Don't let a bad date stop other things. - } - - binGPSStamp.year = binOtherDate.year; - binGPSStamp.month = binOtherDate.month; - binGPSStamp.day = binOtherDate.day; - - XMP_StringPtr goodStr; - XMP_StringLen goodLen; - XMPUtils::ConvertFromDate ( binGPSStamp, &goodStr, &goodLen ); - - gpsDateTime->value.assign ( goodStr, goodLen ); - -} // FixGPSTimeStamp - - -// ------------------------------------------------------------------------------------------------- -// MigrateAudioCopyright -// --------------------- -// -// The initial support for WAV files mapped a legacy ID3 audio copyright into a new xmpDM:copyright -// property. This is special case code to migrate that into dc:rights['x-default']. The rules: -// -// 1. If there is no dc:rights array, or an empty array - -// Create one with dc:rights['x-default'] set from double linefeed and xmpDM:copyright. -// -// 2. If there is a dc:rights array but it has no x-default item - -// Create an x-default item as a copy of the first item then apply rule #3. -// -// 3. If there is a dc:rights array with an x-default item, look for a double linefeed in the value. -// A. If no double linefeed, compare the x-default value to the xmpDM:copyright value. -// A1. If they match then leave the x-default value alone. -// A2. Otherwise, append a double linefeed and the xmpDM:copyright value to the x-default value. -// B. If there is a double linefeed, compare the trailing text to the xmpDM:copyright value. -// B1. If they match then leave the x-default value alone. -// B2. Otherwise, replace the trailing x-default text with the xmpDM:copyright value. -// -// 4. In all cases, delete the xmpDM:copyright property. - -static void -MigrateAudioCopyright ( XMPMeta * xmp, XMP_Node * dmCopyright ) -{ - - try { - - std::string & dmValue = dmCopyright->value; - static const char * kDoubleLF = "\xA\xA"; - - XMP_Node * dcSchema = FindSchemaNode ( &xmp->tree, kXMP_NS_DC, kXMP_CreateNodes ); - XMP_Node * dcRightsArray = FindChildNode ( dcSchema, "dc:rights", kXMP_ExistingOnly ); - - if ( (dcRightsArray == 0) || dcRightsArray->children.empty() ) { - - // 1. No dc:rights array, create from double linefeed and xmpDM:copyright. - dmValue.insert ( 0, kDoubleLF ); - xmp->SetLocalizedText ( kXMP_NS_DC, "rights", "", "x-default", dmValue.c_str(), 0 ); - - } else { - - std::string xdefaultStr ( "x-default" ); - - XMP_Index xdIndex = LookupLangItem ( dcRightsArray, xdefaultStr ); - - if ( xdIndex < 0 ) { - // 2. No x-default item, create from the first item. - XMP_StringPtr firstValue = dcRightsArray->children[0]->value.c_str(); - xmp->SetLocalizedText ( kXMP_NS_DC, "rights", "", "x-default", firstValue, 0 ); - xdIndex = LookupLangItem ( dcRightsArray, xdefaultStr ); - } - - // 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 ); - - if ( lfPos < 0 ) { - - // 3A. No double LF, compare whole values. - if ( dmValue != defaultValue ) { - // 3A2. Append the xmpDM:copyright to the x-default item. - defaultValue += kDoubleLF; - defaultValue += dmValue; - } - - } else { - - // 3B. Has double LF, compare the tail. - if ( defaultValue.compare ( lfPos+2, std::string::npos, dmValue ) != 0 ) { - // 3B2. Replace the x-default tail. - defaultValue.replace ( lfPos+2, std::string::npos, dmValue ); - } - - } - - } - - // 4. Get rid of the xmpDM:copyright. - xmp->DeleteProperty ( kXMP_NS_DM, "copyright" ); - - } catch ( ... ) { - // Don't let failures (like a bad dc:rights form) stop other cleanup. - } - -} // MigrateAudioCopyright - - -// ------------------------------------------------------------------------------------------------- -// RepairAltText -// ------------- -// -// Make sure that the array is well-formed AltText. Each item must be simple and have an xml:lang -// qualifier. If repairs are needed, keep simple non-empty items by adding the xml:lang. - -static void -RepairAltText ( XMP_Node & tree, XMP_StringPtr schemaNS, XMP_StringPtr arrayName ) -{ - XMP_Node * schemaNode = FindSchemaNode ( &tree, schemaNS, kXMP_ExistingOnly ); - if ( schemaNode == 0 ) return; - - XMP_Node * arrayNode = FindChildNode ( schemaNode, arrayName, kXMP_ExistingOnly ); - if ( (arrayNode == 0) || XMP_ArrayIsAltText ( arrayNode->options ) ) return; // Already OK. - - if ( ! XMP_PropIsArray ( arrayNode->options ) ) return; // ! Not even an array, leave it alone. - // *** Should probably change simple values to LangAlt with 'x-default' item. - - arrayNode->options |= (kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText); - - for ( int i = arrayNode->children.size()-1; i >= 0; --i ) { // ! Need a signed index type. - - XMP_Node * currChild = arrayNode->children[i]; - - if ( ! XMP_PropIsSimple ( currChild->options ) ) { - - // Delete non-simple children. - delete ( currChild ); - arrayNode->children.erase ( arrayNode->children.begin() + i ); - - } else if ( ! XMP_PropHasLang ( currChild->options ) ) { - - if ( currChild->value.empty() ) { - - // Delete empty valued children that have no xml:lang. - delete ( currChild ); - arrayNode->children.erase ( arrayNode->children.begin() + i ); - - } else { - - // Add an xml:lang qualifier with the value "x-repair". - XMP_Node * repairLang = new XMP_Node ( currChild, "xml:lang", "x-repair", kXMP_PropIsQualifier ); - if ( currChild->qualifiers.empty() ) { - currChild->qualifiers.push_back ( repairLang ); - } else { - currChild->qualifiers.insert ( currChild->qualifiers.begin(), repairLang ); - } - currChild->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang); - - } - - } - - } - -} // RepairAltText - - -// ------------------------------------------------------------------------------------------------- -// TouchUpDataModel -// ---------------- - -static void -TouchUpDataModel ( XMPMeta * xmp ) -{ - XMP_Node & tree = xmp->tree; - - // Do special case touch ups for certain schema. - - XMP_Node * currSchema = 0; - - currSchema = FindSchemaNode ( &tree, kXMP_NS_EXIF, kXMP_ExistingOnly ); - if ( currSchema != 0 ) { - - // Do a special case fix for exif:GPSTimeStamp. - XMP_Node * gpsDateTime = FindChildNode ( currSchema, "exif:GPSTimeStamp", kXMP_ExistingOnly ); - if ( gpsDateTime != 0 ) FixGPSTimeStamp ( currSchema, gpsDateTime ); - - // *** Should probably have RepairAltText change simple values to LangAlt with 'x-default' item. - // *** For now just do this for exif:UserComment, the one case we know about, late in cycle fix. - XMP_Node * userComment = FindChildNode ( currSchema, "exif:UserComment", kXMP_ExistingOnly ); - if ( (userComment != 0) && XMP_PropIsSimple ( userComment->options ) ) { - XMP_Node * newChild = new XMP_Node ( userComment, kXMP_ArrayItemName, - userComment->value.c_str(), userComment->options ); - newChild->qualifiers.swap ( userComment->qualifiers ); - if ( ! XMP_PropHasLang ( newChild->options ) ) { - XMP_Node * langQual = new XMP_Node ( newChild, "xml:lang", "x-default", kXMP_PropIsQualifier ); - newChild->qualifiers.insert ( newChild->qualifiers.begin(), langQual ); - newChild->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang); - } - userComment->value.erase(); - userComment->options = kXMP_PropArrayFormMask; // ! Happens to have all the right bits. - userComment->children.push_back ( newChild ); - } - - } - - currSchema = FindSchemaNode ( &tree, kXMP_NS_DM, kXMP_ExistingOnly ); - if ( currSchema != 0 ) { - // Do a special case migration of xmpDM:copyright to dc:rights['x-default']. Do this before - // the dc: touch up since it can affect the dc: schema. - XMP_Node * dmCopyright = FindChildNode ( currSchema, "xmpDM:copyright", kXMP_ExistingOnly ); - if ( dmCopyright != 0 ) MigrateAudioCopyright ( xmp, dmCopyright ); - } - - currSchema = FindSchemaNode ( &tree, kXMP_NS_DC, kXMP_ExistingOnly ); - if ( currSchema != 0 ) { - // Do a special case fix for dc:subject, make sure it is an unordered array. - XMP_Node * dcSubject = FindChildNode ( currSchema, "dc:subject", kXMP_ExistingOnly ); - if ( dcSubject != 0 ) { - XMP_OptionBits keepMask = static_cast(~(kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText)); - dcSubject->options &= keepMask; // Make sure any ordered array bits are clear. - } - } - - // Fix any broken AltText arrays that we know about. - - RepairAltText ( tree, kXMP_NS_DC, "dc:description" ); // ! Note inclusion of prefixes for direct node lookup! - RepairAltText ( tree, kXMP_NS_DC, "dc:rights" ); - RepairAltText ( tree, kXMP_NS_DC, "dc:title" ); - RepairAltText ( tree, kXMP_NS_XMP_Rights, "xmpRights:UsageTerms" ); - RepairAltText ( tree, kXMP_NS_EXIF, "exif:UserComment" ); - - // Tweak old XMP: Move an instance ID from rdf:about to the xmpMM:InstanceID property. An old - // instance ID usually looks like "uuid:bac965c4-9d87-11d9-9a30-000d936b79c4", plus InDesign - // 3.0 wrote them like "bac965c4-9d87-11d9-9a30-000d936b79c4". If the name looks like a UUID - // simply move it to xmpMM:InstanceID, don't worry about any existing xmpMM:InstanceID. Both - // will only be present when a newer file with the xmpMM:InstanceID property is updated by an - // old app that uses rdf:about. - - if ( ! tree.name.empty() ) { - - bool nameIsUUID = false; - XMP_StringPtr nameStr = tree.name.c_str(); - - if ( XMP_LitNMatch ( nameStr, "uuid:", 5 ) ) { - - nameIsUUID = true; - - } else if ( tree.name.size() == 36 ) { - - nameIsUUID = true; // ! Assume true, we'll set it to false below if not. - for ( int i = 0; i < 36; ++i ) { - char ch = nameStr[i]; - if ( ch == '-' ) { - if ( (i == 8) || (i == 13) || (i == 18) || (i == 23) ) continue; - nameIsUUID = false; - break; - } else { - if ( (('0' <= ch) && (ch <= '9')) || (('a' <= ch) && (ch <= 'z')) ) continue; - nameIsUUID = false; - break; - } - } - - } - - if ( nameIsUUID ) { - - XMP_ExpandedXPath expPath; - ExpandXPath ( kXMP_NS_XMP_MM, "InstanceID", &expPath ); - XMP_Node * idNode = FindNode ( &tree, expPath, kXMP_CreateNodes, 0 ); - if ( idNode == 0 ) XMP_Throw ( "Failure creating xmpMM:InstanceID", kXMPErr_InternalFailure ); - - idNode->options = 0; // Clobber any existing xmpMM:InstanceID. - idNode->value = tree.name; - idNode->RemoveChildren(); - idNode->RemoveQualifiers(); - - tree.name.erase(); - - } - - } - -} // TouchUpDataModel - - -// ------------------------------------------------------------------------------------------------- -// DetermineInputEncoding -// ---------------------- -// -// Try to determine the character encoding, making a guess if the input is too short. We make some -// simplifying assumtions: the first character must be U+FEFF or ASCII, U+0000 is not allowed. The -// XML 1.1 spec is even more strict, UTF-16 XML documents must begin with U+FEFF, and the first -// "real" character must be '<'. Ignoring the XML declaration, the first XML character could be '<', -// space, tab, CR, or LF. -// -// The possible input sequences are: -// -// Cases with U+FEFF -// EF BB BF -- - UTF-8 -// FE FF -- -- - Big endian UTF-16 -// 00 00 FE FF - Big endian UTF 32 -// FF FE 00 00 - Little endian UTF-32 -// FF FE -- -- - Little endian UTF-16 -// -// Cases with ASCII -// nn mm -- -- - UTF-8 - -// 00 00 00 nn - Big endian UTF-32 -// 00 nn -- -- - Big endian UTF-16 -// nn 00 00 00 - Little endian UTF-32 -// nn 00 -- -- - Little endian UTF-16 -// -// ! We don't check for full patterns, or for errors. We just check enough to determine what the -// ! only possible (or reasonable) case would be. - -static XMP_OptionBits -DetermineInputEncoding ( const XMP_Uns8 * buffer, size_t length ) -{ - if ( length < 2 ) return kXMP_EncodeUTF8; - - XMP_Uns8 * uniChar = (XMP_Uns8*)buffer; // ! Make sure comparisons are unsigned. - - if ( uniChar[0] == 0 ) { - - // These cases are: - // 00 nn -- -- - Big endian UTF-16 - // 00 00 00 nn - Big endian UTF-32 - // 00 00 FE FF - Big endian UTF 32 - - if ( (length < 4) || (uniChar[1] != 0) ) return kXMP_EncodeUTF16Big; - return kXMP_EncodeUTF32Big; - - } else if ( uniChar[0] < 0x80 ) { - - // These cases are: - // nn mm -- -- - UTF-8, includes EF BB BF case - // nn 00 00 00 - Little endian UTF-32 - // nn 00 -- -- - Little endian UTF-16 - - if ( uniChar[1] != 0 ) return kXMP_EncodeUTF8; - if ( (length < 4) || (uniChar[2] != 0) ) return kXMP_EncodeUTF16Little; - return kXMP_EncodeUTF32Little; - - } else { - - // These cases are: - // EF BB BF -- - UTF-8 - // FE FF -- -- - Big endian UTF-16 - // FF FE 00 00 - Little endian UTF-32 - // FF FE -- -- - Little endian UTF-16 - - if ( uniChar[0] == 0xEF ) return kXMP_EncodeUTF8; - if ( uniChar[0] == 0xFE ) return kXMP_EncodeUTF16Big; - if ( (length < 4) || (uniChar[2] != 0) ) return kXMP_EncodeUTF16Little; - return kXMP_EncodeUTF32Little; - - } - -} // DetermineInputEncoding - - -// ------------------------------------------------------------------------------------------------- -// CountUTF8 -// --------- -// -// Look for a valid multi-byte UTF-8 sequence and return its length. Returns 0 for an invalid UTF-8 -// sequence. Returns a negative value for a partial valid sequence at the end of the buffer. -// -// The checking is not strict. We simply count the number of high order 1 bits in the first byte, -// then look for n-1 following bytes whose high order 2 bits are 1 and 0. We do not check for a -// minimal length representation of the codepoint, or that the codepoint is defined by Unicode. - -static int -CountUTF8 ( const XMP_Uns8 * charStart, const XMP_Uns8 * bufEnd ) -{ - XMP_Assert ( charStart < bufEnd ); // Catch this in debug builds. - if ( charStart >= bufEnd ) return 0; // Don't run-on in release builds. - if ( (*charStart & 0xC0) != 0xC0 ) return 0; // Must have at least 2 high bits set. - - int byteCount = 2; - XMP_Uns8 firstByte = *charStart; - for ( firstByte = firstByte << 2; (firstByte & 0x80) != 0; firstByte = firstByte << 1 ) ++byteCount; - - if ( (charStart + byteCount) > bufEnd ) return -byteCount; - - for ( int i = 1; i < byteCount; ++i ) { - if ( (charStart[i] & 0xC0) != 0x80 ) return 0; - } - - return byteCount; - -} // CountUTF8 - - -// ------------------------------------------------------------------------------------------------- -// CountControlEscape -// ------------------ -// -// Look for a numeric escape sequence for a "prohibited" ASCII control character. These are 0x7F, -// and the range 0x00..0x1F except for tab/LF/CR. Return 0 if this is definitely not a numeric -// escape, the length of the escape if found, or a negative value for a partial escape. - -static int -CountControlEscape ( const XMP_Uns8 * escStart, const XMP_Uns8 * bufEnd ) -{ - XMP_Assert ( escStart < bufEnd ); // Catch this in debug builds. - if ( escStart >= bufEnd ) return 0; // Don't run-on in release builds. - XMP_Assert ( *escStart == '&' ); - - size_t tailLen = bufEnd - escStart; - if ( tailLen < 5 ) return -1; // Don't need a more thorough check, we'll catch it on the next pass. - - if ( strncmp ( (char*)escStart, "&#x", 3 ) != 0 ) return 0; - - XMP_Uns8 escValue = 0; - const XMP_Uns8 * escPos = escStart + 3; - - if ( ('0' <= *escPos) && (*escPos <= '9') ) { - escValue = *escPos - '0'; - ++escPos; - } else if ( ('A' <= *escPos) && (*escPos <= 'F') ) { - escValue = *escPos - 'A' + 10; - ++escPos; - } else if ( ('a' <= *escPos) && (*escPos <= 'f') ) { - escValue = *escPos - 'a' + 10; - ++escPos; - } - - if ( ('0' <= *escPos) && (*escPos <= '9') ) { - escValue = (escValue << 4) + (*escPos - '0'); - ++escPos; - } else if ( ('A' <= *escPos) && (*escPos <= 'F') ) { - escValue = (escValue << 4) + (*escPos - 'A' + 10); - ++escPos; - } else if ( ('a' <= *escPos) && (*escPos <= 'f') ) { - escValue = (escValue << 4) + (*escPos - 'a' + 10); - ++escPos; - } - - if ( escPos == bufEnd ) return -1; // Partial escape. - if ( *escPos != ';' ) return 0; - - size_t escLen = escPos - escStart + 1; - if ( escLen < 5 ) return 0; // ! Catch "&#x;". - - if ( (escValue == kTab) || (escValue == kLF) || (escValue == kCR) ) return 0; // An allowed escape. - - return escLen; // Found a full "prohibited" numeric escape. - -} // CountControlEscape - - -// ------------------------------------------------------------------------------------------------- -// ProcessUTF8Portion -// ------------------ -// -// Early versions of the XMP spec mentioned allowing ISO Latin-1 input. There are also problems with -// some clients placing ASCII control characters within XMP values. This is an XML problem, the XML -// spec only allows tab (0x09), LF (0x0A), and CR (0x0D) from the 0x00..0x1F range. As a concession -// to this we scan 8-bit input for byte sequences that are not valid UTF-8 or in the 0x00..0x1F -// range and replace each byte as follows: -// 0x00..0x1F - Replace with a space, except for tab, CR, and LF. -// 0x7F - Replace with a space. This is ASCII Delete, not allowed by ISO Latin-1. -// 0x80..0x9F - Replace with the UTF-8 for a corresponding Unicode character. -// 0xA0..0XFF - Replace with the UTF-8 for a corresponding Unicode character. -// -// The 0x80..0x9F range is not defined by Latin-1. But the Windows 1252 code page defines these and -// is otherwise the same as Latin-1. -// -// For at least historical compatibility reasons we also find and replace singly escaped ASCII -// control characters. The Expat parser we're using does not allow numeric escapes like "". -// The XML spec is clear that raw controls are not allowed (in the RestrictedChar set), but it isn't -// as clear about numeric escapes for them. At any rate, Expat complains, so we treat the numeric -// escapes like raw characters and replace them with a space. -// -// We check for 1 or 2 hex digits (" " or " ") and upper or lower case (" " or " "). -// The full escape sequence is 5 or 6 bytes. - -static size_t -ProcessUTF8Portion ( XMLParserAdapter * xmlParser, - const XMP_Uns8 * buffer, - size_t length, - bool last ) -{ - const XMP_Uns8 * bufEnd = buffer + length; - - const XMP_Uns8 * spanEnd; - - // `buffer` is copied into this std::string. If `buffer` only - // contains valid UTF-8 and no escape characters, then the copy - // will be identical to the original, but invalid characters are - // replaced - usually with a space character. This std::string was - // added as a performance fix for: - // https://github.com/Exiv2/exiv2/security/advisories/GHSA-w8mv-g8qq-36mj - // Previously, the code was repeatedly calling - // `xmlParser->ParseBuffer()`, which turned out to have quadratic - // complexity, because expat kept reparsing the entire string from - // the beginning. - std::string copy; - - for ( spanEnd = buffer; spanEnd < bufEnd; ++spanEnd ) { - - if ( (0x20 <= *spanEnd) && (*spanEnd <= 0x7E) && (*spanEnd != '&') ) { - copy.push_back(*spanEnd); - continue; // A regular ASCII character. - } - - if ( *spanEnd >= 0x80 ) { - - // See if this is a multi-byte UTF-8 sequence, or a Latin-1 character to replace. - - int uniLen = CountUTF8 ( spanEnd, bufEnd ); - - if ( uniLen > 0 ) { - - // A valid UTF-8 character, keep it as-is. - copy.append((const char*)spanEnd, uniLen); - spanEnd += uniLen - 1; // ! The loop increment will put back the +1. - - } else if ( (uniLen < 0) && (! last) ) { - - // Have a partial UTF-8 character at the end of the buffer and more input coming. - xmlParser->ParseBuffer ( copy.c_str(), copy.size(), false ); - return (spanEnd - buffer); - - } else { - - // Not a valid UTF-8 sequence. Replace the first byte with the Latin-1 equivalent. - const char * replacement = kReplaceLatin1 [ *spanEnd - 0x80 ]; - copy.append ( replacement ); - - } - - } else if ( (*spanEnd < 0x20) || (*spanEnd == 0x7F) ) { - - // Replace ASCII controls other than tab, LF, and CR with a space. - - if ( (*spanEnd == kTab) || (*spanEnd == kLF) || (*spanEnd == kCR) ) { - copy.push_back(*spanEnd); - continue; - } - - copy.push_back(' '); - - } else { - - // See if this is a numeric escape sequence for a prohibited ASCII control. - - XMP_Assert ( *spanEnd == '&' ); - int escLen = CountControlEscape ( spanEnd, bufEnd ); - - if ( escLen < 0 ) { - - // Have a partial numeric escape in this buffer, wait for more input. - if ( last ) { - copy.push_back('&'); - continue; // No more buffers, not an escape, absorb as normal input. - } - xmlParser->ParseBuffer ( copy.c_str(), copy.size(), false ); - return (spanEnd - buffer); - - } else if ( escLen > 0 ) { - - // Have a complete numeric escape to replace. - copy.push_back(' '); - spanEnd = spanEnd + escLen - 1; // ! The loop continuation will increment spanEnd! - - } else { - copy.push_back('&'); - } - - } - - } - - XMP_Assert ( spanEnd == bufEnd ); - copy.push_back(' '); - xmlParser->ParseBuffer ( copy.c_str(), copy.size(), true ); - return length; - -} // ProcessUTF8Portion - - -// ------------------------------------------------------------------------------------------------- -// ParseFromBuffer -// --------------- -// -// Although most clients will probably parse everything in one call, we have a buffered API model -// and need to support even the extreme case of 1 byte at a time parsing. This is considerably -// complicated by some special cases for 8-bit input. Because of this, the first thing we do is -// determine whether the input is 8-bit, UTF-16, or UTF-32. -// -// Both the 8-bit special cases and the encoding determination are easier to do with 8 bytes or more -// of input. The XMLParserAdapter class has a pending-input buffer for this. At the start of parsing -// we (moght) try to fill this buffer before determining the input character encoding. After that, -// we (might) use this buffer with the current input to simplify the logic in Process8BitInput. The -// "(might)" part means that we don't actually use the pending-input buffer unless we have to. In -// particular, the common case of single-buffer parsing won't use it. - -void -XMPMeta::ParseFromBuffer ( XMP_StringPtr buffer, - XMP_StringLen xmpSize, - XMP_OptionBits options ) -{ - if ( (buffer == 0) && (xmpSize != 0) ) XMP_Throw ( "Null parse buffer", kXMPErr_BadParam ); - if ( xmpSize == kXMP_UseNullTermination ) xmpSize = strlen ( buffer ); - - const bool lastClientCall = ((options & kXMP_ParseMoreBuffers) == 0); // *** Could use FlagIsSet & FlagIsClear macros. - - this->tree.ClearNode(); // Make sure the target XMP object is totally empty. - - if ( this->xmlParser == 0 ) { - if ( (xmpSize == 0) && lastClientCall ) return; // Tolerate empty parse. Expat complains if there are no XML elements. - this->xmlParser = XMP_NewExpatAdapter(); - } - - XMLParserAdapter& parser = *this->xmlParser; - - #if 0 // XMP_DebugBuild - if ( parser.parseLog != 0 ) { - char message [200]; // AUDIT: Using sizeof(message) below for snprintf length is safe. - snprintf ( message, sizeof(message), "", // AUDIT: See above. - xmpSize, options, (lastClientCall ? " (last)" : "") ); - fwrite ( message, 1, strlen(message), parser.parseLog ); - fflush ( parser.parseLog ); - } - #endif - - try { // Cleanup the tree and xmlParser if anything fails. - - // Determine the character encoding before doing any real parsing. This is needed to do the - // 8-bit special processing. - - if ( parser.charEncoding == XMP_OptionBits(-1) ) { - - if ( (parser.pendingCount == 0) && (xmpSize >= kXMLPendingInputMax) ) { - - // This ought to be the common case, the first buffer is big enough. - parser.charEncoding = DetermineInputEncoding ( (XMP_Uns8*)buffer, xmpSize ); - - } else { - - // Try to fill the pendingInput buffer before calling DetermineInputEncoding. - - size_t pendingOverlap = kXMLPendingInputMax - parser.pendingCount; - if ( pendingOverlap > xmpSize ) pendingOverlap = xmpSize; - - memcpy ( &parser.pendingInput[parser.pendingCount], buffer, pendingOverlap ); // AUDIT: Count is safe. - buffer += pendingOverlap; - xmpSize -= pendingOverlap; - parser.pendingCount += pendingOverlap; - - if ( (! lastClientCall) && (parser.pendingCount < kXMLPendingInputMax) ) return; - parser.charEncoding = DetermineInputEncoding ( parser.pendingInput, parser.pendingCount ); - - #if Trace_ParsingHackery - fprintf ( stderr, "XMP Character encoding is %d\n", parser.charEncoding ); - #endif - - } - - } - - // We have the character encoding. Process UTF-16 and UTF-32 as is. UTF-8 needs special - // handling to take care of things like ISO Latin-1 or unescaped ASCII controls. - - XMP_Assert ( parser.charEncoding != XMP_OptionBits(-1) ); - - if ( parser.charEncoding != kXMP_EncodeUTF8 ) { - - if ( parser.pendingCount > 0 ) { - // Might have pendingInput from the above portion to determine the character encoding. - parser.ParseBuffer ( parser.pendingInput, parser.pendingCount, false ); - } - parser.ParseBuffer ( buffer, xmpSize, lastClientCall ); - - } else { - - #if Trace_ParsingHackery - fprintf ( stderr, "Parsing %d bytes @ %.8X, %s, %d pending, context: %.8s\n", - xmpSize, buffer, (lastClientCall ? "last" : "not last"), parser.pendingCount, buffer ); - #endif - - // The UTF-8 processing is a bit complex due to the need to tolerate ISO Latin-1 input. - // This is done by scanning the input for byte sequences that are not valid UTF-8, - // assuming they are Latin-1 characters in the range 0x80..0xFF. This requires saving a - // pending input buffer to handle partial UTF-8 sequences at the end of a buffer. - - while ( parser.pendingCount > 0 ) { - - // We've got some leftover input, process it first then continue with the current - // buffer. Try to fill the pendingInput buffer before parsing further. We use a loop - // for weird edge cases like a 2 byte input buffer, using 1 byte for pendingInput, - // then having a partial UTF-8 end and need to absorb more. - - size_t pendingOverlap = kXMLPendingInputMax - parser.pendingCount; - if ( pendingOverlap > xmpSize ) pendingOverlap = xmpSize; - - memcpy ( &parser.pendingInput[parser.pendingCount], buffer, pendingOverlap ); // AUDIT: Count is safe. - parser.pendingCount += pendingOverlap; - buffer += pendingOverlap; - xmpSize -= pendingOverlap; - - if ( (! lastClientCall) && (parser.pendingCount < kXMLPendingInputMax) ) return; - size_t bytesDone = ProcessUTF8Portion ( &parser, parser.pendingInput, parser.pendingCount, lastClientCall ); - size_t bytesLeft = parser.pendingCount - bytesDone; - - #if Trace_ParsingHackery - fprintf ( stderr, " ProcessUTF8Portion handled %d pending bytes\n", bytesDone ); - #endif - - if ( bytesDone == parser.pendingCount ) { - - // Done with all of the pending input, move on to the current buffer. - parser.pendingCount = 0; - - } else if ( bytesLeft <= pendingOverlap ) { - - // The leftover pending input all came from the current buffer. Exit this loop. - buffer -= bytesLeft; - xmpSize += bytesLeft; - parser.pendingCount = 0; - - } else if ( xmpSize > 0 ) { - - // Pull more of the current buffer into the pending input and try again. - // Backup by this pass's overlap so the loop entry code runs OK. - parser.pendingCount -= pendingOverlap; - buffer -= pendingOverlap; - xmpSize += pendingOverlap; - - } else { - - // There is no more of the current buffer. Wait for more. Partial sequences at - // the end of the last buffer should be treated as Latin-1 by ProcessUTF8Portion. - XMP_Assert ( ! lastClientCall ); - parser.pendingCount = bytesLeft; - memcpy ( &parser.pendingInput[0], &parser.pendingInput[bytesDone], bytesLeft ); // AUDIT: Count is safe. - return; - - } - - } - - // Done with the pending input, process the current buffer. - - size_t bytesDone = ProcessUTF8Portion ( &parser, (XMP_Uns8*)buffer, xmpSize, lastClientCall ); - - #if Trace_ParsingHackery - fprintf ( stderr, " ProcessUTF8Portion handled %d additional bytes\n", bytesDone ); - #endif - - if ( bytesDone < xmpSize ) { - - XMP_Assert ( ! lastClientCall ); - size_t bytesLeft = xmpSize - bytesDone; - if ( bytesLeft > kXMLPendingInputMax ) XMP_Throw ( "Parser bytesLeft too large", kXMPErr_InternalFailure ); - - memcpy ( parser.pendingInput, &buffer[bytesDone], bytesLeft ); // AUDIT: Count is safe. - parser.pendingCount = bytesLeft; - return; // Wait for the next buffer. - - } - - } - - if ( lastClientCall ) { - - #if XMP_DebugBuild && DumpXMLParseTree - if ( parser.parseLog == 0 ) parser.parseLog = stdout; - DumpXMLTree ( parser.parseLog, parser.tree, 0 ); - #endif - - const XML_Node * xmlRoot = FindRootNode ( this, *this->xmlParser, options ); - - if ( xmlRoot != 0 ) { - - ProcessRDF ( &this->tree, *xmlRoot, options ); - NormalizeDCArrays ( &this->tree ); - if ( this->tree.options & kXMP_PropHasAliases ) MoveExplicitAliases ( &this->tree, options ); - TouchUpDataModel ( this ); - - // Delete empty schema nodes. Do this last, other cleanup can make empty schema. - size_t schemaNum = 0; - while ( schemaNum < this->tree.children.size() ) { - XMP_Node * currSchema = this->tree.children[schemaNum]; - if ( currSchema->children.size() > 0 ) { - ++schemaNum; - } else { - delete this->tree.children[schemaNum]; // ! Delete the schema node itself. - this->tree.children.erase ( this->tree.children.begin() + schemaNum ); - } - } - - } - - delete this->xmlParser; - this->xmlParser = 0; - - } - - } catch ( ... ) { - - delete this->xmlParser; - this->xmlParser = 0; - prevTkVer = 0; - this->tree.ClearNode(); - throw; - - } - -} // ParseFromBuffer - -// ================================================================================================= diff --git a/xmpsdk/src/XMPMeta-Serialize.cpp b/xmpsdk/src/XMPMeta-Serialize.cpp deleted file mode 100644 index 70a7b02093..0000000000 --- a/xmpsdk/src/XMPMeta-Serialize.cpp +++ /dev/null @@ -1,1342 +0,0 @@ -// ================================================================================================= // Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPMeta.hpp" - -#include "XMP_Version.h" -#include "UnicodeInlines.incl_cpp" -#include "UnicodeConversions.hpp" - -#if XMP_DebugBuild - #include -#endif - -using namespace std; - -#if XMP_WinBuild -#ifdef _MSC_VER - #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 -#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 -// ========================= - -static const char * kPacketHeader = ""; -static const char * kPacketTrailer = ""; // ! The w/r is at [size-4]. - -static const char * kRDF_XMPMetaStart = ""; -static const char * kRDF_RDFEnd = ""; - -static const char * kRDF_SchemaStart = ""; - -static const char * kRDF_StructStart = ""; -static const char * kRDF_StructEnd = ""; - -static const char * kRDF_BagStart = ""; - -static const char * kRDF_ItemStart = ""; - -static const char * kRDF_ValueStart = ""; - - -// ================================================================================================= -// Static Variables -// ================ - - -// ================================================================================================= -// Local Utilities -// =============== - - -// ------------------------------------------------------------------------------------------------- -// EstimateRDFSize -// --------------- - -// *** Pull the strlen(kXyz) calls into constants. - -static size_t -EstimateRDFSize ( const XMP_Node * currNode, XMP_Index indent, size_t indentLen ) -{ - size_t outputLen = 2 * (indent*indentLen + currNode->name.size() + 4); // The property element tags. - - if ( ! currNode->qualifiers.empty() ) { - // This node has qualifiers, assume it is written using rdf:value and estimate the qualifiers. - - indent += 2; // Everything else is indented inside the rdf:Description element. - outputLen += 2 * ((indent-1)*indentLen + strlen(kRDF_StructStart) + 2); // The rdf:Description tags. - outputLen += 2 * (indent*indentLen + strlen(kRDF_ValueStart) + 2); // The rdf:value tags. - - for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - const XMP_Node * currQual = currNode->qualifiers[qualNum]; - outputLen += EstimateRDFSize ( currQual, indent, indentLen ); - } - - } - - if ( currNode->options & kXMP_PropValueIsStruct ) { - indent += 1; - outputLen += 2 * (indent*indentLen + strlen(kRDF_StructStart) + 2); // The rdf:Description tags. - } else if ( currNode->options & kXMP_PropValueIsArray ) { - indent += 2; - outputLen += 2 * ((indent-1)*indentLen + strlen(kRDF_BagStart) + 2); // The rdf:Bag/Seq/Alt tags. - outputLen += 2 * currNode->children.size() * (strlen(kRDF_ItemStart) + 2); // The rdf:li tags, indent counted in children. - } else if ( ! (currNode->options & kXMP_SchemaNode) ) { - outputLen += currNode->value.size(); // This is a leaf value node. - } - - for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) { - const XMP_Node * currChild = currNode->children[childNum]; - outputLen += EstimateRDFSize ( currChild, indent+1, indentLen ); - } - - return outputLen; - -} // EstimateRDFSize - - -// ------------------------------------------------------------------------------------------------- -// DeclareOneNamespace -// ------------------- - -static void -DeclareOneNamespace ( const XMP_VarString & nsPrefix, - const XMP_VarString & nsURI, - XMP_VarString & usedNS, // ! A catenation of the prefixes with colons. - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent ) -{ - size_t nsPos = usedNS.find ( nsPrefix ); - - if ( nsPos == XMP_VarString::npos ) { - - outputStr += newline; - for ( ; indent > 0; --indent ) outputStr += indentStr; - outputStr += "xmlns:"; - outputStr += nsPrefix; - outputStr[outputStr.size()-1] = '='; // Change the colon to =. - outputStr += '"'; - outputStr += nsURI; - outputStr += '"'; - - usedNS += nsPrefix; - - } - -} // DeclareOneNamespace - - -// ------------------------------------------------------------------------------------------------- -// DeclareElemNamespace -// -------------------- - -static void -DeclareElemNamespace ( const XMP_VarString & elemName, - XMP_VarString & usedNS, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent ) -{ - size_t colonPos = elemName.find ( ':' ); - - if ( colonPos != XMP_VarString::npos ) { - XMP_VarString nsPrefix ( elemName.substr ( 0, colonPos+1 ) ); - XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix ); - XMP_Enforce ( prefixPos != sNamespacePrefixToURIMap->end() ); - DeclareOneNamespace ( nsPrefix, prefixPos->second, usedNS, outputStr, newline, indentStr, indent ); - } - -} // DeclareElemNamespace - - -// ------------------------------------------------------------------------------------------------- -// DeclareUsedNamespaces -// --------------------- - -// ??? Should iterators be passed by reference to avoid temp copies? - -static void -DeclareUsedNamespaces ( const XMP_Node * currNode, - XMP_VarString & usedNS, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent ) -{ - - if ( currNode->options & kXMP_SchemaNode ) { - // The schema node name is the URI, the value is the prefix. - DeclareOneNamespace ( currNode->value, currNode->name, usedNS, outputStr, newline, indentStr, indent ); - } else if ( currNode->options & kXMP_PropValueIsStruct ) { - for ( size_t fieldNum = 0, fieldLim = currNode->children.size(); fieldNum < fieldLim; ++fieldNum ) { - const XMP_Node * currField = currNode->children[fieldNum]; - DeclareElemNamespace ( currField->name, usedNS, outputStr, newline, indentStr, indent ); - } - } - - for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) { - const XMP_Node * currChild = currNode->children[childNum]; - DeclareUsedNamespaces ( currChild, usedNS, outputStr, newline, indentStr, indent ); - } - - for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - const XMP_Node * currQual = currNode->qualifiers[qualNum]; - DeclareElemNamespace ( currQual->name, usedNS, outputStr, newline, indentStr, indent ); - DeclareUsedNamespaces ( currQual, usedNS, outputStr, newline, indentStr, indent ); - } - -} // DeclareUsedNamespaces - -// ------------------------------------------------------------------------------------------------- -// EmitRDFArrayTag -// --------------- - -// ??? Should iterators be passed by reference to avoid temp copies? - -enum { - kIsStartTag = true, - kIsEndTag = false -}; - -static void -EmitRDFArrayTag ( XMP_OptionBits arrayForm, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent, - XMP_Index arraySize, - bool isStartTag ) -{ - if ( (! isStartTag) && (arraySize == 0) ) return; - - for ( XMP_Index level = indent; level > 0; --level ) outputStr += indentStr; - if ( isStartTag ) { - outputStr += "', and ASCII controls (tab, LF, CR). In -// addition, '"' is escaped for attributes. For efficiency, this is done in a double loop. The outer -// loop makes sure the whole value is processed. The inner loop does a contiguous unescaped run -// followed by one escaped character (if we're not at the end). -// -// We depend on parsing and SetProperty logic to make sure there are no invalid ASCII controls in -// the XMP values. The XML spec only allows tab, LF, and CR. Others are not even allowed as -// numeric escape sequences. - -enum { - kForAttribute = true, - kForElement = false -}; - -static void -AppendNodeValue ( XMP_VarString & outputStr, const XMP_VarString & value, bool forAttribute ) -{ - - unsigned char * runStart = (unsigned char *) value.c_str(); - unsigned char * runLimit = runStart + value.size(); - unsigned char * runEnd; - unsigned char ch=0; - - while ( runStart < runLimit ) { - - for ( runEnd = runStart; runEnd < runLimit; ++runEnd ) { - ch = *runEnd; - if ( forAttribute && (ch == '"') ) break; - if ( (ch < 0x20) || (ch == '&') || (ch == '<') || (ch == '>') ) break; - } - - outputStr.append ( (char *) runStart, (runEnd - runStart) ); - - if ( runEnd < runLimit ) { - - if ( ch < 0x20 ) { - - XMP_Assert ( (ch == kTab) || (ch == kLF) || (ch == kCR) ); - - char hexBuf[16]; - memcpy ( hexBuf, "&#xn;", 5 ); - hexBuf[3] = kHexDigits[ch&0xF]; - outputStr.append ( hexBuf, 5 ); - - } else { - - if ( ch == '"' ) { - outputStr += """; - } else if ( ch == '<' ) { - outputStr += "<"; - } else if ( ch == '>' ) { - outputStr += ">"; - } else { - XMP_Assert ( ch == '&' ); - outputStr += "&"; - } - - } - - ++runEnd; - - } - - runStart = runEnd; - - } - -} // AppendNodeValue - - -// ------------------------------------------------------------------------------------------------- -// CanBeRDFAttrProp -// ---------------- - -static bool -CanBeRDFAttrProp ( const XMP_Node * propNode ) -{ - - if ( propNode->name[0] == '[' ) return false; - if ( ! propNode->qualifiers.empty() ) return false; - if ( propNode->options & kXMP_PropValueIsURI ) return false; - if ( propNode->options & kXMP_PropCompositeMask ) return false; - - return true; - -} // CanBeRDFAttrProp - - -// ------------------------------------------------------------------------------------------------- -// IsRDFAttrQualifier -// ------------------ - -static XMP_StringPtr sAttrQualifiers[] = { "xml:lang", "rdf:resource", "rdf:ID", "rdf:bagID", "rdf:nodeID", "" }; - -static bool -IsRDFAttrQualifier ( XMP_VarString qualName ) -{ - - for ( size_t i = 0; *sAttrQualifiers[i] != 0; ++i ) { - if ( qualName == sAttrQualifiers[i] ) return true; - } - - return false; - -} // IsRDFAttrQualifier - - -// ------------------------------------------------------------------------------------------------- -// SerializePrettyRDFProperty -// -------------------------- -// -// Recursively handles the "value" for a node. It does not matter if it is a top level property, a -// field of a struct, or an item of an array. The indent is that for the property element. An -// xml:lang qualifier is written as an attribute of the property start tag, not by itself forcing -// the qualified property form. The patterns below mostly ignore attribute qualifiers like xml:lang. -// Except for the one struct case, attribute qualifiers don't affect the output form. -// -// value -// -// (If no rdf:resource qualifier) -// ... Fields, same forms as top level properties -// -// -// -// -// -// or Seq or Alt -// ... Array items as rdf:li elements, same forms as top level properties -// -// -// -// -// ... Property "value" following the unqualified forms ... -// ... Qualifiers looking like named struct fields -// - -static void -SerializePrettyRDFProperty ( const XMP_Node * propNode, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent, - bool emitAsRDFValue = false ) -{ - XMP_Index level; - bool emitEndTag = true; - bool indentEndTag = true; - - XMP_OptionBits propForm = propNode->options & kXMP_PropCompositeMask; - - // ------------------------------------------------------------------------------------------ - // Determine the XML element name. Open the start tag with the name and attribute qualifiers. - - XMP_StringPtr elemName = propNode->name.c_str(); - if ( emitAsRDFValue ) { - elemName= "rdf:value"; - } else if ( *elemName == '[' ) { - elemName = "rdf:li"; - } - - for ( level = indent; level > 0; --level ) outputStr += indentStr; - outputStr += '<'; - outputStr += elemName; - - #define isCompact false - bool hasGeneralQualifiers = isCompact; // Might also become true later. - bool hasRDFResourceQual = false; - - for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - const XMP_Node * currQual = propNode->qualifiers[qualNum]; - if ( ! IsRDFAttrQualifier ( currQual->name ) ) { - hasGeneralQualifiers = true; - } else { - if ( currQual->name == "rdf:resource" ) hasRDFResourceQual = true; - if ( ! emitAsRDFValue ) { - outputStr += ' '; - outputStr += currQual->name; - outputStr += "=\""; - AppendNodeValue ( outputStr, currQual->value, kForAttribute ); - outputStr += '"'; - } - } - } - - // -------------------------------------------------------- - // Process the property according to the standard patterns. - - if ( hasGeneralQualifiers && (! emitAsRDFValue) ) { - - // ----------------------------------------------------------------------------------------- - // This node has general, non-attribute, qualifiers. Emit using the qualified property form. - // ! The value is output by a recursive call ON THE SAME NODE with emitAsRDFValue set. - - if ( hasRDFResourceQual ) { - XMP_Throw ( "Can't mix rdf:resource and general qualifiers", kXMPErr_BadRDF ); - } - - outputStr += " rdf:parseType=\"Resource\">"; - outputStr += newline; - - SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true ); - - for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - const XMP_Node * currQual = propNode->qualifiers[qualNum]; - if ( IsRDFAttrQualifier ( currQual->name ) ) continue; - SerializePrettyRDFProperty ( currQual, outputStr, newline, indentStr, indent+1 ); - } - - } else { - - // -------------------------------------------------------------------- - // This node has no general qualifiers. Emit using an unqualified form. - - if ( propForm == 0 ) { - - // -------------------------- - // This is a simple property. - - if ( propNode->options & kXMP_PropValueIsURI ) { - outputStr += " rdf:resource=\""; - AppendNodeValue ( outputStr, propNode->value, kForAttribute ); - outputStr += "\"/>"; - outputStr += newline; - emitEndTag = false; - } else if ( propNode->value.empty() ) { - outputStr += "/>"; - outputStr += newline; - emitEndTag = false; - } else { - outputStr += '>'; - AppendNodeValue ( outputStr, propNode->value, kForElement ); - indentEndTag = false; - } - - } else if ( propForm & kXMP_PropValueIsArray ) { - - // This is an array. - outputStr += '>'; - outputStr += newline; - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, 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]; - SerializePrettyRDFProperty ( currChild, outputStr, newline, indentStr, indent+2 ); - } - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag ); - - - } else if ( ! hasRDFResourceQual ) { - - // This is a "normal" struct, use the rdf:parseType="Resource" form. - XMP_Assert ( propForm & kXMP_PropValueIsStruct ); - if ( propNode->children.size() == 0 ) { - outputStr += " rdf:parseType=\"Resource\"/>"; - outputStr += newline; - emitEndTag = false; - } else { - outputStr += " rdf:parseType=\"Resource\">"; - outputStr += newline; - for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) { - const XMP_Node * currChild = propNode->children[childNum]; - SerializePrettyRDFProperty ( currChild, outputStr, newline, indentStr, indent+1 ); - } - } - - } else { - - // This is a struct with an rdf:resource attribute, use the "empty property element" form. - XMP_Assert ( propForm & kXMP_PropValueIsStruct ); - for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) { - const XMP_Node * currChild = propNode->children[childNum]; - if ( ! CanBeRDFAttrProp ( currChild ) ) { - XMP_Throw ( "Can't mix rdf:resource and complex fields", kXMPErr_BadRDF ); - } - outputStr += newline; - for ( level = indent+1; level > 0; --level ) outputStr += indentStr; - outputStr += ' '; - outputStr += currChild->name; - outputStr += "=\""; - outputStr += currChild->value; - outputStr += '"'; - } - outputStr += "/>"; - outputStr += newline; - emitEndTag = false; - - } - - } - - // ---------------------------------- - // Emit the property element end tag. - - if ( emitEndTag ) { - if ( indentEndTag ) for ( level = indent; level > 0; --level ) outputStr += indentStr; - outputStr += "'; - outputStr += newline; - } - -} // SerializePrettyRDFProperty - - -// ------------------------------------------------------------------------------------------------- -// SerializePrettyRDFSchema -// ------------------------ -// -// Each schema's properties are written in a separate rdf:Description element. All of the necessary -// namespaces are declared in the rdf:Description element. The baseIndent is the base level for the -// entire serialization, that of the x:xmpmeta element. An xml:lang qualifier is written as an -// attribute of the property start tag, not by itself forcing the qualified property form. -// -// -// -// ... The actual properties of the schema, see SerializePrettyRDFProperty -// -// ... If alias comments are wanted -// -// - -static void -SerializePrettyRDFSchema ( const XMP_VarString & treeName, - const XMP_Node * schemaNode, - XMP_VarString & outputStr, - XMP_OptionBits options, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index baseIndent ) -{ - XMP_Assert ( schemaNode->options & kXMP_SchemaNode ); - XMP_Assert ( schemaNode->qualifiers.empty() ); - - // Write the rdf:Description start tag with the namespace declarations. - - XMP_Index level; - for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr; - outputStr += kRDF_SchemaStart; - outputStr += '"'; - outputStr += treeName; - outputStr += '"'; - - size_t totalLen = 8; // Start at 8 for "xml:rdf:". - XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin(); - XMP_cStringMapPos endPos = sNamespacePrefixToURIMap->end(); - for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size(); - - XMP_VarString usedNS; - usedNS.reserve ( totalLen ); - usedNS = "xml:rdf:"; - DeclareUsedNamespaces ( schemaNode, usedNS, outputStr, newline, indentStr, baseIndent+4 ); - - outputStr += ">"; - outputStr += newline; - - // Write alias comments, if wanted. - - if ( options & kXMP_WriteAliasComments ) { // *** Hoist into a routine, used for Plain XMP also. - - #if 0 // *** Buggy, disable for now. - - XMP_cAliasMapPos aliasPos = sRegisteredAliasMap->begin(); - XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end(); - - for ( ; aliasPos != aliasEnd; ++aliasPos ) { - - size_t nsPos = aliasPos->first.find ( schemaNode->value ); - if ( nsPos == XMP_VarString::npos ) continue; - XMP_Assert ( nsPos == 0 ); - - for ( level = baseIndent+3; level > 0; --level ) outputStr += indentStr; - - outputStr += ""; - outputStr += newline; - - } - - #endif - - } - - // Write each of the schema's actual properties. - for ( size_t propNum = 0, propLim = schemaNode->children.size(); propNum < propLim; ++propNum ) { - const XMP_Node * currProp = schemaNode->children[propNum]; - SerializePrettyRDFProperty ( currProp, outputStr, newline, indentStr, baseIndent+3 ); - } - - // Write the rdf:Description end tag. - for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr; - outputStr += kRDF_SchemaEnd; - outputStr += newline; - -} // SerializePrettyRDFSchema - - -// ------------------------------------------------------------------------------------------------- -// SerializeCompactRDFAttrProps -// ---------------------------- -// -// Write each of the parent's simple unqualified properties as an attribute. Returns true if all -// of the properties are written as attributes. - -static bool -SerializeCompactRDFAttrProps ( const XMP_Node * parentNode, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent ) -{ - size_t prop, propLim; - bool allAreAttrs = true; - - for ( prop = 0, propLim = parentNode->children.size(); prop != propLim; ++prop ) { - - const XMP_Node * currProp = parentNode->children[prop]; - if ( ! CanBeRDFAttrProp ( currProp ) ) { - allAreAttrs = false; - continue; - } - - outputStr += newline; - for ( XMP_Index level = indent; level > 0; --level ) outputStr += indentStr; - outputStr += currProp->name; - outputStr += "=\""; - AppendNodeValue ( outputStr, currProp->value, kForAttribute ); - outputStr += '"'; - - } - - return allAreAttrs; - -} // SerializeCompactRDFAttrProps - - -// ------------------------------------------------------------------------------------------------- -// SerializeCompactRDFElemProps -// ---------------------------- -// -// Recursively handles the "value" for a node that must be written as an RDF property element. It -// does not matter if it is a top level property, a field of a struct, or an item of an array. The -// indent is that for the property element. The patterns bwlow ignore attribute qualifiers such as -// xml:lang, they don't affect the output form. -// -// -// -// -// ... The fields as elements, if none are simple and unqualified -// -// -// -// -// ... The compound or qualified fields as elements -// -// -// -// -// or Seq or Alt -// ... Array items as rdf:li elements, same forms as top level properties -// -// -// -// -// ... Property "value" following the unqualified forms ... -// ... Qualifiers looking like named struct fields -// - -// *** Consider numbered array items, but has compatibility problems. -// *** Consider qualified form with rdf:Description and attributes. - -static void -SerializeCompactRDFElemProps ( const XMP_Node * parentNode, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index indent ) -{ - XMP_Index level; - - for ( size_t prop = 0, propLim = parentNode->children.size(); prop != propLim; ++prop ) { - - const XMP_Node * propNode = parentNode->children[prop]; - if ( CanBeRDFAttrProp ( propNode ) ) continue; - - bool emitEndTag = true; - bool indentEndTag = true; - - XMP_OptionBits propForm = propNode->options & kXMP_PropCompositeMask; - - // ----------------------------------------------------------------------------------- - // Determine the XML element name, write the name part of the start tag. Look over the - // qualifiers to decide on "normal" versus "rdf:value" form. Emit the attribute - // qualifiers at the same time. - - XMP_StringPtr elemName = propNode->name.c_str(); - if ( *elemName == '[' ) elemName = "rdf:li"; - - for ( level = indent; level > 0; --level ) outputStr += indentStr; - outputStr += '<'; - outputStr += elemName; - - #define isCompact false - bool hasGeneralQualifiers = isCompact; // Might also become true later. - bool hasRDFResourceQual = false; - - for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - const XMP_Node * currQual = propNode->qualifiers[qualNum]; - if ( ! IsRDFAttrQualifier ( currQual->name ) ) { - hasGeneralQualifiers = true; - } else { - if ( currQual->name == "rdf:resource" ) hasRDFResourceQual = true; - outputStr += ' '; - outputStr += currQual->name; - outputStr += "=\""; - AppendNodeValue ( outputStr, currQual->value, kForAttribute ); - outputStr += '"'; - } - } - - // -------------------------------------------------------- - // Process the property according to the standard patterns. - - if ( hasGeneralQualifiers ) { - - // ------------------------------------------------------------------------------------- - // The node has general qualifiers, ones that can't be attributes on a property element. - // Emit using the qualified property pseudo-struct form. The value is output by a call - // to SerializePrettyRDFProperty with emitAsRDFValue set. - - // *** We're losing compactness in the calls to SerializePrettyRDFProperty. - // *** Should refactor to have SerializeCompactRDFProperty that does one node. - - outputStr += " rdf:parseType=\"Resource\">"; - outputStr += newline; - - SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true ); - - size_t qualNum = 0; - size_t qualLim = propNode->qualifiers.size(); - if ( propNode->options & kXMP_PropHasLang ) ++qualNum; - - for ( ; qualNum < qualLim; ++qualNum ) { - const XMP_Node * currQual = propNode->qualifiers[qualNum]; - SerializePrettyRDFProperty ( currQual, outputStr, newline, indentStr, indent+1 ); - } - - } else { - - // -------------------------------------------------------------------- - // This node has only attribute qualifiers. Emit as a property element. - - if ( propForm == 0 ) { - - // -------------------------- - // This is a simple property. - - if ( propNode->options & kXMP_PropValueIsURI ) { - outputStr += " rdf:resource=\""; - AppendNodeValue ( outputStr, propNode->value, kForAttribute ); - outputStr += "\"/>"; - outputStr += newline; - emitEndTag = false; - } else if ( propNode->value.empty() ) { - outputStr += "/>"; - outputStr += newline; - emitEndTag = false; - } else { - outputStr += '>'; - AppendNodeValue ( outputStr, propNode->value, kForElement ); - indentEndTag = false; - } - - } else if ( propForm & kXMP_PropValueIsArray ) { - - // ----------------- - // This is an array. - - outputStr += '>'; - outputStr += newline; - EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, 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 ); - - } else { - - // ---------------------- - // This must be a struct. - - XMP_Assert ( propForm & kXMP_PropValueIsStruct ); - - bool hasAttrFields = false; - bool hasElemFields = false; - - size_t field, fieldLim; - for ( field = 0, fieldLim = propNode->children.size(); field != fieldLim; ++field ) { - XMP_Node * currField = propNode->children[field]; - if ( CanBeRDFAttrProp ( currField ) ) { - hasAttrFields = true; - if ( hasElemFields ) break; // No sense looking further. - } else { - hasElemFields = true; - if ( hasAttrFields ) break; // No sense looking further. - } - } - - if ( hasRDFResourceQual && hasElemFields ) { - XMP_Throw ( "Can't mix rdf:resource qualifier and element fields", kXMPErr_BadRDF ); - } - - if ( propNode->children.size() == 0 ) { - - // Catch an empty struct as a special case. The case below would emit an empty - // XML element, which gets reparsed as a simple property with an empty value. - outputStr += " rdf:parseType=\"Resource\"/>"; - outputStr += newline; - emitEndTag = false; - - } else if ( ! hasElemFields ) { - - // All fields can be attributes, use the emptyPropertyElt form. - SerializeCompactRDFAttrProps ( propNode, outputStr, newline, indentStr, indent+1 ); - outputStr += "/>"; - outputStr += newline; - emitEndTag = false; - - } else if ( ! hasAttrFields ) { - - // All fields must be elements, use the parseTypeResourcePropertyElt form. - outputStr += " rdf:parseType=\"Resource\">"; - outputStr += newline; - SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+1 ); - - } else { - - // Have a mix of attributes and elements, use an inner rdf:Description. - outputStr += '>'; - outputStr += newline; - for ( level = indent+1; level > 0; --level ) outputStr += indentStr; - outputStr += " 0; --level ) outputStr += indentStr; - outputStr += kRDF_StructEnd; - outputStr += newline; - - } - - } - - } - - // ---------------------------------- - // Emit the property element end tag. - - if ( emitEndTag ) { - if ( indentEndTag ) for ( level = indent; level > 0; --level ) outputStr += indentStr; - outputStr += "'; - outputStr += newline; - } - - } - -} // SerializeCompactRDFElemProps - - -// ------------------------------------------------------------------------------------------------- -// SerializeCompactRDFSchemas -// -------------------------- -// -// All properties from all schema are written in a single rdf:Description element, as are all of the -// necessary namespace declarations. The baseIndent is the base level for the entire serialization, -// that of the x:xmpmeta element. The x:xmpmeta and rdf:RDF elements have already been written. -// -// Top level simple unqualified properties are written as attributes of the (only) rdf:Description -// element. Structs, arrays, and qualified properties are written by SerializeCompactRDFElemProp. An -// xml:lang qualifier on a simple property prevents the attribute form. -// -// -// ... The remaining properties of the schema, see SerializeCompactRDFElemProps -// - -static void -SerializeCompactRDFSchemas ( const XMP_Node & xmpTree, - XMP_VarString & outputStr, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index baseIndent ) -{ - XMP_Index level; - size_t schema, schemaLim; - - // Begin the rdf:Description start tag. - for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr; - outputStr += kRDF_SchemaStart; - outputStr += '"'; - outputStr += xmpTree.name; - outputStr += '"'; - - // Write all necessary xmlns attributes. - - size_t totalLen = 8; // Start at 8 for "xml:rdf:". - XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin(); - XMP_cStringMapPos endPos = sNamespacePrefixToURIMap->end(); - for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size(); - - XMP_VarString usedNS; - usedNS.reserve ( totalLen ); - usedNS = "xml:rdf:"; - - for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) { - const XMP_Node * currSchema = xmpTree.children[schema]; - DeclareUsedNamespaces ( currSchema, usedNS, outputStr, newline, indentStr, baseIndent+4 ); - } - - // Write the top level "attrProps" and close the rdf:Description start tag. - bool allAreAttrs = true; - for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) { - const XMP_Node * currSchema = xmpTree.children[schema]; - allAreAttrs &= SerializeCompactRDFAttrProps ( currSchema, outputStr, newline, indentStr, baseIndent+3 ); - } - if ( ! allAreAttrs ) { - outputStr += ">"; - outputStr += newline; - } else { - outputStr += "/>"; - outputStr += newline; - return; // ! Done if all properties in all schema are written as attributes. - } - - // Write the remaining properties for each schema. - for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) { - const XMP_Node * currSchema = xmpTree.children[schema]; - SerializeCompactRDFElemProps ( currSchema, outputStr, newline, indentStr, baseIndent+3 ); - } - - // Write the rdf:Description end tag. - // *** Elide the end tag if everything (all props in all schema) is an attr. - for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr; - outputStr += kRDF_SchemaEnd; - outputStr += newline; - -} // SerializeCompactRDFSchemas - - -// ------------------------------------------------------------------------------------------------- -// SerializeAsRDF -// -------------- -// -// -// -// -// -// ... The properties, see SerializePrettyRDFSchema or SerializeCompactRDFSchemas -// -// -// -// - -// *** Need to strip empty arrays? -// *** Option to strip/keep empty structs? -// *** Need to verify handling of rdf:type qualifiers in pretty and compact. -// *** Need to verify round tripping of rdf:ID and similar qualifiers, see RDF 7.2.21. -// *** Check cases of rdf:resource plus explicit attr qualifiers (like xml:lang). - -static void -SerializeAsRDF ( const XMPMeta & xmpObj, - XMP_VarString & headStr, // Everything up to the padding. - XMP_VarString & tailStr, // Everything after the padding. - XMP_OptionBits options, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index baseIndent ) -{ - const size_t treeNameLen = xmpObj.tree.name.size(); - const size_t indentLen = strlen ( indentStr ); - - // First estimate the worst case space and reserve room in the output string. This optimization - // avoids reallocating and copying the output as it grows. The initial count does not look at - // the values of properties, so it does not account for character entities, e.g. for newline. - // Since there can be a lot of these in things like the base 64 encoding of a large thumbnail, - // inflate the count by 1/4 (easy to do) to accommodate. - - // *** Need to include estimate for alias comments. - - size_t outputLen = 2 * (strlen(kPacketHeader) + strlen(kRDF_XMPMetaStart) + strlen(kRDF_RDFStart) + 3*baseIndent*indentLen); - - for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) { - const XMP_Node * currSchema = xmpObj.tree.children[schemaNum]; - outputLen += 2*(baseIndent+2)*indentLen + strlen(kRDF_SchemaStart) + treeNameLen + strlen(kRDF_SchemaEnd) + 2; - outputLen += EstimateRDFSize ( currSchema, baseIndent+2, indentLen ); - } - - outputLen += (outputLen >> 2); // Inflate by 1/4, an empirical fudge factor. - - // Now generate the RDF into the head string as UTF-8. - - XMP_Index level; - - headStr.erase(); - headStr.reserve ( outputLen ); - - // Write the packet header PI. - if ( ! (options & kXMP_OmitPacketWrapper) ) { - for ( level = baseIndent; level > 0; --level ) headStr += indentStr; - headStr += kPacketHeader; - headStr += newline; - } - - // Write the xmpmeta element's start tag. - if ( ! (options & kXMP_OmitXMPMetaElement) ) { - for ( level = baseIndent; level > 0; --level ) headStr += indentStr; - headStr += kRDF_XMPMetaStart; - headStr += kXMPCore_VersionMessage "\">"; - headStr += newline; - } - - // Write the rdf:RDF start tag. - for ( level = baseIndent+1; level > 0; --level ) headStr += indentStr; - headStr += kRDF_RDFStart; - headStr += newline; - - // Write all of the properties. - if ( options & kXMP_UseCompactFormat ) { - SerializeCompactRDFSchemas ( xmpObj.tree, headStr, newline, indentStr, baseIndent ); - } else { - if ( xmpObj.tree.children.size() > 0 ) { - for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) { - const XMP_Node * currSchema = xmpObj.tree.children[schemaNum]; - SerializePrettyRDFSchema ( xmpObj.tree.name, currSchema, headStr, options, newline, indentStr, baseIndent ); - } - } else { - for ( XMP_Index level = baseIndent+2; level > 0; --level ) headStr += indentStr; - headStr += kRDF_SchemaStart; // Special case an empty XMP object. - headStr += '"'; - headStr += xmpObj.tree.name; - headStr += "\"/>"; - headStr += newline; - } - } - - // Write the rdf:RDF end tag. - for ( level = baseIndent+1; level > 0; --level ) headStr += indentStr; - headStr += kRDF_RDFEnd; - headStr += newline; - - // Write the xmpmeta end tag. - if ( ! (options & kXMP_OmitXMPMetaElement) ) { - for ( level = baseIndent; level > 0; --level ) headStr += indentStr; - headStr += kRDF_XMPMetaEnd; - headStr += newline; - } - - // Write the packet trailer PI into the tail string as UTF-8. - tailStr.erase(); - if ( ! (options & kXMP_OmitPacketWrapper) ) { - tailStr.reserve ( strlen(kPacketTrailer) + (strlen(indentStr) * baseIndent) ); - for ( level = baseIndent; level > 0; --level ) tailStr += indentStr; - tailStr += kPacketTrailer; - if ( options & kXMP_ReadOnlyPacket ) tailStr[tailStr.size()-4] = 'r'; - } - - // ! This assert is just a performance check, to see if the reserve was enough. - // *** XMP_Assert ( headStr.size() <= outputLen ); - // *** Don't use an assert. Think of some way to track this without risk of aborting the client. - -} // SerializeAsRDF - -// ------------------------------------------------------------------------------------------------- -// SerializeToBuffer -// ----------------- - -void -XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString, - XMP_StringLen * rdfSize, - XMP_OptionBits options, - XMP_StringLen padding, - XMP_StringPtr newline, - XMP_StringPtr indentStr, - XMP_Index baseIndent ) const -{ - XMP_Assert ( (rdfString != 0) && (rdfSize != 0) && (newline != 0) && (indentStr != 0) ); - - // Fix up some default parameters. - - enum { kDefaultPad = 2048 }; - size_t unicodeUnitSize = 1; - XMP_OptionBits charEncoding = options & kXMP_EncodingMask; - - if ( charEncoding != kXMP_EncodeUTF8 ) { - if ( options & _XMP_UTF16_Bit ) { - if ( options & _XMP_UTF32_Bit ) XMP_Throw ( "Can't use both _XMP_UTF16_Bit and _XMP_UTF32_Bit", kXMPErr_BadOptions ); - unicodeUnitSize = 2; - } else if ( options & _XMP_UTF32_Bit ) { - unicodeUnitSize = 4; - } else { - XMP_Throw ( "Can't use _XMP_LittleEndian_Bit by itself", kXMPErr_BadOptions ); - } - } - - if ( options & kXMP_OmitAllFormatting ) { - newline = " "; // ! Yes, a space for "newline". This ensures token separation. - indentStr = ""; - } else { - if ( *newline == 0 ) newline = "\xA"; // Linefeed - if ( *indentStr == 0 ) { - indentStr = " "; - if ( ! (options & kXMP_UseCompactFormat) ) indentStr = " "; - } - } - - if ( options & kXMP_ExactPacketLength ) { - if ( options & (kXMP_OmitPacketWrapper | kXMP_IncludeThumbnailPad) ) { - XMP_Throw ( "Inconsistent options for exact size serialize", kXMPErr_BadOptions ); - } - if ( (padding & (unicodeUnitSize-1)) != 0 ) { - XMP_Throw ( "Exact size must be a multiple of the Unicode element", kXMPErr_BadOptions ); - } - } else if ( options & kXMP_ReadOnlyPacket ) { - if ( options & (kXMP_OmitPacketWrapper | kXMP_IncludeThumbnailPad) ) { - XMP_Throw ( "Inconsistent options for read-only packet", kXMPErr_BadOptions ); - } - padding = 0; - } else if ( options & kXMP_OmitPacketWrapper ) { - if ( options & kXMP_IncludeThumbnailPad ) { - XMP_Throw ( "Inconsistent options for non-packet serialize", kXMPErr_BadOptions ); - } - padding = 0; - } else { - if ( padding == 0 ) padding = kDefaultPad * unicodeUnitSize; - if ( options & kXMP_IncludeThumbnailPad ) { - if ( ! this->DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) padding += (10000 * unicodeUnitSize); // *** Need a better estimate. - } - } - - // Serialize as UTF-8, then convert to UTF-16 or UTF-32 if necessary, and assemble with the padding and tail. - - std::string tailStr; - - SerializeAsRDF ( *this, *sOutputStr, tailStr, options, newline, indentStr, baseIndent ); - if ( charEncoding == kXMP_EncodeUTF8 ) { - - if ( options & kXMP_ExactPacketLength ) { - size_t minSize = sOutputStr->size() + tailStr.size(); - if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize ); - padding -= minSize; // Now the actual amount of padding to add. - } - - size_t newlineLen = strlen ( newline ); - - if ( padding < newlineLen ) { - sOutputStr->append ( padding, ' ' ); - } else { - padding -= newlineLen; // Write this newline last. - while ( padding >= (100 + newlineLen) ) { - sOutputStr->append ( 100, ' ' ); - *sOutputStr += newline; - padding -= (100 + newlineLen); - } - sOutputStr->append ( padding, ' ' ); - *sOutputStr += newline; - } - - *sOutputStr += tailStr; - - } else { - - // Need to convert the encoding. Swap the UTF-8 into a local string and convert back. Assemble everything. - - XMP_VarString utf8Str, newlineStr; - bool bigEndian = ((charEncoding & _XMP_LittleEndian_Bit) == 0); - - if ( charEncoding & _XMP_UTF16_Bit ) { - - std::string padStr ( " " ); padStr[0] = 0; // Assume big endian. - - utf8Str.swap ( *sOutputStr ); - ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian ); - utf8Str.swap ( tailStr ); - ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian ); - - if ( options & kXMP_ExactPacketLength ) { - size_t minSize = sOutputStr->size() + tailStr.size(); - if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize ); - padding -= minSize; // Now the actual amount of padding to add (in bytes). - } - - utf8Str.assign ( newline ); - ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &newlineStr, bigEndian ); - size_t newlineLen = newlineStr.size(); - - if ( padding < newlineLen ) { - for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr; - } else { - padding -= newlineLen; // Write this newline last. - while ( padding >= (200 + newlineLen) ) { - for ( int i = 100; i > 0; --i ) *sOutputStr += padStr; - *sOutputStr += newlineStr; - padding -= (200 + newlineLen); - } - for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr; - *sOutputStr += newlineStr; - } - - *sOutputStr += tailStr; - - } else { - - std::string padStr ( " " ); padStr[0] = padStr[1] = padStr[2] = 0; // Assume big endian. -// UTF8_to_UTF32_Proc Converter = UTF8_to_UTF32BE; - - if ( charEncoding & _XMP_LittleEndian_Bit ) { - padStr[0] = ' '; padStr[1] = padStr[2] = padStr[3] = 0; -// Converter = UTF8_to_UTF32LE; - } - - utf8Str.swap ( *sOutputStr ); - ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian ); - utf8Str.swap ( tailStr ); - ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian ); - - if ( options & kXMP_ExactPacketLength ) { - size_t minSize = sOutputStr->size() + tailStr.size(); - if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize ); - padding -= minSize; // Now the actual amount of padding to add (in bytes). - } - - utf8Str.assign ( newline ); - ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &newlineStr, bigEndian ); - size_t newlineLen = newlineStr.size(); - - if ( padding < newlineLen ) { - for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr; - } else { - padding -= newlineLen; // Write this newline last. - while ( padding >= (400 + newlineLen) ) { - for ( int i = 100; i > 0; --i ) *sOutputStr += padStr; - *sOutputStr += newlineStr; - padding -= (400 + newlineLen); - } - for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr; - *sOutputStr += newlineStr; - } - - *sOutputStr += tailStr; - - } - - } - - // Return the finished string. - - *rdfString = sOutputStr->c_str(); - *rdfSize = sOutputStr->size(); - -} // SerializeToBuffer - -// ================================================================================================= diff --git a/xmpsdk/src/XMPMeta.cpp b/xmpsdk/src/XMPMeta.cpp deleted file mode 100644 index 30ff4a5a75..0000000000 --- a/xmpsdk/src/XMPMeta.cpp +++ /dev/null @@ -1,1653 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include - -#include "XMPMeta.hpp" -#include "XMPIterator.hpp" -#include "XMPUtils.hpp" -#include "XMP_Version.h" -#include "UnicodeInlines.incl_cpp" -#include "UnicodeConversions.hpp" - -#include // For sort and stable_sort. - -#if XMP_DebugBuild - #include -#endif - -using namespace std; - -#if XMP_WinBuild -#ifdef _MSC_VER - #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) - #pragma warning ( disable : 4996 ) // '...' was declared deprecated -#endif -#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 -// ========================= - - -// ================================================================================================= -// Static Variables -// ================ - -XMP_VarString * xdefaultName = 0; - -// These are embedded version strings. - -const char * kXMPCore_EmbeddedVersion = kXMPCore_VersionMessage; -const char * kXMPCore_EmbeddedCopyright = kXMPCoreName " " kXMP_CopyrightStr; - -// ================================================================================================= -// Local Utilities -// =============== - -#define IsHexDigit(ch) ( (('0' <= (ch)) && ((ch) <= '9')) || (('A' <= (ch)) && ((ch) <= 'F')) ) -#define HexDigitValue(ch) ( (((ch) - '0') < 10) ? ((ch) - '0') : ((ch) - 'A' + 10) ) - -static const char * kTenSpaces = " "; -#define OutProcPadding(pad) { size_t padLen = (pad); \ - for ( ; padLen >= 10; padLen -= 10 ) OutProcNChars ( kTenSpaces, 10 ); \ - for ( ; padLen > 0; padLen -= 1 ) OutProcNChars ( " ", 1 ); } - - -#define OutProcNewline() { status = (*outProc) ( refCon, "\n", 1 ); if ( status != 0 ) goto EXIT; } - -#define OutProcNChars(p,n) { status = (*outProc) ( refCon, (p), (n) ); if ( status != 0 ) goto EXIT; } - -#define OutProcLiteral(lit) { status = (*outProc) ( refCon, (lit), strlen(lit) ); if ( status != 0 ) goto EXIT; } - -#define OutProcString(str) { status = (*outProc) ( refCon, (str).c_str(), (str).size() ); if ( status != 0 ) goto EXIT; } - -#define OutProcULong(num) { snprintf ( buffer, sizeof(buffer), "%lu", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \ - status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; } -#ifdef __APPLE__ -#define OutProcHexInt(num) { snprintf ( buffer, sizeof(buffer), "%X", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \ - status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; } -#else -#define OutProcHexInt(num) { snprintf ( buffer, sizeof(buffer), "%lX", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \ - status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; } -#endif - -#define OutProcHexByte(num) { snprintf ( buffer, sizeof(buffer), "%.2X", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \ - status = (*outProc) ( refCon, buffer, strlen(buffer) ); if ( status != 0 ) goto EXIT; } - -static const char * kIndent = " "; -#define OutProcIndent(lev) { for ( size_t i = 0; i < (lev); ++i ) OutProcNChars ( kIndent, 3 ); } - - -// ------------------------------------------------------------------------------------------------- -// DumpClearString -// --------------- - -static XMP_Status -DumpClearString ( const XMP_VarString & value, XMP_TextOutputProc outProc, void * refCon ) -{ - - char buffer [20]; - bool prevNormal; - XMP_Status status = 0; - - XMP_StringPtr spanStart, spanEnd; - XMP_StringPtr valueEnd = &value[0] + value.size(); - - spanStart = &value[0]; - while ( spanStart < valueEnd ) { - - // Output the next span of regular characters. - for ( spanEnd = spanStart; spanEnd < valueEnd; ++spanEnd ) { - if ( (unsigned char)(*spanEnd) > 0x7F ) break; - if ( (*spanEnd < 0x20) && (*spanEnd != kTab) && (*spanEnd != kLF) ) break; - } - if ( spanStart != spanEnd ) status = (*outProc) ( refCon, spanStart, (spanEnd-spanStart) ); - if ( status != 0 ) break; - spanStart = spanEnd; - - // Output the next span of irregular characters. - prevNormal = true; - for ( spanEnd = spanStart; spanEnd < valueEnd; ++spanEnd ) { - if ( ((0x20 <= *spanEnd) && ((unsigned char)(*spanEnd) <= 0x7F)) || (*spanEnd == kTab) || (*spanEnd == kLF) ) break; - char space = ' '; - if ( prevNormal ) space = '<'; - status = (*outProc) ( refCon, &space, 1 ); - if ( status != 0 ) break; - OutProcHexByte ( *spanEnd ); - prevNormal = false; - } - if ( ! prevNormal ) { - status = (*outProc) ( refCon, ">", 1 ); - if ( status != 0 ) return status; - } - spanStart = spanEnd; - - } - -EXIT: - return status; - -} // DumpClearString - - -// ------------------------------------------------------------------------------------------------- -// DumpStringMap -// ------------- - -static XMP_Status -DumpStringMap ( const XMP_StringMap & map, XMP_StringPtr label, XMP_TextOutputProc outProc, void * refCon ) -{ - XMP_Status status; - XMP_cStringMapPos currPos; - XMP_cStringMapPos endPos = map.end(); - - size_t maxLen = 0; - for ( currPos = map.begin(); currPos != endPos; ++currPos ) { - size_t currLen = currPos->first.size(); - if ( currLen > maxLen ) maxLen = currLen; - } - - OutProcNewline(); - OutProcLiteral ( label ); - OutProcNewline(); - - for ( currPos = map.begin(); currPos != endPos; ++currPos ) { - OutProcNChars ( " ", 2 ); - DumpClearString ( currPos->first, outProc, refCon ); - OutProcPadding ( maxLen - currPos->first.size() ); - OutProcNChars ( " => ", 4 ); - DumpClearString ( currPos->second, outProc, refCon ); - OutProcNewline(); - } - -EXIT: - return status; - -} // DumpStringMap - - -// ------------------------------------------------------------------------------------------------- -// DumpNodeOptions -// --------------- - -static XMP_Status -DumpNodeOptions ( XMP_OptionBits options, - XMP_TextOutputProc outProc, - void * refCon ) -{ - XMP_Status status; - char buffer [32]; // Decimal of a 64 bit int is at most about 20 digits. - - static const char * optNames[] = { " schema", // 0x8000_0000 - " ?30", - " ?29", - " -COMMAS-", - " ?27", // 0x0800_0000 - " ?26", - " ?25", - " ?24", - " ?23", // 0x0080_0000 - " isStale", - " isDerived", - " isStable", - " ?19", // 0x0008_0000 - " isInternal", - " hasAliases", - " isAlias", - " -AFTER-", // 0x0000_8000 - " -BEFORE-", - " isCompact", - " isLangAlt", - " isAlt", // 0x0000_0800 - " isOrdered", - " isArray", - " isStruct", - " hasType", // 0x0000_0080 - " hasLang", - " isQual", - " hasQual", - " ?3", // 0x0000_0008 - " ?2", - " URI", - " ?0" }; - - if ( options == 0 ) { - - OutProcNChars ( "(0x0)", 5 ); - - } else { - - OutProcNChars ( "(0x", 3 ); - OutProcHexInt ( options ); - OutProcNChars ( " :", 2 ); - - XMP_OptionBits mask = 0x80000000; - for ( int b = 0; b < 32; ++b ) { - if ( options & mask ) OutProcLiteral ( optNames[b] ); - mask = mask >> 1; - } - OutProcNChars ( ")", 1 ); - - } - -EXIT: - return status; - -} // DumpNodeOptions - - -// ------------------------------------------------------------------------------------------------- -// DumpPropertyTree -// ---------------- - -// *** Extract the validation code into a separate routine to call on exit in debug builds. - -static XMP_Status -DumpPropertyTree ( const XMP_Node * currNode, - int indent, - size_t itemIndex, - XMP_TextOutputProc outProc, - void * refCon ) -{ - XMP_Status status; - char buffer [32]; // Decimal of a 64 bit int is at most about 20 digits. - - OutProcIndent ( (size_t)indent ); - if ( itemIndex == 0 ) { - if ( currNode->options & kXMP_PropIsQualifier ) OutProcNChars ( "? ", 2 ); - DumpClearString ( currNode->name, outProc, refCon ); - } else { - OutProcNChars ( "[", 1 ); - OutProcULong ( static_cast(itemIndex) ); - OutProcNChars ( "]", 1 ); - } - - if ( ! (currNode->options & kXMP_PropCompositeMask) ) { - OutProcNChars ( " = \"", 4 ); - DumpClearString ( currNode->value, outProc, refCon ); - OutProcNChars ( "\"", 1 ); - } - - if ( currNode->options != 0 ) { - OutProcNChars ( " ", 2 ); - status = DumpNodeOptions ( currNode->options, outProc, refCon ); - if ( status != 0 ) goto EXIT; - } - - if ( currNode->options & kXMP_PropHasLang ) { - if ( currNode->qualifiers.empty() || (currNode->qualifiers[0]->name != "xml:lang") ) { - OutProcLiteral ( " ** bad lang flag **" ); - } - } - // *** Check rdf:type also. - - if ( ! (currNode->options & kXMP_PropCompositeMask) ) { - if ( ! currNode->children.empty() ) OutProcLiteral ( " ** bad children **" ); - } else if ( currNode->options & kXMP_PropValueIsArray ) { - if ( currNode->options & kXMP_PropValueIsStruct ) OutProcLiteral ( " ** bad comp flags **" ); - } else if ( (currNode->options & kXMP_PropCompositeMask) != kXMP_PropValueIsStruct ) { - OutProcLiteral ( " ** bad comp flags **" ); - } - - #if 0 // *** XMP_DebugBuild - if ( (currNode->_namePtr != currNode->name.c_str()) || - (currNode->_valuePtr != currNode->value.c_str()) ) OutProcLiteral ( " ** bad debug string **" ); - #endif - - OutProcNewline(); - - for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - - const XMP_Node * currQual = currNode->qualifiers[qualNum]; - - if ( currQual->parent != currNode ) OutProcLiteral ( "** bad parent link => " ); - if ( currQual->name == kXMP_ArrayItemName ) OutProcLiteral ( "** bad qual name => " ); - if ( ! (currQual->options & kXMP_PropIsQualifier) ) OutProcLiteral ( "** bad qual flag => " ); - if ( currQual->name == "xml:lang" ) { - if ( (qualNum != 0) || (! (currNode->options & kXMP_PropHasLang)) ) OutProcLiteral ( "** bad lang qual => " ); - } - - status = DumpPropertyTree ( currQual, indent+2, 0, outProc, refCon ); - if ( status != 0 ) goto EXIT; - - } - - for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) { - - const XMP_Node * currChild = currNode->children[childNum]; - - if ( currChild->parent != currNode ) OutProcLiteral ( "** bad parent link => " ); - if ( currChild->options & kXMP_PropIsQualifier ) OutProcLiteral ( "** bad qual flag => " ); - - if ( currNode->options & kXMP_PropValueIsArray ) { - itemIndex = childNum+1; - if ( currChild->name != kXMP_ArrayItemName ) OutProcLiteral ( "** bad item name => " ); - } else { - itemIndex = 0; - if ( currChild->name == kXMP_ArrayItemName ) OutProcLiteral ( "** bad field name => " ); - } - - status = DumpPropertyTree ( currChild, indent+1, itemIndex, outProc, refCon ); - if ( status != 0 ) goto EXIT; - - } - -EXIT: - return status; - -} // DumpPropertyTree - - -// ------------------------------------------------------------------------------------------------- -// DumpXMLTree -// ----------- - -#if DumpXMLParseTree - -static inline void PutHexByte ( FILE * log, unsigned char ch ) -{ - - fprintf ( log, "\\x" ); - if ( ch < 0x10 ) { - fprintf ( log, "%c", kHexDigits[ch] ); - } else { - fprintf ( log, "%c%c", kHexDigits[ch>>4], kHexDigits[ch&0xF] ); - } - -} // PutHexByte - -// ------------------------------------------------------------------------------------------------- - -static void PutClearString ( FILE * log, const std::string & str ) -{ - - for ( size_t i = 0; i != str.size(); ++i ) { - unsigned char ch = str[i]; - if ( (0x20 <= ch) && (ch <= 0x7F) ) { - fprintf ( log, "%c", ch ); - } else { - PutHexByte ( log, ch ); - } - } - -} // PutClearString - -// ------------------------------------------------------------------------------------------------- - -static void DumpXMLTree ( FILE * log, const XML_Node & node, int indent ) -{ - size_t i; - - #if 0 // *** XMP_DebugBuild - if ( (node._namePtr != node.name.c_str()) || - (node._valuePtr != node.value.c_str()) ) fprintf ( log, "*** bad debug string ***\n" ); - #endif - - for ( i = 0; i != (size_t)indent; ++i ) fprintf ( log, " " ); - - switch ( node.kind ) { - - case kRootNode : - fprintf ( log, "\nStart of XML tree dump\n\n" ); - if ( (indent != 0) || (! node.attrs.empty()) || - (! node.ns.empty()) || (! node.name.empty()) || (!node.value.empty()) ) fprintf ( log, " ** invalid root ** \n" ); - for ( i = 0; i < node.children.size(); ++i ) { - XMP_Uns8 kind = node.children[i]->kind; - if ( (kind == kRootNode) || (kind == kAttrNode) ) fprintf ( log, " ** invalid child ** \n" ); - DumpXMLTree ( log, *node.children[i], indent+1 ); - } - fprintf ( log, "\nEnd of XML tree dump\n" ); - break; - - case kElemNode : - fprintf ( log, "Elem %s", node.name.c_str() ); - if ( indent == 0 ) fprintf ( log, " ** invalid elem ** " ); - if ( ! node.ns.empty() ) fprintf ( log, " @ %s", node.ns.c_str() ); - fprintf ( log, "\n" ); - for ( i = 0; i < node.attrs.size(); ++i ) { - XMP_Uns8 kind = node.attrs[i]->kind; - if ( kind != kAttrNode ) fprintf ( log, " ** invalid attr ** \n" ); - DumpXMLTree ( log, *node.attrs[i], indent+2 ); - } - for ( i = 0; i < node.children.size(); ++i ) { - XMP_Uns8 kind = node.children[i]->kind; - if ( (kind == kRootNode) || (kind == kAttrNode) ) fprintf ( log, " ** invalid child ** \n" ); - DumpXMLTree ( log, *node.children[i], indent+1 ); - } - break; - - case kAttrNode : - fprintf ( log, "Attr %s", node.name.c_str() ); - if ( (indent == 0) || node.name.empty() || (! node.attrs.empty()) || (! node.children.empty()) ) fprintf ( log, " ** invalid attr ** " ); - fprintf ( log, " = \"" ); - PutClearString ( log, node.value ); - fprintf ( log, "\"" ); - if ( ! node.ns.empty() ) fprintf ( log, " @ %s", node.ns.c_str() ); - fprintf ( log, "\n" ); - break; - - case kCDataNode : - if ( (indent == 0) || (! node.ns.empty()) || (! node.name.empty()) || - (! node.attrs.empty()) || (! node.children.empty()) ) fprintf ( log, " ** invalid cdata ** \n" ); - fprintf ( log, "\"" ); - PutClearString ( log, node.value ); - fprintf ( log, "\"\n" ); - break; - - case kPINode : - fprintf ( log, "PI %s", node.name.c_str() ); - if ( (indent == 0) || node.name.empty() || (! node.children.empty()) ) fprintf ( log, " ** invalid pi ** \n" ); - if ( ! node.value.empty() ) { - fprintf ( log, " " ); - } - fprintf ( log, "\n" ); - break; - - } - -} // DumpXMLTree - -#endif // DumpXMLParseTree - - -// ------------------------------------------------------------------------------------------------- -// CompareNodeNames -// ---------------- -// -// Comparison routine for sorting XMP nodes by name. The name "xml:lang" is less than anything else, -// and "rdf:type" is less than anything except "xml:lang". This preserves special rules for qualifiers. - -static bool -CompareNodeNames ( XMP_Node * left, XMP_Node * right ) -{ - - if ( left->name == "xml:lang" ) return true; - if ( right->name == "xml:lang" ) return false; - - if ( left->name == "rdf:type" ) return true; - if ( right->name == "rdf:type" ) return false; - - return ( left->name < right->name ); - -} // CompareNodeNames - - -// ------------------------------------------------------------------------------------------------- -// CompareNodeValues -// ----------------- -// -// Comparison routine for sorting XMP nodes by value. - -static bool -CompareNodeValues ( XMP_Node * left, XMP_Node * right ) -{ - - if ( XMP_PropIsSimple ( left->options ) && XMP_PropIsSimple ( right->options ) ) { - return ( left->value < right->value ); - } - - XMP_OptionBits leftForm = left->options & kXMP_PropCompositeMask; - XMP_OptionBits rightForm = right->options & kXMP_PropCompositeMask; - - return ( leftForm < rightForm ); - -} // CompareNodeValues - - -// ------------------------------------------------------------------------------------------------- -// CompareNodeLangs -// ---------------- -// -// Comparison routine for sorting XMP nodes by xml:lang qualifier. An "x-default" value is less than -// any other language. - -static bool -CompareNodeLangs ( XMP_Node * left, XMP_Node * right ) -{ - - if ( left->qualifiers.empty() || (left->qualifiers[0]->name != "xml:lang") ) return false; - if ( right->qualifiers.empty() || (right->qualifiers[0]->name != "xml:lang") ) return false; - - if ( left->qualifiers[0]->value == "x-default" ) return true; - if ( right->qualifiers[0]->value == "x-default" ) return false; - - return ( left->qualifiers[0]->value < right->qualifiers[0]->value ); - -} // CompareNodeLangs - - -// ------------------------------------------------------------------------------------------------- -// SortWithinOffspring -// ------------------- -// -// Sort one level down, within the elements of a node vector. This sorts the qualifiers of each -// node. If the node is a struct it sorts the fields by names. If the node is an unordered array it -// sorts the elements by value. If the node is an AltText array it sorts the elements by language. - -static void -SortWithinOffspring ( XMP_NodeOffspring & nodeVec ) -{ - - for ( size_t i = 0, limit = nodeVec.size(); i < limit; ++i ) { - - XMP_Node * currPos = nodeVec[i]; - - if ( ! currPos->qualifiers.empty() ) { - sort ( currPos->qualifiers.begin(), currPos->qualifiers.end(), CompareNodeNames ); - SortWithinOffspring ( currPos->qualifiers ); - } - - if ( ! currPos->children.empty() ) { - - if ( XMP_PropIsStruct ( currPos->options ) || XMP_NodeIsSchema ( currPos->options ) ) { - sort ( currPos->children.begin(), currPos->children.end(), CompareNodeNames ); - } else if ( XMP_PropIsArray ( currPos->options ) ) { - if ( XMP_ArrayIsUnordered ( currPos->options ) ) { - stable_sort ( currPos->children.begin(), currPos->children.end(), CompareNodeValues ); - } else if ( XMP_ArrayIsAltText ( currPos->options ) ) { - sort ( currPos->children.begin(), currPos->children.end(), CompareNodeLangs ); - } - } - - SortWithinOffspring ( currPos->children ); - - } - - } - -} // SortWithinOffspring - - -// ================================================================================================= -// Constructors -// ============ - - -XMPMeta::XMPMeta() : clientRefs(0), prevTkVer(0), tree(XMP_Node(0,"",0)), xmlParser(0) -{ - // Nothing more to do, clientRefs is incremented in wrapper. - #if XMP_TraceCTorDTor - printf ( "Default construct XMPMeta @ %.8X\n", this ); - #endif -} // XMPMeta - -// ------------------------------------------------------------------------------------------------- - -XMPMeta::~XMPMeta() RELEASE_NO_THROW -{ - #if XMP_TraceCTorDTor - printf ( "Destruct XMPMeta @ %.8X\n", this ); - #endif - - XMP_Assert ( this->clientRefs <= 0 ); - if ( xmlParser != 0 ) delete ( xmlParser ); - xmlParser = 0; - -} // ~XMPMeta - - -// ================================================================================================= -// Class Static Functions -// ====================== -// -// -// ================================================================================================= - -// ------------------------------------------------------------------------------------------------- -// GetVersionInfo -// -------------- - -/* class-static */ void -XMPMeta::GetVersionInfo ( XMP_VersionInfo * info ) -{ - - memset ( info, 0, sizeof(*info) ); // AUDIT: Safe, using sizeof the destination. - XMP_Assert ( sizeof(*info) == sizeof(XMP_VersionInfo) ); - - info->major = XMP_API_VERSION_MAJOR; - info->minor = XMP_API_VERSION_MINOR; - info->micro = XMP_API_VERSION_MICRO; - info->isDebug = kXMPCore_DebugFlag; - info->flags = 0; // ! None defined yet. - info->message = kXMPCore_VersionMessage; - -} // GetVersionInfo - -// ------------------------------------------------------------------------------------------------- -// Initialize -// ---------- - -/* class-static */ bool -XMPMeta::Initialize() -{ - // Allocate and initialize static objects. - - ++sXMP_InitCount; - if ( sXMP_InitCount > 1 ) return true; - - #if TraceXMPCalls - // xmpOut = fopen ( "xmp.out", "w" ); // Coordinate with client glue in WXMP_Common.hpp - fprintf ( xmpOut, "XMP initializing\n" ); fflush ( xmpOut ); - #endif - - sExceptionMessage = new XMP_VarString(); - XMP_InitMutex ( &sXMPCoreLock ); - sOutputNS = new XMP_VarString; - sOutputStr = new XMP_VarString; - - xdefaultName = new XMP_VarString ( "x-default" ); - - sNamespaceURIToPrefixMap = new XMP_StringMap; - sNamespacePrefixToURIMap = new XMP_StringMap; - sRegisteredAliasMap = new XMP_AliasMap; - - InitializeUnicodeConversions(); - - // Register standard namespaces and aliases. - RegisterNamespace ( kXMP_NS_XML, "xml" ); - RegisterNamespace ( kXMP_NS_RDF, "rdf" ); - RegisterNamespace ( kXMP_NS_DC, "dc" ); - - RegisterNamespace ( kXMP_NS_XMP, "xmp" ); - RegisterNamespace ( kXMP_NS_PDF, "pdf" ); - RegisterNamespace ( kXMP_NS_Photoshop, "photoshop" ); - RegisterNamespace ( kXMP_NS_PSAlbum, "album" ); - RegisterNamespace ( kXMP_NS_EXIF, "exif" ); - RegisterNamespace ( kXMP_NS_EXIF_Aux, "aux" ); - RegisterNamespace ( kXMP_NS_TIFF, "tiff" ); - RegisterNamespace ( kXMP_NS_PNG, "png" ); - RegisterNamespace ( kXMP_NS_JPEG, "jpeg" ); - RegisterNamespace ( kXMP_NS_JP2K, "jp2k" ); - RegisterNamespace ( kXMP_NS_CameraRaw, "crs" ); - RegisterNamespace ( kXMP_NS_ASF, "asf" ); - RegisterNamespace ( kXMP_NS_WAV, "wav" ); - - RegisterNamespace ( kXMP_NS_AdobeStockPhoto, "bmsp" ); - RegisterNamespace ( kXMP_NS_CreatorAtom, "creatorAtom" ); - - RegisterNamespace ( kXMP_NS_XMP_Rights, "xmpRights" ); - RegisterNamespace ( kXMP_NS_XMP_MM, "xmpMM" ); - RegisterNamespace ( kXMP_NS_XMP_BJ, "xmpBJ" ); - RegisterNamespace ( kXMP_NS_XMP_Note, "xmpNote" ); - - RegisterNamespace ( kXMP_NS_DM, "xmpDM" ); - RegisterNamespace ( kXMP_NS_XMP_Text, "xmpT" ); - RegisterNamespace ( kXMP_NS_XMP_PagedFile, "xmpTPg" ); - RegisterNamespace ( kXMP_NS_XMP_Graphics, "xmpG" ); - RegisterNamespace ( kXMP_NS_XMP_Image, "xmpGImg" ); - - RegisterNamespace ( kXMP_NS_XMP_Font, "stFnt" ); - RegisterNamespace ( kXMP_NS_XMP_Dimensions, "stDim" ); - RegisterNamespace ( kXMP_NS_XMP_ResourceEvent, "stEvt" ); - RegisterNamespace ( kXMP_NS_XMP_ResourceRef, "stRef" ); - RegisterNamespace ( kXMP_NS_XMP_ST_Version, "stVer" ); - RegisterNamespace ( kXMP_NS_XMP_ST_Job, "stJob" ); - RegisterNamespace ( kXMP_NS_XMP_ManifestItem, "stMfs" ); - - RegisterNamespace ( kXMP_NS_XMP_IdentifierQual, "xmpidq" ); - - RegisterNamespace ( kXMP_NS_IPTCCore, "Iptc4xmpCore" ); - RegisterNamespace ( kXMP_NS_DICOM, "DICOM" ); - - RegisterNamespace ( kXMP_NS_PDFA_Schema, "pdfaSchema" ); - RegisterNamespace ( kXMP_NS_PDFA_Property, "pdfaProperty" ); - RegisterNamespace ( kXMP_NS_PDFA_Type, "pdfaType" ); - RegisterNamespace ( kXMP_NS_PDFA_Field, "pdfaField" ); - RegisterNamespace ( kXMP_NS_PDFA_ID, "pdfaid" ); - RegisterNamespace ( kXMP_NS_PDFA_Extension, "pdfaExtension" ); - - RegisterNamespace ( kXMP_NS_PDFX, "pdfx" ); - RegisterNamespace ( kXMP_NS_PDFX_ID, "pdfxid" ); - - RegisterNamespace ( "adobe:ns:meta/", "x" ); - RegisterNamespace ( "http://ns.adobe.com/iX/1.0/", "iX" ); - -// 06-Oct-07, ahu: Do not use aliases. They result in unexpected behaviour. -// XMPMeta::RegisterStandardAliases ( "" ); - - // Initialize the other core classes. - - if ( ! XMPIterator::Initialize() ) XMP_Throw ( "Failure from XMPIterator::Initialize", kXMPErr_InternalFailure ); - if ( ! XMPUtils::Initialize() ) XMP_Throw ( "Failure from XMPUtils::Initialize", kXMPErr_InternalFailure ); - // Do miscelaneous semantic checks of types and arithmetic. - - XMP_Assert ( sizeof(XMP_Int8) == 1 ); - XMP_Assert ( sizeof(XMP_Int16) == 2 ); - XMP_Assert ( sizeof(XMP_Int32) == 4 ); - XMP_Assert ( sizeof(XMP_Int64) == 8 ); - XMP_Assert ( sizeof(XMP_Uns8) == 1 ); - XMP_Assert ( sizeof(XMP_Uns16) == 2 ); - XMP_Assert ( sizeof(XMP_Uns32) == 4 ); - XMP_Assert ( sizeof(XMP_Uns64) == 8 ); - - XMP_Assert ( sizeof(XMP_OptionBits) == 4 ); // Check that option masking work on all 32 bits. - XMP_OptionBits flag = ~0; - - XMP_Assert ( flag == (XMP_OptionBits)(-1L) ); - XMP_Assert ( (flag ^ kXMP_PropHasLang) == 0xFFFFFFBFUL ); - XMP_Assert ( (flag & ~kXMP_PropHasLang) == 0xFFFFFFBFUL ); - - XMP_OptionBits opt1 = 0; // Check the general option bit macros. - XMP_OptionBits opt2 = flag; - XMP_SetOption ( opt1, kXMP_PropValueIsArray ); - XMP_ClearOption ( opt2, kXMP_PropValueIsArray ); - XMP_Assert ( opt1 == ~opt2 ); - XMP_Assert ( XMP_TestOption ( opt1, kXMP_PropValueIsArray ) ); - XMP_Assert ( ! XMP_TestOption ( opt2, kXMP_PropValueIsArray ) ); - - XMP_Assert ( XMP_PropIsSimple ( ~kXMP_PropCompositeMask ) ); // Check the special option bit macros. - XMP_Assert ( ! XMP_PropIsSimple ( kXMP_PropValueIsStruct ) ); - XMP_Assert ( ! XMP_PropIsSimple ( kXMP_PropValueIsArray ) ); - - XMP_Assert ( XMP_PropIsStruct ( kXMP_PropValueIsStruct ) ); - XMP_Assert ( XMP_PropIsArray ( kXMP_PropValueIsArray ) ); - XMP_Assert ( ! XMP_PropIsStruct ( ~kXMP_PropValueIsStruct ) ); - XMP_Assert ( ! XMP_PropIsArray ( ~kXMP_PropValueIsArray ) ); - - XMP_Assert ( XMP_ArrayIsUnordered ( ~kXMP_PropArrayIsOrdered ) ); - XMP_Assert ( XMP_ArrayIsOrdered ( kXMP_PropArrayIsOrdered ) ); - XMP_Assert ( XMP_ArrayIsAlternate ( kXMP_PropArrayIsAlternate ) ); - XMP_Assert ( XMP_ArrayIsAltText ( kXMP_PropArrayIsAltText ) ); - XMP_Assert ( ! XMP_ArrayIsUnordered ( kXMP_PropArrayIsOrdered ) ); - XMP_Assert ( ! XMP_ArrayIsOrdered ( ~kXMP_PropArrayIsOrdered ) ); - XMP_Assert ( ! XMP_ArrayIsAlternate ( ~kXMP_PropArrayIsAlternate ) ); - XMP_Assert ( ! XMP_ArrayIsAltText ( ~kXMP_PropArrayIsAltText ) ); - - XMP_Assert ( XMP_PropHasQualifiers ( kXMP_PropHasQualifiers ) ); - XMP_Assert ( XMP_PropIsQualifier ( kXMP_PropIsQualifier ) ); - XMP_Assert ( XMP_PropHasLang ( kXMP_PropHasLang ) ); - XMP_Assert ( ! XMP_PropHasQualifiers ( ~kXMP_PropHasQualifiers ) ); - XMP_Assert ( ! XMP_PropIsQualifier ( ~kXMP_PropIsQualifier ) ); - XMP_Assert ( ! XMP_PropHasLang ( ~kXMP_PropHasLang ) ); - - XMP_Assert ( XMP_NodeIsSchema ( kXMP_SchemaNode ) ); - XMP_Assert ( XMP_PropIsAlias ( kXMP_PropIsAlias ) ); - XMP_Assert ( ! XMP_NodeIsSchema ( ~kXMP_SchemaNode ) ); - XMP_Assert ( ! XMP_PropIsAlias ( ~kXMP_PropIsAlias ) ); - - #if 0 // Generally off, enable to hand check generated code. - extern XMP_OptionBits opt3, opt4; - if ( XMP_TestOption ( opt3, kXMP_PropValueIsArray ) ) opt4 = opt3; - if ( ! XMP_TestOption ( opt3, kXMP_PropValueIsStruct ) ) opt4 = opt3; - static bool ok1 = XMP_TestOption ( opt4, kXMP_PropValueIsArray ); - static bool ok2 = ! XMP_TestOption ( opt4, kXMP_PropValueIsStruct ); - #endif - - // Make sure the embedded info strings are referenced and kept. - if ( (kXMPCore_EmbeddedVersion[0] == 0) || (kXMPCore_EmbeddedCopyright[0] == 0) ) return false; - return true; - -} // Initialize - - -// ------------------------------------------------------------------------------------------------- -// Terminate -// --------- - -#define EliminateGlobal(g) delete ( g ); g = 0 - -/* class-static */ void -XMPMeta::Terminate() RELEASE_NO_THROW -{ - --sXMP_InitCount; - if ( sXMP_InitCount > 0 ) return; - - #if TraceXMPCalls - fprintf ( xmpOut, "XMP terminating\n" ); fflush ( xmpOut ); - // fclose ( xmpOut ); // Coordinate with fopen in XMPMeta::Initialize. - #endif - - XMPIterator::Terminate(); - XMPUtils::Terminate(); - EliminateGlobal ( sNamespaceURIToPrefixMap ); - EliminateGlobal ( sNamespacePrefixToURIMap ); - EliminateGlobal ( sRegisteredAliasMap ); - - EliminateGlobal ( xdefaultName ); - EliminateGlobal ( sOutputNS ); - EliminateGlobal ( sOutputStr ); - EliminateGlobal ( sExceptionMessage ); - - XMP_TermMutex ( sXMPCoreLock ); - -} // Terminate - - -// ------------------------------------------------------------------------------------------------- -// Unlock -// ------ - -/* class-static */ void -XMPMeta::Unlock ( XMP_OptionBits options ) -{ - UNUSED(options); - - #if TraceXMPLocking - fprintf ( xmpOut, " Unlocking XMP toolkit, count = %d\n", sLockCount ); fflush ( xmpOut ); - #endif - --sLockCount; - XMP_Assert ( sLockCount == 0 ); - XMP_ExitCriticalRegion ( sXMPCoreLock ); - -} // Unlock - - -// ------------------------------------------------------------------------------------------------- -// UnlockObject -// ------------ - -void -XMPMeta::UnlockObject ( XMP_OptionBits options ) const -{ - UNUSED(options); - - XMPMeta::Unlock ( 0 ); - -} // UnlockObject - - -// ------------------------------------------------------------------------------------------------- -// DumpNamespaces -// -------------- -// -// Dump the prefix to URI map (easier to read) and verify that both are consistent and legit. - -// *** Should put checks in a separate routine for regular calling in debug builds. - -/* class-static */ XMP_Status -XMPMeta::DumpNamespaces ( XMP_TextOutputProc outProc, - void * refCon ) -{ - XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper. - XMP_Status status = 0; - - XMP_StringMapPos p2uEnd = sNamespacePrefixToURIMap->end(); // ! Move up to avoid gcc complaints. - XMP_StringMapPos u2pEnd = sNamespaceURIToPrefixMap->end(); - - status = DumpStringMap ( *sNamespacePrefixToURIMap, "Dumping namespace prefix to URI map", outProc, refCon ); - if ( status != 0 ) goto EXIT; - - if ( sNamespacePrefixToURIMap->size() != sNamespaceURIToPrefixMap->size() ) { - OutProcLiteral ( "** bad namespace map sizes **" ); - XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure ); - } - - for ( XMP_StringMapPos nsLeft = sNamespacePrefixToURIMap->begin(); nsLeft != p2uEnd; ++nsLeft ) { - - XMP_StringMapPos nsOther = sNamespaceURIToPrefixMap->find ( nsLeft->second ); - if ( (nsOther == u2pEnd) || (nsLeft != sNamespacePrefixToURIMap->find ( nsOther->second )) ) { - OutProcLiteral ( " ** bad namespace URI ** " ); - DumpClearString ( nsLeft->second, outProc, refCon ); - goto FAILURE; - } - - for ( XMP_StringMapPos nsRight = nsLeft; nsRight != p2uEnd; ++nsRight ) { - if ( nsRight == nsLeft ) continue; // ! Can't start at nsLeft+1, no operator+! - if ( nsLeft->second == nsRight->second ) { - OutProcLiteral ( " ** duplicate namespace URI ** " ); - DumpClearString ( nsLeft->second, outProc, refCon ); - goto FAILURE; - } - } - - } - - for ( XMP_StringMapPos nsLeft = sNamespaceURIToPrefixMap->begin(); nsLeft != u2pEnd; ++nsLeft ) { - - XMP_StringMapPos nsOther = sNamespacePrefixToURIMap->find ( nsLeft->second ); - if ( (nsOther == p2uEnd) || (nsLeft != sNamespaceURIToPrefixMap->find ( nsOther->second )) ) { - OutProcLiteral ( " ** bad namespace prefix ** " ); - DumpClearString ( nsLeft->second, outProc, refCon ); - goto FAILURE; - } - - for ( XMP_StringMapPos nsRight = nsLeft; nsRight != u2pEnd; ++nsRight ) { - if ( nsRight == nsLeft ) continue; // ! Can't start at nsLeft+1, no operator+! - if ( nsLeft->second == nsRight->second ) { - OutProcLiteral ( " ** duplicate namespace prefix ** " ); - DumpClearString ( nsLeft->second, outProc, refCon ); - goto FAILURE; - } - } - - } - -EXIT: - return status; - -FAILURE: - OutProcNewline(); - (void) DumpStringMap ( *sNamespaceURIToPrefixMap, "Dumping namespace URI to prefix map", outProc, refCon ); - XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure ); - return 0; - -} // DumpNamespaces - - -// ------------------------------------------------------------------------------------------------- -// DumpAliases -// ----------- - -/* class-static */ XMP_Status -XMPMeta::DumpAliases ( XMP_TextOutputProc outProc, - void * refCon ) -{ - XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper. - XMP_Status status = 0; - - XMP_Assert ( sRegisteredAliasMap != 0 ); - - XMP_cAliasMapPos aliasPos; - XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end(); - - size_t maxLen = 0; - for ( aliasPos = sRegisteredAliasMap->begin(); aliasPos != aliasEnd; ++aliasPos ) { - size_t currLen = aliasPos->first.size(); - if ( currLen > maxLen ) maxLen = currLen; - } - - OutProcLiteral ( "Dumping alias name to actual path map" ); - OutProcNewline(); - - for ( aliasPos = sRegisteredAliasMap->begin(); aliasPos != aliasEnd; ++aliasPos ) { - - OutProcNChars ( " ", 3 ); - DumpClearString ( aliasPos->first, outProc, refCon ); - OutProcPadding ( maxLen - aliasPos->first.size() ); - OutProcNChars ( " => ", 4 ); - - size_t actualPathSize = aliasPos->second.size(); - for ( size_t stepNum = 1; stepNum < actualPathSize; ++stepNum ) OutProcString ( aliasPos->second[stepNum].step ); - - XMP_OptionBits arrayForm = aliasPos->second[1].options & kXMP_PropArrayFormMask; - - if ( arrayForm == 0 ) { - if ( actualPathSize != 2 ) OutProcLiteral ( " ** bad actual path **" ); - } else { - OutProcNChars ( " ", 2 ); - DumpNodeOptions ( arrayForm, outProc, refCon ); - if ( ! (arrayForm & kXMP_PropValueIsArray) ) OutProcLiteral ( " ** bad array form **" ); - if ( actualPathSize != 3 ) OutProcLiteral ( " ** bad actual path **" ); - } - - if ( aliasPos->second[0].options != kXMP_SchemaNode ) OutProcLiteral ( " ** bad schema form **" ); - - OutProcNewline(); - - } - -EXIT: - return status; - -} // DumpAliases - - -// ------------------------------------------------------------------------------------------------- -// GetGlobalOptions -// ---------------- - -/* class-static */ XMP_OptionBits -XMPMeta::GetGlobalOptions() -{ - XMP_OptionBits options = 0; - - return options; - -} // GetGlobalOptions - - -// ------------------------------------------------------------------------------------------------- -// SetGlobalOptions -// ---------------- - -/* class-static */ void -XMPMeta::SetGlobalOptions ( XMP_OptionBits /*options*/ ) -{ - - XMP_Throw ( "Unimplemented method XMPMeta::SetGlobalOptions", kXMPErr_Unimplemented ); - -} // SetGlobalOptions - - -// ------------------------------------------------------------------------------------------------- -// RegisterNamespace -// ----------------- - -/* class-static */ void -XMPMeta::RegisterNamespace ( XMP_StringPtr namespaceURI, - XMP_StringPtr prefix ) -{ - if ( (*namespaceURI == 0) || (*prefix == 0) ) { - XMP_Throw ( "Empty namespace URI or prefix", kXMPErr_BadParam ); - } - - XMP_VarString nsURI ( namespaceURI ); - XMP_VarString prfix ( prefix ); - if ( prfix[prfix.size()-1] != ':' ) prfix += ':'; - VerifySimpleXMLName ( prefix, prefix+prfix.size()-1 ); // Exclude the colon. - - // Set the new namespace in both maps. - (*sNamespaceURIToPrefixMap)[nsURI] = prfix; - (*sNamespacePrefixToURIMap)[prfix] = nsURI; - -} // RegisterNamespace - - -// ------------------------------------------------------------------------------------------------- -// GetNamespacePrefix -// ------------------ - -/* class-static */ bool -XMPMeta::GetNamespacePrefix ( XMP_StringPtr namespaceURI, - XMP_StringPtr * namespacePrefix, - XMP_StringLen * prefixSize ) -{ - bool found = false; - - XMP_Assert ( *namespaceURI != 0 ); // ! Enforced by wrapper. - XMP_Assert ( (namespacePrefix != 0) && (prefixSize != 0) ); // ! Enforced by wrapper. - - XMP_VarString nsURI ( namespaceURI ); - XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( nsURI ); - - if ( uriPos != sNamespaceURIToPrefixMap->end() ) { - *namespacePrefix = uriPos->second.c_str(); - *prefixSize = uriPos->second.size(); - found = true; - } - - return found; - -} // GetNamespacePrefix - - -// ------------------------------------------------------------------------------------------------- -// GetNamespaceURI -// --------------- - -/* class-static */ bool -XMPMeta::GetNamespaceURI ( XMP_StringPtr namespacePrefix, - XMP_StringPtr * namespaceURI, - XMP_StringLen * uriSize ) -{ - bool found = false; - - XMP_Assert ( *namespacePrefix != 0 ); // ! Enforced by wrapper. - XMP_Assert ( (namespacePrefix != 0) && (namespaceURI != 0) ); // ! Enforced by wrapper. - - XMP_VarString nsPrefix ( namespacePrefix ); - if ( nsPrefix[nsPrefix.size()-1] != ':' ) nsPrefix += ':'; - - XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix ); - - if ( prefixPos != sNamespacePrefixToURIMap->end() ) { - *namespaceURI = prefixPos->second.c_str(); - *uriSize = prefixPos->second.size(); - found = true; - } - - return found; - -} // GetNamespaceURI - - -// ------------------------------------------------------------------------------------------------- -// DeleteNamespace -// --------------- - -// *** Don't allow standard namespaces to be deleted. -// *** We would be better off not having this. Instead, have local namespaces from parsing be -// *** restricted to the object that introduced them. - -/* class-static */ void -XMPMeta::DeleteNamespace ( XMP_StringPtr namespaceURI ) -{ - XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( namespaceURI ); - if ( uriPos == sNamespaceURIToPrefixMap->end() ) return; - - XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( uriPos->second ); - if ( prefixPos == sNamespacePrefixToURIMap->end() ) return; - - sNamespaceURIToPrefixMap->erase ( uriPos ); - sNamespacePrefixToURIMap->erase ( prefixPos ); - -} // DeleteNamespace - - -// ------------------------------------------------------------------------------------------------- -// RegisterAlias -// ------------- -// -// Allow 3 kinds of alias: -// TopProp => TopProp -// TopProp => TopArray[1] -// TopProp => TopArray[@xml:lang='x-default'] -// -// A new alias can be made to something that is already aliased, as long as the net result is one of -// the legitimate forms. The new alias can already have aliases to it, also as long as result of -// adjusting all of the exiting aliases leaves them legal. -// -// ! The caller assumes all risk that new aliases do not invalidate existing XMPMeta objects. Any -// ! conflicts will result in later references throwing bad XPath exceptions. - -/* class-static */ void -XMPMeta::RegisterAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr actualNS, - XMP_StringPtr actualProp, - XMP_OptionBits arrayForm ) -{ - XMP_ExpandedXPath expAlias, expActual; - XMP_AliasMapPos mapPos; - XMP_ExpandedXPath * regActual = 0; - - XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) && (actualNS != 0) && (actualProp != 0) ); // Enforced by wrapper. - - // Expand the alias and actual names, make sure they are one of the basic 3 forms. When counting - // the expanded XPath size remember that the schema URI is the first component. We don't have to - // compare the schema URIs though, the (unique) prefix is part of the top property name. - - ExpandXPath ( aliasNS, aliasProp, &expAlias ); - ExpandXPath ( actualNS, actualProp, &expActual ); - if ( (expAlias.size() != 2) || (expActual.size() != 2) ) { - XMP_Throw ( "Alias and actual property names must be simple", kXMPErr_BadXPath ); - } - - arrayForm = VerifySetOptions ( arrayForm, 0 ); - if ( arrayForm != 0 ) { - if ( (arrayForm & ~kXMP_PropArrayFormMask) != 0 ) XMP_Throw ( "Only array form flags are allowed", kXMPErr_BadOptions ); - expActual[1].options |= arrayForm; // Set the array form for the top level step. - if ( ! (arrayForm & kXMP_PropArrayIsAltText) ) { - expActual.push_back ( XPathStepInfo ( "[1]", kXMP_ArrayIndexStep ) ); - } else { - expActual.push_back ( XPathStepInfo ( "[?xml:lang=\"x-default\"]", kXMP_QualSelectorStep ) ); - } - } - - // See if there are any conflicts with existing aliases. A couple of the checks are easy. If the - // alias is already aliased it is only OK to reregister an identical alias. If the actual is - // already aliased to something else and the new chain is legal, just swap in the old base. - - mapPos = sRegisteredAliasMap->find ( expAlias[kRootPropStep].step ); - if ( mapPos != sRegisteredAliasMap->end() ) { - - // This alias is already registered to something, make sure it is the same something. - - regActual = &mapPos->second; - if ( arrayForm != (mapPos->second[1].options & kXMP_PropArrayFormMask) ) { - XMP_Throw ( "Mismatch with existing alias array form", kXMPErr_BadParam ); - } - if ( expActual.size() != regActual->size() ) { - XMP_Throw ( "Mismatch with existing actual path", kXMPErr_BadParam ); - } - if ( expActual[kRootPropStep].step != (*regActual)[kRootPropStep].step ) { - XMP_Throw ( "Mismatch with existing actual name", kXMPErr_BadParam ); - } - if ( (expActual.size() == 3) && (expActual[kAliasIndexStep].step != (*regActual)[kAliasIndexStep].step) ) { - XMP_Throw ( "Mismatch with existing actual array item", kXMPErr_BadParam ); - } - return; - - } - - mapPos = sRegisteredAliasMap->find ( expActual[kRootPropStep].step ); - if ( mapPos != sRegisteredAliasMap->end() ) { - - // The actual is already aliased to something else. - - regActual = &mapPos->second; - if ( expActual.size() == 2 ) { - expActual = *regActual; // TopProp => TopProp => anything : substitute the entire old base. - } else if ( regActual->size() != 2 ) { - XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam ); // TopProp => TopArray[] => TopArray[] : nope. - } else { - expActual[kSchemaStep].step = (*regActual)[kSchemaStep].step; // TopProp => TopArray[] => TopProp : - expActual[kRootPropStep].step = (*regActual)[kRootPropStep].step; // substitute the old base name. - } - - } - - // Checking for existing aliases to this one is touchier. This involves updating the alias map, - // which must not be done unless all of the changes are legal. So we need 2 loops, one to verify - // that everything is OK, and one to make the changes. The bad case is: - // TopProp => TopArray[] => TopArray[] - // In the valid cases we back substitute the new base. - - for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) { - regActual = &mapPos->second; - if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) { - if ( (regActual->size() == 2) && (expAlias.size() == 2) ) { - XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam ); - } - } - } - - for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) { - regActual = &mapPos->second; - if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) { - - if ( regActual->size() == 1 ) { - *regActual = expActual; // TopProp => TopProp => anything : substitute the entire new base. - } else { - (*regActual)[kSchemaStep].step = expActual[kSchemaStep].step; // TopProp => TopArray[] => TopProp : - (*regActual)[kRootPropStep].step = expActual[kRootPropStep].step; // substitute the new base name. - } - - } - } - - // Finally, all is OK to register the new alias. - - (void) sRegisteredAliasMap->insert ( XMP_AliasMap::value_type ( expAlias[kRootPropStep].step, expActual ) ); - -} // RegisterAlias - - -// ------------------------------------------------------------------------------------------------- -// ResolveAlias -// ------------ - -/* class-static */ bool -XMPMeta::ResolveAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr * actualNS, - XMP_StringLen * nsSize, - XMP_StringPtr * actualProp, - XMP_StringLen * propSize, - XMP_OptionBits * arrayForm ) -{ - XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) ); // Enforced by wrapper. - XMP_Assert ( (actualNS != 0) && (nsSize != 0) && (actualProp != 0) && (propSize != 0) && (arrayForm != 0) ); // Enforced by wrapper. - - // Expand the input path and look up the first component in the alias table. Return if not an alias. - - XMP_ExpandedXPath fullPath, minPath; - ExpandXPath ( aliasNS, aliasProp, &fullPath ); - XMP_Assert ( fullPath.size() >= 2 ); - - minPath.push_back ( fullPath[kSchemaStep] ); - minPath.push_back ( fullPath[kRootPropStep] ); - XMP_AliasMapPos mapPos = sRegisteredAliasMap->find ( minPath[kRootPropStep].step ); - if ( mapPos == sRegisteredAliasMap->end() ) return false; - - // Replace the alias portion of the full expanded path. Compose the output path string. - - const XMP_ExpandedXPath & actualPath = mapPos->second; - - fullPath[kSchemaStep] = actualPath[kSchemaStep]; - fullPath[kRootPropStep] = actualPath[kRootPropStep]; - if ( actualPath.size() > 2 ) { // This is an alias to an array item. - XMP_ExpandedXPathPos insertPos = fullPath.begin() + kAliasIndexStep; - fullPath.insert ( insertPos, actualPath[kAliasIndexStep] ); - } - - *sOutputNS = fullPath[kSchemaStep].step; - *actualNS = sOutputNS->c_str(); - *nsSize = sOutputNS->size(); - - ComposeXPath ( fullPath, sOutputStr ); - *actualProp = sOutputStr->c_str(); - *propSize = sOutputStr->size(); - - *arrayForm = actualPath[kRootPropStep].options & kXMP_PropArrayFormMask; - - #if XMP_DebugBuild // Test that the output string is valid and unchanged by round trip expand/compose. - XMP_ExpandedXPath rtPath; - ExpandXPath ( *actualNS, *actualProp, &rtPath ); - std::string rtString; - ComposeXPath ( rtPath, &rtString ); - XMP_Assert ( rtString == *sOutputStr ); - #endif - - return true; - -} // ResolveAlias - - -// ------------------------------------------------------------------------------------------------- -// DeleteAlias -// ----------- - -/* class-static */ void -XMPMeta::DeleteAlias ( XMP_StringPtr /*aliasNS*/, - XMP_StringPtr /*aliasProp*/ ) -{ - -// Todo: XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) ); / / Enforced by wrapper. - XMP_Throw ( "Unimplemented method XMPMeta::DeleteAlias", kXMPErr_Unimplemented ); // *** #error "write me" - -} // DeleteAlias - - -// ------------------------------------------------------------------------------------------------- -// RegisterStandardAliases -// ----------------------- - -/* class-static */ void -XMPMeta::RegisterStandardAliases ( XMP_StringPtr schemaNS ) -{ - XMP_Assert ( schemaNS != 0 ); // Enforced by wrapper. - - const bool doAll = (*schemaNS == 0); - - if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_XMP ) ) { - // Aliases from XMP to DC. - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Authors", kXMP_NS_DC, "creator", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Description", kXMP_NS_DC, "description", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Format", kXMP_NS_DC, "format", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Keywords", kXMP_NS_DC, "subject", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Locale", kXMP_NS_DC, "language", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Title", kXMP_NS_DC, "title", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_XMP_Rights, "Copyright", kXMP_NS_DC, "rights", 0 ); - } - - if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_PDF ) ) { - // Aliases from PDF to DC and XMP. - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered ); - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "BaseURL", kXMP_NS_XMP, "BaseURL", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "CreationDate", kXMP_NS_XMP, "CreateDate", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Creator", kXMP_NS_XMP, "CreatorTool", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "ModDate", kXMP_NS_XMP, "ModifyDate", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Subject", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText ); - XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText ); - } - - if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_Photoshop ) ) { - // Aliases from PHOTOSHOP to DC and XMP. - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered ); - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Caption", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText ); - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Copyright", kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText ); - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Keywords", kXMP_NS_DC, "subject", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Marked", kXMP_NS_XMP_Rights, "Marked", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText ); - XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "WebStatement", kXMP_NS_XMP_Rights, "WebStatement", 0 ); - } - - if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_TIFF ) || XMP_LitMatch ( schemaNS, kXMP_NS_EXIF ) ) { - // Aliases from TIFF and EXIF to DC and XMP. - XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Artist", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered); - XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Copyright", kXMP_NS_DC, "rights", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "DateTime", kXMP_NS_XMP, "ModifyDate", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "ImageDescription", kXMP_NS_DC, "description", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Software", kXMP_NS_XMP, "CreatorTool", 0 ); - } - - if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_PNG ) ) { // ! From Acrobat ImageCapture: - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Author", kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered); - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Copyright", kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText); - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "CreationTime", kXMP_NS_XMP, "CreateDate", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Description", kXMP_NS_DC, "description", kXMP_PropArrayIsAltText); - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "ModificationTime", kXMP_NS_XMP, "ModifyDate", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Software", kXMP_NS_XMP, "CreatorTool", 0 ); - XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Title", kXMP_NS_DC, "title", kXMP_PropArrayIsAltText); - } - -} // RegisterStandardAliases - - -// ================================================================================================= -// Class Methods -// ============= -// -// -// ================================================================================================= - - -// ------------------------------------------------------------------------------------------------- -// DumpObject -// ---------- - -XMP_Status -XMPMeta::DumpObject ( XMP_TextOutputProc outProc, - void * refCon ) const -{ - XMP_Assert ( outProc != 0 ); // ! Enforced by wrapper. - XMP_Status status = 0; - - OutProcLiteral ( "Dumping XMPMeta object \"" ); - DumpClearString ( tree.name, outProc, refCon ); - OutProcNChars ( "\" ", 3 ); - status = DumpNodeOptions ( tree.options, outProc, refCon ); - if ( status != 0 ) goto EXIT; - #if 0 // *** XMP_DebugBuild - if ( (tree._namePtr != tree.name.c_str()) || - (tree._valuePtr != tree.value.c_str()) ) OutProcLiteral ( " ** bad debug string **" ); - #endif - OutProcNewline(); - - if ( ! tree.value.empty() ) { - OutProcLiteral ( "** bad root value ** \"" ); - DumpClearString ( tree.value, outProc, refCon ); - OutProcNChars ( "\"", 1 ); - OutProcNewline(); - } - - if ( ! tree.qualifiers.empty() ) { - OutProcLiteral ( "** bad root qualifiers **" ); - OutProcNewline(); - for ( size_t qualNum = 0, qualLim = tree.qualifiers.size(); qualNum < qualLim; ++qualNum ) { - status = DumpPropertyTree ( tree.qualifiers[qualNum], 3, 0, outProc, refCon ); - } - } - - if ( ! tree.children.empty() ) { - - for ( size_t childNum = 0, childLim = tree.children.size(); childNum < childLim; ++childNum ) { - - const XMP_Node * currSchema = tree.children[childNum]; - - OutProcNewline(); - OutProcIndent ( 1 ); - DumpClearString ( currSchema->value, outProc, refCon ); - OutProcNChars ( " ", 2 ); - DumpClearString ( currSchema->name, outProc, refCon ); - OutProcNChars ( " ", 2 ); - status = DumpNodeOptions ( currSchema->options, outProc, refCon ); - if ( status != 0 ) goto EXIT; - #if 0 // *** XMP_DebugBuild - if ( (currSchema->_namePtr != currSchema->name.c_str()) || - (currSchema->_valuePtr != currSchema->value.c_str()) ) OutProcLiteral ( " ** bad debug string **" ); - #endif - OutProcNewline(); - - if ( ! (currSchema->options & kXMP_SchemaNode) ) { - OutProcLiteral ( "** bad schema options **" ); - OutProcNewline(); - } - - if ( ! currSchema->qualifiers.empty() ) { - OutProcLiteral ( "** bad schema qualifiers **" ); - OutProcNewline(); - for ( size_t qualNum = 0, qualLim = currSchema->qualifiers.size(); qualNum < qualLim; ++qualNum ) { - DumpPropertyTree ( currSchema->qualifiers[qualNum], 3, 0, outProc, refCon ); - } - } - - for ( size_t childNum = 0, childLim = currSchema->children.size(); childNum < childLim; ++childNum ) { - DumpPropertyTree ( currSchema->children[childNum], 2, 0, outProc, refCon ); - } - - } - - } - -EXIT: - return status; - -} // DumpObject - - -// ------------------------------------------------------------------------------------------------- -// CountArrayItems -// --------------- - -XMP_Index -XMPMeta::CountArrayItems ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName ) const -{ - XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; - ExpandXPath ( schemaNS, arrayName, &expPath ); - - const XMP_Node * arrayNode = FindConstNode ( &tree, expPath ); - - 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(); - -} // CountArrayItems - - -// ------------------------------------------------------------------------------------------------- -// GetObjectName -// ------------- - -void -XMPMeta::GetObjectName ( XMP_StringPtr * namePtr, - XMP_StringLen * nameLen ) const -{ - - *namePtr = tree.name.c_str(); - *nameLen = tree.name.size(); - -} // GetObjectName - - -// ------------------------------------------------------------------------------------------------- -// SetObjectName -// ------------- - -void -XMPMeta::SetObjectName ( XMP_StringPtr name ) -{ - VerifyUTF8 ( name ); // Throws if the string is not legit UTF-8. - tree.name = name; - -} // SetObjectName - - -// ------------------------------------------------------------------------------------------------- -// GetObjectOptions -// ---------------- - -XMP_OptionBits -XMPMeta::GetObjectOptions() const -{ - XMP_OptionBits options = 0; - - return options; - -} // GetObjectOptions - - -// ------------------------------------------------------------------------------------------------- -// SetObjectOptions -// ---------------- - -void -XMPMeta::SetObjectOptions ( XMP_OptionBits /*options*/ ) -{ - - XMP_Throw ( "Unimplemented method XMPMeta::SetObjectOptions", kXMPErr_Unimplemented ); - -} // SetObjectOptions - - -// ------------------------------------------------------------------------------------------------- -// Sort -// ---- -// -// At the top level the namespaces are sorted by their prefixes. Within a namespace, the top level -// properties are sorted by name. Within a struct, the fields are sorted by their qualified name, -// i.e. their XML prefix:local form. Unordered arrays of simple items are sorted by value. Language -// Alternative arrays are sorted by the xml:lang qualifiers, with the "x-default" item placed first. - -void -XMPMeta::Sort() -{ - - if ( ! this->tree.qualifiers.empty() ) { - sort ( this->tree.qualifiers.begin(), this->tree.qualifiers.end(), CompareNodeNames ); - SortWithinOffspring ( this->tree.qualifiers ); - } - - if ( ! this->tree.children.empty() ) { - // The schema prefixes are the node's value, the name is the URI, so we sort schemas by value. - sort ( this->tree.children.begin(), this->tree.children.end(), CompareNodeValues ); - SortWithinOffspring ( this->tree.children ); - } - -} // Sort - - -// ------------------------------------------------------------------------------------------------- -// Erase -// ----- -// -// Clear everything except for clientRefs. - -void -XMPMeta::Erase() -{ - - this->prevTkVer = 0; - if ( this->xmlParser != 0 ) { - delete ( this->xmlParser ); - this->xmlParser = 0; - } - this->tree.ClearNode(); - -} // Erase - - -// ------------------------------------------------------------------------------------------------- -// Clone -// ----- - -void -XMPMeta::Clone ( XMPMeta * clone, XMP_OptionBits options ) const -{ - if ( clone == 0 ) XMP_Throw ( "Null clone pointer", kXMPErr_BadParam ); - if ( options != 0 ) XMP_Throw ( "No options are defined yet", kXMPErr_BadOptions ); - XMP_Assert ( this->tree.parent == 0 ); - - clone->tree.ClearNode(); - - clone->tree.options = this->tree.options; - clone->tree.name = this->tree.name; - clone->tree.value = this->tree.value; - - #if 0 // *** XMP_DebugBuild - clone->tree._namePtr = clone->tree.name.c_str(); - clone->tree._valuePtr = clone->tree.value.c_str(); - #endif - - CloneOffspring ( &this->tree, &clone->tree ); - -} // Clone - -// ================================================================================================= diff --git a/xmpsdk/src/XMPMeta.hpp b/xmpsdk/src/XMPMeta.hpp deleted file mode 100644 index 68462dce64..0000000000 --- a/xmpsdk/src/XMPMeta.hpp +++ /dev/null @@ -1,418 +0,0 @@ -#ifndef __XMPMeta_hpp__ -#define __XMPMeta_hpp__ - -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" -#include "XMP_Const.h" -#include "XMPCore_Impl.hpp" -#include "XMLParserAdapter.hpp" - -// ------------------------------------------------------------------------------------------------- - -#ifndef DumpXMLParseTree - #define DumpXMLParseTree 0 -#endif - -extern XMP_VarString * xdefaultName; - -class XMPIterator; -class XMPUtils; - -// ------------------------------------------------------------------------------------------------- - -class XMPMeta { -public: - - static void - GetVersionInfo ( XMP_VersionInfo * info ); - - static bool - Initialize(); - static void - Terminate() RELEASE_NO_THROW; - - static void - Unlock ( XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - - XMPMeta(); - - virtual ~XMPMeta() RELEASE_NO_THROW; - - // --------------------------------------------------------------------------------------------- - - static XMP_OptionBits - GetGlobalOptions(); - - static void - SetGlobalOptions ( XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - - static XMP_Status - DumpNamespaces ( XMP_TextOutputProc outProc, - void * refCon ); - - static XMP_Status - DumpAliases ( XMP_TextOutputProc outProc, - void * refCon ); - - // --------------------------------------------------------------------------------------------- - - static void - RegisterNamespace ( XMP_StringPtr namespaceURI, - XMP_StringPtr prefix ); - - static bool - GetNamespacePrefix ( XMP_StringPtr namespaceURI, - XMP_StringPtr * namespacePrefix, - XMP_StringLen * prefixSize ); - - static bool - GetNamespaceURI ( XMP_StringPtr namespacePrefix, - XMP_StringPtr * namespaceURI, - XMP_StringLen * uriSize ); - - static void - DeleteNamespace ( XMP_StringPtr namespaceURI ); - - // --------------------------------------------------------------------------------------------- - - static void - RegisterAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr actualNS, - XMP_StringPtr actualProp, - XMP_OptionBits arrayForm ); - - static bool - ResolveAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp, - XMP_StringPtr * actualNS, - XMP_StringLen * nsSize, - XMP_StringPtr * actualProp, - XMP_StringLen * propSize, - XMP_OptionBits * arrayForm ); - - static void - DeleteAlias ( XMP_StringPtr aliasNS, - XMP_StringPtr aliasProp ); - - static void - RegisterStandardAliases ( XMP_StringPtr schemaNS ); - - // --------------------------------------------------------------------------------------------- - - void - UnlockObject ( XMP_OptionBits options ) const; - - // --------------------------------------------------------------------------------------------- - - bool - GetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr * propValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const; - - bool - GetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * itemValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const; - - bool - GetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fieldValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const; - - bool - GetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * qualValue, - XMP_StringLen * valueSize, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - - void - SetProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr propValue, - XMP_OptionBits options ); - - void - SetArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr itemValue, - XMP_OptionBits options ); - - void - AppendArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits arrayOptions, - XMP_StringPtr itemValue, - XMP_OptionBits options ); - - void - SetStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_OptionBits options ); - - void - SetQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr qualValue, - XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - - void - DeleteProperty ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ); - - void - DeleteArrayItem ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ); - - void - DeleteStructField ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ); - - void - DeleteQualifier ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ); - - // --------------------------------------------------------------------------------------------- - - bool - DoesPropertyExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName ) const; - - bool - DoesArrayItemExist ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex ) const; - - bool - DoesStructFieldExist ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName ) const; - - bool - DoesQualifierExist ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName ) const; - - // --------------------------------------------------------------------------------------------- - - 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; - - void - SetLocalizedText ( XMP_StringPtr schemaNS, - XMP_StringPtr altTextName, - XMP_StringPtr genericLang, - XMP_StringPtr specificLang, - XMP_StringPtr itemValue, - XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - - bool - GetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool * propValue, - XMP_OptionBits * options ) const; - - bool - GetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 * propValue, - XMP_OptionBits * options ) const; - - bool - GetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 * propValue, - XMP_OptionBits * options ) const; - - bool - GetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double * propValue, - XMP_OptionBits * options ) const; - - bool - GetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_DateTime * propValue, - XMP_OptionBits * options ) const; - - // --------------------------------------------------------------------------------------------- - - void - SetProperty_Bool ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - bool propValue, - XMP_OptionBits options ); - - void - SetProperty_Int ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int32 propValue, - XMP_OptionBits options ); - - void - SetProperty_Int64 ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_Int64 propValue, - XMP_OptionBits options ); - - void - SetProperty_Float ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - double propValue, - XMP_OptionBits options ); - - void - SetProperty_Date ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - const XMP_DateTime & propValue, - XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - - void - GetObjectName ( XMP_StringPtr * namePtr, - XMP_StringLen * nameLen ) const; - - void - SetObjectName ( XMP_StringPtr name ); - - XMP_OptionBits - GetObjectOptions() const; - - void - SetObjectOptions ( XMP_OptionBits options ); - - void - Sort(); - - void - Erase(); - - void - Clone ( XMPMeta * clone, XMP_OptionBits options ) const; - - XMP_Index - CountArrayItems ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName ) const; - - XMP_Status - DumpObject ( XMP_TextOutputProc outProc, - void * refCon ) const; - - // --------------------------------------------------------------------------------------------- - - void - ParseFromBuffer ( XMP_StringPtr buffer, - XMP_StringLen bufferSize, - XMP_OptionBits options ); - - void - SerializeToBuffer ( XMP_StringPtr * rdfString, - XMP_StringLen * rdfSize, - XMP_OptionBits options, - XMP_StringLen padding, - XMP_StringPtr newline, - XMP_StringPtr indent, - XMP_Index baseIndent ) const; - - // ============================================================================================= - - // --------------------------------------------------------------------------------------------- - // - Everything is built out of standard nodes. Each node has a name, value, option flags, a - // vector of child nodes, and a vector of qualifier nodes. - // - // - The option flags are those passed to SetProperty and returned from GetProperty. They tell - // if the node is simple, a struct or an array; whether it has qualifiers, etc. - // - // - The name of the node is an XML qualified name, of the form "prefix:simple-name". Since we - // force all namespaces to be known and to have unique prefixes, this is semantically equivalent - // to using a URI and simple name pair. - // - // - Although the value part is only for leaf properties and the children part is only for - // structs and arrays, it is easier to simply have them in every node. This keeps things visible - // so that debugging is easier - // - // - The top level node children are the namespaces that contain properties, the next level are - // the top level properties, lower levels are the fields of structs or items of arrays. The name - // of the top level nodes is just the namespace prefix, with the colon terminator. The name of - // top level properties includes the namespace prefix. - // - // - Any property node, at any level, can have qualifiers. These are themselves general property - // nodes. And could in fact themselves have qualifiers! - - // ! Expose the implementation so that file static functions can see the data. - - XMP_Int32 clientRefs; // ! Must be signed to allow decrement from 0. - XMP_Int32 prevTkVer; // Previous toolkit version as MMmmuubbb (major, minor, micro, build). - XMP_Node tree; - - XMLParserAdapter * xmlParser; - - friend class XMPIterator; - friend class XMPUtils; - -private: - - // ! These are hidden on purpose: - XMPMeta ( const XMPMeta & /* original */ ) : clientRefs(0), prevTkVer(0), tree(XMP_Node(0,"",0)), xmlParser(0) - { XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); }; - void operator= ( const XMPMeta & /* rhs */ ) - { XMP_Throw ( "Call to hidden operator=", kXMPErr_InternalFailure ); }; - -}; // class XMPMeta - - -// ================================================================================================= - -#endif // __XMPMeta_hpp__ diff --git a/xmpsdk/src/XMPUtils-FileInfo.cpp b/xmpsdk/src/XMPUtils-FileInfo.cpp deleted file mode 100644 index f0f54ba327..0000000000 --- a/xmpsdk/src/XMPUtils-FileInfo.cpp +++ /dev/null @@ -1,1346 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2008 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPUtils.hpp" - -#include -#include -#include -#include -#include - -#include // For snprintf. - -#if XMP_WinBuild -#ifdef _MSC_VER - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) -#endif -#endif - -// ================================================================================================= -// Local Types and Constants -// ========================= - -typedef unsigned long UniCodePoint; - -enum UniCharKind { - UCK_normal, - UCK_space, - UCK_comma, - UCK_semicolon, - UCK_quote, - UCK_control -}; -typedef enum UniCharKind UniCharKind; - -#define UnsByte(c) ((unsigned char)(c)) -#define UCP(u) ((UniCodePoint)(u)) - // ! Needed on Windows (& PC Linux?) for inequalities with literals ito avoid sign extension. - -#ifndef TraceMultiFile - #define TraceMultiFile 0 -#endif - -// ================================================================================================= -// Static Variables -// ================ - -// ================================================================================================= -// Local Utilities -// =============== - -// ------------------------------------------------------------------------------------------------- -// ClassifyCharacter -// ----------------- - -static void -ClassifyCharacter ( XMP_StringPtr fullString, size_t offset, - UniCharKind * charKind, size_t * charSize, UniCodePoint * uniChar ) -{ - *charKind = UCK_normal; // Assume typical case. - - unsigned char currByte = UnsByte ( fullString[offset] ); - - if ( currByte < UnsByte(0x80) ) { - - // ---------------------------------------- - // We've got a single byte ASCII character. - - *charSize = 1; - *uniChar = currByte; - - if ( currByte > UnsByte(0x22) ) { - - if ( currByte == UnsByte(0x2C) ) { - *charKind = UCK_comma; - } else if ( currByte == UnsByte(0x3B) ) { - *charKind = UCK_semicolon; - } else if ( (currByte == UnsByte(0x5B)) || (currByte == UnsByte(0x5D)) ) { - *charKind = UCK_quote; // ! ASCII '[' and ']' are used as quotes in Chinese and Korean. - } - - } else { // currByte <= 0x22 - - if ( currByte == UnsByte(0x22) ) { - *charKind = UCK_quote; - } else if ( currByte == UnsByte(0x21) ) { - *charKind = UCK_normal; - } else if ( currByte == UnsByte(0x20) ) { - *charKind = UCK_space; - } else { - *charKind = UCK_control; - } - - } - - } else { // currByte >= 0x80 - - // --------------------------------------------------------------------------------------- - // We've got a multibyte Unicode character. The first byte has the number of bytes and the - // highest order bits. The other bytes each add 6 more bits. Compose the UTF-32 form so we - // can classify directly with the Unicode code points. Order the upperBits tests to be - // fastest for Japan, probably the most common non-ASCII usage. - - *charSize = 0; - *uniChar = currByte; - while ( (*uniChar & 0x80) != 0 ) { // Count the leading 1 bits in the byte. - ++(*charSize); - *uniChar = *uniChar << 1; - } - XMP_Assert ( (offset + *charSize) <= strlen(fullString) ); - - *uniChar = *uniChar & 0x7F; // Put the character bits in the bottom of uniChar. - *uniChar = *uniChar >> *charSize; - - for ( size_t i = (offset + 1); i < (offset + *charSize); ++i ) { - *uniChar = (*uniChar << 6) | (UnsByte(fullString[i]) & 0x3F); - } - - XMP_Uns32 upperBits = *uniChar >> 8; // First filter on just the high order 24 bits. - - if ( upperBits == 0xFF ) { // U+FFxx - - if ( *uniChar == UCP(0xFF0C) ) { - *charKind = UCK_comma; // U+FF0C, full width comma. - } else if ( *uniChar == UCP(0xFF1B) ) { - *charKind = UCK_semicolon; // U+FF1B, full width semicolon. - } else if ( *uniChar == UCP(0xFF64) ) { - *charKind = UCK_comma; // U+FF64, half width ideographic comma. - } - - } else if ( upperBits == 0xFE ) { // U+FE-- - - if ( *uniChar == UCP(0xFE50) ) { - *charKind = UCK_comma; // U+FE50, small comma. - } else if ( *uniChar == UCP(0xFE51) ) { - *charKind = UCK_comma; // U+FE51, small ideographic comma. - } else if ( *uniChar == UCP(0xFE54) ) { - *charKind = UCK_semicolon; // U+FE54, small semicolon. - } - - } else if ( upperBits == 0x30 ) { // U+30-- - - if ( *uniChar == UCP(0x3000) ) { - *charKind = UCK_space; // U+3000, ideographic space. - } else if ( *uniChar == UCP(0x3001) ) { - *charKind = UCK_comma; // U+3001, ideographic comma. - } else if ( (UCP(0x3008) <= *uniChar) && (*uniChar <= UCP(0x300F)) ) { - *charKind = UCK_quote; // U+3008..U+300F, various quotes. - } else if ( *uniChar == UCP(0x303F) ) { - *charKind = UCK_space; // U+303F, ideographic half fill space. - } else if ( (UCP(0x301D) <= *uniChar) && (*uniChar <= UCP(0x301F)) ) { - *charKind = UCK_quote; // U+301D..U+301F, double prime quotes. - } - - } else if ( upperBits == 0x20 ) { // U+20-- - - if ( (UCP(0x2000) <= *uniChar) && (*uniChar <= UCP(0x200B)) ) { - *charKind = UCK_space; // U+2000..U+200B, en quad through zero width space. - } else if ( *uniChar == UCP(0x2015) ) { - *charKind = UCK_quote; // U+2015, dash quote. - } else if ( (UCP(0x2018) <= *uniChar) && (*uniChar <= UCP(0x201F)) ) { - *charKind = UCK_quote; // U+2018..U+201F, various quotes. - } else if ( *uniChar == UCP(0x2028) ) { - *charKind = UCK_control; // U+2028, line separator. - } else if ( *uniChar == UCP(0x2029) ) { - *charKind = UCK_control; // U+2029, paragraph separator. - } else if ( (*uniChar == UCP(0x2039)) || (*uniChar == UCP(0x203A)) ) { - *charKind = UCK_quote; // U+2039 and U+203A, guillemet quotes. - } - - } else if ( upperBits == 0x06 ) { // U+06-- - - if ( *uniChar == UCP(0x060C) ) { - *charKind = UCK_comma; // U+060C, Arabic comma. - } else if ( *uniChar == UCP(0x061B) ) { - *charKind = UCK_semicolon; // U+061B, Arabic semicolon. - } - - } else if ( upperBits == 0x05 ) { // U+05-- - - if ( *uniChar == UCP(0x055D) ) { - *charKind = UCK_comma; // U+055D, Armenian comma. - } - - } else if ( upperBits == 0x03 ) { // U+03-- - - if ( *uniChar == UCP(0x037E) ) { - *charKind = UCK_semicolon; // U+037E, Greek "semicolon" (really a question mark). - } - - } else if ( upperBits == 0x00 ) { // U+00-- - - if ( (*uniChar == UCP(0x00AB)) || (*uniChar == UCP(0x00BB)) ) { - *charKind = UCK_quote; // U+00AB and U+00BB, guillemet quotes. - } - - } - - } - -} // ClassifyCharacter - - -// ------------------------------------------------------------------------------------------------- -// IsClosingingQuote -// ----------------- - -static inline bool -IsClosingingQuote ( UniCodePoint uniChar, UniCodePoint openQuote, UniCodePoint closeQuote ) -{ - - if ( (uniChar == closeQuote) || - ( (openQuote == UCP(0x301D)) && ((uniChar == UCP(0x301E)) || (uniChar == UCP(0x301F))) ) ) { - return true; - } else { - return false; - } - -} // IsClosingingQuote - - -// ------------------------------------------------------------------------------------------------- -// IsSurroundingQuote -// ------------------ - -static inline bool -IsSurroundingQuote ( UniCodePoint uniChar, UniCodePoint openQuote, UniCodePoint closeQuote ) -{ - - if ( (uniChar == openQuote) || IsClosingingQuote ( uniChar, openQuote, closeQuote ) ) { - return true; - } else { - return false; - } - -} // IsSurroundingQuote - - -// ------------------------------------------------------------------------------------------------- -// GetClosingQuote -// --------------- - -static UniCodePoint -GetClosingQuote ( UniCodePoint openQuote ) -{ - UniCodePoint closeQuote; - - switch ( openQuote ) { - - case UCP(0x0022) : closeQuote = UCP(0x0022); // ! U+0022 is both opening and closing. - break; - case UCP(0x005B) : closeQuote = UCP(0x005D); - break; - case UCP(0x00AB) : closeQuote = UCP(0x00BB); // ! U+00AB and U+00BB are reversible. - break; - case UCP(0x00BB) : closeQuote = UCP(0x00AB); - break; - case UCP(0x2015) : closeQuote = UCP(0x2015); // ! U+2015 is both opening and closing. - break; - case UCP(0x2018) : closeQuote = UCP(0x2019); - break; - case UCP(0x201A) : closeQuote = UCP(0x201B); - break; - case UCP(0x201C) : closeQuote = UCP(0x201D); - break; - case UCP(0x201E) : closeQuote = UCP(0x201F); - break; - case UCP(0x2039) : closeQuote = UCP(0x203A); // ! U+2039 and U+203A are reversible. - break; - case UCP(0x203A) : closeQuote = UCP(0x2039); - break; - case UCP(0x3008) : closeQuote = UCP(0x3009); - break; - case UCP(0x300A) : closeQuote = UCP(0x300B); - break; - case UCP(0x300C) : closeQuote = UCP(0x300D); - break; - case UCP(0x300E) : closeQuote = UCP(0x300F); - break; - case UCP(0x301D) : closeQuote = UCP(0x301F); // ! U+301E also closes U+301D. - break; - default : closeQuote = 0; - break; - - } - - return closeQuote; - -} // GetClosingQuote - - -// ------------------------------------------------------------------------------------------------- -// CodePointToUTF8 -// --------------- - -static void -CodePointToUTF8 ( UniCodePoint uniChar, XMP_VarString & utf8Str ) -{ - size_t i, byteCount; - XMP_Uns8 buffer [8]; - UniCodePoint cpTemp; - - if ( uniChar <= 0x7F ) { - - i = 7; - byteCount = 1; - buffer[7] = char(uniChar); - - } else { - - // --------------------------------------------------------------------------------------- - // Copy the data bits from the low order end to the high order end, include the 0x80 mask. - - i = 8; - cpTemp = uniChar; - while ( cpTemp != 0 ) { - -- i; // Exit with i pointing to the last byte stored. - buffer[i] = UnsByte(0x80) | (UnsByte(cpTemp) & 0x3F); - cpTemp = cpTemp >> 6; - } - byteCount = 8 - i; // The total number of bytes needed. - XMP_Assert ( (2 <= byteCount) && (byteCount <= 6) ); - - // ------------------------------------------------------------------------------------- - // Make sure the high order byte can hold the byte count mask, compute and set the mask. - - size_t bitCount = 0; // The number of data bits in the first byte. - for ( cpTemp = (buffer[i] & UnsByte(0x3F)); cpTemp != 0; cpTemp = cpTemp >> 1 ) bitCount += 1; - if ( bitCount > (8 - (byteCount + 1)) ) byteCount += 1; - - i = 8 - byteCount; // First byte index and mask shift count. - XMP_Assert ( (0 <= i) && (i <= 6) ); - buffer[i] |= (UnsByte(0xFF) << i) & UnsByte(0xFF); // AUDIT: Safe, i is between 0 and 6. - - } - - utf8Str.assign ( (char*)(&buffer[i]), byteCount ); - -} // CodePointToUTF8 - - -// ------------------------------------------------------------------------------------------------- -// ApplyQuotes -// ----------- - -static void -ApplyQuotes ( XMP_VarString * item, UniCodePoint openQuote, UniCodePoint closeQuote, bool allowCommas ) -{ - bool prevSpace = false; - size_t charOffset, charLen; - UniCharKind charKind; - UniCodePoint uniChar; - - // ----------------------------------------------------------------------------------------- - // See if there are any separators in the value. Stop at the first occurrance. This is a bit - // tricky in order to make typical typing work conveniently. The purpose of applying quotes - // is to preserve the values when splitting them back apart. That is CatenateContainerItems - // and SeparateContainerItems must round trip properly. For the most part we only look for - // separators here. Internal quotes, as in -- Irving "Bud" Jones -- won't cause problems in - // the separation. An initial quote will though, it will make the value look quoted. - - charOffset = 0; - ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar ); - - if ( charKind != UCK_quote ) { - - for ( charOffset = 0; size_t(charOffset) < item->size(); charOffset += charLen ) { - - ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar ); - - if ( charKind == UCK_space ) { - if ( prevSpace ) break; // Multiple spaces are a separator. - prevSpace = true; - } else { - prevSpace = false; - if ( (charKind == UCK_semicolon) || (charKind == UCK_control) ) break; - if ( (charKind == UCK_comma) && (! allowCommas) ) break; - } - - } - - } - - if ( size_t(charOffset) < item->size() ) { - - // -------------------------------------------------------------------------------------- - // Create a quoted copy, doubling any internal quotes that match the outer ones. Internal - // quotes did not stop the "needs quoting" search, but they do need doubling. So we have - // to rescan the front of the string for quotes. Handle the special case of U+301D being - // closed by either U+301E or U+301F. - - XMP_VarString newItem; - size_t splitPoint; - - for ( splitPoint = 0; splitPoint <= charOffset; ++splitPoint ) { - ClassifyCharacter ( item->c_str(), splitPoint, &charKind, &charLen, &uniChar ); - if ( charKind == UCK_quote ) break; - } - - CodePointToUTF8 ( openQuote, newItem ); - newItem.append ( *item, 0, splitPoint ); // Copy the leading "normal" portion. - - for ( charOffset = splitPoint; size_t(charOffset) < item->size(); charOffset += charLen ) { - ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar ); - newItem.append ( *item, charOffset, charLen ); - if ( (charKind == UCK_quote) && IsSurroundingQuote ( uniChar, openQuote, closeQuote ) ) { - newItem.append ( *item, charOffset, charLen ); - } - } - - XMP_VarString closeStr; - CodePointToUTF8 ( closeQuote, closeStr ); - newItem.append ( closeStr ); - - *item = newItem; - - } - -} // ApplyQuotes - - -// ------------------------------------------------------------------------------------------------- -// IsInternalProperty -// ------------------ - -// *** Need static checks of the schema prefixes! - -#define IsExternalProperty(s,p) (! IsInternalProperty ( s, p )) - -static bool -IsInternalProperty ( const XMP_VarString & schema, const XMP_VarString & prop ) -{ - bool isInternal = false; - - if ( schema == kXMP_NS_DC ) { - - if ( (prop == "dc:format") || - (prop == "dc:language") ) { - isInternal = true; - } - - } else if ( schema == kXMP_NS_XMP ) { - - if ( (prop == "xmp:BaseURL") || - (prop == "xmp:CreatorTool") || - (prop == "xmp:Format") || - (prop == "xmp:Locale") || - (prop == "xmp:MetadataDate") || - (prop == "xmp:ModifyDate") ) { - isInternal = true; - } - - } else if ( schema == kXMP_NS_PDF ) { - - if ( (prop == "pdf:BaseURL") || - (prop == "pdf:Creator") || - (prop == "pdf:ModDate") || - (prop == "pdf:PDFVersion") || - (prop == "pdf:Producer") ) { - isInternal = true; - } - - } else if ( schema == kXMP_NS_TIFF ) { - - isInternal = true; // ! The TIFF properties are internal by default. - if ( (prop == "tiff:ImageDescription") || // ! ImageDescription, Artist, and Copyright are aliased. - (prop == "tiff:Artist") || - (prop == "tiff:Copyright") ) { - isInternal = false; - } - - } else if ( schema == kXMP_NS_EXIF ) { - - isInternal = true; // ! The EXIF properties are internal by default. - if ( prop == "exif:UserComment" ) isInternal = false; - - } else if ( schema == kXMP_NS_EXIF_Aux ) { - - isInternal = true; // ! The EXIF Aux properties are internal by default. - - } else if ( schema == kXMP_NS_Photoshop ) { - - if ( prop == "photoshop:ICCProfile" ) isInternal = true; - - } else if ( schema == kXMP_NS_CameraRaw ) { - - if ( (prop == "crs:Version") || - (prop == "crs:RawFileName") || - (prop == "crs:ToneCurveName") ) { - isInternal = true; - } - - } else if ( schema == kXMP_NS_AdobeStockPhoto ) { - - isInternal = true; // ! The bmsp schema has only internal properties. - - } else if ( schema == kXMP_NS_XMP_MM ) { - - isInternal = true; // ! The xmpMM schema has only internal properties. - - } else if ( schema == kXMP_NS_XMP_Text ) { - - isInternal = true; // ! The xmpT schema has only internal properties. - - } else if ( schema == kXMP_NS_XMP_PagedFile ) { - - isInternal = true; // ! The xmpTPg schema has only internal properties. - - } else if ( schema == kXMP_NS_XMP_Graphics ) { - - isInternal = true; // ! The xmpG schema has only internal properties. - - } else if ( schema == kXMP_NS_XMP_Image ) { - - isInternal = true; // ! The xmpGImg schema has only internal properties. - - } else if ( schema == kXMP_NS_XMP_Font ) { - - isInternal = true; // ! The stFNT schema has only internal properties. - - } - - return isInternal; - -} // IsInternalProperty - - -// ------------------------------------------------------------------------------------------------- -// RemoveSchemaChildren -// -------------------- - -static void -RemoveSchemaChildren ( XMP_NodePtrPos schemaPos, bool doAll ) -{ - XMP_Node * schemaNode = *schemaPos; - XMP_Assert ( XMP_NodeIsSchema ( schemaNode->options ) ); - - // ! Iterate backwards to reduce shuffling as children are erased and to simplify the logic for - // ! denoting the current child. (Erasing child n makes the old n+1 now be n.) - - size_t propCount = schemaNode->children.size(); - XMP_NodePtrPos beginPos = schemaNode->children.begin(); - - for ( size_t propNum = propCount-1, propLim = (size_t)(-1); propNum != propLim; --propNum ) { - XMP_NodePtrPos currProp = beginPos + propNum; - if ( doAll || IsExternalProperty ( schemaNode->name, (*currProp)->name ) ) { - delete *currProp; // ! Both delete the node and erase the pointer from the parent. - schemaNode->children.erase ( currProp ); - } - } - - if ( schemaNode->children.empty() ) { - XMP_Node * tree = schemaNode->parent; - tree->children.erase ( schemaPos ); - delete schemaNode; - } - -} // RemoveSchemaChildren - - -// ------------------------------------------------------------------------------------------------- -// ItemValuesMatch -// --------------- -// -// Does the value comparisons for array merging as part of XMPUtils::AppendProperties. - -static bool -ItemValuesMatch ( const XMP_Node * leftNode, const XMP_Node * rightNode ) -{ - const XMP_OptionBits leftForm = leftNode->options & kXMP_PropCompositeMask; - const XMP_OptionBits rightForm = leftNode->options & kXMP_PropCompositeMask; - - if ( leftForm != rightForm ) return false; - - if ( leftForm == 0 ) { - - // Simple nodes, check the values and xml:lang qualifiers. - - if ( leftNode->value != rightNode->value ) return false; - if ( (leftNode->options & kXMP_PropHasLang) != (rightNode->options & kXMP_PropHasLang) ) return false; - if ( leftNode->options & kXMP_PropHasLang ) { - if ( leftNode->qualifiers[0]->value != rightNode->qualifiers[0]->value ) return false; - } - - } else if ( leftForm == kXMP_PropValueIsStruct ) { - - // Struct nodes, see if all fields match, ignoring order. - - if ( leftNode->children.size() != rightNode->children.size() ) return false; - - for ( size_t leftNum = 0, leftLim = leftNode->children.size(); leftNum != leftLim; ++leftNum ) { - const XMP_Node * leftField = leftNode->children[leftNum]; - const XMP_Node * rightField = FindConstChild ( rightNode, leftField->name.c_str() ); - if ( (rightField == 0) || (! 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 ); - - for ( size_t leftNum = 0, leftLim = leftNode->children.size(); leftNum != leftLim; ++leftNum ) { - - const XMP_Node * leftItem = leftNode->children[leftNum]; - - size_t rightNum, rightLim; - for ( rightNum = 0, rightLim = rightNode->children.size(); rightNum != rightLim; ++rightNum ) { - const XMP_Node * rightItem = rightNode->children[rightNum]; - if ( ItemValuesMatch ( leftItem, rightItem ) ) break; - } - if ( rightNum == rightLim ) return false; - - } - - } - - return true; // All of the checks passed. - -} // ItemValuesMatch - - -// ------------------------------------------------------------------------------------------------- -// AppendSubtree -// ------------- -// -// The main implementation of XMPUtils::AppendProperties. See the description in TXMPMeta.hpp. - -static void -AppendSubtree ( const XMP_Node * sourceNode, XMP_Node * destParent, const bool replaceOld, const bool deleteEmpty ) -{ - XMP_NodePtrPos destPos; - XMP_Node * destNode = FindChildNode ( destParent, sourceNode->name.c_str(), kXMP_ExistingOnly, &destPos ); - - bool valueIsEmpty = false; - if ( deleteEmpty ) { - if ( XMP_PropIsSimple ( sourceNode->options ) ) { - valueIsEmpty = sourceNode->value.empty(); - } else { - valueIsEmpty = sourceNode->children.empty(); - } - } - - if ( deleteEmpty & valueIsEmpty ) { - - if ( destNode != 0 ) { - delete ( destNode ); - destParent->children.erase ( destPos ); - } - - } else if ( destNode == 0 ) { - - // The one easy case, the destination does not exist. - CloneSubtree ( sourceNode, destParent ); - - } else if ( replaceOld ) { - - // The destination exists and should be replaced. - - destNode->value = sourceNode->value; // *** Should use SetNode. - destNode->options = sourceNode->options; - destNode->RemoveChildren(); - destNode->RemoveQualifiers(); - CloneOffspring ( sourceNode, destNode ); - - #if 0 // *** XMP_DebugBuild - destNode->_valuePtr = destNode->value.c_str(); - #endif - - } else { - - // The destination exists and is not totally replaced. Structs and arrays are merged. - - XMP_OptionBits sourceForm = sourceNode->options & kXMP_PropCompositeMask; - XMP_OptionBits destForm = destNode->options & kXMP_PropCompositeMask; - if ( sourceForm != destForm ) return; - - if ( sourceForm == kXMP_PropValueIsStruct ) { - - // To merge a struct process the fields recursively. E.g. add simple missing fields. The - // recursive call to AppendSubtree will handle deletion for fields with empty values. - - for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) { - const XMP_Node * sourceField = sourceNode->children[sourceNum]; - AppendSubtree ( sourceField, destNode, replaceOld, deleteEmpty ); - if ( deleteEmpty && destNode->children.empty() ) { - delete ( destNode ); - destParent->children.erase ( destPos ); - } - } - - } else if ( sourceForm & kXMP_PropArrayIsAltText ) { - - // Merge AltText arrays by the xml:lang qualifiers. Make sure x-default is first. Make a - // special check for deletion of empty values. Meaningful in AltText arrays because the - // xml:lang qualifier provides unambiguous source/dest correspondence. - - for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) { - - const XMP_Node * sourceItem = sourceNode->children[sourceNum]; - if ( sourceItem->qualifiers.empty() || (sourceItem->qualifiers[0]->name != "xml:lang") ) continue; - - XMP_Index destIndex = LookupLangItem ( destNode, sourceItem->qualifiers[0]->value ); - - if ( deleteEmpty && sourceItem->value.empty() ) { - - if ( destIndex != -1 ) { - delete ( destNode->children[destIndex] ); - destNode->children.erase ( destNode->children.begin() + destIndex ); - if ( destNode->children.empty() ) { - delete ( destNode ); - destParent->children.erase ( destPos ); - } - } - - } else { - - if ( destIndex != -1 ) continue; // Not replacing, keep the existing item. - - if ( (sourceItem->qualifiers[0]->value != "x-default") || destNode->children.empty() ) { - CloneSubtree ( sourceItem, destNode ); - } else { - XMP_Node * destItem = new XMP_Node ( destNode, sourceItem->name, sourceItem->value, sourceItem->options ); - CloneOffspring ( sourceItem, destItem ); - destNode->children.insert ( destNode->children.begin(), destItem ); - } - - } - - } - - } else if ( sourceForm & kXMP_PropValueIsArray ) { - - // Merge other arrays by item values. Don't worry about order or duplicates. Source - // items with empty values do not cause deletion, that conflicts horribly with merging. - - for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) { - const XMP_Node * sourceItem = sourceNode->children[sourceNum]; - - size_t destNum, destLim; - for ( destNum = 0, destLim = destNode->children.size(); destNum != destLim; ++destNum ) { - const XMP_Node * destItem = destNode->children[destNum]; - if ( ItemValuesMatch ( sourceItem, destItem ) ) break; - } - if ( destNum == destLim ) CloneSubtree ( sourceItem, destNode ); - - } - - } - - } - -} // AppendSubtree - - -// ================================================================================================= -// Class Static Functions -// ====================== - -// ------------------------------------------------------------------------------------------------- -// CatenateArrayItems -// ------------------ - -/* class static */ void -XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr separator, - XMP_StringPtr quotes, - XMP_OptionBits options, - XMP_StringPtr * catedStr, - XMP_StringLen * catedLen ) -{ - XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // ! Enforced by wrapper. - XMP_Assert ( (separator != 0) && (quotes != 0) && (catedStr != 0) && (catedLen != 0) ); // ! Enforced by wrapper. - - size_t strLen=0, strPos=0, charLen=0; - UniCharKind charKind; - UniCodePoint currUCP, openQuote, closeQuote; - - const bool allowCommas = ((options & kXMPUtil_AllowCommas) != 0); - - const XMP_Node * arrayNode = 0; // ! Move up to avoid gcc complaints. - XMP_OptionBits arrayForm = 0; - const XMP_Node * currItem = 0; - - // 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. - - sCatenatedItems->erase(); - - XMP_ExpandedXPath arrayPath; - ExpandXPath ( schemaNS, arrayName, &arrayPath ); - - arrayNode = FindConstNode ( &xmpObj.tree, arrayPath ); - if ( arrayNode == 0 ) goto EXIT; // ! Need to set the output pointer and length. - - arrayForm = arrayNode->options & kXMP_PropCompositeMask; - if ( (! (arrayForm & kXMP_PropValueIsArray)) || (arrayForm & kXMP_PropArrayIsAlternate) ) { - XMP_Throw ( "Named property must be non-alternate array", kXMPErr_BadParam ); - } - if ( arrayNode->children.empty() ) goto EXIT; // ! Need to set the output pointer and length. - - // 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 preceding separator. - - currItem = arrayNode->children[0]; - - if ( (currItem->options & kXMP_PropCompositeMask) != 0 ) XMP_Throw ( "Array items must be simple", kXMPErr_BadParam ); - *sCatenatedItems = currItem->value; - ApplyQuotes ( sCatenatedItems, openQuote, closeQuote, allowCommas ); - - for ( size_t itemNum = 1, itemLim = arrayNode->children.size(); itemNum != itemLim; ++itemNum ) { - const XMP_Node * currItem = arrayNode->children[itemNum]; - if ( (currItem->options & kXMP_PropCompositeMask) != 0 ) XMP_Throw ( "Array items must be simple", kXMPErr_BadParam ); - XMP_VarString tempStr ( currItem->value ); - ApplyQuotes ( &tempStr, openQuote, closeQuote, allowCommas ); - *sCatenatedItems += separator; - *sCatenatedItems += tempStr; - } - -EXIT: - *catedStr = sCatenatedItems->c_str(); - *catedLen = sCatenatedItems->size(); - -} // CatenateArrayItems - - -// ------------------------------------------------------------------------------------------------- -// SeparateArrayItems -// ------------------ - -/* class static */ void -XMPUtils::SeparateArrayItems ( XMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr ) -{ - XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (catedStr != 0) ); // ! Enforced by wrapper. - - XMP_VarString itemValue; - size_t itemStart, itemEnd; - size_t nextSize, charSize = 0; // Avoid VS uninit var warnings. - UniCharKind nextKind, charKind = UCK_normal; - UniCodePoint nextChar, uniChar = 0; - - // Extract "special" option bits, verify and normalize the others. - - bool preserveCommas = false; - if ( options & kXMPUtil_AllowCommas ) { - preserveCommas = true; - options ^= kXMPUtil_AllowCommas; - } - - options = VerifySetOptions ( options, 0 ); // Keep a zero value, has special meaning below. - 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 ); - 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. - XMP_OptionBits arrayForm = arrayNode->options & 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. - arrayNode = FindNode ( &xmpObj->tree, arrayPath, kXMP_CreateNodes, (options | kXMP_PropValueIsArray) ); - if ( arrayNode == 0 ) XMP_Throw ( "Failed to create named array", kXMPErr_BadXPath ); - } - - XMP_NodeOffspring oldChildren ( arrayNode->children ); - size_t oldChildCount = oldChildren.size(); - arrayNode->children.clear(); - - // Extract the item values one at a time, until the whole input string is done. Be very careful - // in the extraction about the string positions. They are essentially byte pointers, while the - // contents are UTF-8. Adding or subtracting 1 does not necessarily move 1 Unicode character! - - size_t endPos = strlen ( catedStr ); - - itemEnd = 0; - while ( itemEnd < endPos ) { - - // Skip any leading spaces and separation characters. Always skip commas here. They can be - // kept when within a value, but not when alone between values. - - 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 ) { - - // This is not a quoted value. Scan for the end, create an array item from the substring. - - 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; - for ( oldChild = 0; oldChild < oldChildCount; ++oldChild ) { - if ( (oldChildren[oldChild] != 0) && (itemValue == oldChildren[oldChild]->value) ) break; - } - - XMP_Node * newItem = 0; - if ( oldChild == oldChildCount ) { - newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, itemValue.c_str(), 0 ); - } else { - newItem = oldChildren[oldChild]; - oldChildren[oldChild] = 0; // ! Don't match again, let duplicates be seen. - } - arrayNode->children.push_back ( newItem ); - - } // Loop through all of the returned items. - - // Delete any of the old children that were not kept. - for ( size_t i = 0; i < oldChildCount; ++i ) { - if ( oldChildren[i] != 0 ) delete oldChildren[i]; - } - -} // SeparateArrayItems - - -// ------------------------------------------------------------------------------------------------- -// RemoveProperties -// ---------------- - -/* class static */ void -XMPUtils::RemoveProperties ( XMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ) -{ - 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_NodePtrPos 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). - delete propNode; // ! Both delete the node and erase the pointer from the parent. - parent->children.erase ( propPos ); - DeleteEmptySchema ( parent ); - } - } - - } else if ( *schemaNS != 0 ) { - - // Remove all properties from the named schema. Optionally include aliases, in which case - // there might not be an actual schema node. - - XMP_NodePtrPos schemaPos; - XMP_Node * schemaNode = FindSchemaNode ( &xmpObj->tree, schemaNS, kXMP_ExistingOnly, &schemaPos ); - if ( schemaNode != 0 ) RemoveSchemaChildren ( schemaPos, doAll ); - - if ( includeAliases ) { - - // We're removing the aliases also. Look them up by their namespace prefix. Yes, the - // alias map is sorted so we could process just that portion. But that takes more code - // and the extra speed isn't worth it. (Plus this way we avoid a dependence on the map - // implementation.) Lookup the XMP node from the alias, to make sure the actual exists. - - 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 ) { - XMP_NodePtrPos 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; - if ( doAll || IsExternalProperty ( rootProp->parent->name, rootProp->name ) ) { - XMP_Node * parent = actualProp->parent; - delete actualProp; // ! Both delete the node and erase the pointer from the parent. - parent->children.erase ( actualPos ); - DeleteEmptySchema ( parent ); - } - } - } - } - - } - - } else { - - // Remove all appropriate properties from all schema. In this case we don't have to be - // concerned with aliases, they are handled implicitly from the actual properties. - - // ! Iterate backwards to reduce shuffling if schema are erased and to simplify the logic - // ! for denoting the current schema. (Erasing schema n makes the old n+1 now be n.) - - size_t schemaCount = xmpObj->tree.children.size(); - XMP_NodePtrPos beginPos = xmpObj->tree.children.begin(); - - for ( size_t schemaNum = schemaCount-1, schemaLim = (size_t)(-1); schemaNum != schemaLim; --schemaNum ) { - XMP_NodePtrPos currSchema = beginPos + schemaNum; - RemoveSchemaChildren ( currSchema, doAll ); - } - - } - -} // RemoveProperties - - -// ------------------------------------------------------------------------------------------------- -// AppendProperties -// ---------------- - -/* class static */ void -XMPUtils::AppendProperties ( const XMPMeta & source, - XMPMeta * dest, - XMP_OptionBits options ) -{ - XMP_Assert ( dest != 0 ); // ! Enforced by wrapper. - - const bool doAll = ((options & kXMPUtil_DoAllProperties) != 0); - const bool replaceOld = ((options & kXMPUtil_ReplaceOldValues) != 0); - const bool deleteEmpty = ((options & kXMPUtil_DeleteEmptyValues) != 0); - - for ( size_t schemaNum = 0, schemaLim = source.tree.children.size(); schemaNum != schemaLim; ++schemaNum ) { - - const XMP_Node * sourceSchema = source.tree.children[schemaNum]; - - // Make sure we have a destination schema node. Remember if it is newly created. - - XMP_Node * destSchema = FindSchemaNode ( &dest->tree, sourceSchema->name.c_str(), kXMP_ExistingOnly ); - const bool newDestSchema = (destSchema == 0); - if ( newDestSchema ) { - destSchema = new XMP_Node ( &dest->tree, sourceSchema->name, sourceSchema->value, kXMP_SchemaNode ); - dest->tree.children.push_back ( destSchema ); - } - - // Process the source schema's children. Do this backwards in case deleteEmpty is set. - - for ( long propNum = ((long)sourceSchema->children.size() - 1); propNum >= 0; --propNum ) { - const XMP_Node * sourceProp = sourceSchema->children[propNum]; - if ( doAll || IsExternalProperty ( sourceSchema->name, sourceProp->name ) ) { - AppendSubtree ( sourceProp, destSchema, replaceOld, deleteEmpty ); -// *** RemoveMultiValueInfo ( dest, sourceSchema->name.c_str(), sourceProp->name.c_str() ); - } - } - - if ( destSchema->children.empty() ) { - if ( newDestSchema ) { - delete ( destSchema ); - dest->tree.children.pop_back(); - } else if ( deleteEmpty ) { - DeleteEmptySchema ( destSchema ); - } - } - - } - -} // AppendProperties - - -// ------------------------------------------------------------------------------------------------- -// DuplicateSubtree -// ---------------- - -/* class static */ void -XMPUtils::DuplicateSubtree ( const XMPMeta & source, - XMPMeta * dest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS, - XMP_StringPtr destRoot, - XMP_OptionBits options ) -{ - UNUSED(options); - - bool fullSourceTree = false; - bool fullDestTree = false; - - XMP_ExpandedXPath sourcePath, destPath; - - const XMP_Node * sourceNode = 0; - XMP_Node * destNode = 0; - - 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 ); - destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly ); - - if ( (destNode == 0) || (! XMP_PropIsStruct ( destNode->options )) ) { - XMP_Throw ( "Destination must be an existing struct", kXMPErr_BadXPath ); - } - - if ( ! destNode->children.empty() ) { - if ( options & kXMP_DeleteExisting ) { - destNode->RemoveChildren(); - } else { - XMP_Throw ( "Destination must be an empty struct", kXMPErr_BadXPath ); - } - } - - for ( size_t schemaNum = 0, schemaLim = source.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) { - - const XMP_Node * currSchema = source.tree.children[schemaNum]; - - for ( size_t propNum = 0, propLim = currSchema->children.size(); propNum < propLim; ++propNum ) { - sourceNode = currSchema->children[propNum]; - XMP_Node * copyNode = new XMP_Node ( destNode, sourceNode->name, sourceNode->value, sourceNode->options ); - destNode->children.push_back ( copyNode ); - CloneOffspring ( sourceNode, copyNode ); - } - - } - - } else if ( fullDestTree ) { - - // The source node must be an existing struct, copy all of the fields to the dest top level. - - XMP_ExpandedXPath sourcePath; - ExpandXPath ( sourceNS, sourceRoot, &sourcePath ); - sourceNode = FindConstNode ( &source.tree, sourcePath ); - - if ( (sourceNode == 0) || (! XMP_PropIsStruct ( sourceNode->options )) ) { - XMP_Throw ( "Source must be an existing struct", kXMPErr_BadXPath ); - } - - destNode = &dest->tree; - - if ( ! destNode->children.empty() ) { - if ( options & kXMP_DeleteExisting ) { - destNode->RemoveChildren(); - } else { - XMP_Throw ( "Destination tree must be empty", kXMPErr_BadXPath ); - } - } - - std::string nsPrefix; - XMP_StringPtr nsURI; - XMP_StringLen nsLen; - - for ( size_t fieldNum = 0, fieldLim = sourceNode->children.size(); fieldNum < fieldLim; ++fieldNum ) { - - const XMP_Node * currField = sourceNode->children[fieldNum]; - - size_t colonPos = currField->name.find ( ':' ); - nsPrefix.assign ( currField->name.c_str(), colonPos ); - bool nsOK = XMPMeta::GetNamespaceURI ( nsPrefix.c_str(), &nsURI, &nsLen ); - if ( ! nsOK ) XMP_Throw ( "Source field namespace is not global", kXMPErr_BadSchema ); - - XMP_Node * destSchema = FindSchemaNode ( &dest->tree, nsURI, kXMP_CreateNodes ); - if ( destSchema == 0 ) XMP_Throw ( "Failed to find destination schema", kXMPErr_BadSchema ); - - XMP_Node * copyNode = new XMP_Node ( destSchema, currField->name, currField->value, currField->options ); - destSchema->children.push_back ( copyNode ); - CloneOffspring ( currField, copyNode ); - - } - - } else { - - // Find the root nodes for the source and destination subtrees. - - ExpandXPath ( sourceNS, sourceRoot, &sourcePath ); - ExpandXPath ( destNS, destRoot, &destPath ); - - 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. - if ( destNode != 0 ) XMP_Throw ( "Destination subtree must not exist", kXMPErr_BadXPath ); - - 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 - // because the source already existed and the destination was just created. - - if ( &source == dest ) { - for ( XMP_Node * testNode = destNode; testNode != 0; testNode = testNode->parent ) { - if ( testNode == sourceNode ) { - // *** delete the just-created dest root node - XMP_Throw ( "Destination subtree is within the source subtree", kXMPErr_BadXPath ); - } - } - } - - // *** Could use a CloneTree util here and maybe elsewhere. - - destNode->value = sourceNode->value; // *** Should use SetNode. - destNode->options = sourceNode->options; - CloneOffspring ( sourceNode, destNode ); - - } - -} // DuplicateSubtree - - -// ================================================================================================= diff --git a/xmpsdk/src/XMPUtils.cpp b/xmpsdk/src/XMPUtils.cpp deleted file mode 100644 index 89afd3d62d..0000000000 --- a/xmpsdk/src/XMPUtils.cpp +++ /dev/null @@ -1,2157 +0,0 @@ -// ================================================================================================= -// Copyright 2002-2007 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 "XMP_Environment.h" // ! This must be the first include! -#include "XMPCore_Impl.hpp" - -#include "XMPUtils.hpp" - -#include "MD5.h" - -#include -#include - -#include -#include -#include -#include -#include - -#include // For snprintf. - -#if XMP_WinBuild -#ifdef _MSC_VER - #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning) - #pragma warning ( disable : 4996 ) // '...' was declared deprecated -#endif -#endif - -// ================================================================================================= -// Local Types and Constants -// ========================= - -static const char * sBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -// ================================================================================================= -// Static Variables -// ================ - -XMP_VarString * sComposedPath = 0; // *** Only really need 1 string. Shrink periodically? -XMP_VarString * sConvertedValue = 0; -XMP_VarString * sBase64Str = 0; -XMP_VarString * sCatenatedItems = 0; -XMP_VarString * sStandardXMP = 0; -XMP_VarString * sExtendedXMP = 0; -XMP_VarString * sExtendedDigest = 0; - -// ================================================================================================= -// Local Utilities -// =============== - - -// ------------------------------------------------------------------------------------------------- -// ANSI Time Functions -// ------------------- -// -// A bit of hackery to use the best available time functions. Mac and UNIX have thread safe versions -// of gmtime and localtime. On Mac the CodeWarrior functions are buggy, use Apple's. - -#if XMP_UNIXBuild - - typedef time_t ansi_tt; - typedef struct tm ansi_tm; - - #define ansi_time time - #define ansi_mktime mktime - #define ansi_difftime difftime - - #define ansi_gmtime gmtime_r - #define ansi_localtime localtime_r - -#elif XMP_WinBuild - - // ! VS.Net 2003 (VC7) does not provide thread safe versions of gmtime and localtime. - // ! VS.Net 2005 (VC8) inverts the parameters for the safe versions of gmtime and localtime. - - typedef time_t ansi_tt; - typedef struct tm ansi_tm; - - #define ansi_time time - #define ansi_mktime mktime - #define ansi_difftime difftime - - #if defined(_MSC_VER) && (_MSC_VER >= 1400) - #define ansi_gmtime(tt,tm) gmtime_s ( tm, tt ) - #define ansi_localtime(tt,tm) localtime_s ( tm, tt ) - #else - static inline void ansi_gmtime ( const ansi_tt * ttTime, ansi_tm * tmTime ) - { - ansi_tm * tmx = gmtime ( ttTime ); // ! Hope that there is no race! - if ( tmx == 0 ) XMP_Throw ( "Failure from ANSI C gmtime function", kXMPErr_ExternalFailure ); - *tmTime = *tmx; - } - static inline void ansi_localtime ( const ansi_tt * ttTime, ansi_tm * tmTime ) - { - ansi_tm * tmx = localtime ( ttTime ); // ! Hope that there is no race! - if ( tmx == 0 ) XMP_Throw ( "Failure from ANSI C localtime function", kXMPErr_ExternalFailure ); - *tmTime = *tmx; - } - #endif - -#elif XMP_MacBuild - - #if ! __MWERKS__ - - typedef time_t ansi_tt; - typedef struct tm ansi_tm; - - #define ansi_time time - #define ansi_mktime mktime - #define ansi_difftime difftime - - #define ansi_gmtime gmtime_r - #define ansi_localtime localtime_r - - #else - - // ! The CW versions are buggy. Use Apple's code, time_t, and "struct tm". - - #include - - typedef _BSD_TIME_T_ ansi_tt; - - typedef struct apple_tm { - int tm_sec; /* seconds after the minute [0-60] */ - int tm_min; /* minutes after the hour [0-59] */ - int tm_hour; /* hours since midnight [0-23] */ - int tm_mday; /* day of the month [1-31] */ - int tm_mon; /* months since January [0-11] */ - int tm_year; /* years since 1900 */ - int tm_wday; /* days since Sunday [0-6] */ - int tm_yday; /* days since January 1 [0-365] */ - int tm_isdst; /* Daylight Savings Time flag */ - long tm_gmtoff; /* offset from CUT in seconds */ - char *tm_zone; /* timezone abbreviation */ - } ansi_tm; - - - typedef ansi_tt (* GetTimeProc) ( ansi_tt * ttTime ); - typedef ansi_tt (* MakeTimeProc) ( ansi_tm * tmTime ); - typedef double (* DiffTimeProc) ( ansi_tt t1, ansi_tt t0 ); - - typedef void (* ConvertTimeProc) ( const ansi_tt * ttTime, ansi_tm * tmTime ); - - static GetTimeProc ansi_time = 0; - static MakeTimeProc ansi_mktime = 0; - static DiffTimeProc ansi_difftime = 0; - - static ConvertTimeProc ansi_gmtime = 0; - static ConvertTimeProc ansi_localtime = 0; - - static void LookupTimeProcs() - { - _dyld_lookup_and_bind_with_hint ( "_time", "libSystem", (XMP_Uns32*)&ansi_time, 0 ); - _dyld_lookup_and_bind_with_hint ( "_mktime", "libSystem", (XMP_Uns32*)&ansi_mktime, 0 ); - _dyld_lookup_and_bind_with_hint ( "_difftime", "libSystem", (XMP_Uns32*)&ansi_difftime, 0 ); - _dyld_lookup_and_bind_with_hint ( "_gmtime_r", "libSystem", (XMP_Uns32*)&ansi_gmtime, 0 ); - _dyld_lookup_and_bind_with_hint ( "_localtime_r", "libSystem", (XMP_Uns32*)&ansi_localtime, 0 ); - } - - #endif - -#endif - - -// ------------------------------------------------------------------------------------------------- -// IsLeapYear -// ---------- - -static bool -IsLeapYear ( long year ) -{ - // This code uses the Gregorian calendar algorithm: - // https://en.wikipedia.org/wiki/Leap_year#Algorithm - - if ( (year % 4) != 0 ) return false; // Not a multiple of 4. - if ( (year % 100) != 0 ) return true; // A multiple of 4 but not a multiple of 100. - if ( (year % 400) == 0 ) return true; // A multiple of 400. - - return false; // A multiple of 100 but not a multiple of 400. - -} // IsLeapYear - - -// ------------------------------------------------------------------------------------------------- -// DaysInMonth -// ----------- - -static int -DaysInMonth ( XMP_Int32 year, XMP_Int32 month ) -{ - - static short daysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec - - int days = daysInMonth [ month ]; - if ( (month == 2) && IsLeapYear ( year ) ) days += 1; - - return days; - -} // DaysInMonth - - -// ------------------------------------------------------------------------------------------------- -// AdjustTimeOverflow -// ------------------ - -static void -AdjustTimeOverflow ( XMP_DateTime * time ) -{ - enum { kBillion = 1000*1000*1000L }; - - // ---------------------------------------------------------------------------------------------- - // To be safe against pathalogical overflow we first adjust from month to second, then from - // nanosecond back up to month. This leaves each value closer to zero before propagating into it. - // For example if the hour and minute are both near max, adjusting minutes first can cause the - // hour to overflow. - - // ! Photoshop 8 creates "time only" values with zeros for year, month, and day. - - if ( (time->year != 0) || (time->month != 0) || (time->day != 0) ) { - - while ( time->month < 1 ) { - time->year -= 1; - time->month += 12; - } - - while ( time->month > 12 ) { - time->year += 1; - time->month -= 12; - } - - while ( time->day < 1 ) { - time->month -= 1; - if ( time->month < 1 ) { // ! Keep the months in range for indexing daysInMonth! - time->year -= 1; - time->month += 12; - } - time->day += DaysInMonth ( time->year, time->month ); // ! Decrement month before so index here is right! - } - - while ( time->day > DaysInMonth ( time->year, time->month ) ) { - time->day -= DaysInMonth ( time->year, time->month ); // ! Increment month after so index here is right! - time->month += 1; - if ( time->month > 12 ) { - time->year += 1; - time->month -= 12; - } - } - - } - - while ( time->hour < 0 ) { - time->day -= 1; - time->hour += 24; - } - - while ( time->hour >= 24 ) { - time->day += 1; - time->hour -= 24; - } - - while ( time->minute < 0 ) { - time->hour -= 1; - time->minute += 60; - } - - while ( time->minute >= 60 ) { - time->hour += 1; - time->minute -= 60; - } - - while ( time->second < 0 ) { - time->minute -= 1; - time->second += 60; - } - - while ( time->second >= 60 ) { - time->minute += 1; - time->second -= 60; - } - - while ( time->nanoSecond < 0 ) { - time->second -= 1; - time->nanoSecond += kBillion; - } - - while ( time->nanoSecond >= kBillion ) { - time->second += 1; - time->nanoSecond -= kBillion; - } - - while ( time->second < 0 ) { - time->minute -= 1; - time->second += 60; - } - - while ( time->second >= 60 ) { - time->minute += 1; - time->second -= 60; - } - - while ( time->minute < 0 ) { - time->hour -= 1; - time->minute += 60; - } - - while ( time->minute >= 60 ) { - time->hour += 1; - time->minute -= 60; - } - - while ( time->hour < 0 ) { - time->day -= 1; - time->hour += 24; - } - - while ( time->hour >= 24 ) { - time->day += 1; - time->hour -= 24; - } - - if ( (time->year != 0) || (time->month != 0) || (time->day != 0) ) { - - while ( time->month < 1 ) { // Make sure the months are OK first, for DaysInMonth. - time->year -= 1; - time->month += 12; - } - - while ( time->month > 12 ) { - time->year += 1; - time->month -= 12; - } - - while ( time->day < 1 ) { - time->month -= 1; - if ( time->month < 1 ) { - time->year -= 1; - time->month += 12; - } - time->day += DaysInMonth ( time->year, time->month ); - } - - while ( time->day > DaysInMonth ( time->year, time->month ) ) { - time->day -= DaysInMonth ( time->year, time->month ); - time->month += 1; - if ( time->month > 12 ) { - time->year += 1; - time->month -= 12; - } - } - - } - -} // AdjustTimeOverflow - - -// ------------------------------------------------------------------------------------------------- -// GatherInt -// --------- - -static XMP_Int32 -GatherInt ( XMP_StringPtr strValue, size_t * _pos, const char * errMsg ) -{ - size_t pos = *_pos; - XMP_Int32 value = 0; - - // Limits for overflow checking. Assuming that the maximum value of XMP_Int32 - // is 2147483647, then tens_upperbound == 214748364 and ones_upperbound == 7. - // Most of the time, we can just check that value < tens_upperbound to confirm - // that the calculation won't overflow, which makes the bounds checking more - // efficient for the common case. - const XMP_Int32 tens_upperbound = std::numeric_limits::max() / 10; - const XMP_Int32 ones_upperbound = std::numeric_limits::max() % 10; - - for ( char ch = strValue[pos]; ('0' <= ch) && (ch <= '9'); ++pos, ch = strValue[pos] ) { - const XMP_Int32 digit = ch - '0'; - if (value >= tens_upperbound) { - if (value > tens_upperbound || digit > ones_upperbound) { - XMP_Throw ( errMsg, kXMPErr_BadParam ); - } - } - value = (value * 10) + digit; - } - - if ( pos == *_pos ) XMP_Throw ( errMsg, kXMPErr_BadParam ); - *_pos = pos; - return value; - -} // GatherInt - - -// ------------------------------------------------------------------------------------------------- - -static void FormatFullDateTime ( XMP_DateTime & tempDate, char * buffer, size_t bufferLen ) -{ - - AdjustTimeOverflow ( &tempDate ); // Make sure all time parts are in range. - - if ( (tempDate.second == 0) && (tempDate.nanoSecond == 0) ) { - - // Output YYYY-MM-DDThh:mmTZD. - snprintf ( buffer, bufferLen, "%.4d-%02d-%02dT%02d:%02d", // AUDIT: Callers pass sizeof(buffer). - static_cast(tempDate.year), static_cast(tempDate.month), static_cast(tempDate.day), static_cast(tempDate.hour), static_cast(tempDate.minute) ); - - } else if ( tempDate.nanoSecond == 0 ) { - - // Output YYYY-MM-DDThh:mm:ssTZD. - snprintf ( buffer, bufferLen, "%.4d-%02d-%02dT%02d:%02d:%02d", // AUDIT: Callers pass sizeof(buffer). - static_cast(tempDate.year), static_cast(tempDate.month), static_cast(tempDate.day), - static_cast(tempDate.hour), static_cast(tempDate.minute), static_cast(tempDate.second) ); - - } else { - - // Output YYYY-MM-DDThh:mm:ss.sTZD. - snprintf ( buffer, bufferLen, "%.4d-%02d-%02dT%02d:%02d:%02d.%09d", // AUDIT: Callers pass sizeof(buffer). - static_cast(tempDate.year), static_cast(tempDate.month), static_cast(tempDate.day), - static_cast(tempDate.hour), static_cast(tempDate.minute), static_cast(tempDate.second), static_cast(tempDate.nanoSecond) ); - for ( size_t i = strlen(buffer)-1; buffer[i] == '0'; --i ) buffer[i] = 0; // Trim excess digits. - - } - -} // FormatFullDateTime - - -// ------------------------------------------------------------------------------------------------- -// DecodeBase64Char -// ---------------- - -// The decode mapping: -// -// encoded encoded raw -// char value value -// ------- ------- ----- -// A .. Z 0x41 .. 0x5A 0 .. 25 -// a .. z 0x61 .. 0x7A 26 .. 51 -// 0 .. 9 0x30 .. 0x39 52 .. 61 -// + 0x2B 62 -// / 0x2F 63 - -static unsigned char -DecodeBase64Char ( XMP_Uns8 ch ) -{ - - if ( ('A' <= ch) && (ch <= 'Z') ) { - ch = ch - 'A'; - } else if ( ('a' <= ch) && (ch <= 'z') ) { - ch = ch - 'a' + 26; - } else if ( ('0' <= ch) && (ch <= '9') ) { - ch = ch - '0' + 52; - } else if ( ch == '+' ) { - ch = 62; - } else if ( ch == '/' ) { - ch = 63; - } else if ( (ch == ' ') || (ch == kTab) || (ch == kLF) || (ch == kCR) ) { - ch = 0xFF; // Will be ignored by the caller. - } else { - XMP_Throw ( "Invalid base-64 encoded character", kXMPErr_BadParam ); - } - - return ch; - -} // DecodeBase64Char (); - - -// ------------------------------------------------------------------------------------------------- -// EstimateSizeForJPEG -// ------------------- -// -// Estimate the serialized size for the subtree of an XMP_Node. Support for PackageForJPEG. - -static size_t -EstimateSizeForJPEG ( const XMP_Node * xmpNode ) -{ - - size_t estSize = 0; - size_t nameSize = xmpNode->name.size(); - bool includeName = (! XMP_PropIsArray ( xmpNode->parent->options )); - - if ( XMP_PropIsSimple ( xmpNode->options ) ) { - - if ( includeName ) estSize += (nameSize + 3); // Assume attribute form. - estSize += xmpNode->value.size(); - - } else if ( XMP_PropIsArray ( xmpNode->options ) ) { - - // The form of the value portion is: ...... - if ( includeName ) estSize += (2*nameSize + 5); - size_t arraySize = xmpNode->children.size(); - estSize += 9 + 10; // The rdf:Xyz tags. - estSize += arraySize * (8 + 9); // The rdf:li tags. - for ( size_t i = 0; i < arraySize; ++i ) { - estSize += EstimateSizeForJPEG ( xmpNode->children[i] ); - } - - } else { - - // The form is: ...fields... - if ( includeName ) estSize += (2*nameSize + 5); - estSize += 25; // The rdf:parseType="Resource" attribute. - size_t fieldCount = xmpNode->children.size(); - for ( size_t i = 0; i < fieldCount; ++i ) { - estSize += EstimateSizeForJPEG ( xmpNode->children[i] ); - } - - } - - return estSize; - -} // EstimateSizeForJPEG - - -// ------------------------------------------------------------------------------------------------- -// MoveOneProperty -// --------------- - -static bool MoveOneProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, - XMP_StringPtr schemaURI, XMP_StringPtr propName ) -{ - - XMP_Node * propNode = 0; - XMP_NodePtrPos stdPropPos; - - XMP_Node * stdSchema = FindSchemaNode ( &stdXMP.tree, schemaURI, kXMP_ExistingOnly, 0 ); - if ( stdSchema != 0 ) { - propNode = FindChildNode ( stdSchema, propName, kXMP_ExistingOnly, &stdPropPos ); - } - if ( propNode == 0 ) return false; - - XMP_Node * extSchema = FindSchemaNode ( &extXMP->tree, schemaURI, kXMP_CreateNodes ); - - propNode->parent = extSchema; - - extSchema->options &= ~kXMP_NewImplicitNode; - extSchema->children.push_back ( propNode ); - - stdSchema->children.erase ( stdPropPos ); - DeleteEmptySchema ( stdSchema ); - - return true; - -} // MoveOneProperty - - -// ------------------------------------------------------------------------------------------------- -// CreateEstimatedSizeMap -// ---------------------- - -#ifndef Trace_PackageForJPEG - #define Trace_PackageForJPEG 0 -#endif - -typedef std::pair < XMP_VarString*, XMP_VarString* > StringPtrPair; -typedef std::multimap < size_t, StringPtrPair > PropSizeMap; - -static void CreateEstimatedSizeMap ( XMPMeta & stdXMP, PropSizeMap * propSizes ) -{ - #if Trace_PackageForJPEG - printf ( " Creating top level property map:\n" ); - #endif - - for ( size_t s = stdXMP.tree.children.size(); s > 0; --s ) { - - XMP_Node * stdSchema = stdXMP.tree.children[s-1]; - - for ( size_t p = stdSchema->children.size(); p > 0; --p ) { - - XMP_Node * stdProp = stdSchema->children[p-1]; - if ( (stdSchema->name == kXMP_NS_XMP_Note) && - (stdProp->name == "xmpNote:HasExtendedXMP") ) continue; // ! Don't move xmpNote:HasExtendedXMP. - - size_t propSize = EstimateSizeForJPEG ( stdProp ); - StringPtrPair namePair ( &stdSchema->name, &stdProp->name ); - PropSizeMap::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 - - -// ------------------------------------------------------------------------------------------------- -// MoveLargestProperty -// ------------------- - -static size_t MoveLargestProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, PropSizeMap & propSizes ) -{ - XMP_Assert ( ! propSizes.empty() ); - - #if 0 - // *** Xcode 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 - PropSizeMap::iterator lastPos = propSizes.begin(); - PropSizeMap::iterator nextPos = lastPos; - for ( ++nextPos; nextPos != propSizes.end(); ++nextPos ) lastPos = nextPos; - #endif - - size_t propSize = lastPos->first; - const char * schemaURI = lastPos->second.first->c_str(); - const char * propName = lastPos->second.second->c_str(); - - #if Trace_PackageForJPEG - printf ( " Move %s, %d bytes\n", propName, propSize ); - #endif - - bool moved = MoveOneProperty ( stdXMP, extXMP, schemaURI, propName ); - XMP_Assert ( moved ); - UNUSED(moved); - - propSizes.erase ( lastPos ); - return propSize; - -} // MoveLargestProperty - - -// ================================================================================================= -// Class Static Functions -// ====================== - - -// ------------------------------------------------------------------------------------------------- -// Initialize -// ---------- - -/* class static */ bool -XMPUtils::Initialize() -{ - sComposedPath = new XMP_VarString(); - sConvertedValue = new XMP_VarString(); - sBase64Str = new XMP_VarString(); - sCatenatedItems = new XMP_VarString(); - sStandardXMP = new XMP_VarString(); - sExtendedXMP = new XMP_VarString(); - sExtendedDigest = new XMP_VarString(); - - #if XMP_MacBuild && __MWERKS__ - LookupTimeProcs(); - #endif - - return true; - -} // Initialize - - -// ------------------------------------------------------------------------------------------------- -// Terminate -// --------- - -#define EliminateGlobal(g) delete ( g ); g = 0 - -/* class static */ void -XMPUtils::Terminate() RELEASE_NO_THROW -{ - EliminateGlobal ( sComposedPath ); - EliminateGlobal ( sConvertedValue ); - EliminateGlobal ( sBase64Str ); - EliminateGlobal ( sCatenatedItems ); - EliminateGlobal ( sStandardXMP ); - EliminateGlobal ( sExtendedXMP ); - EliminateGlobal ( sExtendedDigest ); - - return; - -} // Terminate - - -// ------------------------------------------------------------------------------------------------- -// Unlock -// ------ - -/* class static */ void -XMPUtils::Unlock ( XMP_OptionBits options ) -{ - UNUSED(options); - - XMPMeta::Unlock ( 0 ); - -} // Unlock - -// ------------------------------------------------------------------------------------------------- -// ComposeArrayItemPath -// -------------------- -// -// Return "arrayName[index]". - -/* class static */ void -XMPUtils::ComposeArrayItemPath ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ) -{ - XMP_Assert ( schemaNS != 0 ); // Enforced by wrapper. - XMP_Assert ( *arrayName != 0 ); // Enforced by wrapper. - XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path. - ExpandXPath ( schemaNS, arrayName, &expPath ); - - 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. - - sComposedPath->erase(); - sComposedPath->reserve ( reserveLen ); - sComposedPath->append ( reserveLen, ' ' ); - - if ( itemIndex != kXMP_ArrayLastItem ) { - // AUDIT: Using string->size() for the snprintf length is safe. - snprintf ( const_cast(sComposedPath->c_str()), sComposedPath->size(), "%s[%d]", arrayName, static_cast(itemIndex) ); - } else { - *sComposedPath = arrayName; - *sComposedPath += "[last()] "; - (*sComposedPath)[sComposedPath->size()-1] = 0; // ! Final null is for the strlen at exit. - } - - *fullPath = sComposedPath->c_str(); - *pathSize = strlen ( *fullPath ); // ! Don't use sComposedPath->size()! - - XMP_Enforce ( *pathSize < sComposedPath->size() ); // Rather late, but complain about buffer overflow. - -} // ComposeArrayItemPath - - -// ------------------------------------------------------------------------------------------------- -// ComposeStructFieldPath -// ---------------------- -// -// Return "structName/ns:fieldName". - -/* class static */ void -XMPUtils::ComposeStructFieldPath ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ) -{ - XMP_Assert ( (schemaNS != 0) && (fieldNS != 0) ); // Enforced by wrapper. - XMP_Assert ( (*structName != 0) && (*fieldName != 0) ); // Enforced by wrapper. - XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path. - ExpandXPath ( schemaNS, structName, &expPath ); - - XMP_ExpandedXPath fieldPath; - 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; - - sComposedPath->erase(); - sComposedPath->reserve ( reserveLen ); - *sComposedPath = structName; - *sComposedPath += '/'; - *sComposedPath += fieldPath[kRootPropStep].step; - - *fullPath = sComposedPath->c_str(); - *pathSize = sComposedPath->size(); - -} // ComposeStructFieldPath - - -// ------------------------------------------------------------------------------------------------- -// ComposeQualifierPath -// -------------------- -// -// Return "propName/?ns:qualName". - -/* class static */ void -XMPUtils::ComposeQualifierPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ) -{ - XMP_Assert ( (schemaNS != 0) && (qualNS != 0) ); // Enforced by wrapper. - XMP_Assert ( (*propName != 0) && (*qualName != 0) ); // Enforced by wrapper. - XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path. - ExpandXPath ( schemaNS, propName, &expPath ); - - XMP_ExpandedXPath qualPath; - 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; - - sComposedPath->erase(); - sComposedPath->reserve ( reserveLen ); - *sComposedPath = propName; - *sComposedPath += "/?"; - *sComposedPath += qualPath[kRootPropStep].step; - - *fullPath = sComposedPath->c_str(); - *pathSize = sComposedPath->size(); - -} // ComposeQualifierPath - - -// ------------------------------------------------------------------------------------------------- -// ComposeLangSelector -// ------------------- -// -// Return "arrayName[?xml:lang="lang"]". - -// *** #error "handle quotes in the lang - or verify format" - -/* class static */ void -XMPUtils::ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr _langName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ) -{ - XMP_Assert ( schemaNS != 0 ); // Enforced by wrapper. - XMP_Assert ( (*arrayName != 0) && (*_langName != 0) ); // Enforced by wrapper. - XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path. - ExpandXPath ( schemaNS, arrayName, &expPath ); - - XMP_VarString langName ( _langName ); - NormalizeLangValue ( &langName ); - - XMP_StringLen reserveLen = strlen(arrayName) + langName.size() + 14; - - sComposedPath->erase(); - sComposedPath->reserve ( reserveLen ); - *sComposedPath = arrayName; - *sComposedPath += "[?xml:lang=\""; - *sComposedPath += langName; - *sComposedPath += "\"]"; - - *fullPath = sComposedPath->c_str(); - *pathSize = sComposedPath->size(); - -} // ComposeLangSelector - - -// ------------------------------------------------------------------------------------------------- -// ComposeFieldSelector -// -------------------- -// -// Return "arrayName[ns:fieldName="fieldValue"]". - -// *** #error "handle quotes in the value" - -/* class static */ void -XMPUtils::ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ) -{ - XMP_Assert ( (schemaNS != 0) && (fieldNS != 0) && (fieldValue != 0) ); // Enforced by wrapper. - XMP_Assert ( (*arrayName != 0) && (*fieldName != 0) ); // Enforced by wrapper. - XMP_Assert ( (fullPath != 0) && (pathSize != 0) ); // Enforced by wrapper. - - XMP_ExpandedXPath expPath; // Just for side effects to check namespace and basic path. - ExpandXPath ( schemaNS, arrayName, &expPath ); - - XMP_ExpandedXPath fieldPath; - 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; - - sComposedPath->erase(); - sComposedPath->reserve ( reserveLen ); - *sComposedPath = arrayName; - *sComposedPath += '['; - *sComposedPath += fieldPath[kRootPropStep].step; - *sComposedPath += "=\""; - *sComposedPath += fieldValue; - *sComposedPath += "\"]"; - - *fullPath = sComposedPath->c_str(); - *pathSize = sComposedPath->size(); - -} // ComposeFieldSelector - - -// ------------------------------------------------------------------------------------------------- -// ConvertFromBool -// --------------- - -/* class static */ void -XMPUtils::ConvertFromBool ( bool binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ) -{ - XMP_Assert ( (strValue != 0) && (strSize != 0) ); // Enforced by wrapper. - - if ( binValue ) { - *strValue = kXMP_TrueStr; - *strSize = strlen ( kXMP_TrueStr ); - } else { - *strValue = kXMP_FalseStr; - *strSize = strlen ( kXMP_FalseStr ); - } - -} // ConvertFromBool - - -// ------------------------------------------------------------------------------------------------- -// ConvertFromInt -// -------------- - -/* class static */ void -XMPUtils::ConvertFromInt ( XMP_Int32 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ) -{ - XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) ); // Enforced by wrapper. - - if ( *format == 0 ) format = "%d"; - - sConvertedValue->erase(); - sConvertedValue->reserve ( 100 ); // More than enough for any reasonable format and value. - sConvertedValue->append ( 100, ' ' ); - - // AUDIT: Using string->size() for the snprintf length is safe. - snprintf ( const_cast(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue ); - - *strValue = sConvertedValue->c_str(); - *strSize = strlen ( *strValue ); // ! Don't use sConvertedValue->size()! - - XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow. - -} // ConvertFromInt - - -// ------------------------------------------------------------------------------------------------- -// ConvertFromInt64 -// ---------------- - -/* class static */ void -XMPUtils::ConvertFromInt64 ( XMP_Int64 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ) -{ - XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) ); // Enforced by wrapper. - - if ( *format == 0 ) format = "%lld"; - - sConvertedValue->erase(); - sConvertedValue->reserve ( 100 ); // More than enough for any reasonable format and value. - sConvertedValue->append ( 100, ' ' ); - - // AUDIT: Using string->size() for the snprintf length is safe. - snprintf ( const_cast(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue ); - - *strValue = sConvertedValue->c_str(); - *strSize = strlen ( *strValue ); // ! Don't use sConvertedValue->size()! - - XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow. - -} // ConvertFromInt64 - - -// ------------------------------------------------------------------------------------------------- -// ConvertFromFloat -// ---------------- - -/* class static */ void -XMPUtils::ConvertFromFloat ( double binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ) -{ - XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) ); // Enforced by wrapper. - - if ( *format == 0 ) format = "%f"; - - sConvertedValue->erase(); - sConvertedValue->reserve ( 1000 ); // More than enough for any reasonable format and value. - sConvertedValue->append ( 1000, ' ' ); - - // AUDIT: Using string->size() for the snprintf length is safe. - snprintf ( const_cast(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue ); - - *strValue = sConvertedValue->c_str(); - *strSize = strlen ( *strValue ); // ! Don't use sConvertedValue->size()! - - XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow. - -} // ConvertFromFloat - - -// ------------------------------------------------------------------------------------------------- -// ConvertFromDate -// --------------- -// -// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime: -// YYYY -// YYYY-MM -// YYYY-MM-DD -// YYYY-MM-DDThh:mmTZD -// YYYY-MM-DDThh:mm:ssTZD -// YYYY-MM-DDThh:mm:ss.sTZD -// -// YYYY = four-digit year -// MM = two-digit month (01=January, etc.) -// DD = two-digit day of month (01 through 31) -// hh = two digits of hour (00 through 23) -// mm = two digits of minute (00 through 59) -// ss = two digits of second (00 through 59) -// s = one or more digits representing a decimal fraction of a second -// TZD = time zone designator (Z or +hh:mm or -hh:mm) -// -// Note that ISO 8601 does not seem to allow years less than 1000 or greater than 9999. We allow -// any year, even negative ones. The year is formatted as "%.4d". - -// *** Need to check backward compatibility for partial forms! - -/* class static */ void -XMPUtils::ConvertFromDate ( const XMP_DateTime & binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ) -{ - XMP_Assert ( (strValue != 0) && (strSize != 0) ); // Enforced by wrapper. - - bool addTimeZone = false; - char buffer [100]; // Plenty long enough. - - // Pick the format, use snprintf to format into a local buffer, assign to static output string. - // Don't use AdjustTimeOverflow at the start, that will wipe out zero month or day values. - - // ! Photoshop 8 creates "time only" values with zeros for year, month, and day. - - XMP_DateTime tempDate = binValue; - - // Temporary fix for bug 1269463, silently fix out of range month or day. - - bool haveDay = (tempDate.day != 0); - bool haveTime = ( (tempDate.hour != 0) || (tempDate.minute != 0) || - (tempDate.second != 0) || (tempDate.nanoSecond != 0) || - (tempDate.tzSign != 0) || (tempDate.tzHour != 0) || (tempDate.tzMinute != 0) ); - - if ( tempDate.month == 0 ) { - if ( haveDay || haveTime ) tempDate.month = 1; - } else { - if ( tempDate.month < 1 ) tempDate.month = 1; - if ( tempDate.month > 12 ) tempDate.month = 12; - } - - if ( tempDate.day == 0 ) { - if ( haveTime ) tempDate.day = 1; - } else { - if ( tempDate.day < 1 ) tempDate.day = 1; - if ( tempDate.day > 31 ) tempDate.day = 31; - } - - // Now carry on with the original logic. - - if ( tempDate.month == 0 ) { - - // Output YYYY if all else is zero, otherwise output a full string for the quasi-bogus - // "time only" values from Photoshop CS. - if ( (tempDate.day == 0) && (tempDate.hour == 0) && (tempDate.minute == 0) && - (tempDate.second == 0) && (tempDate.nanoSecond == 0) && - (tempDate.tzSign == 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0) ) { - snprintf ( buffer, sizeof(buffer), "%.4d", static_cast(tempDate.year) ); // AUDIT: Using sizeof for snprintf length is safe. - } else if ( (tempDate.year == 0) && (tempDate.day == 0) ) { - FormatFullDateTime ( tempDate, buffer, sizeof(buffer) ); - addTimeZone = true; - } else { - XMP_Throw ( "Invalid partial date", kXMPErr_BadParam); - } - - } else if ( tempDate.day == 0 ) { - - // Output YYYY-MM. - if ( (tempDate.month < 1) || (tempDate.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam); - if ( (tempDate.hour != 0) || (tempDate.minute != 0) || - (tempDate.second != 0) || (tempDate.nanoSecond != 0) || - (tempDate.tzSign != 0) || (tempDate.tzHour != 0) || (tempDate.tzMinute != 0) ) { - XMP_Throw ( "Invalid partial date, non-zeros after zero month and day", kXMPErr_BadParam); - } - snprintf ( buffer, sizeof(buffer), "%.4d-%02d", static_cast(tempDate.year), static_cast(tempDate.month) ); // AUDIT: Using sizeof for snprintf length is safe. - - } else if ( (tempDate.hour == 0) && (tempDate.minute == 0) && - (tempDate.second == 0) && (tempDate.nanoSecond == 0) && - (tempDate.tzSign == 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0) ) { - - // Output YYYY-MM-DD. - if ( (tempDate.month < 1) || (tempDate.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam); - if ( (tempDate.day < 1) || (tempDate.day > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam); - snprintf ( buffer, sizeof(buffer), "%.4d-%02d-%02d", static_cast(tempDate.year), static_cast(tempDate.month), static_cast(tempDate.day) ); // AUDIT: Using sizeof for snprintf length is safe. - - } else { - - FormatFullDateTime ( tempDate, buffer, sizeof(buffer) ); - addTimeZone = true; - - } - - sConvertedValue->assign ( buffer ); - - if ( addTimeZone ) { - - if ( (tempDate.tzHour < 0) || (tempDate.tzHour > 23) || - (tempDate.tzMinute < 0 ) || (tempDate.tzMinute > 59) || - (tempDate.tzSign < -1) || (tempDate.tzSign > +1) || - ((tempDate.tzSign != 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0)) || - ((tempDate.tzSign == 0) && ((tempDate.tzHour != 0) || (tempDate.tzMinute != 0))) ) { - XMP_Throw ( "Invalid time zone values", kXMPErr_BadParam ); - } - - if ( tempDate.tzSign == 0 ) { - *sConvertedValue += 'Z'; - } else { - snprintf ( buffer, sizeof(buffer), "+%02d:%02d", static_cast(tempDate.tzHour), static_cast(tempDate.tzMinute) ); // AUDIT: Using sizeof for snprintf length is safe. - if ( tempDate.tzSign < 0 ) buffer[0] = '-'; - *sConvertedValue += buffer; - } - - } - - *strValue = sConvertedValue->c_str(); - *strSize = sConvertedValue->size(); - -} // ConvertFromDate - - -// ------------------------------------------------------------------------------------------------- -// ConvertToBool -// ------------- -// -// Formally the string value should be "True" or "False", but we should be more flexible here. Map -// the string to lower case. Allow any of "true", "false", "t", "f", "1", or "0". - -/* class static */ bool -XMPUtils::ConvertToBool ( XMP_StringPtr strValue ) -{ - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue ); - - bool result = false; - XMP_VarString strObj ( strValue ); - - for ( XMP_VarStringPos ch = strObj.begin(); ch != strObj.end(); ++ch ) { - if ( ('A' <= *ch) && (*ch <= 'Z') ) *ch += 0x20; - } - - if ( (strObj == "true") || (strObj == "t") || (strObj == "1") ) { - result = true; - } else if ( (strObj == "false") || (strObj == "f") || (strObj == "0") ) { - result = false; - } else { - XMP_Throw ( "Invalid Boolean string", kXMPErr_BadParam ); - } - - return result; - -} // ConvertToBool - - -// ------------------------------------------------------------------------------------------------- -// ConvertToInt -// ------------ - -/* class static */ XMP_Int32 -XMPUtils::ConvertToInt ( XMP_StringPtr strValue ) -{ - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue ); - - int count; - char nextCh; - XMP_Int32 result; - - if ( ! XMP_LitNMatch ( strValue, "0x", 2 ) ) { - count = sscanf ( strValue, "%d%c", (int*)&result, &nextCh ); - } else { - count = sscanf ( strValue, "%x%c", (unsigned int*)&result, &nextCh ); - } - - if ( count != 1 ) XMP_Throw ( "Invalid integer string", kXMPErr_BadParam ); - - return result; - -} // ConvertToInt - - -// ------------------------------------------------------------------------------------------------- -// ConvertToInt64 -// -------------- - -/* class static */ XMP_Int64 -XMPUtils::ConvertToInt64 ( XMP_StringPtr strValue ) -{ -#if defined(__MINGW32__)// || defined(__MINGW64__) - return ConvertToInt(strValue); -#else - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue ); - - int count; - char nextCh; - XMP_Int64 result; - - if ( ! XMP_LitNMatch ( strValue, "0x", 2 ) ) { - count = sscanf ( strValue, "%lld%c", &result, &nextCh ); - } else { - count = sscanf ( strValue, "%llx%c", &result, &nextCh ); - } - - if ( count != 1 ) XMP_Throw ( "Invalid integer string", kXMPErr_BadParam ); - - return result; -#endif -} // ConvertToInt64 - - -// ------------------------------------------------------------------------------------------------- -// ConvertToFloat -// -------------- - -/* class static */ double -XMPUtils::ConvertToFloat ( XMP_StringPtr strValue ) -{ - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue ); - - XMP_VarString oldLocale; // Try to make sure number conversion uses '.' as the decimal point. - XMP_StringPtr oldLocalePtr = setlocale ( LC_ALL, 0 ); - if ( oldLocalePtr != 0 ) { - oldLocale.assign ( oldLocalePtr ); - setlocale ( LC_ALL, "C" ); - } - - errno = 0; - char * numEnd; - double result = strtod ( strValue, &numEnd ); - - if ( oldLocalePtr != 0 ) setlocale ( LC_ALL, oldLocalePtr ); // ! Reset locale before possible throw! - if ( (errno != 0) || (*numEnd != 0) ) XMP_Throw ( "Invalid float string", kXMPErr_BadParam ); - - return result; - -} // ConvertToFloat - - -// ------------------------------------------------------------------------------------------------- -// ConvertToDate -// ------------- -// -// Parse a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime: -// YYYY -// YYYY-MM -// YYYY-MM-DD -// YYYY-MM-DDThh:mmTZD -// YYYY-MM-DDThh:mm:ssTZD -// YYYY-MM-DDThh:mm:ss.sTZD -// -// YYYY = four-digit year -// MM = two-digit month (01=January, etc.) -// DD = two-digit day of month (01 through 31) -// hh = two digits of hour (00 through 23) -// mm = two digits of minute (00 through 59) -// ss = two digits of second (00 through 59) -// s = one or more digits representing a decimal fraction of a second -// TZD = time zone designator (Z or +hh:mm or -hh:mm) -// -// Note that ISO 8601 does not seem to allow years less than 1000 or greater than 9999. We allow -// any year, even negative ones. The year is formatted as "%.4d". - -// ! Tolerate missing TZD, assume the time is in local time -// ! Tolerate missing date portion, in case someone foolishly writes a time-only value that way. - -// *** Put the ISO format comments in the header documentation. - -/* class static */ void -XMPUtils::ConvertToDate ( XMP_StringPtr strValue, - XMP_DateTime * binValue ) -{ - if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue); - - size_t pos = 0; - XMP_Int32 temp; - - XMP_Assert ( sizeof(*binValue) == sizeof(XMP_DateTime) ); - (void) memset ( binValue, 0, sizeof(*binValue) ); // AUDIT: Safe, using sizeof destination. - - bool timeOnly = ( (strValue[0] == 'T') || - ((strlen(strValue) >= 2) && (strValue[1] == ':')) || - ((strlen(strValue) >= 3) && (strValue[2] == ':')) ); - - if ( ! timeOnly ) { - - if ( strValue[0] == '-' ) pos = 1; - - temp = GatherInt ( strValue, &pos, "Invalid year in date string" ); // Extract the year. - if ( (strValue[pos] != 0) && (strValue[pos] != '-') ) XMP_Throw ( "Invalid date string, after year", kXMPErr_BadParam ); - if ( strValue[0] == '-' ) temp = -temp; - binValue->year = temp; - if ( strValue[pos] == 0 ) return; - - ++pos; - temp = GatherInt ( strValue, &pos, "Invalid month in date string" ); // Extract the month. - if ( (temp < 1) || (temp > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam ); - if ( (strValue[pos] != 0) && (strValue[pos] != '-') ) XMP_Throw ( "Invalid date string, after month", kXMPErr_BadParam ); - binValue->month = temp; - if ( strValue[pos] == 0 ) return; - - ++pos; - temp = GatherInt ( strValue, &pos, "Invalid day in date string" ); // Extract the day. - if ( (temp < 1) || (temp > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam ); - if ( (strValue[pos] != 0) && (strValue[pos] != 'T') ) XMP_Throw ( "Invalid date string, after day", kXMPErr_BadParam ); - binValue->day = temp; - if ( strValue[pos] == 0 ) return; - - // Allow year, month, and day to all be zero; implies the date portion is missing. - if ( (binValue->year != 0) || (binValue->month != 0) || (binValue->day != 0) ) { - // Temporary fix for bug 1269463, silently fix out of range month or day. - // if ( (binValue->month < 1) || (binValue->month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam ); - // if ( (binValue->day < 1) || (binValue->day > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam ); - if ( binValue->month < 1 ) binValue->month = 1; - if ( binValue->month > 12 ) binValue->month = 12; - if ( binValue->day < 1 ) binValue->day = 1; - if ( binValue->day > 31 ) binValue->day = 31; - } - - } - - if ( strValue[pos] == 'T' ) { - ++pos; - } else if ( ! timeOnly ) { - XMP_Throw ( "Invalid date string, missing 'T' after date", kXMPErr_BadParam ); - } - - temp = GatherInt ( strValue, &pos, "Invalid hour in date string" ); // Extract the hour. - if ( strValue[pos] != ':' ) XMP_Throw ( "Invalid date string, after hour", kXMPErr_BadParam ); - if ( temp < 0 || temp > 23 ) temp = 23; // *** 1269463: XMP_Throw ( "Hour is out of range", kXMPErr_BadParam ); - binValue->hour = temp; - // Don't check for done, we have to work up to the time zone. - - ++pos; - temp = GatherInt ( strValue, &pos, "Invalid minute in date string" ); // And the minute. - if ( (strValue[pos] != ':') && (strValue[pos] != 'Z') && - (strValue[pos] != '+') && (strValue[pos] != '-') && (strValue[pos] != 0) ) XMP_Throw ( "Invalid date string, after minute", kXMPErr_BadParam ); - if ( temp < 0 || temp > 59 ) temp = 59; // *** 1269463: XMP_Throw ( "Minute is out of range", kXMPErr_BadParam ); - binValue->minute = temp; - // Don't check for done, we have to work up to the time zone. - - if ( strValue[pos] == ':' ) { - - ++pos; - temp = GatherInt ( strValue, &pos, "Invalid whole seconds in date string" ); // Extract the whole seconds. - if ( (strValue[pos] != '.') && (strValue[pos] != 'Z') && - (strValue[pos] != '+') && (strValue[pos] != '-') && (strValue[pos] != 0) ) { - XMP_Throw ( "Invalid date string, after whole seconds", kXMPErr_BadParam ); - } - if ( temp < 0 || temp > 59 ) temp = 59; // *** 1269463: XMP_Throw ( "Whole second is out of range", kXMPErr_BadParam ); - binValue->second = temp; - // Don't check for done, we have to work up to the time zone. - - if ( strValue[pos] == '.' ) { - - ++pos; - size_t digits = pos; // Will be the number of digits later. - - temp = GatherInt ( strValue, &pos, "Invalid fractional seconds in date string" ); // Extract the fractional seconds. - if ( (strValue[pos] != 'Z') && (strValue[pos] != '+') && (strValue[pos] != '-') && (strValue[pos] != 0) ) { - XMP_Throw ( "Invalid date string, after fractional second", kXMPErr_BadParam ); - } - - digits = pos - digits; - for ( ; digits > 9; --digits ) temp = temp / 10; - for ( ; digits < 9; ++digits ) temp = temp * 10; - - if ( temp < 0 || temp >= 1000*1000*1000 ) XMP_Throw ( "Fractional second is out of range", kXMPErr_BadParam ); - binValue->nanoSecond = temp; - // Don't check for done, we have to work up to the time zone. - - } - - } - - if ( strValue[pos] == 'Z' ) { - - ++pos; - - } else if ( strValue[pos] != 0 ) { - - if ( strValue[pos] == '+' ) { - binValue->tzSign = kXMP_TimeEastOfUTC; - } else if ( strValue[pos] == '-' ) { - binValue->tzSign = kXMP_TimeWestOfUTC; - } else { - XMP_Throw ( "Time zone must begin with 'Z', '+', or '-'", kXMPErr_BadParam ); - } - - ++pos; - temp = GatherInt ( strValue, &pos, "Invalid time zone hour in date string" ); // Extract the time zone hour. - if ( strValue[pos] != ':' ) XMP_Throw ( "Invalid date string, after time zone hour", kXMPErr_BadParam ); - if ( temp < 0 || temp > 23 ) XMP_Throw ( "Time zone hour is out of range", kXMPErr_BadParam ); - binValue->tzHour = temp; - - ++pos; - temp = GatherInt ( strValue, &pos, "Invalid time zone minute in date string" ); // Extract the time zone minute. - if ( temp < 0 || temp > 59 ) XMP_Throw ( "Time zone minute is out of range", kXMPErr_BadParam ); - binValue->tzMinute = temp; - - } else { - - XMPUtils::SetTimeZone( binValue ); - - } - - if ( strValue[pos] != 0 ) XMP_Throw ( "Invalid date string, extra chars at end", kXMPErr_BadParam ); - -} // ConvertToDate - - -// ------------------------------------------------------------------------------------------------- -// EncodeToBase64 -// -------------- -// -// Encode a string of raw data bytes in base 64 according to RFC 2045. For the encoding definition -// see section 6.8 in . Although it isn't needed for RDF, we -// do insert a linefeed character as a newline for every 76 characters of encoded output. - -/* class static */ void -XMPUtils::EncodeToBase64 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - XMP_StringPtr * encodedStr, - XMP_StringLen * encodedLen ) -{ - if ( (rawStr == 0) && (rawLen != 0) ) XMP_Throw ( "Null raw data buffer", kXMPErr_BadParam ); - if ( rawLen == 0 ) { - *encodedStr = 0; - *encodedLen = 0; - return; - } - - char encChunk[4]; - - unsigned long in, out; - unsigned char c1, c2, c3; - unsigned long merge; - - const size_t outputSize = (rawLen / 3) * 4; // Approximate, might be small. - - sBase64Str->erase(); - sBase64Str->reserve ( outputSize ); - - // ---------------------------------------------------------------------------------------- - // Each 6 bits of input produces 8 bits of output, so 3 input bytes become 4 output bytes. - // Process the whole chunks of 3 bytes first, then deal with any remainder. Be careful with - // the loop comparison, size-2 could be negative! - - for ( in = 0, out = 0; (in+2) < rawLen; in += 3, out += 4 ) { - - c1 = rawStr[in]; - c2 = rawStr[in+1]; - c3 = rawStr[in+2]; - - merge = (c1 << 16) + (c2 << 8) + c3; - - encChunk[0] = sBase64Chars [ merge >> 18 ]; - encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ]; - encChunk[2] = sBase64Chars [ (merge >> 6) & 0x3F ]; - encChunk[3] = sBase64Chars [ merge & 0x3F ]; - - if ( out >= 76 ) { - sBase64Str->append ( 1, kLF ); - out = 0; - } - sBase64Str->append ( encChunk, 4 ); - - } - - // ------------------------------------------------------------------------------------------ - // The output must always be a multiple of 4 bytes. If there is a 1 or 2 byte input remainder - // we need to create another chunk. Zero pad with bits to a 6 bit multiple, then add one or - // two '=' characters to pad out to 4 bytes. - - switch ( rawLen - in ) { - - case 0: // Done, no remainder. - break; - - case 1: // One input byte remains. - - c1 = rawStr[in]; - merge = c1 << 16; - - encChunk[0] = sBase64Chars [ merge >> 18 ]; - encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ]; - encChunk[2] = encChunk[3] = '='; - - if ( out >= 76 ) sBase64Str->append ( 1, kLF ); - sBase64Str->append ( encChunk, 4 ); - break; - - case 2: // Two input bytes remain. - - c1 = rawStr[in]; - c2 = rawStr[in+1]; - merge = (c1 << 16) + (c2 << 8); - - encChunk[0] = sBase64Chars [ merge >> 18 ]; - encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ]; - encChunk[2] = sBase64Chars [ (merge >> 6) & 0x3F ]; - encChunk[3] = '='; - - if ( out >= 76 ) sBase64Str->append ( 1, kLF ); - sBase64Str->append ( encChunk, 4 ); - break; - - } - - // ------------------------- - // Assign the output values. - - *encodedStr = sBase64Str->c_str(); - *encodedLen = sBase64Str->size(); - -} // EncodeToBase64 - - -// ------------------------------------------------------------------------------------------------- -// DecodeFromBase64 -// ---------------- -// -// Decode a string of raw data bytes from base 64 according to RFC 2045. For the encoding definition -// see section 6.8 in . RFC 2045 talks about ignoring all "bad" -// input but warning about non-whitespace. For XMP use we ignore space, tab, LF, and CR. Any other -// bad input is rejected. - -/* class static */ void -XMPUtils::DecodeFromBase64 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - XMP_StringPtr * rawStr, - XMP_StringLen * rawLen ) -{ - if ( (encodedStr == 0) && (encodedLen != 0) ) XMP_Throw ( "Null encoded data buffer", kXMPErr_BadParam ); - if ( encodedLen == 0 ) { - *rawStr = 0; - *rawLen = 0; - return; - } - - unsigned char ch, rawChunk[3]; - unsigned long inStr, inChunk, inLimit, merge, padding; - - XMP_StringLen outputSize = (encodedLen / 4) * 3; // Only a close approximation. - - sBase64Str->erase(); - sBase64Str->reserve ( outputSize ); - - - // ---------------------------------------------------------------------------------------- - // Each 8 bits of input produces 6 bits of output, so 4 input bytes become 3 output bytes. - // Process all but the last 4 data bytes first, then deal with the final chunk. Whitespace - // in the input must be ignored. The first loop finds where the last 4 data bytes start and - // counts the number of padding equal signs. - - padding = 0; - for ( inStr = 0, inLimit = encodedLen; (inStr < 4) && (inLimit > 0); ) { - inLimit -= 1; // ! Don't do in the loop control, the decr/test order is wrong. - ch = encodedStr[inLimit]; - if ( ch == '=' ) { - padding += 1; // The equal sign padding is a data byte. - } else if ( DecodeBase64Char(ch) == 0xFF ) { - continue; // Ignore whitespace, don't increment inStr. - } else { - inStr += 1; - } - } - - // ! Be careful to count whitespace that is immediately before the final data. Otherwise - // ! middle portion will absorb the final data and mess up the final chunk processing. - - while ( (inLimit > 0) && (DecodeBase64Char(encodedStr[inLimit-1]) == 0xFF) ) --inLimit; - - if ( inStr == 0 ) return; // Nothing but whitespace. - if ( padding > 2 ) XMP_Throw ( "Invalid encoded string", kXMPErr_BadParam ); - - // ------------------------------------------------------------------------------------------- - // Now process all but the last chunk. The limit ensures that we have at least 4 data bytes - // left when entering the output loop, so the inner loop will succeed without overrunning the - // end of the data. At the end of the outer loop we might be past inLimit though. - - inStr = 0; - while ( inStr < inLimit ) { - - merge = 0; - for ( inChunk = 0; inChunk < 4; ++inStr ) { // ! Yes, increment inStr on each pass. - ch = DecodeBase64Char ( encodedStr [inStr] ); - if ( ch == 0xFF ) continue; // Ignore whitespace. - merge = (merge << 6) + ch; - inChunk += 1; - } - - rawChunk[0] = (unsigned char) (merge >> 16); - rawChunk[1] = (unsigned char) ((merge >> 8) & 0xFF); - rawChunk[2] = (unsigned char) (merge & 0xFF); - - sBase64Str->append ( (char*)rawChunk, 3 ); - - } - - // ------------------------------------------------------------------------------------------- - // Process the final, possibly partial, chunk of data. The input is always a multiple 4 bytes, - // but the raw data can be any length. The number of padding '=' characters determines if the - // final chunk has 1, 2, or 3 raw data bytes. - - XMP_Assert ( inStr < encodedLen ); - - merge = 0; - for ( inChunk = 0; inChunk < 4-padding; ++inStr ) { // ! Yes, increment inStr on each pass. - ch = DecodeBase64Char ( encodedStr[inStr] ); - if ( ch == 0xFF ) continue; // Ignore whitespace. - merge = (merge << 6) + ch; - inChunk += 1; - } - - if ( padding == 2 ) { - - rawChunk[0] = (unsigned char) (merge >> 4); - sBase64Str->append ( (char*)rawChunk, 1 ); - - } else if ( padding == 1 ) { - - rawChunk[0] = (unsigned char) (merge >> 10); - rawChunk[1] = (unsigned char) ((merge >> 2) & 0xFF); - sBase64Str->append ( (char*)rawChunk, 2 ); - - } else { - - rawChunk[0] = (unsigned char) (merge >> 16); - rawChunk[1] = (unsigned char) ((merge >> 8) & 0xFF); - rawChunk[2] = (unsigned char) (merge & 0xFF); - sBase64Str->append ( (char*)rawChunk, 3 ); - - } - - // ------------------------- - // Assign the output values. - - *rawStr = sBase64Str->c_str(); - *rawLen = sBase64Str->size(); - -} // DecodeFromBase64 - - -// ------------------------------------------------------------------------------------------------- -// PackageForJPEG -// -------------- - -/* class static */ void -XMPUtils::PackageForJPEG ( const XMPMeta & origXMP, - XMP_StringPtr * stdStr, - XMP_StringLen * stdLen, - XMP_StringPtr * extStr, - XMP_StringLen * extLen, - XMP_StringPtr * digestStr, - XMP_StringLen * digestLen ) -{ - enum { kStdXMPLimit = 65000 }; - static const char * kPacketTrailer = ""; - static size_t kTrailerLen = strlen ( kPacketTrailer ); - - XMP_StringPtr tempStr; - XMP_StringLen tempLen; - - XMPMeta stdXMP, extXMP; - - sStandardXMP->clear(); // Clear the static strings that get returned to the client. - sExtendedXMP->clear(); - sExtendedDigest->clear(); - - XMP_OptionBits keepItSmall = kXMP_UseCompactFormat | kXMP_OmitAllFormatting; - - // Try to serialize everything. Note that we're making internal calls to SerializeToBuffer, so - // we'll be getting back the pointer and length for its internal string. - - origXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 ); - #if Trace_PackageForJPEG - printf ( "\nXMPUtils::PackageForJPEG - Full serialize %d bytes\n", tempLen ); - #endif - - if ( tempLen > kStdXMPLimit ) { - - // Couldn't fit everything, make a copy of the input XMP and make sure there is no xmp:Thumbnails property. - - stdXMP.tree.options = origXMP.tree.options; - stdXMP.tree.name = origXMP.tree.name; - stdXMP.tree.value = origXMP.tree.value; - CloneOffspring ( &origXMP.tree, &stdXMP.tree ); - - if ( stdXMP.DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) { - stdXMP.DeleteProperty ( kXMP_NS_XMP, "Thumbnails" ); - stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 ); - #if Trace_PackageForJPEG - printf ( " Delete xmp:Thumbnails, %d bytes left\n", tempLen ); - #endif - } - - } - - if ( tempLen > 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 ); - - XMP_NodePtrPos crSchemaPos; - XMP_Node * crSchema = FindSchemaNode ( &stdXMP.tree, kXMP_NS_CameraRaw, kXMP_ExistingOnly, &crSchemaPos ); - - if ( crSchema != 0 ) { - crSchema->parent = &extXMP.tree; - extXMP.tree.children.push_back ( crSchema ); - stdXMP.tree.children.erase ( crSchemaPos ); - stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 ); - #if Trace_PackageForJPEG - printf ( " Move Camera Raw schema, %d bytes left\n", tempLen ); - #endif - } - - } - - if ( tempLen > kStdXMPLimit ) { - - // Still doesn't fit, move photoshop:History. - - bool moved = MoveOneProperty ( stdXMP, &extXMP, kXMP_NS_Photoshop, "photoshop:History" ); - - if ( moved ) { - stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 ); - #if Trace_PackageForJPEG - printf ( " Move photoshop:History, %d bytes left\n", tempLen ); - #endif - } - - } - - if ( tempLen > 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. - - PropSizeMap 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 ( (tempLen > kStdXMPLimit) && (! propSizes.empty()) ) { - - // Inner loop, move what seems to be enough according to the estimates. - - 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, &tempLen, keepItSmall, 1, "", "", 0 ); - - } - - } - - if ( tempLen > 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.tree.children.empty() ) { - - // Just have the standard XMP. - sStandardXMP->assign ( tempStr, tempLen ); - - } else { - - // Have extended XMP. Serialize it, compute the digest, reset xmpNote:HasExtendedXMP, and - // reserialize the standard XMP. - - extXMP.SerializeToBuffer ( &tempStr, &tempLen, (keepItSmall | kXMP_OmitPacketWrapper), 0, "", "", 0 ); - sExtendedXMP->assign ( tempStr, tempLen ); - - MD5_CTX context; - XMP_Uns8 digest [16]; - MD5Init ( &context ); - MD5Update ( &context, (XMP_Uns8*)tempStr, tempLen ); - MD5Final ( digest, &context ); - - sExtendedDigest->reserve ( 32 ); - for ( size_t i = 0; i < 16; ++i ) { - XMP_Uns8 byte = digest[i]; - sExtendedDigest->push_back ( kHexDigits [ byte>>4 ] ); - sExtendedDigest->push_back ( kHexDigits [ byte&0xF ] ); - } - - stdXMP.SetProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP", sExtendedDigest->c_str(), 0 ); - stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 ); - sStandardXMP->assign ( tempStr, tempLen ); - - } - - // Adjust the standard XMP padding to be up to 2KB. - - XMP_Assert ( (sStandardXMP->size() > kTrailerLen) && (sStandardXMP->size() <= kStdXMPLimit) ); - const char * packetEnd = 0; - packetEnd = sStandardXMP->c_str() + sStandardXMP->size() - kTrailerLen; - XMP_Assert ( XMP_LitMatch ( packetEnd, kPacketTrailer ) ); - UNUSED(packetEnd); - - size_t extraPadding = kStdXMPLimit - sStandardXMP->size(); // ! Do this before erasing the trailer. - if ( extraPadding > 2047 ) extraPadding = 2047; - sStandardXMP->erase ( sStandardXMP->size() - kTrailerLen ); - sStandardXMP->append ( extraPadding, ' ' ); - sStandardXMP->append ( kPacketTrailer ); - - // Assign the output pointer and sizes. - - *stdStr = sStandardXMP->c_str(); - *stdLen = sStandardXMP->size(); - *extStr = sExtendedXMP->c_str(); - *extLen = sExtendedXMP->size(); - *digestStr = sExtendedDigest->c_str(); - *digestLen = sExtendedDigest->size(); - -} // PackageForJPEG - - -// ------------------------------------------------------------------------------------------------- -// MergeFromJPEG -// ------------- -// -// Copy all of the top level properties from extendedXMP to fullXMP, replacing any duplicates. -// Delete the xmpNote:HasExtendedXMP property from fullXMP. - -/* class static */ void -XMPUtils::MergeFromJPEG ( XMPMeta * fullXMP, - const XMPMeta & extendedXMP ) -{ - - XMPUtils::AppendProperties ( extendedXMP, fullXMP, kXMPUtil_DoAllProperties ); - fullXMP->DeleteProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP" ); - -} // MergeFromJPEG - - -// ------------------------------------------------------------------------------------------------- -// CurrentDateTime -// --------------- - -/* class static */ void -XMPUtils::CurrentDateTime ( XMP_DateTime * xmpTime ) -{ - XMP_Assert ( xmpTime != 0 ); // ! Enforced by wrapper. - - ansi_tt binTime = ansi_time(0); - if ( binTime == -1 ) XMP_Throw ( "Failure from ANSI C time function", kXMPErr_ExternalFailure ); - ansi_tm currTime; - ansi_localtime ( &binTime, &currTime ); - - xmpTime->year = currTime.tm_year + 1900; - xmpTime->month = currTime.tm_mon + 1; - xmpTime->day = currTime.tm_mday; - xmpTime->hour = currTime.tm_hour; - xmpTime->minute = currTime.tm_min; - xmpTime->second = currTime.tm_sec; - - xmpTime->nanoSecond = 0; - xmpTime->tzSign = 0; - xmpTime->tzHour = 0; - xmpTime->tzMinute = 0; - - XMPUtils::SetTimeZone ( xmpTime ); - -} // CurrentDateTime - - -// ------------------------------------------------------------------------------------------------- -// SetTimeZone -// ----------- -// -// Sets just the time zone part of the time. Useful for determining the local time zone or for -// converting a "zone-less" time to a proper local time. The ANSI C time functions are smart enough -// to do all the right stuff, as long as we call them properly! - -/* class static */ void -XMPUtils::SetTimeZone ( XMP_DateTime * xmpTime ) -{ - XMP_Assert ( xmpTime != 0 ); // ! Enforced by wrapper. - - if ( (xmpTime->tzSign != 0) || (xmpTime->tzHour != 0) || (xmpTime->tzMinute != 0) ) { - XMP_Throw ( "SetTimeZone can only be used on \"zoneless\" times", kXMPErr_BadParam ); - } - - // Create ansi_tt form of the input time. Need the ansi_tm form to make the ansi_tt form. - - ansi_tt ttTime; - ansi_tm tmLocal, tmUTC; - - if ( (xmpTime->year == 0) && (xmpTime->month == 0) && (xmpTime->day == 0) ) { - ansi_tt now = ansi_time(0); - if ( now == -1 ) XMP_Throw ( "Failure from ANSI C time function", kXMPErr_ExternalFailure ); - ansi_localtime ( &now, &tmLocal ); - } else { - if (xmpTime->year < std::numeric_limits::min() + 1900) { - XMP_Throw ( "Invalid year", kXMPErr_BadParam); - } else if (xmpTime->year > std::numeric_limits::max()) { - XMP_Throw ( "Invalid year", kXMPErr_BadParam); - } else { - tmLocal.tm_year = xmpTime->year - 1900; - } - tmLocal.tm_mon = xmpTime->month - 1; - tmLocal.tm_mday = xmpTime->day; - } - - tmLocal.tm_hour = xmpTime->hour; - tmLocal.tm_min = xmpTime->minute; - tmLocal.tm_sec = xmpTime->second; - tmLocal.tm_isdst = -1; // Don't know if daylight time is in effect. - - ttTime = ansi_mktime ( &tmLocal ); - if ( ttTime == -1 ) XMP_Throw ( "Failure from ANSI C mktime function", kXMPErr_ExternalFailure ); - - // Convert back to a localized ansi_tm time and get the corresponding UTC ansi_tm time. - - ansi_localtime ( &ttTime, &tmLocal ); - ansi_gmtime ( &ttTime, &tmUTC ); - - // Get the offset direction and amount. - - ansi_tm tmx = tmLocal; // ! Note that mktime updates the ansi_tm parameter, messing up difftime! - ansi_tm tmy = tmUTC; - tmx.tm_isdst = tmy.tm_isdst = 0; - ansi_tt ttx = ansi_mktime ( &tmx ); - ansi_tt tty = ansi_mktime ( &tmy ); - double diffSecs; - - if ( (ttx != -1) && (tty != -1) ) { - diffSecs = ansi_difftime ( ttx, tty ); - } else { - #if XMP_MacBuild - // Looks like Apple's mktime is buggy - see W1140533. But the offset is visible. - diffSecs = tmLocal.tm_gmtoff; - #else - // Win and UNIX don't have a visible offset. Make sure we know about the failure, - // then try using the current date/time as a close fallback. - ttTime = ansi_time(0); - if ( ttTime == -1 ) XMP_Throw ( "Failure from ANSI C time function", kXMPErr_ExternalFailure ); - ansi_localtime ( &ttTime, &tmx ); - ansi_gmtime ( &ttTime, &tmy ); - tmx.tm_isdst = tmy.tm_isdst = 0; - ttx = ansi_mktime ( &tmx ); - tty = ansi_mktime ( &tmy ); - if ( (ttx == -1) || (tty == -1) ) XMP_Throw ( "Failure from ANSI C mktime function", kXMPErr_ExternalFailure ); - diffSecs = ansi_difftime ( ttx, tty ); - #endif - } - - if ( diffSecs > 0.0 ) { - xmpTime->tzSign = kXMP_TimeEastOfUTC; - } else if ( diffSecs == 0.0 ) { - xmpTime->tzSign = kXMP_TimeIsUTC; - } else { - xmpTime->tzSign = kXMP_TimeWestOfUTC; - diffSecs = -diffSecs; - } - xmpTime->tzHour = XMP_Int32 ( diffSecs / 3600.0 ); - xmpTime->tzMinute = XMP_Int32 ( (diffSecs / 60.0) - (xmpTime->tzHour * 60.0) ); - - // *** Save the tm_isdst flag in a qualifier? - - XMP_Assert ( (0 <= xmpTime->tzHour) && (xmpTime->tzHour <= 23) ); - XMP_Assert ( (0 <= xmpTime->tzMinute) && (xmpTime->tzMinute <= 59) ); - XMP_Assert ( (-1 <= xmpTime->tzSign) && (xmpTime->tzSign <= +1) ); - XMP_Assert ( (xmpTime->tzSign == 0) ? ((xmpTime->tzHour == 0) && (xmpTime->tzMinute == 0)) : - ((xmpTime->tzHour != 0) || (xmpTime->tzMinute != 0)) ); - -} // SetTimeZone - - -// ------------------------------------------------------------------------------------------------- -// ConvertToUTCTime -// ---------------- - -/* class static */ void -XMPUtils::ConvertToUTCTime ( XMP_DateTime * time ) -{ - XMP_Assert ( time != 0 ); // ! Enforced by wrapper. - - XMP_Assert ( (0 <= time->tzHour) && (time->tzHour <= 23) ); - XMP_Assert ( (0 <= time->tzMinute) && (time->tzMinute <= 59) ); - XMP_Assert ( (-1 <= time->tzSign) && (time->tzSign <= +1) ); - XMP_Assert ( (time->tzSign == 0) ? ((time->tzHour == 0) && (time->tzMinute == 0)) : - ((time->tzHour != 0) || (time->tzMinute != 0)) ); - - if ( time->tzSign == kXMP_TimeEastOfUTC ) { - // We are before (east of) GMT, subtract the offset from the time. - time->hour -= time->tzHour; - time->minute -= time->tzMinute; - } else if ( time->tzSign == kXMP_TimeWestOfUTC ) { - // We are behind (west of) GMT, add the offset to the time. - time->hour += time->tzHour; - time->minute += time->tzMinute; - } - - AdjustTimeOverflow ( time ); - time->tzSign = time->tzHour = time->tzMinute = 0; - -} // ConvertToUTCTime - - -// ------------------------------------------------------------------------------------------------- -// ConvertToLocalTime -// ------------------ - -/* class static */ void -XMPUtils::ConvertToLocalTime ( XMP_DateTime * time ) -{ - XMP_Assert ( time != 0 ); // ! Enforced by wrapper. - - XMP_Assert ( (0 <= time->tzHour) && (time->tzHour <= 23) ); - XMP_Assert ( (0 <= time->tzMinute) && (time->tzMinute <= 59) ); - XMP_Assert ( (-1 <= time->tzSign) && (time->tzSign <= +1) ); - XMP_Assert ( (time->tzSign == 0) ? ((time->tzHour == 0) && (time->tzMinute == 0)) : - ((time->tzHour != 0) || (time->tzMinute != 0)) ); - - ConvertToUTCTime ( time ); // The existing time zone might not be the local one. - SetTimeZone ( time ); // Fill in the local timezone offset, then adjust the time. - - if ( time->tzSign > 0 ) { - // We are before (east of) GMT, add the offset to the time. - time->hour += time->tzHour; - time->minute += time->tzMinute; - } else if ( time->tzSign < 0 ) { - // We are behind (west of) GMT, subtract the offset from the time. - time->hour -= time->tzHour; - time->minute -= time->tzMinute; - } - - AdjustTimeOverflow ( time ); - -} // ConvertToLocalTime - - -// ------------------------------------------------------------------------------------------------- -// CompareDateTime -// --------------- - -/* class static */ int -XMPUtils::CompareDateTime ( const XMP_DateTime & _in_left, - const XMP_DateTime & _in_right ) -{ - int result; - - XMP_DateTime left = _in_left; - XMP_DateTime right = _in_right; - - ConvertToUTCTime ( &left ); - ConvertToUTCTime ( &right ); - - // *** We could use memcmp if the XMP_DateTime stuct has no holes. - - if ( left.year < right.year ) { - result = -1; - } else if ( left.year > right.year ) { - result = +1; - } else if ( left.month < right.month ) { - result = -1; - } else if ( left.month > right.month ) { - result = +1; - } else if ( left.day < right.day ) { - result = -1; - } else if ( left.day > right.day ) { - result = +1; - } else if ( left.hour < right.hour ) { - result = -1; - } else if ( left.hour > right.hour ) { - result = +1; - } else if ( left.minute < right.minute ) { - result = -1; - } else if ( left.minute > right.minute ) { - result = +1; - } else if ( left.second < right.second ) { - result = -1; - } else if ( left.second > right.second ) { - result = +1; - } else if ( left.nanoSecond < right.nanoSecond ) { - result = -1; - } else if ( left.nanoSecond > right.nanoSecond ) { - result = +1; - } else { - result = 0; - } - - return result; - -} // CompareDateTime - -// ================================================================================================= diff --git a/xmpsdk/src/XMPUtils.hpp b/xmpsdk/src/XMPUtils.hpp deleted file mode 100644 index e1c7e78d01..0000000000 --- a/xmpsdk/src/XMPUtils.hpp +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef __XMPUtils_hpp__ -#define __XMPUtils_hpp__ - -// ================================================================================================= -// Copyright 2002-2007 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 "XMP_Environment.h" -#include "XMP_Const.h" - -#include "XMPMeta.hpp" -#include "XMPCore_Impl.hpp" -#include "client-glue/WXMPUtils.hpp" - -// ------------------------------------------------------------------------------------------------- - -extern XMP_VarString * sComposedPath; // *** Only really need 1 string. Shrink periodically? -extern XMP_VarString * sConvertedValue; -extern XMP_VarString * sBase64Str; -extern XMP_VarString * sCatenatedItems; -extern XMP_VarString * sStandardXMP; -extern XMP_VarString * sExtendedXMP; -extern XMP_VarString * sExtendedDigest; - -// ------------------------------------------------------------------------------------------------- - -class XMPUtils { -public: - - static bool - Initialize(); // ! For internal use only! - - static void - Terminate() RELEASE_NO_THROW; // ! For internal use only! - - static void - Unlock ( XMP_OptionBits options ); - - // --------------------------------------------------------------------------------------------- - - static void - ComposeArrayItemPath ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_Index itemIndex, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ); - - static void - ComposeStructFieldPath ( XMP_StringPtr schemaNS, - XMP_StringPtr structName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ); - - static void - ComposeQualifierPath ( XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_StringPtr qualNS, - XMP_StringPtr qualName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ); - - static void - ComposeLangSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr langName, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ); - - static void - ComposeFieldSelector ( XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_StringPtr fieldNS, - XMP_StringPtr fieldName, - XMP_StringPtr fieldValue, - XMP_StringPtr * fullPath, - XMP_StringLen * pathSize ); - - // --------------------------------------------------------------------------------------------- - - static void - ConvertFromBool ( bool binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ); - - static void - ConvertFromInt ( XMP_Int32 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ); - - static void - ConvertFromInt64 ( XMP_Int64 binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ); - - static void - ConvertFromFloat ( double binValue, - XMP_StringPtr format, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ); - - static void - ConvertFromDate ( const XMP_DateTime & binValue, - XMP_StringPtr * strValue, - XMP_StringLen * strSize ); - - // --------------------------------------------------------------------------------------------- - - static bool - ConvertToBool ( XMP_StringPtr strValue ); - - static XMP_Int32 - ConvertToInt ( XMP_StringPtr strValue ); - - static XMP_Int64 - ConvertToInt64 ( XMP_StringPtr strValue ); - - static double - ConvertToFloat ( XMP_StringPtr strValue ); - - static void - ConvertToDate ( XMP_StringPtr strValue, - XMP_DateTime * binValue ); - - // --------------------------------------------------------------------------------------------- - - static void - CurrentDateTime ( XMP_DateTime * time ); - - static void - SetTimeZone ( XMP_DateTime * time ); - - static void - ConvertToUTCTime ( XMP_DateTime * time ); - - static void - ConvertToLocalTime ( XMP_DateTime * time ); - - static int - CompareDateTime ( const XMP_DateTime & left, - const XMP_DateTime & right ); - // --------------------------------------------------------------------------------------------- - - static void - EncodeToBase64 ( XMP_StringPtr rawStr, - XMP_StringLen rawLen, - XMP_StringPtr * encodedStr, - XMP_StringLen * encodedLen ); - - static void - DecodeFromBase64 ( XMP_StringPtr encodedStr, - XMP_StringLen encodedLen, - XMP_StringPtr * rawStr, - XMP_StringLen * rawLen ); - - // --------------------------------------------------------------------------------------------- - - static void - PackageForJPEG ( const XMPMeta & xmpObj, - XMP_StringPtr * stdStr, - XMP_StringLen * stdLen, - XMP_StringPtr * extStr, - XMP_StringLen * extLen, - XMP_StringPtr * digestStr, - XMP_StringLen * digestLen ); - - 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_StringPtr * catedStr, - XMP_StringLen * catedLen ); - - static void - SeparateArrayItems ( XMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr arrayName, - XMP_OptionBits options, - XMP_StringPtr catedStr ); - - static void - RemoveProperties ( XMPMeta * xmpObj, - XMP_StringPtr schemaNS, - XMP_StringPtr propName, - XMP_OptionBits options ); - - static void - AppendProperties ( const XMPMeta & source, - XMPMeta * dest, - XMP_OptionBits options ); - - static void - DuplicateSubtree ( const XMPMeta & source, - XMPMeta * dest, - XMP_StringPtr sourceNS, - XMP_StringPtr sourceRoot, - XMP_StringPtr destNS, - XMP_StringPtr destRoot, - XMP_OptionBits options ); - -}; // XMPUtils - -// ================================================================================================= - -#endif // __XMPUtils_hpp__ diff --git a/xmpsdk/src/XMP_BuildInfo.h b/xmpsdk/src/XMP_BuildInfo.h deleted file mode 100644 index 2b387c86fa..0000000000 --- a/xmpsdk/src/XMP_BuildInfo.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __XMP_BuildInfo_h__ -#define __XMP_BuildInfo_h__ 1 - -/* --------------------------------------------------------------------------------------------- */ -/* ** IMPORTANT ** This file must be usable by strict ANSI C compilers. No "//" comments, etc. */ -/* --------------------------------------------------------------------------------------------- */ - -/* -// ================================================================================================= -// Copyright 2002-2008 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 kXMP_Copyright Copyright (c) 2002-2008, Adobe Systems Incorporated -#define kXMP_CopyrightStr "Copyright (c) 2002-2008, Adobe Systems Incorporated" -#define kXMP_AdobeIPStr "" - -#endif /* __XMP_BuildInfo_h__ */ From eda82e0624622552e08106af5776a9e8cf41cd03 Mon Sep 17 00:00:00 2001 From: Sergey Hovakimyan Date: Wed, 10 Jul 2024 12:20:41 +0400 Subject: [PATCH 3/6] adds a hacky workaround to work with MD5 implementation from XMP-Toolkit-sdk --- src/convert.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/convert.cpp b/src/convert.cpp index 626933990d..fa3b05c945 100644 --- a/src/convert.cpp +++ b/src/convert.cpp @@ -1265,7 +1265,7 @@ std::string Converter::computeExifDigest(bool tiff) { continue; DataBuf data(pos->size()); pos->copy(data.data(), littleEndian /* FIXME ? */); - MD5Update(&context, data.c_data(), static_cast(data.size())); + MD5Update(&context, const_cast(data.c_data()), static_cast(data.size())); } } MD5Final(digest, &context); From 06bfdc87bcacfb055af6bbdb1c0eeef6bfcf36e1 Mon Sep 17 00:00:00 2001 From: Sergey Hovakimyan Date: Wed, 10 Jul 2024 12:21:49 +0400 Subject: [PATCH 4/6] adds a workaround to avoid calling DeleteNamespace since XMP-Toolkit-sdk does not like it anymore --- src/xmp.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/xmp.cpp b/src/xmp.cpp index da6e11c0fd..dedbbd4979 100644 --- a/src/xmp.cpp +++ b/src/xmp.cpp @@ -634,8 +634,9 @@ void XmpParser::terminate() { void XmpParser::registerNs(const std::string& ns, const std::string& prefix) { try { initialize(); - AutoLock autoLock(xmpLockFct_, pLockData_); - SXMPMeta::DeleteNamespace(ns.c_str()); + // apparently we can't delete namespaces anymore + // see WXMPMeta.cpp + // SXMPMeta::DeleteNamespace(ns.c_str()); #ifdef EXV_ADOBE_XMPSDK SXMPMeta::RegisterNamespace(ns.c_str(), prefix.c_str(), nullptr); #else From 720a1e0db854022fe8befd9f2fc233dae321a8b5 Mon Sep 17 00:00:00 2001 From: Sergey Hovakimyan Date: Wed, 10 Jul 2024 13:14:31 +0400 Subject: [PATCH 5/6] adds submodules cloning for github actions --- .../workflows/nightly_Linux_distributions.yml | 2 ++ .github/workflows/on_PR_linux_matrix.yml | 2 ++ .github/workflows/on_PR_linux_special_builds.yml | 9 +++++++++ .github/workflows/on_PR_linux_staticAnalysis.yml | 1 + .github/workflows/on_PR_mac_matrix.yml | 2 ++ .github/workflows/on_PR_mac_special_builds.yml | 2 ++ .github/workflows/on_PR_meson.yaml | 16 ++++++++++++++++ .github/workflows/on_PR_windows_matrix.yml | 6 ++++++ .github/workflows/on_push_BasicWinLinMac.yml | 6 ++++++ .github/workflows/on_push_ExtraJobsForMain.yml | 2 ++ .github/workflows/on_push_clang_format.yml | 2 ++ .github/workflows/release.yml | 6 ++++++ 12 files changed, 56 insertions(+) diff --git a/.github/workflows/nightly_Linux_distributions.yml b/.github/workflows/nightly_Linux_distributions.yml index 0f1ae1c978..eb2dc3917f 100644 --- a/.github/workflows/nightly_Linux_distributions.yml +++ b/.github/workflows/nightly_Linux_distributions.yml @@ -34,6 +34,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: ./ci/install_dependencies.sh - name: Build and install diff --git a/.github/workflows/on_PR_linux_matrix.yml b/.github/workflows/on_PR_linux_matrix.yml index 1cffe14d59..96cd49394b 100644 --- a/.github/workflows/on_PR_linux_matrix.yml +++ b/.github/workflows/on_PR_linux_matrix.yml @@ -22,6 +22,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | diff --git a/.github/workflows/on_PR_linux_special_builds.yml b/.github/workflows/on_PR_linux_special_builds.yml index 64d9864d85..566b99c3a2 100644 --- a/.github/workflows/on_PR_linux_special_builds.yml +++ b/.github/workflows/on_PR_linux_special_builds.yml @@ -18,6 +18,7 @@ jobs: steps: - uses: actions/checkout@v4 with: + submodules: true fetch-depth: 2 # Trying to deal with warning: -> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0 @@ -65,6 +66,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | @@ -100,6 +103,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | @@ -134,6 +139,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | @@ -156,6 +163,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | diff --git a/.github/workflows/on_PR_linux_staticAnalysis.yml b/.github/workflows/on_PR_linux_staticAnalysis.yml index fa77859c9a..0c71e2682f 100644 --- a/.github/workflows/on_PR_linux_staticAnalysis.yml +++ b/.github/workflows/on_PR_linux_staticAnalysis.yml @@ -18,6 +18,7 @@ jobs: steps: - uses: actions/checkout@v4 with: + submodules: true fetch-depth: 2 # Trying to deal with warning: -> Issue detecting commit SHA. Please run actions/checkout with fetch-depth > 1 or set to 0 diff --git a/.github/workflows/on_PR_mac_matrix.yml b/.github/workflows/on_PR_mac_matrix.yml index ef5d2286d7..d1bcb0d4ba 100644 --- a/.github/workflows/on_PR_mac_matrix.yml +++ b/.github/workflows/on_PR_mac_matrix.yml @@ -22,6 +22,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | diff --git a/.github/workflows/on_PR_mac_special_builds.yml b/.github/workflows/on_PR_mac_special_builds.yml index f03bf0b02c..2461acf2c5 100644 --- a/.github/workflows/on_PR_mac_special_builds.yml +++ b/.github/workflows/on_PR_mac_special_builds.yml @@ -17,6 +17,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | diff --git a/.github/workflows/on_PR_meson.yaml b/.github/workflows/on_PR_meson.yaml index d859195d12..71bd7fcf69 100644 --- a/.github/workflows/on_PR_meson.yaml +++ b/.github/workflows/on_PR_meson.yaml @@ -16,6 +16,8 @@ jobs: deps: ['forcefallback', 'default'] steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: egor-tensin/setup-gcc@v1 with: version: ${{matrix.cxx}} @@ -35,6 +37,8 @@ jobs: deps: ['forcefallback', 'default'] steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: egor-tensin/setup-clang@v1 with: version: ${{matrix.cxx}} @@ -58,6 +62,8 @@ jobs: platform: ['x64', 'x86'] steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install packages run: | @@ -80,6 +86,8 @@ jobs: deps: ['forcefallback', 'default'] steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install packages run: | @@ -107,6 +115,8 @@ jobs: shell: msys2 {0} steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: msys2/setup-msys2@v2 with: @@ -134,6 +144,8 @@ jobs: deps: ['enabled', 'disabled'] steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install packages run: | @@ -148,6 +160,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: vmactions/freebsd-vm@v1 with: prepare: | @@ -160,6 +174,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install packages run: | python3 -m pip install meson ninja diff --git a/.github/workflows/on_PR_windows_matrix.yml b/.github/workflows/on_PR_windows_matrix.yml index ebdee20809..93c9727d90 100644 --- a/.github/workflows/on_PR_windows_matrix.yml +++ b/.github/workflows/on_PR_windows_matrix.yml @@ -30,6 +30,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Set up Visual Studio shell uses: ilammy/msvc-dev-cmd@v1 @@ -94,6 +96,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Set up MSYS2 uses: msys2/setup-msys2@v2 @@ -150,6 +154,8 @@ jobs: - run: git config --global core.autocrlf input shell: pwsh - uses: actions/checkout@v4 + with: + submodules: true - name: Set up Cygwin uses: cygwin/cygwin-install-action@v4 diff --git a/.github/workflows/on_push_BasicWinLinMac.yml b/.github/workflows/on_push_BasicWinLinMac.yml index 533cb614de..447a83a2ba 100644 --- a/.github/workflows/on_push_BasicWinLinMac.yml +++ b/.github/workflows/on_push_BasicWinLinMac.yml @@ -21,6 +21,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Set up Visual Studio shell uses: ilammy/msvc-dev-cmd@v1 @@ -57,6 +59,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | @@ -91,6 +95,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | diff --git a/.github/workflows/on_push_ExtraJobsForMain.yml b/.github/workflows/on_push_ExtraJobsForMain.yml index a40a9ff4bd..8145e6e67a 100644 --- a/.github/workflows/on_push_ExtraJobsForMain.yml +++ b/.github/workflows/on_push_ExtraJobsForMain.yml @@ -21,6 +21,8 @@ jobs: steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | diff --git a/.github/workflows/on_push_clang_format.yml b/.github/workflows/on_push_clang_format.yml index 3516d6804d..858ecd02d0 100644 --- a/.github/workflows/on_push_clang_format.yml +++ b/.github/workflows/on_push_clang_format.yml @@ -8,6 +8,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - uses: DoozyX/clang-format-lint-action@v0.17 with: source: '.' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 375bae91d7..596d84805e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,6 +21,8 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | @@ -58,6 +60,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Install dependencies run: | @@ -96,6 +100,8 @@ jobs: runs-on: windows-2022 steps: - uses: actions/checkout@v4 + with: + submodules: true - name: Set up Visual Studio shell uses: ilammy/msvc-dev-cmd@v1 From a3284aa445689d0da0c09753efd1d02845139967 Mon Sep 17 00:00:00 2001 From: Sergey Hovakimyan Date: Thu, 11 Jul 2024 19:33:42 +0400 Subject: [PATCH 6/6] fixes xmp encoding of multiple items with same lang for langAlt type properties --- src/xmp.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/xmp.cpp b/src/xmp.cpp index dedbbd4979..251514949b 100644 --- a/src/xmp.cpp +++ b/src/xmp.cpp @@ -839,13 +839,36 @@ int XmpParser::encode(std::string& xmpPacket, const XmpData& xmpData, uint16_t f if (!la) throw Error(ErrorCode::kerEncodeLangAltPropertyFailed, xmp.key()); - int idx = 1; for (const auto& [lang, specs] : la->value_) { if (!specs.empty()) { // remove lang specs with no value printNode(ns, xmp.tagName(), specs, 0); - meta.AppendArrayItem(ns.c_str(), xmp.tagName().c_str(), kXMP_PropArrayIsAlternate, specs.c_str()); - const std::string item = xmp.tagName() + "[" + toString(idx++) + "]"; - meta.SetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", lang.c_str()); + + // check if there is an item in the array with given lang + // I am sure this can be rewritten in a more optimal fashion + std::size_t item_cnt = meta.CountArrayItems(ns.c_str(), xmp.tagName().c_str()); + std::size_t existing_item_idx = 0; // 0 means it does not exist + for (std::size_t i = 1; i <= item_cnt; ++i) { + std::string qualifier_value; + XMP_OptionBits qualifier_options; + + const std::string item = xmp.tagName() + "[" + toString(i) + "]"; + + auto found = meta.GetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", &qualifier_value, + &qualifier_options); + if (found and qualifier_value == lang) { + existing_item_idx = i; + break; + } + } + + if (existing_item_idx) { + meta.SetArrayItem(ns.c_str(), xmp.tagName().c_str(), existing_item_idx, specs.c_str()); + } else { + meta.AppendArrayItem(ns.c_str(), xmp.tagName().c_str(), kXMP_PropArrayIsAlternate, specs.c_str()); + auto index = meta.CountArrayItems(ns.c_str(), xmp.tagName().c_str()); + const std::string item = xmp.tagName() + "[" + toString(index) + "]"; + meta.SetQualifier(ns.c_str(), item.c_str(), kXMP_NS_XML, "lang", lang.c_str()); + } } } continue;