1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
19 // FuncMap is the type of the map defining the mapping from names to functions.
20 // Each function must have either a single return value, or two return values of
21 // which the second has type error. In that case, if the second (error)
22 // return value evaluates to non-nil during execution, execution terminates and
23 // Execute returns that error.
25 // When template execution invokes a function with an argument list, that list
26 // must be assignable to the function's parameter types. Functions meant to
27 // apply to arguments of arbitrary type can use parameters of type interface{} or
28 // of type reflect.Value. Similarly, functions meant to return a result of arbitrary
29 // type can return interface{} or reflect.Value.
30 type FuncMap
map[string]interface{}
32 var builtins
= FuncMap
{
42 "printf": fmt
.Sprintf
,
43 "println": fmt
.Sprintln
,
44 "urlquery": URLQueryEscaper
,
55 var builtinFuncs
= createValueFuncs(builtins
)
57 // createValueFuncs turns a FuncMap into a map[string]reflect.Value
58 func createValueFuncs(funcMap FuncMap
) map[string]reflect
.Value
{
59 m
:= make(map[string]reflect
.Value
)
60 addValueFuncs(m
, funcMap
)
64 // addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
65 func addValueFuncs(out
map[string]reflect
.Value
, in FuncMap
) {
66 for name
, fn
:= range in
{
68 panic(fmt
.Errorf("function name %s is not a valid identifier", name
))
70 v
:= reflect
.ValueOf(fn
)
71 if v
.Kind() != reflect
.Func
{
72 panic("value for " + name
+ " not a function")
74 if !goodFunc(v
.Type()) {
75 panic(fmt
.Errorf("can't install method/function %q with %d results", name
, v
.Type().NumOut()))
81 // addFuncs adds to values the functions in funcs. It does no checking of the input -
82 // call addValueFuncs first.
83 func addFuncs(out
, in FuncMap
) {
84 for name
, fn
:= range in
{
89 // goodFunc reports whether the function or method has the right result signature.
90 func goodFunc(typ reflect
.Type
) bool {
91 // We allow functions with 1 result or 2 results where the second is an error.
93 case typ
.NumOut() == 1:
95 case typ
.NumOut() == 2 && typ
.Out(1) == errorType
:
101 // goodName reports whether the function name is a valid identifier.
102 func goodName(name
string) bool {
106 for i
, r
:= range name
{
109 case i
== 0 && !unicode
.IsLetter(r
):
111 case !unicode
.IsLetter(r
) && !unicode
.IsDigit(r
):
118 // findFunction looks for a function in the template, and global map.
119 func findFunction(name
string, tmpl
*Template
) (reflect
.Value
, bool) {
120 if tmpl
!= nil && tmpl
.common
!= nil {
122 defer tmpl
.muFuncs
.RUnlock()
123 if fn
:= tmpl
.execFuncs
[name
]; fn
.IsValid() {
127 if fn
:= builtinFuncs
[name
]; fn
.IsValid() {
130 return reflect
.Value
{}, false
133 // prepareArg checks if value can be used as an argument of type argType, and
134 // converts an invalid value to appropriate zero if possible.
135 func prepareArg(value reflect
.Value
, argType reflect
.Type
) (reflect
.Value
, error
) {
136 if !value
.IsValid() {
137 if !canBeNil(argType
) {
138 return reflect
.Value
{}, fmt
.Errorf("value is nil; should be of type %s", argType
)
140 value
= reflect
.Zero(argType
)
142 if !value
.Type().AssignableTo(argType
) {
143 return reflect
.Value
{}, fmt
.Errorf("value has type %s; should be %s", value
.Type(), argType
)
150 // index returns the result of indexing its first argument by the following
151 // arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each
152 // indexed item must be a map, slice, or array.
153 func index(item reflect
.Value
, indices
...reflect
.Value
) (reflect
.Value
, error
) {
154 v
:= indirectInterface(item
)
156 return reflect
.Value
{}, fmt
.Errorf("index of untyped nil")
158 for _
, i
:= range indices
{
159 index
:= indirectInterface(i
)
161 if v
, isNil
= indirect(v
); isNil
{
162 return reflect
.Value
{}, fmt
.Errorf("index of nil pointer")
165 case reflect
.Array
, reflect
.Slice
, reflect
.String
:
167 switch index
.Kind() {
168 case reflect
.Int
, reflect
.Int8
, reflect
.Int16
, reflect
.Int32
, reflect
.Int64
:
170 case reflect
.Uint
, reflect
.Uint8
, reflect
.Uint16
, reflect
.Uint32
, reflect
.Uint64
, reflect
.Uintptr
:
171 x
= int64(index
.Uint())
172 case reflect
.Invalid
:
173 return reflect
.Value
{}, fmt
.Errorf("cannot index slice/array with nil")
175 return reflect
.Value
{}, fmt
.Errorf("cannot index slice/array with type %s", index
.Type())
177 if x
< 0 || x
>= int64(v
.Len()) {
178 return reflect
.Value
{}, fmt
.Errorf("index out of range: %d", x
)
182 index
, err
:= prepareArg(index
, v
.Type().Key())
184 return reflect
.Value
{}, err
186 if x
:= v
.MapIndex(index
); x
.IsValid() {
189 v
= reflect
.Zero(v
.Type().Elem())
191 case reflect
.Invalid
:
192 // the loop holds invariant: v.IsValid()
195 return reflect
.Value
{}, fmt
.Errorf("can't index item of type %s", v
.Type())
203 // length returns the length of the item, with an error if it has no defined length.
204 func length(item
interface{}) (int, error
) {
205 v
:= reflect
.ValueOf(item
)
207 return 0, fmt
.Errorf("len of untyped nil")
209 v
, isNil
:= indirect(v
)
211 return 0, fmt
.Errorf("len of nil pointer")
214 case reflect
.Array
, reflect
.Chan
, reflect
.Map
, reflect
.Slice
, reflect
.String
:
217 return 0, fmt
.Errorf("len of type %s", v
.Type())
220 // Function invocation
222 // call returns the result of evaluating the first argument as a function.
223 // The function must return 1 result, or 2 results, the second of which is an error.
224 func call(fn reflect
.Value
, args
...reflect
.Value
) (reflect
.Value
, error
) {
225 v
:= indirectInterface(fn
)
227 return reflect
.Value
{}, fmt
.Errorf("call of nil")
230 if typ
.Kind() != reflect
.Func
{
231 return reflect
.Value
{}, fmt
.Errorf("non-function of type %s", typ
)
234 return reflect
.Value
{}, fmt
.Errorf("function called with %d args; should be 1 or 2", typ
.NumOut())
237 var dddType reflect
.Type
238 if typ
.IsVariadic() {
239 if len(args
) < numIn
-1 {
240 return reflect
.Value
{}, fmt
.Errorf("wrong number of args: got %d want at least %d", len(args
), numIn
-1)
242 dddType
= typ
.In(numIn
- 1).Elem()
244 if len(args
) != numIn
{
245 return reflect
.Value
{}, fmt
.Errorf("wrong number of args: got %d want %d", len(args
), numIn
)
248 argv
:= make([]reflect
.Value
, len(args
))
249 for i
, arg
:= range args
{
250 value
:= indirectInterface(arg
)
251 // Compute the expected type. Clumsy because of variadics.
252 var argType reflect
.Type
253 if !typ
.IsVariadic() || i
< numIn
-1 {
260 if argv
[i
], err
= prepareArg(value
, argType
); err
!= nil {
261 return reflect
.Value
{}, fmt
.Errorf("arg %d: %s", i
, err
)
264 result
:= v
.Call(argv
)
265 if len(result
) == 2 && !result
[1].IsNil() {
266 return result
[0], result
[1].Interface().(error
)
268 return result
[0], nil
273 func truth(arg reflect
.Value
) bool {
274 t
, _
:= isTrue(indirectInterface(arg
))
278 // and computes the Boolean AND of its arguments, returning
279 // the first false argument it encounters, or the last argument.
280 func and(arg0 reflect
.Value
, args
...reflect
.Value
) reflect
.Value
{
284 for i
:= range args
{
293 // or computes the Boolean OR of its arguments, returning
294 // the first true argument it encounters, or the last argument.
295 func or(arg0 reflect
.Value
, args
...reflect
.Value
) reflect
.Value
{
299 for i
:= range args
{
308 // not returns the Boolean negation of its argument.
309 func not(arg reflect
.Value
) bool {
315 // TODO: Perhaps allow comparison between signed and unsigned integers.
318 errBadComparisonType
= errors
.New("invalid type for comparison")
319 errBadComparison
= errors
.New("incompatible types for comparison")
320 errNoComparison
= errors
.New("missing argument for comparison")
326 invalidKind kind
= iota
335 func basicKind(v reflect
.Value
) (kind
, error
) {
339 case reflect
.Int
, reflect
.Int8
, reflect
.Int16
, reflect
.Int32
, reflect
.Int64
:
341 case reflect
.Uint
, reflect
.Uint8
, reflect
.Uint16
, reflect
.Uint32
, reflect
.Uint64
, reflect
.Uintptr
:
343 case reflect
.Float32
, reflect
.Float64
:
344 return floatKind
, nil
345 case reflect
.Complex64
, reflect
.Complex128
:
346 return complexKind
, nil
348 return stringKind
, nil
350 return invalidKind
, errBadComparisonType
353 // eq evaluates the comparison a == b || a == c || ...
354 func eq(arg1 reflect
.Value
, arg2
...reflect
.Value
) (bool, error
) {
355 v1
:= indirectInterface(arg1
)
356 k1
, err
:= basicKind(v1
)
361 return false, errNoComparison
363 for _
, arg
:= range arg2
{
364 v2
:= indirectInterface(arg
)
365 k2
, err
:= basicKind(v2
)
371 // Special case: Can compare integer values regardless of type's sign.
373 case k1
== intKind
&& k2
== uintKind
:
374 truth
= v1
.Int() >= 0 && uint64(v1
.Int()) == v2
.Uint()
375 case k1
== uintKind
&& k2
== intKind
:
376 truth
= v2
.Int() >= 0 && v1
.Uint() == uint64(v2
.Int())
378 return false, errBadComparison
383 truth
= v1
.Bool() == v2
.Bool()
385 truth
= v1
.Complex() == v2
.Complex()
387 truth
= v1
.Float() == v2
.Float()
389 truth
= v1
.Int() == v2
.Int()
391 truth
= v1
.String() == v2
.String()
393 truth
= v1
.Uint() == v2
.Uint()
395 panic("invalid kind")
405 // ne evaluates the comparison a != b.
406 func ne(arg1
, arg2 reflect
.Value
) (bool, error
) {
407 // != is the inverse of ==.
408 equal
, err
:= eq(arg1
, arg2
)
412 // lt evaluates the comparison a < b.
413 func lt(arg1
, arg2 reflect
.Value
) (bool, error
) {
414 v1
:= indirectInterface(arg1
)
415 k1
, err
:= basicKind(v1
)
419 v2
:= indirectInterface(arg2
)
420 k2
, err
:= basicKind(v2
)
426 // Special case: Can compare integer values regardless of type's sign.
428 case k1
== intKind
&& k2
== uintKind
:
429 truth
= v1
.Int() < 0 ||
uint64(v1
.Int()) < v2
.Uint()
430 case k1
== uintKind
&& k2
== intKind
:
431 truth
= v2
.Int() >= 0 && v1
.Uint() < uint64(v2
.Int())
433 return false, errBadComparison
437 case boolKind
, complexKind
:
438 return false, errBadComparisonType
440 truth
= v1
.Float() < v2
.Float()
442 truth
= v1
.Int() < v2
.Int()
444 truth
= v1
.String() < v2
.String()
446 truth
= v1
.Uint() < v2
.Uint()
448 panic("invalid kind")
454 // le evaluates the comparison <= b.
455 func le(arg1
, arg2 reflect
.Value
) (bool, error
) {
457 lessThan
, err
:= lt(arg1
, arg2
)
458 if lessThan || err
!= nil {
461 return eq(arg1
, arg2
)
464 // gt evaluates the comparison a > b.
465 func gt(arg1
, arg2 reflect
.Value
) (bool, error
) {
466 // > is the inverse of <=.
467 lessOrEqual
, err
:= le(arg1
, arg2
)
471 return !lessOrEqual
, nil
474 // ge evaluates the comparison a >= b.
475 func ge(arg1
, arg2 reflect
.Value
) (bool, error
) {
476 // >= is the inverse of <.
477 lessThan
, err
:= lt(arg1
, arg2
)
481 return !lessThan
, nil
487 htmlQuot
= []byte(""") // shorter than """
488 htmlApos
= []byte("'") // shorter than "'" and apos was not in HTML until HTML5
489 htmlAmp
= []byte("&")
490 htmlLt
= []byte("<")
491 htmlGt
= []byte(">")
492 htmlNull
= []byte("\uFFFD")
495 // HTMLEscape writes to w the escaped HTML equivalent of the plain text data b.
496 func HTMLEscape(w io
.Writer
, b
[]byte) {
498 for i
, c
:= range b
{
523 // HTMLEscapeString returns the escaped HTML equivalent of the plain text data s.
524 func HTMLEscapeString(s
string) string {
525 // Avoid allocation if we can.
526 if !strings
.ContainsAny(s
, "'\"&<>\000") {
530 HTMLEscape(&b
, []byte(s
))
534 // HTMLEscaper returns the escaped HTML equivalent of the textual
535 // representation of its arguments.
536 func HTMLEscaper(args
...interface{}) string {
537 return HTMLEscapeString(evalArgs(args
))
540 // JavaScript escaping.
543 jsLowUni
= []byte(`\u00`)
544 hex
= []byte("0123456789ABCDEF")
546 jsBackslash
= []byte(`\\`)
547 jsApos
= []byte(`\'`)
548 jsQuot
= []byte(`\"`)
549 jsLt
= []byte(`\x3C`)
550 jsGt
= []byte(`\x3E`)
553 // JSEscape writes to w the escaped JavaScript equivalent of the plain text data b.
554 func JSEscape(w io
.Writer
, b
[]byte) {
556 for i
:= 0; i
< len(b
); i
++ {
559 if !jsIsSpecial(rune(c
)) {
560 // fast path: nothing to do
565 if c
< utf8
.RuneSelf
{
566 // Quotes, slashes and angle brackets get quoted.
567 // Control characters get written as \u00XX.
582 w
.Write(hex
[t
: t
+1])
583 w
.Write(hex
[b
: b
+1])
587 r
, size
:= utf8
.DecodeRune(b
[i
:])
588 if unicode
.IsPrint(r
) {
589 w
.Write(b
[i
: i
+size
])
591 fmt
.Fprintf(w
, "\\u%04X", r
)
600 // JSEscapeString returns the escaped JavaScript equivalent of the plain text data s.
601 func JSEscapeString(s
string) string {
602 // Avoid allocation if we can.
603 if strings
.IndexFunc(s
, jsIsSpecial
) < 0 {
607 JSEscape(&b
, []byte(s
))
611 func jsIsSpecial(r rune
) bool {
613 case '\\', '\'', '"', '<', '>':
616 return r
< ' ' || utf8
.RuneSelf
<= r
619 // JSEscaper returns the escaped JavaScript equivalent of the textual
620 // representation of its arguments.
621 func JSEscaper(args
...interface{}) string {
622 return JSEscapeString(evalArgs(args
))
625 // URLQueryEscaper returns the escaped value of the textual representation of
626 // its arguments in a form suitable for embedding in a URL query.
627 func URLQueryEscaper(args
...interface{}) string {
628 return url
.QueryEscape(evalArgs(args
))
631 // evalArgs formats the list of arguments into a string. It is therefore equivalent to
632 // fmt.Sprint(args...)
633 // except that each argument is indirected (if a pointer), as required,
634 // using the same rules as the default string evaluation during template
636 func evalArgs(args
[]interface{}) string {
639 // Fast path for simple common case.
641 s
, ok
= args
[0].(string)
644 for i
, arg
:= range args
{
645 a
, ok
:= printableValue(reflect
.ValueOf(arg
))
648 } // else let fmt do its thing
650 s
= fmt
.Sprint(args
...)