|
@@ -9,8 +9,9 @@ package fasttemplate
|
|
|
import (
|
|
import (
|
|
|
"bytes"
|
|
"bytes"
|
|
|
"fmt"
|
|
"fmt"
|
|
|
- "github.com/valyala/bytebufferpool"
|
|
|
|
|
"io"
|
|
"io"
|
|
|
|
|
+
|
|
|
|
|
+ "github.com/valyala/bytebufferpool"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// ExecuteFunc calls f on each template tag (placeholder) occurrence.
|
|
// ExecuteFunc calls f on each template tag (placeholder) occurrence.
|
|
@@ -76,6 +77,22 @@ func Execute(template, startTag, endTag string, w io.Writer, m map[string]interf
|
|
|
return ExecuteFunc(template, startTag, endTag, w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
return ExecuteFunc(template, startTag, endTag, w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ExecuteStd works the same way as Execute, but keeps the unknown placeholders.
|
|
|
|
|
+// This can be used as a drop-in replacement for strings.Replacer
|
|
|
|
|
+//
|
|
|
|
|
+// Substitution map m may contain values with the following types:
|
|
|
|
|
+// * []byte - the fastest value type
|
|
|
|
|
+// * string - convenient value type
|
|
|
|
|
+// * TagFunc - flexible value type
|
|
|
|
|
+//
|
|
|
|
|
+// Returns the number of bytes written to w.
|
|
|
|
|
+//
|
|
|
|
|
+// This function is optimized for constantly changing templates.
|
|
|
|
|
+// Use Template.ExecuteStd for frozen templates.
|
|
|
|
|
+func ExecuteStd(template, startTag, endTag string, w io.Writer, m map[string]interface{}) (int64, error) {
|
|
|
|
|
+ return ExecuteFunc(template, startTag, endTag, w, func(w io.Writer, tag string) (int, error) { return keepUnknownTagFunc(w, startTag, endTag, tag, m) })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// ExecuteFuncString calls f on each template tag (placeholder) occurrence
|
|
// ExecuteFuncString calls f on each template tag (placeholder) occurrence
|
|
|
// and substitutes it with the data written to TagFunc's w.
|
|
// and substitutes it with the data written to TagFunc's w.
|
|
|
//
|
|
//
|
|
@@ -128,6 +145,20 @@ func ExecuteString(template, startTag, endTag string, m map[string]interface{})
|
|
|
return ExecuteFuncString(template, startTag, endTag, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
return ExecuteFuncString(template, startTag, endTag, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ExecuteStringStd works the same way as ExecuteString, but keeps the unknown placeholders.
|
|
|
|
|
+// This can be used as a drop-in replacement for strings.Replacer
|
|
|
|
|
+//
|
|
|
|
|
+// Substitution map m may contain values with the following types:
|
|
|
|
|
+// * []byte - the fastest value type
|
|
|
|
|
+// * string - convenient value type
|
|
|
|
|
+// * TagFunc - flexible value type
|
|
|
|
|
+//
|
|
|
|
|
+// This function is optimized for constantly changing templates.
|
|
|
|
|
+// Use Template.ExecuteStringStd for frozen templates.
|
|
|
|
|
+func ExecuteStringStd(template, startTag, endTag string, m map[string]interface{}) string {
|
|
|
|
|
+ return ExecuteFuncString(template, startTag, endTag, func(w io.Writer, tag string) (int, error) { return keepUnknownTagFunc(w, startTag, endTag, tag, m) })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Template implements simple template engine, which can be used for fast
|
|
// Template implements simple template engine, which can be used for fast
|
|
|
// tags' (aka placeholders) substitution.
|
|
// tags' (aka placeholders) substitution.
|
|
|
type Template struct {
|
|
type Template struct {
|
|
@@ -283,6 +314,19 @@ func (t *Template) Execute(w io.Writer, m map[string]interface{}) (int64, error)
|
|
|
return t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
return t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ExecuteStd works the same way as Execute, but keeps the unknown placeholders.
|
|
|
|
|
+// This can be used as a drop-in replacement for strings.Replacer
|
|
|
|
|
+//
|
|
|
|
|
+// Substitution map m may contain values with the following types:
|
|
|
|
|
+// * []byte - the fastest value type
|
|
|
|
|
+// * string - convenient value type
|
|
|
|
|
+// * TagFunc - flexible value type
|
|
|
|
|
+//
|
|
|
|
|
+// Returns the number of bytes written to w.
|
|
|
|
|
+func (t *Template) ExecuteStd(w io.Writer, m map[string]interface{}) (int64, error) {
|
|
|
|
|
+ return t.ExecuteFunc(w, func(w io.Writer, tag string) (int, error) { return keepUnknownTagFunc(w, t.startTag, t.endTag, tag, m) })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// ExecuteFuncString calls f on each template tag (placeholder) occurrence
|
|
// ExecuteFuncString calls f on each template tag (placeholder) occurrence
|
|
|
// and substitutes it with the data written to TagFunc's w.
|
|
// and substitutes it with the data written to TagFunc's w.
|
|
|
//
|
|
//
|
|
@@ -332,6 +376,20 @@ func (t *Template) ExecuteString(m map[string]interface{}) string {
|
|
|
return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { return stdTagFunc(w, tag, m) })
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ExecuteStringStd works the same way as ExecuteString, but keeps the unknown placeholders.
|
|
|
|
|
+// This can be used as a drop-in replacement for strings.Replacer
|
|
|
|
|
+//
|
|
|
|
|
+// Substitution map m may contain values with the following types:
|
|
|
|
|
+// * []byte - the fastest value type
|
|
|
|
|
+// * string - convenient value type
|
|
|
|
|
+// * TagFunc - flexible value type
|
|
|
|
|
+//
|
|
|
|
|
+// This function is optimized for frozen templates.
|
|
|
|
|
+// Use ExecuteStringStd for constantly changing templates.
|
|
|
|
|
+func (t *Template) ExecuteStringStd(m map[string]interface{}) string {
|
|
|
|
|
+ return t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { return keepUnknownTagFunc(w, t.startTag, t.endTag, tag, m) })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func stdTagFunc(w io.Writer, tag string, m map[string]interface{}) (int, error) {
|
|
func stdTagFunc(w io.Writer, tag string, m map[string]interface{}) (int, error) {
|
|
|
v := m[tag]
|
|
v := m[tag]
|
|
|
if v == nil {
|
|
if v == nil {
|
|
@@ -348,3 +406,32 @@ func stdTagFunc(w io.Writer, tag string, m map[string]interface{}) (int, error)
|
|
|
panic(fmt.Sprintf("tag=%q contains unexpected value type=%#v. Expected []byte, string or TagFunc", tag, v))
|
|
panic(fmt.Sprintf("tag=%q contains unexpected value type=%#v. Expected []byte, string or TagFunc", tag, v))
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+func keepUnknownTagFunc(w io.Writer, startTag, endTag, tag string, m map[string]interface{}) (int, error) {
|
|
|
|
|
+ v, ok := m[tag]
|
|
|
|
|
+ if !ok {
|
|
|
|
|
+ if _, err := w.Write(unsafeString2Bytes(startTag)); err != nil {
|
|
|
|
|
+ return 0, err
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := w.Write(unsafeString2Bytes(tag)); err != nil {
|
|
|
|
|
+ return 0, err
|
|
|
|
|
+ }
|
|
|
|
|
+ if _, err := w.Write(unsafeString2Bytes(endTag)); err != nil {
|
|
|
|
|
+ return 0, err
|
|
|
|
|
+ }
|
|
|
|
|
+ return len(startTag) + len(tag) + len(endTag), nil
|
|
|
|
|
+ }
|
|
|
|
|
+ if v == nil {
|
|
|
|
|
+ return 0, nil
|
|
|
|
|
+ }
|
|
|
|
|
+ switch value := v.(type) {
|
|
|
|
|
+ case []byte:
|
|
|
|
|
+ return w.Write(value)
|
|
|
|
|
+ case string:
|
|
|
|
|
+ return w.Write([]byte(value))
|
|
|
|
|
+ case TagFunc:
|
|
|
|
|
+ return value(w, tag)
|
|
|
|
|
+ default:
|
|
|
|
|
+ panic(fmt.Sprintf("tag=%q contains unexpected value type=%#v. Expected []byte, string or TagFunc", tag, v))
|
|
|
|
|
+ }
|
|
|
|
|
+}
|