github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/text/template/funcs.go (about) 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. 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 // 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. 24 // 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{} 31 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, 45 46 // Comparisons 47 "eq": eq, // == 48 "ge": ge, // >= 49 "gt": gt, // > 50 "le": le, // <= 51 "lt": lt, // < 52 "ne": ne, // != 53 } 54 55 var builtinFuncs = createValueFuncs(builtins) 56 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 62 } 63 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)) 69 } 70 v := reflect.ValueOf(fn) 71 if v.Kind() != reflect.Func { 72 panic("value for " + name + " not a function") 73 } 74 if !goodFunc(v.Type()) { 75 panic(fmt.Errorf("can't install method/function %q with %d results", name, v.Type().NumOut())) 76 } 77 out[name] = v 78 } 79 } 80 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 86 } 87 } 88 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 97 } 98 return false 99 } 100 101 // goodName reports whether the function name is a valid identifier. 102 func goodName(name string) bool { 103 if name == "" { 104 return false 105 } 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 113 } 114 } 115 return true 116 } 117 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 125 } 126 } 127 if fn := builtinFuncs[name]; fn.IsValid() { 128 return fn, true 129 } 130 return reflect.Value{}, false 131 } 132 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) 139 } 140 value = reflect.Zero(argType) 141 } 142 if !value.Type().AssignableTo(argType) { 143 return reflect.Value{}, fmt.Errorf("value has type %s; should be %s", value.Type(), argType) 144 } 145 return value, nil 146 } 147 148 // Indexing. 149 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 := item 155 if !v.IsValid() { 156 return reflect.Value{}, fmt.Errorf("index of untyped nil") 157 } 158 for _, index := range indices { 159 var isNil bool 160 if v, isNil = indirect(v); isNil { 161 return reflect.Value{}, fmt.Errorf("index of nil pointer") 162 } 163 switch v.Kind() { 164 case reflect.Array, reflect.Slice, reflect.String: 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 reflect.Value{}, fmt.Errorf("cannot index slice/array with nil") 173 default: 174 return reflect.Value{}, fmt.Errorf("cannot index slice/array with type %s", index.Type()) 175 } 176 if x < 0 || x >= int64(v.Len()) { 177 return reflect.Value{}, fmt.Errorf("index out of range: %d", x) 178 } 179 v = v.Index(int(x)) 180 case reflect.Map: 181 index, err := prepareArg(index, v.Type().Key()) 182 if err != nil { 183 return reflect.Value{}, err 184 } 185 if x := v.MapIndex(index); x.IsValid() { 186 v = x 187 } else { 188 v = reflect.Zero(v.Type().Elem()) 189 } 190 case reflect.Invalid: 191 // the loop holds invariant: v.IsValid() 192 panic("unreachable") 193 default: 194 return reflect.Value{}, fmt.Errorf("can't index item of type %s", v.Type()) 195 } 196 } 197 return v, nil 198 } 199 200 // Length 201 202 // length returns the length of the item, with an error if it has no defined length. 203 func length(item interface{}) (int, error) { 204 v := reflect.ValueOf(item) 205 if !v.IsValid() { 206 return 0, fmt.Errorf("len of untyped nil") 207 } 208 v, isNil := indirect(v) 209 if isNil { 210 return 0, fmt.Errorf("len of nil pointer") 211 } 212 switch v.Kind() { 213 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String: 214 return v.Len(), nil 215 } 216 return 0, fmt.Errorf("len of type %s", v.Type()) 217 } 218 219 // Function invocation 220 221 // call returns the result of evaluating the first argument as a function. 222 // The function must return 1 result, or 2 results, the second of which is an error. 223 func call(fn reflect.Value, args ...reflect.Value) (reflect.Value, error) { 224 v := fn 225 if !v.IsValid() { 226 return reflect.Value{}, fmt.Errorf("call of nil") 227 } 228 typ := v.Type() 229 if typ.Kind() != reflect.Func { 230 return reflect.Value{}, fmt.Errorf("non-function of type %s", typ) 231 } 232 if !goodFunc(typ) { 233 return reflect.Value{}, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut()) 234 } 235 numIn := typ.NumIn() 236 var dddType reflect.Type 237 if typ.IsVariadic() { 238 if len(args) < numIn-1 { 239 return reflect.Value{}, fmt.Errorf("wrong number of args: got %d want at least %d", len(args), numIn-1) 240 } 241 dddType = typ.In(numIn - 1).Elem() 242 } else { 243 if len(args) != numIn { 244 return reflect.Value{}, fmt.Errorf("wrong number of args: got %d want %d", len(args), numIn) 245 } 246 } 247 argv := make([]reflect.Value, len(args)) 248 for i, value := range args { 249 // Compute the expected type. Clumsy because of variadics. 250 var argType reflect.Type 251 if !typ.IsVariadic() || i < numIn-1 { 252 argType = typ.In(i) 253 } else { 254 argType = dddType 255 } 256 257 var err error 258 if argv[i], err = prepareArg(value, argType); err != nil { 259 return reflect.Value{}, fmt.Errorf("arg %d: %s", i, err) 260 } 261 } 262 result := v.Call(argv) 263 if len(result) == 2 && !result[1].IsNil() { 264 return result[0], result[1].Interface().(error) 265 } 266 return result[0], nil 267 } 268 269 // Boolean logic. 270 271 func truth(arg reflect.Value) bool { 272 t, _ := isTrue(arg) 273 return t 274 } 275 276 // and computes the Boolean AND of its arguments, returning 277 // the first false argument it encounters, or the last argument. 278 func and(arg0 reflect.Value, args ...reflect.Value) reflect.Value { 279 if !truth(arg0) { 280 return arg0 281 } 282 for i := range args { 283 arg0 = args[i] 284 if !truth(arg0) { 285 break 286 } 287 } 288 return arg0 289 } 290 291 // or computes the Boolean OR of its arguments, returning 292 // the first true argument it encounters, or the last argument. 293 func or(arg0 reflect.Value, args ...reflect.Value) reflect.Value { 294 if truth(arg0) { 295 return arg0 296 } 297 for i := range args { 298 arg0 = args[i] 299 if truth(arg0) { 300 break 301 } 302 } 303 return arg0 304 } 305 306 // not returns the Boolean negation of its argument. 307 func not(arg reflect.Value) bool { 308 return !truth(arg) 309 } 310 311 // Comparison. 312 313 // TODO: Perhaps allow comparison between signed and unsigned integers. 314 315 var ( 316 errBadComparisonType = errors.New("invalid type for comparison") 317 errBadComparison = errors.New("incompatible types for comparison") 318 errNoComparison = errors.New("missing argument for comparison") 319 ) 320 321 type kind int 322 323 const ( 324 invalidKind kind = iota 325 boolKind 326 complexKind 327 intKind 328 floatKind 329 stringKind 330 uintKind 331 ) 332 333 func basicKind(v reflect.Value) (kind, error) { 334 switch v.Kind() { 335 case reflect.Bool: 336 return boolKind, nil 337 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 338 return intKind, nil 339 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 340 return uintKind, nil 341 case reflect.Float32, reflect.Float64: 342 return floatKind, nil 343 case reflect.Complex64, reflect.Complex128: 344 return complexKind, nil 345 case reflect.String: 346 return stringKind, nil 347 } 348 return invalidKind, errBadComparisonType 349 } 350 351 // eq evaluates the comparison a == b || a == c || ... 352 func eq(arg1 reflect.Value, arg2 ...reflect.Value) (bool, error) { 353 v1 := arg1 354 k1, err := basicKind(v1) 355 if err != nil { 356 return false, err 357 } 358 if len(arg2) == 0 { 359 return false, errNoComparison 360 } 361 for _, v2 := range arg2 { 362 k2, err := basicKind(v2) 363 if err != nil { 364 return false, err 365 } 366 truth := false 367 if k1 != k2 { 368 // Special case: Can compare integer values regardless of type's sign. 369 switch { 370 case k1 == intKind && k2 == uintKind: 371 truth = v1.Int() >= 0 && uint64(v1.Int()) == v2.Uint() 372 case k1 == uintKind && k2 == intKind: 373 truth = v2.Int() >= 0 && v1.Uint() == uint64(v2.Int()) 374 default: 375 return false, errBadComparison 376 } 377 } else { 378 switch k1 { 379 case boolKind: 380 truth = v1.Bool() == v2.Bool() 381 case complexKind: 382 truth = v1.Complex() == v2.Complex() 383 case floatKind: 384 truth = v1.Float() == v2.Float() 385 case intKind: 386 truth = v1.Int() == v2.Int() 387 case stringKind: 388 truth = v1.String() == v2.String() 389 case uintKind: 390 truth = v1.Uint() == v2.Uint() 391 default: 392 panic("invalid kind") 393 } 394 } 395 if truth { 396 return true, nil 397 } 398 } 399 return false, nil 400 } 401 402 // ne evaluates the comparison a != b. 403 func ne(arg1, arg2 reflect.Value) (bool, error) { 404 // != is the inverse of ==. 405 equal, err := eq(arg1, arg2) 406 return !equal, err 407 } 408 409 // lt evaluates the comparison a < b. 410 func lt(v1, v2 reflect.Value) (bool, error) { 411 k1, err := basicKind(v1) 412 if err != nil { 413 return false, err 414 } 415 k2, err := basicKind(v2) 416 if err != nil { 417 return false, err 418 } 419 truth := false 420 if k1 != k2 { 421 // Special case: Can compare integer values regardless of type's sign. 422 switch { 423 case k1 == intKind && k2 == uintKind: 424 truth = v1.Int() < 0 || uint64(v1.Int()) < v2.Uint() 425 case k1 == uintKind && k2 == intKind: 426 truth = v2.Int() >= 0 && v1.Uint() < uint64(v2.Int()) 427 default: 428 return false, errBadComparison 429 } 430 } else { 431 switch k1 { 432 case boolKind, complexKind: 433 return false, errBadComparisonType 434 case floatKind: 435 truth = v1.Float() < v2.Float() 436 case intKind: 437 truth = v1.Int() < v2.Int() 438 case stringKind: 439 truth = v1.String() < v2.String() 440 case uintKind: 441 truth = v1.Uint() < v2.Uint() 442 default: 443 panic("invalid kind") 444 } 445 } 446 return truth, nil 447 } 448 449 // le evaluates the comparison <= b. 450 func le(arg1, arg2 reflect.Value) (bool, error) { 451 // <= is < or ==. 452 lessThan, err := lt(arg1, arg2) 453 if lessThan || err != nil { 454 return lessThan, err 455 } 456 return eq(arg1, arg2) 457 } 458 459 // gt evaluates the comparison a > b. 460 func gt(arg1, arg2 reflect.Value) (bool, error) { 461 // > is the inverse of <=. 462 lessOrEqual, err := le(arg1, arg2) 463 if err != nil { 464 return false, err 465 } 466 return !lessOrEqual, nil 467 } 468 469 // ge evaluates the comparison a >= b. 470 func ge(arg1, arg2 reflect.Value) (bool, error) { 471 // >= is the inverse of <. 472 lessThan, err := lt(arg1, arg2) 473 if err != nil { 474 return false, err 475 } 476 return !lessThan, nil 477 } 478 479 // HTML escaping. 480 481 var ( 482 htmlQuot = []byte(""") // shorter than """ 483 htmlApos = []byte("'") // shorter than "'" and apos was not in HTML until HTML5 484 htmlAmp = []byte("&") 485 htmlLt = []byte("<") 486 htmlGt = []byte(">") 487 ) 488 489 // HTMLEscape writes to w the escaped HTML equivalent of the plain text data b. 490 func HTMLEscape(w io.Writer, b []byte) { 491 last := 0 492 for i, c := range b { 493 var html []byte 494 switch c { 495 case '"': 496 html = htmlQuot 497 case '\'': 498 html = htmlApos 499 case '&': 500 html = htmlAmp 501 case '<': 502 html = htmlLt 503 case '>': 504 html = htmlGt 505 default: 506 continue 507 } 508 w.Write(b[last:i]) 509 w.Write(html) 510 last = i + 1 511 } 512 w.Write(b[last:]) 513 } 514 515 // HTMLEscapeString returns the escaped HTML equivalent of the plain text data s. 516 func HTMLEscapeString(s string) string { 517 // Avoid allocation if we can. 518 if !strings.ContainsAny(s, `'"&<>`) { 519 return s 520 } 521 var b bytes.Buffer 522 HTMLEscape(&b, []byte(s)) 523 return b.String() 524 } 525 526 // HTMLEscaper returns the escaped HTML equivalent of the textual 527 // representation of its arguments. 528 func HTMLEscaper(args ...interface{}) string { 529 return HTMLEscapeString(evalArgs(args)) 530 } 531 532 // JavaScript escaping. 533 534 var ( 535 jsLowUni = []byte(`\u00`) 536 hex = []byte("0123456789ABCDEF") 537 538 jsBackslash = []byte(`\\`) 539 jsApos = []byte(`\'`) 540 jsQuot = []byte(`\"`) 541 jsLt = []byte(`\x3C`) 542 jsGt = []byte(`\x3E`) 543 ) 544 545 // JSEscape writes to w the escaped JavaScript equivalent of the plain text data b. 546 func JSEscape(w io.Writer, b []byte) { 547 last := 0 548 for i := 0; i < len(b); i++ { 549 c := b[i] 550 551 if !jsIsSpecial(rune(c)) { 552 // fast path: nothing to do 553 continue 554 } 555 w.Write(b[last:i]) 556 557 if c < utf8.RuneSelf { 558 // Quotes, slashes and angle brackets get quoted. 559 // Control characters get written as \u00XX. 560 switch c { 561 case '\\': 562 w.Write(jsBackslash) 563 case '\'': 564 w.Write(jsApos) 565 case '"': 566 w.Write(jsQuot) 567 case '<': 568 w.Write(jsLt) 569 case '>': 570 w.Write(jsGt) 571 default: 572 w.Write(jsLowUni) 573 t, b := c>>4, c&0x0f 574 w.Write(hex[t : t+1]) 575 w.Write(hex[b : b+1]) 576 } 577 } else { 578 // Unicode rune. 579 r, size := utf8.DecodeRune(b[i:]) 580 if unicode.IsPrint(r) { 581 w.Write(b[i : i+size]) 582 } else { 583 fmt.Fprintf(w, "\\u%04X", r) 584 } 585 i += size - 1 586 } 587 last = i + 1 588 } 589 w.Write(b[last:]) 590 } 591 592 // JSEscapeString returns the escaped JavaScript equivalent of the plain text data s. 593 func JSEscapeString(s string) string { 594 // Avoid allocation if we can. 595 if strings.IndexFunc(s, jsIsSpecial) < 0 { 596 return s 597 } 598 var b bytes.Buffer 599 JSEscape(&b, []byte(s)) 600 return b.String() 601 } 602 603 func jsIsSpecial(r rune) bool { 604 switch r { 605 case '\\', '\'', '"', '<', '>': 606 return true 607 } 608 return r < ' ' || utf8.RuneSelf <= r 609 } 610 611 // JSEscaper returns the escaped JavaScript equivalent of the textual 612 // representation of its arguments. 613 func JSEscaper(args ...interface{}) string { 614 return JSEscapeString(evalArgs(args)) 615 } 616 617 // URLQueryEscaper returns the escaped value of the textual representation of 618 // its arguments in a form suitable for embedding in a URL query. 619 func URLQueryEscaper(args ...interface{}) string { 620 return url.QueryEscape(evalArgs(args)) 621 } 622 623 // evalArgs formats the list of arguments into a string. It is therefore equivalent to 624 // fmt.Sprint(args...) 625 // except that each argument is indirected (if a pointer), as required, 626 // using the same rules as the default string evaluation during template 627 // execution. 628 func evalArgs(args []interface{}) string { 629 ok := false 630 var s string 631 // Fast path for simple common case. 632 if len(args) == 1 { 633 s, ok = args[0].(string) 634 } 635 if !ok { 636 for i, arg := range args { 637 a, ok := printableValue(reflect.ValueOf(arg)) 638 if ok { 639 args[i] = a 640 } // else let fmt do its thing 641 } 642 s = fmt.Sprint(args...) 643 } 644 return s 645 }