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:
Action_body()31 	Action_body() {}
~Action_body()32 	virtual ~Action_body() {}
begin(const Xml_string &,Xml_attr)33 	virtual void begin(const Xml_string&, Xml_attr) {}
end(const Xml_string &)34 	virtual void end(const Xml_string&) {}
chars(const Xml_string &)35 	virtual void chars(const Xml_string&) {}
reset()36 	virtual void reset() {}
37 
38 	Digester* dig {nullptr};
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:
digester()61 	inline Digester* digester()                { return body->dig; }
setDigester(Digester * dig)62 	inline void setDigester(Digester* dig)     { body->dig = dig; }
63 
begin(const Xml_string & tag,Xml_attr attr)64 	inline void begin(const Xml_string& tag, Xml_attr attr)
65 	                                           { body->begin(tag, attr); }
end(const Xml_string & tag)66 	inline void end(const Xml_string& tag)     { body->end(tag); }
chars(const Xml_string & data)67 	inline void chars(const Xml_string& data)  { body->chars(data); }
68 
69 	// Handle stuff:
Action(const Action & other)70 	Action(const Action& other)
71 	{
72 		body = other.body;
73 		body->refs++;
74 	}
~Action()75 	virtual ~Action()
76 	{
77 		if (--body->refs == 0)
78 			delete body;
79 	}
80 	Action& operator=(const Action& other)
81 	{
82 		if (body != other.body) {
83 			if (--body->refs == 0)
84 				delete body;
85 			body = other.body;
86 			++body->refs;
87 		}
88 		return *this;
89 	}
90 
reset()91 	virtual void reset()
92 	{
93 		body->reset();
94 	}
95 
96 protected:
Action(Action_body * body_)97 	Action(Action_body* body_)
98 	{
99 		body = body_;
100 		body->refs = 1;
101 	}
102 
103 	Action_body* body;
104 
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  */
119 template <class Body, class Arg1=Dummy, class Arg2=Dummy, class Arg3=Dummy, class Arg4=Dummy, class Arg5=Dummy>
120 struct MakeAction : public Action
121 {
MakeActionMakeAction122 	MakeAction() : Action(new Body()) {}
MakeActionMakeAction123 	MakeAction(Arg1 a1) : Action(new Body(a1)) {}
MakeActionMakeAction124 	MakeAction(Arg1 a1, Arg2 a2) : Action(new Body(a1, a2)) {}
MakeActionMakeAction125 	MakeAction(Arg1 a1, Arg2 a2, Arg3 a3) : Action(new Body(a1, a2, a3)) {}
MakeActionMakeAction126 	MakeAction(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4) : Action(new Body(a1, a2, a3, a4)) {}
MakeActionMakeAction127 	MakeAction(Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4, Arg5 a5) : Action(new Body(a1, a2, a3, a4, a5)) {}
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:
eval(Digester * dig_,const Xml_string & tag,Xml_attr attr)141 	virtual Type* eval(Digester* dig_, const Xml_string& tag, Xml_attr attr)
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:
end(const Xml_string &)151 	virtual void end(const Xml_string& ) { dig->pop(); }
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:
eval(Digester * dig,const Xml_string & tag,Xml_attr attr)163 	Type* eval(Digester* dig, const Xml_string& tag, Xml_attr attr)
164 	{
165 		return static_cast<Generator_body<Type>*>(body)->eval(dig, tag, attr);
166 	}
167 
168 protected:
Generator(Generator_body<Type> * body_)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 {
MakeGeneratorMakeGenerator183 	MakeGenerator() : Generator<Obj_Type>(new Body()) {}
MakeGeneratorMakeGenerator184 	MakeGenerator(Arg1 a) : Generator<Obj_Type>(new Body(a)) {}
MakeGeneratorMakeGenerator185 	MakeGenerator(Arg1 a1, Arg2 a2) : Generator<Obj_Type>(new Body(a1, a2)) {}
MakeGeneratorMakeGenerator186 	MakeGenerator(Arg1 a1, Arg2 a2, Arg3 a3) : Generator<Obj_Type>(new Body(a1, a2, a3)) {}
187 };
188 
189 } // namespace
190 
191 #endif
192