X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4c43dd9078b2f9f8bb280020a878932272d0163e..5a61da16c593ba50964e7925525c128c73464c8a:/src/xml/xml.cpp diff --git a/src/xml/xml.cpp b/src/xml/xml.cpp index 619f93ab51..067cd02319 100644 --- a/src/xml/xml.cpp +++ b/src/xml/xml.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: xml.cpp +// Name: src/xml/xml.cpp // Purpose: wxXmlDocument - XML parser & data holder class // Author: Vaclav Slavik // Created: 2000/03/05 @@ -15,21 +15,24 @@ #pragma hdrstop #endif +#if wxUSE_XML + #include "wx/xml/xml.h" -#if wxUSE_XML +#ifndef WX_PRECOMP + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/app.h" +#endif #include "wx/wfstream.h" #include "wx/datstrm.h" #include "wx/zstream.h" -#include "wx/log.h" -#include "wx/intl.h" #include "wx/strconv.h" #include "expat.h" // from Expat // DLL options compatibility check: -#include "wx/app.h" WX_CHECK_BUILD_OPTIONS("wxXML") @@ -175,21 +178,40 @@ void wxXmlNode::AddChild(wxXmlNode *child) child->m_parent = this; } -void wxXmlNode::InsertChild(wxXmlNode *child, wxXmlNode *before_node) +bool wxXmlNode::InsertChild(wxXmlNode *child, wxXmlNode *before_node) { - wxASSERT_MSG(before_node->GetParent() == this, wxT("wxXmlNode::InsertChild - the node has incorrect parent")); + wxCHECK_MSG(before_node == NULL || before_node->GetParent() == this, false, + wxT("wxXmlNode::InsertChild - the node has incorrect parent")); + wxCHECK_MSG(child, false, wxT("Cannot insert a NULL pointer!")); if (m_children == before_node) m_children = child; + else if (m_children == NULL) + { + if (before_node != NULL) + return false; // we have no children so we don't need to search + m_children = child; + } + else if (before_node == NULL) + { + // prepend child + child->m_parent = this; + child->m_next = m_children; + m_children = child; + return true; + } else { wxXmlNode *ch = m_children; - while (ch->m_next != before_node) ch = ch->m_next; + while (ch && ch->m_next != before_node) ch = ch->m_next; + if (!ch) + return false; // before_node not found ch->m_next = child; } child->m_parent = this; child->m_next = before_node; + return true; } bool wxXmlNode::RemoveChild(wxXmlNode *child) @@ -345,12 +367,16 @@ void wxXmlDocument::DoCopy(const wxXmlDocument& doc) bool wxXmlDocument::Load(const wxString& filename, const wxString& encoding) { wxFileInputStream stream(filename); + if (!stream.Ok()) + return false; return Load(stream, encoding); } bool wxXmlDocument::Save(const wxString& filename) const { wxFileOutputStream stream(filename); + if (!stream.Ok()) + return false; return Save(stream); } @@ -365,29 +391,30 @@ bool wxXmlDocument::Save(const wxString& filename) const - process all elements, including CDATA */ -// converts Expat-produced string in UTF-8 into wxString. -inline static wxString CharToString(wxMBConv *conv, +// converts Expat-produced string in UTF-8 into wxString using the specified +// conv or keep in UTF-8 if conv is NULL +static wxString CharToString(wxMBConv *conv, const char *s, size_t len = wxSTRING_MAXLEN) { #if wxUSE_UNICODE - (void)conv; + wxUnusedVar(conv); + return wxString(s, wxConvUTF8, len); -#else +#else // !wxUSE_UNICODE if ( conv ) { - size_t nLen = (len != wxSTRING_MAXLEN) ? len : - wxConvUTF8.MB2WC((wchar_t*) NULL, s, 0); + // there can be no embedded NULs in this string so we don't need the + // output length, it will be NUL-terminated + const wxWCharBuffer wbuf( + wxConvUTF8.cMB2WC(s, len == wxSTRING_MAXLEN ? wxNO_LEN : len, NULL)); - wchar_t *buf = new wchar_t[nLen+1]; - wxConvUTF8.MB2WC(buf, s, nLen); - buf[nLen] = 0; - wxString str(buf, *conv, len); - delete[] buf; - return str; + return wxString(wbuf, *conv); } - else + else // already in UTF-8, no conversion needed + { return wxString(s, len != wxSTRING_MAXLEN ? len : strlen(s)); -#endif + } +#endif // wxUSE_UNICODE/!wxUSE_UNICODE } struct wxXmlParsingContext @@ -398,6 +425,7 @@ struct wxXmlParsingContext wxXmlNode *lastAsText; wxString encoding; wxString version; + bool bLastCdata; }; extern "C" { @@ -441,8 +469,16 @@ static void TextHnd(void *userData, const char *s, int len) if (ctx->lastAsText) { - ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + + if ( ctx->bLastCdata ) + { + ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + + CharToString(NULL, buf)); + } + else + { + ctx->lastAsText->SetContent(ctx->lastAsText->GetContent() + CharToString(ctx->conv, buf)); + } } else { @@ -465,6 +501,27 @@ static void TextHnd(void *userData, const char *s, int len) } } +extern "C" { +static void StartCdataHnd(void *userData) +{ + wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; + + ctx->bLastCdata = true; + + ctx->lastAsText = new wxXmlNode(wxXML_CDATA_SECTION_NODE, wxT("cdata"),wxT("")); + ctx->node->AddChild(ctx->lastAsText); +} +} + +extern "C" { +static void EndCdataHnd(void *userData) +{ + wxXmlParsingContext *ctx = (wxXmlParsingContext*)userData; + + ctx->bLastCdata = false; +} +} + extern "C" { static void CommentHnd(void *userData, const char *data) { @@ -557,10 +614,12 @@ bool wxXmlDocument::Load(wxInputStream& stream, const wxString& encoding) if ( encoding != wxT("UTF-8") && encoding != wxT("utf-8") ) ctx.conv = new wxCSConv(encoding); #endif + ctx.bLastCdata = false; XML_SetUserData(parser, (void*)&ctx); XML_SetElementHandler(parser, StartElementHnd, EndElementHnd); XML_SetCharacterDataHandler(parser, TextHnd); + XML_SetCdataSectionHandler(parser, StartCdataHnd, EndCdataHnd ); XML_SetCommentHandler(parser, CommentHnd); XML_SetDefaultHandler(parser, DefaultHnd); XML_SetUnknownEncodingHandler(parser, UnknownEncodingHnd, NULL); @@ -703,6 +762,12 @@ static void OutputNode(wxOutputStream& stream, wxXmlNode *node, int indent, switch (node->GetType()) { + case wxXML_CDATA_SECTION_NODE: + OutputString( stream, wxT("GetContent() ); + OutputString( stream, wxT("]]>") ); + break; + case wxXML_TEXT_NODE: OutputStringEnt(stream, node->GetContent(), convMem, convFile); break;