From 08ec19535d9394afdaad279d28181cee7e4c3a51 Mon Sep 17 00:00:00 2001 From: Sangbum Kim Date: Fri, 13 Jul 2018 01:29:26 +0900 Subject: [PATCH] =?UTF-8?q?template=20=ED=95=A8=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tmpl/internal.go | 23 +++++++++++++++++ tmpl/map.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ tmpl/stub.s | 1 + 3 files changed, 90 insertions(+) create mode 100644 tmpl/internal.go create mode 100644 tmpl/map.go create mode 100644 tmpl/stub.s diff --git a/tmpl/internal.go b/tmpl/internal.go new file mode 100644 index 0000000..3112d40 --- /dev/null +++ b/tmpl/internal.go @@ -0,0 +1,23 @@ +package tmpl + +import ( + "reflect" + _ "unsafe" +) + +//go:linkname indirectInterface text/template.indirectInterface +//go:nosplit +func indirectInterface(v reflect.Value) reflect.Value + +//go:linkname truth text/template.truth +//go:nosplit +func truth(arg reflect.Value) bool + +//go:linkname isTrue text/template.isTrue +//go:nosplit +func isTrue(arg reflect.Value) (truth, ok bool) + +func evalTrue(val reflect.Value) (truth bool) { + truth, _ = isTrue(val) + return +} diff --git a/tmpl/map.go b/tmpl/map.go new file mode 100644 index 0000000..9bbdce5 --- /dev/null +++ b/tmpl/map.go @@ -0,0 +1,66 @@ +package tmpl + +import ( + "reflect" + _ "unsafe" +) + +type TmplMap struct { + reflect.Value +} + +func (m TmplMap) Keys() ([]reflect.Value) { + return m.MapKeys() +} + +func (m TmplMap) MapWithDefaults(arg0 reflect.Value, args ...reflect.Value) (v reflect.Value) { + if iarg0 := indirectInterface(arg0); evalTrue(iarg0) { + if v = m.MapIndex(iarg0); evalTrue(v) { + return + } + } + + for _, v = range args { + if truth(v) { + break + } + } + return +} + +func (m TmplMap) Map(arg0 reflect.Value, args ...reflect.Value) (v reflect.Value) { + if iarg0 := indirectInterface(arg0); evalTrue(iarg0) { + if v = m.MapIndex(iarg0); evalTrue(v) { + return + } + } + argLen := len(args) + if argLen == 0 { + return + } + keys, defaultValue := args[:argLen-1], args[argLen-1] + for _, k := range keys { + if ik := indirectInterface(k); !evalTrue(ik) { + } else if v = m.Value.MapIndex(ik); evalTrue(v) { + return + } + } + v = defaultValue + return +} + +func MakeMapFunc(arg ...reflect.Value) TmplMap { + if len(arg)%2 != 0 { + panic("bad makemap") + } + + m := reflect.MakeMapWithSize(reflect.TypeOf(map[interface{}]interface{}{}), len(arg)/2) + for i := 0; i < len(arg); i += 2 { + k, v := indirectInterface(arg[i]), indirectInterface(arg[i+1]) + if !(evalTrue(k) && evalTrue(v)) { + continue + } + m.SetMapIndex(k, v) + } + return TmplMap{m} +} diff --git a/tmpl/stub.s b/tmpl/stub.s new file mode 100644 index 0000000..34f84cf --- /dev/null +++ b/tmpl/stub.s @@ -0,0 +1 @@ +// make compiler happy \ No newline at end of file