github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/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 := indirectInterface(item) 155 if !v.IsValid() { 156 return reflect.Value{}, fmt.Errorf("index of untyped nil") 157 } 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") 163 } 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()) 176 } 177 if x < 0 || x >= int64(v.Len()) { 178 return reflect.Value{}, fmt.Errorf("index out of range: %d", x) 179 } 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 185 } 186 if x := v.MapIndex(index); x.IsValid() { 187 v = x 188 } else { 189 v = reflect.Zero(v.Type().Elem()) 190 } 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()) 196 } 197 } 198 return v, nil 199 } 200 201 // Length 202 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") 208 } 209 v, isNil := indirect(v) 210 if isNil { 211 return 0, fmt.Errorf("len of nil pointer") 212 } 213 switch v.Kind() { 214 case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice, reflect.String: 215 return v.Len(), nil 216 } 217 return 0, fmt.Errorf("len of type %s", v.Type()) 218 } 219 220 // Function invocation 221 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") 228 } 229 typ := v.Type() 230 if typ.Kind() != reflect.Func { 231 return reflect.Value{}, fmt.Errorf("non-function of type %s", typ) 232 } 233 if !goodFunc(typ) { 234 return reflect.Value{}, fmt.Errorf("function called with %d args; should be 1 or 2", typ.NumOut()) 235 } 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) 241 } 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) 246 } 247 } 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 257 } 258 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) 262 } 263 } 264 result := v.Call(argv) 265 if len(result) == 2 && !result[1].IsNil() { 266 return result[0], result[1].Interface().(error) 267 } 268 return result[0], nil 269 } 270 271 // Boolean logic. 272 273 func truth(arg reflect.Value) bool { 274 t, _ := isTrue(indirectInterface(arg)) 275 return t 276 } 277 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 283 } 284 for i := range args { 285 arg0 = args[i] 286 if !truth(arg0) { 287 break 288 } 289 } 290 return arg0 291 } 292 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 298 } 299 for i := range args { 300 arg0 = args[i] 301 if truth(arg0) { 302 break 303 } 304 } 305 return arg0 306 } 307 308 // not returns the Boolean negation of its argument. 309 func not(arg reflect.Value) bool { 310 return !truth(arg) 311 } 312 313 // Comparison. 314 315 // TODO: Perhaps allow comparison between signed and unsigned integers. 316 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") 321 ) 322 323 type kind int 324 325 const ( 326 invalidKind kind = iota 327 boolKind 328 complexKind 329 intKind 330 floatKind 331 stringKind 332 uintKind 333 ) 334 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 349 } 350 return invalidKind, errBadComparisonType 351 } 352 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 359 } 360 if len(arg2) == 0 { 361 return false, errNoComparison 362 } 363 for _, arg := range arg2 { 364 v2 := indirectInterface(arg) 365 k2, err := basicKind(v2) 366 if err != nil { 367 return false, err 368 } 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 379 } 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") 396 } 397 } 398 if truth { 399 return true, nil 400 } 401 } 402 return false, nil 403 } 404 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 410 } 411 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 418 } 419 v2 := indirectInterface(arg2) 420 k2, err := basicKind(v2) 421 if err != nil { 422 return false, err 423 } 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 434 } 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") 449 } 450 } 451 return truth, nil 452 } 453 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 460 } 461 return eq(arg1, arg2) 462 } 463 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 470 } 471 return !lessOrEqual, nil 472 } 473 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 480 } 481 return !lessThan, nil 482 } 483 484 // HTML escaping. 485 486 var ( 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") 493 ) 494 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 515 } 516 w.Write(b[last:i]) 517 w.Write(html) 518 last = i + 1 519 } 520 w.Write(b[last:]) 521 } 522 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 528 } 529 var b bytes.Buffer 530 HTMLEscape(&b, []byte(s)) 531 return b.String() 532 } 533 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)) 538 } 539 540 // JavaScript escaping. 541 542 var ( 543 jsLowUni = []byte(`\u00`) 544 hex = []byte("0123456789ABCDEF") 545 546 jsBackslash = []byte(`\\`) 547 jsApos = []byte(`\'`) 548 jsQuot = []byte(`\"`) 549 jsLt = []byte(`\x3C`) 550 jsGt = []byte(`\x3E`) 551 ) 552 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] 558 559 if !jsIsSpecial(rune(c)) { 560 // fast path: nothing to do 561 continue 562 } 563 w.Write(b[last:i]) 564 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]) 584 } 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) 592 } 593 i += size - 1 594 } 595 last = i + 1 596 } 597 w.Write(b[last:]) 598 } 599 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 605 } 606 var b bytes.Buffer 607 JSEscape(&b, []byte(s)) 608 return b.String() 609 } 610 611 func jsIsSpecial(r rune) bool { 612 switch r { 613 case '\\', '\'', '"', '<', '>': 614 return true 615 } 616 return r < ' ' || utf8.RuneSelf <= r 617 } 618 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)) 623 } 624 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)) 629 } 630 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) 642 } 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 649 } 650 s = fmt.Sprint(args...) 651 } 652 return s 653 }