Brian Silverman | 70325d6 | 2015-09-20 17:00:43 -0400 | [diff] [blame] | 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 | // |
| 32 | // This file implements the Template class. For information about |
| 33 | // how to use this class, and to write the templates it takes as input, |
| 34 | // see the doc/ directory. |
| 35 | |
| 36 | #ifndef CTEMPLATE_TEMPLATE_H_ |
| 37 | #define CTEMPLATE_TEMPLATE_H_ |
| 38 | |
| 39 | #include <time.h> // for time_t |
| 40 | #include <string> |
| 41 | #include <ctemplate/template_cache.h> |
| 42 | #include <ctemplate/template_enums.h> |
| 43 | #include <ctemplate/template_string.h> |
| 44 | |
| 45 | // We include this just so folks don't have to include both template.h |
| 46 | // and template_dictionary.h, or template_namelist.h etc, to use the |
| 47 | // template system; we don't actually use anything in these files |
| 48 | // ourselves. |
| 49 | #if 1 |
| 50 | #include <ctemplate/template_dictionary.h> |
| 51 | #include <ctemplate/template_namelist.h> |
| 52 | #include <ctemplate/per_expand_data.h> |
| 53 | #else |
| 54 | namespace ctemplate { |
| 55 | class TemplateDictionaryInterface; |
| 56 | class PerExpandData; |
| 57 | } |
| 58 | #endif |
| 59 | |
| 60 | namespace google_ctemplate_streamhtmlparser { |
| 61 | class HtmlParser; |
| 62 | } |
| 63 | |
| 64 | // NOTE: if you are statically linking the template library into your binary |
| 65 | // (rather than using the template .dll), set '/D CTEMPLATE_DLL_DECL=' |
| 66 | // as a compiler flag in your project file to turn off the dllimports. |
| 67 | #ifndef CTEMPLATE_DLL_DECL |
| 68 | # define CTEMPLATE_DLL_DECL __declspec(dllimport) |
| 69 | #endif |
| 70 | |
| 71 | namespace ctemplate { |
| 72 | |
| 73 | // These free functions form the "simple" template API, and support |
| 74 | // the most common operations (expanding a template from a file, and |
| 75 | // from a string). They all just delegate to a default instance of |
| 76 | // the TemplateCache object. |
| 77 | // |
| 78 | // For more sophisticated use of the template system, you may need |
| 79 | // to create your own TemplateCache object, and work directly with |
| 80 | // it. See template_cache.h for details. |
| 81 | |
| 82 | extern CTEMPLATE_DLL_DECL const TemplateCache* default_template_cache(); |
| 83 | extern CTEMPLATE_DLL_DECL TemplateCache* mutable_default_template_cache(); |
| 84 | |
| 85 | |
| 86 | // ---- EXPANDING A TEMPLATE ------- |
| 87 | // ExpandTemplate |
| 88 | // ExpandWithData |
| 89 | |
| 90 | // Loads the template named filename from disk if necessary -- it |
| 91 | // gets it from the cache instead, if the template had been loaded |
| 92 | // before or if it had been put explicitly in the cache via a call |
| 93 | // to StringToTemplateCache() -- and expands it using the given |
| 94 | // dictionary. |
| 95 | // The first version is the most general, followed by common-case code. |
| 96 | inline bool ExpandTemplate(const TemplateString& filename, Strip strip, |
| 97 | const TemplateDictionaryInterface *dictionary, |
| 98 | ExpandEmitter* output) { |
| 99 | return mutable_default_template_cache()->ExpandWithData( |
| 100 | filename, strip, dictionary, NULL, output); |
| 101 | } |
| 102 | inline bool ExpandTemplate(const TemplateString& filename, Strip strip, |
| 103 | const TemplateDictionaryInterface* dictionary, |
| 104 | std::string* output_buffer) { |
| 105 | return mutable_default_template_cache()->ExpandWithData( |
| 106 | filename, strip, dictionary, NULL, output_buffer); |
| 107 | } |
| 108 | |
| 109 | // If you want any per-expand data to be used at expand time, call |
| 110 | // this routine instead of Expand. You pass in an extra |
| 111 | // PerExpandData structure (see per_expand_data.h) which sets this |
| 112 | // data: whether or not you want the template to be annotated, and |
| 113 | // any data you want to pass in to template modifers. If |
| 114 | // per_expand_data is NULL, this is exactly the same as Expand(). |
| 115 | // The first version is the most general, followed by common-case code. |
| 116 | inline bool ExpandWithData(const TemplateString& filename, Strip strip, |
| 117 | const TemplateDictionaryInterface *dictionary, |
| 118 | PerExpandData* per_expand_data, |
| 119 | ExpandEmitter* output) { |
| 120 | return mutable_default_template_cache()->ExpandWithData( |
| 121 | filename, strip, dictionary, per_expand_data, output); |
| 122 | } |
| 123 | inline bool ExpandWithData(const TemplateString& filename, Strip strip, |
| 124 | const TemplateDictionaryInterface* dictionary, |
| 125 | PerExpandData* per_expand_data, |
| 126 | std::string* output_buffer) { |
| 127 | return mutable_default_template_cache()->ExpandWithData( |
| 128 | filename, strip, dictionary, per_expand_data, output_buffer); |
| 129 | } |
| 130 | |
| 131 | // ---- INSERTING INTO THE CACHE ------- |
| 132 | // LoadTemplate |
| 133 | // StringToTemplateCache |
| 134 | |
| 135 | // Reads a file from disk and inserts it into the template, if it's |
| 136 | // not already there. Returns true on success or false if the |
| 137 | // template could not be found, or could not be parsed. It's never |
| 138 | // necessary to call this -- Expand() will load templates lazily if |
| 139 | // needed -- but you may want to if you want to make sure templates |
| 140 | // exist before trying to expand them, or because you want to |
| 141 | // control disk access patterns, or for some other reason. |
| 142 | inline bool LoadTemplate(const TemplateString& filename, Strip strip) { |
| 143 | return mutable_default_template_cache()->LoadTemplate(filename, strip); |
| 144 | } |
| 145 | |
| 146 | // Inserts the given string into the default template cache, as if |
| 147 | // it were a file read from disk. You can call Expand() with its |
| 148 | // first arg (filename) the same as the key you use here. You can |
| 149 | // also use this key as the 'filename' for sub-included templates, |
| 150 | // in TemplateDictionary::SetFilename(). |
| 151 | inline bool StringToTemplateCache(const TemplateString& key, |
| 152 | const TemplateString& content, |
| 153 | Strip strip) { |
| 154 | return mutable_default_template_cache()->StringToTemplateCache( |
| 155 | key, content, strip); |
| 156 | } |
| 157 | inline bool StringToTemplateCache(const TemplateString& key, |
| 158 | const char* content, size_t content_len, |
| 159 | Strip strip) { |
| 160 | return mutable_default_template_cache()->StringToTemplateCache( |
| 161 | key, content, content_len, strip); |
| 162 | } |
| 163 | |
| 164 | |
| 165 | // --------------------------------------------------------------------- |
| 166 | // The follow are deprecated. |
| 167 | // TODO(csilvers): move to parsed_template.h |
| 168 | |
| 169 | // TemplateState of a template is: |
| 170 | // - TS_EMPTY before parsing is complete, |
| 171 | // - TS_ERROR if a syntax error was found during parsing, and |
| 172 | // - TS_READY if parsing has completed successfully |
| 173 | // (TS_UNUSED is not used) |
| 174 | enum TemplateState { TS_UNUSED, TS_EMPTY, TS_ERROR, TS_READY }; |
| 175 | |
| 176 | // Used for Auto-Escape. It represents the different contexts a template may |
| 177 | // be initialized in via the AUTOESCAPE pragma in the template file |
| 178 | // (or string). It is only public for testing. The contexts are: |
| 179 | // - TC_HTML: The template contains HTML code. Need not be a complete HTML |
| 180 | // page just content the browser interprets in the context of |
| 181 | // HTML parsing. This should be the most common context to use. |
| 182 | // This mode activates our HTML parser. |
| 183 | // - TC_JS: The template contains raw javascript. If your template |
| 184 | // starts with <script> tag, it is of type TC_HTML not TC_JS. |
| 185 | // TC_JS is typically associated with a content-type of |
| 186 | // text/javascript. This mode activates our HTML parser. |
| 187 | // - TC_CSS: The template contains CSS (cascaded style-sheet). If your |
| 188 | // template starts with a <style> tag, it is of type TC_HTML |
| 189 | // not TC_CSS. A TC_CSS template is typically associated with a |
| 190 | // text/css content-type header. Currently treated same as |
| 191 | // TC_HTML but don't rely on that. We may later develop |
| 192 | // CSS-specific sanitizers and parsers. |
| 193 | // - TC_JSON: The template contains raw JSON. Applies javascript_escape |
| 194 | // to variables. Note: javascript_escape is safer than |
| 195 | // json_escape which we may want to remove. |
| 196 | // - TC_XML: The template contains raw XML. Applies xml_escape to variables. |
| 197 | // CAUTION: This mode is not suitable for cases where the |
| 198 | // application data encapsulated in XML requires special |
| 199 | // escaping, such as the case of XHTML. |
| 200 | // TC_XML is typically associated with text/xml content-type. |
| 201 | // - TC_MANUAL: Equivalent to not specifying auto-escaping at all. |
| 202 | // |
| 203 | // TODO(csilvers): Make this a private part of the Template class. |
| 204 | enum TemplateContext { TC_UNUSED, TC_HTML, TC_JS, TC_CSS, TC_JSON, |
| 205 | TC_XML, TC_MANUAL }; |
| 206 | |
| 207 | |
| 208 | // This class is deprecated. Old code uses this class heavily (via |
| 209 | // GetTemplate() to obtain a Template*, and then methods on that |
| 210 | // Template*) but new code should use the free functions above. |
| 211 | class CTEMPLATE_DLL_DECL Template { |
| 212 | public: |
| 213 | // ---- METHODS FOR TOOLS ---- |
| 214 | // These are not intended for normal use, but are public so a |
| 215 | // tool can use them. |
| 216 | |
| 217 | // Used by make_tpl_varnames_h.cc. |
| 218 | void WriteHeaderEntries(std::string *outstring) const; |
| 219 | |
| 220 | // ---- DEPRECATED METHODS ---- |
| 221 | // These methods used to be the primary way of using the Template |
| 222 | // object, but have been deprecated in favor of the (static) |
| 223 | // methods above. If you are using these deprecated methods, |
| 224 | // consider moving to the above methods instead, or to moving to |
| 225 | // using your own TemplateCache (which supports richer operations |
| 226 | // on parsed templates). |
| 227 | |
| 228 | // Loads a template from disk or cache or string, and returns the Template*. |
| 229 | // INSTEAD, use the static Expand that takes a filename. |
| 230 | static Template *GetTemplate(const TemplateString& filename, Strip strip); |
| 231 | virtual ~Template(); // when the time comes to delete these Template*'s. |
| 232 | |
| 233 | // Parses a string immediately and returns the resulting Template*. |
| 234 | // You can call the (deprecated) non-static Expand() method on this |
| 235 | // template in order to expand it with a dictionary. You are |
| 236 | // responsible for deleting the Template* when you are done with it. |
| 237 | // INSTEAD, use StringToTemplateCache (with a key) plus the static Expand(). |
| 238 | // TOOO(csilvers): return a const Template* instead. |
| 239 | static Template* StringToTemplate(const TemplateString& content, |
| 240 | Strip strip); |
| 241 | static Template* StringToTemplate(const char* content, size_t content_len, |
| 242 | Strip strip) { |
| 243 | return StringToTemplate(TemplateString(content, content_len), strip); |
| 244 | } |
| 245 | |
| 246 | // Non-static Expand*() works on a Template* returned from GetTemplate(). |
| 247 | // INSTEAD, use static expand with a filename (or key-name for strings). |
| 248 | bool ExpandWithData(ExpandEmitter* output, |
| 249 | const TemplateDictionaryInterface* dictionary, |
| 250 | PerExpandData* per_expand_data) const { |
| 251 | return ExpandWithDataAndCache(output, dictionary, per_expand_data, |
| 252 | default_template_cache()); |
| 253 | } |
| 254 | bool ExpandWithData(std::string* output_buffer, |
| 255 | const TemplateDictionaryInterface* dictionary, |
| 256 | PerExpandData* per_expand_data) const { |
| 257 | if (output_buffer == NULL) return false; |
| 258 | StringEmitter e(output_buffer); |
| 259 | return ExpandWithData(&e, dictionary, per_expand_data); |
| 260 | } |
| 261 | bool Expand(ExpandEmitter* output, |
| 262 | const TemplateDictionaryInterface* dictionary) const { |
| 263 | return ExpandWithData(output, dictionary, NULL); |
| 264 | } |
| 265 | bool Expand(std::string* output_buffer, |
| 266 | const TemplateDictionaryInterface* dictionary) const { |
| 267 | return ExpandWithData(output_buffer, dictionary, NULL); |
| 268 | } |
| 269 | |
| 270 | // Dump to stdout or a string. filename is just used to annotate output. |
| 271 | void Dump(const char *filename) const; |
| 272 | void DumpToString(const char *filename, std::string *out) const; |
| 273 | |
| 274 | // Retrieves the state, template-file, or strip mode of this Template. |
| 275 | TemplateState state() const; |
| 276 | const char *template_file() const; |
| 277 | const char *original_filename() const; |
| 278 | Strip strip() const; |
| 279 | |
| 280 | // Work at the level of groups of templates, so just call through to |
| 281 | // the default TemplateCache; see template_cache.h for what these do. |
| 282 | // INSTEAD, create your own TemplateCache and call these methods on that. |
| 283 | static bool SetTemplateRootDirectory(const std::string& dir) { |
| 284 | return mutable_default_template_cache()->SetTemplateRootDirectory(dir); |
| 285 | } |
| 286 | static bool AddAlternateTemplateRootDirectory(const std::string& dir) { |
| 287 | return mutable_default_template_cache()->AddAlternateTemplateRootDirectory( |
| 288 | dir); |
| 289 | } |
| 290 | static std::string template_root_directory() { |
| 291 | return default_template_cache()->template_root_directory(); |
| 292 | } |
| 293 | static std::string FindTemplateFilename( |
| 294 | const std::string& unresolved) { |
| 295 | return default_template_cache()->FindTemplateFilename(unresolved); |
| 296 | } |
| 297 | static void RemoveStringFromTemplateCache(const std::string& key) { |
| 298 | mutable_default_template_cache()->Delete(key); |
| 299 | } |
| 300 | static void ClearCache() { |
| 301 | mutable_default_template_cache()->ClearCache(); |
| 302 | } |
| 303 | static void ReloadAllIfChanged() { |
| 304 | mutable_default_template_cache()->ReloadAllIfChanged( |
| 305 | TemplateCache::LAZY_RELOAD); |
| 306 | } |
| 307 | |
| 308 | // ---- EXTRA-DEPRECATED METHODS ---- |
| 309 | // These methods were deprecated even before the move to |
| 310 | // TemplateCache. We'd really like you to move from these to one |
| 311 | // of the "approved" methods, or even one of the deprecated |
| 312 | // methods. Comments here don't even describe what these |
| 313 | // functions do, just how to transition off of using them. |
| 314 | |
| 315 | // INSTEAD, use the StringToTemplateCache function that takes the strip mode. |
| 316 | static bool StringToTemplateCache(const TemplateString& key, |
| 317 | const TemplateString& content); |
| 318 | static bool StringToTemplateCache(const TemplateString& key, |
| 319 | const char* content, size_t content_len) { |
| 320 | return StringToTemplateCache(key, TemplateString(content, content_len)); |
| 321 | } |
| 322 | // This is to prevent against typos: you want the global (free-function) |
| 323 | // StringToTemplateCache here, not the one in Template. |
| 324 | static bool StringToTemplateCache(const TemplateString& key, |
| 325 | const char* content, Strip); |
| 326 | |
| 327 | // INSTEAD, use ReloadAllIfChanged. |
| 328 | bool ReloadIfChanged(); |
| 329 | |
| 330 | protected: |
| 331 | friend class SectionTemplateNode; // for access to set_state(), ParseState |
| 332 | friend class TemplateTemplateNode; // for recursive call to Expand() |
| 333 | |
| 334 | // Template constructor |
| 335 | // Reads the template file and parses it into a parse tree of TemplateNodes |
| 336 | // by calling the method ReloadIfChanged |
| 337 | // The top node is a section node with the arbitrary name "__{{MAIN}}__" |
| 338 | // 'Strip' indicates how to handle whitespace when expanding the |
| 339 | // template. DO_NOT_STRIP keeps the template exactly as-is. |
| 340 | // STRIP_BLANK_LINES elides all blank lines in the template. |
| 341 | // STRIP_WHITESPACE elides all blank lines, and also all whitespace |
| 342 | // at either the beginning or end of a line. It also removes |
| 343 | // any linefeed (possibly following whitespace) that follows a closing |
| 344 | // '}}' of any kind of template marker EXCEPT a template variable. |
| 345 | // This means a linefeed may be removed anywhere by simply placing |
| 346 | // a comment marker as the last element on the line. |
| 347 | // These two options allow the template to include whitespace for |
| 348 | // readability without adding to the expanded output. |
| 349 | Template(const TemplateString& filename, Strip strip, TemplateCache* owner); |
| 350 | |
| 351 | // MaybeInitHtmlParser |
| 352 | // In TemplateContexts where the HTML parser is needed, we |
| 353 | // initialize it in the appropriate mode. Also we do a sanity |
| 354 | // check (cannot fail) on the template filename. This function is |
| 355 | // called at most once for a Template. In_tag is only meaningful |
| 356 | // for TC_HTML: It is true for templates that start inside an HTML |
| 357 | // tag and hence are expected to contain HTML attribute name/value |
| 358 | // pairs only. It is false for standard HTML templates. |
| 359 | void MaybeInitHtmlParser(bool in_tag); |
| 360 | |
| 361 | // BuildTree |
| 362 | // Parses the contents of the file (retrieved via ReloadIfChanged) |
| 363 | // and stores the resulting parse structure in tree_. Returns true |
| 364 | // iff the tree-builder encountered no errors. Note: takes |
| 365 | // ownership of input_buffer, and will delete it. It should have |
| 366 | // been created via new[]. |
| 367 | bool BuildTree(const char *input_buffer, const char* input_buffer_end); |
| 368 | |
| 369 | // Internal version of ReloadIfChanged, used when the function already |
| 370 | // has a write-lock on g_template_mutex. |
| 371 | bool ReloadIfChangedLocked(); |
| 372 | |
| 373 | // set_state |
| 374 | // Sets the state of the template. Used during BuildTree(). |
| 375 | void set_state(TemplateState new_state); |
| 376 | |
| 377 | // StripBuffer |
| 378 | // Modifies buffer in-place based on the strip_ mode, to remove |
| 379 | // extra whitespace. May delete[] the input buffer and replace |
| 380 | // it with a new buffer. Used by ReloadIfChanged(). |
| 381 | void StripBuffer(char **buffer, size_t* len); |
| 382 | |
| 383 | // The file we originally got from the Template() constructor |
| 384 | const std::string original_filename_; |
| 385 | // The pathname as fully resolved on the filesystem |
| 386 | std::string resolved_filename_; |
| 387 | time_t filename_mtime_; // lastmod time for filename last time we loaded it |
| 388 | |
| 389 | // What to do with whitespace at template-expand time |
| 390 | Strip strip_; |
| 391 | |
| 392 | // Keeps track of where we are in reloading, or if there was an error loading |
| 393 | TemplateState state_; |
| 394 | |
| 395 | // The cache we got this template from. This is not well-defined: a |
| 396 | // Template can be in more than one cache. |
| 397 | // TODO(csilvers): remove this once we deprecate the one user, which |
| 398 | // is ReloadIfChanged. |
| 399 | TemplateCache* template_cache_; |
| 400 | |
| 401 | // The current template-contents, as read from the file |
| 402 | const char* template_text_; |
| 403 | int template_text_len_; |
| 404 | |
| 405 | // The current parsed template structure. Has pointers into template_text_. |
| 406 | class SectionTemplateNode *tree_; // defined in template.cc |
| 407 | |
| 408 | // Template markers have the form {{VARIABLE}}, etc. These constants |
| 409 | // define the {{ and }} that delimit template markers. |
| 410 | struct CTEMPLATE_DLL_DECL MarkerDelimiters { |
| 411 | const char* start_marker; |
| 412 | size_t start_marker_len; |
| 413 | const char* end_marker; |
| 414 | size_t end_marker_len; |
| 415 | |
| 416 | MarkerDelimiters() { |
| 417 | start_marker = "{{"; // The default start-marker |
| 418 | start_marker_len = strlen(start_marker); |
| 419 | end_marker = "}}"; |
| 420 | end_marker_len = strlen(end_marker); |
| 421 | } |
| 422 | }; |
| 423 | |
| 424 | // The current parsing state. Used in BuildTree() and subroutines |
| 425 | struct CTEMPLATE_DLL_DECL ParseState { |
| 426 | const char* bufstart; |
| 427 | const char* bufend; |
| 428 | enum { PS_UNUSED, GETTING_TEXT, GETTING_NAME } phase; |
| 429 | MarkerDelimiters current_delimiters; |
| 430 | ParseState() |
| 431 | : bufstart(NULL), bufend(NULL), phase(PS_UNUSED), current_delimiters() |
| 432 | {} |
| 433 | }; |
| 434 | ParseState parse_state_; |
| 435 | |
| 436 | // All templates are initialized to TC_MANUAL (no Auto-Escape). Then, |
| 437 | // during template parsing (BuildTree()), if an AUTOESCAPE pragma is |
| 438 | // encountered, the context changes appropriately. |
| 439 | TemplateContext initial_context_; |
| 440 | // Non-null if the template was initialized in an Auto-Escape mode that |
| 441 | // requires a parser (currently TC_HTML, TC_CSS and TC_JS). |
| 442 | google_ctemplate_streamhtmlparser::HtmlParser *htmlparser_; |
| 443 | |
| 444 | // A sorted list of trusted variable names, declared here because a unittest |
| 445 | // needs to verify that it is appropriately sorted (an unsorted array would |
| 446 | // lead to the binary search of this array failing). |
| 447 | static const char * const kSafeWhitelistedVariables[]; |
| 448 | static const size_t kNumSafeWhitelistedVariables; |
| 449 | |
| 450 | private: |
| 451 | friend class TemplateCache; |
| 452 | friend class TemplateCachePeer; // to access num_deletes_ |
| 453 | |
| 454 | // Internal implementation of Expand |
| 455 | bool ExpandWithDataAndCache(ExpandEmitter* output, |
| 456 | const TemplateDictionaryInterface *dictionary, |
| 457 | PerExpandData* per_expand_data, |
| 458 | const TemplateCache* cache) const; |
| 459 | |
| 460 | // This is called for recursive expands, when we already hold template_lock. |
| 461 | bool ExpandLocked(ExpandEmitter* output, |
| 462 | const TemplateDictionaryInterface *dictionary, |
| 463 | PerExpandData* per_expand_data, |
| 464 | const TemplateCache* cache) const; |
| 465 | |
| 466 | // Returns the lastmod time in mtime_ |
| 467 | // For string-based templates, not backed by a file, this returns 0 |
| 468 | time_t mtime() const; |
| 469 | |
| 470 | // These are helper routines to StripFile. I would make them static |
| 471 | // inside template.cc, but they use the MarerDelimiters struct. |
| 472 | static bool ParseDelimiters(const char* text, size_t textlen, |
| 473 | MarkerDelimiters* delim); |
| 474 | static bool IsBlankOrOnlyHasOneRemovableMarker(const char** line, size_t* len, |
| 475 | const MarkerDelimiters& delim); |
| 476 | static size_t InsertLine(const char *line, size_t len, Strip strip, |
| 477 | const MarkerDelimiters& delim, char* buffer); |
| 478 | |
| 479 | // This is only used by template_cache_test, via TemplateCachePeer. |
| 480 | static int num_deletes() { return num_deletes_; } |
| 481 | |
| 482 | static int num_deletes_; // how many times the destructor has been called |
| 483 | |
| 484 | // Can't invoke copy constructor or assignment operator |
| 485 | Template(const Template&); |
| 486 | void operator=(const Template &); |
| 487 | }; |
| 488 | |
| 489 | } |
| 490 | |
| 491 | |
| 492 | #endif // CTEMPLATE_TEMPLATE_H_ |