home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / include / scribus-ng / desaxe / actions.h next >
Encoding:
C/C++ Source or Header  |  2007-04-24  |  5.2 KB  |  187 lines

  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:
  31.     Action_body() :                     dig(NULL)  {}
  32.     virtual ~Action_body()                         {}
  33.     virtual void begin(const Xml_string&, Xml_attr) {} 
  34.                                                
  35.     virtual void end(const Xml_string&)             {}
  36.     virtual void chars(const Xml_string&)           {}
  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.     
  64.     inline void begin(const Xml_string& tag, Xml_attr attr) 
  65.                                                { body->begin(tag, attr); }
  66.     inline void end(const Xml_string& tag)     { body->end(tag); }
  67.     inline void chars(const Xml_string& data)  { body->chars(data); }
  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.     {
  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.  
  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.  */
  114. template <class Body, class Arg1=Dummy, class Arg2=Dummy, class Arg3=Dummy, class Arg4=Dummy, class Arg5=Dummy>
  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)) {}
  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)) {}
  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:
  136.     virtual Type* eval(Digester* dig_, const Xml_string& tag, Xml_attr attr)
  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:
  146.     virtual void end(const Xml_string& ) { dig->pop(); }
  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:
  158.     Type* eval(Digester* dig, const Xml_string& tag, Xml_attr attr)
  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
  187.