Source file src/pkg/text/template/funcs.go
1
2
3
4
5 package template
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "net/url"
13 "reflect"
14 "strings"
15 "unicode"
16 "unicode/utf8"
17 )
18
19
20
21
22
23
24
25
26
27
28
29
30 type FuncMap map[string]interface{}
31
32 var builtins = FuncMap{
33 "and": and,
34 "call": call,
35 "html": HTMLEscaper,
36 "index": index,
37 "slice": slice,
38 "js": JSEscaper,
39 "len": length,
40 "not": not,
41 "or": or,
42 "print": fmt.Sprint,
43 "printf": fmt.Sprintf,
44 "println": fmt.Sprintln,
45 "urlquery": URLQueryEscaper,
46
47
48 "eq": eq,
49 "ge": ge,
50 "gt": gt,
51 "le": le,
52 "lt": lt,
53 "ne": ne,
54 }
55
56 var builtinFuncs = createValueFuncs(builtins)
57
58
59 func createValueFuncs(funcMap FuncMap) map[string]reflect.Value {
60 m := make(map[string]reflect.Value)
61 addValueFuncs(m, funcMap)
62 return m
63 }
64
65
66 func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
67 for name, fn := range in {
68 if !goodName(name) {
69 panic(fmt.Errorf("function name %q is not a valid identifier", name))
70 }
71 v := reflect.ValueOf(fn)
72 if v.Kind() != reflect.Func {
73 panic("value for " + name + " not a function")
74 }
75 if !goodFunc(v.Type()) {
76 panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut()))
77 }
78 out[name] = v
79 }
80 }
81
82
83
84 func addFuncs(out, in FuncMap) {
85 for name, fn := range in {
86 out[name] = fn
87 }
88 }
89
90
91 func goodFunc(typ reflect.Type) bool {
92
93 switch {
94 case typ.NumOut() == 1:
95 return true
96 case typ.NumOut() == 2 && typ.Out(1) == errorType:
97 return true
98 }
99 return false
100 }
101
102
103 func goodName(name string) bool {
104 if name == "" {
105 return false
106 }
107 for i, r := range name {
108 switch {
109 case r == '_':
110 case i == 0 && !unicode.IsLetter(r):
111 return false
112 case !unicode.IsLetter(r) && !unicode.IsDigit(r):
113 return false
114 }
115 }
116 return true
117 }
118
119
120 func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
121 if tmpl != nil && tmpl.common != nil {
122 tmpl.muFuncs.RLock()
123 defer tmpl.muFuncs.RUnlock()
124 if fn := tmpl.execFuncs[name]; fn.IsValid() {
125 return fn, true
126 }
127 }
128 if fn := builtinFuncs[name]; fn.IsValid() {
129 return fn, true
130 }
131 return reflect.Value{}, false
132 }
133
134
135
136 func prepareArg(value reflect.Value, argType reflect.Type) (reflect.Value, error) {
137 if !value.IsValid() {
138 if !canBeNil(argType) {
139 return reflect.Value{}, fmt.Errorf("value is nil; should be of type %s", argType)
140 }
141 value = reflect.Zero(argType)
142 }
143 if value.Type().AssignableTo(argType) {
144 return value, nil
145 }
146 if intLike(value.Kind()) && intLike(argType.Kind()) && value.Type().ConvertibleTo(argType) {
147 value = value.Convert(argType)
148 return value, nil
149 }
150 return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType)
151 }
152
153 func intLike(typ reflect.Kind) bool {
154 switch typ {
155 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
156 return true
157 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
158 return true
159 }
160 return false
161 }
162
163
164 func indexArg(index reflect.Value, cap int) (int, error) {
165 var x int64
166 switch index.Kind() {
167 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
168 x = index.Int()
169 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
170 x = int64(index.Uint())
171 case reflect.Invalid:
172 return 0, fmt.Errorf("cannot index slice/array with nil")
173 default:
174 return 0, fmt.Errorf("cannot index slice/array with type %s", index.Type())
175 }
176 if x < 0 || int(x) < 0 || int(x) > cap {
177 return 0, fmt.Errorf("index out of range: %d", x)
178 }
179 return int(x), nil
180 }
181
182
183
184
185
186
187 func index(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error) {
188 v := indirectInterface(item)
189 if !v.IsValid() {
190 return reflect.Value{}, fmt.Errorf("index of untyped nil")
191 }
192 for _, i := range indexes {
193 index := indirectInterface(i)
194 var isNil bool
195 if v, isNil = indirect(v); isNil {
196 return reflect.Value{}, fmt.Errorf("index of nil pointer")
197 }
198 switch v.Kind() {
199 case reflect.Array, reflect.Slice, reflect.String:
200 x, err := indexArg(index, v.Len())
201 if err != nil {
202 return reflect.Value{}, err
203 }
204 v = v.Index(x)
205 case reflect.Map:
206 index, err := prepareArg(index, v.Type().Key())
207 if err != nil {
208 return reflect.Value{}, err
209 }
210 if x := v.MapIndex(index); x.IsValid() {
211 v = x
212 } else {
213 v = reflect.Zero(v.Type().Elem())
214 }
215 case reflect.Invalid:
216
217 panic("unreachable")
218 default:
219 return reflect.Value{}, fmt.Errorf("can't index item of type %s", v.Type())
220 }
221 }
222 return v, nil
223 }
224
225
226
227
228
229
230
231 func slice(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error) {
232 var (
233 cap int
234 v = indirectInterface(item)
235 )
236 if !v.IsValid() {
237 return reflect.Value{}, fmt.Errorf("slice of untyped nil")
238 }
239 if len(indexes) > 3 {
240 return reflect.Value{}, fmt.Errorf("too many slice indexes: %d", len(indexes))
241 }
242 switch v.Kind() {
243 case reflect.String:
244 if len(indexes) == 3 {
245 return reflect.Value{}, fmt.Errorf("cannot 3-index slice a string")
246 }
247 cap = v.Len()
248 case reflect.Array, reflect.Slice:
249 cap = v.Cap()
250 default:
251 return reflect.Value{}, fmt.Errorf("can't slice item of type %s", v.Type())
252 }
253
254 idx := [3]int{0, v.Len()}
255 for i, index := range indexes {
256 x, err := indexArg(index, cap)
257 if err != nil {
258 return reflect.Value{}, err
259 }
260 idx[i] = x
261 }
262
263 if idx[0] > idx[1] {
264 return reflect.Value{}, fmt.Errorf("invalid slice index: %d > %d", idx[0], idx[1])
265 }
266 if len(indexes) < 3 {
267 return item.Slice(idx[0], idx[1]), nil
268 }
269
270 if idx[1] > idx[2] {
271 return reflect.Value{}, fmt.Errorf("invalid slice index: %d > %d", idx[1], idx[2])
272 }
273 return item.Slice3(idx[0], idx[1], idx[2]), nil
274 }
275
276
277
278
279 func length(item interface{}) (int, error) {
280 v := reflect.ValueOf(item)
281 if !v.IsValid() {
282 return 0, fmt.Errorf("len of untyped nil")
283 }
284 v, isNil := indirect(v)
285 if isNil {
286 return 0, fmt.Errorf("len of nil pointer")
287 }
288 switch v.Kind() {
289 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String:
290 return v.Len(), nil
291 }
292 return 0, fmt.Errorf("len of type %s", v.Type())
293 }
294
295
296
297
298
299 func call(fn reflect.Value, args ...reflect.Value) (reflect.Value, error) {
300 v := indirectInterface(fn)
301 if !v.IsValid() {
302 return reflect.Value{}, fmt.Errorf("call of nil")
303 }
304 typ := v.Type()
305 if typ.Kind() != reflect.Func {
306 return reflect.Value{}, fmt.Errorf("non-function of type %s", typ)
307 }
308 if !goodFunc(typ) {
309 return reflect.Value{}, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut())
310 }
311 numIn := typ.NumIn()
312 var dddType reflect.Type
313 if typ.IsVariadic() {
314 if len(args) < numIn-1 {
315 return reflect.Value{}, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1)
316 }
317 dddType = typ.In(numIn - 1).Elem()
318 } else {
319 if len(args) != numIn {
320 return reflect.Value{}, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn)
321 }
322 }
323 argv := make([]reflect.Value, len(args))
324 for i, arg := range args {
325 value := indirectInterface(arg)
326
327 argType := dddType
328 if !typ.IsVariadic() || i < numIn-1 {
329 argType = typ.In(i)
330 }
331
332 var err error
333 if argv[i], err = prepareArg(value, argType); err != nil {
334 return reflect.Value{}, fmt.Errorf("arg %d: %s", i, err)
335 }
336 }
337 return safeCall(v, argv)
338 }
339
340
341
342 func safeCall(fun reflect.Value, args []reflect.Value) (val reflect.Value, err error) {
343 defer func() {
344 if r := recover(); r != nil {
345 if e, ok := r.(error); ok {
346 err = e
347 } else {
348 err = fmt.Errorf("%v", r)
349 }
350 }
351 }()
352 ret := fun.Call(args)
353 if len(ret) == 2 && !ret[1].IsNil() {
354 return ret[0], ret[1].Interface().(error)
355 }
356 return ret[0], nil
357 }
358
359
360
361 func truth(arg reflect.Value) bool {
362 t, _ := isTrue(indirectInterface(arg))
363 return t
364 }
365
366
367
368 func and(arg0 reflect.Value, args ...reflect.Value) reflect.Value {
369 if !truth(arg0) {
370 return arg0
371 }
372 for i := range args {
373 arg0 = args[i]
374 if !truth(arg0) {
375 break
376 }
377 }
378 return arg0
379 }
380
381
382
383 func or(arg0 reflect.Value, args ...reflect.Value) reflect.Value {
384 if truth(arg0) {
385 return arg0
386 }
387 for i := range args {
388 arg0 = args[i]
389 if truth(arg0) {
390 break
391 }
392 }
393 return arg0
394 }
395
396
397 func not(arg reflect.Value) bool {
398 return !truth(arg)
399 }
400
401
402
403
404
405 var (
406 errBadComparisonType = errors.New("invalid type for comparison")
407 errBadComparison = errors.New("incompatible types for comparison")
408 errNoComparison = errors.New("missing argument for comparison")
409 )
410
411 type kind int
412
413 const (
414 invalidKind kind = iota
415 boolKind
416 complexKind
417 intKind
418 floatKind
419 stringKind
420 uintKind
421 )
422
423 func basicKind(v reflect.Value) (kind, error) {
424 switch v.Kind() {
425 case reflect.Bool:
426 return boolKind, nil
427 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
428 return intKind, nil
429 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
430 return uintKind, nil
431 case reflect.Float32, reflect.Float64:
432 return floatKind, nil
433 case reflect.Complex64, reflect.Complex128:
434 return complexKind, nil
435 case reflect.String:
436 return stringKind, nil
437 }
438 return invalidKind, errBadComparisonType
439 }
440
441
442 func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) {
443 v1 := indirectInterface(arg1)
444 k1, err := basicKind(v1)
445 if err != nil {
446 return false, err
447 }
448 if len(arg2) == 0 {
449 return false, errNoComparison
450 }
451 for _, arg := range arg2 {
452 v2 := indirectInterface(arg)
453 k2, err := basicKind(v2)
454 if err != nil {
455 return false, err
456 }
457 truth := false
458 if k1 != k2 {
459
460 switch {
461 case k1 == intKind && k2 == uintKind:
462 truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint()
463 case k1 == uintKind && k2 == intKind:
464 truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int())
465 default:
466 return false, errBadComparison
467 }
468 } else {
469 switch k1 {
470 case boolKind:
471 truth = v1.Bool() == v2.Bool()
472 case complexKind:
473 truth = v1.Complex() == v2.Complex()
474 case floatKind:
475 truth = v1.Float() == v2.Float()
476 case intKind:
477 truth = v1.Int() == v2.Int()
478 case stringKind:
479 truth = v1.String() == v2.String()
480 case uintKind:
481 truth = v1.Uint() == v2.Uint()
482 default:
483 panic("invalid kind")
484 }
485 }
486 if truth {
487 return true, nil
488 }
489 }
490 return false, nil
491 }
492
493
494 func ne(arg1, arg2 reflect.Value) (bool, error) {
495
496 equal, err := eq(arg1, arg2)
497 return !equal, err
498 }
499
500
501 func lt(arg1, arg2 reflect.Value) (bool, error) {
502 v1 := indirectInterface(arg1)
503 k1, err := basicKind(v1)
504 if err != nil {
505 return false, err
506 }
507 v2 := indirectInterface(arg2)
508 k2, err := basicKind(v2)
509 if err != nil {
510 return false, err
511 }
512 truth := false
513 if k1 != k2 {
514
515 switch {
516 case k1 == intKind && k2 == uintKind:
517 truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint()
518 case k1 == uintKind && k2 == intKind:
519 truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int())
520 default:
521 return false, errBadComparison
522 }
523 } else {
524 switch k1 {
525 case boolKind, complexKind:
526 return false, errBadComparisonType
527 case floatKind:
528 truth = v1.Float() < v2.Float()
529 case intKind:
530 truth = v1.Int() < v2.Int()
531 case stringKind:
532 truth = v1.String() < v2.String()
533 case uintKind:
534 truth = v1.Uint() < v2.Uint()
535 default:
536 panic("invalid kind")
537 }
538 }
539 return truth, nil
540 }
541
542
543 func le(arg1, arg2 reflect.Value) (bool, error) {
544
545 lessThan, err := lt(arg1, arg2)
546 if lessThan || err != nil {
547 return lessThan, err
548 }
549 return eq(arg1, arg2)
550 }
551
552
553 func gt(arg1, arg2 reflect.Value) (bool, error) {
554
555 lessOrEqual, err := le(arg1, arg2)
556 if err != nil {
557 return false, err
558 }
559 return !lessOrEqual, nil
560 }
561
562
563 func ge(arg1, arg2 reflect.Value) (bool, error) {
564
565 lessThan, err := lt(arg1, arg2)
566 if err != nil {
567 return false, err
568 }
569 return !lessThan, nil
570 }
571
572
573
574 var (
575 htmlQuot = []byte(""")
576 htmlApos = []byte("'")
577 htmlAmp = []byte("&")
578 htmlLt = []byte("<")
579 htmlGt = []byte(">")
580 htmlNull = []byte("\uFFFD")
581 )
582
583
584 func HTMLEscape(w io.Writer, b []byte) {
585 last := 0
586 for i, c := range b {
587 var html []byte
588 switch c {
589 case '\000':
590 html = htmlNull
591 case '"':
592 html = htmlQuot
593 case '\'':
594 html = htmlApos
595 case '&':
596 html = htmlAmp
597 case '<':
598 html = htmlLt
599 case '>':
600 html = htmlGt
601 default:
602 continue
603 }
604 w.Write(b[last:i])
605 w.Write(html)
606 last = i + 1
607 }
608 w.Write(b[last:])
609 }
610
611
612 func HTMLEscapeString(s string) string {
613
614 if !strings.ContainsAny(s, "'\"&<>\000") {
615 return s
616 }
617 var b bytes.Buffer
618 HTMLEscape(&b, []byte(s))
619 return b.String()
620 }
621
622
623
624 func HTMLEscaper(args ...interface{}) string {
625 return HTMLEscapeString(evalArgs(args))
626 }
627
628
629
630 var (
631 jsLowUni = []byte(`\u00`)
632 hex = []byte("0123456789ABCDEF")
633
634 jsBackslash = []byte(`\\`)
635 jsApos = []byte(`\'`)
636 jsQuot = []byte(`\"`)
637 jsLt = []byte(`\x3C`)
638 jsGt = []byte(`\x3E`)
639 )
640
641
642 func JSEscape(w io.Writer, b []byte) {
643 last := 0
644 for i := 0; i < len(b); i++ {
645 c := b[i]
646
647 if !jsIsSpecial(rune(c)) {
648
649 continue
650 }
651 w.Write(b[last:i])
652
653 if c < utf8.RuneSelf {
654
655
656 switch c {
657 case '\\':
658 w.Write(jsBackslash)
659 case '\'':
660 w.Write(jsApos)
661 case '"':
662 w.Write(jsQuot)
663 case '<':
664 w.Write(jsLt)
665 case '>':
666 w.Write(jsGt)
667 default:
668 w.Write(jsLowUni)
669 t, b := c>>4, c&0x0f
670 w.Write(hex[t : t+1])
671 w.Write(hex[b : b+1])
672 }
673 } else {
674
675 r, size := utf8.DecodeRune(b[i:])
676 if unicode.IsPrint(r) {
677 w.Write(b[i : i+size])
678 } else {
679 fmt.Fprintf(w, "\\u%04X", r)
680 }
681 i += size - 1
682 }
683 last = i + 1
684 }
685 w.Write(b[last:])
686 }
687
688
689 func JSEscapeString(s string) string {
690
691 if strings.IndexFunc(s, jsIsSpecial) < 0 {
692 return s
693 }
694 var b bytes.Buffer
695 JSEscape(&b, []byte(s))
696 return b.String()
697 }
698
699 func jsIsSpecial(r rune) bool {
700 switch r {
701 case '\\', '\'', '"', '<', '>':
702 return true
703 }
704 return r < ' ' || utf8.RuneSelf <= r
705 }
706
707
708
709 func JSEscaper(args ...interface{}) string {
710 return JSEscapeString(evalArgs(args))
711 }
712
713
714
715 func URLQueryEscaper(args ...interface{}) string {
716 return url.QueryEscape(evalArgs(args))
717 }
718
719
720
721
722
723
724 func evalArgs(args []interface{}) string {
725 ok := false
726 var s string
727
728 if len(args) == 1 {
729 s, ok = args[0].(string)
730 }
731 if !ok {
732 for i, arg := range args {
733 a, ok := printableValue(reflect.ValueOf(arg))
734 if ok {
735 args[i] = a
736 }
737 }
738 s = fmt.Sprint(args...)
739 }
740 return s
741 }
742
View as plain text