98ae7edb84e5c78040cc5c327806989bcdf7b9d4
[platform/upstream/doxygen.git] / src / template.h
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15
16 #ifndef TEMPLATE_H
17 #define TEMPLATE_H
18
19 #include <qcstring.h>
20 #include <qvaluelist.h>
21
22 class FTextStream;
23
24 class TemplateListIntf;
25 class TemplateStructIntf;
26 class TemplateEngine;
27
28 /** @defgroup template_api Template API
29  *
30  *  This is the API for a
31  *  <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a>
32  *  compatible template system written in C++.
33  *  It is somewhat inspired by Stephen Kelly's
34  *  <a href="http://www.gitorious.org/grantlee/pages/Home">Grantlee</a>.
35  *
36  *  A template is simply a text file.
37  *  A template contains \b variables, which get replaced with values when the
38  *  template is evaluated, and \b tags, which control the logic of the template.
39  *
40  *  Variables look like this: `{{ variable }}`
41  *  When the template engine encounters a variable, it evaluates that variable and
42  *  replaces it with the result. Variable names consist of any combination of
43  *  alphanumeric characters and the underscore ("_").
44  *  Use a dot (.) to access attributes of a structured variable.
45  *
46  *  One can modify variables for display by using \b filters, for example:
47  *  `{{ value|default:"nothing" }}`
48  *
49  *  Tags look like this: `{% tag %}`. Tags are more complex than variables:
50  *  Some create text in the output, some control flow by performing loops or logic,
51  *  and some load external information into the template to be used by later variables.
52  *
53  *  To comment-out part of a line in a template, use the comment syntax:
54  *  `{# comment text #}`.
55  *
56  *  Supported Django tags:
57  *  - `for ... empty ... endfor`
58  *  - `if ... else ... endif`
59  *  - `block ... endblock`
60  *  - `extend`
61  *  - `include`
62  *  - `with ... endwith`
63  *  - `spaceless ... endspaceless`
64  *  - `cycle`
65  *
66  *  Extension tags:
67  *  - `create` which instantiates a template and writes the result to a file.
68  *     The syntax is `{% create 'filename' from 'template' %}`.
69  *  - `recursetree`
70  *  - `markers`
71  *  - `msg` ... `endmsg`
72  *  - `set`
73  *
74  *  Supported Django filters:
75  *  - `default`
76  *  - `length`
77  *  - `add`
78  *  - `divisibleby`
79  *
80  *  Extension filters:
81  *  - `stripPath`
82  *  - `nowrap`
83  *  - `prepend`
84  *  - `append`
85  *
86  *  @{
87  */
88
89 /** @brief Variant type which can hold one value of a fixed set of types. */
90 class TemplateVariant
91 {
92   public:
93     /** @brief Helper class to create a delegate that can store a function/method call. */
94     class Delegate
95     {
96       public:
97         /** Callback type to use when creating a delegate from a function. */
98         typedef TemplateVariant (*StubType)(const void *obj, const QValueList<TemplateVariant> &args);
99
100         Delegate() : m_objectPtr(0) , m_stubPtr(0) {}
101
102         /** Creates a delegate given an object. The method to call is passed as a template parameter */
103         template <class T, TemplateVariant (T::*TMethod)(const QValueList<TemplateVariant> &) const>
104         static Delegate fromMethod(const T* objectPtr)
105         {
106           Delegate d;
107           d.m_objectPtr = objectPtr;
108           d.m_stubPtr   = &methodStub<T, TMethod>;
109           return d;
110         }
111         /** Creates a delegate given an object, and a plain function. */
112         static Delegate fromFunction(const void *obj,StubType func)
113         {
114           Delegate d;
115           d.m_objectPtr = obj;
116           d.m_stubPtr = func;
117           return d;
118         }
119
120         /** Invokes the function/method stored in the delegate */
121         TemplateVariant operator()(const QValueList<TemplateVariant> &args) const
122         {
123           return (*m_stubPtr)(m_objectPtr, args);
124         }
125
126       private:
127         const void* m_objectPtr;
128         StubType    m_stubPtr;
129
130         template <class T, TemplateVariant (T::*TMethod)(const QValueList<TemplateVariant> &) const>
131         static TemplateVariant methodStub(const void* objectPtr, const QValueList<TemplateVariant> &args)
132         {
133           T* p = (T*)(objectPtr);
134           return (p->*TMethod)(args);
135         }
136     };
137
138     /** Types of data that can be stored in a TemplateVariant */
139     enum Type { None, Bool, Integer, String, Struct, List, Function };
140
141     /** Returns the type of the value stored in the variant */
142     Type type() const { return m_type; }
143
144     /** Return a string representation of the type of the value stored in the variant */
145     QCString typeAsString() const
146     {
147       switch (m_type)
148       {
149         case None:     return "none";
150         case Bool:     return "bool";
151         case Integer:  return "integer";
152         case String:   return "string";
153         case Struct:   return "struct";
154         case List:     return "list";
155         case Function: return "function";
156       }
157       return "invalid";
158     }
159
160     /** Returns TRUE if the variant holds a valid value, or FALSE otherwise */
161     bool isValid() const { return m_type!=None; }
162
163     /** Constructs an invalid variant. */
164     TemplateVariant() : m_type(None), m_strukt(0), m_raw(FALSE) {}
165
166     /** Constructs a new variant with a boolean value \a b. */
167     explicit TemplateVariant(bool b) : m_type(Bool), m_boolVal(b), m_raw(FALSE) {}
168
169     /** Constructs a new variant with a integer value \a v. */
170     TemplateVariant(int v) : m_type(Integer), m_intVal(v), m_raw(FALSE) {}
171
172     /** Constructs a new variant with a string value \a s. */
173     TemplateVariant(const char *s,bool raw=FALSE) : m_type(String), m_strVal(s), m_strukt(0), m_raw(raw) {}
174
175     /** Constructs a new variant with a string value \a s. */
176     TemplateVariant(const QCString &s,bool raw=FALSE) : m_type(String), m_strVal(s), m_strukt(0), m_raw(raw) {}
177
178     /** Constructs a new variant with a struct value \a s.
179      *  @note. The variant will hold a reference to the object.
180      */
181     TemplateVariant(TemplateStructIntf *s);
182
183     /** Constructs a new variant with a list value \a l.
184      *  @note. The variant will hold a reference to the object.
185      */
186     TemplateVariant(TemplateListIntf *l);
187
188     /** Constructs a new variant which represents a method call
189      *  @param[in] delegate Delegate object to invoke when
190      *             calling call() on this variant.
191      *  @note Use TemplateVariant::Delegate::fromMethod() and
192      *  TemplateVariant::Delegate::fromFunction() to create
193      *  Delegate objects.
194      */
195     TemplateVariant(const Delegate &delegate) : m_type(Function), m_strukt(0), m_delegate(delegate), m_raw(FALSE) {}
196
197     /** Destroys the Variant object */
198     ~TemplateVariant();
199
200     /** Constructs a copy of the variant, \a v,
201      *  passed as the argument to this constructor.
202      */
203     TemplateVariant(const TemplateVariant &v);
204
205     /** Assigns the value of the variant \a v to this variant. */
206     TemplateVariant &operator=(const TemplateVariant &v);
207
208     /** Compares this QVariant with v and returns true if they are equal;
209      *  otherwise returns false.
210      */
211     bool operator==(TemplateVariant &other)
212     {
213       if (m_type==None)
214       {
215         return FALSE;
216       }
217       if (m_type==TemplateVariant::List && other.m_type==TemplateVariant::List)
218       {
219         return m_list==other.m_list; // TODO: improve me
220       }
221       else if (m_type==TemplateVariant::Struct && other.m_type==TemplateVariant::Struct)
222       {
223         return m_strukt==other.m_strukt; // TODO: improve me
224       }
225       else
226       {
227         return toString()==other.toString();
228       }
229     }
230
231     /** Returns the variant as a string. */
232     QCString toString() const
233     {
234       switch (m_type)
235       {
236         case None:     return QCString();
237         case Bool:     return m_boolVal ? "true" : "false";
238         case Integer:  return QCString().setNum(m_intVal);
239         case String:   return m_strVal;
240         case Struct:   return "[struct]";
241         case List:     return "[list]";
242         case Function: return "[function]";
243       }
244       return QCString();
245     }
246
247     /** Returns the variant as a boolean. */
248     bool toBool() const;
249
250     /** Returns the variant as an integer. */
251     int toInt() const;
252
253     /** Returns the pointer to list referenced by this variant
254      *  or 0 if this variant does not have list type.
255      */
256     TemplateListIntf   *toList() const
257     {
258       return m_type==List ? m_list : 0;
259     }
260
261     /** Returns the pointer to struct referenced by this variant
262      *  or 0 if this variant does not have struct type.
263      */
264     TemplateStructIntf *toStruct() const
265     {
266       return m_type==Struct ? m_strukt : 0;
267     }
268
269     /** Return the result of apply this function with \a args.
270      *  Returns an empty string if the variant type is not a function.
271      */
272     TemplateVariant call(const QValueList<TemplateVariant> &args)
273     {
274       if (m_type==Function) return m_delegate(args);
275       return TemplateVariant();
276     }
277
278     /** Sets whether or not the value of the Variant should be
279      *  escaped or written as-is (raw).
280      *  @param[in] b TRUE means write as-is, FALSE means apply escaping.
281      */
282     void setRaw(bool b) { m_raw = b; }
283
284     /** Returns whether or not the value of the Value is raw.
285      *  @see setRaw()
286      */
287     bool raw() const { return m_raw; }
288
289   private:
290     Type                  m_type;
291     QCString              m_strVal;
292     union
293     {
294       int                 m_intVal;
295       bool                m_boolVal;
296       TemplateStructIntf *m_strukt;
297       TemplateListIntf   *m_list;
298     };
299     Delegate              m_delegate;
300     bool                  m_raw;
301 };
302
303 //------------------------------------------------------------------------
304
305 template<class T> class TemplateAutoRef
306 {
307   public:
308     TemplateAutoRef(T *obj) : m_obj(obj)
309     {
310       m_obj->addRef();
311     }
312    ~TemplateAutoRef()
313     {
314       m_obj->release();
315     }
316     T &operator*() const { return *m_obj; }
317     T *operator->() const { return m_obj; }
318     T *get() const { return m_obj; }
319
320   private:
321    T *m_obj;
322 };
323
324 //------------------------------------------------------------------------
325
326 /** @brief Abstract read-only interface for a context value of type list.
327  *  @note The values of the list are TemplateVariants.
328  */
329 class TemplateListIntf
330 {
331   public:
332     /** @brief Abstract interface for a iterator of a list. */
333     class ConstIterator
334     {
335       public:
336         /** Destructor for the iterator */
337         virtual ~ConstIterator() {}
338         /** Moves iterator to the first element in the list */
339         virtual void toFirst() = 0;
340         /** Moves iterator to the last element in the list */
341         virtual void toLast() = 0;
342         /** Moves iterator to the next element in the list */
343         virtual void toNext() = 0;
344         /** Moves iterator to the previous element in the list */
345         virtual void toPrev() = 0;
346         /* Returns TRUE if the iterator points to a valid element
347          * in the list, or FALSE otherwise.
348          * If TRUE is returned, the value pointed to be the
349          * iterator is assigned to \a v.
350          */
351         virtual bool current(TemplateVariant &v) const = 0;
352     };
353
354     /** Destroys the list */
355     virtual ~TemplateListIntf() {}
356
357     /** Returns the number of elements in the list */
358     virtual int count() const = 0;
359
360     /** Returns the element at index position \a index. */
361     virtual TemplateVariant  at(int index) const = 0;
362
363     /** Creates a new iterator for this list.
364      *  @note the user should call delete on the returned pointer.
365      */
366     virtual TemplateListIntf::ConstIterator *createIterator() const = 0;
367
368     /** Increase object's reference count */
369     virtual int addRef() = 0;
370
371     /** Decreases object's referenc count, destroy object if 0 */
372     virtual int release() = 0;
373 };
374
375 /** @brief Default implementation of a context value of type list. */
376 class TemplateList : public TemplateListIntf
377 {
378   public:
379     // TemplateListIntf methods
380     virtual int  count() const;
381     virtual TemplateVariant at(int index) const;
382     virtual TemplateListIntf::ConstIterator *createIterator() const;
383     virtual int addRef();
384     virtual int release();
385
386     /** Creates an instance with ref count set to 0 */
387     static TemplateList *alloc();
388
389     /** Appends element \a v to the end of the list */
390     virtual void append(const TemplateVariant &v);
391
392   private:
393     /** Creates a list */
394     TemplateList();
395     /** Destroys the list */
396    ~TemplateList();
397
398     friend class TemplateListConstIterator;
399     class Private;
400     Private *p;
401 };
402
403 //------------------------------------------------------------------------
404
405 /** @brief Abstract interface for a context value of type struct. */
406 class TemplateStructIntf
407 {
408   public:
409     /** Destroys the struct */
410     virtual ~TemplateStructIntf() {}
411
412     /** Gets the value for a field name.
413      *  @param[in] name The name of the field.
414      */
415     virtual TemplateVariant get(const char *name) const = 0;
416
417     /** Increase object's reference count */
418     virtual int addRef() = 0;
419
420     /** Decreases object's referenc count, destroy object if 0 */
421     virtual int release() = 0;
422 };
423
424
425 /** @brief Default implementation of a context value of type struct. */
426 class TemplateStruct : public TemplateStructIntf
427 {
428   public:
429     // TemplateStructIntf methods
430     virtual TemplateVariant get(const char *name) const;
431     virtual int addRef();
432     virtual int release();
433
434     /** Creates an instance with ref count set to 0. */
435     static TemplateStruct *alloc();
436
437     /** Sets the value the field of a struct
438      *  @param[in] name The name of the field.
439      *  @param[in] v The value to set.
440      */
441     virtual void set(const char *name,const TemplateVariant &v);
442
443
444   private:
445     /** Creates a struct */
446     TemplateStruct();
447     /** Destroys the struct */
448     virtual ~TemplateStruct();
449
450     class Private;
451     Private *p;
452 };
453
454 //------------------------------------------------------------------------
455
456 /** @brief Interface used to escape characters in a string */
457 class TemplateEscapeIntf
458 {
459   public:
460     /** Returns the \a input after escaping certain characters */
461     virtual QCString escape(const QCString &input) = 0;
462     /** Setting tabbing mode on or off (for LaTeX) */
463     virtual void enableTabbing(bool b) = 0;
464 };
465
466 //------------------------------------------------------------------------
467
468 /** @brief Interface used to remove redundant spaces inside a spaceless block */
469 class TemplateSpacelessIntf
470 {
471   public:
472     /** Returns the \a input after removing redundant whitespace */
473     virtual QCString remove(const QCString &input) = 0;
474     /** Reset filter state */
475     virtual void reset() = 0;
476 };
477
478 //------------------------------------------------------------------------
479
480 /** @brief Abstract interface for a template context.
481  *
482  *  A Context consists of a stack of dictionaries.
483  *  A dictionary consists of a mapping of string keys onto TemplateVariant values.
484  *  A key is searched starting with the dictionary at the top of the stack
485  *  and searching downwards until it is found. The stack is used to create
486  *  local scopes.
487  *  @note This object must be created by TemplateEngine::createContext()
488  */
489 class TemplateContext
490 {
491   public:
492     virtual ~TemplateContext() {}
493
494     /** Push a new scope on the stack. */
495     virtual void push() = 0;
496
497     /** Pop the current scope from the stack. */
498     virtual void pop() = 0;
499
500     /** Sets a value in the current scope.
501      *  @param[in] name The name of the value; the key in the dictionary.
502      *  @param[in] v The value associated with the key.
503      *  @note When a given key is already present,
504      *  its value will be replaced by \a v
505      */
506     virtual void set(const char *name,const TemplateVariant &v) = 0;
507
508     /** Gets the value for a given key
509      *  @param[in] name The name of key.
510      *  @returns The value, which can be an invalid variant in case the
511      *  key was not found.
512      */
513     virtual TemplateVariant get(const QCString &name) const = 0;
514
515     /** Returns a pointer to the value corresponding to a given key.
516      *  @param[in] name The name of key.
517      *  @returns A pointer to the value, or 0 in case the key was not found.
518      */
519     virtual const TemplateVariant *getRef(const QCString &name) const = 0;
520
521     /** When files are created (i.e. by {% create ... %}) they written
522      *  to the directory \a dir.
523      */
524     virtual void setOutputDirectory(const QCString &dir) = 0;
525
526     /** Sets the interface that will be used for escaping the result
527      *  of variable expansion before writing it to the output.
528      */
529     virtual void setEscapeIntf(const QCString &extension, TemplateEscapeIntf *intf) = 0;
530
531     /** Sets the interface that will be used inside a spaceless block
532      *  to remove any redundant whitespace.
533      */
534     virtual void setSpacelessIntf(TemplateSpacelessIntf *intf) = 0;
535 };
536
537 //------------------------------------------------------------------------
538
539 /** @brief Abstract interface for a template.
540  *  @note Must be created and is deleted by the TemplateEngine
541  */
542 class Template
543 {
544   public:
545     /** Destructor */
546     virtual ~Template() {}
547
548     /** Renders a template instance to a stream.
549      *  @param[in] ts The text stream to write the results to.
550      *  @param[in] c The context containing data that can be used
551      *  when instantiating the template.
552      */
553     virtual void render(FTextStream &ts,TemplateContext *c) = 0;
554 };
555
556 //------------------------------------------------------------------------
557
558 /** @brief Engine to create templates and template contexts. */
559 class TemplateEngine
560 {
561   public:
562     /** Create a template engine. */
563     TemplateEngine();
564
565     /** Destroys the template engine. */
566    ~TemplateEngine();
567
568     /** Creates a new context that can be using to render a template.
569      *  @see Template::render()
570      */
571     TemplateContext *createContext() const;
572
573     /** Destroys a context created via createContext().
574      *  @param[in] ctx The context.
575      */
576     void destroyContext(TemplateContext *ctx);
577
578     /** Creates a new template whose contents are in a file.
579      *  @param[in] fileName The name of the file containing the template data
580      *  @param[in] fromLine The line number of the statement that triggered the load
581      *  @return the new template, the engine will keep ownership of the object.
582      */
583     Template *loadByName(const QCString &fileName,int fromLine);
584
585     /** Indicates that template \a t is no longer needed. The engine
586      *  may decide to delete it.
587      */
588     void unload(Template *t);
589
590     /** Prints the current template file include stack */
591     void printIncludeContext(const char *fileName,int line) const;
592
593     /** Sets the search directory where to look for template files */
594     void setTemplateDir(const char *dirName);
595
596   private:
597     friend class TemplateNodeBlock;
598     friend class TemplateNodeCreate;
599
600     void enterBlock(const QCString &fileName,const QCString &blockName,int line);
601     void leaveBlock();
602
603     /** Sets the extension of the output file. This is used to control the
604      *  format of 'special' tags in the template
605      */
606     void setOutputExtension(const char *extension);
607
608     /** Returns the output extension, set via setOutputExtension() */
609     QCString outputExtension() const;
610
611     class Private;
612     Private *p;
613 };
614
615 /** @} */
616
617 #endif