summaryrefslogtreecommitdiff
path: root/cpp/src/IceXML/Parser.cpp
diff options
context:
space:
mode:
authorJoe George <joe@zeroc.com>2015-03-03 17:30:50 -0500
committerJoe George <joe@zeroc.com>2015-05-12 11:41:55 -0400
commitd35bb9f5c19e34aee31f83d445695a8186ef675e (patch)
treed5324eaf44f5f9776495537c51653f50a66a7237 /cpp/src/IceXML/Parser.cpp
downloadice-d35bb9f5c19e34aee31f83d445695a8186ef675e.tar.bz2
ice-d35bb9f5c19e34aee31f83d445695a8186ef675e.tar.xz
ice-d35bb9f5c19e34aee31f83d445695a8186ef675e.zip
Ice 3.4.2 Source Distributionv3.4.2
Diffstat (limited to 'cpp/src/IceXML/Parser.cpp')
-rw-r--r--cpp/src/IceXML/Parser.cpp426
1 files changed, 426 insertions, 0 deletions
diff --git a/cpp/src/IceXML/Parser.cpp b/cpp/src/IceXML/Parser.cpp
new file mode 100644
index 00000000000..8405f7c05a0
--- /dev/null
+++ b/cpp/src/IceXML/Parser.cpp
@@ -0,0 +1,426 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+#include <IceXML/Parser.h>
+#include <IceUtil/Unicode.h>
+#include <IceUtil/FileUtil.h>
+#include <expat.h>
+#include <list>
+
+using namespace std;
+using namespace IceXML;
+
+//
+// ParserException
+//
+IceXML::ParserException::ParserException(const string& reason) :
+ IceUtil::Exception(), _reason(reason)
+{
+}
+
+IceXML::ParserException::ParserException(const char* file, int line, const string& reason) :
+ IceUtil::Exception(file, line), _reason(reason)
+{
+}
+
+IceXML::ParserException::~ParserException() throw()
+{
+}
+
+const char* IceXML::ParserException::_name = "IceXML::ParserException";
+
+string
+IceXML::ParserException::ice_name() const
+{
+ return _name;
+}
+
+void
+IceXML::ParserException::ice_print(std::ostream& out) const
+{
+#ifdef __BCPLUSPLUS__
+ IceUtil::Exception::ice_print(out);
+#else
+ Exception::ice_print(out);
+#endif
+ if(!_reason.empty())
+ {
+ out << "\n" << _reason;
+ }
+ else
+ {
+ out << ":\nXML parser exception";
+ }
+}
+
+IceUtil::Exception*
+IceXML::ParserException::ice_clone() const
+{
+ return new ParserException(*this);
+}
+
+void
+IceXML::ParserException::ice_throw() const
+{
+ throw *this;
+}
+
+string
+IceXML::ParserException::reason() const
+{
+ return _reason;
+}
+
+//
+// Node
+//
+IceXML::Node::Node(const NodePtr& parent, const string& name, const string& value, int line, int column) :
+ _parent(parent), _name(name), _value(value), _line(line), _column(column)
+{
+}
+
+IceXML::Node::~Node()
+{
+}
+
+IceXML::NodePtr
+IceXML::Node::getParent() const
+{
+ return _parent;
+}
+
+string
+IceXML::Node::getName() const
+{
+ return _name;
+}
+
+string
+IceXML::Node::getValue() const
+{
+ return _value;
+}
+
+IceXML::NodeList
+IceXML::Node::getChildren() const
+{
+ return NodeList();
+}
+
+IceXML::Attributes
+IceXML::Node::getAttributes() const
+{
+ return Attributes();
+}
+
+string
+IceXML::Node::getAttribute(const string&) const
+{
+ return string();
+}
+
+bool
+IceXML::Node::addChild(const NodePtr&)
+{
+ return false;
+}
+
+int
+IceXML::Node::getLine() const
+{
+ return _line;
+}
+
+int
+IceXML::Node::getColumn() const
+{
+ return _column;
+}
+
+//
+// Element
+//
+IceXML::Element::Element(const NodePtr& parent, const string& name, const Attributes& attributes, int line,
+ int column) :
+ Node(parent, name, "", line, column), _attributes(attributes)
+{
+}
+
+IceXML::Element::~Element()
+{
+}
+
+IceXML::NodeList
+IceXML::Element::getChildren() const
+{
+ return _children;
+}
+
+IceXML::Attributes
+IceXML::Element::getAttributes() const
+{
+ return _attributes;
+}
+
+string
+IceXML::Element::getAttribute(const string& name) const
+{
+ Attributes::const_iterator p = _attributes.find(name);
+ if(p != _attributes.end())
+ {
+ return p->second;
+ }
+ return string();
+}
+
+bool
+IceXML::Element::addChild(const NodePtr& child)
+{
+ _children.push_back(child);
+ return true;
+}
+
+//
+// Text
+//
+IceXML::Text::Text(const NodePtr& parent, const string& value, int line, int column) :
+ Node(parent, "", value, line, column)
+{
+}
+
+IceXML::Text::~Text()
+{
+}
+
+//
+// Document
+//
+IceXML::Document::Document() :
+ Node(0, "", "", 0, 0)
+{
+}
+
+IceXML::Document::~Document()
+{
+}
+
+IceXML::NodeList
+IceXML::Document::getChildren() const
+{
+ return _children;
+}
+
+bool
+IceXML::Document::addChild(const NodePtr& child)
+{
+ _children.push_back(child);
+ return true;
+}
+
+//
+// Handler
+//
+IceXML::Handler::~Handler()
+{
+}
+
+void
+IceXML::Handler::error(const string& msg, int line, int column)
+{
+ ostringstream out;
+ out << "XML error at input line " << line << ", column " << column << ":" << endl << msg;
+ throw ParserException(__FILE__, __LINE__, out.str());
+}
+
+//
+// DocumentBuilder
+//
+namespace IceXML
+{
+
+class DocumentBuilder : public Handler
+{
+public:
+ DocumentBuilder();
+
+ virtual void startElement(const string&, const Attributes&, int, int);
+ virtual void endElement(const string&, int, int);
+ virtual void characters(const string&, int, int);
+
+ DocumentPtr getDocument() const;
+
+private:
+ list<NodePtr> _nodeStack;
+ DocumentPtr _document;
+};
+
+}
+
+IceXML::DocumentBuilder::DocumentBuilder()
+{
+ _document = new Document;
+ _nodeStack.push_front(_document);
+}
+
+void
+IceXML::DocumentBuilder::startElement(const string& name, const Attributes& attributes, int line, int column)
+{
+ NodePtr parent = _nodeStack.front();
+
+ Element* element = new Element(parent, name, attributes, line, column);
+#ifdef NDEBUG
+ parent->addChild(element);
+#else
+ assert(parent->addChild(element));
+#endif
+
+ _nodeStack.push_front(element);
+}
+
+void
+IceXML::DocumentBuilder::endElement(const string& name, int, int)
+{
+ assert(!_nodeStack.empty());
+ _nodeStack.pop_front();
+}
+
+void
+IceXML::DocumentBuilder::characters(const string& data, int line, int column)
+{
+ NodePtr parent = _nodeStack.front();
+ TextPtr text = new Text(parent, data, line, column);
+ parent->addChild(text);
+}
+
+DocumentPtr
+IceXML::DocumentBuilder::getDocument() const
+{
+ return _document;
+}
+
+//
+// expat callbacks
+//
+struct CallbackData
+{
+ XML_Parser parser;
+ Handler* handler;
+};
+
+extern "C"
+{
+
+static void
+startElementHandler(void* data, const XML_Char* name, const XML_Char** attr)
+{
+ CallbackData* cb = static_cast<CallbackData*>(data);
+
+ Attributes attributes;
+ for(int i = 0; attr[i]; i += 2)
+ {
+ attributes[attr[i]] = attr[i + 1];
+ }
+
+ int line = XML_GetCurrentLineNumber(cb->parser);
+ int column = XML_GetCurrentColumnNumber(cb->parser);
+ cb->handler->startElement(name, attributes, line, column);
+}
+
+static void
+endElementHandler(void* data, const XML_Char* name)
+{
+ CallbackData* cb = static_cast<CallbackData*>(data);
+ int line = XML_GetCurrentLineNumber(cb->parser);
+ int column = XML_GetCurrentColumnNumber(cb->parser);
+ cb->handler->endElement(name, line, column);
+}
+
+static void
+characterDataHandler(void* data, const XML_Char* s, int len)
+{
+ CallbackData* cb = static_cast<CallbackData*>(data);
+
+ string str(s, len);
+ int line = XML_GetCurrentLineNumber(cb->parser);
+ int column = XML_GetCurrentColumnNumber(cb->parser);
+ cb->handler->characters(str, line, column);
+}
+
+}
+
+//
+// Parser
+//
+IceXML::DocumentPtr
+IceXML::Parser::parse(const string& file)
+{
+ DocumentBuilder builder;
+ parse(file, builder);
+ return builder.getDocument();
+}
+
+IceXML::DocumentPtr
+IceXML::Parser::parse(istream& in)
+{
+ DocumentBuilder builder;
+ parse(in, builder);
+ return builder.getDocument();
+}
+
+void
+IceXML::Parser::parse(const string& file, Handler& handler) // The given filename must be UTF-8 encoded
+{
+ IceUtilInternal::ifstream in(file);
+ if(!in.good())
+ {
+ ostringstream out;
+ out << "unable to open file `" << file << "'";
+ throw ParserException(__FILE__, __LINE__, out.str());
+ }
+ parse(in, handler);
+}
+
+void
+IceXML::Parser::parse(istream& in, Handler& handler)
+{
+ XML_Parser parser = XML_ParserCreate(NULL);
+ CallbackData cb;
+ cb.parser = parser;
+ cb.handler = &handler;
+ XML_SetUserData(parser, &cb);
+ XML_SetElementHandler(parser, startElementHandler, endElementHandler);
+ XML_SetCharacterDataHandler(parser, characterDataHandler);
+
+ try
+ {
+ char buff[1024];
+ int isFinal = 0;
+ while(!isFinal)
+ {
+ in.read(buff, 1024);
+ if(in.gcount() < 1024)
+ {
+ isFinal = 1;
+ }
+ if(XML_Parse(parser, buff, static_cast<int>(in.gcount()), isFinal) != 1)
+ {
+ handler.error(XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser));
+ return;
+ }
+ }
+ }
+ catch(...)
+ {
+ XML_ParserFree(parser);
+ throw;
+ }
+
+ XML_ParserFree(parser);
+}