Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
5633 avox 1
/*
2
 *  simple_actions.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 SIMPLE_ACTIONS_H
13
#define SIMPLE_ACTIONS_H
14
 
8228 avox 15
#include "actions.h"
5633 avox 16
/*****
17
 
18
    Defines the following actions:
19
 
20
    Factory<D>( fun )                               - -> D
21
    Factory<D>()                                    - -> D
22
    Prototype<D>( data )                            - -> D
8266 avox 23
    Top<O>( 3 )                                     O x x x -> O x x x O
5633 avox 24
    Getter<O,D>( fun )                              O -> O D
25
    Setter<O,D>( fun )                              O D -> O D
8266 avox 26
    SetterWithConversion<O,D,S>( fun )              O S -> O S
5633 avox 27
    SetAttribute<O,D>( fun, name, default)          O -> O
8228 avox 28
    SetAttribute<O,D>( fun, name)                   O -> O
29
    SetAttributeWithConversion<O,D>( f, n, c, def)  O -> O
30
    SetAttributeWithConversion<O,D>( f, n, convert) O -> O
5633 avox 31
    SetAttributes<O>( fun )                         O -> O
32
    SetText<O,D>( fun )                             O -> O
33
    AddText<O,D>( fun )                             O -> O
8266 avox 34
    Transform<D,E> ( fun )                          D -> E
5633 avox 35
    *TransformLater<D,E> ( fun )                     D -> E
8266 avox 36
    IdRef<O>()                                      O -> O
37
    Lookup<D>( name )                               - -> D
38
    PatchIdRefAttribute<O,D>( fun, name)            O -> O
5633 avox 39
    Result<O>()                                     O -> O
40
 
41
*****/
42
 
43
 
44
namespace desaxe {
45
 
8228 avox 46
        using namespace desaxe;
47
 
5633 avox 48
/**
49
 *   Pushes a new object of type Obj_Type onto the stack.
8228 avox 50
 *   Obj_Type needs a default constructor
5633 avox 51
 */
52
template<class Obj_Type>
53
class Factory_body : public Generator_body<Obj_Type>
54
{
55
public:
56
        typedef Obj_Type* (*FunType)();
57
 
58
        Factory_body()
59
        : create_(NULL)
60
    {}
61
 
62
        Factory_body(FunType create)
63
        : create_(create)
64
    {}
65
 
9010 avox 66
        void begin(const Xml_string&, Xml_attr)
5633 avox 67
    {
8228 avox 68
                this->dig->push(create_? create_() : new Obj_Type());
5633 avox 69
    }  
70
private:
8228 avox 71
    Obj_Type* (*create_)();
5633 avox 72
};
73
 
74
template <class Type>
75
struct  Factory : public MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>
76
{
77
        Factory(typename Factory_body<Type>::FunType create)
8271 jghali 78
        : MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>(create) {}
5633 avox 79
 
80
        Factory()
8271 jghali 81
        : MakeGenerator<Factory_body<Type>, Type, typename Factory_body<Type>::FunType>() {}
5633 avox 82
};
83
 
84
 
85
/**
8228 avox 86
 *   Pushes a new object of type Obj_Type onto the stack.
87
 */
88
template<class Obj_Type>
89
class FactoryWithArgs_body : public Generator_body<Obj_Type>
90
{
91
public:
8807 jghali 92
        typedef Obj_Type* (*FunType)(const Xml_string&, Xml_attr);
8228 avox 93
 
94
        FactoryWithArgs_body(FunType create)
95
                : create_(create)
96
    {}
97
 
8807 jghali 98
        void begin(const Xml_string& name, Xml_attr attr)
8228 avox 99
    {
100
                this->dig->push(create_(name, attr));
101
    }  
102
private:
8807 jghali 103
                Obj_Type* (*create_)(const Xml_string&, Xml_attr);
8228 avox 104
};
105
 
106
template <class Type>
107
struct  FactoryWithArgs : public MakeGenerator<FactoryWithArgs_body<Type>, Type, typename FactoryWithArgs_body<Type>::FunType>
108
{
109
        FactoryWithArgs(typename FactoryWithArgs_body<Type>::FunType create)
110
        : MakeGenerator<FactoryWithArgs_body<Type>, Type, typename FactoryWithArgs_body<Type>::FunType>::MakeGenerator(create) {}
111
};
112
 
113
 
114
/**
5633 avox 115
 *   Pushes a new object of type Obj_Type onto the stack which is initialized with the tag name.
5670 avox 116
 *   If no create method is given, Obj_Type needs a constructor which taks a Xml_string argument
5633 avox 117
 */
118
template<class Obj_Type>
119
class FactoryWithName_body : public Generator_body<Obj_Type>
120
{
121
public:
8807 jghali 122
        typedef Obj_Type* (*FunType)(const Xml_string&);
5633 avox 123
 
124
        FactoryWithName_body()
125
        : create_(NULL)
126
        {}
127
 
128
        FactoryWithName_body(FunType create)
129
        : create_(create)
130
        {}
131
 
8807 jghali 132
        void begin(const Xml_string& tag, Xml_attr)
5633 avox 133
        {
8228 avox 134
                this->dig->push(create_? create_(tag) : new Obj_Type(tag));
5633 avox 135
        }      
136
private:
137
        FunType create_;
138
};
139
 
140
template <class Type>
141
struct  FactoryWithName : public MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>
142
{
143
        FactoryWithName()
144
        : MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>::MakeGenerator() {}
145
 
146
        FactoryWithName(typename FactoryWithName_body<Type>::FunType create)
147
        : MakeGenerator<FactoryWithName_body<Type>, Type, typename FactoryWithName_body<Type>::FunType>::MakeGenerator(create) {}
148
};
149
 
150
 
151
/**
152
 *   Pushes a clone of proto onto the stack. Obj_Type needs a copy constructor
153
 */
154
template<class Obj_Type>
155
class Prototype_body : public Generator_body<Obj_Type>
156
{
157
public:
158
        Prototype_body(const Obj_Type& proto)
159
        : proto_(new Obj_Type(proto))
160
        {}
161
 
162
        ~Prototype_body()
163
        {
164
                delete proto_;
165
        }
166
 
8807 jghali 167
        void begin(const Xml_string&, Xml_attr)
5633 avox 168
        {
8228 avox 169
                this->dig->push(new Obj_Type(proto_));
5633 avox 170
        }
171
private:
172
        const Obj_Type* proto_;
173
};
174
 
175
 
176
template <class Type>
177
struct  Prototype : public MakeGenerator<Prototype_body<Type>, Type, const Type&>
178
{
179
        Prototype(const Type& def)
180
        : MakeGenerator<Prototype_body<Type>, Type, const Type&>::MakeGenerator(def) {}
181
};
182
 
183
 
184
 
8266 avox 185
/**
186
 *   Pushes a new pointer to the n-th object on the stack.
187
 */
188
template<class Obj_Type>
189
class Top_body : public Generator_body<Obj_Type>
190
{
191
public:
192
        Top_body(unsigned int n)
193
        : distance(n)
194
        {}
195
 
8807 jghali 196
        void begin(const Xml_string&, Xml_attr)
8266 avox 197
        {
198
                this->dig->push(this->dig->template top<Obj_Type>(distance));
199
        }
200
private:
201
        unsigned int distance;
202
};
203
 
204
 
205
template <class Type>
206
struct  Top : public MakeGenerator<Top_body<Type>, Type, unsigned int>
207
{
208
        Top(unsigned int distance)
209
        : MakeGenerator<Top_body<Type>, Type, unsigned int>::MakeGenerator(distance) {}
210
        Top()
211
        : MakeGenerator<Top_body<Type>, Type, unsigned int>::MakeGenerator(0) {}
212
};
213
 
214
 
215
 
5633 avox 216
/**
217
 *  Reads an object of type Data_Type from the object on top of the stack,
218
 *  then pushes this Data_Type object onto the stack.
219
 */
220
template<class Obj_Type, class Data_Type>
221
class Getter_body : public Generator_body<Data_Type>
222
{
223
public:
224
        typedef const Data_Type& (Obj_Type::*FunType)();
225
 
226
        Getter_body(FunType get)
227
        : get_(get)
228
        {}
229
 
8807 jghali 230
        void begin(const Xml_string&, Xml_attr)
5633 avox 231
        {
8228 avox 232
                Obj_Type* obj = this->dig->template top<Obj_Type>(1);
5633 avox 233
                Data_Type* data = (obj->*get_)();
8228 avox 234
                this->dig->push(data);
5633 avox 235
        }
236
private:
237
        FunType get_;  
238
};
239
 
240
 
241
template <class Type, class Data>
242
struct  Getter : public MakeGenerator<Getter_body<Type, Data>, Data, typename Getter_body<Type, Data>::FunType>
243
{
244
        Getter(typename Getter_body<Type, Data>::FunType get)
245
        : MakeGenerator<Getter_body<Type, Data>, Data, typename Getter_body<Type, Data>::FunType>::MakeGenerator(get) {}
246
};
247
 
248
 
249
/**
8266 avox 250
 *    Writes the topmost object to the topmost object but one on the stack, where the set method takes a pointer
5633 avox 251
 */
8289 avox 252
template<class Obj_Type, class Data_Type, class Store_Type>
5633 avox 253
class SetterP_body : public Action_body
254
{
255
public:
256
        typedef void (Obj_Type::*FunType)(Data_Type*);
257
 
258
        SetterP_body(FunType set)
259
        : set_(set)
260
        {}
261
 
8807 jghali 262
        void end(const Xml_string&)
5633 avox 263
        {
8289 avox 264
                Store_Type* data = this->dig->template top<Store_Type>();
8228 avox 265
                Obj_Type* obj = this->dig->template top<Obj_Type>(1);
5670 avox 266
#ifdef DESAXE_DEBUG
5633 avox 267
                std::cerr << "setter(ptr): " << obj << " .= " << data << "\n";
5670 avox 268
#endif
5633 avox 269
                (obj->*set_)( data );
270
        }      
271
private:
272
        FunType set_;
273
};
274
 
275
 
8289 avox 276
template <class Type, class Data, class Store = Data>
277
struct  SetterP : public MakeAction<SetterP_body<Type, Data, Store>, typename SetterP_body<Type, Data, Store>::FunType>
5633 avox 278
{
8289 avox 279
        SetterP(typename SetterP_body<Type, Data, Store>::FunType set)
280
        : MakeAction<SetterP_body<Type, Data, Store>, typename SetterP_body<Type, Data, Store>::FunType>(set) {}
5633 avox 281
};
282
 
283
 
284
/**
8266 avox 285
 *  Writes the topmost object to the topmost object but one on the stack.
5633 avox 286
 */
287
template<class Obj_Type, class Data_Type>
288
class Setter_body : public Action_body
289
{
290
public:
291
        typedef void (Obj_Type::*FunType)(Data_Type);
292
 
293
        Setter_body(FunType set)
294
        : set_(set)
295
        {}
296
 
8807 jghali 297
        void end(const Xml_string&)
5633 avox 298
        {
8228 avox 299
                Data_Type* data = this->dig->template top<Data_Type>();
300
                Obj_Type* obj = this->dig->template top<Obj_Type>(1);
5670 avox 301
#ifdef DESAXE_DEBUG
5633 avox 302
                std::cerr << "setter: " << obj << " .= *(" << data << ")\n";
5670 avox 303
#endif
5633 avox 304
                (obj->*set_)( *data );
305
        }      
306
private:
307
        FunType set_;
308
};
309
 
310
 
311
template <class Type, class Data>
312
struct  Setter : public MakeAction<Setter_body<Type, Data>, typename Setter_body<Type, Data>::FunType>
313
{
314
        Setter(typename Setter_body<Type, Data>::FunType set)
8267 jghali 315
        : MakeAction<Setter_body<Type, Data>, typename Setter_body<Type, Data>::FunType>(set) {}
5633 avox 316
};
317
 
318
 
319
/**
8266 avox 320
*  Writes the topmost object to the topmost object but one on the stack.
321
 */
322
template<class Obj_Type, class Data_Type, class Store_Type>
323
class SetterWithConversion_body : public Action_body
324
{
325
public:
326
        typedef void (Obj_Type::*FunType)(Data_Type);
327
        typedef Data_Type (*ConvType)(Store_Type);
328
 
329
        SetterWithConversion_body(FunType set, ConvType conv)
330
                : set_(set), conv_(conv)
331
        {}
332
 
8807 jghali 333
        void end(const Xml_string&)
8266 avox 334
        {
335
                Store_Type* data = this->dig->template top<Store_Type>();
336
                Obj_Type* obj = this->dig->template top<Obj_Type>(1);
337
#ifdef DESAXE_DEBUG
338
                std::cerr << "setter: " << obj << " .= " << conv_ << "(*" << data << ")\n";
339
#endif
340
                if (conv_)
341
                        (obj->*set_)( conv_(*data) );
342
                else
343
                        (obj->*set_)( static_cast<Data_Type>(*data) );
344
        }      
345
private:
346
                FunType set_;
347
        ConvType conv_;
348
};
349
 
350
 
351
template <class Type, class Data, class Store>
352
struct  SetterWithConversion : public MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>
353
{
354
        typedef SetterWithConversion_body<Type, Data, Store> BodyType;
355
        SetterWithConversion(typename SetterWithConversion_body<Type, Data, Store>::FunType set)
8267 jghali 356
        : MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>(set, NULL) {}
8266 avox 357
        SetterWithConversion(typename BodyType::FunType set, typename SetterWithConversion_body<Type, Data, Store>::ConvType conv)
8269 jghali 358
        : MakeAction<SetterWithConversion_body<Type, Data, Store>, typename SetterWithConversion_body<Type, Data, Store>::FunType, typename SetterWithConversion_body<Type, Data, Store>::ConvType>(set, conv) {}
8266 avox 359
};
360
 
361
 
362
/**
5633 avox 363
 *   Stores all attributes to the topmost object on the stack.
364
 */
365
template<class Obj_Type>
366
class SetAttributes_body : public Action_body
367
{
368
public:
5670 avox 369
        typedef void (Obj_Type::*FunType)(const Xml_string&, const Xml_string&) ;
5633 avox 370
 
371
        SetAttributes_body(FunType set) : set_(set)
372
        {}
373
 
8807 jghali 374
        void begin(const Xml_string&, Xml_attr attr)
5633 avox 375
        {
8228 avox 376
                Obj_Type* obj = this->dig->template top<Obj_Type>();
5670 avox 377
                Xml_attr::iterator it;
5633 avox 378
                for(it=attr.begin(); it != attr.end(); ++it)
5670 avox 379
                        (obj->*set_)( Xml_key(it), Xml_data(it) );
5633 avox 380
        }      
381
private:
382
        FunType set_;
383
};
384
 
385
 
386
template <class Type>
387
struct  SetAttributes : public MakeAction<SetAttributes_body<Type>, typename SetAttributes_body<Type>::FunType>
388
{
389
        SetAttributes(typename SetAttributes_body<Type>::FunType set)
8267 jghali 390
        : MakeAction<SetAttributes_body<Type>, typename SetAttributes_body<Type>::FunType>(set) {}
5633 avox 391
};
392
 
393
 
394
 
395
/**
8228 avox 396
 *   Stores named attribute to the topmost object on the stack if attribute present,
397
 *   or stores defauot if present.
398
 */
399
template<class Obj_Type, class Data_Type>
400
class SetAttribute_body : public Action_body
401
{
402
public:
403
        typedef void (Obj_Type::*FunType)(Data_Type) ;
404
 
8807 jghali 405
        SetAttribute_body(FunType set, const Xml_string& name)
8228 avox 406
                : set_(set), name_(name), default_(), hasDefault_(false)
407
        {}
408
 
8807 jghali 409
        SetAttribute_body(FunType set, const Xml_string& name, Data_Type deflt)
8228 avox 410
                : set_(set), name_(name), default_(deflt), hasDefault_(true)
411
        {}
412
 
8807 jghali 413
        void begin(const Xml_string&, Xml_attr attr)
8228 avox 414
        {
415
                Obj_Type* obj = this->dig->template top<Obj_Type>();
416
                Xml_attr::iterator it = attr.find(name_);
417
                if (it != attr.end() )
418
                        (obj->*set_)( Data_Type(Xml_data(it)) );
419
                else if (hasDefault_)
420
                        (obj->*set_)( default_ );                      
421
        }      
422
private:
423
        FunType set_;
424
        Xml_string name_;
425
        Data_Type default_;
426
        bool hasDefault_;
427
};
428
 
429
 
430
template <class Type, class Data>
8832 avox 431
struct  SetAttribute : public MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>
8228 avox 432
{
8832 avox 433
        SetAttribute(typename SetAttribute_body<Type,Data>::FunType set, const Xml_string& name)
434
        : MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>(set,name) {}
8228 avox 435
 
8832 avox 436
        SetAttribute(typename SetAttribute_body<Type,Data>::FunType set, const Xml_string& name, Data deflt)
437
        : MakeAction<SetAttribute_body<Type,Data>, typename SetAttribute_body<Type,Data>::FunType, const Xml_string&, Data>(set,name,deflt) {}
8228 avox 438
};
439
 
440
 
441
 
442
/**
443
*   Stores named attribute to the topmost object on the stack if attribute present,
8266 avox 444
 *   or stores default if present.
8228 avox 445
 */
446
template<class Obj_Type, class Data_Type>
447
class SetAttributeWithConversion_body : public Action_body
448
{
449
public:
450
        typedef void (Obj_Type::*FunType)(Data_Type) ;
8807 jghali 451
        typedef Data_Type (*ConvType)(const Xml_string&);
8228 avox 452
 
8807 jghali 453
        SetAttributeWithConversion_body(FunType set, const Xml_string& name, ConvType conv)
8228 avox 454
                : set_(set), name_(name), conv_(conv), default_(), hasDefault_(false)
455
        {}
456
 
8807 jghali 457
        SetAttributeWithConversion_body(FunType set, const Xml_string& name, ConvType conv, Data_Type deflt)
8228 avox 458
                : set_(set), name_(name), conv_(conv), default_(deflt), hasDefault_(true)
459
        {}
460
 
8807 jghali 461
        void begin(const Xml_string&, Xml_attr attr)
8228 avox 462
        {
463
                Obj_Type* obj = this->dig->template top<Obj_Type>();
464
                Xml_attr::iterator it = attr.find(name_);
8266 avox 465
                if (it != attr.end() && conv_)
8228 avox 466
                        (obj->*set_)( conv_(Xml_data(it)) );
467
                else if (hasDefault_)
468
                        (obj->*set_)( default_ );                      
469
        }      
470
private:
471
        FunType set_;
472
        Xml_string name_;
473
        ConvType conv_;
474
        Data_Type default_;
475
        bool hasDefault_;
476
};
477
 
478
 
479
template <class Type, class Data>
8832 avox 480
struct  SetAttributeWithConversion : public MakeAction<SetAttributeWithConversion_body<Type,Data>, typename SetAttributeWithConversion_body<Type,Data>::FunType, const Xml_string&, typename SetAttributeWithConversion_body<Type,Data>::ConvType, Data>
8228 avox 481
{      
8266 avox 482
        typedef SetAttributeWithConversion_body<Type,Data> BodyType;
8228 avox 483
 
8807 jghali 484
        SetAttributeWithConversion(typename BodyType::FunType set, const Xml_string& name, typename BodyType::ConvType conv)
8832 avox 485
        : MakeAction<BodyType, typename BodyType::FunType, const Xml_string&, typename BodyType::ConvType, Data>(set,name,conv) {}
8266 avox 486
 
8807 jghali 487
        SetAttributeWithConversion(typename BodyType::FunType set, const Xml_string& name, typename BodyType::ConvType conv, Data deflt)
8832 avox 488
        : MakeAction<BodyType, typename BodyType::FunType, const Xml_string&, typename BodyType::ConvType, Data>(set,name,conv,deflt) {}
8228 avox 489
};
490
 
491
 
492
 
493
/**
5633 avox 494
 *   Stores text (PCDATA) in the topmost object on the stack.
495
 *   This might be called more than once.
496
 */
497
template<class Obj_Type>
498
class AddText_body : public Action_body
499
{
500
public:
5670 avox 501
        typedef void (Obj_Type::*FunType)(const Xml_string&);
5633 avox 502
 
503
        AddText_body(FunType add) : addT(add)
504
        {}
505
 
8807 jghali 506
        void chars(const Xml_string& txt)
5633 avox 507
        {
8228 avox 508
                Obj_Type* obj = this->dig->template top<Obj_Type>();
5633 avox 509
                (obj->*addT)( txt );
510
        }      
511
private:
512
        FunType addT;
513
};
514
 
515
 
516
 
517
template <class Type>
518
struct  AddText : public MakeAction<AddText_body<Type>, typename AddText_body<Type>::FunType>
519
{
520
        AddText(typename AddText_body<Type>::FunType set)
8267 jghali 521
        : MakeAction<AddText_body<Type>, typename AddText_body<Type>::FunType>(set) {}
5633 avox 522
};
523
 
524
 
525
 
526
 
527
/**
8046 avox 528
 *   Collects text (PCDATA) chunks and later stores it in the topmost object
5633 avox 529
 *   on the stack.
530
 *   This is only called once at the close tag of the current pattern.
531
 *   WARNING: not safe for nesting
532
 */
533
template<class Obj_Type>
534
class SetText_body : public Action_body
535
{
536
public:
5670 avox 537
        typedef void (Obj_Type::*FunType)(const Xml_string&);
5633 avox 538
 
539
        SetText_body(FunType set) : setT(set)
540
        {}
541
 
8807 jghali 542
        void begin(const Xml_string&, Xml_attr)
5633 avox 543
        {
544
                txt = "";
545
        }
546
 
8807 jghali 547
        void chars(const Xml_string& chunk)
5633 avox 548
        {
549
                txt += chunk;
550
        }
551
 
8807 jghali 552
        void end(const Xml_string& tag)
5633 avox 553
        {
8228 avox 554
                Obj_Type* obj = this->dig->template top<Obj_Type>();
5633 avox 555
                (obj->*setT)( txt );
556
        }      
557
 
558
private:
559
        FunType setT;
5670 avox 560
        Xml_string txt;
5633 avox 561
};
562
 
563
 
564
 
565
template <class Type>
566
struct  SetText : public MakeAction<SetText_body<Type>, typename SetText_body<Type>::FunType>
567
{
8266 avox 568
        typedef SetText_body<Type> BodyType;
569
        SetText(typename BodyType::FunType set)
8269 jghali 570
        : MakeAction<BodyType, typename BodyType::FunType>(set) {}
5633 avox 571
};
572
 
573
 
574
 
575
 
8412 avox 576
template<class Obj_Type>
577
class Store_body : public Action_body
578
{
579
public:
8807 jghali 580
        Store_body(const Xml_string& name) : m_name(name) {}
8412 avox 581
 
8807 jghali 582
        void begin(const Xml_string& tag, Xml_attr attr)
8412 avox 583
        {
584
                Obj_Type* obj = this->dig->template top<Obj_Type>();
8455 avox 585
                qDebug(QString("Store: %1 <- %2").arg(tag).arg(typeid(obj).name()));
8412 avox 586
                this->dig->template store<Obj_Type>(m_name, obj);
587
        }
588
 
589
private:
590
        Xml_string m_name;
591
};
592
 
593
 
594
template <class Type>
8832 avox 595
struct  Store : public MakeAction<Store_body<Type>, const Xml_string& >
8412 avox 596
{
8832 avox 597
        Store(const Xml_string& name) : MakeAction<Store_body<Type>, const Xml_string& >(name) {}
8412 avox 598
};
599
 
600
 
601
 
8266 avox 602
/**
603
*  This applies "id" and "idref" attributes to the object on top of the stack.
604
*  In case of an "id" attribute, if there is no entry with this ID in
605
*  the digester's storage, the topmost object is stored there. Otherwise the
606
*  topmost object is replaced with the stored object.
607
*  In case of an "idref" attribute, if there is no entry with this ID in
608
*  the digester's storage, the topmost object is also stored there. Then the
609
*  trigger "WithinIdRef" is set during begin() and the processing continues
610
*  normally. When end() is called, the topmost object is replaced by the
611
*  stored one (this will be a no-op if there wasnt an entry in storage before)
612
*/
613
template<class Obj_Type>
614
class IdRef_body : public Action_body
615
{
616
public:
617
        IdRef_body() : stack() {}
618
 
8807 jghali 619
        void begin(const Xml_string&, Xml_attr attr)
8266 avox 620
        {
621
                Obj_Type* obj = this->dig->template top<Obj_Type>();
622
                Mode mode;
623
                Xml_attr::iterator it = attr.find("id");
624
                if (it != attr.end())
625
                {
626
                        mode.ID = attr["id"];
627
                        mode.isIdRef = false;
628
                }
629
                else {
630
                        Xml_attr::iterator it = attr.find("idref");
631
                        if (it != attr.end())
632
                        {
633
                                mode.ID = attr["idref"];
634
                                mode.isIdRef = true;
635
                        }
636
                        else {
637
                                mode.ID = "";
638
                                mode.isIdRef = false;
639
                        }
640
                }
8382 avox 641
                if (mode.ID != "")
8266 avox 642
                {
8382 avox 643
                        Obj_Type* storedObj = this->dig->template lookup<Obj_Type>(mode.ID);
644
                        if ( !storedObj )
645
                        {
646
                                this->dig->store(mode.ID, obj);
647
                        }
648
                        else if ( !mode.isIdRef )
649
                        {
650
                                delete (this->dig->template top<Obj_Type>());
651
                                this->dig->pop();
652
                                this->dig->push(this->dig->template lookup<Obj_Type>(mode.ID));
653
                        }
654
                        else
655
                        {
656
                                // NYI: set trigger
657
                        }
8266 avox 658
                }
659
                stack.push_back(mode);
660
 
661
        }
8807 jghali 662
        void end(const Xml_string&)
8266 avox 663
        {
664
                Mode mode = stack.back();
665
                stack.pop_back();
666
                if (mode.isIdRef)
667
                {
668
                        delete (this->dig->template top<Obj_Type>());
669
                        this->dig->pop();
670
                        this->dig->push(this->dig->template lookup<Obj_Type>(mode.ID));
671
                        // NYI reset trigger
672
                }
673
        }
674
private:
675
        struct Mode { Xml_string ID; bool isIdRef; };
676
        std::vector<Mode> stack;
677
};
678
 
679
 
680
template <class Type>
681
struct  IdRef : public MakeAction<IdRef_body<Type> >
682
{};
683
 
684
 
685
/**
686
 *  Reads an object of type Data_Type from the digesters
687
 *  storage and pushes it onto the stack.
688
 *  WARNING: this might be a NULL pointer
689
 */
690
template<class Data_Type>
691
class Lookup_body : public Generator_body<Data_Type>
692
{
693
public:
8807 jghali 694
        Lookup_body(const Xml_string& ID)
8266 avox 695
                : ID_(ID)
696
        {}
697
 
8807 jghali 698
        void begin(const Xml_string&, Xml_attr)
8266 avox 699
        {
700
                Data_Type* data = this->dig->template lookup<Data_Type>(ID_);
701
                this->dig->push(data);
702
        }
703
private:
704
        Xml_string ID_;
705
};
706
 
707
 
708
template <class Data>
8832 avox 709
struct  Lookup : public MakeGenerator<Lookup_body<Data>, const Xml_string&>
8266 avox 710
{
711
        Lookup(Xml_string ID)
8832 avox 712
        : MakeGenerator<Lookup_body<Data>, const Xml_string&>::MakeGenerator(ID) {}
8266 avox 713
};
714
 
715
 
716
 
5633 avox 717
/**
8266 avox 718
*  Transforms the topmost object to the topmost object but one on the stack. // FIXME: this should just be a getter...
719
 */
720
template<class Obj_Type, class Arg_Type>
721
class Transform_body : public Action_body
722
{
723
public:
724
        typedef Obj_Type (*FunType)(const Arg_Type&);
725
 
726
        Transform_body(FunType fun)
727
                : fun_(fun), stack()
728
        {}
729
 
8807 jghali 730
        void begin(const Xml_string&, Xml_attr)
8266 avox 731
        {
732
                Cell cell;
733
                cell.arg = this->dig->template top<Arg_Type>();
734
                cell.obj = fun_(*cell.arg);
735
#ifdef DESAXE_DEBUG
736
                std::cerr << "transform: " << cell.arg << " -> " << cell.obj << ")\n";
737
#endif
738
                stack.push_back(cell);
739
                this->dig->pop();
740
                this->dig->push(&cell.obj);
741
        }      
742
 
8807 jghali 743
        void end(const Xml_string&)
8266 avox 744
        {
745
                Cell cell = stack.back();
746
                stack.pop_back();
747
                this->dig->pop();
748
                this->dig->push(cell.arg);
749
        }
750
private:
751
                FunType fun_;
752
        struct Cell { Arg_Type* arg; Obj_Type obj; };
753
        std::vector<Cell> stack;
754
};
755
 
756
 
757
template <class Type, class Arg>
758
struct  Transform : public MakeAction<Transform_body<Type, Arg>, typename Transform_body<Type, Arg>::FunType>
759
{
760
        typedef Transform_body<Type, Arg> BodyType;
8267 jghali 761
        Transform(typename BodyType::FunType f) : MakeAction<BodyType, typename BodyType::FunType>(f) {}
8266 avox 762
};
763
 
764
 
765
 
766
 
767
template<class Obj_Type, class Data_Type>
768
class PatchIdRefAttribute_body : public Action_body
769
{
770
public:
771
        typedef void (Obj_Type::*FunType)(Data_Type*) ;
772
 
8832 avox 773
        PatchIdRefAttribute_body(FunType set, const Xml_string& name)
8266 avox 774
                : set_(set), name_(name)
775
        {}
776
 
8807 jghali 777
        void begin(const Xml_string&, Xml_attr attr)
8266 avox 778
        {
779
                Xml_attr::iterator it = attr.find(name_);
780
                if (it != attr.end())
781
                {
782
                        Obj_Type* obj = this->dig->template top<Obj_Type>();
783
                        this->dig->template patchInvoke<Obj_Type,Data_Type>(Xml_data(it), obj, set_);
784
                }
785
        }      
786
private:
787
        FunType set_;
788
        Xml_string name_;
789
};
790
 
791
 
792
template <class Type, class Data>
8832 avox 793
struct  PatchIdRefAttribute : public MakeAction<PatchIdRefAttribute_body<Type,Data>, typename PatchIdRefAttribute_body<Type,Data>::FunType, const Xml_string&>
8266 avox 794
{
795
        typedef PatchIdRefAttribute_body<Type,Data> BodyType;
8832 avox 796
        PatchIdRefAttribute(typename BodyType::FunType set, const Xml_string& name)
797
        : MakeAction<BodyType, typename BodyType::FunType, const Xml_string&>(set,name) {}
8266 avox 798
};
799
 
800
 
801
 
802
 
803
/**
5633 avox 804
 *   defines the topmost object as the result
805
 */
806
template<class Data_Type>
807
class Result_body : public Action_body
808
{
809
public:
810
        Result_body()
811
        {}
812
 
8807 jghali 813
        void end(const Xml_string&)
5633 avox 814
        {
8228 avox 815
                this->dig->setResult(dig->template top<Data_Type>());
5633 avox 816
        }
817
};
818
 
819
 
820
 
821
template <class Data>
822
struct  Result : public MakeAction<Result_body<Data> > {};
823
 
824
 
825
} // namespace
826
 
827
#endif