1 /******************************************************************************
3 * Copyright (C) 1997-2015 by Dimitri van Heesch.
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.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
20 #include <qvaluelist.h>
24 class TemplateListIntf;
25 class TemplateStructIntf;
28 /** @defgroup template_api Template API
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>.
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.
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.
46 * One can modify variables for display by using \b filters, for example:
47 * `{{ value|default:"nothing" }}`
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.
53 * To comment-out part of a line in a template, use the comment syntax:
54 * `{# comment text #}`.
56 * Supported Django tags:
57 * - `for ... empty ... endfor`
58 * - `if ... else ... endif`
59 * - `block ... endblock`
62 * - `with ... endwith`
63 * - `spaceless ... endspaceless`
67 * - `create` which instantiates a template and writes the result to a file.
68 * The syntax is `{% create 'filename' from 'template' %}`.
71 * - `msg` ... `endmsg`
74 * Supported Django filters:
89 /** @brief Variant type which can hold one value of a fixed set of types. */
93 /** @brief Helper class to create a delegate that can store a function/method call. */
97 /** Callback type to use when creating a delegate from a function. */
98 typedef TemplateVariant (*StubType)(const void *obj, const QValueList<TemplateVariant> &args);
100 Delegate() : m_objectPtr(0) , m_stubPtr(0) {}
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)
107 d.m_objectPtr = objectPtr;
108 d.m_stubPtr = &methodStub<T, TMethod>;
111 /** Creates a delegate given an object, and a plain function. */
112 static Delegate fromFunction(const void *obj,StubType func)
120 /** Invokes the function/method stored in the delegate */
121 TemplateVariant operator()(const QValueList<TemplateVariant> &args) const
123 return (*m_stubPtr)(m_objectPtr, args);
127 const void* m_objectPtr;
130 template <class T, TemplateVariant (T::*TMethod)(const QValueList<TemplateVariant> &) const>
131 static TemplateVariant methodStub(const void* objectPtr, const QValueList<TemplateVariant> &args)
133 T* p = (T*)(objectPtr);
134 return (p->*TMethod)(args);
138 /** Types of data that can be stored in a TemplateVariant */
139 enum Type { None, Bool, Integer, String, Struct, List, Function };
141 /** Returns the type of the value stored in the variant */
142 Type type() const { return m_type; }
144 /** Return a string representation of the type of the value stored in the variant */
145 QCString typeAsString() const
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";
160 /** Returns TRUE if the variant holds a valid value, or FALSE otherwise */
161 bool isValid() const { return m_type!=None; }
163 /** Constructs an invalid variant. */
164 TemplateVariant() : m_type(None), m_strukt(0), m_raw(FALSE) {}
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) {}
169 /** Constructs a new variant with a integer value \a v. */
170 TemplateVariant(int v) : m_type(Integer), m_intVal(v), m_raw(FALSE) {}
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) {}
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) {}
178 /** Constructs a new variant with a struct value \a s.
179 * @note. The variant will hold a reference to the object.
181 TemplateVariant(TemplateStructIntf *s);
183 /** Constructs a new variant with a list value \a l.
184 * @note. The variant will hold a reference to the object.
186 TemplateVariant(TemplateListIntf *l);
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
195 TemplateVariant(const Delegate &delegate) : m_type(Function), m_strukt(0), m_delegate(delegate), m_raw(FALSE) {}
197 /** Destroys the Variant object */
200 /** Constructs a copy of the variant, \a v,
201 * passed as the argument to this constructor.
203 TemplateVariant(const TemplateVariant &v);
205 /** Assigns the value of the variant \a v to this variant. */
206 TemplateVariant &operator=(const TemplateVariant &v);
208 /** Compares this QVariant with v and returns true if they are equal;
209 * otherwise returns false.
211 bool operator==(TemplateVariant &other)
217 if (m_type==TemplateVariant::List && other.m_type==TemplateVariant::List)
219 return m_list==other.m_list; // TODO: improve me
221 else if (m_type==TemplateVariant::Struct && other.m_type==TemplateVariant::Struct)
223 return m_strukt==other.m_strukt; // TODO: improve me
227 return toString()==other.toString();
231 /** Returns the variant as a string. */
232 QCString toString() const
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]";
247 /** Returns the variant as a boolean. */
250 /** Returns the variant as an integer. */
253 /** Returns the pointer to list referenced by this variant
254 * or 0 if this variant does not have list type.
256 TemplateListIntf *toList() const
258 return m_type==List ? m_list : 0;
261 /** Returns the pointer to struct referenced by this variant
262 * or 0 if this variant does not have struct type.
264 TemplateStructIntf *toStruct() const
266 return m_type==Struct ? m_strukt : 0;
269 /** Return the result of apply this function with \a args.
270 * Returns an empty string if the variant type is not a function.
272 TemplateVariant call(const QValueList<TemplateVariant> &args)
274 if (m_type==Function) return m_delegate(args);
275 return TemplateVariant();
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.
282 void setRaw(bool b) { m_raw = b; }
284 /** Returns whether or not the value of the Value is raw.
287 bool raw() const { return m_raw; }
296 TemplateStructIntf *m_strukt;
297 TemplateListIntf *m_list;
303 //------------------------------------------------------------------------
305 template<class T> class TemplateAutoRef
308 TemplateAutoRef(T *obj) : m_obj(obj)
316 T &operator*() const { return *m_obj; }
317 T *operator->() const { return m_obj; }
318 T *get() const { return m_obj; }
324 //------------------------------------------------------------------------
326 /** @brief Abstract read-only interface for a context value of type list.
327 * @note The values of the list are TemplateVariants.
329 class TemplateListIntf
332 /** @brief Abstract interface for a iterator of a list. */
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.
351 virtual bool current(TemplateVariant &v) const = 0;
354 /** Destroys the list */
355 virtual ~TemplateListIntf() {}
357 /** Returns the number of elements in the list */
358 virtual int count() const = 0;
360 /** Returns the element at index position \a index. */
361 virtual TemplateVariant at(int index) const = 0;
363 /** Creates a new iterator for this list.
364 * @note the user should call delete on the returned pointer.
366 virtual TemplateListIntf::ConstIterator *createIterator() const = 0;
368 /** Increase object's reference count */
369 virtual int addRef() = 0;
371 /** Decreases object's referenc count, destroy object if 0 */
372 virtual int release() = 0;
375 /** @brief Default implementation of a context value of type list. */
376 class TemplateList : public TemplateListIntf
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();
386 /** Creates an instance with ref count set to 0 */
387 static TemplateList *alloc();
389 /** Appends element \a v to the end of the list */
390 virtual void append(const TemplateVariant &v);
393 /** Creates a list */
395 /** Destroys the list */
398 friend class TemplateListConstIterator;
403 //------------------------------------------------------------------------
405 /** @brief Abstract interface for a context value of type struct. */
406 class TemplateStructIntf
409 /** Destroys the struct */
410 virtual ~TemplateStructIntf() {}
412 /** Gets the value for a field name.
413 * @param[in] name The name of the field.
415 virtual TemplateVariant get(const char *name) const = 0;
417 /** Increase object's reference count */
418 virtual int addRef() = 0;
420 /** Decreases object's referenc count, destroy object if 0 */
421 virtual int release() = 0;
425 /** @brief Default implementation of a context value of type struct. */
426 class TemplateStruct : public TemplateStructIntf
429 // TemplateStructIntf methods
430 virtual TemplateVariant get(const char *name) const;
431 virtual int addRef();
432 virtual int release();
434 /** Creates an instance with ref count set to 0. */
435 static TemplateStruct *alloc();
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.
441 virtual void set(const char *name,const TemplateVariant &v);
445 /** Creates a struct */
447 /** Destroys the struct */
448 virtual ~TemplateStruct();
454 //------------------------------------------------------------------------
456 /** @brief Interface used to escape characters in a string */
457 class TemplateEscapeIntf
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;
466 //------------------------------------------------------------------------
468 /** @brief Interface used to remove redundant spaces inside a spaceless block */
469 class TemplateSpacelessIntf
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;
478 //------------------------------------------------------------------------
480 /** @brief Abstract interface for a template context.
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
487 * @note This object must be created by TemplateEngine::createContext()
489 class TemplateContext
492 virtual ~TemplateContext() {}
494 /** Push a new scope on the stack. */
495 virtual void push() = 0;
497 /** Pop the current scope from the stack. */
498 virtual void pop() = 0;
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
506 virtual void set(const char *name,const TemplateVariant &v) = 0;
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
513 virtual TemplateVariant get(const QCString &name) const = 0;
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.
519 virtual const TemplateVariant *getRef(const QCString &name) const = 0;
521 /** When files are created (i.e. by {% create ... %}) they written
522 * to the directory \a dir.
524 virtual void setOutputDirectory(const QCString &dir) = 0;
526 /** Sets the interface that will be used for escaping the result
527 * of variable expansion before writing it to the output.
529 virtual void setEscapeIntf(const QCString &extension, TemplateEscapeIntf *intf) = 0;
531 /** Sets the interface that will be used inside a spaceless block
532 * to remove any redundant whitespace.
534 virtual void setSpacelessIntf(TemplateSpacelessIntf *intf) = 0;
537 //------------------------------------------------------------------------
539 /** @brief Abstract interface for a template.
540 * @note Must be created and is deleted by the TemplateEngine
546 virtual ~Template() {}
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.
553 virtual void render(FTextStream &ts,TemplateContext *c) = 0;
556 //------------------------------------------------------------------------
558 /** @brief Engine to create templates and template contexts. */
562 /** Create a template engine. */
565 /** Destroys the template engine. */
568 /** Creates a new context that can be using to render a template.
569 * @see Template::render()
571 TemplateContext *createContext() const;
573 /** Destroys a context created via createContext().
574 * @param[in] ctx The context.
576 void destroyContext(TemplateContext *ctx);
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.
583 Template *loadByName(const QCString &fileName,int fromLine);
585 /** Indicates that template \a t is no longer needed. The engine
586 * may decide to delete it.
588 void unload(Template *t);
590 /** Prints the current template file include stack */
591 void printIncludeContext(const char *fileName,int line) const;
593 /** Sets the search directory where to look for template files */
594 void setTemplateDir(const char *dirName);
597 friend class TemplateNodeBlock;
598 friend class TemplateNodeCreate;
600 void enterBlock(const QCString &fileName,const QCString &blockName,int line);
603 /** Sets the extension of the output file. This is used to control the
604 * format of 'special' tags in the template
606 void setOutputExtension(const char *extension);
608 /** Returns the output extension, set via setOutputExtension() */
609 QCString outputExtension() const;