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