Added sharedXml library and links to boost/libxml2/iconv libraries

This commit is contained in:
Anonymous
2014-01-14 15:18:21 -07:00
parent dfa993e0d4
commit dcef2e89f3
24 changed files with 1272 additions and 1 deletions

View File

@@ -10,6 +10,9 @@ set(SWG_ENGINE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/engine)
set(SWG_EXTERNALS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external)
set(SWG_GAME_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/game)
find_package(Boost REQUIRED)
find_package(Iconv REQUIRED)
find_package(LibXml2 REQUIRED)
find_package(STLPort REQUIRED)
find_package(ZLib REQUIRED)

29
cmake/FindIconv.cmake Normal file
View File

@@ -0,0 +1,29 @@
find_path(ICONV_ROOT
NAMES include/iconv.h
)
find_path(ICONV_INCLUDE_DIR iconv.h
HINTS
$ENV{ICONV_ROOT}
PATH_SUFFIXES include
PATHS
${ICONV_ROOT}
${ICONV_INCLUDEDIR}
)
find_library(ICONV_LIBRARY
NAMES iconv
PATH_SUFFIXES lib
HINTS
$ENV{ICONV_ROOT}
${ICONV_ROOT}
${ICONV_LIBRARYDIR}
)
# handle the QUIETLY and REQUIRED arguments and set OPENAL_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ICONV DEFAULT_MSG ICONV_LIBRARY ICONV_INCLUDE_DIR)
mark_as_advanced(ICONV_ROOT ICONV_INCLUDE_DIR ICONV_LIBRARY)

29
cmake/FindLibXml2.cmake Normal file
View File

@@ -0,0 +1,29 @@
find_path(LIBXML2_ROOT
NAMES include/zlib.h
)
find_path(LIBXML2_INCLUDE_DIR libxml/xpath.h
HINTS
$ENV{LIBXML2_ROOT}
PATH_SUFFIXES include include/libxml2 libxml2
PATHS
${LIBXML2_ROOT}
${LIBXML2_INCLUDEDIR}
)
find_library(LIBXML2_LIBRARY
NAMES xml2 libxml2
PATH_SUFFIXES lib
HINTS
$ENV{LIBXML2_ROOT}
${LIBXML2_ROOT}
${LIBXML2_LIBRARYDIR}
)
# handle the QUIETLY and REQUIRED arguments and set OPENAL_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LIBXML2 DEFAULT_MSG LIBXML2_LIBRARY LIBXML2_INCLUDE_DIR)
mark_as_advanced(LIBXML2_ROOT LIBXML2_INCLUDE_DIR LIBXML2_LIBRARY)

View File

@@ -23,3 +23,4 @@ add_subdirectory(sharedSynchronization)
add_subdirectory(sharedTerrain)
add_subdirectory(sharedThread)
add_subdirectory(sharedUtility)
add_subdirectory(sharedXml)

View File

@@ -330,6 +330,7 @@ include_directories(
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localizationArchive/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
${Boost_INCLUDE_DIR}
)
add_library(sharedGame STATIC

View File

@@ -712,9 +712,10 @@ include_directories(
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedGame/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMath/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMathArchive/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedObject/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedUtility/include/public
${SWG_GAME_SOURCE_DIR}/shared/library/swgSharedUtility/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
@@ -723,6 +724,7 @@ include_directories(
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/singleton/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
${Boost_INCLUDE_DIR}
)
add_library(sharedNetworkMessages STATIC

View File

@@ -124,6 +124,7 @@ include_directories(
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/localization/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicode/include
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/unicodeArchive/include/public
${Boost_INCLUDE_DIR}
)
add_library(sharedUtility STATIC

View File

@@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 2.8)
project(sharedXml)
if(WIN32)
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
endif()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
add_subdirectory(src)

View File

@@ -0,0 +1 @@
#include "../../src/shared/core/FirstSharedXml.h"

View File

@@ -0,0 +1 @@
#include "../../src/shared/core/SetupSharedXml.h"

View File

@@ -0,0 +1 @@
#include "../../src/shared/tree/XmlTreeDocument.h"

View File

@@ -0,0 +1 @@
#include "../../src/shared/tree/XmlTreeDocumentList.h"

View File

@@ -0,0 +1 @@
#include "../../src/shared/tree/XmlTreeNode.h"

View File

@@ -0,0 +1,40 @@
set(SHARED_SOURCES
shared/core/FirstSharedXml.h
shared/core/SetupSharedXml.cpp
shared/core/SetupSharedXml.h
shared/tree/XmlTreeDocument.cpp
shared/tree/XmlTreeDocument.h
shared/tree/XmlTreeDocumentList.cpp
shared/tree/XmlTreeDocumentList.h
shared/tree/XmlTreeNode.cpp
shared/tree/XmlTreeNode.h
)
if(WIN32)
set(PLATFORM_SOURCES
win32/core/FirstSharedXml.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
else()
set(PLATFORM_SOURCES "")
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/shared
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFile/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
${ICONV_INCLUDE_DIR}
${LIBXML2_INCLUDE_DIR}
)
add_library(sharedXml STATIC
${SHARED_SOURCES}
${PLATFORM_SOURCES}
)

View File

@@ -0,0 +1,11 @@
// ======================================================================
//
// FirstSharedXml.h
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedFoundation/FirstSharedFoundation.h"
// ======================================================================

View File

@@ -0,0 +1,97 @@
// ======================================================================
//
// SetupSharedXml.cpp
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedXml/FirstSharedXml.h"
#include "sharedXml/SetupSharedXml.h"
#include "libxml/parser.h"
#include "sharedDebug/InstallTimer.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedXml/XmlTreeDocumentList.h"
// ======================================================================
namespace SetupSharedXmlNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void remove();
void *xmlAllocate(size_t byteCount);
void xmlFree2(void *memory);
char *xmlDuplicateString(char const *source);
void *xmlReAllocate(void *memory, size_t byteCount);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool s_installed;
}
using namespace SetupSharedXmlNamespace;
// ======================================================================
// namespace SetupSharedXmlNamespace
// ======================================================================
void SetupSharedXmlNamespace::remove()
{
FATAL(!s_installed, ("SetupSharedXml not installed."));
s_installed = false;
xmlCleanupParser();
}
// ----------------------------------------------------------------------
void *SetupSharedXmlNamespace::xmlAllocate(size_t byteCount)
{
return new byte[byteCount];
}
// ----------------------------------------------------------------------
void SetupSharedXmlNamespace::xmlFree2(void *memory)
{
delete [] reinterpret_cast<byte*>(memory);
}
// ----------------------------------------------------------------------
char *SetupSharedXmlNamespace::xmlDuplicateString(char const *source)
{
return DuplicateString(source);
}
// ----------------------------------------------------------------------
void *SetupSharedXmlNamespace::xmlReAllocate(void *memory, size_t byteCount)
{
return MemoryManager::reallocate(memory, byteCount);
}
// ======================================================================
// class SetupSharedXml: PUBLIC STATIC
// ======================================================================
void SetupSharedXml::install()
{
InstallTimer const installTimer("SetupSharedXml::install");
FATAL(s_installed, ("SetupSharedXml already installed."));
//-- Tell libxml to use our memory management functions via these stubs.
int const result = xmlMemSetup(SetupSharedXmlNamespace::xmlFree2, SetupSharedXmlNamespace::xmlAllocate, SetupSharedXmlNamespace::xmlReAllocate, SetupSharedXmlNamespace::xmlDuplicateString);
FATAL(result != 0, ("sharedXml failed to install memory handlers with error code [%d].", result));
XmlTreeDocumentList::install();
s_installed = true;
ExitChain::add(SetupSharedXmlNamespace::remove, "SetupSharedXml");
}
// ======================================================================

View File

@@ -0,0 +1,31 @@
// ======================================================================
//
// SetupSharedXml.h
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_SetupSharedXml_H
#define INCLUDED_SetupSharedXml_H
// ======================================================================
class SetupSharedXml
{
public:
static void install();
private:
// Disabled.
SetupSharedXml();
SetupSharedXml(SetupSharedXml const&);
SetupSharedXml &operator =(SetupSharedXml const&);
};
// ======================================================================
#endif

View File

@@ -0,0 +1,165 @@
// ======================================================================
//
// XmlTreeDocument.cpp
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedXml/FirstSharedXml.h"
#include "sharedXml/XmlTreeDocument.h"
#include "libxml/tree.h"
#include "libxml/parser.h"
#include "sharedXml/XmlTreeDocumentList.h"
#include "sharedXml/XmlTreeNode.h"
#include <string>
// ======================================================================
// class XmlTreeDocument: PUBLIC
// ======================================================================
XmlTreeNode XmlTreeDocument::getRootTreeNode() const
{
return XmlTreeNode(xmlDocGetRootElement(m_xmlDocument));
}
// ----------------------------------------------------------------------
void XmlTreeDocument::fetch() const
{
DEBUG_FATAL(m_referenceCount < 0, ("XmlTreeDocument::fetch(): invalid reference count handling, reference count=[%s].", m_referenceCount));
++m_referenceCount;
}
// ----------------------------------------------------------------------
void XmlTreeDocument::release() const
{
DEBUG_FATAL(m_referenceCount <= 0, ("XmlTreeDocument::release(): invalid reference count handling, reference count=[%s].", m_referenceCount));
--m_referenceCount;
if (m_referenceCount == 0)
{
if(m_track)
// Tell the tree list to stop tracking this document.
XmlTreeDocumentList::stopTracking(this);
// Delete this document.
delete const_cast<XmlTreeDocument*>(this);
}
}
// ----------------------------------------------------------------------
void XmlTreeDocument::getAsText(std::string &documentText)
{
if(!m_xmlDocument)
return;
int docSize;
xmlChar *buf;
xmlDocDumpFormatMemory(m_xmlDocument, &buf, &docSize, 1);
documentText = reinterpret_cast<char const*>(buf);
xmlFree(buf);
}
// ----------------------------------------------------------------------
int XmlTreeDocument::getReferenceCount() const
{
return m_referenceCount;
}
// ----------------------------------------------------------------------
CrcString const &XmlTreeDocument::getName() const
{
return m_name;
}
// ======================================================================
// class XmlTreeDocument: STATIC
// ======================================================================
XmlTreeDocument* XmlTreeDocument::createDocument(const char * rootNodeName)
{
// create new doc
DEBUG_FATAL( !rootNodeName, ("XmlTreeDocument::createDocument called without root node name") );
xmlDoc *doc;
doc = xmlNewDoc(BAD_CAST "1.0");
DEBUG_FATAL( !doc, ("Attempted to make new xmlDoc but failed") );
xmlNode * node = xmlNewNode( NULL, BAD_CAST rootNodeName );
DEBUG_FATAL( !node, ("Attempted to make root node for new xml document, but failed"));
xmlDocSetRootElement(doc, node);
XmlTreeDocument *treeDoc = new XmlTreeDocument(doc);
DEBUG_WARNING( !treeDoc, ("Attempted to make new XmlTreeDoc but failed") );
if (!treeDoc)
{
xmlFree(doc);
return 0;
}
treeDoc->fetch();
return treeDoc;
}
// ----------------------------------------------------------------------
XmlTreeDocument * XmlTreeDocument::buildDocumentFromText(const std::string &inputText)
{
xmlDoc *doc;
doc = xmlParseMemory(inputText.c_str(), inputText.length());
if(!doc)
{
DEBUG_FATAL(true, ("Attempted to parse XML document from memory buffer, but failed."));
return 0;
}
XmlTreeDocument *treeDoc = new XmlTreeDocument(doc);
if(!treeDoc)
{
DEBUG_FATAL(true, ("Failure building XmlTreeDocument after successful parsing of memory buffer."));
xmlFree(doc);
return 0;
}
treeDoc->fetch();
return treeDoc;
}
// ======================================================================
// class XmlTreeDocument: PRIVATE
// ======================================================================
XmlTreeDocument::XmlTreeDocument(CrcString const &name, xmlDoc *xmlDocument) :
m_name(name),
m_xmlDocument(xmlDocument),
m_referenceCount(0),
m_track( true )
{
DEBUG_FATAL(m_xmlDocument == NULL, ("XmlTreeDocument(): tried to construct with a NULL xmlDocument."));
WARNING(m_xmlDocument == NULL, ("XmlTreeDocument(): tried to construct with a NULL xmlDocument."));
}
// ----------------------------------------------------------------------
XmlTreeDocument::XmlTreeDocument(xmlDoc *xmlDocument) :
m_name(),
m_xmlDocument(xmlDocument),
m_referenceCount(0),
m_track(false) // documents without names are temporary documents for creation of formatted xml
{
DEBUG_FATAL(m_xmlDocument == NULL, ("XmlTreeDocument(): tried to construct with a NULL xmlDocument."));
}
// ----------------------------------------------------------------------
XmlTreeDocument::~XmlTreeDocument()
{
xmlFreeDoc(m_xmlDocument);
m_xmlDocument = NULL;
}
// ======================================================================

View File

@@ -0,0 +1,68 @@
// ======================================================================
//
// XmlTreeDocument.h
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_XmlTreeDocument_H
#define INCLUDED_XmlTreeDocument_H
// ======================================================================
class XmlTreeNode;
struct _xmlDoc;
typedef struct _xmlDoc xmlDoc;
#include "sharedFoundation/PersistentCrcString.h"
#include <string>
// ======================================================================
class XmlTreeDocument
{
friend class XmlTreeDocumentList;
public:
XmlTreeNode getRootTreeNode() const;
void fetch() const;
void release() const;
int getReferenceCount() const;
CrcString const &getName() const;
static XmlTreeDocument *createDocument(const char * rootNodeName);
static XmlTreeDocument *buildDocumentFromText(const std::string &inputText);
void setRootNode(XmlTreeNode * node);
void getAsText(std::string &documentText);
private:
XmlTreeDocument(CrcString const &name, xmlDoc *xmlDocument);
XmlTreeDocument(xmlDoc *xmlDocument);
~XmlTreeDocument();
// Disabled.
XmlTreeDocument();
XmlTreeDocument(XmlTreeDocument const &);
XmlTreeDocument &operator =(XmlTreeDocument const&);
private:
PersistentCrcString m_name;
xmlDoc *m_xmlDocument;
mutable int m_referenceCount;
bool m_track;
};
// ======================================================================
#endif

View File

@@ -0,0 +1,161 @@
// ======================================================================
//
// XmlTreeDocumentList.cpp
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedXml/FirstSharedXml.h"
#include "sharedXml/XmlTreeDocumentList.h"
#include "libxml/parser.h"
#include "sharedDebug/DebugFlags.h"
#include "sharedFile/TreeFile.h"
#include "sharedFoundation/CrcString.h"
#include "sharedFoundation/ExitChain.h"
#include "sharedFoundation/LessPointerComparator.h"
#include "sharedXml/XmlTreeDocument.h"
#include <map>
// ======================================================================
namespace XmlTreeDocumentListNamespace
{
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
typedef std::map<CrcString const*, XmlTreeDocument*, LessPointerComparator> NamedDocumentMap;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void remove();
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool s_installed;
NamedDocumentMap s_documents;
#ifdef _DEBUG
bool s_logXmlDomTreeSize;
#endif
}
using namespace XmlTreeDocumentListNamespace;
// ======================================================================
// namespace XmlTreeDocumentListNamespace
// ======================================================================
void XmlTreeDocumentListNamespace::remove()
{
FATAL(!s_installed, ("XmlTreeDocumentList not installed."));
s_installed = false;
//-- Clean up and report on any XmlTreeDocumentList resources still open.
// Keep these leaked so we can debug allocation call stacks when we do have them leaking.
if (!s_documents.empty())
{
DEBUG_WARNING(true, ("XmlTreeDocumentList: leaked [%d] xml tree documents, see below for details.", static_cast<int>(s_documents.size())));
NamedDocumentMap::iterator const endIt = s_documents.end();
for (NamedDocumentMap::iterator it = s_documents.begin(); it != endIt; ++it)
{
DEBUG_REPORT_LOG(true, ("-- xml tree document name [%s], reference count [%d].\n", it->first ? it->first->getString() : "<null name>", it->second ? it->second->getReferenceCount() : -1));
}
}
}
// ======================================================================
// class XmlTreeDocumentList: PUBLIC STATIC
// ======================================================================
void XmlTreeDocumentList::install()
{
FATAL(s_installed, ("XmlTreeDocumentList already installed."));
#ifdef _DEBUG
DebugFlags::registerFlag(s_logXmlDomTreeSize, "SharedXml", "logXmlDomTreeSize");
#endif
s_installed = true;
ExitChain::add(XmlTreeDocumentListNamespace::remove, "XmlTreeDocumentList");
}
// ----------------------------------------------------------------------
XmlTreeDocument const *XmlTreeDocumentList::fetch(CrcString const &filename)
{
FATAL(!s_installed, ("XmlTreeDocumentList not installed."));
//-- Check if we already have an entry.
NamedDocumentMap::iterator const lowerBound = s_documents.lower_bound(&filename);
bool const haveEntry = (lowerBound != s_documents.end()) && !s_documents.key_comp()(&filename, lowerBound->first);
//-- Handle existing entry.
if (haveEntry)
{
FATAL(!lowerBound->second, ("XmlTreeDocumentList::fetch() found an entry for filename [%s] but the mapped document was NULL.", filename.getString()));
// Increment reference count and return.
lowerBound->second->fetch();
return lowerBound->second;
}
//-- Get file size and contents.
char const *const cPathName = filename.getString();
AbstractFile *const file = TreeFile::open(cPathName, AbstractFile::PriorityData, false);
FATAL(!file, ("XmlTreeDocumentList::fetch(): TreeFile::open() failed for filename [%s].", filename.getString()));
int const fileSize = file->length();
byte *const fileContents = file->readEntireFileAndClose();
//-- Close the file.
file->close();
delete file;
//-- Create an XML DOM tree out of it.
#ifdef _DEBUG
unsigned long const preDomBytesAllocated = MemoryManager::getCurrentNumberOfBytesAllocated();
#endif
xmlDocPtr const xmlDocument = xmlParseMemory(reinterpret_cast<char const *>(fileContents), fileSize);
FATAL(!xmlDocument, ("xmlParseMemory() returned NULL when parsing contents of file [%s].", cPathName));
#ifdef _DEBUG
unsigned long const postDomBytesAllocated = MemoryManager::getCurrentNumberOfBytesAllocated();
DEBUG_REPORT_LOG(s_logXmlDomTreeSize, ("XmlTreeDocumentList: XML tree file [%s]: XML DOM tree appears to have consumed [%d] bytes.\n", cPathName, static_cast<int>(postDomBytesAllocated - preDomBytesAllocated)));
#endif
// Release initial file contents buffer.
delete [] fileContents;
//-- Create the XmlTreeDocument, bump up reference count and add it to the map.
XmlTreeDocument *const newDocument = new XmlTreeDocument(filename, xmlDocument);
newDocument->fetch();
std::pair<NamedDocumentMap::iterator, bool> const insertResult = s_documents.insert(NamedDocumentMap::value_type(&newDocument->getName(), newDocument));
FATAL(!insertResult.second, ("XmlTreeDocumentList::fetch() failed to insert document filename [%s] into the map.", filename.getString()));
return newDocument;
}
// ======================================================================
// class XmlTreeDocumentList: PRIVATE STATIC
// ======================================================================
void XmlTreeDocumentList::stopTracking(XmlTreeDocument const *document)
{
FATAL(!s_installed, ("XmlTreeDocumentList not installed."));
FATAL(!document, ("XmlTreeDocumentList::stopTracking(): null document passed in."));
//-- Find the map entry for the xml tree document.
NamedDocumentMap::iterator const findIt = s_documents.find(&(document->getName()));
FATAL(findIt == s_documents.end(), ("XmlTreeDocumentList::stopTracking(): xml tree document [%s] not tracked.", document->getName().getString()));
//-- Remove the entry.
s_documents.erase(findIt);
}
// ======================================================================

View File

@@ -0,0 +1,37 @@
// ======================================================================
//
// XmlTreeDocumentList.h
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_XmlTreeDocumentList_H
#define INCLUDED_XmlTreeDocumentList_H
// ======================================================================
class CrcString;
class XmlTreeDocument;
// ======================================================================
class XmlTreeDocumentList
{
friend class XmlTreeDocument;
public:
static void install();
static XmlTreeDocument const *fetch(CrcString const &filename);
private:
static void stopTracking(XmlTreeDocument const *document);
};
// ======================================================================
#endif

View File

@@ -0,0 +1,413 @@
// ======================================================================
//
// XmlTreeNode.cpp
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedXml/FirstSharedXml.h"
#include "sharedXml/XmlTreeNode.h"
#include "libxml/tree.h"
#include <string>
// ======================================================================
namespace XmlTreeNodeNamespace
{
std::string s_attributeValue;
}
using namespace XmlTreeNodeNamespace;
// ======================================================================
XmlTreeNode::XmlTreeNode(const std::string &name, const std::string &content) :
m_treeNode(0)
{
std::string nameCopy = name;
std::string contentCopy = content;
// verify parameters
DEBUG_FATAL(!name.length(), ("Attempt to construct new XmlTreeNode but no name given"));
if (!name.length())
{
nameCopy = "garbage";
}
DEBUG_FATAL(!content.length(), ("Attempt to construct new XmlTreeNode with text, but no text sent"));
if (!content.length())
{
contentCopy = "garbage";
}
xmlNode *textNode = xmlNewText(BAD_CAST contentCopy.c_str() );
m_treeNode = xmlNewNode(NULL, BAD_CAST nameCopy.c_str());
// verify new nodes
DEBUG_FATAL(!textNode, ("Failed to create xml text node"));
DEBUG_FATAL(!m_treeNode, ("Failed to create new xml tree node"));
if ((!m_treeNode) || (!textNode))
{
m_treeNode = 0;
return;
}
// add text node to the "real" one.
xmlAddChild(m_treeNode,textNode);
}
// ----------------------------------------------------------------------
XmlTreeNode::XmlTreeNode(const std::string &name) :
m_treeNode(0)
{
std::string nameCopy = name;
// verify parameters
DEBUG_FATAL(!name.length(), ("Attempt to construct new XmlTreeNode but no name given"));
if(!name.length())
{
nameCopy = "garbage";
}
m_treeNode = xmlNewNode(NULL, BAD_CAST nameCopy.c_str());
// verify new nodes
DEBUG_FATAL(!m_treeNode, ("Failed to create new xml tree node"));
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::addChildNode(const char * name)
{
DEBUG_FATAL( !m_treeNode, ("Attempted to add child to null xml node"));
XmlTreeNode node(name);
if (m_treeNode)
{
addChild(node);
}
return node;
}
// ----------------------------------------------------------------------
void XmlTreeNode::addProperty(char const *attributeName, const std::string& value)
{
xmlNewProp(m_treeNode, BAD_CAST attributeName, BAD_CAST value.c_str());
}
// ----------------------------------------------------------------------
void XmlTreeNode::addChild( const XmlTreeNode& node )
{
xmlAddChild(m_treeNode, node.m_treeNode);
}
// ----------------------------------------------------------------------
bool XmlTreeNode::isNull() const
{
return (m_treeNode == NULL);
}
// ----------------------------------------------------------------------
bool XmlTreeNode::isElement() const
{
return (m_treeNode && (m_treeNode->type == XML_ELEMENT_NODE));
}
// ----------------------------------------------------------------------
bool XmlTreeNode::isAttribute() const
{
return (m_treeNode && (m_treeNode->type == XML_ATTRIBUTE_NODE));
}
// ----------------------------------------------------------------------
bool XmlTreeNode::isText() const
{
return (m_treeNode && (m_treeNode->type == XML_TEXT_NODE));
}
// ----------------------------------------------------------------------
void XmlTreeNode::assertIsElement(char const *const elementName) const
{
char const *const nodeName = getName();
UNREF(elementName);
UNREF(nodeName);
DEBUG_FATAL(!isElement(), ("expecting element named [%s], found non-element entity named [%s].", elementName ? elementName : "<null element name>", nodeName));
DEBUG_FATAL(_stricmp(elementName, nodeName), ("expecting element named [%s], found element named [%s] instead.", nodeName));
}
// ----------------------------------------------------------------------
char const *XmlTreeNode::getName() const
{
return (m_treeNode ? reinterpret_cast<char const*>(m_treeNode->name) : "<null tree node>");
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getNextSiblingElementNode() const
{
xmlNode *siblingNode = m_treeNode ? m_treeNode->next : NULL;
while (siblingNode && (siblingNode->type != XML_ELEMENT_NODE))
siblingNode = siblingNode->next;
return XmlTreeNode(siblingNode);
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getFirstChildNode() const
{
return XmlTreeNode(m_treeNode ? m_treeNode->children : NULL);
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getFirstChildElementNode() const
{
//-- Check if we have a NULL node.
if (!m_treeNode)
return XmlTreeNode(NULL);
//-- Look for the first child node that is an element.
xmlNode *childNode = m_treeNode->children;
while (childNode && (childNode->type != XML_ELEMENT_NODE))
childNode = childNode->next;
// Either we found a child that is an element node or we don't have a child element node.
return XmlTreeNode(childNode);
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getFirstChildTextNode() const
{
//-- Check if we have a NULL node.
if (!m_treeNode)
return XmlTreeNode(NULL);
//-- Look for the first child node that is a text node.
xmlNode *childNode = m_treeNode->children;
while (childNode && (childNode->type != XML_TEXT_NODE))
childNode = childNode->next;
// Either we found a child that is an element node or we don't have a child element node.
return XmlTreeNode(childNode);
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getElementAttributeValueNode(char const *attributeName, bool optional) const
{
UNREF(optional);
//-- Validate parameters and preconditions.
if (!isElement())
{
DEBUG_FATAL(!optional, ("getElementAttributeValueNode(): node [%s] is not an element.", m_treeNode ? reinterpret_cast<char const*>(m_treeNode->name) : "<null node>"));
return XmlTreeNode(NULL);
}
if (!attributeName)
{
DEBUG_FATAL(!optional, ("getElementAttributeValueNode(): attributeName is NULL."));
return XmlTreeNode(NULL);
}
//-- Check the attribute nodes for a match on the given name. Ignore case.
for (xmlAttr *attributeNode = m_treeNode ? m_treeNode->properties : NULL; attributeNode; attributeNode = attributeNode->next)
{
if (!_stricmp(attributeName, reinterpret_cast<char const*>(attributeNode->name)))
{
// Return the first child node of the matching attribute. This should be the first (and probably only) value node.
return XmlTreeNode(attributeNode->children);
}
}
//-- No attribute node matched the attribute name.
DEBUG_FATAL(!optional, ("getElementAttributeValueNode(): failed to find attribute [%s] on element node [%s].", attributeName, getName()));
return XmlTreeNode(NULL);
}
// ----------------------------------------------------------------------
bool XmlTreeNode::getElementAttributeAsBool(char const *attributeName, bool &value, bool optional) const
{
//-- Get the attribute node.
XmlTreeNode const attributeValueNode(getElementAttributeValueNode(attributeName, optional));
if (attributeValueNode.isNull())
return false;
//-- Get the value as text.
char const *const contents = attributeValueNode.getTextValue();
if (!contents)
{
DEBUG_FATAL(!contents, ("contents of attribute [%s] is NULL.", attributeName));
return false; //lint !e527 // unreachable // reachable in release.
}
//-- Consider "true" or "1" as true, anything else as false.
value = (contents && (!_stricmp(contents, "true") || !strcmp(contents, "1")));
return true;
}
// ----------------------------------------------------------------------
bool XmlTreeNode::getElementAttributeAsFloat(char const *attributeName, float &value, bool optional) const
{
//-- Get the attribute node.
XmlTreeNode const attributeValueNode(getElementAttributeValueNode(attributeName, optional));
if (attributeValueNode.isNull())
{
DEBUG_FATAL(!optional, ("Attribute [%s] does not exist.", attributeName));
return false;
}
//-- Get the value as text.
char const *const contents = attributeValueNode.getTextValue();
if (!contents)
{
DEBUG_FATAL(!contents, ("contents of attribute [%s] is NULL.", attributeName));
return false; //lint !e527 // unreachable // reachable in release.
}
//-- Consider "true" or "1" as true, anything else as false.
int const scanCount = sscanf(contents, "%f", &value);
if (scanCount != 1)
{
DEBUG_FATAL(!optional, ("could not convert [%s] into a float", contents));
return false;
}
return true;
}
// ----------------------------------------------------------------------
bool XmlTreeNode::getElementAttributeAsInt(char const *attributeName, int &value, bool optional) const
{
//-- Get the attribute node.
XmlTreeNode const attributeValueNode(getElementAttributeValueNode(attributeName, optional));
if (attributeValueNode.isNull())
{
DEBUG_FATAL(!optional, ("Attribute [%s] does not exist.", attributeName));
return false;
}
//-- Get the value as text.
char const *const contents = attributeValueNode.getTextValue();
if (!contents)
{
DEBUG_FATAL(!contents, ("contents of attribute [%s] is NULL.", attributeName));
return false; //lint !e527 // unreachable // reachable in release.
}
//-- Consider "true" or "1" as true, anything else as false.
int const scanCount = sscanf(contents, "%d", &value);
if (scanCount != 1)
{
DEBUG_FATAL(!optional, ("could not convert [%s] into an integer", contents));
return false;
}
return true;
}
// ----------------------------------------------------------------------
bool XmlTreeNode::getElementAttributeAsString(char const *attributeName, std::string &value, bool optional) const
{
//-- Get the attribute node.
XmlTreeNode const attributeValueNode(getElementAttributeValueNode(attributeName, optional));
if (attributeValueNode.isNull())
return false;
//-- Get the value as text.
value = attributeValueNode.getTextValue();
return true;
}
// ----------------------------------------------------------------------
// Note that this method is somewhat limited. It's not going to handle embedded elements
// within a text node well. Specifically, a node that looks like:
// <parent>this is<embedded/> some text</parent>
// would most likely return the text "this is", if called on the parent of the text.
// If this becomes an issue, you'll either need to manually iterate
// over the nodes contained by the parent, calling getTextValue() on
// each one that's a text node, or expand this method to do so for you, in cases
// where it is called on a parent of a text node.
char const *XmlTreeNode::getTextValue() const
{
XmlTreeNode node = *this;
// if we're not a text node, see if one of our children is. If so, it's pretty clear
// what was intended, and we should Do The Right Thing.
if(!isText())
{
// to compile, we have to call this off of our constructed node.
// we're a const method, and getChildNodeNamed() is not. However,
// in reality it's the xmlNode contained by us that does the changing,
// not ourself.
//
// getChildNodeNamed() should probably be turned to const, but to be safe I'm
// leaving it so that nothing breaks.
node = node.getChildNodeNamed("text");
}
//-- Ensure we're a text node.
if(!node.isText())
{
DEBUG_FATAL(true, ("node [%s] is not a text node", m_treeNode ? reinterpret_cast<char const*>(m_treeNode->name) : "<null>"));
return NULL; //lint !e527 // unreachable // reachable in release.
}
//-- Return contents.
return node.m_treeNode ? reinterpret_cast<char const*>(node.m_treeNode->content) : NULL;
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getChildNodeNamed(const char * name)
{
XmlTreeNode node = getFirstChildNode();
while(!node.isNull() && _stricmp(node.getName(), name))
node = node.getNextSiblingElementNode();
return node;
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getChildElementNodeNamed(const char * name)
{
XmlTreeNode node = getFirstChildNode();
while(!node.isNull() && (!node.isElement() || _stricmp(node.getName(), name)))
node = node.getNextSiblingElementNode();
return node;
}
// ----------------------------------------------------------------------
XmlTreeNode XmlTreeNode::getTextChildNodeNamed(const char * name)
{
XmlTreeNode node = getChildNodeNamed(name);
if(!node.isNull())
node = node.getChildNodeNamed("text");
return node;
}
// ======================================================================

View File

@@ -0,0 +1,155 @@
// ======================================================================
//
// XmlTreeNode.h
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#ifndef INCLUDED_XmlTreeNode_H
#define INCLUDED_XmlTreeNode_H
#include<iostream>
#include<sstream>
// ======================================================================
struct _xmlNode;
typedef struct _xmlNode xmlNode;
// ======================================================================
class XmlTreeNode
{
public:
explicit XmlTreeNode(xmlNode *treeNode);
XmlTreeNode(XmlTreeNode const &rhs);
explicit XmlTreeNode(const std::string &name);
explicit XmlTreeNode(const std::string &name, const std::string &content);
XmlTreeNode &operator =(const XmlTreeNode &rhs);
bool isNull() const;
bool isElement() const;
bool isAttribute() const;
bool isText() const;
void assertIsElement(char const *const elementName) const;
char const *getName() const;
XmlTreeNode getNextSiblingElementNode() const;
XmlTreeNode getFirstChildNode() const;
XmlTreeNode getFirstChildElementNode() const;
XmlTreeNode getFirstChildTextNode() const;
//-- Functions to call on element nodes.
XmlTreeNode getElementAttributeValueNode(char const *attributeName, bool optional) const;
XmlTreeNode getChildNodeNamed(const char * name);
XmlTreeNode getChildElementNodeNamed(const char * name);
XmlTreeNode getTextChildNodeNamed(const char * name);
XmlTreeNode addChildNode(char const * name);
template <class T> XmlTreeNode addChildTextNode(char const * name, const T &value);
template <class T> void setElementAttribute(char const *attributeName, const T &value);
void getElementAttributeAsBool(char const *attributeName, bool &value) const;
void getElementAttributeAsFloat(char const *attributeName, float &value) const;
void getElementAttributeAsInt(char const *attributeName, int &value) const;
void getElementAttributeAsString(char const *attributeName, std::string &value) const;
bool getElementAttributeAsBool(char const *attributeName, bool &value, bool optional) const;
bool getElementAttributeAsFloat(char const *attributeName, float &value, bool optional) const;
bool getElementAttributeAsInt(char const *attributeName, int &value, bool optional) const;
bool getElementAttributeAsString(char const *attributeName, std::string &value, bool optional) const;
//-- Functions to call on text nodes.
char const *getTextValue() const;
private:
// Disabled.
XmlTreeNode();
void addProperty( char const *attributeName, const std::string& value);
void addChild(const XmlTreeNode &node);
private:
xmlNode *m_treeNode;
};
// ======================================================================
inline XmlTreeNode::XmlTreeNode(xmlNode *treeNode) :
m_treeNode(treeNode)
{
}
// ----------------------------------------------------------------------
inline XmlTreeNode::XmlTreeNode(XmlTreeNode const &rhs) :
m_treeNode(rhs.m_treeNode) //lint !e1554 // Direct pointer copy. This is okay, this class is simply a wrapper for one of these pointers.
{
}
// ----------------------------------------------------------------------
inline XmlTreeNode &XmlTreeNode::operator =(const XmlTreeNode &rhs)
{
m_treeNode = rhs.m_treeNode;
return *this;
}
// ----------------------------------------------------------------------
inline void XmlTreeNode::getElementAttributeAsBool(char const *attributeName, bool &value) const
{
IGNORE_RETURN(getElementAttributeAsBool(attributeName, value, false));
}
// ----------------------------------------------------------------------
inline void XmlTreeNode::getElementAttributeAsFloat(char const *attributeName, float &value) const
{
IGNORE_RETURN(getElementAttributeAsFloat(attributeName, value, false));
}
// ----------------------------------------------------------------------
inline void XmlTreeNode::getElementAttributeAsInt(char const *attributeName, int &value) const
{
IGNORE_RETURN(getElementAttributeAsInt(attributeName, value, false));
}
// ----------------------------------------------------------------------
inline void XmlTreeNode::getElementAttributeAsString(char const *attributeName, std::string &value) const
{
IGNORE_RETURN(getElementAttributeAsString(attributeName, value, false));
}
// ======================================================================
template<class T> void XmlTreeNode::setElementAttribute( char const *attributeName, const T &value)
{
std::ostringstream oss;
oss << value;
addProperty(attributeName, oss.str());
}
// ----------------------------------------------------------------------
template <class T> XmlTreeNode XmlTreeNode::addChildTextNode(const char * name, const T &value)
{
std::ostringstream oss;
oss << value;
XmlTreeNode node(name, oss.str());
addChild( node );
return node;
}
#endif

View File

@@ -0,0 +1,11 @@
// ======================================================================
//
// FirstSharedXml.cpp
// Copyright 2004 Sony Online Entertainment, Inc.
// All Rights Reserved.
//
// ======================================================================
#include "sharedXml/FirstSharedXml.h"
// ======================================================================