|
Packit Service |
21b5d1 |
// ================================================================================================= // Copyright 2002-2008 Adobe Systems Incorporated
|
|
Packit Service |
21b5d1 |
// All Rights Reserved.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
|
|
Packit Service |
21b5d1 |
// of the Adobe license agreement accompanying it.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Adobe patent application tracking #P435, entitled 'Unique markers to simplify embedding data of
|
|
Packit Service |
21b5d1 |
// one format in a file with a different format', inventors: Sean Parent, Greg Gilley.
|
|
Packit Service |
21b5d1 |
// =================================================================================================
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#include "XMP_Environment.h" // ! This must be the first include!
|
|
Packit Service |
21b5d1 |
#include "XMPCore_Impl.hpp"
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#include "XMPMeta.hpp"
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#include "XMP_Version.h"
|
|
Packit Service |
21b5d1 |
#include "UnicodeInlines.incl_cpp"
|
|
Packit Service |
21b5d1 |
#include "UnicodeConversions.hpp"
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#if XMP_DebugBuild
|
|
Packit Service |
21b5d1 |
#include <iostream>
|
|
Packit Service |
21b5d1 |
#endif
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
using namespace std;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#if XMP_WinBuild
|
|
Packit Service |
21b5d1 |
#ifdef _MSC_VER
|
|
Packit Service |
21b5d1 |
#pragma warning ( disable : 4533 ) // initialization of '...' is skipped by 'goto ...'
|
|
Packit Service |
21b5d1 |
#pragma warning ( disable : 4702 ) // unreachable code
|
|
Packit Service |
21b5d1 |
#pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning)
|
|
Packit Service |
21b5d1 |
#endif
|
|
Packit Service |
21b5d1 |
#endif
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros
|
|
Packit Service |
21b5d1 |
// *** Add debug codegen checks, e.g. that typical masking operations really work
|
|
Packit Service |
21b5d1 |
// *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// =================================================================================================
|
|
Packit Service |
21b5d1 |
// Local Types and Constants
|
|
Packit Service |
21b5d1 |
// =========================
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kPacketHeader = "";
|
|
Packit Service |
21b5d1 |
static const char * kPacketTrailer = ""; // ! The w/r is at [size-4].
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_XMPMetaStart = "
|
|
Packit Service |
21b5d1 |
static const char * kRDF_XMPMetaEnd = "</x:xmpmeta>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_RDFStart = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">";
|
|
Packit Service |
21b5d1 |
static const char * kRDF_RDFEnd = "</rdf:RDF>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_SchemaStart = "
|
|
Packit Service |
21b5d1 |
static const char * kRDF_SchemaEnd = "</rdf:Description>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_StructStart = "<rdf:Description>";
|
|
Packit Service |
21b5d1 |
static const char * kRDF_StructEnd = "</rdf:Description>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_BagStart = "<rdf:Bag>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_ItemStart = "<rdf:li>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static const char * kRDF_ValueStart = "<rdf:value>";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// =================================================================================================
|
|
Packit Service |
21b5d1 |
// Static Variables
|
|
Packit Service |
21b5d1 |
// ================
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// =================================================================================================
|
|
Packit Service |
21b5d1 |
// Local Utilities
|
|
Packit Service |
21b5d1 |
// ===============
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// EstimateRDFSize
|
|
Packit Service |
21b5d1 |
// ---------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// *** Pull the strlen(kXyz) calls into constants.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static size_t
|
|
Packit Service |
21b5d1 |
EstimateRDFSize ( const XMP_Node * currNode, XMP_Index indent, size_t indentLen )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
size_t outputLen = 2 * (indent*indentLen + currNode->name.size() + 4); // The property element tags.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( ! currNode->qualifiers.empty() ) {
|
|
Packit Service |
21b5d1 |
// This node has qualifiers, assume it is written using rdf:value and estimate the qualifiers.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
indent += 2; // Everything else is indented inside the rdf:Description element.
|
|
Packit Service |
21b5d1 |
outputLen += 2 * ((indent-1)*indentLen + strlen(kRDF_StructStart) + 2); // The rdf:Description tags.
|
|
Packit Service |
21b5d1 |
outputLen += 2 * (indent*indentLen + strlen(kRDF_ValueStart) + 2); // The rdf:value tags.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currQual = currNode->qualifiers[qualNum];
|
|
Packit Service |
21b5d1 |
outputLen += EstimateRDFSize ( currQual, indent, indentLen );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( currNode->options & kXMP_PropValueIsStruct ) {
|
|
Packit Service |
21b5d1 |
indent += 1;
|
|
Packit Service |
21b5d1 |
outputLen += 2 * (indent*indentLen + strlen(kRDF_StructStart) + 2); // The rdf:Description tags.
|
|
Packit Service |
21b5d1 |
} else if ( currNode->options & kXMP_PropValueIsArray ) {
|
|
Packit Service |
21b5d1 |
indent += 2;
|
|
Packit Service |
21b5d1 |
outputLen += 2 * ((indent-1)*indentLen + strlen(kRDF_BagStart) + 2); // The rdf:Bag/Seq/Alt tags.
|
|
Packit Service |
21b5d1 |
outputLen += 2 * currNode->children.size() * (strlen(kRDF_ItemStart) + 2); // The rdf:li tags, indent counted in children.
|
|
Packit Service |
21b5d1 |
} else if ( ! (currNode->options & kXMP_SchemaNode) ) {
|
|
Packit Service |
21b5d1 |
outputLen += currNode->value.size(); // This is a leaf value node.
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currChild = currNode->children[childNum];
|
|
Packit Service |
21b5d1 |
outputLen += EstimateRDFSize ( currChild, indent+1, indentLen );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return outputLen;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // EstimateRDFSize
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// DeclareOneNamespace
|
|
Packit Service |
21b5d1 |
// -------------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
DeclareOneNamespace ( const XMP_VarString & nsPrefix,
|
|
Packit Service |
21b5d1 |
const XMP_VarString & nsURI,
|
|
Packit Service |
21b5d1 |
XMP_VarString & usedNS, // ! A catenation of the prefixes with colons.
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
size_t nsPos = usedNS.find ( nsPrefix );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( nsPos == XMP_VarString::npos ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
for ( ; indent > 0; --indent ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += "xmlns:";
|
|
Packit Service |
21b5d1 |
outputStr += nsPrefix;
|
|
Packit Service |
21b5d1 |
outputStr[outputStr.size()-1] = '='; // Change the colon to =.
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
outputStr += nsURI;
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
usedNS += nsPrefix;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // DeclareOneNamespace
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// DeclareElemNamespace
|
|
Packit Service |
21b5d1 |
// --------------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
DeclareElemNamespace ( const XMP_VarString & elemName,
|
|
Packit Service |
21b5d1 |
XMP_VarString & usedNS,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
size_t colonPos = elemName.find ( ':' );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( colonPos != XMP_VarString::npos ) {
|
|
Packit Service |
21b5d1 |
XMP_VarString nsPrefix ( elemName.substr ( 0, colonPos+1 ) );
|
|
Packit Service |
21b5d1 |
XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix );
|
|
Packit Service |
21b5d1 |
XMP_Enforce ( prefixPos != sNamespacePrefixToURIMap->end() );
|
|
Packit Service |
21b5d1 |
DeclareOneNamespace ( nsPrefix, prefixPos->second, usedNS, outputStr, newline, indentStr, indent );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // DeclareElemNamespace
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// DeclareUsedNamespaces
|
|
Packit Service |
21b5d1 |
// ---------------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ??? Should iterators be passed by reference to avoid temp copies?
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
DeclareUsedNamespaces ( const XMP_Node * currNode,
|
|
Packit Service |
21b5d1 |
XMP_VarString & usedNS,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( currNode->options & kXMP_SchemaNode ) {
|
|
Packit Service |
21b5d1 |
// The schema node name is the URI, the value is the prefix.
|
|
Packit Service |
21b5d1 |
DeclareOneNamespace ( currNode->value, currNode->name, usedNS, outputStr, newline, indentStr, indent );
|
|
Packit Service |
21b5d1 |
} else if ( currNode->options & kXMP_PropValueIsStruct ) {
|
|
Packit Service |
21b5d1 |
for ( size_t fieldNum = 0, fieldLim = currNode->children.size(); fieldNum < fieldLim; ++fieldNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currField = currNode->children[fieldNum];
|
|
Packit Service |
21b5d1 |
DeclareElemNamespace ( currField->name, usedNS, outputStr, newline, indentStr, indent );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currChild = currNode->children[childNum];
|
|
Packit Service |
21b5d1 |
DeclareUsedNamespaces ( currChild, usedNS, outputStr, newline, indentStr, indent );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currQual = currNode->qualifiers[qualNum];
|
|
Packit Service |
21b5d1 |
DeclareElemNamespace ( currQual->name, usedNS, outputStr, newline, indentStr, indent );
|
|
Packit Service |
21b5d1 |
DeclareUsedNamespaces ( currQual, usedNS, outputStr, newline, indentStr, indent );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // DeclareUsedNamespaces
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// EmitRDFArrayTag
|
|
Packit Service |
21b5d1 |
// ---------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ??? Should iterators be passed by reference to avoid temp copies?
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
enum {
|
|
Packit Service |
21b5d1 |
kIsStartTag = true,
|
|
Packit Service |
21b5d1 |
kIsEndTag = false
|
|
Packit Service |
21b5d1 |
};
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
EmitRDFArrayTag ( XMP_OptionBits arrayForm,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent,
|
|
Packit Service |
21b5d1 |
XMP_Index arraySize,
|
|
Packit Service |
21b5d1 |
bool isStartTag )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
if ( (! isStartTag) && (arraySize == 0) ) return;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( XMP_Index level = indent; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
if ( isStartTag ) {
|
|
Packit Service |
21b5d1 |
outputStr += "
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
outputStr += "
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( arrayForm & kXMP_PropArrayIsAlternate ) {
|
|
Packit Service |
21b5d1 |
outputStr += "Alt";
|
|
Packit Service |
21b5d1 |
} else if ( arrayForm & kXMP_PropArrayIsOrdered ) {
|
|
Packit Service |
21b5d1 |
outputStr += "Seq";
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
outputStr += "Bag";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( isStartTag && (arraySize == 0) ) outputStr += '/';
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // EmitRDFArrayTag
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// AppendNodeValue
|
|
Packit Service |
21b5d1 |
// ---------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Append a property or qualifier value to the output with appropriate XML escaping. The escaped
|
|
Packit Service |
21b5d1 |
// characters for elements and attributes are '&', '<', '>', and ASCII controls (tab, LF, CR). In
|
|
Packit Service |
21b5d1 |
// addition, '"' is escaped for attributes. For efficiency, this is done in a double loop. The outer
|
|
Packit Service |
21b5d1 |
// loop makes sure the whole value is processed. The inner loop does a contiguous unescaped run
|
|
Packit Service |
21b5d1 |
// followed by one escaped character (if we're not at the end).
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// We depend on parsing and SetProperty logic to make sure there are no invalid ASCII controls in
|
|
Packit Service |
21b5d1 |
// the XMP values. The XML spec only allows tab, LF, and CR. Others are not even allowed as
|
|
Packit Service |
21b5d1 |
// numeric escape sequences.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
enum {
|
|
Packit Service |
21b5d1 |
kForAttribute = true,
|
|
Packit Service |
21b5d1 |
kForElement = false
|
|
Packit Service |
21b5d1 |
};
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( XMP_VarString & outputStr, const XMP_VarString & value, bool forAttribute )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
unsigned char * runStart = (unsigned char *) value.c_str();
|
|
Packit Service |
21b5d1 |
unsigned char * runLimit = runStart + value.size();
|
|
Packit Service |
21b5d1 |
unsigned char * runEnd;
|
|
Packit Service |
21b5d1 |
unsigned char ch=0;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
while ( runStart < runLimit ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( runEnd = runStart; runEnd < runLimit; ++runEnd ) {
|
|
Packit Service |
21b5d1 |
ch = *runEnd;
|
|
Packit Service |
21b5d1 |
if ( forAttribute && (ch == '"') ) break;
|
|
Packit Service |
21b5d1 |
if ( (ch < 0x20) || (ch == '&') || (ch == '<') || (ch == '>') ) break;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr.append ( (char *) runStart, (runEnd - runStart) );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( runEnd < runLimit ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( ch < 0x20 ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_Assert ( (ch == kTab) || (ch == kLF) || (ch == kCR) );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
char hexBuf[16];
|
|
Packit Service |
21b5d1 |
memcpy ( hexBuf, ";", 5 );
|
|
Packit Service |
21b5d1 |
hexBuf[3] = kHexDigits[ch&0xF];
|
|
Packit Service |
21b5d1 |
outputStr.append ( hexBuf, 5 );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( ch == '"' ) {
|
|
Packit Service |
21b5d1 |
outputStr += """;
|
|
Packit Service |
21b5d1 |
} else if ( ch == '<' ) {
|
|
Packit Service |
21b5d1 |
outputStr += "<";
|
|
Packit Service |
21b5d1 |
} else if ( ch == '>' ) {
|
|
Packit Service |
21b5d1 |
outputStr += ">";
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
XMP_Assert ( ch == '&' );
|
|
Packit Service |
21b5d1 |
outputStr += "&";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
++runEnd;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
runStart = runEnd;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // AppendNodeValue
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// CanBeRDFAttrProp
|
|
Packit Service |
21b5d1 |
// ----------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static bool
|
|
Packit Service |
21b5d1 |
CanBeRDFAttrProp ( const XMP_Node * propNode )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( propNode->name[0] == '[' ) return false;
|
|
Packit Service |
21b5d1 |
if ( ! propNode->qualifiers.empty() ) return false;
|
|
Packit Service |
21b5d1 |
if ( propNode->options & kXMP_PropValueIsURI ) return false;
|
|
Packit Service |
21b5d1 |
if ( propNode->options & kXMP_PropCompositeMask ) return false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return true;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // CanBeRDFAttrProp
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// IsRDFAttrQualifier
|
|
Packit Service |
21b5d1 |
// ------------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static XMP_StringPtr sAttrQualifiers[] = { "xml:lang", "rdf:resource", "rdf:ID", "rdf:bagID", "rdf:nodeID", "" };
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static bool
|
|
Packit Service |
21b5d1 |
IsRDFAttrQualifier ( XMP_VarString qualName )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t i = 0; *sAttrQualifiers[i] != 0; ++i ) {
|
|
Packit Service |
21b5d1 |
if ( qualName == sAttrQualifiers[i] ) return true;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // IsRDFAttrQualifier
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializePrettyRDFProperty
|
|
Packit Service |
21b5d1 |
// --------------------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Recursively handles the "value" for a node. It does not matter if it is a top level property, a
|
|
Packit Service |
21b5d1 |
// field of a struct, or an item of an array. The indent is that for the property element. An
|
|
Packit Service |
21b5d1 |
// xml:lang qualifier is written as an attribute of the property start tag, not by itself forcing
|
|
Packit Service |
21b5d1 |
// the qualified property form. The patterns below mostly ignore attribute qualifiers like xml:lang.
|
|
Packit Service |
21b5d1 |
// Except for the one struct case, attribute qualifiers don't affect the output form.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:UnqualifiedSimpleProperty>value</ns:UnqualifiedSimpleProperty>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:UnqualifiedStructProperty rdf:parseType="Resource"> (If no rdf:resource qualifier)
|
|
Packit Service |
21b5d1 |
// ... Fields, same forms as top level properties
|
|
Packit Service |
21b5d1 |
// </ns:UnqualifiedStructProperty>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// ... Fields as attributes
|
|
Packit Service |
21b5d1 |
// >
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:UnqualifiedArrayProperty>
|
|
Packit Service |
21b5d1 |
// <rdf:Bag> or Seq or Alt
|
|
Packit Service |
21b5d1 |
// ... Array items as rdf:li elements, same forms as top level properties
|
|
Packit Service |
21b5d1 |
// </rdf:Bag>
|
|
Packit Service |
21b5d1 |
// </ns:UnqualifiedArrayProperty>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:QualifiedProperty rdf:parseType="Resource">
|
|
Packit Service |
21b5d1 |
// <rdf:value> ... Property "value" following the unqualified forms ... </rdf:value>
|
|
Packit Service |
21b5d1 |
// ... Qualifiers looking like named struct fields
|
|
Packit Service |
21b5d1 |
// </ns:QualifiedProperty>
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( const XMP_Node * propNode,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent,
|
|
Packit Service |
21b5d1 |
bool emitAsRDFValue = false )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
XMP_Index level;
|
|
Packit Service |
21b5d1 |
bool emitEndTag = true;
|
|
Packit Service |
21b5d1 |
bool indentEndTag = true;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_OptionBits propForm = propNode->options & kXMP_PropCompositeMask;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// Determine the XML element name. Open the start tag with the name and attribute qualifiers.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_StringPtr elemName = propNode->name.c_str();
|
|
Packit Service |
21b5d1 |
if ( emitAsRDFValue ) {
|
|
Packit Service |
21b5d1 |
elemName= "rdf:value";
|
|
Packit Service |
21b5d1 |
} else if ( *elemName == '[' ) {
|
|
Packit Service |
21b5d1 |
elemName = "rdf:li";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( level = indent; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += '<';
|
|
Packit Service |
21b5d1 |
outputStr += elemName;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#define isCompact false
|
|
Packit Service |
21b5d1 |
bool hasGeneralQualifiers = isCompact; // Might also become true later.
|
|
Packit Service |
21b5d1 |
bool hasRDFResourceQual = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currQual = propNode->qualifiers[qualNum];
|
|
Packit Service |
21b5d1 |
if ( ! IsRDFAttrQualifier ( currQual->name ) ) {
|
|
Packit Service |
21b5d1 |
hasGeneralQualifiers = true;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
if ( currQual->name == "rdf:resource" ) hasRDFResourceQual = true;
|
|
Packit Service |
21b5d1 |
if ( ! emitAsRDFValue ) {
|
|
Packit Service |
21b5d1 |
outputStr += ' ';
|
|
Packit Service |
21b5d1 |
outputStr += currQual->name;
|
|
Packit Service |
21b5d1 |
outputStr += "=\"";
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, currQual->value, kForAttribute );
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// --------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// Process the property according to the standard patterns.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( hasGeneralQualifiers && (! emitAsRDFValue) ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -----------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// This node has general, non-attribute, qualifiers. Emit using the qualified property form.
|
|
Packit Service |
21b5d1 |
// ! The value is output by a recursive call ON THE SAME NODE with emitAsRDFValue set.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( hasRDFResourceQual ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Can't mix rdf:resource and general qualifiers", kXMPErr_BadRDF );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:parseType=\"Resource\">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currQual = propNode->qualifiers[qualNum];
|
|
Packit Service |
21b5d1 |
if ( IsRDFAttrQualifier ( currQual->name ) ) continue;
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( currQual, outputStr, newline, indentStr, indent+1 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// --------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// This node has no general qualifiers. Emit using an unqualified form.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( propForm == 0 ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// --------------------------
|
|
Packit Service |
21b5d1 |
// This is a simple property.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( propNode->options & kXMP_PropValueIsURI ) {
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:resource=\"";
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, propNode->value, kForAttribute );
|
|
Packit Service |
21b5d1 |
outputStr += "\"/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
} else if ( propNode->value.empty() ) {
|
|
Packit Service |
21b5d1 |
outputStr += "/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, propNode->value, kForElement );
|
|
Packit Service |
21b5d1 |
indentEndTag = false;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else if ( propForm & kXMP_PropValueIsArray ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// This is an array.
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsStartTag );
|
|
Packit Service |
21b5d1 |
if ( XMP_ArrayIsAltText(propNode->options) ) NormalizeLangArray ( (XMP_Node*)propNode );
|
|
Packit Service |
21b5d1 |
for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currChild = propNode->children[childNum];
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( currChild, outputStr, newline, indentStr, indent+2 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else if ( ! hasRDFResourceQual ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// This is a "normal" struct, use the rdf:parseType="Resource" form.
|
|
Packit Service |
21b5d1 |
XMP_Assert ( propForm & kXMP_PropValueIsStruct );
|
|
Packit Service |
21b5d1 |
if ( propNode->children.size() == 0 ) {
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:parseType=\"Resource\"/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:parseType=\"Resource\">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currChild = propNode->children[childNum];
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( currChild, outputStr, newline, indentStr, indent+1 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// This is a struct with an rdf:resource attribute, use the "empty property element" form.
|
|
Packit Service |
21b5d1 |
XMP_Assert ( propForm & kXMP_PropValueIsStruct );
|
|
Packit Service |
21b5d1 |
for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currChild = propNode->children[childNum];
|
|
Packit Service |
21b5d1 |
if ( ! CanBeRDFAttrProp ( currChild ) ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Can't mix rdf:resource and complex fields", kXMPErr_BadRDF );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
for ( level = indent+1; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += ' ';
|
|
Packit Service |
21b5d1 |
outputStr += currChild->name;
|
|
Packit Service |
21b5d1 |
outputStr += "=\"";
|
|
Packit Service |
21b5d1 |
outputStr += currChild->value;
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
outputStr += "/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ----------------------------------
|
|
Packit Service |
21b5d1 |
// Emit the property element end tag.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( emitEndTag ) {
|
|
Packit Service |
21b5d1 |
if ( indentEndTag ) for ( level = indent; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += "</";
|
|
Packit Service |
21b5d1 |
outputStr += elemName;
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializePrettyRDFProperty
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializePrettyRDFSchema
|
|
Packit Service |
21b5d1 |
// ------------------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Each schema's properties are written in a separate rdf:Description element. All of the necessary
|
|
Packit Service |
21b5d1 |
// namespaces are declared in the rdf:Description element. The baseIndent is the base level for the
|
|
Packit Service |
21b5d1 |
// entire serialization, that of the x:xmpmeta element. An xml:lang qualifier is written as an
|
|
Packit Service |
21b5d1 |
// attribute of the property start tag, not by itself forcing the qualified property form.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// xmlns:ns="URI" ... >
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// ... The actual properties of the schema, see SerializePrettyRDFProperty
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// ... If alias comments are wanted
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// </rdf:Description>
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFSchema ( const XMP_VarString & treeName,
|
|
Packit Service |
21b5d1 |
const XMP_Node * schemaNode,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_OptionBits options,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index baseIndent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
XMP_Assert ( schemaNode->options & kXMP_SchemaNode );
|
|
Packit Service |
21b5d1 |
XMP_Assert ( schemaNode->qualifiers.empty() );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the rdf:Description start tag with the namespace declarations.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_Index level;
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += kRDF_SchemaStart;
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
outputStr += treeName;
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t totalLen = 8; // Start at 8 for "xml:rdf:".
|
|
Packit Service |
21b5d1 |
XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin();
|
|
Packit Service |
21b5d1 |
XMP_cStringMapPos endPos = sNamespacePrefixToURIMap->end();
|
|
Packit Service |
21b5d1 |
for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_VarString usedNS;
|
|
Packit Service |
21b5d1 |
usedNS.reserve ( totalLen );
|
|
Packit Service |
21b5d1 |
usedNS = "xml:rdf:";
|
|
Packit Service |
21b5d1 |
DeclareUsedNamespaces ( schemaNode, usedNS, outputStr, newline, indentStr, baseIndent+4 );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += ">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write alias comments, if wanted.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_WriteAliasComments ) { // *** Hoist into a routine, used for Plain XMP also.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#if 0 // *** Buggy, disable for now.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_cAliasMapPos aliasPos = sRegisteredAliasMap->begin();
|
|
Packit Service |
21b5d1 |
XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( ; aliasPos != aliasEnd; ++aliasPos ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t nsPos = aliasPos->first.find ( schemaNode->value );
|
|
Packit Service |
21b5d1 |
if ( nsPos == XMP_VarString::npos ) continue;
|
|
Packit Service |
21b5d1 |
XMP_Assert ( nsPos == 0 );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+3; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += "
|
|
Packit Service |
21b5d1 |
outputStr += aliasPos->first;
|
|
Packit Service |
21b5d1 |
outputStr += " is aliased to ";
|
|
Packit Service |
21b5d1 |
for ( size_t step = 1, stepLim = aliasPos->second.size(); step != stepLim; ++step ) {
|
|
Packit Service |
21b5d1 |
outputStr += aliasPos->second[step].step;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
outputStr += " -->";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#endif
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write each of the schema's actual properties.
|
|
Packit Service |
21b5d1 |
for ( size_t propNum = 0, propLim = schemaNode->children.size(); propNum < propLim; ++propNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currProp = schemaNode->children[propNum];
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( currProp, outputStr, newline, indentStr, baseIndent+3 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the rdf:Description end tag.
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += kRDF_SchemaEnd;
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializePrettyRDFSchema
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializeCompactRDFAttrProps
|
|
Packit Service |
21b5d1 |
// ----------------------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Write each of the parent's simple unqualified properties as an attribute. Returns true if all
|
|
Packit Service |
21b5d1 |
// of the properties are written as attributes.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static bool
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFAttrProps ( const XMP_Node * parentNode,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
size_t prop, propLim;
|
|
Packit Service |
21b5d1 |
bool allAreAttrs = true;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( prop = 0, propLim = parentNode->children.size(); prop != propLim; ++prop ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const XMP_Node * currProp = parentNode->children[prop];
|
|
Packit Service |
21b5d1 |
if ( ! CanBeRDFAttrProp ( currProp ) ) {
|
|
Packit Service |
21b5d1 |
allAreAttrs = false;
|
|
Packit Service |
21b5d1 |
continue;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
for ( XMP_Index level = indent; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += currProp->name;
|
|
Packit Service |
21b5d1 |
outputStr += "=\"";
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, currProp->value, kForAttribute );
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return allAreAttrs;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializeCompactRDFAttrProps
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializeCompactRDFElemProps
|
|
Packit Service |
21b5d1 |
// ----------------------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Recursively handles the "value" for a node that must be written as an RDF property element. It
|
|
Packit Service |
21b5d1 |
// does not matter if it is a top level property, a field of a struct, or an item of an array. The
|
|
Packit Service |
21b5d1 |
// indent is that for the property element. The patterns bwlow ignore attribute qualifiers such as
|
|
Packit Service |
21b5d1 |
// xml:lang, they don't affect the output form.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// ... The fields as attributes, if all are simple and unqualified
|
|
Packit Service |
21b5d1 |
// />
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:UnqualifiedStructProperty-2 rdf:parseType="Resource">
|
|
Packit Service |
21b5d1 |
// ... The fields as elements, if none are simple and unqualified
|
|
Packit Service |
21b5d1 |
// </ns:UnqualifiedStructProperty-2>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:UnqualifiedStructProperty-3>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// ... The simple and unqualified fields as attributes
|
|
Packit Service |
21b5d1 |
// >
|
|
Packit Service |
21b5d1 |
// ... The compound or qualified fields as elements
|
|
Packit Service |
21b5d1 |
// </rdf:Description>
|
|
Packit Service |
21b5d1 |
// </ns:UnqualifiedStructProperty-3>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:UnqualifiedArrayProperty>
|
|
Packit Service |
21b5d1 |
// <rdf:Bag> or Seq or Alt
|
|
Packit Service |
21b5d1 |
// ... Array items as rdf:li elements, same forms as top level properties
|
|
Packit Service |
21b5d1 |
// </rdf:Bag>
|
|
Packit Service |
21b5d1 |
// </ns:UnqualifiedArrayProperty>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <ns:QualifiedProperty rdf:parseType="Resource">
|
|
Packit Service |
21b5d1 |
// <rdf:value> ... Property "value" following the unqualified forms ... </rdf:value>
|
|
Packit Service |
21b5d1 |
// ... Qualifiers looking like named struct fields
|
|
Packit Service |
21b5d1 |
// </ns:QualifiedProperty>
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// *** Consider numbered array items, but has compatibility problems.
|
|
Packit Service |
21b5d1 |
// *** Consider qualified form with rdf:Description and attributes.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFElemProps ( const XMP_Node * parentNode,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index indent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
XMP_Index level;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t prop = 0, propLim = parentNode->children.size(); prop != propLim; ++prop ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const XMP_Node * propNode = parentNode->children[prop];
|
|
Packit Service |
21b5d1 |
if ( CanBeRDFAttrProp ( propNode ) ) continue;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
bool emitEndTag = true;
|
|
Packit Service |
21b5d1 |
bool indentEndTag = true;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_OptionBits propForm = propNode->options & kXMP_PropCompositeMask;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -----------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// Determine the XML element name, write the name part of the start tag. Look over the
|
|
Packit Service |
21b5d1 |
// qualifiers to decide on "normal" versus "rdf:value" form. Emit the attribute
|
|
Packit Service |
21b5d1 |
// qualifiers at the same time.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_StringPtr elemName = propNode->name.c_str();
|
|
Packit Service |
21b5d1 |
if ( *elemName == '[' ) elemName = "rdf:li";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( level = indent; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += '<';
|
|
Packit Service |
21b5d1 |
outputStr += elemName;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#define isCompact false
|
|
Packit Service |
21b5d1 |
bool hasGeneralQualifiers = isCompact; // Might also become true later.
|
|
Packit Service |
21b5d1 |
bool hasRDFResourceQual = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currQual = propNode->qualifiers[qualNum];
|
|
Packit Service |
21b5d1 |
if ( ! IsRDFAttrQualifier ( currQual->name ) ) {
|
|
Packit Service |
21b5d1 |
hasGeneralQualifiers = true;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
if ( currQual->name == "rdf:resource" ) hasRDFResourceQual = true;
|
|
Packit Service |
21b5d1 |
outputStr += ' ';
|
|
Packit Service |
21b5d1 |
outputStr += currQual->name;
|
|
Packit Service |
21b5d1 |
outputStr += "=\"";
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, currQual->value, kForAttribute );
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// --------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// Process the property according to the standard patterns.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( hasGeneralQualifiers ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// The node has general qualifiers, ones that can't be attributes on a property element.
|
|
Packit Service |
21b5d1 |
// Emit using the qualified property pseudo-struct form. The value is output by a call
|
|
Packit Service |
21b5d1 |
// to SerializePrettyRDFProperty with emitAsRDFValue set.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// *** We're losing compactness in the calls to SerializePrettyRDFProperty.
|
|
Packit Service |
21b5d1 |
// *** Should refactor to have SerializeCompactRDFProperty that does one node.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:parseType=\"Resource\">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t qualNum = 0;
|
|
Packit Service |
21b5d1 |
size_t qualLim = propNode->qualifiers.size();
|
|
Packit Service |
21b5d1 |
if ( propNode->options & kXMP_PropHasLang ) ++qualNum;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( ; qualNum < qualLim; ++qualNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currQual = propNode->qualifiers[qualNum];
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFProperty ( currQual, outputStr, newline, indentStr, indent+1 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// --------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// This node has only attribute qualifiers. Emit as a property element.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( propForm == 0 ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// --------------------------
|
|
Packit Service |
21b5d1 |
// This is a simple property.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( propNode->options & kXMP_PropValueIsURI ) {
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:resource=\"";
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, propNode->value, kForAttribute );
|
|
Packit Service |
21b5d1 |
outputStr += "\"/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
} else if ( propNode->value.empty() ) {
|
|
Packit Service |
21b5d1 |
outputStr += "/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
AppendNodeValue ( outputStr, propNode->value, kForElement );
|
|
Packit Service |
21b5d1 |
indentEndTag = false;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else if ( propForm & kXMP_PropValueIsArray ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -----------------
|
|
Packit Service |
21b5d1 |
// This is an array.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsStartTag );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( XMP_ArrayIsAltText(propNode->options) ) NormalizeLangArray ( (XMP_Node*)propNode );
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+2 );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ----------------------
|
|
Packit Service |
21b5d1 |
// This must be a struct.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_Assert ( propForm & kXMP_PropValueIsStruct );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
bool hasAttrFields = false;
|
|
Packit Service |
21b5d1 |
bool hasElemFields = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t field, fieldLim;
|
|
Packit Service |
21b5d1 |
for ( field = 0, fieldLim = propNode->children.size(); field != fieldLim; ++field ) {
|
|
Packit Service |
21b5d1 |
XMP_Node * currField = propNode->children[field];
|
|
Packit Service |
21b5d1 |
if ( CanBeRDFAttrProp ( currField ) ) {
|
|
Packit Service |
21b5d1 |
hasAttrFields = true;
|
|
Packit Service |
21b5d1 |
if ( hasElemFields ) break; // No sense looking further.
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
hasElemFields = true;
|
|
Packit Service |
21b5d1 |
if ( hasAttrFields ) break; // No sense looking further.
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( hasRDFResourceQual && hasElemFields ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Can't mix rdf:resource qualifier and element fields", kXMPErr_BadRDF );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( propNode->children.size() == 0 ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Catch an empty struct as a special case. The case below would emit an empty
|
|
Packit Service |
21b5d1 |
// XML element, which gets reparsed as a simple property with an empty value.
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:parseType=\"Resource\"/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else if ( ! hasElemFields ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// All fields can be attributes, use the emptyPropertyElt form.
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFAttrProps ( propNode, outputStr, newline, indentStr, indent+1 );
|
|
Packit Service |
21b5d1 |
outputStr += "/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
emitEndTag = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else if ( ! hasAttrFields ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// All fields must be elements, use the parseTypeResourcePropertyElt form.
|
|
Packit Service |
21b5d1 |
outputStr += " rdf:parseType=\"Resource\">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+1 );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Have a mix of attributes and elements, use an inner rdf:Description.
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
for ( level = indent+1; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += "
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFAttrProps ( propNode, outputStr, newline, indentStr, indent+2 );
|
|
Packit Service |
21b5d1 |
outputStr += ">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+1 );
|
|
Packit Service |
21b5d1 |
for ( level = indent+1; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += kRDF_StructEnd;
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ----------------------------------
|
|
Packit Service |
21b5d1 |
// Emit the property element end tag.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( emitEndTag ) {
|
|
Packit Service |
21b5d1 |
if ( indentEndTag ) for ( level = indent; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += "</";
|
|
Packit Service |
21b5d1 |
outputStr += elemName;
|
|
Packit Service |
21b5d1 |
outputStr += '>';
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializeCompactRDFElemProps
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializeCompactRDFSchemas
|
|
Packit Service |
21b5d1 |
// --------------------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// All properties from all schema are written in a single rdf:Description element, as are all of the
|
|
Packit Service |
21b5d1 |
// necessary namespace declarations. The baseIndent is the base level for the entire serialization,
|
|
Packit Service |
21b5d1 |
// that of the x:xmpmeta element. The x:xmpmeta and rdf:RDF elements have already been written.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// Top level simple unqualified properties are written as attributes of the (only) rdf:Description
|
|
Packit Service |
21b5d1 |
// element. Structs, arrays, and qualified properties are written by SerializeCompactRDFElemProp. An
|
|
Packit Service |
21b5d1 |
// xml:lang qualifier on a simple property prevents the attribute form.
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// xmlns:ns="URI" ...
|
|
Packit Service |
21b5d1 |
// ns:UnqualifiedSimpleProperty="value" ... >
|
|
Packit Service |
21b5d1 |
// ... The remaining properties of the schema, see SerializeCompactRDFElemProps
|
|
Packit Service |
21b5d1 |
// </rdf:Description>
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFSchemas ( const XMP_Node & xmpTree,
|
|
Packit Service |
21b5d1 |
XMP_VarString & outputStr,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index baseIndent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
XMP_Index level;
|
|
Packit Service |
21b5d1 |
size_t schema, schemaLim;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Begin the rdf:Description start tag.
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += kRDF_SchemaStart;
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
outputStr += xmpTree.name;
|
|
Packit Service |
21b5d1 |
outputStr += '"';
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write all necessary xmlns attributes.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t totalLen = 8; // Start at 8 for "xml:rdf:".
|
|
Packit Service |
21b5d1 |
XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin();
|
|
Packit Service |
21b5d1 |
XMP_cStringMapPos endPos = sNamespacePrefixToURIMap->end();
|
|
Packit Service |
21b5d1 |
for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_VarString usedNS;
|
|
Packit Service |
21b5d1 |
usedNS.reserve ( totalLen );
|
|
Packit Service |
21b5d1 |
usedNS = "xml:rdf:";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currSchema = xmpTree.children[schema];
|
|
Packit Service |
21b5d1 |
DeclareUsedNamespaces ( currSchema, usedNS, outputStr, newline, indentStr, baseIndent+4 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the top level "attrProps" and close the rdf:Description start tag.
|
|
Packit Service |
21b5d1 |
bool allAreAttrs = true;
|
|
Packit Service |
21b5d1 |
for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currSchema = xmpTree.children[schema];
|
|
Packit Service |
21b5d1 |
allAreAttrs &= SerializeCompactRDFAttrProps ( currSchema, outputStr, newline, indentStr, baseIndent+3 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
if ( ! allAreAttrs ) {
|
|
Packit Service |
21b5d1 |
outputStr += ">";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
outputStr += "/>";
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
return; // ! Done if all properties in all schema are written as attributes.
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the remaining properties for each schema.
|
|
Packit Service |
21b5d1 |
for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currSchema = xmpTree.children[schema];
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFElemProps ( currSchema, outputStr, newline, indentStr, baseIndent+3 );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the rdf:Description end tag.
|
|
Packit Service |
21b5d1 |
// *** Elide the end tag if everything (all props in all schema) is an attr.
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
|
|
Packit Service |
21b5d1 |
outputStr += kRDF_SchemaEnd;
|
|
Packit Service |
21b5d1 |
outputStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializeCompactRDFSchemas
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializeAsRDF
|
|
Packit Service |
21b5d1 |
// --------------
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// <x:xmpmeta xmlns:x=... >
|
|
Packit Service |
21b5d1 |
// <rdf:RDF xmlns:rdf=... >
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// ... The properties, see SerializePrettyRDFSchema or SerializeCompactRDFSchemas
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
// </rdf:RDF>
|
|
Packit Service |
21b5d1 |
// </x:xmpmeta>
|
|
Packit Service |
21b5d1 |
//
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// *** Need to strip empty arrays?
|
|
Packit Service |
21b5d1 |
// *** Option to strip/keep empty structs?
|
|
Packit Service |
21b5d1 |
// *** Need to verify handling of rdf:type qualifiers in pretty and compact.
|
|
Packit Service |
21b5d1 |
// *** Need to verify round tripping of rdf:ID and similar qualifiers, see RDF 7.2.21.
|
|
Packit Service |
21b5d1 |
// *** Check cases of rdf:resource plus explicit attr qualifiers (like xml:lang).
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
static void
|
|
Packit Service |
21b5d1 |
SerializeAsRDF ( const XMPMeta & xmpObj,
|
|
Packit Service |
21b5d1 |
XMP_VarString & headStr, // Everything up to the padding.
|
|
Packit Service |
21b5d1 |
XMP_VarString & tailStr, // Everything after the padding.
|
|
Packit Service |
21b5d1 |
XMP_OptionBits options,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index baseIndent )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
const size_t treeNameLen = xmpObj.tree.name.size();
|
|
Packit Service |
21b5d1 |
const size_t indentLen = strlen ( indentStr );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// First estimate the worst case space and reserve room in the output string. This optimization
|
|
Packit Service |
21b5d1 |
// avoids reallocating and copying the output as it grows. The initial count does not look at
|
|
Packit Service |
21b5d1 |
// the values of properties, so it does not account for character entities, e.g.
for newline.
|
|
Packit Service |
21b5d1 |
// Since there can be a lot of these in things like the base 64 encoding of a large thumbnail,
|
|
Packit Service |
21b5d1 |
// inflate the count by 1/4 (easy to do) to accommodate.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// *** Need to include estimate for alias comments.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t outputLen = 2 * (strlen(kPacketHeader) + strlen(kRDF_XMPMetaStart) + strlen(kRDF_RDFStart) + 3*baseIndent*indentLen);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currSchema = xmpObj.tree.children[schemaNum];
|
|
Packit Service |
21b5d1 |
outputLen += 2*(baseIndent+2)*indentLen + strlen(kRDF_SchemaStart) + treeNameLen + strlen(kRDF_SchemaEnd) + 2;
|
|
Packit Service |
21b5d1 |
outputLen += EstimateRDFSize ( currSchema, baseIndent+2, indentLen );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
outputLen += (outputLen >> 2); // Inflate by 1/4, an empirical fudge factor.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Now generate the RDF into the head string as UTF-8.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_Index level;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
headStr.erase();
|
|
Packit Service |
21b5d1 |
headStr.reserve ( outputLen );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the packet header PI.
|
|
Packit Service |
21b5d1 |
if ( ! (options & kXMP_OmitPacketWrapper) ) {
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent; level > 0; --level ) headStr += indentStr;
|
|
Packit Service |
21b5d1 |
headStr += kPacketHeader;
|
|
Packit Service |
21b5d1 |
headStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the xmpmeta element's start tag.
|
|
Packit Service |
21b5d1 |
if ( ! (options & kXMP_OmitXMPMetaElement) ) {
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent; level > 0; --level ) headStr += indentStr;
|
|
Packit Service |
21b5d1 |
headStr += kRDF_XMPMetaStart;
|
|
Packit Service |
21b5d1 |
headStr += kXMPCore_VersionMessage "\">";
|
|
Packit Service |
21b5d1 |
headStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the rdf:RDF start tag.
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+1; level > 0; --level ) headStr += indentStr;
|
|
Packit Service |
21b5d1 |
headStr += kRDF_RDFStart;
|
|
Packit Service |
21b5d1 |
headStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write all of the properties.
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_UseCompactFormat ) {
|
|
Packit Service |
21b5d1 |
SerializeCompactRDFSchemas ( xmpObj.tree, headStr, newline, indentStr, baseIndent );
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
if ( xmpObj.tree.children.size() > 0 ) {
|
|
Packit Service |
21b5d1 |
for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {
|
|
Packit Service |
21b5d1 |
const XMP_Node * currSchema = xmpObj.tree.children[schemaNum];
|
|
Packit Service |
21b5d1 |
SerializePrettyRDFSchema ( xmpObj.tree.name, currSchema, headStr, options, newline, indentStr, baseIndent );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
for ( XMP_Index level = baseIndent+2; level > 0; --level ) headStr += indentStr;
|
|
Packit Service |
21b5d1 |
headStr += kRDF_SchemaStart; // Special case an empty XMP object.
|
|
Packit Service |
21b5d1 |
headStr += '"';
|
|
Packit Service |
21b5d1 |
headStr += xmpObj.tree.name;
|
|
Packit Service |
21b5d1 |
headStr += "\"/>";
|
|
Packit Service |
21b5d1 |
headStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the rdf:RDF end tag.
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent+1; level > 0; --level ) headStr += indentStr;
|
|
Packit Service |
21b5d1 |
headStr += kRDF_RDFEnd;
|
|
Packit Service |
21b5d1 |
headStr += newline;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the xmpmeta end tag.
|
|
Packit Service |
21b5d1 |
if ( ! (options & kXMP_OmitXMPMetaElement) ) {
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent; level > 0; --level ) headStr += indentStr;
|
|
Packit Service |
21b5d1 |
headStr += kRDF_XMPMetaEnd;
|
|
Packit Service |
21b5d1 |
headStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Write the packet trailer PI into the tail string as UTF-8.
|
|
Packit Service |
21b5d1 |
tailStr.erase();
|
|
Packit Service |
21b5d1 |
if ( ! (options & kXMP_OmitPacketWrapper) ) {
|
|
Packit Service |
21b5d1 |
tailStr.reserve ( strlen(kPacketTrailer) + (strlen(indentStr) * baseIndent) );
|
|
Packit Service |
21b5d1 |
for ( level = baseIndent; level > 0; --level ) tailStr += indentStr;
|
|
Packit Service |
21b5d1 |
tailStr += kPacketTrailer;
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_ReadOnlyPacket ) tailStr[tailStr.size()-4] = 'r';
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// ! This assert is just a performance check, to see if the reserve was enough.
|
|
Packit Service |
21b5d1 |
// *** XMP_Assert ( headStr.size() <= outputLen );
|
|
Packit Service |
21b5d1 |
// *** Don't use an assert. Think of some way to track this without risk of aborting the client.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializeAsRDF
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// -------------------------------------------------------------------------------------------------
|
|
Packit Service |
21b5d1 |
// SerializeToBuffer
|
|
Packit Service |
21b5d1 |
// -----------------
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
void
|
|
Packit Service |
21b5d1 |
XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
|
|
Packit Service |
21b5d1 |
XMP_StringLen * rdfSize,
|
|
Packit Service |
21b5d1 |
XMP_OptionBits options,
|
|
Packit Service |
21b5d1 |
XMP_StringLen padding,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr newline,
|
|
Packit Service |
21b5d1 |
XMP_StringPtr indentStr,
|
|
Packit Service |
21b5d1 |
XMP_Index baseIndent ) const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
XMP_Assert ( (rdfString != 0) && (rdfSize != 0) && (newline != 0) && (indentStr != 0) );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Fix up some default parameters.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
enum { kDefaultPad = 2048 };
|
|
Packit Service |
21b5d1 |
size_t unicodeUnitSize = 1;
|
|
Packit Service |
21b5d1 |
XMP_OptionBits charEncoding = options & kXMP_EncodingMask;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( charEncoding != kXMP_EncodeUTF8 ) {
|
|
Packit Service |
21b5d1 |
if ( options & _XMP_UTF16_Bit ) {
|
|
Packit Service |
21b5d1 |
if ( options & _XMP_UTF32_Bit ) XMP_Throw ( "Can't use both _XMP_UTF16_Bit and _XMP_UTF32_Bit", kXMPErr_BadOptions );
|
|
Packit Service |
21b5d1 |
unicodeUnitSize = 2;
|
|
Packit Service |
21b5d1 |
} else if ( options & _XMP_UTF32_Bit ) {
|
|
Packit Service |
21b5d1 |
unicodeUnitSize = 4;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Can't use _XMP_LittleEndian_Bit by itself", kXMPErr_BadOptions );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_OmitAllFormatting ) {
|
|
Packit Service |
21b5d1 |
newline = " "; // ! Yes, a space for "newline". This ensures token separation.
|
|
Packit Service |
21b5d1 |
indentStr = "";
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
if ( *newline == 0 ) newline = "\xA"; // Linefeed
|
|
Packit Service |
21b5d1 |
if ( *indentStr == 0 ) {
|
|
Packit Service |
21b5d1 |
indentStr = " ";
|
|
Packit Service |
21b5d1 |
if ( ! (options & kXMP_UseCompactFormat) ) indentStr = " ";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_ExactPacketLength ) {
|
|
Packit Service |
21b5d1 |
if ( options & (kXMP_OmitPacketWrapper | kXMP_IncludeThumbnailPad) ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Inconsistent options for exact size serialize", kXMPErr_BadOptions );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
if ( (padding & (unicodeUnitSize-1)) != 0 ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Exact size must be a multiple of the Unicode element", kXMPErr_BadOptions );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
} else if ( options & kXMP_ReadOnlyPacket ) {
|
|
Packit Service |
21b5d1 |
if ( options & (kXMP_OmitPacketWrapper | kXMP_IncludeThumbnailPad) ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Inconsistent options for read-only packet", kXMPErr_BadOptions );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
padding = 0;
|
|
Packit Service |
21b5d1 |
} else if ( options & kXMP_OmitPacketWrapper ) {
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_IncludeThumbnailPad ) {
|
|
Packit Service |
21b5d1 |
XMP_Throw ( "Inconsistent options for non-packet serialize", kXMPErr_BadOptions );
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
padding = 0;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
if ( padding == 0 ) padding = kDefaultPad * unicodeUnitSize;
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_IncludeThumbnailPad ) {
|
|
Packit Service |
21b5d1 |
if ( ! this->DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) padding += (10000 * unicodeUnitSize); // *** Need a better estimate.
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Serialize as UTF-8, then convert to UTF-16 or UTF-32 if necessary, and assemble with the padding and tail.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
std::string tailStr;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
SerializeAsRDF ( *this, *sOutputStr, tailStr, options, newline, indentStr, baseIndent );
|
|
Packit Service |
21b5d1 |
if ( charEncoding == kXMP_EncodeUTF8 ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_ExactPacketLength ) {
|
|
Packit Service |
21b5d1 |
size_t minSize = sOutputStr->size() + tailStr.size();
|
|
Packit Service |
21b5d1 |
if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
|
|
Packit Service |
21b5d1 |
padding -= minSize; // Now the actual amount of padding to add.
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
size_t newlineLen = strlen ( newline );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( padding < newlineLen ) {
|
|
Packit Service |
21b5d1 |
sOutputStr->append ( padding, ' ' );
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
padding -= newlineLen; // Write this newline last.
|
|
Packit Service |
21b5d1 |
while ( padding >= (100 + newlineLen) ) {
|
|
Packit Service |
21b5d1 |
sOutputStr->append ( 100, ' ' );
|
|
Packit Service |
21b5d1 |
*sOutputStr += newline;
|
|
Packit Service |
21b5d1 |
padding -= (100 + newlineLen);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
sOutputStr->append ( padding, ' ' );
|
|
Packit Service |
21b5d1 |
*sOutputStr += newline;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
*sOutputStr += tailStr;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Need to convert the encoding. Swap the UTF-8 into a local string and convert back. Assemble everything.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
XMP_VarString utf8Str, newlineStr;
|
|
Packit Service |
21b5d1 |
bool bigEndian = ((charEncoding & _XMP_LittleEndian_Bit) == 0);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( charEncoding & _XMP_UTF16_Bit ) {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
std::string padStr ( " " ); padStr[0] = 0; // Assume big endian.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
utf8Str.swap ( *sOutputStr );
|
|
Packit Service |
21b5d1 |
ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian );
|
|
Packit Service |
21b5d1 |
utf8Str.swap ( tailStr );
|
|
Packit Service |
21b5d1 |
ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_ExactPacketLength ) {
|
|
Packit Service |
21b5d1 |
size_t minSize = sOutputStr->size() + tailStr.size();
|
|
Packit Service |
21b5d1 |
if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
|
|
Packit Service |
21b5d1 |
padding -= minSize; // Now the actual amount of padding to add (in bytes).
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
utf8Str.assign ( newline );
|
|
Packit Service |
21b5d1 |
ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &newlineStr, bigEndian );
|
|
Packit Service |
21b5d1 |
size_t newlineLen = newlineStr.size();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( padding < newlineLen ) {
|
|
Packit Service |
21b5d1 |
for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
padding -= newlineLen; // Write this newline last.
|
|
Packit Service |
21b5d1 |
while ( padding >= (200 + newlineLen) ) {
|
|
Packit Service |
21b5d1 |
for ( int i = 100; i > 0; --i ) *sOutputStr += padStr;
|
|
Packit Service |
21b5d1 |
*sOutputStr += newlineStr;
|
|
Packit Service |
21b5d1 |
padding -= (200 + newlineLen);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr;
|
|
Packit Service |
21b5d1 |
*sOutputStr += newlineStr;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
*sOutputStr += tailStr;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
std::string padStr ( " " ); padStr[0] = padStr[1] = padStr[2] = 0; // Assume big endian.
|
|
Packit Service |
21b5d1 |
// UTF8_to_UTF32_Proc Converter = UTF8_to_UTF32BE;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( charEncoding & _XMP_LittleEndian_Bit ) {
|
|
Packit Service |
21b5d1 |
padStr[0] = ' '; padStr[1] = padStr[2] = padStr[3] = 0;
|
|
Packit Service |
21b5d1 |
// Converter = UTF8_to_UTF32LE;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
utf8Str.swap ( *sOutputStr );
|
|
Packit Service |
21b5d1 |
ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian );
|
|
Packit Service |
21b5d1 |
utf8Str.swap ( tailStr );
|
|
Packit Service |
21b5d1 |
ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian );
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( options & kXMP_ExactPacketLength ) {
|
|
Packit Service |
21b5d1 |
size_t minSize = sOutputStr->size() + tailStr.size();
|
|
Packit Service |
21b5d1 |
if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
|
|
Packit Service |
21b5d1 |
padding -= minSize; // Now the actual amount of padding to add (in bytes).
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
utf8Str.assign ( newline );
|
|
Packit Service |
21b5d1 |
ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &newlineStr, bigEndian );
|
|
Packit Service |
21b5d1 |
size_t newlineLen = newlineStr.size();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( padding < newlineLen ) {
|
|
Packit Service |
21b5d1 |
for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr;
|
|
Packit Service |
21b5d1 |
} else {
|
|
Packit Service |
21b5d1 |
padding -= newlineLen; // Write this newline last.
|
|
Packit Service |
21b5d1 |
while ( padding >= (400 + newlineLen) ) {
|
|
Packit Service |
21b5d1 |
for ( int i = 100; i > 0; --i ) *sOutputStr += padStr;
|
|
Packit Service |
21b5d1 |
*sOutputStr += newlineStr;
|
|
Packit Service |
21b5d1 |
padding -= (400 + newlineLen);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr;
|
|
Packit Service |
21b5d1 |
*sOutputStr += newlineStr;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
*sOutputStr += tailStr;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Return the finished string.
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
*rdfString = sOutputStr->c_str();
|
|
Packit Service |
21b5d1 |
*rdfSize = sOutputStr->size();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
} // SerializeToBuffer
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// =================================================================================================
|