Subversion Repositories Scribus

Rev

Rev 8329 | Rev 8452 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5633 avox 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>
8266 avox 20
#include <typeinfo>
5633 avox 21
 
5670 avox 22
#include "desaxe_conf.h"
6733 avox 23
#include "saxhandler.h"
5633 avox 24
 
8266 avox 25
 
8289 avox 26
//#define DESAXE_DEBUG 1
8266 avox 27
 
5633 avox 28
namespace desaxe {
29
 
30
class Action;
31
class RuleState;
32
 
8390 avox 33
 
34
namespace PRIVATE {
8266 avox 35
 
8289 avox 36
        class VarPtr
8266 avox 37
        {
8289 avox 38
        public:
8266 avox 39
                void* ptr;
40
                std::string type;
41
        };
5633 avox 42
 
8266 avox 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;
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
 
8289 avox 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
 
8390 avox 89
} // namespace PRIVATE  
8266 avox 90
 
91
 
92
 
5633 avox 93
/**
94
   Digester helps you to create C++ objects from a SAX stream.
95
   All you have to do is register actions for patterns of element tags
96
   you expect in your XML stream. These actions can create new objects, set
97
   attributes, or call methods. Actions operate on intermediate objects which
98
   are hold on a stack maintained by Digester.  
99
 */
6733 avox 100
class Digester : public SaxHandler {   
5633 avox 101
public:
102
        Digester();
103
        Digester& operator=(const Digester& other);
104
        virtual ~Digester();
5670 avox 105
        void addRule(const Xml_string pattern, Action action);
5633 avox 106
 
5670 avox 107
        void parseFile(const Xml_string filename);
5633 avox 108
        void parseMemory(const char* data, unsigned int length);
109
 
8266 avox 110
        template<class ObjType>
111
                ObjType*  result();    
5633 avox 112
        int nrOfErrors() const;
5670 avox 113
        const Xml_string getError(int i) const;
5633 avox 114
 
115
// called by SAX parser:
6733 avox 116
        void beginDoc();
117
        void endDoc();
5670 avox 118
        void begin(Xml_string tag, Xml_attr attr);
119
        void end(Xml_string tag);
120
        void chars(Xml_string text);
5633 avox 121
 
122
// used by actions:
123
        void fail();
5670 avox 124
        void error(const Xml_string msg);
5633 avox 125
 
8266 avox 126
        template<class ObjType>
127
        ObjType*  top(unsigned int offset = 0);
5633 avox 128
 
8266 avox 129
        template<class ObjType>
130
        ObjType*  bottom(unsigned int offset = 0);
5633 avox 131
 
8266 avox 132
        template<class ObjType>
133
        void setResult( ObjType* res );
5633 avox 134
 
135
        void pop();
8266 avox 136
        void popn(unsigned int number);
5633 avox 137
 
8266 avox 138
        template<class ObjType>
139
        void push(ObjType* obj);
140
 
141
//  used to resolve idrefs and for general storage      
142
        template<class ObjType>
143
                ObjType*  lookup(const Xml_string idref);      
144
        template<class ObjType>
145
                void store(const Xml_string idref, ObjType* res );
146
 
147
//  used to resolve idrefs if use is before definition
148
        template<class LinkType>
149
                void patchCall(const Xml_string idref, void (*fun)(LinkType*) );
150
        template<class ObjType, class LinkType>
151
                void patchInvoke(const Xml_string idref, ObjType* obj, void (ObjType::*fun)(LinkType*) );
152
 
153
        // used to insert "/" where necessary
154
        static Xml_string concat(const Xml_string pattern1, const Xml_string pattern2);
5633 avox 155
 
156
private:
8266 avox 157
        RuleState*
158
                state;
159
 
8390 avox 160
        std::vector<PRIVATE::VarPtr>
8266 avox 161
                objects;
162
 
8390 avox 163
        std::map<Xml_string, PRIVATE::VarPtr>
8266 avox 164
                storage;
165
 
8390 avox 166
        std::map<Xml_string, PRIVATE::Patch*>
8266 avox 167
                patches;
168
 
8390 avox 169
        PRIVATE::VarPtr
8266 avox 170
                result_;
171
 
172
        std::vector<Xml_string>
173
                errors;
5633 avox 174
};
175
 
176
 
8266 avox 177
 
178
template<class ObjType>
5633 avox 179
inline
8266 avox 180
ObjType*  Digester::top(unsigned int offset)
5670 avox 181
{
182
#ifdef DESAXE_DEBUG
5633 avox 183
        std::cerr << "top(" << offset << ") of " << objects.size() << "\n";
5670 avox 184
#endif
5633 avox 185
        unsigned int count = objects.size();
186
        assert (offset < count);
8390 avox 187
        PRIVATE::chkcell<ObjType>(objects[count - offset - 1], &objects);
5670 avox 188
#ifdef DESAXE_DEBUG
8266 avox 189
        std::cerr << "stack-> " << static_cast<ObjType*>(objects[count - offset - 1].ptr) << "\n";
5670 avox 190
#endif
8266 avox 191
 
192
        return static_cast<ObjType*>(objects[count - offset - 1].ptr);
5633 avox 193
}
194
 
8266 avox 195
 
196
template<class ObjType>
5633 avox 197
inline
8266 avox 198
ObjType*  Digester::bottom(unsigned int offset)
5633 avox 199
{
5670 avox 200
#ifdef DESAXE_DEBUG
5633 avox 201
        std::cerr << "bottom(" << offset << ") of " << objects.size() << "\n";
5670 avox 202
#endif
5633 avox 203
        unsigned int count = objects.size();
204
        assert (offset < count);
8390 avox 205
        PRIVATE::chkcell<ObjType> (objects[offset]);
8266 avox 206
        return static_cast<ObjType*>(objects[offset].ptr);
5633 avox 207
}
208
 
209
 
8266 avox 210
template<class ObjType>
5633 avox 211
inline
8266 avox 212
ObjType*  Digester::result()
5633 avox 213
{
8329 avox 214
        ObjType* dummy;
215
        if (result_.type != typeid(dummy).name())
216
                return NULL;
5670 avox 217
#ifdef DESAXE_DEBUG
8266 avox 218
        std::cerr << "result-> " << static_cast<ObjType*>(result_.ptr) << "\n";
5670 avox 219
#endif
8266 avox 220
        return static_cast<ObjType*>(result_.ptr);
5633 avox 221
}
222
 
223
 
8266 avox 224
template<class ObjType>
5633 avox 225
inline
8266 avox 226
void Digester::setResult(ObjType* res)
5633 avox 227
{
5670 avox 228
#ifdef DESAXE_DEBUG
5633 avox 229
        std::cerr << res << " ->result\n";
5670 avox 230
#endif
8390 avox 231
        result_ = PRIVATE::mkcell(res);
5633 avox 232
}
233
 
234
 
235
inline
236
void Digester::pop()
237
{
238
        unsigned int count = objects.size();
239
        assert (1 <= count);
240
        objects.pop_back();
241
}
242
 
243
inline
8266 avox 244
void Digester::popn(unsigned int number)
5633 avox 245
{
246
        unsigned int count = objects.size();
247
        assert (number <= count);
248
        objects.resize(count - number);
249
}
250
 
251
 
8266 avox 252
template<class ObjType>
5633 avox 253
inline
8266 avox 254
void Digester::push(ObjType* obj)
5633 avox 255
{
5670 avox 256
#ifdef DESAXE_DEBUG
5633 avox 257
        std::cerr << "stack<- " << obj << "\n";
5670 avox 258
#endif
8390 avox 259
        objects.push_back(PRIVATE::mkcell(obj));
5633 avox 260
}
261
 
262
 
8266 avox 263
// now lookup / store / patch business
264
 
8390 avox 265
namespace PRIVATE {
8289 avox 266
 
8266 avox 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
 
8390 avox 298
        inline
8266 avox 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
 
8390 avox 310
        inline
8266 avox 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
 
8289 avox 327
 
328
//      template<> class Patch1<void>;
329
//      template<> class Patch2<VarPtr,void>;
330
 
8390 avox 331
} //namespace PRIVATE
8266 avox 332
 
333
 
334
 
335
template<class ObjType>
336
inline
337
ObjType*  Digester::lookup(const Xml_string idref)
338
{
8390 avox 339
        using namespace PRIVATE;
340
 
8266 avox 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";
5633 avox 346
#endif
8266 avox 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)
8390 avox 364
{
365
        using namespace PRIVATE;
8266 avox 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
{
8390 avox 378
        using namespace PRIVATE;
379
 
8266 avox 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
        {
8289 avox 387
                Patch1<LinkType>(fun).run(cell->second);
8266 avox 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
{
8390 avox 395
        using namespace PRIVATE;
396
 
8266 avox 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
        {
8289 avox 404
                Patch2<ObjType,LinkType>(obj, fun).run(cell->second);
8266 avox 405
        }
406
}
407
 
408
} // namespace desaxe
409
 
410
#endif