summaryrefslogtreecommitdiff
path: root/cpp/src/IceXML/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/IceXML/Parser.cpp')
-rw-r--r--cpp/src/IceXML/Parser.cpp378
1 files changed, 378 insertions, 0 deletions
diff --git a/cpp/src/IceXML/Parser.cpp b/cpp/src/IceXML/Parser.cpp
new file mode 100644
index 00000000000..68fb3b372ff
--- /dev/null
+++ b/cpp/src/IceXML/Parser.cpp
@@ -0,0 +1,378 @@
+// **********************************************************************
+//
+// Copyright (c) 2003
+// ZeroC, Inc.
+// Billerica, MA, USA
+//
+// All Rights Reserved.
+//
+// Ice is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License version 2 as published by
+// the Free Software Foundation.
+//
+// **********************************************************************
+
+#include <IceXML/Parser.h>
+#include <expat.h>
+#include <list>
+#include <fstream>
+
+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)
+{
+}
+
+string
+IceXML::ParserException::ice_name() const
+{
+ return "IceXML::ParserException";
+}
+
+void
+IceXML::ParserException::ice_print(std::ostream& out) const
+{
+ Exception::ice_print(out);
+ 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;
+}
+
+//
+// Node
+//
+IceXML::Node::Node(const NodePtr& parent, const string& name, const string& value) :
+ _parent(parent), _name(name), _value(value)
+{
+}
+
+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& name) const
+{
+ return string();
+}
+
+bool
+IceXML::Node::addChild(const NodePtr& child)
+{
+ return false;
+}
+
+//
+// Element
+//
+IceXML::Element::Element(const NodePtr& parent, const string& name, const Attributes& attributes) :
+ Node(parent, name, ""), _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) :
+ Node(parent, "", value)
+{
+}
+
+IceXML::Text::~Text()
+{
+}
+
+//
+// Document
+//
+IceXML::Document::Document() :
+ Node(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 col)
+{
+ ostringstream out;
+ out << "XML error at input line " << line << ", column " << col << ":" << endl << msg;
+ throw ParserException(__FILE__, __LINE__, out.str());
+}
+
+//
+// DocumentBuilder
+//
+namespace IceXML
+{
+
+class DocumentBuilder : public Handler
+{
+public:
+ DocumentBuilder();
+
+ virtual void startElement(const string&, const Attributes&);
+ virtual void endElement(const string&);
+ virtual void characters(const string&);
+
+ 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)
+{
+ NodePtr parent = _nodeStack.front();
+
+ Element* element = new Element(parent, name, attributes);
+ bool b = parent->addChild(element);
+ assert(b);
+
+ _nodeStack.push_front(element);
+}
+
+void
+IceXML::DocumentBuilder::endElement(const string& name)
+{
+ assert(!_nodeStack.empty());
+ _nodeStack.pop_front();
+}
+
+void
+IceXML::DocumentBuilder::characters(const string& data)
+{
+ NodePtr parent = _nodeStack.front();
+ TextPtr text = new Text(parent, data);
+ parent->addChild(text);
+}
+
+DocumentPtr
+IceXML::DocumentBuilder::getDocument() const
+{
+ return _document;
+}
+
+//
+// expat callbacks
+//
+static void
+startElementHandler(void* data, const XML_Char* name, const XML_Char** attr)
+{
+ Handler* handler = static_cast<Handler*>(data);
+
+ Attributes attributes;
+ for(int i = 0; attr[i]; i += 2)
+ {
+ attributes[attr[i]] = attr[i + 1];
+ }
+
+ handler->startElement(name, attributes);
+}
+
+static void
+endElementHandler(void* data, const XML_Char* name)
+{
+ Handler* handler = static_cast<Handler*>(data);
+ handler->endElement(name);
+}
+
+static void
+characterDataHandler(void* data, const XML_Char* s, int len)
+{
+ Handler* handler = static_cast<Handler*>(data);
+
+ string str(s, len);
+ handler->characters(str);
+}
+
+//
+// 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)
+{
+ ifstream in(file.c_str());
+ 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);
+ XML_SetUserData(parser, &handler);
+ 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, in.gcount(), isFinal) != XML_STATUS_OK)
+ {
+ handler.error(XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser));
+ return;
+ }
+ }
+ }
+ catch(...)
+ {
+ XML_ParserFree(parser);
+ throw;
+ }
+
+ XML_ParserFree(parser);
+}