URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [text/] [template/] [template.go] - Rev 747
Compare with Previous | Blame | View Log
// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package templateimport ("fmt""reflect""text/template/parse")// common holds the information shared by related templates.type common struct {tmpl map[string]*Template// We use two maps, one for parsing and one for execution.// This separation makes the API cleaner since it doesn't// expose reflection to the client.parseFuncs FuncMapexecFuncs map[string]reflect.Value}// Template is the representation of a parsed template. The *parse.Tree// field is exported only for use by html/template and should be treated// as unexported by all other clients.type Template struct {name string*parse.Tree*commonleftDelim stringrightDelim string}// New allocates a new template with the given name.func New(name string) *Template {return &Template{name: name,}}// Name returns the name of the template.func (t *Template) Name() string {return t.name}// New allocates a new template associated with the given one and with the same// delimiters. The association, which is transitive, allows one template to// invoke another with a {{template}} action.func (t *Template) New(name string) *Template {t.init()return &Template{name: name,common: t.common,leftDelim: t.leftDelim,rightDelim: t.rightDelim,}}func (t *Template) init() {if t.common == nil {t.common = new(common)t.tmpl = make(map[string]*Template)t.parseFuncs = make(FuncMap)t.execFuncs = make(map[string]reflect.Value)}}// Clone returns a duplicate of the template, including all associated// templates. The actual representation is not copied, but the name space of// associated templates is, so further calls to Parse in the copy will add// templates to the copy but not to the original. Clone can be used to prepare// common templates and use them with variant definitions for other templates by// adding the variants after the clone is made.func (t *Template) Clone() *Template {nt := t.copy(nil)nt.init()nt.tmpl[t.name] = ntfor k, v := range t.tmpl {if k == t.name { // Already installed.continue}// The associated templates share nt's common structure.tmpl := v.copy(nt.common)nt.tmpl[k] = tmpl}for k, v := range t.parseFuncs {nt.parseFuncs[k] = v}for k, v := range t.execFuncs {nt.execFuncs[k] = v}return nt}// copy returns a shallow copy of t, with common set to the argument.func (t *Template) copy(c *common) *Template {nt := New(t.name)nt.Tree = t.Treent.common = cnt.leftDelim = t.leftDelimnt.rightDelim = t.rightDelimreturn nt}// AddParseTree creates a new template with the name and parse tree// and associates it with t.func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {if t.tmpl[name] != nil {return nil, fmt.Errorf("template: redefinition of template %q", name)}nt := t.New(name)nt.Tree = treet.tmpl[name] = ntreturn nt, nil}// Templates returns a slice of the templates associated with t, including t// itself.func (t *Template) Templates() []*Template {// Return a slice so we don't expose the map.m := make([]*Template, 0, len(t.tmpl))for _, v := range t.tmpl {m = append(m, v)}return m}// Delims sets the action delimiters to the specified strings, to be used in// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template// definitions will inherit the settings. An empty delimiter stands for the// corresponding default: {{ or }}.// The return value is the template, so calls can be chained.func (t *Template) Delims(left, right string) *Template {t.leftDelim = leftt.rightDelim = rightreturn t}// Funcs adds the elements of the argument map to the template's function map.// It panics if a value in the map is not a function with appropriate return// type. However, it is legal to overwrite elements of the map. The return// value is the template, so calls can be chained.func (t *Template) Funcs(funcMap FuncMap) *Template {t.init()addValueFuncs(t.execFuncs, funcMap)addFuncs(t.parseFuncs, funcMap)return t}// Lookup returns the template with the given name that is associated with t,// or nil if there is no such template.func (t *Template) Lookup(name string) *Template {if t.common == nil {return nil}return t.tmpl[name]}// Parse parses a string into a template. Nested template definitions will be// associated with the top-level template t. Parse may be called multiple times// to parse definitions of templates to associate with t. It is an error if a// resulting template is non-empty (contains content other than template// definitions) and would replace a non-empty template with the same name.// (In multiple calls to Parse with the same receiver template, only one call// can contain text other than space, comments, and template definitions.)func (t *Template) Parse(text string) (*Template, error) {t.init()trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins)if err != nil {return nil, err}// Add the newly parsed trees, including the one for t, into our common structure.for name, tree := range trees {// If the name we parsed is the name of this template, overwrite this template.// The associate method checks it's not a redefinition.tmpl := tif name != t.name {tmpl = t.New(name)}// Even if t == tmpl, we need to install it in the common.tmpl map.if err := t.associate(tmpl); err != nil {return nil, err}tmpl.Tree = treetmpl.leftDelim = t.leftDelimtmpl.rightDelim = t.rightDelim}return t, nil}// associate installs the new template into the group of templates associated// with t. It is an error to reuse a name except to overwrite an empty// template. The two are already known to share the common structure.func (t *Template) associate(new *Template) error {if new.common != t.common {panic("internal error: associate not common")}name := new.nameif old := t.tmpl[name]; old != nil {oldIsEmpty := parse.IsEmptyTree(old.Root)newIsEmpty := new.Tree != nil && parse.IsEmptyTree(new.Root)if !oldIsEmpty && !newIsEmpty {return fmt.Errorf("template: redefinition of template %q", name)}if newIsEmpty {// Whether old is empty or not, new is empty; no reason to replace old.return nil}}t.tmpl[name] = newreturn nil}
