Subversion Repositories Scribus

Rev

Rev 24665 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5633 avox 1
/*
2
 *  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
#ifndef ACTIONS_H
12
#define ACTIONS_H
13
 
14
#include <map>
15
#include <string>
16
#include "digester.h"
17
 
18
namespace desaxe {
19
 
20
/**
21
 *   Action / Action_body follow the handle/body pattern. This allows to omit the
22
 *   new operator when creating Action expressions and make dynamic memory handling
23
 *   more secure.
24
 *   Base class for the body of all actions. Usually Digester calls these methods,
25
 *   but subclasses are also allowed to call those methods if they know what they are
26
 *   doing...
27
 */
28
class Action_body
29
{
30
protected:
23017 craig 31
        Action_body() {}
32
        virtual ~Action_body() {}
33
        virtual void begin(const Xml_string&, Xml_attr) {}                      
34
        virtual void end(const Xml_string&) {}
35
        virtual void chars(const Xml_string&) {}
36
        virtual void reset() {}
5633 avox 37
 
23017 craig 38
        Digester* dig {nullptr};
5633 avox 39
private:
25210 jghali 40
        int refs { 0 };
5633 avox 41
        friend class Action;
42
};
43
 
44
 
45
 
46
/**
47
 *   Actions do all the real work when digesting XML files: creating new objects,
48
 *   setting attributes, calling methods. Each Action gets control two or more times
49
 *   for each time the corresponding rule triggers: 1 x begin(), 0- x chars(), 1 x end().
50
 *   They come in two basic flavors: Generators create a new object in their begin()
51
 *   method and put it on the object stack. Other Actions use objects on the stack,
52
 *   XML attributes or XML text to store this data in other objects. This is usually
53
 *   done in the end() method.
54
 *   Warning: end() methods are called in reverse order. This is to ensure that they
24665 jghali 55
 *   see exactly the same stack content as their corresponding begin() method.
5633 avox 56
 *   This is the handle class which delegates to the body
57
 */
58
class Action
59
{
60
public:
61
        inline Digester* digester()                { return body->dig; }
62
        inline void setDigester(Digester* dig)     { body->dig = dig; }
63
 
8834 cbradney 64
        inline void begin(const Xml_string& tag, Xml_attr attr)
5633 avox 65
                                                   { body->begin(tag, attr); }
8834 cbradney 66
        inline void end(const Xml_string& tag)     { body->end(tag); }
67
        inline void chars(const Xml_string& data)  { body->chars(data); }
5633 avox 68
 
69
        // Handle stuff:
70
        Action(const Action& other)
71
        {
72
                body = other.body;
73
                body->refs++;
74
        }
75
        virtual ~Action()                          
76
        {
77
                if (--body->refs == 0)
78
                        delete body;
79
        }
80
        Action& operator=(const Action& other)
81
        {
8046 avox 82
                if (body != other.body) {
83
                        if (--body->refs == 0)
84
                                delete body;
85
                        body = other.body;
86
                        ++body->refs;
87
                }
5633 avox 88
                return *this;
89
        }
90
 
17743 jghali 91
        virtual void reset()
92
        {
93
                body->reset();
94
        }
95
 
5633 avox 96
protected:
97
        Action(Action_body* body_)
98
        {
99
                body = body_;
100
                body->refs = 1;
101
        }
102
 
25210 jghali 103
        Action_body* body { nullptr };
17382 jghali 104
 
5633 avox 105
private:
106
        Action();  // not defined
107
};
108
 
109
 
110
class Dummy {};
111
 
112
/**
113
 * This class implements typed constructors. They are in a subclass since
114
 * we don't want the type arguments in Action itself.
115
 * Use "class MyAction : public MakeAction<MyAction_body> {} " to define
116
 * your own Actions. You have to implement MyAction constructors if you
117
 * want constructors with arguments.
118
 */
8228 avox 119
template <class Body, class Arg1=Dummy, class Arg2=Dummy, class Arg3=Dummy, class Arg4=Dummy, class Arg5=Dummy>
5633 avox 120
struct MakeAction : public Action
121
{
122
        MakeAction() : Action(new Body()) {}
123
        MakeAction(Arg1 a1) : Action(new Body(a1)) {}
124
        MakeAction(Arg1 a1, Arg2 a2) : Action(new Body(a1, a2)) {}
125
        MakeAction(Arg1 a1, Arg2 a2, Arg3 a3) : Action(new Body(a1, a2, a3)) {}
8228 avox 126
        MakeAction(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4) : Action(new Body(a1, a2, a3, a4)) {}
127
        MakeAction(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4, Arg5 a5) : Action(new Body(a1, a2, a3, a4, a5)) {}
5633 avox 128
};
129
 
130
 
131
 
132
/**
133
 *   Abstract class for actions which leave a new object on the stack
134
 *   The begin() method is defined in subclasses and puts the object on stack,
135
 *   the generic end() method removes this object from stack.
136
 */
137
template<class Type>
138
class Generator_body : public Action_body
139
{
140
public:
8834 cbradney 141
        virtual Type* eval(Digester* dig_, const Xml_string& tag, Xml_attr attr)
5633 avox 142
        {
143
                dig = dig_;
144
                begin(tag, attr);
145
                Type* res;
146
                res = dig->template top<Type>();
147
                end(tag);
148
                return res;
149
        }
150
protected:
9042 avox 151
        virtual void end(const Xml_string& ) { dig->pop(); }
5633 avox 152
};
153
 
154
 
155
 
156
/**
157
 * Generators have their own handle class, which is a subclass of Action
158
 */
159
template<class Type>
160
class Generator : public Action
161
{
162
public:
8834 cbradney 163
        Type* eval(Digester* dig, const Xml_string& tag, Xml_attr attr)
5633 avox 164
        {
165
                return static_cast<Generator_body<Type>*>(body)->eval(dig, tag, attr);
166
        }
167
 
168
protected:
169
        Generator(Generator_body<Type>* body_) : Action(body_) {}
170
};
171
 
172
 
173
/**
174
 * This class implements typed constructors. They are in a subclass since
175
 * we don't want the type arguments in Generator itself.
176
 * Use "class MyGenerator : public MakeGenerator<MyGenarator_body, MyType> {} " to
177
 * define your own generators. You have to implement MyGenerator constructors if you
178
 * want constructors with arguments.
179
 */
180
template <class Body, class Obj_Type, class Arg1=Dummy, class Arg2=Dummy, class Arg3=Dummy>
181
struct MakeGenerator : public Generator<Obj_Type>
182
{
183
        MakeGenerator() : Generator<Obj_Type>(new Body()) {}
184
        MakeGenerator(Arg1 a) : Generator<Obj_Type>(new Body(a)) {}
185
        MakeGenerator(Arg1 a1, Arg2 a2) : Generator<Obj_Type>(new Body(a1, a2)) {}
186
        MakeGenerator(Arg1 a1, Arg2 a2, Arg3 a3) : Generator<Obj_Type>(new Body(a1, a2, a3)) {}
187
};
188
 
189
} // namespace
190
 
191
#endif