diff options
Diffstat (limited to 'src/pkg/exp/template/funcs.go')
-rw-r--r-- | src/pkg/exp/template/funcs.go | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/src/pkg/exp/template/funcs.go b/src/pkg/exp/template/funcs.go deleted file mode 100644 index 66be40fd4..000000000 --- a/src/pkg/exp/template/funcs.go +++ /dev/null @@ -1,294 +0,0 @@ -// 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 template - -import ( - "bytes" - "fmt" - "io" - "os" - "reflect" - "strings" - "unicode" - "utf8" -) - -// FuncMap is the type of the map defining the mapping from names to functions. -// Each function must have either a single return value, or two return values of -// which the second has type os.Error. -type FuncMap map[string]interface{} - -var funcs = map[string]reflect.Value{ - "and": reflect.ValueOf(and), - "html": reflect.ValueOf(HTMLEscaper), - "index": reflect.ValueOf(index), - "js": reflect.ValueOf(JSEscaper), - "not": reflect.ValueOf(not), - "or": reflect.ValueOf(or), - "printf": reflect.ValueOf(fmt.Sprintf), -} - -// addFuncs adds to values the functions in funcs, converting them to reflect.Values. -func addFuncs(values map[string]reflect.Value, funcMap FuncMap) { - for name, fn := range funcMap { - v := reflect.ValueOf(fn) - if v.Kind() != reflect.Func { - panic("value for " + name + " not a function") - } - if !goodFunc(v.Type()) { - panic(fmt.Errorf("can't handle multiple results from method/function %q", name)) - } - values[name] = v - } -} - -// goodFunc checks that the function or method has the right result signature. -func goodFunc(typ reflect.Type) bool { - // We allow functions with 1 result or 2 results where the second is an os.Error. - switch { - case typ.NumOut() == 1: - return true - case typ.NumOut() == 2 && typ.Out(1) == osErrorType: - return true - } - return false -} - -// findFunction looks for a function in the template, set, and global map. -func findFunction(name string, tmpl *Template, set *Set) (reflect.Value, bool) { - if tmpl != nil { - if fn := tmpl.funcs[name]; fn.IsValid() { - return fn, true - } - } - if set != nil { - if fn := set.funcs[name]; fn.IsValid() { - return fn, true - } - } - if fn := funcs[name]; fn.IsValid() { - return fn, true - } - return reflect.Value{}, false -} - -// Indexing. - -// index returns the result of indexing its first argument by the following -// arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each -// indexed item must be a map, slice, or array. -func index(item interface{}, indices ...interface{}) (interface{}, os.Error) { - v := reflect.ValueOf(item) - for _, i := range indices { - index := reflect.ValueOf(i) - var isNil bool - if v, isNil = indirect(v); isNil { - return nil, fmt.Errorf("index of nil pointer") - } - switch v.Kind() { - case reflect.Array, reflect.Slice: - var x int64 - switch index.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - x = index.Int() - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - x = int64(index.Uint()) - default: - return nil, fmt.Errorf("cannot index slice/array with type %s", index.Type()) - } - if x < 0 || x >= int64(v.Len()) { - return nil, fmt.Errorf("index out of range: %d", x) - } - v = v.Index(int(x)) - case reflect.Map: - if !index.Type().AssignableTo(v.Type().Key()) { - return nil, fmt.Errorf("%s is not index type for %s", index.Type(), v.Type()) - } - v = v.MapIndex(index) - if !v.IsValid() { - return nil, fmt.Errorf("index %v not present in map", index.Interface()) - } - default: - return nil, fmt.Errorf("can't index item of type %s", index.Type()) - } - } - return v.Interface(), nil -} - -// Boolean logic. - -// and returns the Boolean AND of its arguments. -func and(arg0 interface{}, args ...interface{}) (truth bool) { - truth, _ = isTrue(reflect.ValueOf(arg0)) - for i := 0; truth && i < len(args); i++ { - truth, _ = isTrue(reflect.ValueOf(args[i])) - } - return -} - -// or returns the Boolean OR of its arguments. -func or(arg0 interface{}, args ...interface{}) (truth bool) { - truth, _ = isTrue(reflect.ValueOf(arg0)) - for i := 0; !truth && i < len(args); i++ { - truth, _ = isTrue(reflect.ValueOf(args[i])) - } - return -} - -// not returns the Boolean negation of its argument. -func not(arg interface{}) (truth bool) { - truth, _ = isTrue(reflect.ValueOf(arg)) - return !truth -} - -// HTML escaping. - -var ( - htmlQuot = []byte(""") // shorter than """ - htmlApos = []byte("'") // shorter than "'" - htmlAmp = []byte("&") - htmlLt = []byte("<") - htmlGt = []byte(">") -) - -// HTMLEscape writes to w the escaped HTML equivalent of the plain text data b. -func HTMLEscape(w io.Writer, b []byte) { - last := 0 - for i, c := range b { - var html []byte - switch c { - case '"': - html = htmlQuot - case '\'': - html = htmlApos - case '&': - html = htmlAmp - case '<': - html = htmlLt - case '>': - html = htmlGt - default: - continue - } - w.Write(b[last:i]) - w.Write(html) - last = i + 1 - } - w.Write(b[last:]) -} - -// HTMLEscapeString returns the escaped HTML equivalent of the plain text data s. -func HTMLEscapeString(s string) string { - // Avoid allocation if we can. - if strings.IndexAny(s, `'"&<>`) < 0 { - return s - } - var b bytes.Buffer - HTMLEscape(&b, []byte(s)) - return b.String() -} - -// HTMLEscaper returns the escaped HTML equivalent of the textual -// representation of its arguments. -func HTMLEscaper(args ...interface{}) string { - ok := false - var s string - if len(args) == 1 { - s, ok = args[0].(string) - } - if !ok { - s = fmt.Sprint(args...) - } - return HTMLEscapeString(s) -} - -// JavaScript escaping. - -var ( - jsLowUni = []byte(`\u00`) - hex = []byte("0123456789ABCDEF") - - jsBackslash = []byte(`\\`) - jsApos = []byte(`\'`) - jsQuot = []byte(`\"`) -) - - -// JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. -func JSEscape(w io.Writer, b []byte) { - last := 0 - for i := 0; i < len(b); i++ { - c := b[i] - - if ' ' <= c && c < utf8.RuneSelf && c != '\\' && c != '"' && c != '\'' { - // fast path: nothing to do - continue - } - w.Write(b[last:i]) - - if c < utf8.RuneSelf { - // Quotes and slashes get quoted. - // Control characters get written as \u00XX. - switch c { - case '\\': - w.Write(jsBackslash) - case '\'': - w.Write(jsApos) - case '"': - w.Write(jsQuot) - default: - w.Write(jsLowUni) - t, b := c>>4, c&0x0f - w.Write(hex[t : t+1]) - w.Write(hex[b : b+1]) - } - } else { - // Unicode rune. - rune, size := utf8.DecodeRune(b[i:]) - if unicode.IsPrint(rune) { - w.Write(b[i : i+size]) - } else { - // TODO(dsymonds): Do this without fmt? - fmt.Fprintf(w, "\\u%04X", rune) - } - i += size - 1 - } - last = i + 1 - } - w.Write(b[last:]) -} - -// JSEscapeString returns the escaped JavaScript equivalent of the plain text data s. -func JSEscapeString(s string) string { - // Avoid allocation if we can. - if strings.IndexFunc(s, jsIsSpecial) < 0 { - return s - } - var b bytes.Buffer - JSEscape(&b, []byte(s)) - return b.String() -} - -func jsIsSpecial(rune int) bool { - switch rune { - case '\\', '\'', '"': - return true - } - return rune < ' ' || utf8.RuneSelf <= rune -} - -// JSEscaper returns the escaped JavaScript equivalent of the textual -// representation of its arguments. -func JSEscaper(args ...interface{}) string { - ok := false - var s string - if len(args) == 1 { - s, ok = args[0].(string) - } - if !ok { - s = fmt.Sprint(args...) - } - return JSEscapeString(s) -} |