From 15102ac3db19b4c829569af24db629dec371aff7 Mon Sep 17 00:00:00 2001 From: wangtf Date: Mon, 12 Aug 2019 15:14:33 +0800 Subject: [PATCH] add UnmarshalPartially --- decode.go | 43 +++++++++++++++++++++++++++++++++++++++++-- hjson_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/decode.go b/decode.go index e2bbe3e..d28eab6 100644 --- a/decode.go +++ b/decode.go @@ -117,7 +117,7 @@ func (p *hjsonParser) readString(allowML bool) (string, error) { return "", p.errAt("Bad escape \\" + string(p.ch)) } } else if p.ch == '\n' || p.ch == '\r' { - return "", p.errAt("Bad string containing newline"); + return "", p.errAt("Bad string containing newline") } else { res.WriteByte(p.ch) } @@ -425,7 +425,7 @@ func (p *hjsonParser) rootValue() (interface{}, error) { } // assume we have a root object without braces - res, err := p.checkTrailing(p.readObject(true)); + res, err := p.checkTrailing(p.readObject(true)) if err == nil { return res, nil } @@ -479,3 +479,42 @@ func Unmarshal(data []byte, v interface{}) (err error) { rv.Set(reflect.ValueOf(value)) return err } + +func (p *hjsonParser) rootValueWithTrail() (interface{}, error) { + // Braces for the root object are optional + + p.white() + switch p.ch { + case '{': + return p.readObject(false) + case '[': + return p.readArray() + } + + // assume we have a root object without braces + res, err := p.readObject(true) + if err == nil { + return res, nil + } + + // test if we are dealing with a single JSON value instead (true/false/null/num/"") + p.resetAt() + if res2, err2 := p.readValue(); err2 == nil { + return res2, nil + } + return res, err +} + +// UnmarshalPartially try to partially parse the Hjson-encoded data, +// return the value and the start position of unprocessed parts. +func UnmarshalPartially(data []byte) (v interface{}, next int, err error) { + parser := &hjsonParser{data, 0, ' '} + parser.resetAt() + + v, err = parser.rootValueWithTrail() + if err != nil { + return + } + next = parser.at + 1 + return +} diff --git a/hjson_test.go b/hjson_test.go index 113c3b2..d2f76d5 100644 --- a/hjson_test.go +++ b/hjson_test.go @@ -105,3 +105,34 @@ func TestInvalidDestinationType(t *testing.T) { panic("An error should occur") } } + +func TestUnmarshalPartially(t *testing.T) { + var src = ` + { + database: + { + host: 127.0.0.1 + port: 555 + } + } + @@there is sth cannot be parsed as hijson. + ` + v, next, err := UnmarshalPartially([]byte(src)) + if err != nil { + panic(err) + } + if next != strings.Index(src, "@") { + panic("wrong next value") + } + if v == nil { + panic("v is nil") + } + val, ok := v.(map[string]interface{}) + if !ok { + panic("v has wrong type") + } + _, ok = val["database"] + if !ok { + panic("v has wrong value") + } +}