summaryrefslogtreecommitdiffstats
path: root/src/template.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/template.h')
-rw-r--r--src/template.h395
1 files changed, 395 insertions, 0 deletions
diff --git a/src/template.h b/src/template.h
new file mode 100644
index 0000000..454a70b
--- /dev/null
+++ b/src/template.h
@@ -0,0 +1,395 @@
+#ifndef TEMPLATE_H
+#define TEMPLATE_H
+
+#include <qcstring.h>
+#include <qvaluelist.h>
+
+class FTextStream;
+
+class TemplateListIntf;
+class TemplateStructIntf;
+class TemplateEngine;
+
+/** @defgroup template_api Template API
+ *
+ * This is the API for a
+ * <a href="https://docs.djangoproject.com/en/1.6/topics/templates/">Django</a>
+ * compatible template system written in C++.
+ * It is somewhat inspired by Stephen Kelly's
+ * <a href="http://www.gitorious.org/grantlee/pages/Home">Grantlee</a>.
+ *
+ * A template is simply a text file.
+ * A template contains \b variables, which get replaced with values when the
+ * template is evaluated, and \b tags, which control the logic of the template.
+ *
+ * Variables look like this: `{{ variable }}`
+ * When the template engine encounters a variable, it evaluates that variable and
+ * replaces it with the result. Variable names consist of any combination of
+ * alphanumeric characters and the underscore ("_").
+ * Use a dot (.) to access attributes of a variable.
+ *
+ * One can modify variables for display by using \b filters, for example:
+ * `{{ value|default:"nothing" }}`
+ *
+ * Tags look like this: `{% tag %}`. Tags are more complex than variables:
+ * Some create text in the output, some control flow by performing loops or logic,
+ * and some load external information into the template to be used by later variables.
+ *
+ * To comment-out part of a line in a template, use the comment syntax:
+ * `{# comment text #}`.
+ *
+ * Supported Django tags:
+ * - `for ... empty ... endfor`
+ * - `if ... else ... endif`
+ * - `block ... endblock`
+ * - `extends`
+ * - `include`
+ *
+ * Supported Django filters:
+ * - `default`
+ * - `length`
+ * - `add`
+ *
+ * Extension tags:
+ * - `create` which instantiates a template and writes the result to a file.
+ * The syntax is `{% create 'filename' from 'template' %}`.
+ *
+ * @{
+ */
+
+/** @brief Variant type which can hold one value of a fixed set of types. */
+class TemplateVariant
+{
+ public:
+ /** Signature of the callback function, used for function type variants */
+ typedef QCString (*FuncType)(const void *obj, const QValueList<TemplateVariant> &args);
+
+ /** Types of data that can be stored in a TemplateVariant */
+ enum Type { None, Bool, Integer, String, Struct, List, Function };
+
+ /** Returns the type of the value stored in the variant */
+ Type type() const;
+
+ /** Returns TRUE if the variant holds a valid value, or FALSE otherwise */
+ bool isValid() const;
+
+ /** Constructs an invalid variant. */
+ TemplateVariant();
+
+ /** Constructs a new variant with a boolean value \a b. */
+ explicit TemplateVariant(bool b);
+
+ /** Constructs a new variant with a integer value \a v. */
+ TemplateVariant(int v);
+
+ /** Constructs a new variant with a string value \a s. */
+ TemplateVariant(const char *s);
+
+ /** Constructs a new variant with a string value \a s. */
+ TemplateVariant(const QCString &s);
+
+ /** Constructs a new variant with a struct value \a s.
+ * @note. Only a pointer to the struct is stored. The caller
+ * is responsible to manage the memory for the struct object.
+ */
+ TemplateVariant(const TemplateStructIntf *s);
+
+ /** Constructs a new variant with a list value \a l.
+ * @note. Only a pointer to the struct is stored. The caller
+ * is responsible to manage the memory for the list object.
+ */
+ TemplateVariant(const TemplateListIntf *l);
+
+ /** Constructs a new variant which represents a function
+ * @param[in] obj Opaque user defined pointer, which
+ * is passed back when call() is invoked.
+ * @param[in] func Callback function to invoke when
+ * calling call() on this variant.
+ */
+ TemplateVariant(const void *obj,FuncType func);
+
+ /** Destroys the Variant object */
+ ~TemplateVariant();
+
+ /** Constructs a copy of the variant, \a v,
+ * passed as the argument to this constructor.
+ */
+ TemplateVariant(const TemplateVariant &v);
+
+ /** Assigns the value of the variant \a v to this variant. */
+ TemplateVariant &operator=(const TemplateVariant &v);
+
+ /** Compares this QVariant with v and returns true if they are equal;
+ * otherwise returns false.
+ */
+ bool operator==(TemplateVariant &other);
+
+ /** Returns the variant as a string. */
+ QCString toString() const;
+
+ /** Returns the variant as a boolean. */
+ bool toBool() const;
+
+ /** Returns the variant as an integer. */
+ int toInt() const;
+
+ /** Returns the pointer to list referenced by this variant
+ * or 0 if this variant does not have list type.
+ */
+ const TemplateListIntf *toList() const;
+
+ /** Returns the pointer to struct referenced by this variant
+ * or 0 if this variant does not have struct type.
+ */
+ const TemplateStructIntf *toStruct() const;
+
+ /** Return the result of apply this function with \a args.
+ * Returns an empty string if the variant type is not a function.
+ */
+ QCString call(const QValueList<TemplateVariant> &args);
+
+ /** Sets whether or not the value of the Variant should be
+ * escaped or written as-is (raw).
+ * @param[in] b TRUE means write as-is, FALSE means apply escaping.
+ */
+ void setRaw(bool b);
+
+ /** Returns whether or not the value of the Value is raw.
+ * @see setRaw()
+ */
+ bool raw() const;
+
+ private:
+ class Private;
+ Private *p;
+};
+
+//------------------------------------------------------------------------
+
+/** @brief Abstract read-only interface for a context value of type list.
+ * @note The values of the list are TemplateVariants.
+ */
+class TemplateListIntf
+{
+ public:
+ /** @brief Abstract interface for a iterator of a list. */
+ class ConstIterator
+ {
+ public:
+ /** Destructor for the iterator */
+ virtual ~ConstIterator() {}
+ /** Moves iterator to the first element in the list */
+ virtual void toFirst() = 0;
+ /** Moves iterator to the last element in the list */
+ virtual void toLast() = 0;
+ /** Moves iterator to the next element in the list */
+ virtual void toNext() = 0;
+ /** Moves iterator to the previous element in the list */
+ virtual void toPrev() = 0;
+ /* Returns TRUE if the iterator points to a valid element
+ * in the list, or FALSE otherwise.
+ * If TRUE is returned, the value pointed to be the
+ * iterator is assigned to \a v.
+ */
+ virtual bool current(TemplateVariant &v) const = 0;
+ };
+
+ /** Destroys the list */
+ virtual ~TemplateListIntf() {}
+
+ /** Returns the number of elements in the list */
+ virtual int count() const = 0;
+
+ /** Returns the element at index position \a index. */
+ virtual TemplateVariant at(int index) const = 0;
+
+ /** Creates a new iterator for this list.
+ * @note the user should call delete on the returned pointer.
+ */
+ virtual TemplateListIntf::ConstIterator *createIterator() const = 0;
+};
+
+/** @brief Default implementation of a context value of type list. */
+class TemplateList : public TemplateListIntf
+{
+ public:
+ /** Creates a list */
+ TemplateList();
+ /** Destroys the list */
+ ~TemplateList();
+
+ // TemplateListIntf methods
+ virtual int count() const;
+ virtual TemplateVariant at(int index) const;
+ virtual TemplateListIntf::ConstIterator *createIterator() const;
+
+ /** Appends element \a v to the end of the list */
+ virtual void append(const TemplateVariant &v);
+
+ private:
+ friend class TemplateListConstIterator;
+ class Private;
+ Private *p;
+};
+
+//------------------------------------------------------------------------
+
+/** @brief Abstract interface for a context value of type struct. */
+class TemplateStructIntf
+{
+ public:
+ /** Destroys the struct */
+ virtual ~TemplateStructIntf() {}
+
+ /** Gets the value for a field name.
+ * @param[in] name The name of the field.
+ */
+ virtual TemplateVariant get(const char *name) const = 0;
+};
+
+
+/** @brief Default implementation of a context value of type struct. */
+class TemplateStruct : public TemplateStructIntf
+{
+ public:
+ /** Creates a struct */
+ TemplateStruct();
+ /** Destroys the struct */
+ virtual ~TemplateStruct();
+
+ // TemplateStructIntf methods
+ virtual TemplateVariant get(const char *name) const;
+
+ /** Sets the value the field of a struct
+ * @param[in] name The name of the field.
+ * @param[in] v The value to set.
+ */
+ virtual void set(const char *name,const TemplateVariant &v);
+
+ private:
+ class Private;
+ Private *p;
+};
+
+//------------------------------------------------------------------------
+
+/** @brief Interface used to escape characters in a string */
+class TemplateEscapeIntf
+{
+ public:
+ /** Returns the \a input after escaping certain characters */
+ virtual QCString escape(const QCString &input) = 0;
+};
+
+//------------------------------------------------------------------------
+
+/** @brief Abstract interface for a template context.
+ *
+ * A Context consists of a stack of dictionaries.
+ * A dictionary consists of a mapping of string keys onto TemplateVariant values.
+ * A key is searched starting with the dictionary at the top of the stack
+ * and searching downwards until it is found. The stack is used to create
+ * local scopes.
+ * @note This object must be created by TemplateEngine
+ */
+class TemplateContext
+{
+ public:
+ virtual ~TemplateContext() {}
+
+ /** Push a new scope on the stack. */
+ virtual void push() = 0;
+
+ /** Pop the current scope from the stack. */
+ virtual void pop() = 0;
+
+ /** Sets a value in the current scope.
+ * @param[in] name The name of the value; the key in the dictionary.
+ * @param[in] v The value associated with the key.
+ * @note When a given key is already present,
+ * its value will be replaced by \a v
+ */
+ virtual void set(const char *name,const TemplateVariant &v) = 0;
+
+ /** Gets the value for a given key
+ * @param[in] name The name of key.
+ * @returns The value, which can be an invalid variant in case the
+ * key was not found.
+ */
+ virtual TemplateVariant get(const QCString &name) const = 0;
+
+ /** Returns a pointer to the value corresponding to a given key.
+ * @param[in] name The name of key.
+ * @returns A pointer to the value, or 0 in case the key was not found.
+ */
+ virtual const TemplateVariant *getRef(const QCString &name) const = 0;
+
+ /** When files are create (i.e. by {% create ... %}) they written
+ * to the directory \a dir.
+ */
+ virtual void setOutputDirectory(const QCString &dir) = 0;
+
+ /** Sets the interface that will be used for escaping the result
+ * of variable expansion before writing it to the output.
+ */
+ virtual void setEscapeIntf(TemplateEscapeIntf *intf) = 0;
+};
+
+//------------------------------------------------------------------------
+
+/** @brief Abstract interface for a template.
+ * @note Must be created by TemplateEngine
+ */
+class Template
+{
+ public:
+ /** Destructor */
+ virtual ~Template() {}
+
+ /** Renders a template instance to a stream.
+ * @param[in] ts The text stream to write the results to.
+ * @param[in] c The context containing data that can be used
+ * when instantiating the template.
+ */
+ virtual void render(FTextStream &ts,TemplateContext *c) = 0;
+};
+
+//------------------------------------------------------------------------
+
+/** @brief Engine to create templates and template contexts. */
+class TemplateEngine
+{
+ public:
+ /** Create a template engine. */
+ TemplateEngine();
+
+ /** Destroys the template engine. */
+ ~TemplateEngine();
+
+ /** Creates a new context that can be using to render a template.
+ * @see Template::render()
+ */
+ TemplateContext *createContext() const;
+
+ /** Creates a new template whose contents are given by a string.
+ * @param[in] name The name of the template.
+ * @param[in] data The contents of the template.
+ * @return the new template, the caller will be the owner.
+ */
+ Template *newTemplate(const QCString &name,const QCString &data);
+
+ /** Creates a new template whole contents are in a file.
+ * @param[in] fileName The name of the file containing the
+ * template data
+ * @return the new template, the caller will be the owner.
+ */
+ Template *loadByName(const QCString &fileName);
+
+ private:
+ class Private;
+ Private *p;
+};
+
+/** @} */
+
+#endif