X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ca7408bd9ab49ba525517eb03c6b861c850c3199..56d2f75071fc2a29ec10abe97c5a908bb35f30f4:/contrib/src/xml/xmlpars.cpp?ds=sidebyside diff --git a/contrib/src/xml/xmlpars.cpp b/contrib/src/xml/xmlpars.cpp new file mode 100644 index 0000000000..797c76d0a9 --- /dev/null +++ b/contrib/src/xml/xmlpars.cpp @@ -0,0 +1,283 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: xmlpars.cpp +// Purpose: wxXmlDocument - XML parser +// Author: Vaclav Slavik +// Created: 2000/03/05 +// RCS-ID: $Id$ +// Copyright: (c) 2000 Vaclav Slavik +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ +// nothing - already in xml.cpp +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/wfstream.h" +#include "wx/intl.h" +#include "wx/log.h" +#include "wx/dynlib.h" +#include "wx/xml/xmlio.h" + +#include + +// dynamically loaded functions from libxml: +typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt) + (xmlSAXHandlerPtr sax, void *, const char *, int, const char *); +typedef xmlNodePtr (*type_xmlNewText)(const xmlChar *); +typedef xmlAttrPtr (*type_xmlSetProp)(xmlNodePtr, const xmlChar *, const xmlChar *); +typedef int (*type_xmlParseChunk)(xmlParserCtxtPtr, const char *, int, int); +typedef void (*type_xmlFreeParserCtxt)(xmlParserCtxtPtr); +typedef xmlDocPtr (*type_xmlNewDoc)(const xmlChar *); +typedef void (*type_xmlFreeDoc)(xmlDocPtr); +typedef xmlNodePtr (*type_xmlNewDocNode)(xmlDocPtr, xmlNsPtr, const xmlChar *, const xmlChar *); +typedef void (*type_xmlDocDumpMemory)(xmlDocPtr, xmlChar**, int *); +typedef xmlNodePtr (*type_xmlAddChild)(xmlNodePtr, xmlNodePtr); +typedef xmlNodePtr (*type_xmlNewChild)(xmlNodePtr, xmlNsPtr, const xmlChar *, const xmlChar *); +typedef xmlChar * (*type_xmlNodeListGetString)(xmlDocPtr, xmlNodePtr, int); +typedef xmlNodePtr (*type_xmlDocGetRootElement)(xmlDocPtr); +typedef xmlNodePtr (*type_xmlDocSetRootElement)(xmlDocPtr doc, xmlNodePtr root); + +static struct +{ + wxDllType Handle; + + type_xmlCreatePushParserCtxt xmlCreatePushParserCtxt; + type_xmlNewText xmlNewText; + type_xmlSetProp xmlSetProp; + type_xmlParseChunk xmlParseChunk; + type_xmlFreeParserCtxt xmlFreeParserCtxt; + type_xmlNewDoc xmlNewDoc; + type_xmlFreeDoc xmlFreeDoc; + type_xmlNewDocNode xmlNewDocNode; + type_xmlDocDumpMemory xmlDocDumpMemory; + type_xmlAddChild xmlAddChild; + type_xmlNewChild xmlNewChild; + type_xmlNodeListGetString xmlNodeListGetString; + type_xmlDocGetRootElement xmlDocGetRootElement; + type_xmlDocSetRootElement xmlDocSetRootElement; +} gs_libxmlDLL; + +static bool gs_libxmlLoaded = FALSE; +static bool gs_libxmlLoadFailed = FALSE; + + + +static void ReleaseLibxml() +{ + if (gs_libxmlLoaded) + { + wxLogDebug("Releasing libxml.so.2"); + wxDllLoader::UnloadLibrary(gs_libxmlDLL.Handle); + } + gs_libxmlLoaded = FALSE; + gs_libxmlLoadFailed = FALSE; +} + + +static bool LoadLibxml() +{ + if (gs_libxmlLoaded) return TRUE; + if (gs_libxmlLoadFailed) return FALSE; + gs_libxmlLoadFailed = TRUE; + + wxLogDebug("Loading libxml.so.2..."); +#ifdef __UNIX__ + gs_libxmlDLL.Handle = + wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded); +#endif + + if (!gs_libxmlLoaded) return FALSE; + +#define LOAD_SYMBOL(sym) \ + gs_libxmlDLL.sym = \ + (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \ + if (!gs_libxmlDLL.sym) { ReleaseLibxml(); return FALSE; } + + LOAD_SYMBOL(xmlCreatePushParserCtxt) + LOAD_SYMBOL(xmlNewText) + LOAD_SYMBOL(xmlSetProp) + LOAD_SYMBOL(xmlParseChunk) + LOAD_SYMBOL(xmlFreeParserCtxt) + LOAD_SYMBOL(xmlNewDoc) + LOAD_SYMBOL(xmlFreeDoc) + LOAD_SYMBOL(xmlNewDocNode) + LOAD_SYMBOL(xmlDocDumpMemory) + LOAD_SYMBOL(xmlAddChild) + LOAD_SYMBOL(xmlNewChild) + LOAD_SYMBOL(xmlNodeListGetString) + LOAD_SYMBOL(xmlDocGetRootElement) + LOAD_SYMBOL(xmlDocSetRootElement) + +#undef LOAD_SYMBOL + + gs_libxmlLoadFailed = FALSE; + + wxLogDebug("...succeed"); + return TRUE; +} + + + + +bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream& stream) +{ + if (!LoadLibxml()) return FALSE; + char cheader[7]; + cheader[6] = 0; + stream.Read(cheader, 6); + stream.SeekI(-6, wxFromCurrent); + return strcmp(cheader, "children, 1); + wxXmlProperty *prop = + new wxXmlProperty(attr->name, val, CreateWXProperty(doc, attr->next)); + free(val); + return prop; +} + + + +static wxXmlNode *CreateWXNode(xmlDocPtr doc, wxXmlNode *parent, xmlNodePtr node) +{ + if (node == NULL) return NULL; + + wxXmlNode *nd = new wxXmlNode(parent, (wxXmlNodeType)node->type, + node->name, node->content, + CreateWXProperty(doc, node->properties), + CreateWXNode(doc, parent, node->next)); + CreateWXNode(doc, nd, node->children); + return nd; +} + + + +bool wxXmlIOHandlerLibxml::Load(wxInputStream& stream, wxXmlDocument& doc) +{ + if (!LoadLibxml()) return FALSE; + + xmlDocPtr dc; + xmlParserCtxtPtr ctxt; + + char buffer[1024]; + int res; + + res = stream.Read(buffer, 4).LastRead(); + if (res > 0) + { + bool okay = TRUE; + ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(NULL, NULL, + buffer, res, ""/*docname*/); + while ((res = stream.Read(buffer, 1024).LastRead()) > 0) + if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, res, 0) != 0) + okay = FALSE; + if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, 0, 1) != 0) okay = FALSE; + dc = ctxt->myDoc; + gs_libxmlDLL.xmlFreeParserCtxt(ctxt); + + doc.SetVersion(dc->version); + doc.SetEncoding(dc->encoding); + doc.SetRoot(CreateWXNode(dc, NULL, gs_libxmlDLL.xmlDocGetRootElement(dc))); + + gs_libxmlDLL.xmlFreeDoc(dc); + + return okay; + } + else return FALSE; +} + + + +static void CreateLibxmlNode(xmlNodePtr node, wxXmlNode *wxnode) +{ + node->type = (xmlElementType)wxnode->GetType(); + + wxXmlProperty *prop = wxnode->GetProperties(); + while (prop) + { + gs_libxmlDLL.xmlSetProp(node, (xmlChar*)prop->GetName().mb_str(), + (xmlChar*)prop->GetValue().mb_str()); + prop = prop->GetNext(); + } + + wxXmlNode *child = wxnode->GetChildren(); + xmlNodePtr n; + xmlChar *content, *name; + + while (child) + { + name = (xmlChar*)child->GetName().mb_str(); + if (!child->GetContent()) content = NULL; + else content = (xmlChar*)child->GetContent().mb_str(); + if (child->GetType() == wxXML_TEXT_NODE) + gs_libxmlDLL.xmlAddChild(node, n = gs_libxmlDLL.xmlNewText(content)); + else + n = gs_libxmlDLL.xmlNewChild(node, NULL, name, content); + CreateLibxmlNode(n, child); + child = child->GetNext(); + } +} + + + +bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc) +{ + if (!LoadLibxml()) return FALSE; + + xmlDocPtr dc; + + wxASSERT_MSG(doc.GetRoot() != NULL, _("Trying to save empty document!")); + + dc = gs_libxmlDLL.xmlNewDoc((xmlChar*)doc.GetVersion().mb_str()); + + gs_libxmlDLL.xmlDocSetRootElement(dc, + gs_libxmlDLL.xmlNewDocNode(dc, NULL, + (xmlChar*)doc.GetRoot()->GetName().mb_str(), NULL)); + CreateLibxmlNode(gs_libxmlDLL.xmlDocGetRootElement(dc), doc.GetRoot()); + + xmlChar *buffer; + int size; + + gs_libxmlDLL.xmlDocDumpMemory(dc, &buffer, &size); + gs_libxmlDLL.xmlFreeDoc(dc); + stream.Write(buffer, size); + free(buffer); + return stream.LastWrite() == (unsigned)size; +} + + + + +#include "wx/module.h" + +class wxXmlLibxmlModule: public wxModule +{ + DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule) + public: + wxXmlLibxmlModule() {} + bool OnInit() { return TRUE; } + void OnExit() { ReleaseLibxml(); } +}; + +IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule, wxModule)