Scribus
Open source desktop publishing at your fingertips
digester.h
1 /*
2  * digester.h
3  *
4  *
5  * Created by Andreas Vox on 02.06.06.
6  * Copyright 2006 under GPL2. All rights reserved.
7  *
8  */
9 
10 
11 
12 #ifndef DIGESTER_H
13 #define DIGESTER_H
14 
15 #include <cassert>
16 #include <iostream>
17 #include <vector>
18 #include <map>
19 #include <string>
20 #include <typeinfo>
21 
22 #include "desaxe_conf.h"
23 #include "saxhandler.h"
24 
25 
26 //#define DESAXE_DEBUG 1
27 
28 namespace desaxe {
29 
30 class Action;
31 class RuleState;
32 
33 
34 namespace PRIVATE {
35 
36  class VarPtr
37  {
38  public:
39  void* ptr;
40  std::string type;
41  };
42 
43 
44  template<class ObjType>
45  inline
46  VarPtr mkcell(ObjType* obj)
47  {
48  VarPtr result;
49  result.ptr = obj;// result.ptr = const_cast<void*>(static_cast<const void*>(obj)); //??
50  result.type = typeid(obj).name();
51  return result;
52  }
53 
54 
55  template<class ObjType>
56  inline
57  void chkcell(const VarPtr& cell, std::vector<VarPtr>* stack = NULL)
58  {
59  ObjType* dummy = NULL;
60  if( cell.type != typeid(dummy).name() )
61  {
62  std::cerr << "requested type '" << typeid(dummy).name() << "' doesnt match cell type '" << cell.type << "'\n";
63  if (stack)
64  {
65  int i=0;
66  std::vector<VarPtr>::iterator it;
67  for (it = stack->begin(); it != stack->end(); ++it)
68  {
69  std::cerr << i++ << "\t" << (*it).type << "\t" << (*it).ptr << "\n";
70  }
71  }
72  assert (false);
73  }
74  }
75 
76 
77 
78 class Patch {
79 public:
80  // internal linked list
81  Patch* next;
82  Patch(Patch* nxt) : next(nxt) {}
83 
84  virtual void run(VarPtr lnk) = 0;
85  virtual ~Patch() {}
86 };
87 
88 
89 } // namespace PRIVATE
90 
91 
92 
100 class Digester : public SaxHandler {
101 public:
102  Digester();
103  Digester& operator=(const Digester& other);
104  virtual ~Digester();
105  void reset();
106  void addRule(const Xml_string& pattern, Action action);
107 
108  void parseFile(const Xml_string& filename);
109  void parseMemory(const char* data, unsigned int length);
110 
111  template<class ObjType>
112  ObjType* result();
113  int nrOfErrors() const;
114  const Xml_string getError(int i) const;
115 
116 // called by SAX parser:
117  void beginDoc();
118  void endDoc();
119  void begin(const Xml_string& tag, Xml_attr attr);
120  void end(const Xml_string& tag);
121  void chars(const Xml_string& text);
122 
123 // used by actions:
124  void fail();
125  void error(const Xml_string& msg);
126 
127  template<class ObjType>
128  ObjType* top(unsigned int offset = 0);
129 
130  template<class ObjType>
131  ObjType* bottom(unsigned int offset = 0);
132 
133  template<class ObjType>
134  void setResult( ObjType* res );
135 
136  void pop();
137  void popn(unsigned int number);
138 
139  template<class ObjType>
140  void push(ObjType* obj);
141 
142 // used to resolve idrefs and for general storage
143  template<class ObjType>
144  ObjType* lookup(const Xml_string& idref);
145  template<class ObjType>
146  void store(const Xml_string& idref, ObjType* res );
147 
148 // used to resolve idrefs if use is before definition
149  template<class LinkType>
150  void patchCall(const Xml_string& idref, void (*fun)(LinkType*) );
151  template<class ObjType, class LinkType>
152  void patchInvoke(const Xml_string& idref, ObjType* obj, void (ObjType::*fun)(LinkType*) );
153 
154  // used to insert "/" where necessary
155  static Xml_string concat(const Xml_string& pattern1, const Xml_string& pattern2);
156 
157 private:
158  RuleState*
159  state;
160 
161  std::vector<PRIVATE::VarPtr>
162  objects;
163 
164  std::map<Xml_string, PRIVATE::VarPtr>
165  storage;
166 
167  std::map<Xml_string, PRIVATE::Patch*>
168  patches;
169 
171  result_;
172 
173  std::vector<Xml_string>
174  errors;
175 };
176 
177 
178 
179 template<class ObjType>
180 inline
181 ObjType* Digester::top(unsigned int offset)
182 {
183 #ifdef DESAXE_DEBUG
184  std::cerr << "top(" << offset << ") of " << objects.size() << "\n";
185 #endif
186  unsigned int count = objects.size();
187  assert (offset < count);
188  PRIVATE::chkcell<ObjType>(objects[count - offset - 1], &objects);
189 #ifdef DESAXE_DEBUG
190  std::cerr << "stack-> " << static_cast<ObjType*>(objects[count - offset - 1].ptr) << "\n";
191 #endif
192 
193  return static_cast<ObjType*>(objects[count - offset - 1].ptr);
194 }
195 
196 
197 template<class ObjType>
198 inline
199 ObjType* Digester::bottom(unsigned int offset)
200 {
201 #ifdef DESAXE_DEBUG
202  std::cerr << "bottom(" << offset << ") of " << objects.size() << "\n";
203 #endif
204  //unsigned int count = objects.size();
205  assert (offset < objects.size());
206  PRIVATE::chkcell<ObjType> (objects[offset]);
207  return static_cast<ObjType*>(objects[offset].ptr);
208 }
209 
210 
211 template<class ObjType>
212 inline
213 ObjType* Digester::result()
214 {
215  ObjType* dummy = NULL;
216  if (result_.type != typeid(dummy).name())
217  return NULL;
218 #ifdef DESAXE_DEBUG
219  std::cerr << "result-> " << static_cast<ObjType*>(result_.ptr) << "\n";
220 #endif
221  return static_cast<ObjType*>(result_.ptr);
222 }
223 
224 
225 template<class ObjType>
226 inline
227 void Digester::setResult(ObjType* res)
228 {
229 #ifdef DESAXE_DEBUG
230  std::cerr << res << " ->result\n";
231 #endif
232  result_ = PRIVATE::mkcell(res);
233 }
234 
235 
236 inline
237 void Digester::pop()
238 {
239  assert (1 <= (unsigned int) objects.size());
240  objects.pop_back();
241 }
242 
243 inline
244 void Digester::popn(unsigned int number)
245 {
246  unsigned int count = (unsigned int) objects.size();
247  assert (number <= count);
248  objects.resize(count - number);
249 }
250 
251 
252 template<class ObjType>
253 inline
254 void Digester::push(ObjType* obj)
255 {
256 #ifdef DESAXE_DEBUG
257  std::cerr << "stack<- " << obj << "\n";
258 #endif
259  objects.push_back(PRIVATE::mkcell(obj));
260 }
261 
262 
263 // now lookup / store / patch business
264 
265 namespace PRIVATE {
266 
267  template <class LinkType>
268  struct Patch1 : public Patch
269  {
270  typedef void (*FunType1)(LinkType*);
271  FunType1 fun;
272 
273  Patch1(FunType1 fn, Patch* nxt = NULL) : Patch(nxt), fun(fn) {}
274 
275  void run(VarPtr link)
276  {
277  fun( static_cast<LinkType*>(link.ptr) );
278  }
279  };
280 
281 
282  template <class ObjType, class LinkType>
283  struct Patch2 : public Patch
284  {
285  typedef void (ObjType::*FunType2)(LinkType*);
286  ObjType* obj;
287  FunType2 fun;
288 
289  Patch2(ObjType* ob, FunType2 fn, Patch* nxt = NULL) : Patch(nxt), obj(ob), fun(fn) {}
290 
291  void run(VarPtr link)
292  {
293  (obj->*fun)( static_cast<LinkType*>(link.ptr) );
294  }
295  };
296 
297 
298  inline
299  void runPatches(Patch*& list, VarPtr link)
300  {
301  while (list)
302  {
303  Patch* nxt = list->next;
304  list->run(link);
305  delete list;
306  list = nxt;
307  }
308  }
309 
310  inline
311  void deletePatches(std::map<Xml_string, Patch*>& patches)
312  {
313  std::map<Xml_string, Patch*>::iterator it;
314  for (it = patches.begin(); it != patches.end(); ++it)
315  {
316  Patch* list = it->second;
317  while (list)
318  {
319  Patch* nxt = list->next;
320  delete list;
321  list = nxt;
322  }
323  }
324  patches.clear();
325  }
326 
327 
328 // template<> class Patch1<void>;
329 // template<> class Patch2<VarPtr,void>;
330 
331 } //namespace PRIVATE
332 
333 
334 
335 template<class ObjType>
336 inline
337 ObjType* Digester::lookup(const Xml_string& idref)
338 {
339  using namespace PRIVATE;
340 
341  std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
342  if (cell == storage.end())
343  {
344 #ifdef DESAXE_DEBUG
345  std::cerr << "lookup[" << idref << "]-> NULL\n";
346 #endif
347  return NULL;
348  }
349  else
350  {
351  chkcell<ObjType> (cell->second);
352 #ifdef DESAXE_DEBUG
353  std::cerr << "lookup[" << idref << "]-> " << static_cast<ObjType*>(cell->second.ptr) << "\n";
354 #endif
355  return static_cast<ObjType*>(cell->second.ptr);
356  }
357 }
358 
359 
360 
361 template<class ObjType>
362 inline
363 void Digester::store(const Xml_string& idref, ObjType* obj)
364 {
365  using namespace PRIVATE;
366 #ifdef DESAXE_DEBUG
367  std::cerr << "store[" << idref << "] <- " << obj << "\n";
368 #endif
369  storage[idref] = mkcell(obj);
370  runPatches(patches[idref], storage[idref]);
371 }
372 
373 
374 
375 template<class LinkType>
376 void Digester::patchCall(const Xml_string& idref, void (*fun)(LinkType*) )
377 {
378  using namespace PRIVATE;
379 
380  std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
381  if (cell == storage.end())
382  {
383  patches[idref] = new Patch1<LinkType>(fun, patches[idref] );
384  }
385  else
386  {
387  Patch1<LinkType>(fun).run(cell->second);
388  }
389 }
390 
391 
392 template<class ObjType, class LinkType>
393 void Digester::patchInvoke(const Xml_string& idref, ObjType* obj, void (ObjType::*fun)(LinkType*) )
394 {
395  using namespace PRIVATE;
396 
397  std::map<Xml_string, VarPtr>::iterator cell = storage.find(idref);
398  if (cell == storage.end())
399  {
400  patches[idref] = new Patch2<ObjType,LinkType>(obj, fun, patches[idref] );
401  }
402  else
403  {
404  Patch2<ObjType,LinkType>(obj, fun).run(cell->second);
405  }
406 }
407 
408 } // namespace desaxe
409 
410 #endif
Definition: digester.h:78
Definition: digester.cpp:50
Definition: saxhandler.h:21
Definition: digester.h:36
Definition: digester.h:268
Definition: digester.h:100
Definition: actions.h:59
Definition: actions.h:18
Definition: digester.h:283