00001
00002
00003
00004 #ifndef SIMGEAR_XMLSTATICPARSER_HXX
00005 #define SIMGEAR_XMLSTATICPARSER_HXX 1
00006
00007 #include <string>
00008 #include <map>
00009 #include <stack>
00010 #include <auto_ptr>
00011
00012 #include <osg/ref_ptr>
00013 #include <osg/Referenced>
00014
00015 #include "easyxml.hxx"
00016
00017 namespace simgear
00018 {
00019
00020 template <typename Element> class XMLStaticParser;
00021
00022
00023
00024 template<typename Element>
00025 struct ElementBuilder : public osg::Referenced
00026 {
00027 ElementBuilder(XMLStaticParser<Element>* builder) {}
00028 ElementBuilder(const ElementBuilder& rhs) const {}
00029 virtual ~ElementBuilder() {}
00030 virtual void initialize(const XMLAttributes& attributes) = 0;
00031 virtual void processSubElement(Element* subElement) = 0;
00032 virtual void processData(const char* data, int length) = 0;
00033 virtual Element* finalize() = 0;
00034
00035 virtual ElementBuilder* clone() const = 0;
00036 };
00037
00038 template<typename Element>
00039 struct BuilderFactory : public osg::Referenced
00040 {
00041 typedef ElementBuilder<Element> builder_type;
00042 typedef std::map<std::string, osg::ref_ptr<const ElementBuilder> >
00043 BuilderMap;
00044 BuilderMap builderMap;
00045 ~virtual BuilderFactory() {}
00046 static void registerBuilder(const std::string& name,
00047 const builder_type* prototype)
00048 {
00049 if (!builderFactory.valid())
00050 builderFactory = new BuilderFactory;
00051 builderFactory->builderMap[name] = prototype;
00052 }
00053 };
00054
00055 template <typename Element>
00056 class XMLStaticParser : public XMLVisitor
00057 {
00058 public:
00059
00060
00061 static osg::ref_ptr<BuilderFactory> builderFactory;
00062
00063
00064
00065 static ElementBuilder* makeBuilder(const std::string& name)
00066 {
00067 BuilderMap::iterator iter = builderFactory->builderMap.find(name);
00068 if (iter == builderFactory->builderMap.end())
00069 return 0;
00070 return iter->second->clone();
00071 }
00072
00073 typedef std::stack<osg::ref_ptr<ElementBuilder> > BuilderStack;
00074 BuilderStack builderStack;
00075
00076 Element* result;
00077
00078 XMLStaticParser() : result(0) {}
00079 virtual ~XMLStaticParser() {}
00080
00081 virtual void startXML()
00082 {
00083 builderStack.push(makeBuilder(""));
00084 }
00085
00086 virtual void endXML()
00087 {
00088
00089 result = builderStack.top()->finalize();
00090 }
00091
00092 virtual void startElement(const char* name, const XMLAttributes& atts)
00093 {
00094 ElementBuilder* builder = makeBuilder(name);
00095 if (builder) {
00096 builderStack.push(builder);
00097 builder->initialize(atts);
00098 }
00099 }
00100
00101 virtual void endElement(const char* name)
00102 {
00103 Element* result = builderStack.top()->finalize();
00104 builderStack.pop();
00105 if (!builderStack.empty())
00106 builderStack.top()->processSubElement(result);
00107 }
00108
00109 virtual void data(const char* s, int length)
00110 {
00111 builderStack.top()->processData(s, length);
00112 }
00113
00114 struct RegisterBuilderProxy
00115 {
00116 RegisterBuilderProxy(const char* name, ElementBuilder* builder)
00117 {
00118 registerBuilder(name, builder);
00119 }
00120 };
00121 };
00122
00123 template <typename E>
00124 static osg::ref_ptr<BuilderFactory<E> > builderFactory;
00125 }
00126 #endif