-// easyxml.cxx - implementation of EasyXML interfaces.
+/**
+ * \file easyxml.cxx - implementation of EasyXML interfaces.
+ * Written by David Megginson, 2000-2001
+ * This file is in the Public Domain, and comes with NO WARRANTY of any kind.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <simgear_config.h>
+#endif
+
+#include <simgear/compiler.h>
+
+#include <string.h> // strcmp()
#include "easyxml.hxx"
-#include "xmlparse.h"
+
+#ifdef SYSTEM_EXPAT
+# include <expat.h>
+#else
+# include "sg_expat.h"
+#endif
+
+#include <fstream>
+#include <iostream>
+
+using std::ifstream;
+using std::istream;
+using std::string;
\f
////////////////////////////////////////////////////////////////////////
}
-\f
+//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+void XMLVisitor::savePosition(void)
+{
+ if (parser) {
+ column = XML_GetCurrentColumnNumber(parser);
+ line = XML_GetCurrentLineNumber(parser);
+ }
+}
+
////////////////////////////////////////////////////////////////////////
// Attribute list wrapper for Expat.
////////////////////////////////////////////////////////////////////////
-class ExpatAtts : public XMLAttributes
-{
-public:
- ExpatAtts (const char ** atts) : _atts(atts) {}
-
- virtual int size () const;
- virtual const char * getName (int i) const;
- virtual const char * getValue (int i) const;
-
-private:
- const char ** _atts;
-};
-
int
ExpatAtts::size () const
{
return _atts[i*2+1];
}
+const char *
+ExpatAtts::getValue (const char * name) const
+{
+ return XMLAttributes::getValue(name);
+}
\f
////////////////////////////////////////////////////////////////////////
// Static callback functions for Expat.
////////////////////////////////////////////////////////////////////////
-#define VISITOR (*((XMLVisitor*)userData))
+#define VISITOR (*((XMLVisitor *)userData))
static void
start_element (void * userData, const char * name, const char ** atts)
{
+ VISITOR.savePosition();
VISITOR.startElement(name, ExpatAtts(atts));
}
static void
end_element (void * userData, const char * name)
{
+ VISITOR.savePosition();
VISITOR.endElement(name);
}
static void
character_data (void * userData, const char * s, int len)
{
+ VISITOR.savePosition();
VISITOR.data(s, len);
}
const char * target,
const char * data)
{
+ VISITOR.savePosition();
VISITOR.pi(target, data);
}
// Implementation of XMLReader.
////////////////////////////////////////////////////////////////////////
-bool
-readXML (istream &input, XMLVisitor &visitor)
+void
+readXML (istream &input, XMLVisitor &visitor, const string &path)
{
- bool retval = true;
-
XML_Parser parser = XML_ParserCreate(0);
XML_SetUserData(parser, &visitor);
XML_SetElementHandler(parser, start_element, end_element);
XML_SetCharacterDataHandler(parser, character_data);
XML_SetProcessingInstructionHandler(parser, processing_instruction);
+ visitor.setParser(parser);
+ visitor.setPath(path);
visitor.startXML();
char buf[16384];
while (!input.eof()) {
+ // FIXME: get proper error string from system
+ if (!input.good()) {
+ sg_io_exception ex ("Problem reading file",
+ sg_location(path,
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser)),
+ "SimGear XML Parser");
+ visitor.setParser(0);
+ XML_ParserFree(parser);
+ throw ex;
+ }
+
input.read(buf,16384);
- // TODO: deal with bad stream.
if (!XML_Parse(parser, buf, input.gcount(), false)) {
- visitor.error(XML_ErrorString(XML_GetErrorCode(parser)),
- XML_GetCurrentColumnNumber(parser),
- XML_GetCurrentLineNumber(parser));
- retval = false;
+ sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
+ sg_location(path,
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser)),
+ "SimGear XML Parser");
+ visitor.setParser(0);
+ XML_ParserFree(parser);
+ throw ex;
}
+
}
- if (retval)
- visitor.endXML();
+ // Verify end of document.
+ if (!XML_Parse(parser, buf, 0, true)) {
+ sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
+ sg_location(path,
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser)),
+ "SimGear XML Parser");
+ visitor.setParser(0);
+ XML_ParserFree(parser);
+ throw ex;
+ }
+ visitor.setParser(0);
XML_ParserFree(parser);
+ visitor.endXML();
+}
- return retval;
+void
+readXML (const string &path, XMLVisitor &visitor)
+{
+ ifstream input(path.c_str());
+ if (input.good()) {
+ try {
+ readXML(input, visitor, path);
+ } catch (sg_io_exception &) {
+ input.close();
+ throw;
+ } catch (sg_throwable &) {
+ input.close();
+ throw;
+ }
+ } else {
+ throw sg_io_exception("Failed to open file", sg_location(path),
+ "SimGear XML Parser");
+ }
+ input.close();
+}
+
+void
+readXML (const char *buf, const int size, XMLVisitor &visitor)
+{
+ XML_Parser parser = XML_ParserCreate(0);
+ XML_SetUserData(parser, &visitor);
+ XML_SetElementHandler(parser, start_element, end_element);
+ XML_SetCharacterDataHandler(parser, character_data);
+ XML_SetProcessingInstructionHandler(parser, processing_instruction);
+
+ visitor.startXML();
+
+ if (!XML_Parse(parser, buf, size, false)) {
+ sg_io_exception ex (XML_ErrorString(XML_GetErrorCode(parser)),
+ sg_location("In-memory XML buffer",
+ XML_GetCurrentLineNumber(parser),
+ XML_GetCurrentColumnNumber(parser)),
+ "SimGear XML Parser");
+ XML_ParserFree(parser);
+ throw ex;
+ }
+
+ XML_ParserFree(parser);
+ visitor.endXML();
}
// end of easyxml.cxx