#include "structureSerializerXML.h"
#include "metadataXML.h"
#include "metadataXMLPluginStrings.h"
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <maya/MString.h>
#include <maya/MStringResource.h>
#include <maya/adskDataStructure.h>
#include <assert.h>
#include <libxml/globals.h>
#include <libxml/xmlreader.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
ImplementSerializerFormat(StructureSerializerXML,StructureSerializer,xmlFormatType);
StructureSerializerXML::StructureSerializerXML()
{
}
StructureSerializerXML::~StructureSerializerXML ()
{
}
Structure*
StructureSerializerXML::read(
std::istream& cSrc,
std::string& errors ) const
{
unsigned int errorCount = 0;
Structure* newStructure = NULL;
errors = "";
xmlDocPtr doc = NULL;
LIBXML_TEST_VERSION
cSrc.seekg (0, std::ios::end);
int size = (int) cSrc.tellg();
char* memblock = new char [size];
cSrc.seekg (0, std::ios::beg);
cSrc.read (memblock, size);
doc = xmlReadMemory(memblock, size, NULL, NULL, 0);
xmlNode* structureNode = XML::Util::findNamedNode( xmlDocGetRootElement(doc), xmlTagStructure );
do
{
if( ! structureNode )
{
REPORT_ERROR_AT_LINE(kStructureXMLStructureTagNotFound, 1);
break;
}
xmlNode* structureNameNode = XML::Util::findNamedNode( structureNode->children, xmlTagStructureName );
xmlChar* structureName = XML::Util::findText( doc, structureNameNode );
if( ! structureName )
{
REPORT_ERROR_AT_LINE(kStructureXMLStructureNameNotFound, structureNameNode ? structureNameNode->line : structureNode->line);
break;
}
newStructure = Structure::create();
newStructure->setName( (const char*)structureName );
xmlFree( structureName );
for (xmlNode* childNode = structureNode->children; childNode; childNode = childNode->next)
{
if( (childNode->type != XML_ELEMENT_NODE)
|| ( 0 != strcmp((const char*)childNode->name, xmlTagStructureMember) ) )
{
continue;
}
xmlNode* memberDimNode = XML::Util::findNamedNode( childNode->children, xmlTagStructureMemberDim );
int memberDim = 1;
if( memberDimNode )
{
xmlChar* value = XML::Util::findText( doc, memberDimNode );
if( value )
{
memberDim = atol( (const char*)value );
xmlFree( value );
}
else
{
REPORT_ERROR_AT_LINE( kStructureXMLMemberDimNotFound, memberDimNode->line );
break;
}
}
xmlNode* memberNameNode = XML::Util::findNamedNode( childNode->children, xmlTagStructureMemberName );
xmlChar* memberName = memberNameNode ? XML::Util::findText( doc, memberNameNode ) : NULL;
if( ! memberName )
{
REPORT_ERROR_AT_LINE(kStructureXMLMemberNameNotFound, (memberNameNode ? memberNameNode->line : childNode->line));
break;
}
xmlNode* memberTypeNode = XML::Util::findNamedNode( childNode->children, xmlTagStructureMemberType );
xmlChar* memberType = memberTypeNode ? XML::Util::findText( doc, memberTypeNode ) : NULL;
if( ! memberType )
{
REPORT_ERROR_AT_LINE(kStructureXMLMemberTypeNotFound, (memberTypeNode ? memberTypeNode->line : childNode->line));
xmlFree( memberName );
break;
}
Member::eDataType dataType = Member::typeFromName((const char*)memberType);
if( dataType == Member::kInvalidType )
{
REPORT_ERROR_AT_LINE(kStructureXMLMemberTypeInvalid, memberTypeNode->line);
}
else
{
newStructure->addMember( dataType, memberDim, (const char*) memberName );
}
xmlFree( memberType );
xmlFree( memberName );
}
break;
} while( true );
delete[] memblock;
xmlFreeDoc(doc);
if( errorCount > 0 )
{
if( newStructure )
{
newStructure->ref();
newStructure->unref();
newStructure = NULL;
}
}
return newStructure;
}
int
StructureSerializerXML::write(
const Structure& dataToWrite,
std::ostream& cDst ) const
{
cDst << "<?xml version='1.0' encoding='UTF-8'?>" << std::endl;
xmlChar* structureName = xmlEncodeSpecialChars(NULL, (const xmlChar*)dataToWrite.name());
cDst << "<" << xmlTagStructure << ">" << std::endl;
cDst << " <" << xmlTagStructureName << ">"
<< structureName
<< " </" << xmlTagStructureName << ">" << std::endl;
cDst << "</" << xmlTagStructureName << ">" << std::endl;
xmlFree( structureName );
for( Structure::iterator structIt = dataToWrite.begin();
structIt != dataToWrite.end();
++structIt )
{
xmlChar* memberName = xmlEncodeSpecialChars(NULL, (const xmlChar*)structIt->name());
xmlChar* memberType = xmlEncodeSpecialChars(NULL, (const xmlChar*)Member::typeName(structIt->type()));
cDst << " <" << xmlTagStructureMember << ">" << std::endl;
cDst << " <" << xmlTagStructureMemberName << ">" << memberName
<< " </" << xmlTagStructureMemberName << ">" << std::endl;
cDst << " <" << xmlTagStructureMemberType << ">" << memberType
<< " </" << xmlTagStructureMemberType << ">" << std::endl;
if( structIt->length() != 1 )
{
cDst << " <" << xmlTagStructureMemberDim << ">" << structIt->length()
<< " </" << xmlTagStructureMemberDim << ">" << std::endl;
}
cDst << " </" << xmlTagStructureMember << ">" << std::endl;
xmlFree( memberName );
xmlFree( memberType );
}
cDst << "</" << xmlTagStructure << ">" << std::endl;
return 0;
}
void
StructureSerializerXML::getFormatDescription(
std::ostream& info ) const
{
for( unsigned int i=Member::kFirstType; i<Member::kLastType; i++ )
{
if( i != Member::kFirstType ) info << ", ";
info << Member::typeName((Member::eDataType)i);
}
}