libgo: update to go1.9
[official-gcc.git] / libgo / go / text / template / funcs.go
blob910743103747a53bd903523a3abfe9f58d41f41b
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.
5 package template
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "net/url"
13 "reflect"
14 "strings"
15 "unicode"
16 "unicode/utf8"
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{
33 "and": and,
34 "call": call,
35 "html": HTMLEscaper,
36 "index": index,
37 "js": JSEscaper,
38 "len": length,
39 "not": not,
40 "or": or,
41 "print": fmt.Sprint,
42 "printf": fmt.Sprintf,
43 "println": fmt.Sprintln,
44 "urlquery": URLQueryEscaper,
46 // Comparisons
47 "eq": eq, // ==
48 "ge": ge, // >=
49 "gt": gt, // >
50 "le": le, // <=
51 "lt": lt, // <
52 "ne": ne, // !=
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)
61 return m
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 {
67 if !goodName(name) {
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()))
77 out[name] = v
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 {
85 out[name] = fn
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.
92 switch {
93 case typ.NumOut() == 1:
94 return true
95 case typ.NumOut() == 2 && typ.Out(1) == errorType:
96 return true
98 return false
101 // goodName reports whether the function name is a valid identifier.
102 func goodName(name string) bool {
103 if name == "" {
104 return false
106 for i, r := range name {
107 switch {
108 case r == '_':
109 case i == 0 && !unicode.IsLetter(r):
110 return false
111 case !unicode.IsLetter(r) && !unicode.IsDigit(r):
112 return false
115 return true
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 {
121 tmpl.muFuncs.RLock()
122 defer tmpl.muFuncs.RUnlock()
123 if fn := tmpl.execFuncs[name]; fn.IsValid() {
124 return fn, true
127 if fn := builtinFuncs[name]; fn.IsValid() {
128 return fn, true
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)
145 return value, nil
148 // Indexing.
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)
155 if !v.IsValid() {
156 return reflect.Value{}, fmt.Errorf("index of untyped nil")
158 for _, i := range indices {
159 index := indirectInterface(i)
160 var isNil bool
161 if v, isNil = indirect(v); isNil {
162 return reflect.Value{}, fmt.Errorf("index of nil pointer")
164 switch v.Kind() {
165 case reflect.Array, reflect.Slice, reflect.String:
166 var x int64
167 switch index.Kind() {
168 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
169 x = index.Int()
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")
174 default:
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)
180 v = v.Index(int(x))
181 case reflect.Map:
182 index, err := prepareArg(index, v.Type().Key())
183 if err != nil {
184 return reflect.Value{}, err
186 if x := v.MapIndex(index); x.IsValid() {
187 v = x
188 } else {
189 v = reflect.Zero(v.Type().Elem())
191 case reflect.Invalid:
192 // the loop holds invariant: v.IsValid()
193 panic("unreachable")
194 default:
195 return reflect.Value{}, fmt.Errorf("can't index item of type %s", v.Type())
198 return v, nil
201 // Length
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)
206 if !v.IsValid() {
207 return 0, fmt.Errorf("len of untyped nil")
209 v, isNil := indirect(v)
210 if isNil {
211 return 0, fmt.Errorf("len of nil pointer")
213 switch v.Kind() {
214 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
215 return v.Len(), nil
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)
226 if !v.IsValid() {
227 return reflect.Value{}, fmt.Errorf("call of nil")
229 typ := v.Type()
230 if typ.Kind() != reflect.Func {
231 return reflect.Value{}, fmt.Errorf("non-function of type %s", typ)
233 if !goodFunc(typ) {
234 return reflect.Value{}, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
236 numIn := typ.NumIn()
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()
243 } else {
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 {
254 argType = typ.In(i)
255 } else {
256 argType = dddType
259 var err error
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
271 // Boolean logic.
273 func truth(arg reflect.Value) bool {
274 t, _ := isTrue(indirectInterface(arg))
275 return t
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 {
281 if !truth(arg0) {
282 return arg0
284 for i := range args {
285 arg0 = args[i]
286 if !truth(arg0) {
287 break
290 return arg0
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 {
296 if truth(arg0) {
297 return arg0
299 for i := range args {
300 arg0 = args[i]
301 if truth(arg0) {
302 break
305 return arg0
308 // not returns the Boolean negation of its argument.
309 func not(arg reflect.Value) bool {
310 return !truth(arg)
313 // Comparison.
315 // TODO: Perhaps allow comparison between signed and unsigned integers.
317 var (
318 errBadComparisonType = errors.New("invalid type for comparison")
319 errBadComparison = errors.New("incompatible types for comparison")
320 errNoComparison = errors.New("missing argument for comparison")
323 type kind int
325 const (
326 invalidKind kind = iota
327 boolKind
328 complexKind
329 intKind
330 floatKind
331 stringKind
332 uintKind
335 func basicKind(v reflect.Value) (kind, error) {
336 switch v.Kind() {
337 case reflect.Bool:
338 return boolKind, nil
339 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
340 return intKind, nil
341 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
342 return uintKind, nil
343 case reflect.Float32, reflect.Float64:
344 return floatKind, nil
345 case reflect.Complex64, reflect.Complex128:
346 return complexKind, nil
347 case reflect.String:
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)
357 if err != nil {
358 return false, err
360 if len(arg2) == 0 {
361 return false, errNoComparison
363 for _, arg := range arg2 {
364 v2 := indirectInterface(arg)
365 k2, err := basicKind(v2)
366 if err != nil {
367 return false, err
369 truth := false
370 if k1 != k2 {
371 // Special case: Can compare integer values regardless of type's sign.
372 switch {
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())
377 default:
378 return false, errBadComparison
380 } else {
381 switch k1 {
382 case boolKind:
383 truth = v1.Bool() == v2.Bool()
384 case complexKind:
385 truth = v1.Complex() == v2.Complex()
386 case floatKind:
387 truth = v1.Float() == v2.Float()
388 case intKind:
389 truth = v1.Int() == v2.Int()
390 case stringKind:
391 truth = v1.String() == v2.String()
392 case uintKind:
393 truth = v1.Uint() == v2.Uint()
394 default:
395 panic("invalid kind")
398 if truth {
399 return true, nil
402 return false, nil
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)
409 return !equal, err
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)
416 if err != nil {
417 return false, err
419 v2 := indirectInterface(arg2)
420 k2, err := basicKind(v2)
421 if err != nil {
422 return false, err
424 truth := false
425 if k1 != k2 {
426 // Special case: Can compare integer values regardless of type's sign.
427 switch {
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())
432 default:
433 return false, errBadComparison
435 } else {
436 switch k1 {
437 case boolKind, complexKind:
438 return false, errBadComparisonType
439 case floatKind:
440 truth = v1.Float() < v2.Float()
441 case intKind:
442 truth = v1.Int() < v2.Int()
443 case stringKind:
444 truth = v1.String() < v2.String()
445 case uintKind:
446 truth = v1.Uint() < v2.Uint()
447 default:
448 panic("invalid kind")
451 return truth, nil
454 // le evaluates the comparison <= b.
455 func le(arg1, arg2 reflect.Value) (bool, error) {
456 // <= is < or ==.
457 lessThan, err := lt(arg1, arg2)
458 if lessThan || err != nil {
459 return lessThan, err
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)
468 if err != nil {
469 return false, err
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)
478 if err != nil {
479 return false, err
481 return !lessThan, nil
484 // HTML escaping.
486 var (
487 htmlQuot = []byte("&#34;") // shorter than "&quot;"
488 htmlApos = []byte("&#39;") // shorter than "&apos;" and apos was not in HTML until HTML5
489 htmlAmp = []byte("&amp;")
490 htmlLt = []byte("&lt;")
491 htmlGt = []byte("&gt;")
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) {
497 last := 0
498 for i, c := range b {
499 var html []byte
500 switch c {
501 case '\000':
502 html = htmlNull
503 case '"':
504 html = htmlQuot
505 case '\'':
506 html = htmlApos
507 case '&':
508 html = htmlAmp
509 case '<':
510 html = htmlLt
511 case '>':
512 html = htmlGt
513 default:
514 continue
516 w.Write(b[last:i])
517 w.Write(html)
518 last = i + 1
520 w.Write(b[last:])
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") {
527 return s
529 var b bytes.Buffer
530 HTMLEscape(&b, []byte(s))
531 return b.String()
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.
542 var (
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) {
555 last := 0
556 for i := 0; i < len(b); i++ {
557 c := b[i]
559 if !jsIsSpecial(rune(c)) {
560 // fast path: nothing to do
561 continue
563 w.Write(b[last:i])
565 if c < utf8.RuneSelf {
566 // Quotes, slashes and angle brackets get quoted.
567 // Control characters get written as \u00XX.
568 switch c {
569 case '\\':
570 w.Write(jsBackslash)
571 case '\'':
572 w.Write(jsApos)
573 case '"':
574 w.Write(jsQuot)
575 case '<':
576 w.Write(jsLt)
577 case '>':
578 w.Write(jsGt)
579 default:
580 w.Write(jsLowUni)
581 t, b := c>>4, c&0x0f
582 w.Write(hex[t : t+1])
583 w.Write(hex[b : b+1])
585 } else {
586 // Unicode rune.
587 r, size := utf8.DecodeRune(b[i:])
588 if unicode.IsPrint(r) {
589 w.Write(b[i : i+size])
590 } else {
591 fmt.Fprintf(w, "\\u%04X", r)
593 i += size - 1
595 last = i + 1
597 w.Write(b[last:])
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 {
604 return s
606 var b bytes.Buffer
607 JSEscape(&b, []byte(s))
608 return b.String()
611 func jsIsSpecial(r rune) bool {
612 switch r {
613 case '\\', '\'', '"', '<', '>':
614 return true
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
635 // execution.
636 func evalArgs(args []interface{}) string {
637 ok := false
638 var s string
639 // Fast path for simple common case.
640 if len(args) == 1 {
641 s, ok = args[0].(string)
643 if !ok {
644 for i, arg := range args {
645 a, ok := printableValue(reflect.ValueOf(arg))
646 if ok {
647 args[i] = a
648 } // else let fmt do its thing
650 s = fmt.Sprint(args...)
652 return s