1
// Copyright (c) 2006, Google Inc.
2
// All rights reserved.
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are
8
// * Redistributions of source code must retain the above copyright
9
// notice, this list of conditions and the following disclaimer.
10
// * Redistributions in binary form must reproduce the above
11
// copyright notice, this list of conditions and the following disclaimer
12
// in the documentation and/or other materials provided with the
14
// * Neither the name of Google Inc. nor the names of its
15
// contributors may be used to endorse or promote products derived from
16
// this software without specific prior written permission.
18
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
// Author: Craig Silverstein
33
// Based on the 'old' TemplateDictionary by Frank Jernigan.
35
// A template dictionary maps names (as found in template files)
36
// to their values. There are three types of names:
37
// variables: value is a string.
38
// sections: value is a list of sub-dicts to use when expanding the section;
39
// the section is expanded once per sub-dict.
40
// template-include: value is a list of pairs: name of the template file
41
// to include, and the sub-dict to use when expanding it.
42
// TemplateDictionary has routines for setting these values.
44
// For (many) more details, see the doc/ directory.
47
#ifndef TEMPLATE_TEMPLATE_DICTIONARY_H_
48
#define TEMPLATE_TEMPLATE_DICTIONARY_H_
50
#include <stdlib.h> // for NULL
51
#include <stdarg.h> // for StringAppendV()
52
#include <sys/types.h> // for size_t
53
#include <functional> // for less<>
57
#include <ctemplate/template_dictionary_interface.h>
58
#include <ctemplate/template_string.h>
59
#include <ctemplate/template_modifiers.h>
61
// NOTE: if you are statically linking the template library into your binary
62
// (rather than using the template .dll), set '/D CTEMPLATE_DLL_DECL='
63
// as a compiler flag in your project file to turn off the dllimports.
64
#ifndef CTEMPLATE_DLL_DECL
65
# define CTEMPLATE_DLL_DECL __declspec(dllimport)
71
template<typename A, int B, typename C, typename D> class small_map;
72
template<typename NormalMap> class small_map_default_init; // in small_map.h
74
template <class T> class ArenaAllocator {
77
typedef size_t size_type;
78
typedef ptrdiff_t difference_type;
81
typedef const T* const_pointer;
83
typedef const T& const_reference;
84
pointer address(reference r) const { return &r; }
85
const_pointer address(const_reference r) const { return &r; }
86
size_type max_size() const { return size_t(-1) / sizeof(T); }
88
// DO NOT USE! The default constructor is for gcc3 compatibility only.
89
ArenaAllocator() : arena_(0) { }
90
ArenaAllocator(UnsafeArena* arena) : arena_(arena) { }
93
pointer allocate(size_type n, std::allocator<void>::const_pointer /*hint*/ = 0);
94
void deallocate(pointer p, size_type n);
95
void construct(pointer p, const T & val) {
96
new(reinterpret_cast<void*>(p)) T(val);
98
void destroy(pointer p) { p->~T(); }
100
UnsafeArena* arena(void) const { return arena_; }
102
template<class U> struct rebind {
103
typedef ArenaAllocator<U> other;
106
template<class U> ArenaAllocator(const ArenaAllocator<U>& other)
107
: arena_(other.arena()) { }
109
template<class U> bool operator==(const ArenaAllocator<U>& other) const {
110
return arena_ == other.arena();
113
template<class U> bool operator!=(const ArenaAllocator<U>& other) const {
114
return arena_ != other.arena();
118
static const int kAlignment;
122
class CTEMPLATE_DLL_DECL TemplateDictionary : public TemplateDictionaryInterface {
124
// name is used only for debugging.
125
// arena is used to store all names and values. It can be NULL (the
126
// default), in which case we create own own arena.
127
explicit TemplateDictionary(const TemplateString& name,
128
UnsafeArena* arena=NULL);
129
~TemplateDictionary();
131
// If you want to be explicit, you can use NO_ARENA as a synonym to NULL.
132
static UnsafeArena* const NO_ARENA;
134
std::string name() const { return std::string(name_.ptr_, name_.length_); }
136
// Returns a recursive copy of this dictionary. This dictionary
137
// *must* be a "top-level" dictionary (that is, not created via
138
// AddSectionDictionary() or AddIncludeDictionary()). Caller owns
139
// the resulting dict, and must delete it. If arena is NULL, we
140
// create our own. Returns NULL if the copy fails (probably because
141
// the "top-level" rule was violated).
142
TemplateDictionary* MakeCopy(const TemplateString& name_of_copy,
143
UnsafeArena* arena=NULL);
145
// --- Routines for VARIABLES
146
// These are the five main routines used to set the value of a variable.
147
// As always, wherever you see TemplateString, you can also pass in
148
// either a char* or a C++ string, or a TemplateString(s, slen).
150
void SetValue(const TemplateString variable, const TemplateString value);
151
void SetIntValue(const TemplateString variable, long value);
152
void SetFormattedValue(const TemplateString variable, const char* format, ...)
154
__attribute__((__format__ (__printf__, 3, 4)))
156
; // starts at 3 because of implicit 1st arg 'this'
158
// We also let you set values in the 'global' dictionary which is
159
// referenced when all other dictionaries fail. Note this is a
160
// static method: no TemplateDictionary instance needed. Since
161
// this routine is rarely used, we don't provide variants.
162
static void SetGlobalValue(const TemplateString variable,
163
const TemplateString value);
165
// This is used for a value that you want to be 'global', but only
166
// in the scope of a given template, including all its sections and
167
// all its sub-included dictionaries. The main difference between
168
// SetTemplateGlobalValue() and SetValue(), is that
169
// SetTemplateGlobalValue() values persist across template-includes.
170
// This is intended for session-global data; since that should be
171
// fairly rare, we don't provide variants.
172
void SetTemplateGlobalValue(const TemplateString variable,
173
const TemplateString value);
175
// Similar SetTemplateGlobalValue above, this method shows a section in this
176
// template, all its sections, and all its template-includes. This is intended
177
// for session-global data, for example allowing you to show variant portions
178
// of your template for certain browsers/languages without having to call
179
// ShowSection on each template you use.
180
void ShowTemplateGlobalSection(const TemplateString variable);
182
// These routines are like SetValue and SetTemplateGlobalValue, but
183
// they do not make a copy of the input data. THE CALLER IS
184
// RESPONSIBLE FOR ENSURING THE PASSED-IN STRINGS LIVE FOR AT LEAST
185
// AS LONG AS THIS DICTIONARY! In general, they yield a quite minor
186
// performance increase for significant increased code fragility,
187
// so do not use them unless you really need the speed improvements.
188
void SetValueWithoutCopy(const TemplateString variable,
189
const TemplateString value);
190
void SetTemplateGlobalValueWithoutCopy(const TemplateString variable,
191
const TemplateString value);
194
// --- Routines for SECTIONS
195
// We show a section once per dictionary that is added with its name.
196
// Recall that lookups are hierarchical: if a section tried to look
197
// up a variable in its sub-dictionary and fails, it will look next
198
// in its parent dictionary (us). So it's perfectly appropriate to
199
// keep the sub-dictionary empty: that will show the section once,
200
// and take all var definitions from us. ShowSection() is a
201
// convenience routine that does exactly that.
203
// Creates an empty dictionary whose parent is us, and returns it.
204
// As always, wherever you see TemplateString, you can also pass in
205
// either a char* or a C++ string, or a TemplateString(s, slen).
206
TemplateDictionary* AddSectionDictionary(const TemplateString section_name);
207
void ShowSection(const TemplateString section_name);
209
// A convenience method. Often a single variable is surrounded by
210
// some HTML that should not be printed if the variable has no
211
// value. The way to do this is to put that html in a section.
212
// This method makes it so the section is shown exactly once, with a
213
// dictionary that maps the variable to the proper value. If the
214
// value is "", on the other hand, this method does nothing, so the
215
// section remains hidden.
216
void SetValueAndShowSection(const TemplateString variable,
217
const TemplateString value,
218
const TemplateString section_name);
221
// --- Routines for TEMPLATE-INCLUDES
222
// Included templates are treated like sections, but they require
223
// the name of the include-file to go along with each dictionary.
225
TemplateDictionary* AddIncludeDictionary(const TemplateString variable);
227
// This is required for include-templates; it specifies what template
228
// to include. But feel free to call this on any dictionary, to
229
// document what template-file the dictionary is intended to go with.
230
void SetFilename(const TemplateString filename);
232
// --- DEBUGGING TOOLS
234
// Logs the contents of a dictionary and its sub-dictionaries.
235
// Dump goes to stdout/stderr, while DumpToString goes to the given string.
236
// 'indent' is how much to indent each line of the output.
237
void Dump(int indent=0) const;
238
void DumpToString(std::string* out, int indent=0) const;
240
// --- DEPRECATED ESCAPING FUNCTIONALITY
242
// Escaping in the binary has been deprecated in favor of using modifiers
243
// to do the escaping in the template:
244
// "...{{MYVAR:html_escape}}..."
245
void SetEscapedValue(const TemplateString variable, const TemplateString value,
246
const TemplateModifier& escfn);
247
void SetEscapedFormattedValue(const TemplateString variable,
248
const TemplateModifier& escfn,
249
const char* format, ...)
251
__attribute__((__format__ (__printf__, 4, 5)))
253
; // starts at 4 because of implicit 1st arg 'this'
254
void SetEscapedValueAndShowSection(const TemplateString variable,
255
const TemplateString value,
256
const TemplateModifier& escfn,
257
const TemplateString section_name);
260
friend class SectionTemplateNode; // for access to GetSectionValue(), etc.
261
friend class TemplateTemplateNode; // for access to GetSectionValue(), etc.
262
friend class VariableTemplateNode; // for access to GetSectionValue(), etc.
263
// For unittesting code using a TemplateDictionary.
264
friend class TemplateDictionaryPeer;
266
class DictionaryPrinter;
268
// We need this functor to tell small_map how to create a map<> when
269
// it decides to do so: we want it to create that map on the arena.
270
class map_arena_init;
272
typedef std::vector<TemplateDictionary*,
273
ArenaAllocator<TemplateDictionary*> >
275
// The '4' here is the size where small_map switches from vector<> to map<>.
276
typedef small_map<std::map<TemplateId, TemplateString, std::less<TemplateId>,
277
ArenaAllocator<std::pair<const TemplateId, TemplateString> > >,
278
4, std::equal_to<TemplateId>, map_arena_init>
280
typedef small_map<std::map<TemplateId, DictVector*, std::less<TemplateId>,
281
ArenaAllocator<std::pair<const TemplateId, DictVector*> > >,
282
4, std::equal_to<TemplateId>, map_arena_init>
284
typedef small_map<std::map<TemplateId, DictVector*, std::less<TemplateId>,
285
ArenaAllocator<std::pair<const TemplateId, DictVector*> > >,
286
4, std::equal_to<TemplateId>, map_arena_init>
288
// This is used only for global_dict_, which is just like a VariableDict
289
// but does not bother with an arena (since this memory lives forever).
290
typedef small_map< std::map<TemplateId, TemplateString, std::less<TemplateId> >,
291
4, std::equal_to<TemplateId>,
292
small_map_default_init<
293
std::map<TemplateId, TemplateString,
294
std::less<TemplateId> > > >
297
// These are helper functions to allocate the parts of the dictionary
299
template<typename T> inline void LazilyCreateDict(T** dict);
300
inline void LazyCreateTemplateGlobalDict();
301
inline DictVector* CreateDictVector();
302
inline TemplateDictionary* CreateTemplateSubdict(
303
const TemplateString& name,
305
TemplateDictionary* parent_dict,
306
TemplateDictionary* template_global_dict_owner);
308
// This is a helper function to insert <key,value> into m.
309
// Normally, we'd just use m[key] = value, but map rules
310
// require default constructor to be public for that to compile, and
311
// for some types we'd rather not allow that. HashInsert also inserts
312
// the key into an id(key)->key map, to allow for id-lookups later.
313
template<typename MapType, typename ValueType>
314
static void HashInsert(MapType* m, TemplateString key, ValueType value);
316
// Constructor created for all children dictionaries. This includes
317
// both a pointer to the parent dictionary and also the the
318
// template-global dictionary from which all children (both
319
// IncludeDictionary and SectionDictionary) inherit. Values are
320
// filled into global_template_dict via SetTemplateGlobalValue.
321
explicit TemplateDictionary(const TemplateString& name,
322
class UnsafeArena* arena,
323
TemplateDictionary* parent_dict,
324
TemplateDictionary* template_global_dict_owner);
326
// Helps set up the static stuff. Must be called exactly once before
327
// accessing global_dict_. GoogleOnceInit() is used to manage that
328
// initialization in a thread-safe way.
329
static void SetupGlobalDict();
331
// Utility functions for copying a string into the arena.
332
// Memdup also copies in a trailing NUL, which is why we have the
333
// trailing-NUL check in the TemplateString version of Memdup.
334
TemplateString Memdup(const char* s, size_t slen);
335
TemplateString Memdup(const TemplateString& s) {
336
if (s.is_immutable() && s.ptr_[s.length_] == '\0') {
339
return Memdup(s.ptr_, s.length_);
342
// Used for recursive MakeCopy calls.
343
TemplateDictionary* InternalMakeCopy(
344
const TemplateString& name_of_copy,
346
TemplateDictionary* parent_dict,
347
TemplateDictionary* template_global_dict_owner);
349
// Must be called whenever we add a value to one of the dictionaries above,
350
// to ensure that we can reconstruct the id -> string mapping.
351
static void AddToIdToNameMap(TemplateId id, const TemplateString& str);
353
// Used to do the formatting for the SetFormatted*() functions
354
static int StringAppendV(char* space, char** out,
355
const char* format, va_list ap);
357
// How Template::Expand() and its children access the template-dictionary.
358
// These fill the API required by TemplateDictionaryInterface.
359
// TODO(csilvers): have GetSectionValue return a TemplateString.
360
virtual const char *GetSectionValue(const TemplateString& variable) const;
361
virtual bool IsHiddenSection(const TemplateString& name) const;
362
virtual bool IsUnhiddenSection(const TemplateString& name) const {
363
return !IsHiddenSection(name);
365
virtual bool IsHiddenTemplate(const TemplateString& name) const;
366
virtual const char *GetIncludeTemplateName(const TemplateString& variable,
369
// Determine whether there's anything set in this dictionary
372
// This is needed by DictionaryPrinter because it's not a friend
373
// of TemplateString, but we are
374
static std::string PrintableTemplateString(const TemplateString& ts) {
375
return std::string(ts.ptr_, ts.length_);
377
static bool InvalidTemplateString(const TemplateString& ts) {
378
return ts.ptr_ == NULL;
381
// CreateTemplateIterator
382
// This is SectionIterator exactly, just with a different name to
383
// self-document the fact the value applies to a template include.
384
// Caller frees return value.
385
virtual TemplateDictionaryInterface::Iterator* CreateTemplateIterator(
386
const TemplateString& section_name) const;
388
// CreateSectionIterator
389
// Factory method implementation that constructs a iterator representing the
390
// set of dictionaries associated with a section name, if any. This
391
// implementation checks the local dictionary itself, not the template-wide
392
// dictionary or the global dictionary.
393
// Caller frees return value.
394
virtual TemplateDictionaryInterface::Iterator* CreateSectionIterator(
395
const TemplateString& section_name) const;
397
// TemplateDictionary-specific implementation of dictionary iterators.
398
template <typename T> // T is TemplateDictionary::const_iterator
399
class Iterator : public TemplateDictionaryInterface::Iterator {
401
friend class TemplateDictionary;
402
Iterator(T begin, T end) : begin_(begin), end_(end) { }
404
virtual ~Iterator() { }
405
virtual bool HasNext() const;
406
virtual const TemplateDictionaryInterface& Next();
412
// A small helper factory function for Iterator
413
template <typename T>
414
static Iterator<typename T::const_iterator>* MakeIterator(const T& dv) {
415
return new Iterator<typename T::const_iterator>(dv.begin(), dv.end());
419
// The "name" of the dictionary for debugging output (Dump, etc.)
420
// The arena, also set at construction time.
421
class UnsafeArena* const arena_;
422
bool should_delete_arena_; // only true if we 'new arena' in constructor
423
TemplateString name_; // points into the arena, or to static memory
425
// The three dictionaries that I own -- for vars, sections, and template-incs
426
VariableDict* variable_dict_;
427
SectionDict* section_dict_;
428
IncludeDict* include_dict_;
430
// The template_global_dict is consulted if a lookup in the variable, section,
431
// or include dicts named above fails. It forms a convenient place to store
432
// session-specific data that's applicable to all templates in the dictionary
434
// For the parent-template, template_global_dict_ is not NULL, and
435
// template_global_dict_owner_ is this. For all of its children,
436
// template_global_dict_ is NULL, and template_global_dict_owner_ points to
437
// the root parent-template (the one with the non-NULL template_global_dict_).
438
TemplateDictionary* template_global_dict_;
439
TemplateDictionary* template_global_dict_owner_;
441
// My parent dictionary, used when variable lookups at this level fail.
442
// Note this is only for *variables*, not sections or templates.
443
TemplateDictionary* parent_dict_;
444
// The static, global dictionary, at the top of the parent-dictionary chain
445
static GlobalDict* global_dict_;
447
// The filename associated with this dictionary. If set, this declares
448
// what template the dictionary is supposed to be expanded with. Required
449
// for template-includes, optional (but useful) for 'normal' dicts.
450
const char* filename_;
453
// Used by our nested class (friendship rules require us to forward this).
454
static TemplateString IdToString(TemplateId id) {
455
return TemplateString::IdToString(id);
458
// Can't invoke copy constructor or assignment operator
459
TemplateDictionary(const TemplateDictionary&);
460
void operator=(const TemplateDictionary&);
465
#endif // TEMPLATE_TEMPLATE_DICTIONARY_H_