Subversion Repositories Scribus

Rev

Rev 8832 | 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:
5694 avox 31
        Action_body() :                     dig(NULL)  {}
32
        virtual ~Action_body()                         {}
8832 avox 33
        virtual void begin(const Xml_string&, Xml_attr) {}
5694 avox 34
 
8832 avox 35
        virtual void end(const Xml_string&)             {}
36
        virtual void chars(const Xml_string&)           {}
5633 avox 37
 
38
        Digester* dig;
39
private:
40
        int refs;
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
55
 *   see exactly the same stack content as their corresponging begin() method.
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
 
8832 avox 64
        inline void begin(const Xml_string& tag, Xml_attr attr)
5633 avox 65
                                                   { body->begin(tag, attr); }
8832 avox 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
 
91
protected:
92
        Action(Action_body* body_)
93
        {
94
                body = body_;
95
                body->refs = 1;
96
        }
97
 
98
private:
99
        Action();  // not defined
100
 
101
        Action_body* body;
102
};
103
 
104
 
105
class Dummy {};
106
 
107
/**
108
 * This class implements typed constructors. They are in a subclass since
109
 * we don't want the type arguments in Action itself.
110
 * Use "class MyAction : public MakeAction<MyAction_body> {} " to define
111
 * your own Actions. You have to implement MyAction constructors if you
112
 * want constructors with arguments.
113
 */
8228 avox 114
template <class Body, class Arg1=Dummy, class Arg2=Dummy, class Arg3=Dummy, class Arg4=Dummy, class Arg5=Dummy>
5633 avox 115
struct MakeAction : public Action
116
{
117
        MakeAction() : Action(new Body()) {}
118
        MakeAction(Arg1 a1) : Action(new Body(a1)) {}
119
        MakeAction(Arg1 a1, Arg2 a2) : Action(new Body(a1, a2)) {}
120
        MakeAction(Arg1 a1, Arg2 a2, Arg3 a3) : Action(new Body(a1, a2, a3)) {}
8228 avox 121
        MakeAction(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4) : Action(new Body(a1, a2, a3, a4)) {}
122
        MakeAction(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4, Arg5 a5) : Action(new Body(a1, a2, a3, a4, a5)) {}
5633 avox 123
};
124
 
125
 
126
 
127
/**
128
 *   Abstract class for actions which leave a new object on the stack
129
 *   The begin() method is defined in subclasses and puts the object on stack,
130
 *   the generic end() method removes this object from stack.
131
 */
132
template<class Type>
133
class Generator_body : public Action_body
134
{
135
public:
8832 avox 136
        virtual Type* eval(Digester* dig_, const Xml_string& tag, Xml_attr attr)
5633 avox 137
        {
138
                dig = dig_;
139
                begin(tag, attr);
140
                Type* res;
141
                res = dig->template top<Type>();
142
                end(tag);
143
                return res;
144
        }
145
protected:
9010 avox 146
        virtual void end(const Xml_string&) { dig->pop(); }
5633 avox 147
};
148
 
149
 
150
 
151
/**
152
 * Generators have their own handle class, which is a subclass of Action
153
 */
154
template<class Type>
155
class Generator : public Action
156
{
157
public:
8832 avox 158
        Type* eval(Digester* dig, const Xml_string& tag, Xml_attr attr)
5633 avox 159
        {
160
                return static_cast<Generator_body<Type>*>(body)->eval(dig, tag, attr);
161
        }
162
 
163
protected:
164
        Generator(Generator_body<Type>* body_) : Action(body_) {}
165
};
166
 
167
 
168
/**
169
 * This class implements typed constructors. They are in a subclass since
170
 * we don't want the type arguments in Generator itself.
171
 * Use "class MyGenerator : public MakeGenerator<MyGenarator_body, MyType> {} " to
172
 * define your own generators. You have to implement MyGenerator constructors if you
173
 * want constructors with arguments.
174
 */
175
template <class Body, class Obj_Type, class Arg1=Dummy, class Arg2=Dummy, class Arg3=Dummy>
176
struct MakeGenerator : public Generator<Obj_Type>
177
{
178
        MakeGenerator() : Generator<Obj_Type>(new Body()) {}
179
        MakeGenerator(Arg1 a) : Generator<Obj_Type>(new Body(a)) {}
180
        MakeGenerator(Arg1 a1, Arg2 a2) : Generator<Obj_Type>(new Body(a1, a2)) {}
181
        MakeGenerator(Arg1 a1, Arg2 a2, Arg3 a3) : Generator<Obj_Type>(new Body(a1, a2, a3)) {}
182
};
183
 
184
} // namespace
185
 
186
#endif