~ubuntu-branches/ubuntu/oneiric/ctemplate/oneiric

« back to all changes in this revision

Viewing changes to src/windows/ctemplate/template_dictionary.h

  • Committer: Bazaar Package Importer
  • Author(s): Florian Reinhard
  • Date: 2010-01-14 22:31:32 UTC
  • Revision ID: james.westby@ubuntu.com-20100114223132-w9ritwjg2av4rfb3
Tags: upstream-0.96
ImportĀ upstreamĀ versionĀ 0.96

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) 2006, Google Inc.
 
2
// All rights reserved.
 
3
//
 
4
// Redistribution and use in source and binary forms, with or without
 
5
// modification, are permitted provided that the following conditions are
 
6
// met:
 
7
//
 
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
 
13
// distribution.
 
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.
 
17
//
 
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.
 
29
 
 
30
// ---
 
31
// Author: Craig Silverstein
 
32
//
 
33
// Based on the 'old' TemplateDictionary by Frank Jernigan.
 
34
//
 
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.
 
43
//
 
44
// For (many) more details, see the doc/ directory.
 
45
 
 
46
 
 
47
#ifndef TEMPLATE_TEMPLATE_DICTIONARY_H_
 
48
#define TEMPLATE_TEMPLATE_DICTIONARY_H_
 
49
 
 
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<>
 
54
#include <map>
 
55
#include <string>
 
56
#include <vector>
 
57
#include <ctemplate/template_dictionary_interface.h>
 
58
#include <ctemplate/template_string.h>
 
59
#include <ctemplate/template_modifiers.h>
 
60
 
 
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)
 
66
#endif
 
67
 
 
68
namespace ctemplate {
 
69
 
 
70
class UnsafeArena;
 
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
 
73
 
 
74
template <class T> class ArenaAllocator {
 
75
 public:
 
76
  typedef T value_type;
 
77
  typedef size_t size_type;
 
78
  typedef ptrdiff_t difference_type;
 
79
 
 
80
  typedef T* pointer;
 
81
  typedef const T* const_pointer;
 
82
  typedef T& reference;
 
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); }
 
87
 
 
88
  // DO NOT USE! The default constructor is for gcc3 compatibility only.
 
89
  ArenaAllocator() : arena_(0) { }
 
90
  ArenaAllocator(UnsafeArena* arena) : arena_(arena) { }
 
91
  ~ArenaAllocator() { }
 
92
 
 
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);
 
97
  }
 
98
  void destroy(pointer p) { p->~T(); }
 
99
 
 
100
  UnsafeArena* arena(void) const { return arena_; }
 
101
 
 
102
  template<class U> struct rebind {
 
103
    typedef ArenaAllocator<U> other;
 
104
  };
 
105
 
 
106
  template<class U> ArenaAllocator(const ArenaAllocator<U>& other)
 
107
    : arena_(other.arena()) { }
 
108
 
 
109
  template<class U> bool operator==(const ArenaAllocator<U>& other) const {
 
110
    return arena_ == other.arena();
 
111
  }
 
112
 
 
113
  template<class U> bool operator!=(const ArenaAllocator<U>& other) const {
 
114
    return arena_ != other.arena();
 
115
  }
 
116
 
 
117
 protected:
 
118
  static const int kAlignment;
 
119
  UnsafeArena* arena_;
 
120
};
 
121
 
 
122
class CTEMPLATE_DLL_DECL TemplateDictionary : public TemplateDictionaryInterface {
 
123
 public:
 
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();
 
130
 
 
131
  // If you want to be explicit, you can use NO_ARENA as a synonym to NULL.
 
132
  static UnsafeArena* const NO_ARENA;
 
133
 
 
134
  std::string name() const { return std::string(name_.ptr_, name_.length_); }
 
135
 
 
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);
 
144
 
 
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).
 
149
 
 
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, ...)
 
153
#if 0
 
154
       __attribute__((__format__ (__printf__, 3, 4)))
 
155
#endif
 
156
      ;  // starts at 3 because of implicit 1st arg 'this'
 
157
 
 
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);
 
164
 
 
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);
 
174
 
 
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);
 
181
 
 
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);
 
192
 
 
193
 
 
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.
 
202
 
 
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);
 
208
 
 
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);
 
219
 
 
220
 
 
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.
 
224
 
 
225
  TemplateDictionary* AddIncludeDictionary(const TemplateString variable);
 
226
 
 
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);
 
231
 
 
232
  // --- DEBUGGING TOOLS
 
233
 
 
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;
 
239
 
 
240
  // --- DEPRECATED ESCAPING FUNCTIONALITY
 
241
 
 
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, ...)
 
250
#if 0
 
251
       __attribute__((__format__ (__printf__, 4, 5)))
 
252
#endif
 
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);
 
258
 
 
259
 private:
 
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;
 
265
 
 
266
  class DictionaryPrinter;
 
267
 
 
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;
 
271
 
 
272
  typedef std::vector<TemplateDictionary*,
 
273
                      ArenaAllocator<TemplateDictionary*> >
 
274
      DictVector;
 
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>
 
279
      VariableDict;
 
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>
 
283
      SectionDict;
 
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>
 
287
      IncludeDict;
 
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> > > >
 
295
      GlobalDict;
 
296
 
 
297
  // These are helper functions to allocate the parts of the dictionary
 
298
  // on the arena.
 
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,
 
304
      UnsafeArena* arena,
 
305
      TemplateDictionary* parent_dict,
 
306
      TemplateDictionary* template_global_dict_owner);
 
307
 
 
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);
 
315
 
 
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);
 
325
 
 
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();
 
330
 
 
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') {
 
337
      return s;
 
338
    }
 
339
    return Memdup(s.ptr_, s.length_);
 
340
  }
 
341
 
 
342
  // Used for recursive MakeCopy calls.
 
343
  TemplateDictionary* InternalMakeCopy(
 
344
      const TemplateString& name_of_copy,
 
345
      UnsafeArena* arena,
 
346
      TemplateDictionary* parent_dict,
 
347
      TemplateDictionary* template_global_dict_owner);
 
348
 
 
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);
 
352
 
 
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);
 
356
 
 
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);
 
364
  }
 
365
  virtual bool IsHiddenTemplate(const TemplateString& name) const;
 
366
  virtual const char *GetIncludeTemplateName(const TemplateString& variable,
 
367
                                             int dictnum) const;
 
368
 
 
369
  // Determine whether there's anything set in this dictionary
 
370
  bool Empty() const;
 
371
 
 
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_);
 
376
  }
 
377
  static bool InvalidTemplateString(const TemplateString& ts) {
 
378
    return ts.ptr_ == NULL;
 
379
  }
 
380
 
 
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;
 
387
 
 
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;
 
396
 
 
397
  // TemplateDictionary-specific implementation of dictionary iterators.
 
398
  template <typename T>   // T is TemplateDictionary::const_iterator
 
399
  class Iterator : public TemplateDictionaryInterface::Iterator {
 
400
   protected:
 
401
    friend class TemplateDictionary;
 
402
    Iterator(T begin, T end) : begin_(begin), end_(end) { }
 
403
   public:
 
404
    virtual ~Iterator() { }
 
405
    virtual bool HasNext() const;
 
406
    virtual const TemplateDictionaryInterface& Next();
 
407
   private:
 
408
    T begin_;
 
409
    const T end_;
 
410
  };
 
411
 
 
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());
 
416
  }
 
417
 
 
418
 
 
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
 
424
 
 
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_;
 
429
 
 
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
 
433
  // tree.
 
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_;
 
440
 
 
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_;
 
446
 
 
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_;
 
451
 
 
452
 private:
 
453
  // Used by our nested class (friendship rules require us to forward this).
 
454
  static TemplateString IdToString(TemplateId id) {
 
455
    return TemplateString::IdToString(id);
 
456
  }
 
457
 
 
458
  // Can't invoke copy constructor or assignment operator
 
459
  TemplateDictionary(const TemplateDictionary&);
 
460
  void operator=(const TemplateDictionary&);
 
461
};
 
462
 
 
463
}
 
464
 
 
465
#endif  // TEMPLATE_TEMPLATE_DICTIONARY_H_