LP-311 Remove basic/advanced stabilization tab auto-switch (autotune/txpid lock issues)
[librepilot.git] / ground / gcs / src / libs / utils / mustache.h
blob2d76e35640b40a8059d9e298880c6549970f509b
1 /*
2 Copyright 2012, Robert Knight
4 Redistribution and use in source and binary forms, with or without modification,
5 are permitted provided that the following conditions are met:
7 Redistributions of source code must retain the above copyright notice,
8 this list of conditions and the following disclaimer.
10 Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
15 #pragma once
17 #include <QtCore/QStack>
18 #include <QtCore/QString>
19 #include <QtCore/QVariant>
21 #include "utils_global.h"
23 #if __cplusplus >= 201103L
24 #include <functional> /* for std::function */
25 #endif
27 namespace Mustache {
28 class PartialResolver;
29 class Renderer;
31 /** Context is an interface that Mustache::Renderer::render() uses to
32 * fetch substitutions for template tags.
34 class QTCREATOR_UTILS_EXPORT Context {
35 public:
36 /** Create a context. @p resolver is used to fetch the expansions for any {{>partial}} tags
37 * which appear in a template.
39 explicit Context(PartialResolver *resolver = 0);
40 virtual ~Context() {}
42 /** Returns a string representation of the value for @p key in the current context.
43 * This is used to replace a Mustache value tag.
45 virtual QString stringValue(const QString & key) const = 0;
47 /** Returns true if the value for @p key is 'false' or an empty list.
48 * 'False' values typically include empty strings, the boolean value false etc.
50 * When processing a section Mustache tag, the section is not rendered if the key
51 * is false, or for an inverted section tag, the section is only rendered if the key
52 * is false.
54 virtual bool isFalse(const QString & key) const = 0;
56 /** Returns the number of items in the list value for @p key or 0 if
57 * the value for @p key is not a list.
59 virtual int listCount(const QString & key) const = 0;
61 /** Set the current context to the value for @p key.
62 * If index is >= 0, set the current context to the @p index'th value
63 * in the list value for @p key.
65 virtual void push(const QString & key, int index = -1) = 0;
67 /** Exit the current context. */
68 virtual void pop() = 0;
70 /** Returns the partial template for a given @p key. */
71 QString partialValue(const QString & key) const;
73 /** Returns the partial resolver passed to the constructor. */
74 PartialResolver *partialResolver() const;
76 /** Returns true if eval() should be used to render section tags using @p key.
77 * If canEval() returns true for a key, the renderer will pass the literal, unrendered
78 * block of text for the section to eval() and replace the section with the result.
80 * canEval() and eval() are equivalents for callable objects (eg. lambdas) in other
81 * Mustache implementations.
83 * The default implementation always returns false.
85 virtual bool canEval(const QString & key) const;
87 /** Callback used to render a template section with the given @p key.
88 * @p renderer will substitute the original section tag with the result of eval().
90 * The default implementation returns an empty string.
92 virtual QString eval(const QString & key, const QString & _template, Renderer *renderer);
94 private:
95 PartialResolver *m_partialResolver;
98 /** A context implementation which wraps a QVariantHash or QVariantMap. */
99 class QTCREATOR_UTILS_EXPORT QtVariantContext : public Context {
100 public:
101 /** Construct a QtVariantContext which wraps a dictionary in a QVariantHash
102 * or a QVariantMap.
104 #if __cplusplus >= 201103L
105 typedef std::function<QString(const QString &, Mustache::Renderer *, Mustache::Context *)> fn_t;
106 #else
107 typedef QString (*fn_t)(const QString &, Mustache::Renderer *, Mustache::Context *);
108 #endif
109 explicit QtVariantContext(const QVariant & root, PartialResolver *resolver = 0);
111 virtual QString stringValue(const QString & key) const;
112 virtual bool isFalse(const QString & key) const;
113 virtual int listCount(const QString & key) const;
114 virtual void push(const QString & key, int index = -1);
115 virtual void pop();
116 virtual bool canEval(const QString & key) const;
117 virtual QString eval(const QString & key, const QString & _template, Mustache::Renderer *renderer);
119 private:
120 QVariant value(const QString & key) const;
122 QStack<QVariant> m_contextStack;
125 /** Interface for fetching template partials. */
126 class QTCREATOR_UTILS_EXPORT PartialResolver {
127 public:
128 virtual ~PartialResolver() {}
130 /** Returns the partial template with a given @p name. */
131 virtual QString getPartial(const QString & name) = 0;
134 /** A simple partial fetcher which returns templates from a map of (partial name -> template)
136 class QTCREATOR_UTILS_EXPORT PartialMap : public PartialResolver {
137 public:
138 explicit PartialMap(const QHash<QString, QString> & partials);
140 virtual QString getPartial(const QString & name);
142 private:
143 QHash<QString, QString> m_partials;
146 /** A partial fetcher when loads templates from '<name>.mustache' files
147 * in a given directory.
149 * Once a partial has been loaded, it is cached for future use.
151 class QTCREATOR_UTILS_EXPORT PartialFileLoader : public PartialResolver {
152 public:
153 explicit PartialFileLoader(const QString & basePath);
155 virtual QString getPartial(const QString & name);
157 private:
158 QString m_basePath;
159 QHash<QString, QString> m_cache;
162 /** Holds properties of a tag in a mustache template. */
163 struct Tag {
164 enum Type {
165 Null,
166 Value, /// A {{key}} or {{{key}}} tag
167 SectionStart, /// A {{#section}} tag
168 InvertedSectionStart, /// An {{^inverted-section}} tag
169 SectionEnd, /// A {{/section}} tag
170 Partial, /// A {{^partial}} tag
171 Comment, /// A {{! comment }} tag
172 SetDelimiter /// A {{=<% %>=}} tag
175 enum EscapeMode {
176 Escape,
177 Unescape,
181 Tag()
182 : type(Null)
183 , start(0)
184 , end(0)
185 , escapeMode(Escape)
188 Type type;
189 QString key;
190 int start;
191 int end;
192 EscapeMode escapeMode;
195 /** Renders Mustache templates, replacing mustache tags with
196 * values from a provided context.
198 class QTCREATOR_UTILS_EXPORT Renderer {
199 public:
200 Renderer();
202 /** Render a Mustache template, using @p context to fetch
203 * the values used to replace Mustache tags.
205 QString render(const QString & _template, Context *context);
207 /** Returns a message describing the last error encountered by the previous
208 * render() call.
210 QString error() const;
212 /** Returns the position in the template where the last error occurred
213 * when rendering the template or -1 if no error occurred.
215 * If the error occurred in a partial template, the returned position is the offset
216 * in the partial template.
218 int errorPos() const;
220 /** Returns the name of the partial where the error occurred, or an empty string
221 * if the error occurred in the main template.
223 QString errorPartial() const;
225 /** Sets the default tag start and end markers.
226 * This can be overridden within a template.
228 void setTagMarkers(const QString & startMarker, const QString & endMarker);
230 private:
231 QString render(const QString & _template, int startPos, int endPos, Context *context);
233 Tag findTag(const QString & content, int pos, int endPos);
234 Tag findEndTag(const QString & content, const Tag & startTag, int endPos);
235 void setError(const QString & error, int pos);
237 void readSetDelimiter(const QString & content, int pos, int endPos);
238 static QString readTagName(const QString & content, int pos, int endPos);
240 /** Expands @p tag to fill the line, but only if it is standalone.
242 * The start position is moved to the beginning of the line. The end position is
243 * moved to one past the end of the line. If @p tag is not standalone, it is
244 * left unmodified.
246 * A tag is standalone if it is the only non-whitespace token on the the line.
248 static void expandTag(Tag & tag, const QString & content);
250 QStack<QString> m_partialStack;
251 QString m_error;
252 int m_errorPos;
253 QString m_errorPartial;
255 QString m_tagStartMarker;
256 QString m_tagEndMarker;
258 QString m_defaultTagStartMarker;
259 QString m_defaultTagEndMarker;
262 /** A convenience function which renders a template using the given data. */
263 QString renderTemplate(const QString & templateString, const QVariantHash & args);
266 Q_DECLARE_METATYPE(Mustache::QtVariantContext::fn_t)