From 31a0fbd2283cc1dc174757359fc341ddfc9098c6 Mon Sep 17 00:00:00 2001 From: tidwall Date: Tue, 30 Mar 2021 07:17:01 -0700 Subject: [PATCH] Upgrade gjson --- go.mod | 6 +- go.sum | 9 +- vendor/github.com/tidwall/gjson/README.md | 10 +- vendor/github.com/tidwall/gjson/SYNTAX.md | 17 +- vendor/github.com/tidwall/gjson/gjson.go | 74 +++++---- vendor/github.com/tidwall/gjson/go.mod | 2 +- vendor/github.com/tidwall/gjson/go.sum | 6 +- vendor/github.com/tidwall/pretty/.travis.yml | 1 - vendor/github.com/tidwall/pretty/README.md | 43 ++++- vendor/github.com/tidwall/pretty/pretty.go | 158 +++++++++++++++++-- vendor/modules.txt | 4 +- 11 files changed, 260 insertions(+), 70 deletions(-) delete mode 100644 vendor/github.com/tidwall/pretty/.travis.yml diff --git a/go.mod b/go.mod index f40f8c65..e8f049c6 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/tidwall/tile38 -go 1.15 +go 1.16 require ( github.com/Shopify/sarama v1.27.2 @@ -17,9 +17,9 @@ require ( github.com/tidwall/buntdb v1.2.0 github.com/tidwall/geoindex v1.4.1 github.com/tidwall/geojson v1.2.4 - github.com/tidwall/gjson v1.6.8 + github.com/tidwall/gjson v1.7.4 github.com/tidwall/match v1.0.3 - github.com/tidwall/pretty v1.0.2 + github.com/tidwall/pretty v1.1.0 github.com/tidwall/redbench v0.1.0 github.com/tidwall/redcon v1.4.0 github.com/tidwall/resp v0.1.0 diff --git a/go.sum b/go.sum index c93b13b7..5841d2c1 100644 --- a/go.sum +++ b/go.sum @@ -83,7 +83,6 @@ github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8Bz github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mmcloughlin/geohash v0.10.0 h1:9w1HchfDfdeLc+jFEf/04D27KP7E2QmpDu52wPbJWRE= github.com/mmcloughlin/geohash v0.10.0/go.mod h1:oNZxQo5yWJh0eMQEP/8hwQuVx9Z9tjwFUqcTB1SmG0c= -github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/jwt v1.1.0 h1:+vOlgtM0ZsF46GbmUoadq0/2rChNS45gtxHEa3H1gqM= github.com/nats-io/jwt v1.1.0/go.mod h1:n3cvmLfBfnpV4JJRN7lRYCyZnw48ksGsbThGXEk4w9M= @@ -96,7 +95,6 @@ github.com/nats-io/nkeys v0.1.4 h1:aEsHIssIk6ETN5m2/MD8Y4B2X7FfXrBAUdkyRvbVYzA= github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/peterh/liner v1.2.1 h1:O4BlKaq/LWu6VRWmol4ByWfzx6MfXc5Op5HETyIy5yg= github.com/peterh/liner v1.2.1/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= @@ -128,8 +126,9 @@ github.com/tidwall/geoindex v1.4.1/go.mod h1:NQJQszWCH4+KlD0wY+mgQ2hK/GdSH+9+ZRk github.com/tidwall/geojson v1.2.4 h1:INKsEJULXKiKSuFQZQ7Vy3v9zchg0VPtcQl2+KeTlvc= github.com/tidwall/geojson v1.2.4/go.mod h1:ZaA93utbJL8CLGaJ5L/M8gV/YC81lvW3ydzo5fI7yp0= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= -github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w= github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= +github.com/tidwall/gjson v1.7.4 h1:19cchw8FOxkG5mdLRkGf9jqIqEyqdZhPqW60XfyFxk8= +github.com/tidwall/gjson v1.7.4/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= github.com/tidwall/grect v0.1.0 h1:ICcKWD5uu5A5fmxApGIa0QRvfGnSWKRd07POT08CQSA= github.com/tidwall/grect v0.1.0/go.mod h1:sa5O42oP6jWfTShL9ka6Sgmg3TgIK649veZe05B7+J8= github.com/tidwall/lotsa v1.0.1 h1:w4gpDvI7RdkgbMC0q5ndKqG2ffrwCgerUY/gM2TYkH4= @@ -137,8 +136,9 @@ github.com/tidwall/lotsa v1.0.1/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UM github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= +github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/redbench v0.1.0 h1:UZYUMhwMMObQRq5xU4SA3lmlJRztXzqtushDii+AmPo= github.com/tidwall/redbench v0.1.0/go.mod h1:zxcRGCq/JcqV48YjK9WxBNJL7JSpMzbLXaHvMcnanKQ= github.com/tidwall/redcon v1.4.0 h1:y2PmDD55STRdy4S98qP/Dn+gZG+cPVvIDi9BJV2aOwA= @@ -231,7 +231,6 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw= gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo= diff --git a/vendor/github.com/tidwall/gjson/README.md b/vendor/github.com/tidwall/gjson/README.md index 8553273a..55620142 100644 --- a/vendor/github.com/tidwall/gjson/README.md +++ b/vendor/github.com/tidwall/gjson/README.md @@ -14,6 +14,8 @@ It has features such as [one line retrieval](#get-a-value), [dot notation paths] Also check out [SJSON](https://github.com/tidwall/sjson) for modifying json, and the [JJ](https://github.com/tidwall/jj) command line tool. +For the Rust version go to [gjson.rs](https://github.com/tidwall/gjson.rs). + Getting Started =============== @@ -482,11 +484,3 @@ widget.text.onMouseUp ``` *These benchmarks were run on a MacBook Pro 15" 2.8 GHz Intel Core i7 using Go 1.8 and can be found [here](https://github.com/tidwall/gjson-benchmarks).* - - -## Contact -Josh Baker [@tidwall](http://twitter.com/tidwall) - -## License - -GJSON source code is available under the MIT [License](/LICENSE). diff --git a/vendor/github.com/tidwall/gjson/SYNTAX.md b/vendor/github.com/tidwall/gjson/SYNTAX.md index 5ea0407f..86235b9b 100644 --- a/vendor/github.com/tidwall/gjson/SYNTAX.md +++ b/vendor/github.com/tidwall/gjson/SYNTAX.md @@ -77,14 +77,21 @@ Special purpose characters, such as `.`, `*`, and `?` can be escaped with `\`. fav\.movie "Deer Hunter" ``` -You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in source code. +You'll also need to make sure that the `\` character is correctly escaped when hardcoding a path in you source code. ```go -res := gjson.Get(json, "fav\\.movie") // must escape the slash -res := gjson.Get(json, `fav\.movie`) // no need to escape the slash - +// Go +val := gjson.Get(json, "fav\\.movie") // must escape the slash +val := gjson.Get(json, `fav\.movie`) // no need to escape the slash ``` +```rust +// Rust +let val = gjson::get(json, "fav\\.movie") // must escape the slash +let val = gjson::get(json, r#"fav\.movie"#) // no need to escape the slash +``` + + ### Arrays The `#` character allows for digging into JSON Arrays. @@ -248,6 +255,8 @@ gjson.AddModifier("case", func(json, arg string) string { "children.@case:lower.@reverse" ["jack","alex","sara"] ``` +*Note: Custom modifiers are not yet available in the Rust version* + ### Multipaths Starting with v1.3.0, GJSON added the ability to join multiple paths together diff --git a/vendor/github.com/tidwall/gjson/gjson.go b/vendor/github.com/tidwall/gjson/gjson.go index 4f988d0d..7bb82e95 100644 --- a/vendor/github.com/tidwall/gjson/gjson.go +++ b/vendor/github.com/tidwall/gjson/gjson.go @@ -731,8 +731,13 @@ func parseArrayPath(path string) (r arrayPathResult) { } if path[i] == '.' { r.part = path[:i] - r.path = path[i+1:] - r.more = true + if !r.arrch && i < len(path)-1 && isDotPiperChar(path[i+1]) { + r.pipe = path[i+1:] + r.piped = true + } else { + r.path = path[i+1:] + r.more = true + } return } if path[i] == '#' { @@ -978,6 +983,11 @@ right: return s } +// peek at the next byte and see if it's a '@', '[', or '{'. +func isDotPiperChar(c byte) bool { + return !DisableModifiers && (c == '@' || c == '[' || c == '{') +} + type objectPathResult struct { part string path string @@ -996,12 +1006,8 @@ func parseObjectPath(path string) (r objectPathResult) { return } if path[i] == '.' { - // peek at the next byte and see if it's a '@', '[', or '{'. r.part = path[:i] - if !DisableModifiers && - i < len(path)-1 && - (path[i+1] == '@' || - path[i+1] == '[' || path[i+1] == '{') { + if i < len(path)-1 && isDotPiperChar(path[i+1]) { r.pipe = path[i+1:] r.piped = true } else { @@ -1031,14 +1037,11 @@ func parseObjectPath(path string) (r objectPathResult) { continue } else if path[i] == '.' { r.part = string(epart) - // peek at the next byte and see if it's a '@' modifier - if !DisableModifiers && - i < len(path)-1 && path[i+1] == '@' { + if i < len(path)-1 && isDotPiperChar(path[i+1]) { r.pipe = path[i+1:] r.piped = true } else { r.path = path[i+1:] - r.more = true } r.more = true return @@ -1403,7 +1406,6 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { } return false } - for i < len(c.json)+1 { if !rp.arrch { pmatch = partidx == h @@ -1605,10 +1607,17 @@ func parseArray(c *parseContext, i int, path string) (int, bool) { c.calcd = true return i + 1, true } - if len(multires) > 0 && !c.value.Exists() { - c.value = Result{ - Raw: string(append(multires, ']')), - Type: JSON, + if !c.value.Exists() { + if len(multires) > 0 { + c.value = Result{ + Raw: string(append(multires, ']')), + Type: JSON, + } + } else if rp.query.all { + c.value = Result{ + Raw: "[]", + Type: JSON, + } } } return i + 1, false @@ -2173,11 +2182,6 @@ func parseAny(json string, i int, hit bool) (int, Result, bool) { return i, res, false } -var ( // used for testing - testWatchForFallback bool - testLastWasFallback bool -) - // GetMany searches json for the multiple paths. // The return value is a Result array where the number of items // will be equal to the number of input paths. @@ -2378,6 +2382,12 @@ func validnumber(data []byte, i int) (outi int, ok bool) { // sign if data[i] == '-' { i++ + if i == len(data) { + return i, false + } + if data[i] < '0' || data[i] > '9' { + return i, false + } } // int if i == len(data) { @@ -2528,7 +2538,10 @@ func parseInt(s string) (n int64, ok bool) { return n, true } +// safeInt validates a given JSON number +// ensures it lies within the minimum and maximum representable JSON numbers func safeInt(f float64) (n int64, ok bool) { + // https://tc39.es/ecma262/#sec-number.min_safe_integer || https://tc39.es/ecma262/#sec-number.max_safe_integer if f < -9007199254740991 || f > 9007199254740991 { return 0, false } @@ -2739,19 +2752,24 @@ func modFlatten(json, arg string) string { out = append(out, '[') var idx int res.ForEach(func(_, value Result) bool { - if idx > 0 { - out = append(out, ',') - } + var raw string if value.IsArray() { if deep { - out = append(out, unwrap(modFlatten(value.Raw, arg))...) + raw = unwrap(modFlatten(value.Raw, arg)) } else { - out = append(out, unwrap(value.Raw)...) + raw = unwrap(value.Raw) } } else { - out = append(out, value.Raw...) + raw = value.Raw + } + raw = strings.TrimSpace(raw) + if len(raw) > 0 { + if idx > 0 { + out = append(out, ',') + } + out = append(out, raw...) + idx++ } - idx++ return true }) out = append(out, ']') diff --git a/vendor/github.com/tidwall/gjson/go.mod b/vendor/github.com/tidwall/gjson/go.mod index 30d18043..9853a309 100644 --- a/vendor/github.com/tidwall/gjson/go.mod +++ b/vendor/github.com/tidwall/gjson/go.mod @@ -4,5 +4,5 @@ go 1.12 require ( github.com/tidwall/match v1.0.3 - github.com/tidwall/pretty v1.0.2 + github.com/tidwall/pretty v1.1.0 ) diff --git a/vendor/github.com/tidwall/gjson/go.sum b/vendor/github.com/tidwall/gjson/go.sum index 1eb20140..739d1327 100644 --- a/vendor/github.com/tidwall/gjson/go.sum +++ b/vendor/github.com/tidwall/gjson/go.sum @@ -1,6 +1,4 @@ -github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= -github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= -github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= +github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= diff --git a/vendor/github.com/tidwall/pretty/.travis.yml b/vendor/github.com/tidwall/pretty/.travis.yml deleted file mode 100644 index 4f2ee4d9..00000000 --- a/vendor/github.com/tidwall/pretty/.travis.yml +++ /dev/null @@ -1 +0,0 @@ -language: go diff --git a/vendor/github.com/tidwall/pretty/README.md b/vendor/github.com/tidwall/pretty/README.md index 09884692..7a614223 100644 --- a/vendor/github.com/tidwall/pretty/README.md +++ b/vendor/github.com/tidwall/pretty/README.md @@ -1,8 +1,6 @@ # Pretty -[![Build Status](https://img.shields.io/travis/tidwall/pretty.svg?style=flat-square)](https://travis-ci.org/tidwall/prettty) -[![Coverage Status](https://img.shields.io/badge/coverage-100%25-brightgreen.svg?style=flat-square)](http://gocover.io/github.com/tidwall/pretty) -[![GoDoc](https://img.shields.io/badge/api-reference-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/tidwall/pretty) +[![GoDoc](https://img.shields.io/badge/api-reference-blue.svg?style=flat-square)](https://pkg.go.dev/github.com/tidwall/pretty) Pretty is a Go package that provides [fast](#performance) methods for formatting JSON for human readability, or to compact JSON for smaller payloads. @@ -81,6 +79,45 @@ Will format the json to: {"name":{"first":"Tom","last":"Anderson"},"age":37,"children":["Sara","Alex","Jack"],"fav.movie":"Deer Hunter","friends":[{"first":"Janet","last":"Murphy","age":44}]}``` ``` +## Spec + +Spec cleans comments and trailing commas from input JSON, converting it to +valid JSON per the official spec: https://tools.ietf.org/html/rfc8259 + +The resulting JSON will always be the same length as the input and it will +include all of the same line breaks at matching offsets. This is to ensure +the result can be later processed by a external parser and that that +parser will report messages or errors with the correct offsets. + +The following example uses a JSON document that has comments and trailing +commas and converts it prior to unmarshalling to using the standard Go +JSON library. + +```go + +data := ` +{ + /* Dev Machine */ + "dbInfo": { + "host": "localhost", + "port": 5432, // use full email address + "username": "josh", + "password": "pass123", // use a hashed password + } + /* Only SMTP Allowed */ + "emailInfo": { + "email": "josh@example.com", + "password": "pass123", + "smtp": "smpt.example.com", + } +} +` + +err := json.Unmarshal(pretty.Spec(data), &config) + +``` + + ## Customized output diff --git a/vendor/github.com/tidwall/pretty/pretty.go b/vendor/github.com/tidwall/pretty/pretty.go index 2951c610..7fa9d639 100644 --- a/vendor/github.com/tidwall/pretty/pretty.go +++ b/vendor/github.com/tidwall/pretty/pretty.go @@ -118,21 +118,27 @@ type pair struct { vstart, vend int } -type byKey struct { +type byKeyVal struct { sorted bool json []byte pairs []pair } -func (arr *byKey) Len() int { +func (arr *byKeyVal) Len() int { return len(arr.pairs) } -func (arr *byKey) Less(i, j int) bool { +func (arr *byKeyVal) Less(i, j int) bool { key1 := arr.json[arr.pairs[i].kstart+1 : arr.pairs[i].kend-1] key2 := arr.json[arr.pairs[j].kstart+1 : arr.pairs[j].kend-1] - return string(key1) < string(key2) + if string(key1) < string(key2) { + return true + } + if string(key1) > string(key2) { + return false + } + return arr.pairs[i].vstart < arr.pairs[j].vstart } -func (arr *byKey) Swap(i, j int) { +func (arr *byKeyVal) Swap(i, j int) { arr.pairs[i], arr.pairs[j] = arr.pairs[j], arr.pairs[i] arr.sorted = true } @@ -174,7 +180,11 @@ func appendPrettyObject(buf, json []byte, i int, open, close byte, pretty bool, } if n > 0 { nl = len(buf) - buf = append(buf, '\n') + if buf[nl-1] == ' ' { + buf[nl-1] = '\n' + } else { + buf = append(buf, '\n') + } } if buf[len(buf)-1] != open { buf = appendTabs(buf, prefix, indent, tabs) @@ -193,7 +203,11 @@ func appendPrettyObject(buf, json []byte, i int, open, close byte, pretty bool, var p pair if pretty { nl = len(buf) - buf = append(buf, '\n') + if buf[nl-1] == ' ' { + buf[nl-1] = '\n' + } else { + buf = append(buf, '\n') + } if open == '{' && sortkeys { p.kstart = i p.vstart = len(buf) @@ -235,8 +249,8 @@ func sortPairs(json, buf []byte, pairs []pair) []byte { } vstart := pairs[0].vstart vend := pairs[len(pairs)-1].vend - arr := byKey{false, json, pairs} - sort.Sort(&arr) + arr := byKeyVal{false, json, pairs} + sort.Stable(&arr) if !arr.sorted { return buf } @@ -305,6 +319,7 @@ func appendTabs(buf []byte, prefix, indent string, tabs int) []byte { type Style struct { Key, String, Number [2]string True, False, Null [2]string + Escape [2]string Append func(dst []byte, c byte) []byte } @@ -328,6 +343,7 @@ func init() { True: [2]string{"\x1B[96m", "\x1B[0m"}, False: [2]string{"\x1B[96m", "\x1B[0m"}, Null: [2]string{"\x1B[91m", "\x1B[0m"}, + Escape: [2]string{"\x1B[35m", "\x1B[0m"}, Append: func(dst []byte, c byte) []byte { if c < ' ' && (c != '\r' && c != '\n' && c != '\t' && c != '\v') { dst = append(dst, "\\u00"...) @@ -367,8 +383,39 @@ func Color(src []byte, style *Style) []byte { dst = append(dst, style.String[0]...) } dst = apnd(dst, '"') + esc := false + uesc := 0 for i = i + 1; i < len(src); i++ { - dst = apnd(dst, src[i]) + if src[i] == '\\' { + if key { + dst = append(dst, style.Key[1]...) + } else { + dst = append(dst, style.String[1]...) + } + dst = append(dst, style.Escape[0]...) + dst = apnd(dst, src[i]) + esc = true + if i+1 < len(src) && src[i+1] == 'u' { + uesc = 5 + } else { + uesc = 1 + } + } else if esc { + dst = apnd(dst, src[i]) + if uesc == 1 { + esc = false + dst = append(dst, style.Escape[1]...) + if key { + dst = append(dst, style.Key[0]...) + } else { + dst = append(dst, style.String[0]...) + } + } else { + uesc-- + } + } else { + dst = apnd(dst, src[i]) + } if src[i] == '"' { j := i - 1 for ; ; j-- { @@ -381,7 +428,9 @@ func Color(src []byte, style *Style) []byte { } } } - if key { + if esc { + dst = append(dst, style.Escape[1]...) + } else if key { dst = append(dst, style.Key[1]...) } else { dst = append(dst, style.String[1]...) @@ -434,3 +483,90 @@ func Color(src []byte, style *Style) []byte { } return dst } + +// Spec strips out comments and trailing commas and convert the input to a +// valid JSON per the official spec: https://tools.ietf.org/html/rfc8259 +// +// The resulting JSON will always be the same length as the input and it will +// include all of the same line breaks at matching offsets. This is to ensure +// the result can be later processed by a external parser and that that +// parser will report messages or errors with the correct offsets. +func Spec(src []byte) []byte { + return spec(src, nil) +} + +// SpecInPlace is the same as Spec, but this method reuses the input json +// buffer to avoid allocations. Do not use the original bytes slice upon return. +func SpecInPlace(src []byte) []byte { + return spec(src, src) +} + +func spec(src, dst []byte) []byte { + dst = dst[:0] + for i := 0; i < len(src); i++ { + if src[i] == '/' { + if i < len(src)-1 { + if src[i+1] == '/' { + dst = append(dst, ' ', ' ') + i += 2 + for ; i < len(src); i++ { + if src[i] == '\n' { + dst = append(dst, '\n') + break + } else if src[i] == '\t' || src[i] == '\r' { + dst = append(dst, src[i]) + } else { + dst = append(dst, ' ') + } + } + continue + } + if src[i+1] == '*' { + dst = append(dst, ' ', ' ') + i += 2 + for ; i < len(src)-1; i++ { + if src[i] == '*' && src[i+1] == '/' { + dst = append(dst, ' ', ' ') + i++ + break + } else if src[i] == '\n' || src[i] == '\t' || + src[i] == '\r' { + dst = append(dst, src[i]) + } else { + dst = append(dst, ' ') + } + } + continue + } + } + } + dst = append(dst, src[i]) + if src[i] == '"' { + for i = i + 1; i < len(src); i++ { + dst = append(dst, src[i]) + if src[i] == '"' { + j := i - 1 + for ; ; j-- { + if src[j] != '\\' { + break + } + } + if (j-i)%2 != 0 { + break + } + } + } + } else if src[i] == '}' || src[i] == ']' { + for j := len(dst) - 2; j >= 0; j-- { + if dst[j] <= ' ' { + continue + } + if dst[j] == ',' { + dst[j] = ' ' + } + break + } + } + } + return dst +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 016fc0b3..4031dc12 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -132,7 +132,7 @@ github.com/tidwall/geoindex/child github.com/tidwall/geojson github.com/tidwall/geojson/geo github.com/tidwall/geojson/geometry -# github.com/tidwall/gjson v1.6.8 +# github.com/tidwall/gjson v1.7.4 ## explicit github.com/tidwall/gjson # github.com/tidwall/grect v0.1.0 @@ -142,7 +142,7 @@ github.com/tidwall/lotsa # github.com/tidwall/match v1.0.3 ## explicit github.com/tidwall/match -# github.com/tidwall/pretty v1.0.2 +# github.com/tidwall/pretty v1.1.0 ## explicit github.com/tidwall/pretty # github.com/tidwall/redbench v0.1.0