1 /*-
2  * Copyright (c) 2004 Jacques A. Vidrine
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  */
27 #ifndef CELABO_20040211_PARSER_HH
28 #define CELABO_20040211_PARSER_HH
29 
30 #if defined(HAVE_BSDXML)
31 #include <bsdxml.h>
32 #else
33 #include <expat.h>
34 #endif
35 
36 namespace vuxml {
37 
38 
39 class Element {
40 public:
41   Element(std::string &xmlns, std::string &name);
id() const42   inline int id() const { return id_; }
xmlns() const43   inline const std::string &xmlns() const { return xmlns_; }
name() const44   inline const std::string &name() const  { return name_; }
45 private:
46   int id_;
47   std::string xmlns_;
48   std::string name_;
49 };
50 
51 
52 class Parser;
53 
54 
55 class XMLHandler {
56 public:
57 
XMLHandler()58   XMLHandler() {}
~XMLHandler()59   virtual ~XMLHandler() {}
60 
61   virtual void setParser(Parser &p) = 0;
62 
63   virtual void startElement(std::string &xmlns, std::string &name,
64       Attributes &attr) = 0;
65   virtual void endElement(std::string &xmlns, std::string &name) = 0;
66   virtual void characters(std::string &pcdata) = 0;
67 };
68 
69 
70 class Parser {
71 public:
72   Parser();
73   ~Parser();
74 
75   void			 signalError(const std::string &serr);
76   bool		 	 fail() const;
77   const std::string	&getErrorString() const;
78   unsigned int		 getLine() const;
79 
80   void	*getBuffer(size_t n);
81   bool	 parseBuffer(size_t n, bool last);
82   void	 parseStream(std::istream &is);
83 
84   void		 setHandler(XMLHandler &h);
85   XMLHandler	&getHandler();
86 
87   static void	charactersDispatcher(void *data, const char *s, int len);
88   static void	startElementDispatcher(void *data, const char *name,
89       const char **atts);
90   static void	endElementDispatcher(void *data, const char *name);
91 
92 private:
93   XML_Parser		 parser_;
94   XMLHandler		*handler_;
95   bool			 fail_;
96   unsigned int		 line_;
97   std::string		 serr_;
98 
99   static Parser	*dispatcherSetup(void *data);
100 };
101 
102 
103 class XMLState {
104 public:
105   virtual XMLState	*child(const Element &element) = 0;
106   virtual void		 start(const Element &element,
107 			    Attributes &attr) = 0;
108   virtual void		 characters(std::string &pcdata) = 0;
109   virtual XMLState	*end(const Element &element) = 0;
110 };
111 
112 
113 template<class T>
114 class XMLStateFacet : public XMLState {
115 public:
116   typedef XMLState *(T::*FnChild)(const Element &element);
117   typedef void (T::*FnStart)(const Element &element, Attributes &attr);
118   typedef void (T::*FnCharacters)(std::string &pcdata);
119   typedef XMLState *(T::*FnEnd)(const Element &element);
120 
XMLStateFacet(T & t,FnChild a,FnStart b,FnCharacters c,FnEnd d)121   XMLStateFacet(T &t, FnChild a, FnStart b, FnCharacters c, FnEnd d) :
122       t_(t), child_(a), start_(b), characters_(c), end_(d) {}
123 
child(const Element & element)124   XMLState *child(const Element &element)   { return (t_.*child_)(element); }
start(const Element & element,Attributes & attr)125   void      start(const Element &element,
126       Attributes &attr)                     { (t_.*start_)(element, attr); }
characters(std::string & pcdata)127   void      characters(std::string &pcdata) { (t_.*characters_)(pcdata); }
end(const Element & element)128   XMLState *end(const Element &element)     { return (t_.*end_)(element); }
129 
130 private:
131   T		&t_;
132   FnChild	 child_;
133   FnStart	 start_;
134   FnCharacters	 characters_;
135   FnEnd		 end_;
136 };
137 
138 
139 }
140 #endif
141