Elm  2
ELM is a library providing generic data structures, OS-independent interface, plugins and XML.
dtd.h
1 /*
2  * dtd module interface
3  *
4  * This file is part of OTAWA
5  * Copyright (c) 2020, IRIT UPS.
6  *
7  * OTAWA is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * OTAWA is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with OTAWA; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 #ifndef INCLUDE_ELM_XOM_DTD_H_
22 #define INCLUDE_ELM_XOM_DTD_H_
23 
24 #include <elm/data/HashMap.h>
25 #include <elm/data/List.h>
26 #include <elm/io/InStream.h>
27 #include <elm/xom.h>
28 
29 namespace elm { namespace dtd {
30 
31 using namespace elm;
32 
34 public:
35  Exception(xom::Element *element, const string& message);
36 };
37 
38 class Element;
39 class AbstractAttribute;
40 class Factory;
41 
42 class Parser {
43  friend class Element;
44 public:
45 
46  static const t::uint32 CROP = 0x01;
47 
48  Parser(Factory& factory, Element& element, t::uint32 flags = CROP);
49 
50  inline bool doesCrop() const { return _flags & CROP; }
51  inline Factory& factory(void) const { return _fact; }
52  inline Element& element(void) const { return *cur.elt; }
53  inline Option<xom::String> get(xom::String name) const
54  { return asElement()->getAttributeValue(name); }
55  inline xom::Element *asElement() const
56  { return static_cast<xom::Element *>(cur.node); }
57  inline xom::Element *parent() const
58  { ASSERT(!stack.isEmpty()); return static_cast<xom::Element *>(stack.top().node); }
59  bool isEmpty();
60 
61  inline void raise(const string& msg) const { throw Exception(asElement(), msg); }
62  inline void fail(const string& msg) const { throw Exception(_last_error, msg); }
63  inline void recordError() { _last_error = asElement(); }
64 
65  inline bool ended() const { return cur.node == nullptr; }
66  inline xom::Node *current(void) const { return cur.node; }
67  inline void next(void) { cur.i++; setNode(); }
68 
69  typedef int mark_t;
70  inline mark_t mark(void) { return cur.i; }
71  inline bool backtrack(mark_t m) { cur.i = m; setNode(); return false; }
72 
73  void begin(Element& element);
74  void end(bool success);
75 
76  inline bool hasID(xom::String id) const { return _map.hasKey(id); };
77  inline void *getID(xom::String id) const { return _map.get(id, nullptr); };
78  inline void addPost(AbstractAttribute *att) { _posts.add(att); }
79  void recordPatch(xom::String id, AbstractAttribute& attr);
80  void recordID(xom::String id, Element& element);
81 
82  void parse(xom::Element *xelt);
83 
84 private:
85  void setNode();
86 
87  struct backpatch_t {
88  inline backpatch_t(AbstractAttribute *a, void *o, xom::Element *xe)
89  : attr(a), object(o), xelt(xe) { }
90  AbstractAttribute *attr;
91  void *object;
92  xom::Element *xelt;
93  };
94 
95  Factory& _fact;
96  Element& _elt;
97  typedef struct {
98  int i;
99  Element *elt;
100  xom::Node *node;
101  } context_t;
102  context_t cur;
103  Vector<context_t> stack;
106  t::uint32 _flags;
107  xom::Element *_last_error;
109 };
110 
111 
112 class Factory {
113 public:
114  virtual ~Factory();
115  virtual void begin(Element& element);
116  virtual void end(Element& element);
117  virtual void backtrack(Element& element);
118  virtual void *getRef(Element& element);
119  virtual void getPCDATA(xom::String data);
120  virtual void patch(AbstractAttribute& attr, void *object, void *ref);
121  virtual void *getPatchRef(AbstractAttribute& attr);
122  virtual void getAny(xom::Node *node);
123 };
124 
126  friend class Element;
127  friend class Parser;
128 public:
129  static const t::uint32
130  REQUIRED = 0x01,
131  STRICT = 0x02,
132  FORWARD = 0x04;
133  AbstractAttribute(Element& element, xom::String name, t::uint32 flags = 0);
134  virtual ~AbstractAttribute();
135  inline xom::String name() const { return _name; }
136 
137  inline Element& element() const { return _elt; }
138  inline bool isRequired() const { return _flags & REQUIRED; }
139  inline bool isStrict() const { return _flags & STRICT; }
140  inline bool isForward() const { return _flags & FORWARD; }
141  inline bool isSet() const { return _set; }
142 
143  inline bool operator==(const AbstractAttribute& a) const { return this == &a; }
144  inline bool operator!=(const AbstractAttribute& a) const { return !operator==(a); }
145 
146 protected:
147  bool parse(Parser& parser);
148  virtual bool process(Parser& parser, xom::String value);
149  virtual void reset();
150  virtual void postprocess(Parser& parser);
151 
152 private:
153  Element& _elt;
154  xom::String _name;
155  t::uint32 _flags;
156  bool _set;
157 };
158 
159 
160 class Content {
161  friend class Element;
162 public:
163  virtual ~Content(void);
164  virtual void reset() = 0;
165 
166 protected:
167  inline bool doParse(Content& content, Parser& parser) { return content.parse(parser); }
168  virtual bool parse(Parser& parser) = 0;
169 };
170 
171 class Element: public Content {
172  friend class Parser;
173  friend class AbstractAttribute;
174 public:
175  Element(xom::String name);
176  Element(xom::String name, Content& content);
177  ~Element();
178 
179  inline xom::String name() const { return _name; }
180  inline Content& content() const { return _content; }
181  inline const Vector<AbstractAttribute *>& attributes() const { return attrs; }
182  inline bool operator==(const Element& element) const { return this == &element; }
183  inline bool operator!=(const Element& element) const { return !operator==(element); }
184 
185  void parse(Factory& factory, xom::Element *element, t::uint32 flags = Parser::CROP);
186  void parse(Factory& factory, xom::Document *doc, t::uint32 flags = Parser::CROP);
187  void parse(Factory& factory, string uri, t::uint32 flags = Parser::CROP);
188  void parse(Factory& factory, io::InStream& in, t::uint32 flags = Parser::CROP);
189 
190 protected:
191  void reset() override;
192  bool parse(Parser& parser) override;
193 private:
194  xom::String _name;
196  Content& _content;
197 };
198 
199 
200 class Optional: public Content {
201 public:
202  Optional(Content& content);
203 protected:
204  void reset() override;
205  bool parse(Parser& parser) override;
206 private:
207  Content& con;
208 };
209 
210 
211 class Alt: public Content {
212 public:
213  Alt(Content& content1, Content& content2);
214 protected:
215  bool parse(Parser& parser) override;
216  void reset() override;
217 private:
218  Content &con1, &con2;
219 };
220 
221 class Seq: public Content {
222 public:
223  Seq(Content& content1, Content& content2);
224 protected:
225  bool parse(Parser& parser) override;
226  void reset() override;
227 private:
228  Content &con1, &con2;
229 };
230 
231 
232 class Repeat: public Content {
233 public:
234  Repeat(Content& content);
235 protected:
236  bool parse(Parser& parser) override;
237  void reset() override;
238 private:
239  Content& con;
240 };
241 
242 
243 template <class T>
245 public:
246  Attribute(Element& element, xom::String name, const T& init, t::uint32 flags = 0)
247  : AbstractAttribute(element, name, flags), i(init) { }
248  inline const T& operator*() const { return v; }
249 protected:
250  bool process(Parser& parser, xom::String value) override
251  { io::StringInput in(value); in >> v; return !in.failed(); }
252  void reset() override
253  { AbstractAttribute::reset(); v = i; }
254 private:
255  T v, i;
256 };
257 
258 template <>
259 class Attribute<xom::String>: public AbstractAttribute {
260 public:
261  Attribute(Element& element, xom::String name, const xom::String& init, t::uint32 flags = 0)
262  : AbstractAttribute(element, name, flags), i(init) { }
263  inline xom::String operator*() const { return v; }
264 protected:
265  bool process(Parser& parser, xom::String value) override { v = value; return true; }
266  void reset() override { v = i; }
267 private:
268  xom::String v, i;
269 };
270 
271 
273 public:
274  IDAttribute(Element& element, xom::String name, t::uint32 flags = 0);
275  inline xom::String operator*() const { return _id; }
276 protected:
277  bool process(Parser& parser, xom::String value) override;
278  void reset() override;
279  void postprocess(Parser& parser) override;
280 private:
281  xom::String _id;
282 };
283 
284 
285 template <class T>
287 public:
288  inline RefAttribute(Element& element, xom::String name, t::uint32 flags = 0)
289  : AbstractAttribute(element, name, flags), _done(false), ref(nullptr) { }
290  inline T *operator*() const { return ref; }
291  inline bool done() const { return _done; }
292  inline xom::String id() const { return _id; }
293 protected:
294  bool process(Parser& parser, xom::String value) override {
295  _id = value;
296  if(parser.hasID(value)) {
297  _done = true;
298  ref = static_cast<T *>(parser.getID(value));
299  return true;
300  }
301  else {
302  _done = false;
303  ref = nullptr;
304  if(isForward())
305  { parser.addPost(this); return true; }
306  else if(isStrict())
307  parser.raise(_ << "undefined reference \"" << value << "\" in " << name());
308  return false;
309  }
310  }
311 
312  void reset() override
313  { AbstractAttribute::reset(); _done = false; ref = nullptr; }
314 
315  void postprocess(Parser& parser) override
316  { parser.recordPatch(_id, *this); }
317 
318 private:
319  bool _done;
320  T *ref;
321  xom::String _id;
322 };
323 
325 
328 Content& operator+(Content& c1, Content& c2);
329 Content& operator|(Content& c1, Content& c2);
330 Content& operator,(Content& c1, Content& c2);
331 Content& operator&(Content& c1, Content& c2);
332 
337 
338 extern Content& EMPTY;
339 extern Content& ignored;
340 extern Content& PCDATA;
341 extern Content& ANY;
342 
343 } } // dtd::elm
344 
345 #endif /* INCLUDE_ELM_XOM_DTD_H_ */
elm::Option
Definition: Option.h:35
elm::dtd::AbstractAttribute::FORWARD
static const t::uint32 FORWARD
Definition: dtd.h:132
elm::MessageException
Definition: MessageException.h:30
elm::dtd::operator+
Content & operator+(Content &c1, Content &c2)
Definition: xom_dtd.cpp:1200
elm::operator==
bool operator==(const CString &s1, const CString &s2)
Definition: string.h:35
elm::dtd::Optional
Definition: dtd.h:200
elm::xom::Node::node
void * node
Definition: Node.h:60
elm::dtd::Parser::hasID
bool hasID(xom::String id) const
Definition: dtd.h:76
elm::dtd::Element
Definition: dtd.h:171
elm::dtd::Parser::next
void next(void)
Definition: dtd.h:67
elm::dtd::Element::name
xom::String name() const
Definition: dtd.h:179
elm::HashMap
Definition: HashMap.h:32
elm::dtd::Content::doParse
bool doParse(Content &content, Parser &parser)
Definition: dtd.h:167
elm::dtd::Parser::CROP
static const t::uint32 CROP
Definition: dtd.h:46
elm::dtd::Parser::backtrack
bool backtrack(mark_t m)
Definition: dtd.h:71
elm::dtd::Attribute::operator*
const T & operator*() const
Definition: dtd.h:248
elm::xom::String
Definition: String.h:35
elm::t::ref
mut< T > ref(var< T > &x)
Definition: type_info.h:289
elm::Exception::message
virtual String message(void)
Definition: utility.cpp:79
elm::dtd::Parser::ended
bool ended() const
Definition: dtd.h:65
elm::dtd::IDAttribute::operator*
xom::String operator*() const
Definition: dtd.h:275
elm::dtd::Attribute::process
bool process(Parser &parser, xom::String value) override
Definition: dtd.h:250
elm::dtd::ANY
Content & ANY
Definition: xom_dtd.cpp:1070
elm::dtd::Repeat
Definition: dtd.h:232
elm::dtd::Attribute::reset
void reset() override
Definition: dtd.h:252
elm::dtd::AbstractAttribute::element
Element & element() const
Definition: dtd.h:137
elm::dtd::Parser::current
xom::Node * current(void) const
Definition: dtd.h:66
elm::dtd::STRICT
const t::uint32 STRICT
Definition: dtd.h:333
elm::dtd::Factory
Definition: dtd.h:112
elm::dtd::RefAttribute::done
bool done() const
Definition: dtd.h:291
elm::dtd::Parser
Definition: dtd.h:42
elm::Exception
Definition: Exception.h:29
elm::dtd::CROP
const t::uint32 CROP
Definition: dtd.h:336
elm::dtd::Parser::recordError
void recordError()
Definition: dtd.h:63
elm::dtd::Parser::get
Option< xom::String > get(xom::String name) const
Definition: dtd.h:53
elm::dtd::Attribute< xom::String >::process
bool process(Parser &parser, xom::String value) override
Definition: dtd.h:265
elm::dtd::Parser::parent
xom::Element * parent() const
Definition: dtd.h:57
elm::dtd::AbstractAttribute::REQUIRED
static const t::uint32 REQUIRED
Definition: dtd.h:130
elm::dtd::IDAttribute
Definition: dtd.h:272
value
elm::dtd::Parser::mark
mark_t mark(void)
Definition: dtd.h:70
elm::dtd::operator*
Content & operator*(Content &c)
Definition: xom_dtd.cpp:1185
elm::dtd::AbstractAttribute::STRICT
static const t::uint32 STRICT
Definition: dtd.h:131
elm::dtd::RefAttribute::id
xom::String id() const
Definition: dtd.h:292
elm::dtd::AbstractAttribute::operator==
bool operator==(const AbstractAttribute &a) const
Definition: dtd.h:143
elm::dtd::ignored
Content & ignored
Definition: xom_dtd.cpp:714
elm::dtd::AbstractAttribute::reset
virtual void reset()
Definition: xom_dtd.cpp:631
elm::dtd::PCDATA
Content & PCDATA
Definition: xom_dtd.cpp:1047
elm::dtd::Seq
Definition: dtd.h:221
elm::dtd::Attribute::Attribute
Attribute(Element &element, xom::String name, const T &init, t::uint32 flags=0)
Definition: dtd.h:246
elm::dtd::operator,
Content & operator,(Content &c1, Content &c2)
Definition: xom_dtd.cpp:1218
elm::dtd::Parser::element
Element & element(void) const
Definition: dtd.h:52
elm::t::in
typename type_info< T >::in_t in
Definition: type_info.h:283
elm::dtd::Parser::addPost
void addPost(AbstractAttribute *att)
Definition: dtd.h:78
elm::dtd::FORWARD
const t::uint32 FORWARD
Definition: dtd.h:335
elm::_
AutoStringStartup & _
Definition: debug_CrashHandler.cpp:232
elm::dtd::operator&
Content & operator&(Content &c1, Content &c2)
Definition: xom_dtd.cpp:1226
elm::dtd::Attribute
Definition: dtd.h:244
elm::dtd::Parser::doesCrop
bool doesCrop() const
Definition: dtd.h:50
elm::dtd::CDATA
xom::String CDATA
Definition: dtd.h:324
elm::dtd::AbstractAttribute::isRequired
bool isRequired() const
Definition: dtd.h:138
elm::dtd::Alt
Definition: dtd.h:211
elm
Definition: adapter.h:26
elm::dtd::EMPTY
Content & EMPTY
Definition: xom_dtd.cpp:694
elm::Vector< context_t >
elm::dtd::Content::parse
virtual bool parse(Parser &parser)=0
elm::dtd::Element::content
Content & content() const
Definition: dtd.h:180
elm::dtd::AbstractAttribute::name
xom::String name() const
Definition: dtd.h:135
elm::dtd::AbstractAttribute
Definition: dtd.h:125
elm::dtd::RefAttribute
Definition: dtd.h:286
elm::xom::Document
Definition: Document.h:20
elm::dtd::Parser::factory
Factory & factory(void) const
Definition: dtd.h:51
elm::dtd::Parser::asElement
xom::Element * asElement() const
Definition: dtd.h:55
elm::dtd::RefAttribute::RefAttribute
RefAttribute(Element &element, xom::String name, t::uint32 flags=0)
Definition: dtd.h:288
elm::t::uint32
unsigned int uint32
Definition: arch.h:31
elm::dtd::AbstractAttribute::isSet
bool isSet() const
Definition: dtd.h:141
elm::dtd::Parser::raise
void raise(const string &msg) const
Definition: dtd.h:61
elm::dtd::RefAttribute::postprocess
void postprocess(Parser &parser) override
Definition: dtd.h:315
elm::String
Definition: String.h:30
elm::dtd::AbstractAttribute::isForward
bool isForward() const
Definition: dtd.h:140
elm::dtd::Parser::recordPatch
void recordPatch(xom::String id, AbstractAttribute &attr)
Definition: xom_dtd.cpp:360
elm::dtd::Parser::mark_t
int mark_t
Definition: dtd.h:69
elm::dtd::AbstractAttribute::operator!=
bool operator!=(const AbstractAttribute &a) const
Definition: dtd.h:144
elm::dtd::RefAttribute::reset
void reset() override
Definition: dtd.h:312
elm::xom::Element
Definition: Element.h:21
elm::io::StringInput
Definition: StringInput.h:30
elm::dtd::Parser::fail
void fail(const string &msg) const
Definition: dtd.h:62
elm::dtd::Element::operator!=
bool operator!=(const Element &element) const
Definition: dtd.h:183
elm::dtd::REQUIRED
const t::uint32 REQUIRED
Definition: dtd.h:334
elm::dtd::operator!
Content & operator!(Content &c)
Definition: xom_dtd.cpp:1192
elm::dtd::Attribute< xom::String >::Attribute
Attribute(Element &element, xom::String name, const xom::String &init, t::uint32 flags=0)
Definition: dtd.h:261
elm::dtd::operator|
Content & operator|(Content &c1, Content &c2)
Definition: xom_dtd.cpp:1208
elm::dtd::Parser::getID
void * getID(xom::String id) const
Definition: dtd.h:77
elm::dtd::Attribute< xom::String >::operator*
xom::String operator*() const
Definition: dtd.h:263
elm::dtd::Element::attributes
const Vector< AbstractAttribute * > & attributes() const
Definition: dtd.h:181
elm::dtd::Attribute< xom::String >::reset
void reset() override
Definition: dtd.h:266
elm::dtd::RefAttribute::process
bool process(Parser &parser, xom::String value) override
Definition: dtd.h:294
elm::dtd::Content
Definition: dtd.h:160
elm::dtd::Element::operator==
bool operator==(const Element &element) const
Definition: dtd.h:182
elm::dtd::AbstractAttribute::isStrict
bool isStrict() const
Definition: dtd.h:139
elm::io::InStream
Definition: InStream.h:29
elm::dtd::RefAttribute::operator*
T * operator*() const
Definition: dtd.h:290
elm::xom::Node
Definition: Node.h:40