Squashed 'third_party/ctemplate/' content from commit 6742f62
Change-Id: I828e4e4c906f13ba19944d78a8a78652b62949af
git-subtree-dir: third_party/ctemplate
git-subtree-split: 6742f6233db12f545e90baa8f34f5c29c4eb396a
diff --git a/doc/example.html b/doc/example.html
new file mode 100644
index 0000000..91464c5
--- /dev/null
+++ b/doc/example.html
@@ -0,0 +1,345 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>Template Examples</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link href="designstyle.css" type="text/css" rel="stylesheet">
+<style type="text/css">
+ ol.bluelist li {
+ color: #3366ff;
+ font-family: sans-serif;
+ }
+ ol.bluelist li p {
+ color: #000;
+ font-family: "Times Roman", times, serif;
+ }
+ ul.blacklist li {
+ color: #000;
+ font-family: "Times Roman", times, serif;
+ }
+</style>
+</head>
+
+<body>
+
+<h1>Template Examples</h1>
+
+
+<h2> Simple Example </h2>
+
+<p>One reason this example is so simple is that it doesn't even
+require a separate template file, but instead uses
+<code>StringToTemplateCache()</code>. It also doesn't use sections or
+template-includes.</p>
+
+<pre class=example>
+
+int main() {
+ static const char template_text[] =
+ "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n";
+ ctemplate::StringToTemplateCache("mytpl", template_text, ctemplate::DO_NOT_STRIP);
+ FILE* fp = fopen(argv[1], "r");
+ if (fp == NULL) {
+ int err_no = errno; // squirrel this away
+ ctemplate::TemplateDictionary dict("error_msg: fopen()");
+ dict.SetValue("FUNCTION", "fopen");
+ dict.SetValue("ARGS", argv[1]);
+ dict.SetIntValue("ERROR_CODE", err_no);
+ dict.SetValue("ERROR_MESSAGE", strerror(err_no));
+
+ string error_text;
+ ctemplate::ExpandTemplate("mytpl", ctemplate::DO_NOT_STRIP, &dict, &error_text);
+ puts(error_text.c_str());
+ }
+}
+
+</pre>
+
+Note: If this template was intended to run in a web application, you can
+leverage the functionality provided by the auto-escape mode. Simply add
+the AUTOESCAPE pragma directive at the top of the template text and your
+variables will be automatically escaped for the context you specify.
+
+For example, if your template is returned in an HTML context,
+change the <code>template_text</code> declaration as follows:
+
+<pre class=example>
+ static const char template_text[] =
+ "{{%AUTOESCAPE context=\"HTML\"}}"
+ "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}: {{ERROR_MESSAGE}}\n";
+</pre>
+
+<p>This example is only slightly more complicated: we only print the
+": <error message>" part when the error message isn't the empty
+string.</p>
+
+<pre class=example>
+
+int main() {
+ static const char template_text[] =
+ "ERROR: {{FUNCTION}}({{ARGS}}) returned {{ERROR_CODE}}"
+ "{{#MSG_SECTION}}: {{ERROR_MESSAGE}}{{/MSG_SECTION}}\n";
+ ctemplate::StringToTemplateCache("mytpl", template_text, ctemplate::DO_NOT_STRIP);
+ FILE* fp = fopen(argv[1], "r");
+ if (fp == NULL) {
+ int err_no = errno; // squirrel this away
+ ctemplate::TemplateDictionary dict("file_error_message");
+ dict.SetValue("FUNCTION", "fopen");
+ dict.SetValue("ARGS", argv[1]);
+ dict.SetIntValue("ERROR_CODE", err_no);
+ if (err_no > 0)
+ dict.SetValueAndShowSection("ERROR_MESSAGE", strerror(err_no),
+ "MSG_SECTION");
+
+ string error_text;
+ ctemplate::ExpandTemplate("mytpl", ctemplate::DO_NOT_STRIP, &dict, &error_text);
+ puts(error_text.c_str());
+ }
+ delete tpl;
+}
+
+</pre>
+
+<p>This maybe-show-text functionality is one way the template
+machinery is more powerful than just using <code>printf</code>.
+Another nice property of templates is you can reuse the same variable
+multiple times in your template string. You can also define the
+variable values in any order.</p>
+
+
+<h2> Search Results Page </h2>
+
+<p>Here is an example template that could be used to format a Google
+search results page:</p>
+
+<pre class=example>
+
+{{>HEADER}}
+<body bgcolor=white>
+
+{{>PAGE_HEADING}}{{!The following div must be on the same line}}<div>
+
+{{!The ONE_RESULT section displays a single search item}}
+{{#ONE_RESULT}}
+ {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}}
+ {{#SUBITEM_SECTION}}<blockquote>{{/SUBITEM_SECTION}}
+ {{! LEAD_LINE is received HTML-escaped from the backend.}}
+ <p><a href="{{JUMP_TO_URL:html_escape}}" target=nw>{{LEAD_LINE}}</a><font size=-1>
+
+ {{! SNIPPET1, SNIPPET2 are HTML-escaped in the snippet generator.}}
+ {{#SNIPPET1_SECTION}}
+ <br>{{SNIPPET1}}
+ {{/SNIPPET1_SECTION}}
+
+ {{#SNIPPET2_SECTION}}
+ <br>{{SNIPPET2}}
+ {{/SNIPPET2_SECTION}}
+
+ {{#DESCRIPTION_SECTION}}
+ {{! DESC is received HTML-escaped from the backend.}}
+ <br><span class=f>Description:</span> {{DESC}}
+ {{/DESCRIPTION_SECTION}}
+
+ {{#CATEGORY_SECTION}}
+ <br><span class=f>Category:</span> <a href="{{CAT_URL:html_escape}}" class=f>
+ {{CATEGORY:html_escape}}</a>
+ {{/CATEGORY_SECTION}}
+
+ {{#LASTLINE_SECTION}}
+ <br><font color="{{ALT_TEXT_COLOR:h}}">{{URL:h}}
+ {{#KS_SECTION}}} - {{KSIZE:h}}{{/KS_SECTION}}}
+ {{#CACHE_SECTION}}} - <a href="{{CACHE_URL:h}}" class=f>Cached</A>
+ {{/CACHE_SECTION}}}
+ {{#SIM_SECTION}}} - <a href="{{SIM_PAGES_URL:h}}" class=f>Similar pages</A>
+ {{/SIM_SECTION}}}
+
+ {{#STOCK_SECTION}}
+ - <a href="{{STOCK_URL:h}}" class=f>Stock quotes: {{STOCK_SYMBOL:h}}</a>
+ {{/STOCK_SECTION}}
+ </font>
+ {{/LASTLINE_SECTION}}
+
+ {{#MORE_SECTION}}
+ <br>[ <a href="{{MORE_URL:h}}" class=f>More results from {{MORE_LABEL:h}}</a> ]
+ {{/MORE_SECTION}}
+
+ </font><br>
+ {{! Note: there are two SUBITEM_SECTIONs. They both show or hide together}}
+ {{#SUBITEM_SECTION}}</blockquote>{{/SUBITEM_SECTION}}
+{{/ONE_RESULT}}
+</div> {{! this /div closes the div at the top of this file}}
+{{>PAGE_FOOTING}}
+
+</pre>
+
+<p> Here is a sample procedure that could populate a dictionary for
+expanding that template. The "one procedure" entry point is
+<code>fill_search_results_dictionary</code>. The
+<code>SetTemplateValues</code> function is a separate entry point for
+initializing each top-level template with some standard values.</p>
+
+<pre class=example>
+#include "template.h"
+
+RegisterTemplateFilename(SEARCH_RESULTS_FN, "search_results.tpl");
+#include "search_results.tpl.varnames.h" // defines ksr_HEADER, etc.
+
+using ctemplate::TemplateDictionary;
+using ctemplate::ExpandTemplate;
+using ctemplate::STRIP_WHITESPACE;
+
+// IsEmpty
+// A simple utility function
+static bool IsEmpty(const string &str) {
+ return str.empty();
+}
+
+// SetTemplateValues
+// Use the TemplateDictionary object to set template-wide values that
+// may be used in the top-level template and all its sub-sections
+// and included templates. The template-wide values are all
+// colors from the Palette object
+void SetTemplateValues(TemplateDictionary *dictionary, const Palette* colors) {
+ // better would be to use ksr_LINK_COLOR, etc, assuming those are
+ // defined in search_results.tpl.varnames.h. But using literal
+ // text, as here, is legal as well.
+ dictionary->SetValue("LINK_COLOR", colors->link_color);
+ dictionary->SetValue("BAR_TEXT_COLOR", colors->bar_text_color);
+ dictionary->SetValue("TEXT_COLOR", colors->text_color);
+ dictionary->SetValue("FAINT_COLOR", colors->faint_color);
+ dictionary->SetValue("IMPORTANT_COLOR", colors->important_color);
+ dictionary->SetValue("BAR_COLOR", colors->bar_color);
+ dictionary->SetValue("ALT_TEXT_COLOR", colors->alt_text_color);
+ dictionary->SetValue("ALINK_COLOR", colors->alink_color);
+ dictionary->SetValue("VLINK_COLOR", colors->vlink_color);
+}
+
+// fill_search_results_dictionary
+// Iterates through all the QueryResults contained in the Query object.
+// For each one, it sets corresponding template dictionary values
+// (or hides sections containing their variables, if appropriate) in
+// a sub-dictionary and then adds that dictionary to the parent
+void fill_search_results_dictionary(TemplateDictionary *dictionary,
+ const Query *query) {
+ dictionary->SetFilename(SEARCH_RESULTS_FN);
+
+ // These two functions are defined elsewhere
+ fill_header_dictionary(dictionary->AddIncludeDictionary(ksr_HEADER));
+ fill_page_heading_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_HEADING),
+ query);
+
+ ResultsList *results = query->GetResults();
+ int resCount = 0;
+
+ for (ResultsList::const_iterator iter = results->begin();
+ iter != results->end();
+ ++iter) {
+ QueryResult *qr = (*iter);
+
+ // Create a new sub-dictionary named "Result Dict <n>" for this entry
+
+ ++resCount;
+
+ TemplateDictionary *result_dictionary =
+ dictionary->AddSectionDictionary(ksr_ONE_RESULT);
+
+ result_dictionary->SetValue(ksr_JUMP_TO_URL, qr->GetUrl());
+
+ if (qr->IsSubItem()) {
+ result_dictionary->ShowSection(ksr_SUBITEM_SECTION);
+ }
+
+ result_dictionary->SetValue(ksr_LEAD_LINE, qr->GetLeadLine());
+
+ result_dictionary->SetValueAndShowSection(ksr_SNIPPET1, qr->GetSnippet1(),
+ ksr_SNIPPET1_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_SNIPPET2, qr->GetSnippet2(),
+ ksr_SNIPPET2_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_DESC, qr->GetDescription(),
+ ksr_DESCRIPTION_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_CAT_URL, qr->GetCategoryUrl(),
+ ksr_CATEGORY_SECTION);
+
+ result_dictionary->SetValueAndShowSection("CATEGORY", qr->GetCategoryName(),
+ "CATEGORY_SECTION");
+
+
+ if (IsEmpty(qr->GetDisplayUrl()) &&
+ IsEmpty(qr->GetPageSize()) &&
+ IsEmpty(qr->GetCachedUrl()) &&
+ IsEmpty(qr->GetSimilarPagesUrl()) &&
+ (IsEmpty(qr->GetStockUrl()) ||
+ IsEmpty(qr->GetStockSymbol())) ) {
+ // there is nothing on the last line, so hide it altogether
+ } else {
+ result_dictionary->ShowSection("LASTLINE_SECTION");
+
+ result_dictionary->SetValue(ksr_URL, qr->GetDisplayUrl());
+
+ result_dictionary->SetValueAndShowSection(ksr_KSIZE, qr->GetPageSize(),
+ ksr_KS_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_CACHE_URL, qr->GetCachedUrl(),
+ ksr_CACHE_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_SIM_PAGES_URL,
+ qr->GetSimilarPagesUrl(),
+ ksr_SIM_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_STOCK_URL, qr->GetStockUrl(),
+ ksr_STOCK_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_STOCK_SYMBOL,
+ qr->GetStockSymbol(),
+ ksr_STOCK_SECTION);
+ }
+
+ result_dictionary->SetValueAndShowSection(ksr_MORE_URL, qr->GetMoreUrl(),
+ ksr_MORE_SECTION);
+
+ result_dictionary->SetValueAndShowSection(ksr_MORE_LABEL, qr->GetMoreLabel(),
+ ksr_MORE_SECTION);
+
+ }
+
+ fill_page_footing_dictionary(dictionary->AddIncludeDictionary(ksr_PAGE_FOOTING),
+ query);
+}
+
+void output_page(const Query* query) {
+ TemplateDictionary dict("search-results dict");
+ string output;
+ fill_search_results_dictionary(&dict, query);
+ ctemplate::ExpandTemplate(SEARCH_RESULTS_FN, STRIP_WHITESPACE, &dict, &output);
+ // output now holds the expanded template
+}
+
+</pre>
+
+
+<hr>
+<ul>
+ <li> <A HREF="guide.html">User's Guide</A> </li>
+ <li> <A HREF="reference.html">Reference Manual</A> </li>
+ <li> <A HREF="auto_escape.html">Auto Escape</A> </li>
+ <li> <A HREF="tips.html">Tips</A> </li>
+<!--
+ <li> <A HREF="example.html">Example</A> </li>
+-->
+</ul>
+
+<hr>
+<address>
+Craig Silverstein<br>
+<script type=text/javascript>
+ var lm = new Date(document.lastModified);
+ document.write(lm.toDateString());
+</script>
+</address>
+
+</body>
+</html>