From a6ea770365a2d261251a48e49c251e2236e6d676 Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Fri, 16 Jun 2017 00:10:05 +0800 Subject: [PATCH] #53 implement SetEscapeHtml --- feature_adapter.go | 90 +++++++--------------------------------- feature_config.go | 67 ++++++++++++++++++++++++++++++ jsoniter_adapter_test.go | 2 + 3 files changed, 83 insertions(+), 76 deletions(-) diff --git a/feature_adapter.go b/feature_adapter.go index eb9af88..76f1eb1 100644 --- a/feature_adapter.go +++ b/feature_adapter.go @@ -14,9 +14,7 @@ package jsoniter import ( "bytes" "encoding/json" - "errors" "io" - "reflect" "unsafe" ) @@ -25,41 +23,12 @@ import ( // Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v. // Refer to https://godoc.org/encoding/json#Unmarshal for more information func Unmarshal(data []byte, v interface{}) error { - data = data[:lastNotSpacePos(data)] - iter := ParseBytes(ConfigOfDefault, data) - typ := reflect.TypeOf(v) - if typ.Kind() != reflect.Ptr { - // return non-pointer error - return errors.New("the second param must be ptr type") - } - iter.ReadVal(v) - if iter.head == iter.tail { - iter.loadMore() - } - if iter.Error == io.EOF { - return nil - } - if iter.Error == nil { - iter.reportError("Unmarshal", "there are bytes left after unmarshal") - } - return iter.Error + return ConfigOfDefault.Unmarshal(data, v) } // UnmarshalAny adapts to func UnmarshalAny(data []byte) (Any, error) { - data = data[:lastNotSpacePos(data)] - iter := ParseBytes(ConfigOfDefault, data) - any := iter.ReadAny() - if iter.head == iter.tail { - iter.loadMore() - } - if iter.Error == io.EOF { - return any, nil - } - if iter.Error == nil { - iter.reportError("UnmarshalAny", "there are bytes left after unmarshal") - } - return any, iter.Error + return ConfigOfDefault.UnmarshalAny(data) } func lastNotSpacePos(data []byte) int { @@ -72,37 +41,11 @@ func lastNotSpacePos(data []byte) int { } func UnmarshalFromString(str string, v interface{}) error { - data := []byte(str) - data = data[:lastNotSpacePos(data)] - iter := ParseBytes(ConfigOfDefault, data) - iter.ReadVal(v) - if iter.head == iter.tail { - iter.loadMore() - } - if iter.Error == io.EOF { - return nil - } - if iter.Error == nil { - iter.reportError("UnmarshalFromString", "there are bytes left after unmarshal") - } - return iter.Error + return ConfigOfDefault.UnmarshalFromString(str, v) } func UnmarshalAnyFromString(str string) (Any, error) { - data := []byte(str) - data = data[:lastNotSpacePos(data)] - iter := ParseBytes(ConfigOfDefault, data) - any := iter.ReadAny() - if iter.head == iter.tail { - iter.loadMore() - } - if iter.Error == io.EOF { - return any, nil - } - if iter.Error == nil { - iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal") - } - return nil, iter.Error + return ConfigOfDefault.UnmarshalAnyFromString(str) } // Marshal adapts to json/encoding Marshal API @@ -110,20 +53,11 @@ func UnmarshalAnyFromString(str string) (Any, error) { // Marshal returns the JSON encoding of v, adapts to json/encoding Marshal API // Refer to https://godoc.org/encoding/json#Marshal for more information func Marshal(v interface{}) ([]byte, error) { - stream := NewStream(ConfigOfDefault, nil, 256) - stream.WriteVal(v) - if stream.Error != nil { - return nil, stream.Error - } - return stream.Buffer(), nil + return ConfigOfDefault.Marshal(v) } func MarshalToString(v interface{}) (string, error) { - buf, err := Marshal(v) - if err != nil { - return "", err - } - return string(buf), nil + return ConfigOfDefault.MarshalToString(v) } // NewDecoder adapts to json/stream NewDecoder API. @@ -133,8 +67,7 @@ func MarshalToString(v interface{}) (string, error) { // Instead of a json/encoding Decoder, an AdaptedDecoder is returned // Refer to https://godoc.org/encoding/json#NewDecoder for more information func NewDecoder(reader io.Reader) *AdaptedDecoder { - iter := Parse(ConfigOfDefault, reader, 512) - return &AdaptedDecoder{iter} + return ConfigOfDefault.NewDecoder(reader) } // AdaptedDecoder reads and decodes JSON values from an input stream. @@ -172,8 +105,7 @@ func (decoder *AdaptedDecoder) UseNumber() { } func NewEncoder(writer io.Writer) *AdaptedEncoder { - stream := NewStream(Config{}.Froze(), writer, 512) - return &AdaptedEncoder{stream} + return ConfigOfDefault.NewEncoder(writer) } type AdaptedEncoder struct { @@ -189,3 +121,9 @@ func (adapter *AdaptedEncoder) Encode(val interface{}) error { func (adapter *AdaptedEncoder) SetIndent(prefix, indent string) { adapter.stream.cfg.indentionStep = len(indent) } + +func (adapter *AdaptedEncoder) SetEscapeHTML(escapeHtml bool) { + config := adapter.stream.cfg.configBeforeFrozen + config.EscapeHtml = escapeHtml + adapter.stream.cfg = config.Froze() +} diff --git a/feature_config.go b/feature_config.go index ed70d75..a39b21b 100644 --- a/feature_config.go +++ b/feature_config.go @@ -5,6 +5,7 @@ import ( "reflect" "sync/atomic" "unsafe" + "errors" ) type Config struct { @@ -15,6 +16,7 @@ type Config struct { } type frozenConfig struct { + configBeforeFrozen Config indentionStep int decoderCache unsafe.Pointer encoderCache unsafe.Pointer @@ -43,6 +45,7 @@ func (cfg Config) Froze() *frozenConfig { if cfg.EscapeHtml { frozenConfig.escapeHtml() } + frozenConfig.configBeforeFrozen = cfg return frozenConfig } @@ -166,3 +169,67 @@ func (cfg *frozenConfig) UnmarshalFromString(str string, v interface{}) error { } return iter.Error } + +func (cfg *frozenConfig) NewEncoder(writer io.Writer) *AdaptedEncoder { + stream := NewStream(cfg, writer, 512) + return &AdaptedEncoder{stream} +} + +func (cfg *frozenConfig) NewDecoder(reader io.Reader) *AdaptedDecoder { + iter := Parse(cfg, reader, 512) + return &AdaptedDecoder{iter} +} + +func (cfg *frozenConfig) UnmarshalAnyFromString(str string) (Any, error) { + data := []byte(str) + data = data[:lastNotSpacePos(data)] + iter := ParseBytes(cfg, data) + any := iter.ReadAny() + if iter.head == iter.tail { + iter.loadMore() + } + if iter.Error == io.EOF { + return any, nil + } + if iter.Error == nil { + iter.reportError("UnmarshalAnyFromString", "there are bytes left after unmarshal") + } + return nil, iter.Error +} + +func (cfg *frozenConfig) UnmarshalAny(data []byte) (Any, error) { + data = data[:lastNotSpacePos(data)] + iter := ParseBytes(cfg, data) + any := iter.ReadAny() + if iter.head == iter.tail { + iter.loadMore() + } + if iter.Error == io.EOF { + return any, nil + } + if iter.Error == nil { + iter.reportError("UnmarshalAny", "there are bytes left after unmarshal") + } + return any, iter.Error +} + +func (cfg *frozenConfig) Unmarshal(data []byte, v interface{}) error { + data = data[:lastNotSpacePos(data)] + iter := ParseBytes(cfg, data) + typ := reflect.TypeOf(v) + if typ.Kind() != reflect.Ptr { + // return non-pointer error + return errors.New("the second param must be ptr type") + } + iter.ReadVal(v) + if iter.head == iter.tail { + iter.loadMore() + } + if iter.Error == io.EOF { + return nil + } + if iter.Error == nil { + iter.reportError("Unmarshal", "there are bytes left after unmarshal") + } + return iter.Error +} \ No newline at end of file diff --git a/jsoniter_adapter_test.go b/jsoniter_adapter_test.go index d16be40..a33cd4e 100644 --- a/jsoniter_adapter_test.go +++ b/jsoniter_adapter_test.go @@ -37,10 +37,12 @@ func Test_new_encoder(t *testing.T) { should := require.New(t) buf1 := &bytes.Buffer{} encoder1 := json.NewEncoder(buf1) + encoder1.SetEscapeHTML(false) encoder1.Encode([]int{1}) should.Equal("[1]\n", buf1.String()) buf2 := &bytes.Buffer{} encoder2 := NewEncoder(buf2) + encoder2.SetEscapeHTML(false) encoder2.Encode([]int{1}) should.Equal("[1]", buf2.String()) }