From 3a82defb408da2ff433bee235a4a9eb71f2769f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E8=B6=85?= <7546302+red_q@user.noreply.gitee.com>
Date: Thu, 27 Feb 2025 10:48:32 +0800
Subject: [PATCH] =?UTF-8?q?json=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
attack_event/fw.go | 29 +-
conn/http_req.go | 15 +-
go.mod | 2 +
go.sum | 14 +
.../Andrew-M-C/go.jsonvalue/CHANGELOG.md | 121 +
.../go.jsonvalue/CHANGELOG_zh-cn.md | 126 +
.../Andrew-M-C/go.jsonvalue/LICENSE | 101 +
.../Andrew-M-C/go.jsonvalue/README.md | 87 +
.../Andrew-M-C/go.jsonvalue/any_ltgo17.go | 3 +
.../Andrew-M-C/go.jsonvalue/codecov.yml | 8 +
.../Andrew-M-C/go.jsonvalue/compare.go | 136 +
.../Andrew-M-C/go.jsonvalue/conv.go | 201 ++
.../Andrew-M-C/go.jsonvalue/errors.go | 99 +
.../github.com/Andrew-M-C/go.jsonvalue/get.go | 552 ++++
.../Andrew-M-C/go.jsonvalue/import_export.go | 598 +++++
.../go.jsonvalue/insert_append_delete.go | 632 +++++
.../go.jsonvalue/insert_append_delete_must.go | 245 ++
.../go.jsonvalue/internal/buffer/buffer.go | 18 +
.../internal/buffer/buffer_impl.go | 32 +
.../internal/buffer/buffer_internal.go | 1 +
.../go.jsonvalue/internal/unsafe/unsafe.go | 18 +
.../Andrew-M-C/go.jsonvalue/iteration.go | 150 ++
.../Andrew-M-C/go.jsonvalue/jsonvalue.go | 598 +++++
.../go.jsonvalue/jsonvalue_internal.go | 112 +
.../Andrew-M-C/go.jsonvalue/marshal.go | 325 +++
.../go.jsonvalue/marshaler_unmarshaler.go | 44 +
.../github.com/Andrew-M-C/go.jsonvalue/new.go | 273 ++
.../Andrew-M-C/go.jsonvalue/option.go | 634 +++++
.../github.com/Andrew-M-C/go.jsonvalue/set.go | 412 +++
.../Andrew-M-C/go.jsonvalue/set_must.go | 162 ++
.../Andrew-M-C/go.jsonvalue/sort.go | 326 +++
.../Andrew-M-C/go.jsonvalue/unmarshal.go | 900 +++++++
.../github.com/shopspring/decimal/.gitignore | 9 +
.../shopspring/decimal/CHANGELOG.md | 76 +
vendor/github.com/shopspring/decimal/LICENSE | 45 +
.../github.com/shopspring/decimal/README.md | 139 +
vendor/github.com/shopspring/decimal/const.go | 63 +
.../shopspring/decimal/decimal-go.go | 415 +++
.../github.com/shopspring/decimal/decimal.go | 2339 +++++++++++++++++
.../github.com/shopspring/decimal/rounding.go | 160 ++
vendor/modules.txt | 8 +
41 files changed, 10209 insertions(+), 19 deletions(-)
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG.md
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG_zh-cn.md
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/LICENSE
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/README.md
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/any_ltgo17.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/codecov.yml
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/compare.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/conv.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/errors.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/get.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/import_export.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete_must.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_impl.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_internal.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/internal/unsafe/unsafe.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/iteration.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue_internal.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/marshal.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/marshaler_unmarshaler.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/new.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/option.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/set.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/set_must.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/sort.go
create mode 100644 vendor/github.com/Andrew-M-C/go.jsonvalue/unmarshal.go
create mode 100644 vendor/github.com/shopspring/decimal/.gitignore
create mode 100644 vendor/github.com/shopspring/decimal/CHANGELOG.md
create mode 100644 vendor/github.com/shopspring/decimal/LICENSE
create mode 100644 vendor/github.com/shopspring/decimal/README.md
create mode 100644 vendor/github.com/shopspring/decimal/const.go
create mode 100644 vendor/github.com/shopspring/decimal/decimal-go.go
create mode 100644 vendor/github.com/shopspring/decimal/decimal.go
create mode 100644 vendor/github.com/shopspring/decimal/rounding.go
diff --git a/attack_event/fw.go b/attack_event/fw.go
index b3082d6..b66117d 100644
--- a/attack_event/fw.go
+++ b/attack_event/fw.go
@@ -5,7 +5,6 @@ import (
"dt_automate/conn"
"dt_automate/tool"
"encoding/json"
- "fmt"
"log"
"net/url"
"strconv"
@@ -56,18 +55,15 @@ func Fw_event(cookieStr string) {
"referer": "https://11.2.68.146/wnm/frame/index.php",
"cookie": cookieStr,
}
- datas := conn.DT_POST("https://11.2.68.146/wnm/get.j", header, bytes.NewBufferString(values.Encode()))["NTOP"].(map[string]interface{})["LogPaging"]
- var a map[string]interface{}
- for v, k := range datas.([]interface{}) {
- b := k.(map[string]interface{})["OutputJSON"].(string)
- if err := json.Unmarshal([]byte(b), &a); err != nil {
- log.Fatalf("Failed to unmarshal JSON: %v", err)
- }
- fmt.Println(v, a)
- fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"])
+ body := conn.DT_POST("https://11.2.68.146/wnm/get.j", header, bytes.NewBufferString(values.Encode()))
+ var bodys Person
+ json.Unmarshal(body, &bodys)
+
+ for v, k := range bodys.LogPaging {
+ // fmt.Printf("序号:%d,攻击时间:[%s],安全域:%s-%s##攻击源IP:%s#目的源IP:%s:%s,攻击类型:%s,应用协议:%s,请求域名:%s\n", v, a["Time"], a["SrcZoneName"], a["DestZoneName"], a["SrcIPAddr"], a["DestIPAddr"], strconv.FormatFloat(a["DestPort"].(float64), 'f', 0, 64), a["ThreatName"], a["Application"], a["HttpHost"])
sheet.Cell("A" + strconv.Itoa(v+1)).SetString(strconv.Itoa(v)) // 第一列 (A1)
- sheet.Cell("B" + strconv.Itoa(v+1)).SetString(a["Time"].(string))
- sheet.Cell("C" + strconv.Itoa(v+1)).SetString(a["SrcZoneName"].(string))
+ sheet.Cell("B" + strconv.Itoa(v+1)).SetString(k.Time)
+ sheet.Cell("C" + strconv.Itoa(v+1)).SetString(k.SrcZoneName)
sheet.Cell("D" + strconv.Itoa(v+1)).SetString(a["DestZoneName"].(string))
sheet.Cell("E" + strconv.Itoa(v+1)).SetString(a["SrcIPAddr"].(string))
sheet.Cell("F" + strconv.Itoa(v+1)).SetString(a["DestIPAddr"].(string))
@@ -84,3 +80,12 @@ func Fw_event(cookieStr string) {
log.Fatalf("保存文件时出错: %s", err)
}
}
+
+type Person struct {
+ NTOP string `json:"ntop"`
+ LogPaging []LogPaging `json:"logpaging"`
+}
+type LogPaging struct {
+ Time string `json:"time"`
+ SrcZoneName string `json"srczonename"`
+}
diff --git a/conn/http_req.go b/conn/http_req.go
index debc4b0..be4085a 100644
--- a/conn/http_req.go
+++ b/conn/http_req.go
@@ -12,7 +12,7 @@ import (
// headers := map[string]string{
// "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
// }
-func DT_POST(urls string, headers map[string]string, bytess io.Reader) map[string]interface{} {
+func DT_POST(urls string, headers map[string]string, bytess io.Reader) []byte {
url, err := url.Parse(urls)
if err != nil {
log.Println(err)
@@ -52,12 +52,13 @@ func DT_POST(urls string, headers map[string]string, bytess io.Reader) map[strin
if err != nil {
log.Println(err)
}
- log.Println(string(body))
- var gcresp map[string]interface{}
- if err := ScanJson(resp, gcresp); err != nil {
- log.Println(err)
- }
- return gcresp
+ // log.Println(string(body))
+ // var gcresp map[string]interface{}
+ // if err := ScanJson(resp, gcresp); err != nil {
+ // log.Println(err)
+ // }
+
+ return body
}
// req 请求体 url 请求地址 headers请求头
diff --git a/go.mod b/go.mod
index f21b662..293984f 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module dt_automate
go 1.23.6
require (
+ github.com/Andrew-M-C/go.jsonvalue v1.4.1
github.com/Esword618/unioffice v1.4.1
github.com/go-sql-driver/mysql v1.9.0
github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c
@@ -19,6 +20,7 @@ require (
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/jezek/xgb v1.1.1 // indirect
github.com/lxn/win v0.0.0-20210218163916-a377121e959e // indirect
+ github.com/shopspring/decimal v1.4.0 // indirect
github.com/stretchr/testify v1.9.0 // indirect
golang.org/x/sys v0.28.0 // indirect
)
diff --git a/go.sum b/go.sum
index c758ab3..2b3b314 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
+github.com/Andrew-M-C/go.jsonvalue v1.4.1 h1:MGtqaKy5Z7Xi/hnWaeqWDMwno79uNRt0XoCGHa1pm74=
+github.com/Andrew-M-C/go.jsonvalue v1.4.1/go.mod h1:EsYbZ97LlOhGUs+7qTwZI9KaJrPe6nK8sEZKEqr70Ww=
github.com/Esword618/unioffice v1.4.1 h1:qdcC+FpAPfLU3/WbUoICt1WgDR0tDC9ZPmBx4g3LRXM=
github.com/Esword618/unioffice v1.4.1/go.mod h1:8BQw+FmXV1Xfu7UeEtwL8wdk8gfM1Ib0RHqklrRr764=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -18,8 +20,12 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jezek/xgb v1.1.1 h1:bE/r8ZZtSv7l9gk6nU0mYx51aXrvnyb44892TwSaqS4=
github.com/jezek/xgb v1.1.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c h1:1IlzDla/ZATV/FsRn1ETf7ir91PHS2mrd4VMunEtd9k=
github.com/kbinani/screenshot v0.0.0-20250118074034-a3924b7bbc8c/go.mod h1:Pmpz2BLf55auQZ67u3rvyI2vAQvNetkK/4zYUmpauZQ=
github.com/lxn/win v0.0.0-20210218163916-a377121e959e h1:H+t6A/QJMbhCSEH5rAuRxh+CtW96g0Or0Fxa9IKr4uc=
@@ -30,6 +36,12 @@ github.com/playwright-community/playwright-go v0.5001.0 h1:EY3oB+rU9cUp6CLHguWE8
github.com/playwright-community/playwright-go v0.5001.0/go.mod h1:kBNWs/w2aJ2ZUp1wEOOFLXgOqvppFngM5OS+qyhl+ZM=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
+github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
+github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
+github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
+github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
+github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
@@ -42,6 +54,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@@ -73,6 +86,7 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG.md b/vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG.md
new file mode 100644
index 0000000..0c27bf1
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG.md
@@ -0,0 +1,121 @@
+Change Log
+
+[中文](./CHANGELOG_zh-cn.md)
+
+- [v1.4.1](#v141)
+- [v1.4.0](#v140)
+- [v1.3.8](#v138)
+- [v1.3.7](#v137)
+- [v1.3.6](#v136)
+- [v1.3.5](#v135)
+- [v1.3.4](#v134)
+- [v1.3.3](#v133)
+- [v1.3.2](#v132)
+- [v1.3.1](#v131)
+- [v1.3.0](#v130)
+- [v1.2.1](#v121)
+- [v1.2.0](#v120)
+- [v1.1.1](#v111)
+
+## v1.4.1
+
+- Add `v.At(...).Set(...)` pattern, allowing putting keys ahead (comparing to `v.Set(...).At(...)`).
+
+## v1.4.0
+
+- Allow passing parameter with a single slice or array for Get, Set, Append, Insert, Delete methods.
+- Add GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual methods for number comparation.
+
+## v1.3.8
+
+- Fix Issue [#30](https://github.com/Andrew-M-C/go.jsonvalue/issues/30)
+
+## v1.3.7
+
+- Fix Issue [#29](https://github.com/Andrew-M-C/go.jsonvalue/issues/29)
+
+## v1.3.6
+
+- Fix a floating sign [bug](https://github.com/akbarfa49/go.jsonvalue/commit/278817)
+- Fix Issue [#27](https://github.com/Andrew-M-C/go.jsonvalue/issues/27)
+
+## v1.3.5
+
+- Fix Issue [#26](https://github.com/Andrew-M-C/go.jsonvalue/issues/26)
+
+## v1.3.4
+
+Release jsonvalue v1.3.4. Comparing to v1.3.3:
+
+- `*jsonvalue.V` type now implements following interfaces thus it can used directly in `encoding/json`:
+ - `json.Marshaler`、`json.Unmarshaler`
+ - `encoding.BinaryMarshaler`、`encoding.BinaryUnmarshaler`
+- Supports importing data types those implement `json.Marshaler` or `encoding.TextMarshaler` interfaces, just like `encoding/json` does.
+- Add `MustAdd`, `MustAppend`, `MustInsert`, `MustSet`, `MustDelete` methods. These methods will not return sub-values or errors.
+ - This will prevent golangci-lint warning of "return value is not used"
+- Bug fix: When invoking `Append(xxx).InTheBeginning()`, the sub-value was actually and faulty append to the end.
+- Pre-allocate some buffer and space when marshaling and unmarshaling. It will speed-up a little bit and save 40% alloc count by average.
+
+## v1.3.3
+
+Release jsonvalue v1.3.3. Comparing to v1.3.2:
+
+- Release Engligh [wiki](https://github.com/Andrew-M-C/go.jsonvalue/blob/master/docs/en/README.md).
+- Fix #19 and #22.
+
+## v1.3.2
+
+Release jsonvalue 1.3.2. Comparing to v1.3.1, [#17](https://github.com/Andrew-M-C/go.jsonvalue/issues/17) is fixed.
+
+## v1.3.1
+
+Release jsonvalue 1.3.1. Comparing to v1.3.0:
+
+- It is available to get key sequences of an unmarshaled object JSON
+- Supporting marshal object by key sequence of when they are set.
+- All invisible ASCII characters will be escaped in `\u00XX` format.
+
+## v1.3.0
+
+Release v1.3.0. Comparing to v1.2.x:
+
+- No longer escape % symbol by default.
+- Add `Import` and `Export` function to support conversion between Go standard types and jsonvalue.
+- Support generics-like operations in `Set, Append, Insert, Add, New` functions, which allows programmers to set any legal types without specifying types explicitly.
+- Add `OptIndent` to support indent in marshaling.
+
+## v1.2.1
+
+Release v1.2.1. Comparing to v1.2.0:
+
+- Support not escaping slash symbol / in marshaling. Please refer to `OptEscapeSlash` function.
+- Support not escaping several HTML symbols in marshaling (issue #13). Please refer to OptEscapeHTML function.
+- Support not escaping unicodes greater than `\u00FF` in marshaling. Please refer to OptUTF8 function.
+- Support children-auto-generating in `Append(...).InTheBeginning()` and `Append(...).InTheEnd()`. But keep in mind that Insert operations remains not doing that.
+- You can override default marshaling options from now on. Please refer to `SetDefaultMarshalOptions` function.
+
+Other changes:
+
+- Instead of Travis-CI, I will use Github Actions in order to generate go test reports from now on.
+
+## v1.2.0
+
+Release v1.2.0, comparing to v1.1.1:
+
+- Fix the bug that float-pointed numbers with scientific notation format are not supported. ([issue #8](https://github.com/Andrew-M-C/go.jsonvalue/issues/8))
+- Add detailed wiki written in simplified Chinese. If you need English one, please leave me an issue.
+- Deprecate `Opt{}` for additional options, and replace with `OptXxx()` functions.
+- A first non-forward-compatible feature is released: Parameter formats for `NewFloat64` and `NewFloat32` is changed.
+ - If you want to specify format of float-pointed numbers, please use `NewFloat64f` and `NewFloat32f` instead.
+- Add `ForRangeArr` and `ForRangeObj` functions, deprecating `IterArray` and `IterObject`.
+- Support `SetEscapeHTML`. ([issue11](https://github.com/Andrew-M-C/go.jsonvalue/issues/11))
+- Support converting number to legal JSON data when they are `+/-NaN` and `+/-Inf`.
+
+## v1.1.1
+
+Release v1.1.1, comparing to v1.1.0:
+
+- All functions will NOT return nil `*jsonvalue.V` object instead of an instance with `NotExist` type when error occurs.
+ - Therefore, programmers can use the returned instance for shorter operations.
+- Supports `MustGet()` function, without error returning.
+- Supports `String()` for `ValueType` type
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG_zh-cn.md b/vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG_zh-cn.md
new file mode 100644
index 0000000..7aa9e2b
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/CHANGELOG_zh-cn.md
@@ -0,0 +1,126 @@
+变更日志
+
+[English](./CHANGELOG.md)
+
+- [v1.4.1](#v141)
+- [v1.4.0](#v140)
+- [v1.3.8](#v138)
+- [v1.3.7](#v137)
+- [v1.3.6](#v136)
+- [v1.3.5](#v135)
+- [v1.3.4](#v134)
+- [v1.3.3](#v133)
+- [v1.3.2](#v132)
+- [v1.3.1](#v131)
+- [v1.3.0](#v130)
+- [v1.2.1](#v121)
+- [v1.2.0](#v120)
+- [v1.1.1](#v111)
+
+## v1.4.1
+
+- 新增 `v.At(...).Set(...)` 模式, 相比 `v.Set(...).At(...)` 模式不同的是将 key 放在前面
+
+## v1.4.0
+
+- 在 Get, Set, Append, Insert, Delete 等方法中, 允许传递一个切片参数, 用来标识 key 链
+- 添加 GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual 方法用于数字比较
+
+## v1.3.8
+
+- 修复 Issue [#30](https://github.com/Andrew-M-C/go.jsonvalue/issues/30)
+
+## v1.3.7
+
+- 修复 Issue [#29](https://github.com/Andrew-M-C/go.jsonvalue/issues/29)
+
+## v1.3.6
+
+- 修复一个浮点数符号的 [bug](https://github.com/akbarfa49/go.jsonvalue/commit/278817)
+- 修复 Issue [#27](https://github.com/Andrew-M-C/go.jsonvalue/issues/27)
+
+## v1.3.5
+
+- 修复 Issue [#26](https://github.com/Andrew-M-C/go.jsonvalue/issues/26)
+
+## v1.3.4
+
+发布 jsonvalue v1.3.4,相比 v1.3.3:
+
+- 添加 `*jsonvalue.V` 对以下接口的支持, 使之可以适配 `encoding/json`:
+ - `json.Marshaler`、`json.Unmarshaler`
+ - `encoding.BinaryMarshaler`、`encoding.BinaryUnmarshaler`
+- `Import` 和 `New` 函数支持导入实现了 `json.Marshaler` 和 `encoding.TextMarshaler` 的数据类型, 就像 `encoding/json` 一样 ([#24](https://github.com/Andrew-M-C/go.jsonvalue/issues/24))
+- 添加 `MustAdd`, `MustAppend`, `MustInsert`, `MustSet`, `MustDelete` 等方法, 这些方法不返回子值和 error 信息
+ - 可以避免 golangci-lint 的警告提示
+- Bug 修复: 当 `Append(xxx).InTheBeginning()` 时, 实际上追加到了末尾
+- 在 Unmarshal 时, 通过预估对象 / 数组大小的方式预创建空间, 略微提升一点点速度, 以及节省平均约 40% 的 alloc 数
+
+## v1.3.3
+
+发布 jsonvalue v1.3.3,相比 v1.3.2:
+
+- 发布英文 [wiki](https://github.com/Andrew-M-C/go.jsonvalue/blob/master/docs/en/README.md)。
+- 修复了 #19 和 #22。
+
+## v1.3.2
+
+发布 jsonvalue 1.3.2,相比 1.3.1,主要是修复了 [#17](https://github.com/Andrew-M-C/go.jsonvalue/issues/17)。
+
+## v1.3.1
+
+发布 jsonvalue 1.3.1,相比 1.3.0,改动如下:
+
+- 支持获取 object 类型的键(key)的顺序
+- 按照 key 被设置的顺序进行 object 的序列化
+- 当序列化时,如果遇到 ASCII 的非可打印字符(包括控制字符),均进行 `\u00XX` 转义
+
+具体说明情参见 [wiki](https://github.com/Andrew-M-C/go.jsonvalue/blob/feature/v1.3.0/docs/zh-cn/12_new_feature.md)
+
+## v1.3.0
+
+发布 v1.3.0,相比 v1.2.x,改动如下:
+
+- 不再默认转义 % 字符
+- 支持与原生 json 的转换,也即支持从 `struct` 和其他类型中导入为 jsonvalue 类型,也支持将 jsonvalue 导出到 Go 标准类型中
+- 支持类泛型操作,最直接的影响就是 `Set, Append, Insert, Add, New` 等函数可以传入任意类型
+- 新增 `OptIndent` 函数以支持可视化锁进
+
+具体说明情参见 [wiki](https://github.com/Andrew-M-C/go.jsonvalue/blob/feature/v1.3.0/docs/zh-cn/12_new_feature.md)
+
+## v1.2.1
+
+发布 v1.2.1,相比 v1.2.1,改动如下:
+
+- Marshal 时,允许不转义斜杠符号 '/',参见 `OptEscapeSlash` 函数。
+- Marshal 时,允许不转义几个 HTML 关键符号 (issue #13)。参见 OptEscapeHTML 函数
+- Marshal 时,对于大于 `\u00FF` 的字符,允许保留 UTF-8 编码,而不进行转义。参见 OptUTF8 函数
+- `Append(...).InTheBeginning()` 和 `Append(...).InTheEnd()` 操作时,支持自动创建不存在的层级。但 insert 操作依然不会自动创建,这一点请留意
+- 支持设置默认序列化选项,请参见 SetDefaultMarshalOptions 函数
+
+其他变更:
+
+- CI 弃用 Travis-CI,改用 Github Actions
+
+## v1.2.0
+
+发布 v1.2.0,相比 v1.1.1,改动如下:
+
+- 修复不支持科学计数法浮点数的 bug([issue #8](https://github.com/Andrew-M-C/go.jsonvalue/issues/8))
+- 添加详细的中文 [wiki](https://github.com/Andrew-M-C/go.jsonvalue/blob/master/docs/zh-cn/README.md)。
+- Marshal 时的额外参数配置,原使用的是 `Opt` 结构体,现推荐改为使用一个或多个 `OptXxx()` 函数
+- 发布第一个不向前兼容的变更: 修改 `NewFloat64` 和 `NewFloat32` 的入参
+ - 原函数的 `prec` 变量及相关功能改由 `NewFloat64f` 和 `NewFloat32f` 承担。
+- 添加 `ForRangeArr` 和 `ForRangeObj` 以取代 `IterArray` 和 `IterObject` 函数,参见 [wiki](https://github.com/Andrew-M-C/go.jsonvalue/blob/master/docs/zh-cn/05_iteration.md#%E6%A6%82%E8%BF%B0)
+- 支持 `SetEscapeHTML`([issue11](https://github.com/Andrew-M-C/go.jsonvalue/issues/11))
+- 当浮点值中出现 `+/-NaN` 和 `+/-Inf` 时,支持进行特殊转换以符合 JSON 标准
+
+## v1.1.1
+
+发布 v1.1.1,相比 v1.1.0,变更如下:
+
+- 无论是否错误,所有返回 `*jsonvalue.V` 的函数都不会返回 nil。如果错误发生,那么至少会返回一个有效的 `*V` 实例,但是 `Type` 等于 `NotExist`
+ - 这样一来,程序员可以在代码中放心地直接使用返回的 *V 对象,简化代码,而忽略不必要的错误检查。
+- 支持 `MustGet` 函数,只返回 `*V` 而不返回 error 变量,便于一些级联的代码。
+- `ValueType` 类型支持 `String()` 函数。
+
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/LICENSE b/vendor/github.com/Andrew-M-C/go.jsonvalue/LICENSE
new file mode 100644
index 0000000..f2f1710
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/LICENSE
@@ -0,0 +1,101 @@
+MIT License
+
+Copyright (c) 2019-2024 Andrew Min Chang
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+Other dependencies and licenses:
+
+github.com/shopspring/decimal
+--------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Spring, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+- Based on https://github.com/oguzbilgic/fpd, which has the following license:
+"""
+The MIT License (MIT)
+
+Copyright (c) 2013 Oguz Bilgic
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"""
+
+github.com/smartystreets/goconvey
+--------------------------------------------------------------------
+
+MIT License
+
+Copyright (c) 2022 Smarty
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+Software, and to permit persons to whom the Software is furnished to do so, subject
+to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+NOTE: Various optional and subordinate components carry their own licensing
+requirements and restrictions. Use of those components is subject to the terms
+and conditions outlined the respective license of each component.
+
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/README.md b/vendor/github.com/Andrew-M-C/go.jsonvalue/README.md
new file mode 100644
index 0000000..aadd536
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/README.md
@@ -0,0 +1,87 @@
+# Jsonvalue - A Fast and Convenient Alternation of Go map[string]interface{}
+
+[](https://github.com/Andrew-M-C/go.jsonvalue/actions/workflows/go_test_general.yml)
+[](https://codecov.io/gh/Andrew-M-C/go.jsonvalue)
+[](https://goreportcard.com/report/github.com/Andrew-M-C/go.jsonvalue)
+[](https://codebeat.co/projects/github-com-andrew-m-c-go-jsonvalue-master)
+
+[](https://pkg.go.dev/github.com/Andrew-M-C/go.jsonvalue@v1.4.0)
+[](https://github.com/Andrew-M-C/go.jsonvalue/tree/v1.4.0)
+[](https://opensource.org/license/MIT)
+
+- [Wiki](./docs/en/README.md)
+- [中文版](./docs/zh-cn/README.md)
+
+Package **jsonvalue** is for handling unstructured JSON data or customizing JSON marshaling. It is far more faster and convenient than using `interface{}` with `encoding/json`.
+
+Please refer to [pkg site](https://pkg.go.dev/github.com/Andrew-M-C/go.jsonvalue) or [wiki](./docs/en/README.md) for detailed usage and examples.
+
+Especially, please check for jsonvalue's [programming scenarios](./docs/en/10_scenarios.md).
+
+## Import
+
+Use following statements to import jsonvalue:
+
+```go
+import (
+ jsonvalue "github.com/Andrew-M-C/go.jsonvalue"
+)
+```
+
+## Quick Start
+
+Sometimes we want to create a complex JSON object like:
+
+```json
+{
+ "someObject": {
+ "someObject": {
+ "someObject": {
+ "message": "Hello, JSON!"
+ }
+ }
+ }
+}
+```
+
+With `jsonvalue`, It is quite simple to implement this:
+
+```go
+ v := jsonvalue.NewObject()
+ v.MustSet("Hello, JSON").At("someObject", "someObject", "someObject", "message")
+ fmt.Println(v.MustMarshalString())
+ // Output:
+ // {"someObject":{"someObject":{"someObject":{"message":"Hello, JSON!"}}}
+```
+
+Similarly, it is quite easy to create sub-arrays like:
+
+```json
+[
+ {
+ "someArray": [
+ "Hello, JSON!"
+ ]
+ }
+]
+```
+
+```go
+ v := jsonvalue.NewArray()
+ v.MustSet("Hello, JSON").At(0, "someObject", 0)
+ fmt.Println(v.MustMarshalString())
+ // Output:
+ // [{"someObject":["Hello, JSON"]}]
+```
+
+In opposite, to parse and read the first JSON above, you can use jsonvalue like this:
+
+```go
+ const raw = `{"someObject": {"someObject": {"someObject": {"message": "Hello, JSON!"}}}}`
+ s := jsonvalue.MustUnmarshalString(s).GetString("someObject", "someObject", "someObject", "message")
+ fmt.Println(s)
+ // Output:
+ // Hello, JSON!
+```
+
+However, it is quite complex and annoying in automatically creating array. I strongly suggest using `SetArray()` to create the array first, then use `Append()` or `Insert()` to set array elements. Please refer go [godoc](https://godoc.org/github.com/Andrew-M-C/go.jsonvalue) or [Wiki](./docs/en/README.md).
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/any_ltgo17.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/any_ltgo17.go
new file mode 100644
index 0000000..a3ad8b3
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/any_ltgo17.go
@@ -0,0 +1,3 @@
+package jsonvalue
+
+type any = interface{}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/codecov.yml b/vendor/github.com/Andrew-M-C/go.jsonvalue/codecov.yml
new file mode 100644
index 0000000..4d8ce6f
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/codecov.yml
@@ -0,0 +1,8 @@
+codecov:
+ bot: laplacezhang@126.com
+
+coverage:
+ round: down
+ range: "95..97"
+ precision: 2
+
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/compare.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/compare.go
new file mode 100644
index 0000000..9f7f8b2
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/compare.go
@@ -0,0 +1,136 @@
+package jsonvalue
+
+import (
+ "bytes"
+
+ "github.com/shopspring/decimal"
+)
+
+// GreaterThan returns whether v is greater than another value.
+//
+// Both values should be number type, otherwise false will be returned.
+func (v *V) GreaterThan(another *V) bool {
+ res, _ := greaterThan(v, another)
+ return res
+}
+
+// GreaterThanOrEqual returns whether v is greater than or equal to another value.
+//
+// Both values should be number type, otherwise false will be returned.
+func (v *V) GreaterThanOrEqual(another *V) bool {
+ res, _ := greaterOrEqualThan(v, another)
+ return res
+}
+
+// LessThan returns whether v is less than another value.
+//
+// Both values should be number type, otherwise false will be returned.
+func (v *V) LessThan(another *V) bool {
+ res, ok := greaterOrEqualThan(v, another)
+ if !ok {
+ return false
+ }
+ return !res
+}
+
+// LessThanOrEqual returns whether v is less than or equal to another value.
+//
+// Both values should be number type, otherwise false will be returned.
+func (v *V) LessThanOrEqual(another *V) bool {
+ res, ok := greaterThan(v, another)
+ if !ok {
+ return false
+ }
+ return !res
+}
+
+func greaterThan(left, right *V) (result, ok bool) {
+ if left.valueType != Number || right.valueType != Number {
+ return false, false
+ }
+ a1, _ := decimal.NewFromString(string(left.srcByte))
+ a2, _ := decimal.NewFromString(string(right.srcByte))
+ return a1.GreaterThan(a2), true
+}
+
+func greaterOrEqualThan(left, right *V) (result, ok bool) {
+ if left.valueType != Number || right.valueType != Number {
+ return false, false
+ }
+ if bytes.Equal(left.srcByte, right.srcByte) {
+ return true, true
+ }
+ a1, _ := decimal.NewFromString(string(left.srcByte))
+ a2, _ := decimal.NewFromString(string(right.srcByte))
+ return a1.GreaterThanOrEqual(a2), true
+}
+
+// Equal shows whether the content of two JSON values equal to each other.
+//
+// Equal 判断两个 JSON 的内容是否相等
+func (v *V) Equal(another *V) bool {
+ if v == nil || another == nil {
+ return false
+ }
+ if v.valueType != another.valueType {
+ return false
+ }
+
+ switch v.valueType {
+ default: // including NotExist, Unknown
+ return false
+ case String:
+ return v.valueStr == another.valueStr
+ case Number:
+ return numberEqual(v, another)
+ case Object:
+ return objectEqual(v, another)
+ case Array:
+ return arrayEqual(v, another)
+ case Boolean:
+ return v.valueBool == another.valueBool
+ case Null:
+ return true
+ }
+}
+
+func numberEqual(left, right *V) bool {
+ if bytes.Equal(left.srcByte, right.srcByte) {
+ return true
+ }
+
+ d1, _ := decimal.NewFromString(string(left.srcByte))
+ d2, _ := decimal.NewFromString(string(right.srcByte))
+ return d1.Equal(d2)
+}
+
+func objectEqual(left, right *V) bool {
+ if len(left.children.object) != len(right.children.object) {
+ return false
+ }
+
+ for k, leftChild := range left.children.object {
+ rightChild, exist := right.children.object[k]
+ if !exist {
+ return false
+ }
+ if !leftChild.v.Equal(rightChild.v) {
+ return false
+ }
+ }
+ return true
+}
+
+func arrayEqual(left, right *V) bool {
+ if len(left.children.arr) != len(right.children.arr) {
+ return false
+ }
+
+ for i, leftChild := range left.children.arr {
+ rightChild := right.children.arr[i]
+ if !leftChild.Equal(rightChild) {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/conv.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/conv.go
new file mode 100644
index 0000000..0c9f90c
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/conv.go
@@ -0,0 +1,201 @@
+package jsonvalue
+
+import (
+ "fmt"
+ "reflect"
+
+ "github.com/Andrew-M-C/go.jsonvalue/internal/buffer"
+)
+
+func formatBool(b bool) string {
+ if b {
+ return "true"
+ }
+ return "false"
+}
+
+// reference:
+// - [UTF-16](https://zh.wikipedia.org/zh-cn/UTF-16)
+// - [JavaScript has a Unicode problem](https://mathiasbynens.be/notes/javascript-unicode)
+// - [Meaning of escaped unicode characters in JSON](https://stackoverflow.com/questions/21995410/meaning-of-escaped-unicode-characters-in-json)
+func escapeGreaterUnicodeToBuffByUTF16(r rune, buf buffer.Buffer) {
+ if r <= '\uffff' {
+ _, _ = buf.WriteString(fmt.Sprintf("\\u%04X", r))
+ return
+ }
+ // if r > 0x10FFFF {
+ // // invalid unicode
+ // buf.WriteRune(r)
+ // return
+ // }
+
+ r = r - 0x10000
+ lo := r & 0x003FF
+ hi := (r & 0xFFC00) >> 10
+ _, _ = buf.WriteString(fmt.Sprintf("\\u%04X", hi+0xD800))
+ _, _ = buf.WriteString(fmt.Sprintf("\\u%04X", lo+0xDC00))
+}
+
+func escapeGreaterUnicodeToBuffByUTF8(r rune, buf buffer.Buffer) {
+ // Comments below are copied from encoding/json:
+ //
+ // U+2028 is LINE SEPARATOR.
+ // U+2029 is PARAGRAPH SEPARATOR.
+ // They are both technically valid characters in JSON strings,
+ // but don't work in JSONP, which has to be evaluated as JavaScript,
+ // and can lead to security holes there. It is valid JSON to
+ // escape them, so we do so unconditionally.
+ // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
+ if r == '\u2028' || r == '\u2029' {
+ escapeGreaterUnicodeToBuffByUTF16(r, buf)
+ } else {
+ _, _ = buf.WriteRune(r)
+ }
+}
+
+func escapeNothing(b byte, buf buffer.Buffer) {
+ _ = buf.WriteByte(b)
+}
+
+func escAsciiControlChar(b byte, buf buffer.Buffer) {
+ upper := b >> 4
+ lower := b & 0x0F
+
+ writeChar := func(c byte) {
+ if c < 0xA {
+ _ = buf.WriteByte('0' + c)
+ } else {
+ _ = buf.WriteByte('A' + (c - 0xA))
+ }
+ }
+
+ _, _ = buf.Write([]byte{'\\', 'u', '0', '0'})
+ writeChar(upper)
+ writeChar(lower)
+}
+
+func escDoubleQuote(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', '"'})
+}
+
+func escSlash(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', '/'})
+}
+
+func escBackslash(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', '\\'})
+}
+
+func escBackspace(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'b'})
+}
+
+func escVertTab(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'f'})
+}
+
+func escTab(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 't'})
+}
+
+func escNewLine(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'n'})
+}
+
+func escReturn(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'r'})
+}
+
+func escLeftAngle(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'u', '0', '0', '3', 'C'})
+}
+
+func escRightAngle(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'u', '0', '0', '3', 'E'})
+}
+
+func escAnd(_ byte, buf buffer.Buffer) {
+ _, _ = buf.Write([]byte{'\\', 'u', '0', '0', '2', '6'})
+}
+
+// func escPercent(_ byte, buf buffer.Buffer) {
+// buf.Write([]byte{'\\', 'u', '0', '0', '2', '5'})
+// }
+
+func escapeStringToBuff(s string, buf buffer.Buffer, opt *Opt) {
+ for _, r := range s {
+ if r <= 0x7F {
+ b := byte(r)
+ opt.asciiCharEscapingFunc[b](b, buf)
+ } else {
+ opt.unicodeEscapingFunc(r, buf)
+ }
+ }
+}
+
+func anyToInt(v any) (u int, err error) {
+ if v == nil {
+ return 0, fmt.Errorf("%w: parameter is nil", ErrParameterError)
+ }
+ value := reflect.ValueOf(v)
+ switch value.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return int(value.Int()), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ return int(value.Uint()), nil
+ default:
+ return 0, fmt.Errorf("%v is not a number", reflect.TypeOf(v))
+ }
+}
+
+func anyToString(v any) (s string, err error) {
+ if v == nil {
+ return "", fmt.Errorf("%w: parameter is nil", ErrParameterError)
+ }
+ rv := reflect.ValueOf(v)
+ if rv.Type().Kind() == reflect.String {
+ return rv.String(), nil
+ }
+
+ return "", fmt.Errorf("%w: %s is not a string", ErrParameterError, reflect.TypeOf(v).String())
+}
+
+func isSliceAndExtractDividedParams(p any) (ok bool, firstParam any, otherParams []any) {
+ v := reflect.ValueOf(p)
+ switch v.Kind() {
+ default:
+ return false, nil, nil
+ case reflect.Slice, reflect.Array:
+ // yes, go on
+ }
+
+ paramCount := v.Len()
+ if paramCount == 0 {
+ return true, nil, nil
+ }
+
+ firstParam = v.Index(0).Interface()
+
+ for i := 1; i < v.Len(); i++ {
+ element := v.Index(i)
+ otherParams = append(otherParams, element.Interface())
+ }
+ return true, firstParam, otherParams
+}
+
+func isSliceAndExtractJointParams(p any) (bool, []any) {
+ v := reflect.ValueOf(p)
+ switch v.Kind() {
+ default:
+ return false, nil
+ case reflect.Slice, reflect.Array:
+ // yes, go on
+ }
+
+ res := make([]any, 0, v.Len())
+ for i := 0; i < v.Len(); i++ {
+ element := v.Index(i)
+ res = append(res, element.Interface())
+ }
+ return true, res
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/errors.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/errors.go
new file mode 100644
index 0000000..6162f96
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/errors.go
@@ -0,0 +1,99 @@
+package jsonvalue
+
+// Error is equivalent to string and used to create some error constants in this package.
+// Error constants: http://godoc.org/github.com/Andrew-M-C/go.jsonvalue/#pkg-constants
+type Error string
+
+func (e Error) Error() string {
+ return string(e)
+}
+
+const (
+ // ErrNilParameter identifies input parameter is nil
+ //
+ // ErrNilParameter 表示参数为空
+ ErrNilParameter = Error("nil parameter")
+
+ // ErrValueUninitialized identifies that a V object is not initialized
+ //
+ // ErrValueUninitialized 表示当前的 jsonvalue 实例未初始化
+ ErrValueUninitialized = Error("jsonvalue instance is not initialized")
+
+ // ErrRawBytesUnrecognized identifies all unexpected raw bytes
+ //
+ // ErrRawBytesUnrecognized 表示无法识别的序列文本
+ ErrRawBytesUnrecognized = Error("unrecognized raw text")
+
+ // ErrNotValidNumberValue shows that a value starts with number or '-' is not eventually a number value
+ //
+ // ErrNotValidNumberValue 表示当前值不是一个合法的数值值
+ ErrNotValidNumberValue = Error("not a valid number value")
+
+ // ErrNotValidBoolValue shows that a value starts with 't' or 'f' is not eventually a bool value
+ //
+ // ErrNotValidBoolValue 表示当前值不是一个合法的布尔值
+ ErrNotValidBoolValue = Error("not a valid bool value")
+
+ // ErrNotValidNullValue shows that a value starts with 'n' is not eventually a bool value
+ //
+ // ErrNotValidNullValue 表示当前不是一个 null 值类型的 JSON
+ ErrNotValidNullValue = Error("not a valid null value")
+
+ // ErrOutOfRange identifies that given position for a JSON array is out of range
+ //
+ // ErrOutOfRange 表示请求数组成员超出数组范围
+ ErrOutOfRange = Error("out of range")
+
+ // ErrNotFound shows that given target is not found in Delete()
+ //
+ // ErrNotFound 表示目标无法找到
+ ErrNotFound = Error("target not found")
+
+ // ErrTypeNotMatch shows that value type is not same as GetXxx()
+ //
+ // ErrTypeNotMatch 表示指定的对象不匹配
+ ErrTypeNotMatch = Error("not match given type")
+
+ // ErrParseNumberFromString shows the error when parsing number from string
+ //
+ // ErrParseNumberFromString 表示从 string 类型的 value 中读取数字失败
+ ErrParseNumberFromString = Error("failed to parse number from string")
+
+ // ErrNotArrayValue shows that operation target value is not an array
+ //
+ // ErrNotArrayValue 表示当前不是一个数组类型 JSON
+ ErrNotArrayValue = Error("not an array typed value")
+
+ // ErrNotObjectValue shows that operation target value is not an valid object
+ //
+ // ErrNotObjectValue 表示当前不是一个合法的对象类型 JSON
+ ErrNotObjectValue = Error("not an object typed value")
+
+ // ErrIllegalString shows that it is not a legal JSON string typed value
+ //
+ // ErrIllegalString 表示字符串不合法
+ ErrIllegalString = Error("illegal string")
+
+ // ErrUnsupportedFloat shows that float value is not supported, like +Inf, -Inf and NaN.
+ //
+ // ErrUnsupportedFloat 表示 float64 是一个不支持的数值,如 +Inf, -Inf 和 NaN
+ ErrUnsupportedFloat = Error("unsupported float value")
+
+ // ErrUnsupportedFloatInOpt shows that float value in option is not supported, like +Inf, -Inf and NaN.
+ //
+ // ErrUnsupportedFloat 表示配置中的 float64 是一个不支持的数值,如 +Inf, -Inf 和 NaN
+ ErrUnsupportedFloatInOpt = Error("unsupported float value in option")
+
+ // ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven indicates that if you
+ // use a slice pr array as first param in Get(...), Set(...).At(...), etc, no
+ // further params are allowed
+ //
+ // ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven 表示如果你在使用 Get(...)、
+ // Set(...).At(...) 等类似方法时, 首参数传入一个切片或数组, 那么不允许再传入更多的参数了
+ ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven = Error("if first param is a slice or array, no further param are allowed")
+
+ // ErrParameterError indicates misc parameter error.
+ //
+ // ErrParameterError 表示各种参数错误
+ ErrParameterError = Error("parameter error")
+)
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/get.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/get.go
new file mode 100644
index 0000000..2ebf605
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/get.go
@@ -0,0 +1,552 @@
+package jsonvalue
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+)
+
+// ================ GET ================
+
+// Len returns length of an object or array type JSON value.
+//
+// Len 返回当前对象类型或数组类型的 JSON 的成员长度。如果不是这两种类型,那么会返回 0。
+func (v *V) Len() int {
+ switch v.valueType {
+ case Array:
+ return len(v.children.arr)
+ case Object:
+ return len(v.children.object)
+ default:
+ return 0
+ }
+}
+
+// Get returns JSON value in specified position. Param formats are like At().
+//
+// Get 返回按照参数指定的位置的 JSON 成员值。参数格式与 At() 函数相同
+func (v *V) Get(firstParam any, otherParams ...any) (*V, error) {
+ return get(v, false, firstParam, otherParams...)
+}
+
+// MustGet is same as Get(), but does not return error. If error occurs, a JSON value with
+// NotExist type will be returned.
+//
+// MustGet 与 Get() 函数相同,不过不返回错误。如果发生错误了,那么会返回一个 ValueType() 返回值为 NotExist
+// 的 JSON 值对象。
+func (v *V) MustGet(firstParam any, otherParams ...any) *V {
+ res, _ := get(v, false, firstParam, otherParams...)
+ return res
+}
+
+func get(v *V, caseless bool, firstParam any, otherParams ...any) (*V, error) {
+ if ok, p1, p2 := isSliceAndExtractDividedParams(firstParam); ok {
+ if len(otherParams) > 0 {
+ return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return get(v, caseless, p1, p2...)
+ }
+ child, err := getInCurrentValue(v, caseless, firstParam)
+ if err != nil {
+ return &V{}, err
+ }
+
+ if len(otherParams) == 0 {
+ return child, nil
+ }
+ return get(child, caseless, otherParams[0], otherParams[1:]...)
+}
+
+func initCaselessStorage(v *V) {
+ if v.children.lowerCaseKeys != nil {
+ return
+ }
+ v.children.lowerCaseKeys = make(map[string]map[string]struct{}, len(v.children.object))
+ for k := range v.children.object {
+ addCaselessKey(v, k)
+ }
+}
+
+func getFromObjectChildren(v *V, caseless bool, key string) (child *V, exist bool) {
+ childProperty, exist := v.children.object[key]
+ if exist {
+ return childProperty.v, true
+ }
+
+ if !caseless {
+ return &V{}, false
+ }
+
+ initCaselessStorage(v)
+
+ lowerCaseKey := strings.ToLower(key)
+ keys, exist := v.children.lowerCaseKeys[lowerCaseKey]
+ if !exist {
+ return &V{}, false
+ }
+
+ for actualKey := range keys {
+ childProperty, exist = v.children.object[actualKey]
+ if exist {
+ return childProperty.v, true
+ }
+ }
+
+ return &V{}, false
+}
+
+func getInCurrentValue(v *V, caseless bool, param any) (*V, error) {
+ switch v.valueType {
+ case Array:
+ return getInCurrentArray(v, param)
+ case Object:
+ return getInCurrentObject(v, caseless, param)
+ default:
+ return &V{}, fmt.Errorf("%v type does not supports Get()", v.valueType)
+ }
+}
+
+func getInCurrentArray(v *V, param any) (*V, error) {
+ // integer expected
+ pos, err := anyToInt(param)
+ if err != nil {
+ return &V{}, err
+ }
+ child, ok := childAtIndex(v, pos)
+ if !ok {
+ return &V{}, ErrOutOfRange
+ }
+ return child, nil
+}
+
+func getInCurrentObject(v *V, caseless bool, param any) (*V, error) {
+ // string expected
+ key, err := anyToString(param)
+ if err != nil {
+ return &V{}, err
+ }
+ child, exist := getFromObjectChildren(v, caseless, key)
+ if !exist {
+ return &V{}, ErrNotFound
+ }
+ return child, nil
+}
+
+// GetBytes is similar with v, err := Get(...); v.Bytes(). But if error occurs or Base64 decode error, returns error.
+//
+// GetBytes 类似于 v, err := Get(...); v.Bytes(),但如果查询中发生错误,或者 base64 解码错误,则返回错误。
+func (v *V) GetBytes(firstParam any, otherParams ...any) ([]byte, error) {
+ return getBytes(v, false, firstParam, otherParams...)
+}
+
+func getBytes(v *V, caseless bool, firstParam any, otherParams ...any) ([]byte, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return []byte{}, err
+ }
+ if ret.valueType != String {
+ return []byte{}, ErrTypeNotMatch
+ }
+ b, err := internal.b64.DecodeString(ret.valueStr)
+ if err != nil {
+ return []byte{}, err
+ }
+ return b, nil
+}
+
+// GetString is equivalent to v, err := Get(...); v.String(). If error occurs, returns "".
+//
+// GetString 等效于 v, err := Get(...); v.String()。如果发生错误,则返回 ""。
+func (v *V) GetString(firstParam any, otherParams ...any) (string, error) {
+ return getString(v, false, firstParam, otherParams...)
+}
+
+func getString(v *V, caseless bool, firstParam any, otherParams ...any) (string, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return "", err
+ }
+ if ret.valueType != String {
+ return "", ErrTypeNotMatch
+ }
+ return ret.String(), nil
+}
+
+// GetInt is equivalent to v, err := Get(...); v.Int(). If error occurs, returns 0.
+//
+// GetInt 等效于 v, err := Get(...); v.Int()。如果发生错误,则返回 0。
+func (v *V) GetInt(firstParam any, otherParams ...any) (int, error) {
+ return getInt(v, false, firstParam, otherParams...)
+}
+
+func getInt(v *V, caseless bool, firstParam any, otherParams ...any) (int, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Int(), err
+}
+
+// GetUint is equivalent to v, err := Get(...); v.Uint(). If error occurs, returns 0.
+//
+// GetUint 等效于 v, err := Get(...); v.Uint()。如果发生错误,则返回 0。
+func (v *V) GetUint(firstParam any, otherParams ...any) (uint, error) {
+ return getUint(v, false, firstParam, otherParams...)
+}
+
+func getUint(v *V, caseless bool, firstParam any, otherParams ...any) (uint, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Uint(), err
+}
+
+// GetInt64 is equivalent to v, err := Get(...); v.Int64(). If error occurs, returns 0.
+//
+// GetInt64 等效于 v, err := Get(...); v.Int64()。如果发生错误,则返回 0。
+func (v *V) GetInt64(firstParam any, otherParams ...any) (int64, error) {
+ return getInt64(v, false, firstParam, otherParams...)
+}
+
+func getInt64(v *V, caseless bool, firstParam any, otherParams ...any) (int64, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Int64(), err
+}
+
+// GetUint64 is equivalent to v, err := Get(...); v.Unt64(). If error occurs, returns 0.
+//
+// GetUint64 等效于 v, err := Get(...); v.Unt64()。如果发生错误,则返回 0。
+func (v *V) GetUint64(firstParam any, otherParams ...any) (uint64, error) {
+ return getUint64(v, false, firstParam, otherParams...)
+}
+
+func getUint64(v *V, caseless bool, firstParam any, otherParams ...any) (uint64, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Uint64(), err
+}
+
+// GetInt32 is equivalent to v, err := Get(...); v.Int32(). If error occurs, returns 0.
+//
+// GetInt32 等效于 v, err := Get(...); v.Int32()。如果发生错误,则返回 0。
+func (v *V) GetInt32(firstParam any, otherParams ...any) (int32, error) {
+ return getInt32(v, false, firstParam, otherParams...)
+}
+
+func getInt32(v *V, caseless bool, firstParam any, otherParams ...any) (int32, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Int32(), err
+}
+
+// GetUint32 is equivalent to v, err := Get(...); v.Uint32(). If error occurs, returns 0.
+//
+// GetUint32 等效于 v, err := Get(...); v.Uint32()。如果发生错误,则返回 0。
+func (v *V) GetUint32(firstParam any, otherParams ...any) (uint32, error) {
+ return getUint32(v, false, firstParam, otherParams...)
+}
+
+func getUint32(v *V, caseless bool, firstParam any, otherParams ...any) (uint32, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Uint32(), err
+}
+
+// GetFloat64 is equivalent to v, err := Get(...); v.Float64(). If error occurs, returns 0.0.
+//
+// GetFloat64 等效于 v, err := Get(...); v.Float64()。如果发生错误,则返回 0.0。
+func (v *V) GetFloat64(firstParam any, otherParams ...any) (float64, error) {
+ return getFloat64(v, false, firstParam, otherParams...)
+}
+
+func getFloat64(v *V, caseless bool, firstParam any, otherParams ...any) (float64, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Float64(), err
+}
+
+// GetFloat32 is equivalent to v, err := Get(...); v.Float32(). If error occurs, returns 0.0.
+//
+// GetFloat32 等效于 v, err := Get(...); v.Float32()。如果发生错误,则返回 0.0。
+func (v *V) GetFloat32(firstParam any, otherParams ...any) (float32, error) {
+ return getFloat32(v, false, firstParam, otherParams...)
+}
+
+func getFloat32(v *V, caseless bool, firstParam any, otherParams ...any) (float32, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return 0, err
+ }
+ ret, err = getNumberAndErrorFromValue(ret)
+ return ret.Float32(), err
+}
+
+// GetBool is equivalent to v, err := Get(...); v.Bool(). If error occurs, returns false.
+//
+// GetBool 等效于 v, err := Get(...); v.Bool()。如果发生错误,则返回 false。
+func (v *V) GetBool(firstParam any, otherParams ...any) (bool, error) {
+ return getBool(v, false, firstParam, otherParams...)
+}
+
+func getBool(v *V, caseless bool, firstParam any, otherParams ...any) (bool, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return false, err
+ }
+ ret, err = getBoolAndErrorFromValue(ret)
+ return ret.Bool(), err
+}
+
+// GetNull is equivalent to v, err := Get(...); raise err if error occurs or v.IsNull() == false.
+//
+// GetNull 等效于 v, err := Get(...);,如果发生错误或者 v.IsNull() == false 则返回错误。
+func (v *V) GetNull(firstParam any, otherParams ...any) error {
+ return getNull(v, false, firstParam, otherParams...)
+}
+
+func getNull(v *V, caseless bool, firstParam any, otherParams ...any) error {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return err
+ }
+ if ret.valueType != Null {
+ return ErrTypeNotMatch
+ }
+ return nil
+}
+
+// GetObject is equivalent to v, err := Get(...); raise err if error occurs or v.IsObject() == false.
+//
+// GetObject 等效于 v, err := Get(...);,如果发生错误或者 v.IsObject() == false 则返回错误。
+func (v *V) GetObject(firstParam any, otherParams ...any) (*V, error) {
+ return getObject(v, false, firstParam, otherParams...)
+}
+
+func getObject(v *V, caseless bool, firstParam any, otherParams ...any) (*V, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return &V{}, err
+ }
+ if ret.valueType != Object {
+ return &V{}, ErrTypeNotMatch
+ }
+ return ret, nil
+}
+
+// GetArray is equivalent to v, err := Get(...); raise err if or v.IsArray() == false.
+//
+// GetArray 等效于 v, err := Get(...);,如果发生错误或者 v.IsArray() == false 则返回错误。
+func (v *V) GetArray(firstParam any, otherParams ...any) (*V, error) {
+ return getArray(v, false, firstParam, otherParams...)
+}
+
+func getArray(v *V, caseless bool, firstParam any, otherParams ...any) (*V, error) {
+ ret, err := get(v, caseless, firstParam, otherParams...)
+ if err != nil {
+ return &V{}, err
+ }
+ if ret.valueType != Array {
+ return &V{}, ErrTypeNotMatch
+ }
+ return ret, nil
+}
+
+// ================ CASELESS ================
+
+// Caseless is returned by Caseless(). operations of Caseless type are same as (*V).Get(), but are via caseless key.
+//
+// Caseless 类型通过 Caseless() 函数返回。通过 Caseless 接口操作的所有操作均与 (*v).Get()
+// 相同,但是对 key 进行读取的时候,不区分大小写。
+type Caseless interface {
+ Get(firstParam any, otherParams ...any) (*V, error)
+ MustGet(firstParam any, otherParams ...any) *V
+ GetBytes(firstParam any, otherParams ...any) ([]byte, error)
+ GetString(firstParam any, otherParams ...any) (string, error)
+ GetInt(firstParam any, otherParams ...any) (int, error)
+ GetUint(firstParam any, otherParams ...any) (uint, error)
+ GetInt64(firstParam any, otherParams ...any) (int64, error)
+ GetUint64(firstParam any, otherParams ...any) (uint64, error)
+ GetInt32(firstParam any, otherParams ...any) (int32, error)
+ GetUint32(firstParam any, otherParams ...any) (uint32, error)
+ GetFloat64(firstParam any, otherParams ...any) (float64, error)
+ GetFloat32(firstParam any, otherParams ...any) (float32, error)
+ GetBool(firstParam any, otherParams ...any) (bool, error)
+ GetNull(firstParam any, otherParams ...any) error
+ GetObject(firstParam any, otherParams ...any) (*V, error)
+ GetArray(firstParam any, otherParams ...any) (*V, error)
+
+ Delete(firstParam any, otherParams ...any) error
+ MustDelete(firstParam any, otherParams ...any)
+}
+
+var _ Caseless = (*V)(nil)
+
+// Caseless returns Caseless interface to support caseless getting.
+//
+// IMPORTANT: This function is not gouroutine-safe. Write-mutex (instead of read-mutex)
+// should be attached in cross-goroutine scenarios.
+//
+// Caseless 返回 Caseless 接口,从而实现不区分大小写的 Get 操作。
+//
+// 注意: 该函数不是协程安全的,如果在多协程场景下,调用该函数,需要加上写锁,而不能用读锁。
+func (v *V) Caseless() Caseless {
+ switch v.valueType {
+ default:
+ return v
+
+ case Array, Object:
+ return &caselessOp{
+ v: v,
+ }
+ }
+}
+
+type caselessOp struct {
+ v *V
+}
+
+func (g *caselessOp) Get(firstParam any, otherParams ...any) (*V, error) {
+ return get(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) MustGet(firstParam any, otherParams ...any) *V {
+ res, _ := get(g.v, true, firstParam, otherParams...)
+ return res
+}
+
+func (g *caselessOp) GetBytes(firstParam any, otherParams ...any) ([]byte, error) {
+ return getBytes(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetString(firstParam any, otherParams ...any) (string, error) {
+ return getString(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetInt(firstParam any, otherParams ...any) (int, error) {
+ return getInt(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetUint(firstParam any, otherParams ...any) (uint, error) {
+ return getUint(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetInt64(firstParam any, otherParams ...any) (int64, error) {
+ return getInt64(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetUint64(firstParam any, otherParams ...any) (uint64, error) {
+ return getUint64(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetInt32(firstParam any, otherParams ...any) (int32, error) {
+ return getInt32(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetUint32(firstParam any, otherParams ...any) (uint32, error) {
+ return getUint32(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetFloat64(firstParam any, otherParams ...any) (float64, error) {
+ return getFloat64(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetFloat32(firstParam any, otherParams ...any) (float32, error) {
+ return getFloat32(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetBool(firstParam any, otherParams ...any) (bool, error) {
+ return getBool(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetNull(firstParam any, otherParams ...any) error {
+ return getNull(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetObject(firstParam any, otherParams ...any) (*V, error) {
+ return getObject(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) GetArray(firstParam any, otherParams ...any) (*V, error) {
+ return getArray(g.v, true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) Delete(firstParam any, otherParams ...any) error {
+ return g.v.delete(true, firstParam, otherParams...)
+}
+
+func (g *caselessOp) MustDelete(firstParam any, otherParams ...any) {
+ _ = g.v.delete(true, firstParam, otherParams...)
+}
+
+// ==== internal value access functions ====
+
+func getNumberFromNotNumberValue(v *V) *V {
+ if !v.IsString() {
+ return NewInt(0)
+ }
+ if v.valueStr == "" {
+ return NewInt64(0)
+ }
+ ret, _ := newFromNumber(globalPool{}, bytes.TrimSpace([]byte(v.valueStr)))
+ err := parseNumber(ret, globalPool{})
+ if err != nil {
+ return NewInt64(0)
+ }
+ return ret
+}
+
+func getNumberAndErrorFromValue(v *V) (*V, error) {
+ switch v.valueType {
+ default:
+ return NewInt(0), ErrTypeNotMatch
+
+ case Number:
+ return v, nil
+
+ case String:
+ ret, _ := newFromNumber(globalPool{}, bytes.TrimSpace([]byte(v.valueStr)))
+ err := parseNumber(ret, globalPool{})
+ if err != nil {
+ return NewInt(0), fmt.Errorf("%w: %v", ErrParseNumberFromString, err)
+ }
+ return ret, ErrTypeNotMatch
+ }
+}
+
+func getBoolAndErrorFromValue(v *V) (*V, error) {
+ switch v.valueType {
+ default:
+ return NewBool(false), ErrTypeNotMatch
+
+ case Number:
+ return NewBool(v.Float64() != 0), ErrTypeNotMatch
+
+ case String:
+ if v.valueStr == "true" {
+ return NewBool(true), ErrTypeNotMatch
+ }
+ return NewBool(false), ErrTypeNotMatch
+
+ case Boolean:
+ return v, nil
+ }
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/import_export.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/import_export.go
new file mode 100644
index 0000000..724754e
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/import_export.go
@@ -0,0 +1,598 @@
+package jsonvalue
+
+import (
+ "encoding"
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strconv"
+ "strings"
+)
+
+// Export convert jsonvalue to another type of parameter. The target parameter type should match the type of *V.
+//
+// Export 将 *V 转到符合原生 encoding/json 的一个 struct 中。
+func (v *V) Export(dst any) error {
+ b, err := v.Marshal()
+ if err != nil {
+ return err
+ }
+
+ return json.Unmarshal(b, dst)
+}
+
+// Import convert json value from a marshal-able parameter to *V. This a experimental function.
+//
+// Import 将符合 encoding/json 的 struct 转为 *V 类型。不经过 encoding/json,并且支持 Option.
+func Import(src any, opts ...Option) (*V, error) {
+ opt := combineOptions(opts)
+ ext := ext{}
+ ext.ignoreOmitempty = opt.ignoreJsonOmitempty
+ v, fu, err := validateValAndReturnParser(reflect.ValueOf(src), ext)
+ if err != nil {
+ return &V{}, err
+ }
+ res, err := fu(v, ext)
+ if err != nil {
+ return &V{}, err
+ }
+ return res, nil
+}
+
+// parserFunc 处理对应 reflect.Value 的函数
+type parserFunc func(v reflect.Value, ex ext) (*V, error)
+
+type ext struct {
+ // standard encoding/json tag
+ omitempty bool
+ toString bool
+
+ // revert of isExported
+ private bool
+
+ // extended jsonvalue options
+ ignoreOmitempty bool
+}
+
+func (e ext) shouldOmitEmpty() bool {
+ if e.ignoreOmitempty {
+ return false
+ }
+ return e.omitempty || e.private
+}
+
+// validateValAndReturnParser 检查入参合法性并返回相应的处理函数
+func validateValAndReturnParser(v reflect.Value, ex ext) (out reflect.Value, fu parserFunc, err error) {
+ out = v
+
+ // json.Marshaler and encoding.TextMarshaler
+ if o, f := checkAndParseMarshaler(v); f != nil {
+ // jsonvalue itself
+ if _, ok := v.Interface().(deepCopier); ok {
+ return out, parseJSONValueDeepCopier, nil
+ }
+ return o, f, nil
+ }
+
+ switch v.Kind() {
+ default:
+ // fallthrough
+ // case reflect.Invalid, reflect.Complex64, reflect.Complex128:
+ // fallthrough
+ // case reflect.Chan, reflect.Func, reflect.UnsafePointer:
+ err = fmt.Errorf("jsonvalue: unsupported type: %v", v.Type())
+
+ case reflect.Invalid:
+ fu = parseInvalidValue
+
+ case reflect.Bool:
+ fu = parseBoolValue
+
+ case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
+ fu = parseIntValue
+
+ case reflect.Uintptr, reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8:
+ fu = parseUintValue
+
+ case reflect.Float32:
+ fu = parseFloat32Value
+
+ case reflect.Float64:
+ fu = parseFloat64Value
+
+ case reflect.Array:
+ fu = parseArrayValue
+
+ case reflect.Interface:
+ return validateValAndReturnParser(v.Elem(), ex)
+
+ case reflect.Map:
+ switch v.Type().Key().Kind() {
+ default:
+ err = fmt.Errorf("unsupported key type for a map: %v", v.Type().Key())
+ case reflect.String:
+ fu = parseStringMapValue
+ case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
+ fu = parseIntMapValue
+ case reflect.Uintptr, reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8:
+ fu = parseUintMapValue
+ }
+
+ case reflect.Ptr:
+ fu = parsePtrValue
+
+ case reflect.Slice:
+ if v.Type() == reflect.TypeOf([]byte{}) {
+ fu = parseBytesValue
+ } else {
+ fu = parseSliceValue
+ }
+
+ case reflect.String:
+ fu = parseStringValue
+
+ case reflect.Struct:
+ fu = parseStructValue
+ }
+
+ return
+}
+
+// Hit marshaler if fu is not nil.
+func checkAndParseMarshaler(v reflect.Value) (out reflect.Value, fu parserFunc) {
+ out = v
+ if !v.IsValid() {
+ return
+ }
+
+ // check type itself
+ if v.Type().Implements(internal.types.JSONMarshaler) {
+ return v, parseJSONMarshaler
+ }
+ if v.Type().Implements(internal.types.TextMarshaler) {
+ return v, parseTextMarshaler
+ }
+
+ // check its origin type
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return
+ }
+ elem := v.Elem()
+ if elem.Type().Implements(internal.types.JSONMarshaler) {
+ return elem, parseJSONMarshaler
+ }
+ if elem.Type().Implements(internal.types.TextMarshaler) {
+ return elem, parseTextMarshaler
+ }
+ return
+ }
+
+ // check its pointer type
+ // referenceType := reflect.PointerTo(v.Type()) // go 1.17 +
+ referenceType := reflect.PtrTo(v.Type())
+ if referenceType.Implements(internal.types.JSONMarshaler) {
+ return getPointerOfValue(v), parseJSONMarshaler
+ }
+ if referenceType.Implements(internal.types.TextMarshaler) {
+ return getPointerOfValue(v), parseTextMarshaler
+ }
+
+ return
+}
+
+// reference:
+// - [Using reflect to get a pointer to a struct passed as an interface{}](https://groups.google.com/g/golang-nuts/c/KB3_Yj3Ny4c)
+// - [reflect.Set slice-of-structs value to a struct, without type assertion (because it's unknown)](https://stackoverflow.com/questions/40474682)
+func getPointerOfValue(v reflect.Value) reflect.Value {
+ vp := reflect.New(reflect.TypeOf(v.Interface()))
+ vp.Elem().Set(v)
+ return vp
+}
+
+func parseJSONValueDeepCopier(v reflect.Value, ex ext) (*V, error) {
+ if v.IsNil() {
+ return nil, nil // empty
+ }
+ j, _ := v.Interface().(deepCopier)
+ return j.deepCopy(), nil
+}
+
+func parseJSONMarshaler(v reflect.Value, ex ext) (*V, error) {
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ return nil, nil // empty
+ }
+ marshaler, _ := v.Interface().(json.Marshaler)
+ if marshaler == nil {
+ return nil, nil // empty
+ }
+ b, err := marshaler.MarshalJSON()
+ if err != nil {
+ return &V{}, fmt.Errorf("JSONMarshaler returns error: %w", err)
+ }
+
+ res, err := Unmarshal(b)
+ if err != nil {
+ return nil, fmt.Errorf("illegal JSON data generated from type '%v', error: %w", v.Type(), err)
+ }
+
+ if ex.shouldOmitEmpty() {
+ switch res.ValueType() {
+ default:
+ return nil, nil
+ case String:
+ if res.String() == "" {
+ return nil, nil
+ }
+ case Number:
+ if res.Float64() == 0 {
+ return nil, nil
+ }
+ case Array, Object:
+ if res.Len() == 0 {
+ return nil, nil
+ }
+ case Boolean:
+ if !res.Bool() {
+ return nil, nil
+ }
+ case Null:
+ return nil, nil
+ }
+ }
+
+ return res, nil
+}
+
+func parseTextMarshaler(v reflect.Value, ex ext) (*V, error) {
+ if v.Kind() == reflect.Ptr && v.IsNil() {
+ return nil, nil // empty
+ }
+ marshaler, _ := v.Interface().(encoding.TextMarshaler)
+ if marshaler == nil {
+ return NewNull(), nil // empty
+ }
+ b, err := marshaler.MarshalText()
+ if err != nil {
+ return &V{}, err
+ }
+
+ if len(b) == 0 && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ return NewString(string(b)), nil
+}
+
+func parseInvalidValue(_ reflect.Value, ex ext) (*V, error) {
+ if ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ return NewNull(), nil
+}
+
+func parseBoolValue(v reflect.Value, ex ext) (*V, error) {
+ b := v.Bool()
+ if !b && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ if ex.toString {
+ return NewString(fmt.Sprint(b)), nil
+ }
+ return NewBool(b), nil
+}
+
+func parseIntValue(v reflect.Value, ex ext) (*V, error) {
+ i := v.Int()
+ if i == 0 && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ if ex.toString {
+ return NewString(strconv.FormatInt(i, 10)), nil
+ }
+ return NewInt64(i), nil
+}
+
+func parseUintValue(v reflect.Value, ex ext) (*V, error) {
+ u := v.Uint()
+ if u == 0 && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ if ex.toString {
+ return NewString(strconv.FormatUint(u, 10)), nil
+ }
+ return NewUint64(u), nil
+}
+
+func parseFloat64Value(v reflect.Value, ex ext) (*V, error) {
+ f := v.Float()
+ if f == 0.0 && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ if ex.toString {
+ f64 := NewFloat64(f)
+ return NewString(f64.MustMarshalString()), nil
+ }
+ return NewFloat64(f), nil
+}
+
+func parseFloat32Value(v reflect.Value, ex ext) (*V, error) {
+ f := v.Float()
+ if f == 0.0 && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ if ex.toString {
+ f32 := NewFloat32(float32(f))
+ return NewString(f32.MustMarshalString()), nil
+ }
+ return NewFloat32(float32(f)), nil
+}
+
+func parseArrayValue(v reflect.Value, ex ext) (*V, error) {
+ ex.omitempty = false
+ res := NewArray()
+ le := v.Len()
+
+ for i := 0; i < le; i++ {
+ vv := v.Index(i)
+ vv, fu, err := validateValAndReturnParser(vv, ex)
+ if err != nil {
+ return nil, err
+ }
+ child, err := fu(vv, ex)
+ if err != nil {
+ return nil, err
+ }
+ res.MustAppend(child).InTheEnd()
+ }
+
+ return res, nil
+}
+
+func parseMapValue(v reflect.Value, ex ext, keyFunc func(key reflect.Value) string) (*V, error) {
+ if v.IsNil() {
+ return parseNullValue(v, ex)
+ }
+
+ keys := v.MapKeys()
+ if len(keys) == 0 {
+ if ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ return NewObject(), nil
+ }
+
+ res := NewObject()
+
+ for _, kk := range keys {
+ vv := v.MapIndex(kk)
+ vv, fu, err := validateValAndReturnParser(vv, ex)
+ if err != nil {
+ return res, err
+ }
+ child, err := fu(vv, ex)
+ if err != nil {
+ return res, err
+ }
+ res.MustSet(child).At(keyFunc(kk))
+ }
+
+ return res, nil
+}
+
+func parseStringMapValue(v reflect.Value, ex ext) (*V, error) {
+ return parseMapValue(v, ex, func(k reflect.Value) string {
+ return k.String()
+ })
+}
+
+func parseIntMapValue(v reflect.Value, ex ext) (*V, error) {
+ return parseMapValue(v, ex, func(k reflect.Value) string {
+ return strconv.FormatInt(k.Int(), 10)
+ })
+}
+
+func parseUintMapValue(v reflect.Value, ex ext) (*V, error) {
+ return parseMapValue(v, ex, func(k reflect.Value) string {
+ return strconv.FormatUint(k.Uint(), 10)
+ })
+}
+
+func parsePtrValue(v reflect.Value, ex ext) (*V, error) {
+ if v.IsNil() {
+ return parseNullValue(v, ex)
+ }
+
+ v, fu, err := validateValAndReturnParser(v.Elem(), ex)
+ if err != nil {
+ return nil, err
+ }
+
+ return fu(v, ex)
+}
+
+func parseSliceValue(v reflect.Value, ex ext) (*V, error) {
+ if v.IsNil() || v.Len() == 0 {
+ if ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ return NewArray(), nil
+ }
+
+ return parseArrayValue(v, ex)
+}
+
+func parseBytesValue(v reflect.Value, ex ext) (*V, error) {
+ b := v.Interface().([]byte)
+ if len(b) == 0 && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+
+ return NewBytes(b), nil
+}
+
+func parseStringValue(v reflect.Value, ex ext) (*V, error) {
+ str := v.String()
+ if str == "" && ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+
+ return NewString(str), nil
+}
+
+func parseStructValue(v reflect.Value, ex ext) (*V, error) {
+ t := v.Type()
+ numField := t.NumField()
+
+ res := NewObject()
+
+ for i := 0; i < numField; i++ {
+ vv := v.Field(i)
+ tt := t.Field(i)
+
+ keys, children, err := parseStructFieldValue(vv, tt, ex)
+ if err != nil {
+ return nil, err
+ }
+
+ for i, k := range keys {
+ v := children[i]
+ res.MustSet(v).At(k)
+ }
+ }
+
+ return res, nil
+}
+
+func parseNullValue(_ reflect.Value, ex ext) (*V, error) {
+ if ex.shouldOmitEmpty() {
+ return nil, nil
+ }
+ return NewNull(), nil
+}
+
+func parseStructFieldValue(
+ fv reflect.Value, ft reflect.StructField, parentEx ext,
+) (keys []string, children []*V, err error) {
+
+ if ft.Anonymous {
+ return parseStructAnonymousFieldValue(fv, ft, parentEx)
+ }
+
+ if !fv.CanInterface() {
+ return
+ }
+
+ fieldName, ex := readFieldTag(ft, "json", parentEx)
+ if fieldName == "-" {
+ return
+ }
+
+ fv, fu, err := validateValAndReturnParser(fv, ex)
+ if err != nil {
+ err = fmt.Errorf("parsing field '%s' error: %w", fieldName, err)
+ return
+ }
+
+ child, err := fu(fv, ex)
+ if err != nil {
+ err = fmt.Errorf("parsing field '%s' error: %w", fieldName, err)
+ return
+ }
+ if child != nil {
+ return []string{fieldName}, []*V{child}, nil
+ }
+
+ return nil, nil, nil
+}
+
+func parseStructAnonymousFieldValue(
+ fv reflect.Value, ft reflect.StructField, parentEx ext,
+) (keys []string, children []*V, err error) {
+
+ fieldName, ex := readAnonymousFieldTag(ft, "json", parentEx)
+ if fieldName == "-" {
+ return nil, nil, nil
+ }
+ if fv.Kind() == reflect.Ptr && fv.IsNil() {
+ if ex.shouldOmitEmpty() {
+ return nil, nil, nil
+ }
+ return []string{fieldName}, []*V{NewNull()}, nil
+ }
+
+ fv, fu, err := validateValAndReturnParser(fv, ex)
+ if err != nil {
+ err = fmt.Errorf("parsing anonymous field error: %w", err)
+ return
+ }
+
+ child, err := fu(fv, ex)
+ if err != nil {
+ err = fmt.Errorf("parsing anonymous field error: %w", err)
+ return
+ }
+ if child == nil {
+ return nil, nil, nil
+ }
+
+ switch child.ValueType() {
+ default: // invalid
+ return nil, nil, nil
+
+ case String, Number, Boolean, Null, Array:
+ if ex.private {
+ return nil, nil, nil
+ }
+ return []string{fieldName}, []*V{child}, nil
+
+ case Object:
+ child.RangeObjectsBySetSequence(func(k string, c *V) bool {
+ keys = append(keys, k)
+ children = append(children, c)
+ return true
+ })
+ return
+ }
+}
+
+func readFieldTag(ft reflect.StructField, name string, parentEx ext) (field string, ex ext) {
+ tg := ft.Tag.Get(name)
+
+ if tg == "" {
+ return ft.Name, ext{
+ ignoreOmitempty: parentEx.ignoreOmitempty,
+ }
+ }
+
+ parts := strings.Split(tg, ",")
+ for i, s := range parts {
+ parts[i] = strings.TrimSpace(s)
+ if i > 0 {
+ if s == "omitempty" {
+ ex.omitempty = true
+ } else if s == "string" {
+ ex.toString = true
+ }
+ }
+ }
+
+ field = parts[0]
+ if field == "" {
+ field = ft.Name
+ }
+ ex.ignoreOmitempty = parentEx.ignoreOmitempty
+ return
+}
+
+func readAnonymousFieldTag(ft reflect.StructField, name string, parentEx ext) (field string, ex ext) {
+ field, ex = readFieldTag(ft, name, parentEx)
+
+ firstChar := ft.Name[0]
+ if firstChar >= 'A' && firstChar <= 'Z' {
+ ex.private = false
+ } else {
+ ex.private = true
+ }
+
+ return
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete.go
new file mode 100644
index 0000000..535a4a2
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete.go
@@ -0,0 +1,632 @@
+package jsonvalue
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+)
+
+// ================ INSERT ================
+
+// MARK: INSERT
+
+// Inserter type is for After() and Before() methods.
+//
+// # Should be generated ONLY BY V.Insert() !
+//
+// Insert 类型适用于 After() 和 Before() 方法。请注意:该类型仅应由 V.Insert 函数生成!
+type Inserter interface {
+ // After completes the following operation of Insert(). It inserts value AFTER
+ // specified position.
+ //
+ // The last parameter identifies the position where a new JSON is inserted after,
+ // it should ba an integer, no matter signed or unsigned. If the position is
+ // zero or positive integer, it tells the index of an array. If the position
+ // is negative, it tells the backward index of an array.
+ //
+ // For example, 0 represents the first, and -2 represents the second last.
+ //
+ // After 结束并完成 Insert() 函数的后续插入操作,表示插入到指定位置的前面。
+ //
+ // 在 Before 函数的最后一个参数指定了被插入的 JSON 数组的位置,这个参数应当是一个整型
+ // (有无符号类型均可)。
+ // 如果这个值等于0或者正整数,那么它指定的是在 JSON 数组中的位置(从0开始)。如果这个值是负数,
+ // 那么它指定的是 JSON 数组中从最后一个位置开始算起的位置。
+ //
+ // 举例说明:0 表示第一个位置,而 -2 表示倒数第二个位置。
+ After(firstParam any, otherParams ...any) (*V, error)
+
+ // Before completes the following operation of Insert(). It inserts value BEFORE
+ // specified position.
+ //
+ // The last parameter identifies the position where a new JSON is inserted after,
+ // it should ba an integer, no matter signed or unsigned.
+ // If the position is zero or positive integer, it tells the index of an array.
+ // If the position is negative, it tells the backward index of an array.
+ //
+ // For example, 0 represents the first, and -2 represents the second last.
+ //
+ // Before 结束并完成 Insert() 函数的后续插入操作,表示插入到指定位置的后面。
+ //
+ // 在 Before 函数的最后一个参数指定了被插入的 JSON 数组的位置,这个参数应当是一个整型
+ //(有无符号类型均可)。
+ // 如果这个值等于0或者正整数,那么它指定的是在 JSON 数组中的位置(从0开始)。如果这个值是负数,
+ // 那么它指定的是 JSON 数组中从最后一个位置开始算起的位置。
+ //
+ // 举例说明:0 表示第一个位置,而 -2 表示倒数第二个位置。
+ Before(firstParam any, otherParams ...any) (*V, error)
+}
+
+type insert struct {
+ v *V
+ c *V // child
+
+ err error
+}
+
+// Insert starts inserting a child JSON value
+//
+// Insert 开启一个 JSON 数组成员的插入操作.
+func (v *V) Insert(child any) Inserter {
+ var ch *V
+ var err error
+
+ if child == nil {
+ ch = NewNull()
+ } else if childV, ok := child.(*V); ok {
+ ch = childV
+ } else {
+ ch, err = Import(child)
+ }
+
+ return &insert{
+ v: v,
+ c: ch,
+ err: err,
+ }
+}
+
+// InsertString is equivalent to Insert(jsonvalue.NewString(s))
+//
+// InsertString 等效于 Insert(jsonvalue.NewString(s))
+func (v *V) InsertString(s string) Inserter {
+ return v.Insert(NewString(s))
+}
+
+// InsertBool is equivalent to Insert(jsonvalue.NewBool(b))
+//
+// InsertBool 等效于 Insert(jsonvalue.NewBool(b))
+func (v *V) InsertBool(b bool) Inserter {
+ return v.Insert(NewBool(b))
+}
+
+// InsertInt is equivalent to Insert(jsonvalue.NewInt(b))
+//
+// InsertInt 等效于 Insert(jsonvalue.NewInt(b))
+func (v *V) InsertInt(i int) Inserter {
+ return v.Insert(NewInt(i))
+}
+
+// InsertInt64 is equivalent to Insert(jsonvalue.NewInt64(b))
+//
+// InsertInt64 等效于 Insert(jsonvalue.NewInt64(b))
+func (v *V) InsertInt64(i int64) Inserter {
+ return v.Insert(NewInt64(i))
+}
+
+// InsertInt32 is equivalent to Insert(jsonvalue.NewInt32(b))
+//
+// InsertInt32 等效于 Insert(jsonvalue.NewInt32(b))
+func (v *V) InsertInt32(i int32) Inserter {
+ return v.Insert(NewInt32(i))
+}
+
+// InsertUint is equivalent to Insert(jsonvalue.NewUint(b))
+//
+// InsertUint 等效于 Insert(jsonvalue.NewUint(b))
+func (v *V) InsertUint(u uint) Inserter {
+ return v.Insert(NewUint(u))
+}
+
+// InsertUint64 is equivalent to Insert(jsonvalue.NewUint64(b))
+//
+// InsertUint64 等效于 Insert(jsonvalue.NewUint64(b))
+func (v *V) InsertUint64(u uint64) Inserter {
+ return v.Insert(NewUint64(u))
+}
+
+// InsertUint32 is equivalent to Insert(jsonvalue.NewUint32(b))
+//
+// InsertUint32 等效于 Insert(jsonvalue.NewUint32(b))
+func (v *V) InsertUint32(u uint32) Inserter {
+ return v.Insert(NewUint32(u))
+}
+
+// InsertFloat64 is equivalent to Insert(jsonvalue.NewFloat64(b))
+//
+// InsertFloat64 等效于 Insert(jsonvalue.NewFloat64(b))
+func (v *V) InsertFloat64(f float64) Inserter {
+ return v.Insert(NewFloat64(f))
+}
+
+// InsertFloat32 is equivalent to Insert(jsonvalue.NewFloat32(b))
+//
+// InsertFloat32 等效于 Insert(jsonvalue.NewFloat32(b))
+func (v *V) InsertFloat32(f float32) Inserter {
+ return v.Insert(NewFloat32(f))
+}
+
+// InsertNull is equivalent to Insert(jsonvalue.NewNull())
+//
+// InsertNull 等效于 Insert(jsonvalue.NewNull())
+func (v *V) InsertNull() Inserter {
+ return v.Insert(NewNull())
+}
+
+// InsertObject is equivalent to Insert(jsonvalue.NewObject())
+//
+// InsertObject 等效于 Insert(jsonvalue.NewObject())
+func (v *V) InsertObject() Inserter {
+ return v.Insert(NewObject())
+}
+
+// InsertArray is equivalent to Insert(jsonvalue.NewArray())
+//
+// InsertArray 等效于 Insert(jsonvalue.NewArray())
+func (v *V) InsertArray() Inserter {
+ return v.Insert(NewArray())
+}
+
+func (ins *insert) Before(firstParam any, otherParams ...any) (*V, error) {
+ if ins.err != nil {
+ return &V{}, ins.err
+ }
+ if ok, p1, p2 := isSliceAndExtractDividedParams(firstParam); ok {
+ if len(otherParams) > 0 {
+ return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return ins.Before(p1, p2...)
+ }
+ v := ins.v
+ c := ins.c
+ if v.valueType == NotExist {
+ return &V{}, ErrValueUninitialized
+ }
+
+ // this is the last iteration
+ paramCount := len(otherParams)
+ if paramCount == 0 {
+ if v.valueType != Array {
+ return &V{}, ErrNotArrayValue
+ }
+
+ pos, err := anyToInt(firstParam)
+ if err != nil {
+ return &V{}, err
+ }
+
+ pos = posAtIndexForInsertBefore(v, pos)
+ if pos < 0 {
+ return &V{}, ErrOutOfRange
+ }
+ insertToArr(v, pos, c)
+ return c, nil
+ }
+
+ // this is not the last iteration
+ child, err := v.GetArray(firstParam, otherParams[:paramCount-1]...)
+ if err != nil {
+ return &V{}, err
+ }
+
+ childIns := &insert{
+ v: child,
+ c: c,
+ }
+ return childIns.Before(otherParams[paramCount-1])
+}
+
+func (ins *insert) After(firstParam any, otherParams ...any) (*V, error) {
+ if ins.err != nil {
+ return &V{}, ins.err
+ }
+ if ok, p1, p2 := isSliceAndExtractDividedParams(firstParam); ok {
+ if len(otherParams) > 0 {
+ return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return ins.After(p1, p2...)
+ }
+ v := ins.v
+ c := ins.c
+ if nil == v || v.valueType == NotExist {
+ return &V{}, ErrValueUninitialized
+ }
+
+ // this is the last iteration
+ paramCount := len(otherParams)
+ if paramCount == 0 {
+ if v.valueType != Array {
+ return &V{}, ErrNotArrayValue
+ }
+
+ pos, err := anyToInt(firstParam)
+ if err != nil {
+ return &V{}, err
+ }
+
+ pos, appendToEnd := posAtIndexForInsertAfter(v, pos)
+ if pos < 0 {
+ return &V{}, ErrOutOfRange
+ }
+ if appendToEnd {
+ appendToArr(v, c)
+ } else {
+ insertToArr(v, pos, c)
+ }
+ return c, nil
+ }
+
+ // this is not the last iteration
+ child, err := v.GetArray(firstParam, otherParams[:paramCount-1]...)
+ if err != nil {
+ return &V{}, err
+ }
+
+ childIns := &insert{
+ v: child,
+ c: c,
+ }
+ return childIns.After(otherParams[paramCount-1])
+}
+
+func insertToArr(v *V, pos int, child *V) {
+ v.children.arr = append(v.children.arr, nil)
+ copy(v.children.arr[pos+1:], v.children.arr[pos:])
+ v.children.arr[pos] = child
+}
+
+// ================ APPEND ================
+
+// MARK: APPEND
+
+// Appender type is for InTheEnd() or InTheBeginning() function.
+//
+// Appender 类型是用于 InTheEnd() 和 InTheBeginning() 函数的。使用者可以不用关注这个类型。
+// 并且这个类型只应当由 V.Append() 产生。
+type Appender interface {
+ InTheBeginning(params ...any) (*V, error)
+ InTheEnd(params ...any) (*V, error)
+}
+
+type appender struct {
+ v *V
+ c *V // child
+
+ err error
+}
+
+// Append starts appending a child JSON value to a JSON array.
+//
+// Append 开始将一个 JSON 值添加到一个数组中。需结合 InTheEnd() 和 InTheBeginning() 函数使用。
+func (v *V) Append(child any) Appender {
+ var ch *V
+ var err error
+
+ if child == nil {
+ ch = NewNull()
+ } else if childV, ok := child.(*V); ok {
+ ch = childV
+ } else {
+ ch, err = Import(child)
+ }
+ return &appender{
+ v: v,
+ c: ch,
+ err: err,
+ }
+}
+
+// AppendString is equivalent to Append(jsonvalue.NewString(s))
+//
+// AppendString 等价于 Append(jsonvalue.NewString(s))
+func (v *V) AppendString(s string) Appender {
+ return v.Append(NewString(s))
+}
+
+// AppendBytes is equivalent to Append(jsonvalue.NewBytes(b))
+//
+// AppendBytes 等价于 Append(jsonvalue.NewBytes(b))
+func (v *V) AppendBytes(b []byte) Appender {
+ return v.Append(NewBytes(b))
+}
+
+// AppendBool is equivalent to Append(jsonvalue.NewBool(b))
+//
+// AppendBool 等价于 Append(jsonvalue.NewBool(b))
+func (v *V) AppendBool(b bool) Appender {
+ return v.Append(NewBool(b))
+}
+
+// AppendInt is equivalent to Append(jsonvalue.NewInt(b))
+//
+// AppendInt 等价于 Append(jsonvalue.NewInt(b))
+func (v *V) AppendInt(i int) Appender {
+ return v.Append(NewInt(i))
+}
+
+// AppendInt64 is equivalent to Append(jsonvalue.NewInt64(b))
+//
+// AppendInt64 等价于 Append(jsonvalue.NewInt64(b))
+func (v *V) AppendInt64(i int64) Appender {
+ return v.Append(NewInt64(i))
+}
+
+// AppendInt32 is equivalent to Append(jsonvalue.NewInt32(b))
+//
+// AppendInt32 等价于 Append(jsonvalue.NewInt32(b))
+func (v *V) AppendInt32(i int32) Appender {
+ return v.Append(NewInt32(i))
+}
+
+// AppendUint is equivalent to Append(jsonvalue.NewUint(b))
+//
+// AppendUint 等价于 Append(jsonvalue.NewUint(b))
+func (v *V) AppendUint(u uint) Appender {
+ return v.Append(NewUint(u))
+}
+
+// AppendUint64 is equivalent to Append(jsonvalue.NewUint64(b))
+//
+// AppendUint64 等价于 Append(jsonvalue.NewUint64(b))
+func (v *V) AppendUint64(u uint64) Appender {
+ return v.Append(NewUint64(u))
+}
+
+// AppendUint32 is equivalent to Append(jsonvalue.NewUint32(b))
+//
+// AppendUint32 等价于 Append(jsonvalue.NewUint32(b))
+func (v *V) AppendUint32(u uint32) Appender {
+ return v.Append(NewUint32(u))
+}
+
+// AppendFloat64 is equivalent to Append(jsonvalue.NewFloat64(b))
+//
+// AppendUint32 等价于 Append(jsonvalue.NewUint32(b))
+func (v *V) AppendFloat64(f float64) Appender {
+ return v.Append(NewFloat64(f))
+}
+
+// AppendFloat32 is equivalent to Append(jsonvalue.NewFloat32(b))
+//
+// AppendFloat32 等价于 Append(jsonvalue.NewFloat32(b))
+func (v *V) AppendFloat32(f float32) Appender {
+ return v.Append(NewFloat32(f))
+}
+
+// AppendNull is equivalent to Append(jsonvalue.NewNull())
+//
+// AppendNull 等价于 Append(jsonvalue.NewNull())
+func (v *V) AppendNull() Appender {
+ return v.Append(NewNull())
+}
+
+// AppendObject is equivalent to Append(jsonvalue.NewObject())
+//
+// AppendObject 等价于 Append(jsonvalue.NewObject())
+func (v *V) AppendObject() Appender {
+ return v.Append(NewObject())
+}
+
+// AppendArray is equivalent to Append(jsonvalue.NewArray())
+//
+// AppendArray 等价于 Append(jsonvalue.NewArray())
+func (v *V) AppendArray() Appender {
+ return v.Append(NewArray())
+}
+
+// InTheBeginning completes the following operation of Append().
+//
+// InTheBeginning 函数将 Append 函数指定的 JSON 值,添加到参数指定的数组的最前端
+func (apd *appender) InTheBeginning(params ...any) (*V, error) {
+ v := apd.v
+ c := apd.c
+ if nil == v || v.valueType == NotExist {
+ return &V{}, ErrValueUninitialized
+ }
+
+ // this is the last iteration
+ paramCount := len(params)
+ if paramCount == 0 {
+ if v.valueType != Array {
+ return &V{}, ErrNotArrayValue
+ }
+ if v.Len() == 0 {
+ appendToArr(v, c)
+ } else {
+ insertToArr(v, 0, c)
+ }
+ return c, nil
+ }
+ if ok, p := isSliceAndExtractJointParams(params[0]); ok {
+ if len(params) > 1 {
+ return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return apd.InTheBeginning(p...)
+ }
+
+ // this is not the last iteration
+ child, err := v.GetArray(params[0], params[1:paramCount]...)
+ if err != nil {
+ if !errors.Is(err, ErrNotFound) {
+ return &V{}, err
+ }
+ child, err = v.SetArray().At(params[0], params[1:]...)
+ if err != nil {
+ return &V{}, err
+ }
+ }
+
+ if child.Len() == 0 {
+ appendToArr(child, c)
+ } else {
+ insertToArr(child, 0, c)
+ }
+ return c, nil
+}
+
+// InTheEnd completes the following operation of Append().
+//
+// InTheEnd 函数将 Append 函数指定的 JSON 值,添加到参数指定的数组的最后面
+func (apd *appender) InTheEnd(params ...any) (*V, error) {
+ v := apd.v
+ c := apd.c
+ if v.valueType == NotExist {
+ return &V{}, ErrValueUninitialized
+ }
+
+ // this is the last iteration
+ paramCount := len(params)
+ if paramCount == 0 {
+ if v.valueType != Array {
+ return &V{}, ErrNotArrayValue
+ }
+
+ appendToArr(v, c)
+ return c, nil
+ }
+ if ok, p := isSliceAndExtractJointParams(params[0]); ok {
+ if len(params) > 1 {
+ return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return apd.InTheEnd(p...)
+ }
+
+ // this is not the last iteration
+ child, err := v.GetArray(params[0], params[1:paramCount]...)
+ if err != nil {
+ if !errors.Is(err, ErrNotFound) {
+ return &V{}, err
+ }
+ child, err = v.SetArray().At(params[0], params[1:]...)
+ if err != nil {
+ return &V{}, err
+ }
+ }
+
+ appendToArr(child, c)
+ return c, nil
+}
+
+// ================ DELETE ================
+
+// MARK: DELETE
+
+func delFromObjectChildren(v *V, caseless bool, key string) (exist bool) {
+ _, exist = v.children.object[key]
+ if exist {
+ delete(v.children.object, key)
+ delCaselessKey(v, key)
+ return true
+ }
+
+ if !caseless {
+ return false
+ }
+
+ initCaselessStorage(v)
+
+ lowerKey := strings.ToLower(key)
+ keys, exist := v.children.lowerCaseKeys[lowerKey]
+ if !exist {
+ return false
+ }
+
+ for actualKey := range keys {
+ _, exist = v.children.object[actualKey]
+ if exist {
+ delete(v.children.object, actualKey)
+ delCaselessKey(v, actualKey)
+ return true
+ }
+ }
+
+ return false
+}
+
+// Delete deletes specified JSON value. For example, parameters ("data", "list") identifies deleting value in data.list.
+// While ("list", 1) means deleting the second element from the "list" array.
+//
+// Delete 从 JSON 中删除参数指定的对象。比如参数 ("data", "list") 表示删除 data.list 值;参数 ("list", 1) 则表示删除 list
+// 数组的第2(从1算起)个值。
+func (v *V) Delete(firstParam any, otherParams ...any) error {
+ return v.delete(false, firstParam, otherParams...)
+}
+
+func (v *V) delete(caseless bool, firstParam any, otherParams ...any) error {
+ if ok, p1, p2 := isSliceAndExtractDividedParams(firstParam); ok {
+ if len(otherParams) > 0 {
+ return ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return v.delete(caseless, p1, p2...)
+ }
+
+ paramCount := len(otherParams)
+ if paramCount == 0 {
+ return deleteInCurrentValue(v, caseless, firstParam)
+ }
+
+ child, err := get(v, caseless, firstParam, otherParams[:paramCount-1]...)
+ if err != nil {
+ return err
+ }
+ // if child == nil {
+ // return ErrNotFound
+ // }
+
+ return child.delete(caseless, otherParams[paramCount-1])
+}
+
+func deleteInCurrentValue(v *V, caseless bool, param any) error {
+ switch v.valueType {
+ case Object:
+ return deleteInCurrentObject(v, caseless, param)
+ case Array:
+ return deleteInCurrentArray(v, param)
+ default:
+ // else, this is an object value
+ return fmt.Errorf("%v type does not supports Delete()", v.valueType)
+ }
+}
+
+func deleteInCurrentObject(v *V, caseless bool, param any) error {
+ // string expected
+ key, err := anyToString(param)
+ if err != nil {
+ return err
+ }
+ if exist := delFromObjectChildren(v, caseless, key); !exist {
+ return ErrNotFound
+ }
+ return nil
+}
+
+func deleteInCurrentArray(v *V, param any) error {
+ // integer expected
+ pos, err := anyToInt(param)
+ if err != nil {
+ return err
+ }
+ pos = posAtIndexForRead(v, pos)
+ if pos < 0 {
+ return ErrOutOfRange
+ }
+ deleteInArr(v, pos)
+ return nil
+}
+
+func deleteInArr(v *V, pos int) {
+ le := len(v.children.arr)
+ v.children.arr[pos] = nil
+ copy(v.children.arr[pos:], v.children.arr[pos+1:])
+ v.children.arr = v.children.arr[:le-1]
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete_must.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete_must.go
new file mode 100644
index 0000000..c21b6b1
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/insert_append_delete_must.go
@@ -0,0 +1,245 @@
+package jsonvalue
+
+// ================ INSERT ================
+
+// MustInserter is just like Inserter, but not returning sub-value or error.
+type MustInserter interface {
+ // After completes the following operation of Insert(). It inserts value AFTER
+ // specified position.
+ //
+ // The last parameter identifies the position where a new JSON is inserted after,
+ // it should ba an integer, no matter signed or unsigned. If the position is
+ // zero or positive integer, it tells the index of an array. If the position
+ // is negative, it tells the backward index of an array.
+ //
+ // For example, 0 represents the first, and -2 represents the second last.
+ //
+ // After 结束并完成 Insert() 函数的后续插入操作,表示插入到指定位置的前面。
+ //
+ // 在 Before 函数的最后一个参数指定了被插入的 JSON 数组的位置,这个参数应当是一个整型
+ // (有无符号类型均可)。
+ // 如果这个值等于0或者正整数,那么它指定的是在 JSON 数组中的位置(从0开始)。如果这个值是负数,
+ // 那么它指定的是 JSON 数组中从最后一个位置开始算起的位置。
+ //
+ // 举例说明:0 表示第一个位置,而 -2 表示倒数第二个位置。
+ After(firstParam any, otherParams ...any)
+
+ // Before completes the following operation of Insert(). It inserts value BEFORE
+ // specified position.
+ //
+ // The last parameter identifies the position where a new JSON is inserted after,
+ // it should ba an integer, no matter signed or unsigned. If the position is
+ // zero or positive integer, it tells the index of an array. If the position
+ // is negative, it tells the backward index of an array.
+ //
+ // For example, 0 represents the first, and -2 represents the second last.
+ //
+ // Before 结束并完成 Insert() 函数的后续插入操作,表示插入到指定位置的后面。
+ //
+ // 在 Before 函数的最后一个参数指定了被插入的 JSON 数组的位置,这个参数应当是一个整型
+ // (有无符号类型均可)。
+ // 如果这个值等于0或者正整数,那么它指定的是在 JSON 数组中的位置(从0开始)。如果这个值是负数,
+ // 那么它指定的是 JSON 数组中从最后一个位置开始算起的位置。
+ //
+ // 举例说明:0 表示第一个位置,而 -2 表示倒数第二个位置。
+ Before(firstParam any, otherParams ...any)
+}
+
+type mInsert struct {
+ inserter Inserter
+}
+
+// MustInsert is just like Insert, but not returning sub-value or error.
+func (v *V) MustInsert(child any) MustInserter {
+ ins := v.Insert(child)
+ return &mInsert{
+ inserter: ins,
+ }
+}
+
+// MustInsertString is just like InsertString, but not returning sub-value or error.
+func (v *V) MustInsertString(s string) MustInserter {
+ return v.MustInsert(NewString(s))
+}
+
+// MustInsertBool is just like InsertBool, but not returning sub-value or error.
+func (v *V) MustInsertBool(b bool) MustInserter {
+ return v.MustInsert(NewBool(b))
+}
+
+// MustInsertInt is just like InsertInt, but not returning sub-value or error.
+func (v *V) MustInsertInt(i int) MustInserter {
+ return v.MustInsert(NewInt(i))
+}
+
+// MustInsertInt64 is just like InsertInt64, but not returning sub-value or error.
+func (v *V) MustInsertInt64(i int64) MustInserter {
+ return v.MustInsert(NewInt64(i))
+}
+
+// MustInsertInt32 is just like InsertInt32, but not returning sub-value or error.
+func (v *V) MustInsertInt32(i int32) MustInserter {
+ return v.MustInsert(NewInt32(i))
+}
+
+// MustInsertUint is just like InsertUint, but not returning sub-value or error.
+func (v *V) MustInsertUint(u uint) MustInserter {
+ return v.MustInsert(NewUint(u))
+}
+
+// MustInsertUint64 is just like InsertUint64, but not returning sub-value or error.
+func (v *V) MustInsertUint64(u uint64) MustInserter {
+ return v.MustInsert(NewUint64(u))
+}
+
+// MustInsertUint32 is just like InsertUint32, but not returning sub-value or error.
+func (v *V) MustInsertUint32(u uint32) MustInserter {
+ return v.MustInsert(NewUint32(u))
+}
+
+// MustInsertFloat64 is just like InsertFloat64, but not returning sub-value or error.
+func (v *V) MustInsertFloat64(f float64) MustInserter {
+ return v.MustInsert(NewFloat64(f))
+}
+
+// MustInsertFloat32 is just like InsertFloat32, but not returning sub-value or error.
+func (v *V) MustInsertFloat32(f float32) MustInserter {
+ return v.MustInsert(NewFloat32(f))
+}
+
+// MustInsertNull is just like InsertNull, but not returning sub-value or error.
+func (v *V) MustInsertNull() MustInserter {
+ return v.MustInsert(NewNull())
+}
+
+// MustInsertObject is just like InsertObject, but not returning sub-value or error.
+func (v *V) MustInsertObject() MustInserter {
+ return v.MustInsert(NewObject())
+}
+
+// MustInsertArray is just like InsertArray, but not returning sub-value or error.
+func (v *V) MustInsertArray() MustInserter {
+ return v.MustInsert(NewArray())
+}
+
+func (ins *mInsert) Before(firstParam any, otherParams ...any) {
+ _, _ = ins.inserter.Before(firstParam, otherParams...)
+}
+
+func (ins *mInsert) After(firstParam any, otherParams ...any) {
+ _, _ = ins.inserter.After(firstParam, otherParams...)
+}
+
+// ================ APPEND ================
+
+// MustAppender is just like Appender, but not returning sub-value or error.
+type MustAppender interface {
+ // InTheBeginning completes the following operation of Append().
+ //
+ // InTheBeginning 函数将 Append 函数指定的 JSON 值,添加到参数指定的数组的最前端
+ InTheBeginning(params ...any)
+
+ // InTheEnd completes the following operation of Append().
+ //
+ // InTheEnd 函数将 Append 函数指定的 JSON 值,添加到参数指定的数组的最后面
+ InTheEnd(params ...any)
+}
+
+type mAppender struct {
+ appender Appender
+}
+
+// Append starts appending a child JSON value to a JSON array.
+//
+// Append 开始将一个 JSON 值添加到一个数组中。需结合 InTheEnd() 和 InTheBeginning() 函数使用。
+func (v *V) MustAppend(child any) MustAppender {
+ a := v.Append(child)
+ return &mAppender{
+ appender: a,
+ }
+}
+
+// MustAppendString is just like AppendString, but not returning sub-value or error.
+func (v *V) MustAppendString(s string) MustAppender {
+ return v.MustAppend(NewString(s))
+}
+
+// MustAppendBytes is just like AppendBytes, but not returning sub-value or error.
+func (v *V) MustAppendBytes(b []byte) MustAppender {
+ return v.MustAppend(NewBytes(b))
+}
+
+// MustAppendBool is just like AppendBool, but not returning sub-value or error.
+func (v *V) MustAppendBool(b bool) MustAppender {
+ return v.MustAppend(NewBool(b))
+}
+
+// MustAppendInt is just like AppendInt, but not returning sub-value or error.
+func (v *V) MustAppendInt(i int) MustAppender {
+ return v.MustAppend(NewInt(i))
+}
+
+// MustAppendInt64 is just like AppendInt64, but not returning sub-value or error.
+func (v *V) MustAppendInt64(i int64) MustAppender {
+ return v.MustAppend(NewInt64(i))
+}
+
+// MustAppendInt32 is just like AppendInt32, but not returning sub-value or error.
+func (v *V) MustAppendInt32(i int32) MustAppender {
+ return v.MustAppend(NewInt32(i))
+}
+
+// MustAppendUint is just like AppendUint, but not returning sub-value or error.
+func (v *V) MustAppendUint(u uint) MustAppender {
+ return v.MustAppend(NewUint(u))
+}
+
+// MustAppendUint64 is just like AppendUint64, but not returning sub-value or error.
+func (v *V) MustAppendUint64(u uint64) MustAppender {
+ return v.MustAppend(NewUint64(u))
+}
+
+// MustAppendUint32 is just like AppendUint32, but not returning sub-value or error.
+func (v *V) MustAppendUint32(u uint32) MustAppender {
+ return v.MustAppend(NewUint32(u))
+}
+
+// MustAppendFloat64 is just like AppendFloat64, but not returning sub-value or error.
+func (v *V) MustAppendFloat64(f float64) MustAppender {
+ return v.MustAppend(NewFloat64(f))
+}
+
+// MustAppendFloat32 is just like AppendFloat32, but not returning sub-value or error.
+func (v *V) MustAppendFloat32(f float32) MustAppender {
+ return v.MustAppend(NewFloat32(f))
+}
+
+// MustAppendNull is just like AppendNull, but not returning sub-value or error.
+func (v *V) MustAppendNull() MustAppender {
+ return v.MustAppend(NewNull())
+}
+
+// MustAppendObject is just like AppendObject, but not returning sub-value or error.
+func (v *V) MustAppendObject() MustAppender {
+ return v.MustAppend(NewObject())
+}
+
+// MustAppendArray is just like AppendArray, but not returning sub-value or error.
+func (v *V) MustAppendArray() MustAppender {
+ return v.MustAppend(NewArray())
+}
+
+func (apd *mAppender) InTheBeginning(params ...any) {
+ _, _ = apd.appender.InTheBeginning(params...)
+}
+
+func (apd *mAppender) InTheEnd(params ...any) {
+ _, _ = apd.appender.InTheEnd(params...)
+}
+
+// ================ DELETE ================
+
+// MustDelete is just like Delete, but not returning error.
+func (v *V) MustDelete(firstParam any, otherParams ...any) {
+ _ = v.Delete(firstParam, otherParams...)
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer.go
new file mode 100644
index 0000000..415958d
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer.go
@@ -0,0 +1,18 @@
+// Package buffer implements a marshaling buffer for jsonvalue
+package buffer
+
+// Buffer defines a buffer type
+type Buffer interface {
+ WriteByte(byte) error
+ Write(d []byte) (int, error)
+ WriteString(s string) (int, error)
+ WriteRune(r rune) (int, error)
+ Bytes() []byte
+}
+
+// NewBuffer returns a buffer
+func NewBuffer() Buffer {
+ return &buffer{
+ buff: make([]byte, 0, 4096),
+ }
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_impl.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_impl.go
new file mode 100644
index 0000000..5a4be13
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_impl.go
@@ -0,0 +1,32 @@
+package buffer
+
+import (
+ "github.com/Andrew-M-C/go.jsonvalue/internal/unsafe"
+)
+
+type buffer struct {
+ buff []byte
+}
+
+func (b *buffer) WriteByte(c byte) error {
+ b.buff = append(b.buff, c)
+ return nil
+}
+
+func (b *buffer) Write(d []byte) (int, error) {
+ b.buff = append(b.buff, d...)
+ return len(d), nil
+}
+
+func (b *buffer) WriteString(s string) (int, error) {
+ d := unsafe.StoB(s)
+ return b.Write(d)
+}
+
+func (b *buffer) WriteRune(r rune) (int, error) {
+ return b.WriteString(string(r))
+}
+
+func (b *buffer) Bytes() []byte {
+ return b.buff
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_internal.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_internal.go
new file mode 100644
index 0000000..68027d1
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/buffer/buffer_internal.go
@@ -0,0 +1 @@
+package buffer
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/unsafe/unsafe.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/unsafe/unsafe.go
new file mode 100644
index 0000000..53f95ec
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/internal/unsafe/unsafe.go
@@ -0,0 +1,18 @@
+package unsafe
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// BtoS []byte to string
+func BtoS(b []byte) string {
+ return *(*string)(unsafe.Pointer(&b))
+}
+
+// StoB string to []byte
+func StoB(s string) []byte {
+ sh := (*reflect.SliceHeader)(unsafe.Pointer(&s))
+ sh.Cap = sh.Len
+ return *(*[]byte)(unsafe.Pointer(sh))
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/iteration.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/iteration.go
new file mode 100644
index 0000000..ca182a1
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/iteration.go
@@ -0,0 +1,150 @@
+package jsonvalue
+
+import "sort"
+
+// Deprecated: ObjectIter is a deprecated type.
+type ObjectIter struct {
+ K string
+ V *V
+}
+
+// Deprecated: ArrayIter is a deprecated type.
+type ArrayIter struct {
+ I int
+ V *V
+}
+
+// RangeObjects goes through each children when this is an object value
+//
+// Return true in callback to continue range iteration, while false to break.
+//
+// 若当前 JSON 值是一个 object 类型时,RangeObjects 遍历所有的键值对。
+//
+// 在回调函数中返回 true 表示继续迭代,返回 false 表示退出迭代
+func (v *V) RangeObjects(callback func(k string, v *V) bool) {
+ if !v.IsObject() {
+ return
+ }
+ if nil == callback {
+ return
+ }
+
+ for k, c := range v.children.object {
+ ok := callback(k, c.v)
+ if !ok {
+ break
+ }
+ }
+}
+
+// RangeObjectsBySetSequence acts just like RangeObjects, but the key sequence
+// is arranged by when a key is set to the given object.
+//
+// RangeObjectsBySetSequence 类似于 RangeObjects 函数, 但是 key 的顺序会依照其被 set
+// 进这个 object 的顺序传递。
+func (v *V) RangeObjectsBySetSequence(callback func(k string, v *V) bool) {
+ if !v.IsObject() {
+ return
+ }
+ if nil == callback {
+ return
+ }
+
+ type keysAndID struct {
+ k string
+ id uint32
+ v *V
+ }
+
+ kvs := make([]keysAndID, 0, len(v.children.object))
+ for k, child := range v.children.object {
+ kvs = append(kvs, keysAndID{
+ k: k,
+ id: child.id,
+ v: child.v,
+ })
+ }
+ sort.Slice(kvs, func(i, j int) bool {
+ return kvs[i].id <= kvs[j].id
+ })
+
+ for _, kv := range kvs {
+ ok := callback(kv.k, kv.v)
+ if !ok {
+ break
+ }
+ }
+}
+
+// Deprecated: IterObjects is deprecated, please Use ForRangeObj() instead.
+func (v *V) IterObjects() <-chan *ObjectIter {
+ ch := make(chan *ObjectIter, len(v.children.object))
+
+ go func() {
+ for k, c := range v.children.object {
+ ch <- &ObjectIter{
+ K: k,
+ V: c.v,
+ }
+ }
+ close(ch)
+ }()
+ return ch
+}
+
+// ForRangeObj returns a map which can be used in for - range block to iteration KVs in a JSON object value.
+//
+// ForRangeObj 返回一个 map 类型,用于使用 for - range 块迭代 JSON 对象类型的子成员。
+func (v *V) ForRangeObj() map[string]*V {
+ res := make(map[string]*V, len(v.children.object))
+ for k, c := range v.children.object {
+ res[k] = c.v
+ }
+ return res
+}
+
+// RangeArray goes through each children when this is an array value
+//
+// Return true in callback to continue range iteration, while false to break.
+//
+// 若当前 JSON 值是一个 array 类型时,RangeArray 遍历所有的数组成员。
+//
+// 在回调函数中返回 true 表示继续迭代,返回 false 表示退出迭代
+func (v *V) RangeArray(callback func(i int, v *V) bool) {
+ if !v.IsArray() {
+ return
+ }
+ if nil == callback {
+ return
+ }
+
+ for i, child := range v.children.arr {
+ if ok := callback(i, child); !ok {
+ break
+ }
+ }
+}
+
+// Deprecated: IterArray is deprecated, please Use ForRangeArr() instead.
+func (v *V) IterArray() <-chan *ArrayIter {
+ c := make(chan *ArrayIter, len(v.children.arr))
+
+ go func() {
+ for i, child := range v.children.arr {
+ c <- &ArrayIter{
+ I: i,
+ V: child,
+ }
+ }
+ close(c)
+ }()
+ return c
+}
+
+// ForRangeArr returns a slice which can be used in for - range block to iteration KVs in a JSON array value.
+//
+// ForRangeObj 返回一个切片,用于使用 for - range 块迭代 JSON 数组类型的子成员。
+func (v *V) ForRangeArr() []*V {
+ res := make([]*V, 0, len(v.children.arr))
+ return append(res, v.children.arr...)
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue.go
new file mode 100644
index 0000000..d9e64de
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue.go
@@ -0,0 +1,598 @@
+// Package jsonvalue is for JSON parsing and setting. It is used in situations those
+// Go structures cannot achieve, or "map[string]any" could not do properly.
+//
+// As a quick start:
+//
+// v := jsonvalue.NewObject()
+// v.SetString("Hello, JSON").At("someObject", "someObject", "someObject", "message") // automatically create sub objects
+// fmt.Println(v.MustMarshalString()) // marshal to string type. Use MustMarshal if you want []byte instead.
+// // Output:
+// // {"someObject":{"someObject":{"someObject":{"message":"Hello, JSON!"}}}
+//
+// If you want to parse raw JSON data, use Unmarshal()
+//
+// raw := []byte(`{"message":"hello, world"}`)
+// v, err := jsonvalue.Unmarshal(raw)
+// s, _ := v.GetString("message")
+// fmt.Println(s)
+// // Output:
+// // hello, world
+//
+// jsonvalue 包用于 JSON 的解析(反序列化)和编码(序列化)。通常情况下我们用 struct 来处理
+// 结构化的 JSON,但是有时候使用 struct 不方便或者是功能不足的时候,go 一般而言使用的是
+// "map[string]any",但是后者也有很多不方便的地方。本包即是用于替代这些不方便的情况的。
+//
+// 快速上手:
+//
+// v := jsonvalue.NewObject()
+// v.SetString("Hello, JSON").At("someObject", "someObject", "someObject", "message") // 自动创建子成员
+// fmt.Println(v.MustMarshalString()) // 序列化为 string 类型,如果你要 []byte 类型,则使用 MustMarshal 函数。
+// // 输出:
+// // {"someObject":{"someObject":{"someObject":{"message":"Hello, JSON!"}}}
+//
+// 如果要反序列化原始的 JSON 文本,则使用 Unmarshal():
+//
+// raw := []byte(`{"message":"hello, world"}`)
+// v, err := jsonvalue.Unmarshal(raw)
+// s, _ := v.GetString("message")
+// fmt.Println(s)
+// // 输出:
+// // hello, world
+package jsonvalue
+
+import (
+ "bytes"
+ "strconv"
+ "strings"
+
+ "github.com/Andrew-M-C/go.jsonvalue/internal/unsafe"
+)
+
+// ValueType identifying JSON value type
+type ValueType int
+
+const (
+ // NotExist type tells that this JSON value is not exist or legal
+ NotExist ValueType = iota
+ // String JSON string type
+ String
+ // Number JSON number type
+ Number
+ // Object JSON object type
+ Object
+ // Array JSON array type
+ Array
+ // Boolean JSON boolean type
+ Boolean
+ // Null JSON null type
+ Null
+ // Unknown unknown JSON type
+ Unknown
+)
+
+var typeStr = [Unknown + 1]string{
+ "illegal",
+ "string",
+ "number",
+ "object",
+ "array",
+ "boolean",
+ "null",
+ "unknown",
+}
+
+// String show the type name of JSON
+func (t ValueType) String() string {
+ if t > Unknown {
+ t = NotExist
+ } else if t < 0 {
+ t = NotExist
+ }
+ return typeStr[int(t)]
+}
+
+// ValueType returns the type of this JSON value.
+func (v *V) ValueType() ValueType {
+ return v.valueType
+}
+
+// V is the main type of jsonvalue, representing a JSON value.
+//
+// V 是 jsonvalue 的主类型,表示一个 JSON 值。
+type V struct {
+ valueType ValueType
+
+ srcByte []byte
+
+ num num
+ valueStr string
+ valueBool bool
+ children children
+}
+
+type num struct {
+ negative bool
+ floated bool
+ i64 int64
+ u64 uint64
+ f64 float64
+}
+
+type childWithProperty struct {
+ id uint32
+ v *V
+}
+
+type children struct {
+ incrID uint32
+ arr []*V
+ object map[string]childWithProperty
+
+ // As official json package supports caseless key accessing, I decide to do it as well
+ lowerCaseKeys map[string]map[string]struct{}
+}
+
+func (c *children) deepCopy() children {
+ res := children{
+ incrID: c.incrID,
+ }
+
+ // if length or arr > 0, this must be an array type
+ if len(c.arr) > 0 {
+ for _, v := range c.arr {
+ res.arr = append(res.arr, v.deepCopy())
+ }
+ return res
+ }
+
+ // if this is an object?
+ if c.object != nil {
+ res.object = make(map[string]childWithProperty, len(c.object))
+ for key, item := range c.object {
+ res.object[key] = childWithProperty{
+ id: item.id,
+ v: item.v.deepCopy(),
+ }
+ }
+ }
+
+ // no need to copy lowerCaseKeys because it could be rebuild after calling
+ // Caseless() next time
+
+ return res
+}
+
+func addCaselessKey(v *V, k string) {
+ if v.children.lowerCaseKeys == nil {
+ return
+ }
+ lowerK := strings.ToLower(k)
+ keys, exist := v.children.lowerCaseKeys[lowerK]
+ if !exist {
+ keys = make(map[string]struct{})
+ v.children.lowerCaseKeys[lowerK] = keys
+ }
+ keys[k] = struct{}{}
+}
+
+func delCaselessKey(v *V, k string) {
+ if v.children.lowerCaseKeys == nil {
+ return
+ }
+ lowerK := strings.ToLower(k)
+ keys, exist := v.children.lowerCaseKeys[lowerK]
+ if !exist {
+ return
+ }
+
+ delete(keys, k)
+
+ if len(keys) == 0 {
+ delete(v.children.lowerCaseKeys, lowerK)
+ }
+}
+
+// MustUnmarshalString just like UnmarshalString(). If error occurs, a JSON value
+// with "NotExist" type would be returned, which could do nothing and return nothing
+// in later use. It is useful to shorten codes.
+//
+// MustUnmarshalString 的逻辑与 UnmarshalString() 相同,不过如果错误的话,会返回一个类型未
+// "NotExist" 的 JSON 值,这个值在后续的操作中将无法返回有效的数据,或者是执行任何有效的操作。
+// 但起码不会导致程序 panic,便于使用短代码实现一些默认逻辑。
+func MustUnmarshalString(s string) *V {
+ v, _ := UnmarshalString(s)
+ return v
+}
+
+// UnmarshalString is equivalent to Unmarshal([]byte(b)), but more efficient.
+//
+// UnmarshalString 等效于 Unmarshal([]byte(b)),但效率更高。
+func UnmarshalString(s string) (*V, error) {
+ // reference: https://stackoverflow.com/questions/41591097/slice-bounds-out-of-range-when-using-unsafe-pointer
+ // sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
+ // bh := reflect.SliceHeader{
+ // Data: sh.Data,
+ // Len: sh.Len,
+ // Cap: sh.Len,
+ // }
+ // b := *(*[]byte)(unsafe.Pointer(&bh))
+ b := []byte(s)
+ return UnmarshalNoCopy(b)
+}
+
+// MustUnmarshal just like Unmarshal(). If error occurs, a JSON value with "NotExist"
+// type would be returned, which could do nothing and return nothing in later use. It
+// is useful to shorten codes.
+//
+// MustUnmarshal 的逻辑与 Unmarshal() 相同,不过如果错误的话,会返回一个类型未 "NotExist" 的
+// JSON 值,这个值在后续的操作中将无法返回有效的数据,或者是执行任何有效的操作。但起码不会导致程序
+// panic,便于使用短代码实现一些默认逻辑。
+func MustUnmarshal(b []byte) *V {
+ v, _ := Unmarshal(b)
+ return v
+}
+
+// Unmarshal parse raw bytes(encoded in UTF-8 or pure AscII) and returns a *V instance.
+//
+// Unmarshal 解析原始的字节类型数据(以 UTF-8 或纯 AscII 编码),并返回一个 *V 对象。
+func Unmarshal(b []byte) (ret *V, err error) {
+ le := len(b)
+ if le == 0 {
+ return nil, ErrNilParameter
+ }
+
+ trueB := make([]byte, len(b))
+ copy(trueB, b)
+ it := iter(trueB)
+ p := newPool(len(b))
+ ret, err = unmarshalWithIter(p, it, 0)
+ p.release()
+ return
+}
+
+// MustUnmarshalNoCopy just like UnmarshalNoCopy(). If error occurs, a JSON value
+// with "NotExist" type would be returned, which could do nothing and return nothing
+// in later use. It is useful to shorten codes.
+//
+// MustUnmarshalNoCopy 的逻辑与 UnmarshalNoCopy() 相同,不过如果错误的话,会返回一个类型未
+// "NotExist" 的 JSON 值,这个值在后续的操作中将无法返回有效的数据,或者是执行任何有效的操作。
+// 但起码不会导致程序 panic,便于使用短代码实现一些默认逻辑。
+func MustUnmarshalNoCopy(b []byte) *V {
+ v, _ := UnmarshalNoCopy(b)
+ return v
+}
+
+// UnmarshalNoCopy is same as Unmarshal, but it does not copy another []byte instance
+// for saving CPU time. But pay attention that the input []byte may be used as buffer
+// by jsonvalue and mey be modified.
+//
+// UnmarshalNoCopy 与 Unmarshal 相同,但是这个函数在解析过程中不会重新复制一个 []byte,对于大
+// json 的解析而言能够大大节省时间。但请注意传入的 []byte 变量可能会被 jsonvalue 用作缓冲区,并进行修改
+func UnmarshalNoCopy(b []byte) (ret *V, err error) {
+ le := len(b)
+ if le == 0 {
+ return &V{}, ErrNilParameter
+ }
+ p := newPool(len(b))
+ ret, err = unmarshalWithIter(p, iter(b), 0)
+ p.release()
+ return
+}
+
+// ==== type access ====
+
+// IsObject tells whether value is an object
+//
+// IsObject 判断当前值是不是一个对象类型
+func (v *V) IsObject() bool {
+ return v.valueType == Object
+}
+
+// IsArray tells whether value is an array
+//
+// IsArray 判断当前值是不是一个数组类型
+func (v *V) IsArray() bool {
+ return v.valueType == Array
+}
+
+// IsString tells whether value is a string
+//
+// IsString 判断当前值是不是一个字符串类型
+func (v *V) IsString() bool {
+ return v.valueType == String
+}
+
+// IsNumber tells whether value is a number
+//
+// IsNumber 判断当前值是不是一个数字类型
+func (v *V) IsNumber() bool {
+ return v.valueType == Number
+}
+
+// IsFloat tells whether value is a float point number. If there is no decimal point
+// in original text, it returns false while IsNumber returns true.
+//
+// IsFloat 判断当前值是不是一个浮点数类型。如果给定的数不包含小数点,那么即便是数字类型,该函数也会返回 false.
+func (v *V) IsFloat() bool {
+ if v.valueType != Number {
+ return false
+ }
+ return v.num.floated
+}
+
+// IsInteger tells whether value is a fix point integer
+//
+// IsNumber 判断当前值是不是一个定点数整型
+func (v *V) IsInteger() bool {
+ if v.valueType != Number {
+ return false
+ }
+ return !(v.num.floated)
+}
+
+// IsNegative tells whether value is a negative number
+//
+// IsNegative 判断当前值是不是一个负数
+func (v *V) IsNegative() bool {
+ if v.valueType != Number {
+ return false
+ }
+ return v.num.negative
+}
+
+// IsPositive tells whether value is a positive number
+//
+// IsPositive 判断当前值是不是一个正数
+func (v *V) IsPositive() bool {
+ if v.valueType != Number {
+ return false
+ }
+ return !(v.num.negative)
+}
+
+// GreaterThanInt64Max return true when ALL conditions below are met:
+// 1. It is a number value.
+// 2. It is a positive integer.
+// 3. Its value is greater than 0x7fffffffffffffff.
+//
+// GreaterThanInt64Max 判断当前值是否超出 int64 可表示的范围。当以下条件均成立时,返回 true,
+// 否则返回 false:
+// 1. 是一个数字类型值.
+// 2. 是一个正整型数字.
+// 3. 该正整数的值大于 0x7fffffffffffffff.
+func (v *V) GreaterThanInt64Max() bool {
+ if v.valueType != Number {
+ return false
+ }
+ if v.num.negative {
+ return false
+ }
+ return v.num.u64 > 0x7fffffffffffffff
+}
+
+// IsBoolean tells whether value is a boolean
+//
+// IsBoolean 判断当前值是不是一个布尔类型
+func (v *V) IsBoolean() bool {
+ return v.valueType == Boolean
+}
+
+// IsNull tells whether value is a null
+//
+// IsBoolean 判断当前值是不是一个空类型
+func (v *V) IsNull() bool {
+ return v.valueType == Null
+}
+
+// Bool returns represented bool value. If value is not boolean, returns false.
+//
+// Bool 返回布尔类型值。如果当前值不是布尔类型,则判断是否为 string,不是 string 返回 false;
+// 是 string 的话则返回字面值是否等于 true
+func (v *V) Bool() bool {
+ if v.valueType == Boolean {
+ return v.valueBool
+ }
+ b, _ := getBoolAndErrorFromValue(v)
+ return b.valueBool
+}
+
+// Int returns represented int value. If value is not a number, returns zero.
+//
+// Int 返回 int 类型值。如果当前值不是数字类型,则返回 0。
+func (v *V) Int() int {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Int()
+ }
+ return int(v.num.i64)
+}
+
+// Uint returns represented uint value. If value is not a number, returns zero.
+//
+// Uint 返回 uint 类型值。如果当前值不是数字类型,则返回 0。
+func (v *V) Uint() uint {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Uint()
+ }
+ return uint(v.num.u64)
+}
+
+// Int64 returns represented int64 value. If value is not a number, returns zero.
+//
+// Int64 返回 int64 类型值。如果当前值不是数字类型,则返回 0。
+func (v *V) Int64() int64 {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Int64()
+ }
+ return int64(v.num.i64)
+}
+
+// Uint64 returns represented uint64 value. If value is not a number, returns zero.
+//
+// Uint64 返回 uint64 类型值。如果当前值不是数字类型,则返回 0。
+func (v *V) Uint64() uint64 {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Uint64()
+ }
+ return uint64(v.num.u64)
+}
+
+// Int32 returns represented int32 value. If value is not a number, returns zero.
+//
+// Int32 返回 int32 类型值。如果当前值不是数字类型,则返回 0。
+func (v *V) Int32() int32 {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Int32()
+ }
+ return int32(v.num.i64)
+}
+
+// Uint32 returns represented uint32 value. If value is not a number, returns zero.
+//
+// Uint32 返回 uint32 类型值。如果当前值不是数字类型,则返回 0。
+func (v *V) Uint32() uint32 {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Uint32()
+ }
+ return uint32(v.num.u64)
+}
+
+// Float64 returns represented float64 value. If value is not a number, returns zero.
+//
+// Float64 返回 float64 类型值。如果当前值不是数字类型,则返回 0.0。
+func (v *V) Float64() float64 {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Float64()
+ }
+ return v.num.f64
+}
+
+// Float32 returns represented float32 value. If value is not a number, returns zero.
+//
+// Float32 返回 float32 类型值。如果当前值不是数字类型,则返回 0.0。
+func (v *V) Float32() float32 {
+ if v.valueType != Number {
+ return getNumberFromNotNumberValue(v).Float32()
+ }
+ return float32(v.num.f64)
+}
+
+// Bytes returns represented binary data which is encoded as Base64 string. []byte{}
+// would be returned if value is
+// not a string type or base64 decode failed.
+//
+// Bytes 返回以 Base64 编码在 string 类型中的二进制数据。如果当前值不是字符串类型,或者是 base64
+// 编码失败,则返回 []byte{}。
+func (v *V) Bytes() []byte {
+ if v.valueType != String {
+ return []byte{}
+ }
+ b, err := internal.b64.DecodeString(v.valueStr)
+ if err != nil {
+ return []byte{}
+ }
+ return b
+}
+
+func (v *V) deepCopy() *V {
+ if v == nil {
+ return &V{}
+ }
+
+ switch v.valueType {
+ default:
+ // fallthrough
+ // case NotExist, Unknown:
+ return &V{}
+ case String:
+ return NewString(v.String())
+ case Number:
+ res := new(globalPool{}, Number)
+ res.num = v.num
+ res.srcByte = v.srcByte
+ return res
+ case Object:
+ res := new(globalPool{}, Object)
+ res.children = v.children.deepCopy()
+ return res
+ case Array:
+ res := new(globalPool{}, Array)
+ res.children = v.children.deepCopy()
+ return res
+ case Boolean:
+ return NewBool(v.Bool())
+ case Null:
+ return NewNull()
+ }
+}
+
+type deepCopier interface {
+ deepCopy() *V
+}
+
+// String returns represented string value or the description for the jsonvalue.V
+// instance if it is not a string.
+//
+// String 返回 string 类型值。如果当前值不是字符串类型,则返回当前 *V 类型的描述说明。
+func (v *V) String() string {
+ if v == nil {
+ return "nil"
+ }
+ switch v.valueType {
+ default:
+ return ""
+ case Null:
+ return "null"
+ case Number:
+ if len(v.srcByte) > 0 {
+ return unsafe.BtoS(v.srcByte)
+ }
+ return strconv.FormatFloat(v.num.f64, 'g', -1, 64)
+ case String:
+ return v.valueStr
+ case Boolean:
+ return formatBool(v.valueBool)
+ case Object:
+ return packObjChildren(v)
+ case Array:
+ return packArrChildren(v)
+ }
+}
+
+func packObjChildren(v *V) string {
+ buf := bytes.Buffer{}
+ bufObjChildren(v, &buf)
+ return buf.String()
+}
+
+func bufObjChildren(v *V, buf *bytes.Buffer) {
+ buf.WriteByte('{')
+ i := 0
+ for k, v := range v.children.object {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(k)
+ buf.WriteString(": ")
+ buf.WriteString(v.v.String())
+ i++
+ }
+ buf.WriteByte('}')
+}
+
+func packArrChildren(v *V) string {
+ buf := bytes.Buffer{}
+ bufArrChildren(v, &buf)
+ return buf.String()
+}
+
+func bufArrChildren(v *V, buf *bytes.Buffer) {
+ buf.WriteByte('[')
+ v.RangeArray(func(i int, v *V) bool {
+ if i > 0 {
+ buf.WriteString(", ")
+ }
+ buf.WriteString(v.String())
+ return true
+ })
+ buf.WriteByte(']')
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue_internal.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue_internal.go
new file mode 100644
index 0000000..f797560
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/jsonvalue_internal.go
@@ -0,0 +1,112 @@
+package jsonvalue
+
+import (
+ "encoding"
+ "encoding/base64"
+ "encoding/json"
+ "reflect"
+ "sync/atomic"
+)
+
+var internal = struct {
+ b64 *base64.Encoding
+
+ defaultMarshalOption *Opt
+
+ predict struct {
+ bytesPerValue uint64
+ calcStorage uint64 // upper 32 bits - size; lower 32 bits - value count
+ }
+
+ types struct {
+ JSONMarshaler reflect.Type
+ TextMarshaler reflect.Type
+ }
+}{}
+
+func init() {
+ internal.b64 = base64.StdEncoding
+ internal.defaultMarshalOption = emptyOptions()
+ internalAddPredictSizePerValue(16, 1)
+
+ internal.types.JSONMarshaler = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
+ internal.types.TextMarshaler = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+}
+
+func internalLoadPredictSizePerValue() int {
+ if n := atomic.LoadUint64(&internal.predict.bytesPerValue); n > 0 {
+ return int(n)
+ }
+
+ v := atomic.LoadUint64(&internal.predict.calcStorage)
+ total := v >> 32
+ num := v & 0xFFFFFFFF
+ return int(total / num)
+}
+
+func internalAddPredictSizePerValue(total, num int) {
+ v := atomic.LoadUint64(&internal.predict.calcStorage)
+ preTotal := v >> 32
+ preNum := v & 0xFFFFFFFF
+
+ nextTotal := uint64(total) + preTotal
+ nextNum := uint64(num) + preNum
+
+ if nextTotal < 0x7FFFFFFF {
+ v := (nextTotal << 32) + nextNum
+ atomic.StoreUint64(&internal.predict.calcStorage, v)
+ return
+ }
+
+ per := nextTotal / nextNum
+ atomic.StoreUint64(&internal.predict.bytesPerValue, per)
+ atomic.StoreUint64(&internal.predict.calcStorage, (per<<32)+1)
+}
+
+type pool interface {
+ get() *V
+}
+
+type globalPool struct{}
+
+func (globalPool) get() *V {
+ return &V{}
+}
+
+type poolImpl struct {
+ pool []V
+
+ count int
+ actual int // actual counted values
+
+ rawSize int
+}
+
+func newPool(rawSize int) *poolImpl {
+ per := internalLoadPredictSizePerValue()
+ cnt := rawSize / per
+
+ p := &poolImpl{
+ pool: make([]V, cnt),
+ count: cnt,
+ actual: 0,
+ rawSize: rawSize,
+ }
+
+ return p
+}
+
+func (p *poolImpl) get() *V {
+ if p.actual < p.count {
+ v := &p.pool[p.actual]
+ p.actual++
+ return v
+ }
+
+ p.actual++
+ return globalPool{}.get()
+}
+
+func (p *poolImpl) release() {
+ internalAddPredictSizePerValue(p.rawSize, p.actual)
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/marshal.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/marshal.go
new file mode 100644
index 0000000..405d9d4
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/marshal.go
@@ -0,0 +1,325 @@
+package jsonvalue
+
+import (
+ "encoding/json"
+ "fmt"
+ "math"
+ "strings"
+
+ "github.com/Andrew-M-C/go.jsonvalue/internal/buffer"
+ "github.com/Andrew-M-C/go.jsonvalue/internal/unsafe"
+)
+
+// MustMarshal is the same as Marshal. If error occurs, an empty byte slice will be returned.
+//
+// MustMarshal 与 Marshal 相同,但是当错误发生时,什么都不做,直接返回空数据
+func (v *V) MustMarshal(opts ...Option) []byte {
+ ret, err := v.Marshal(opts...)
+ if err != nil {
+ return []byte{}
+ }
+ return ret
+}
+
+// MustMarshalString is the same as MarshalString, If error occurs, an empty byte slice will be returned.
+//
+// MustMarshalString 与 MarshalString 相同,但是当错误发生时,什么都不做,直接返回空数据
+func (v *V) MustMarshalString(opt ...Option) string {
+ ret, err := v.MarshalString(opt...)
+ if err != nil {
+ return ""
+ }
+ return ret
+}
+
+// Marshal returns marshaled bytes.
+//
+// Marshal 返回序列化后的 JSON 字节序列。
+func (v *V) Marshal(opts ...Option) (b []byte, err error) {
+ if NotExist == v.valueType {
+ return nil, ErrValueUninitialized
+ }
+
+ buf := buffer.NewBuffer()
+ opt := combineOptions(opts)
+
+ err = marshalToBuffer(v, nil, buf, opt)
+ if err != nil {
+ return nil, err
+ }
+
+ b = buf.Bytes()
+ return b, nil
+}
+
+// MarshalString is same with Marshal, but returns string. It is much more efficient than string(b).
+//
+// MarshalString 与 Marshal 相同, 不同的是返回 string 类型。它比 string(b) 操作更高效。
+func (v *V) MarshalString(opts ...Option) (s string, err error) {
+ b, err := v.Marshal(opts...)
+ if err != nil {
+ return "", err
+ }
+ return unsafe.BtoS(b), nil
+}
+
+func marshalToBuffer(v *V, parentInfo *ParentInfo, buf buffer.Buffer, opt *Opt) (err error) {
+ switch v.valueType {
+ default:
+ // do nothing
+ case String:
+ marshalString(v, buf, opt)
+ case Boolean:
+ marshalBoolean(v, buf)
+ case Number:
+ err = marshalNumber(v, buf, opt)
+ case Null:
+ marshalNull(buf)
+ case Object:
+ marshalObject(v, parentInfo, buf, opt)
+ case Array:
+ marshalArray(v, parentInfo, buf, opt)
+ }
+ return err
+}
+
+func marshalString(v *V, buf buffer.Buffer, opt *Opt) {
+ _ = buf.WriteByte('"')
+ escapeStringToBuff(v.valueStr, buf, opt)
+ _ = buf.WriteByte('"')
+}
+
+func marshalBoolean(v *V, buf buffer.Buffer) {
+ _, _ = buf.WriteString(formatBool(v.valueBool))
+}
+
+func marshalNumber(v *V, buf buffer.Buffer, opt *Opt) error {
+ if b := v.srcByte; len(b) > 0 {
+ _, _ = buf.Write(b)
+ return nil
+ }
+ // else, +Inf or -Inf or NaN
+ if math.IsInf(v.num.f64, 1) { // +Inf
+ return marshalInfP(buf, opt)
+ }
+ if math.IsInf(v.num.f64, -1) { // -Inf
+ return marshalInfN(buf, opt)
+ }
+
+ return marshalNaN(buf, opt)
+}
+
+func marshalNaN(buf buffer.Buffer, opt *Opt) error {
+ switch opt.FloatNaNHandleType {
+ default:
+ fallthrough
+ case FloatNaNTreatAsError:
+ return fmt.Errorf("%w: %v", ErrUnsupportedFloat, math.NaN())
+
+ case FloatNaNConvertToFloat:
+ if !isValidFloat(opt.FloatNaNToFloat) {
+ return fmt.Errorf("%w: %v", ErrUnsupportedFloatInOpt, opt.FloatNaNToFloat)
+ }
+ b, _ := json.Marshal(opt.FloatNaNToFloat)
+ _, _ = buf.Write(b)
+
+ case FloatNaNNull:
+ _, _ = buf.WriteString("null")
+
+ case FloatNaNConvertToString:
+ if s := opt.FloatNaNToString; s == "" {
+ _, _ = buf.WriteString(`"NaN"`)
+ } else {
+ _ = buf.WriteByte('"')
+ escapeStringToBuff(s, buf, opt)
+ _ = buf.WriteByte('"')
+ }
+ }
+
+ return nil
+}
+
+func marshalInfP(buf buffer.Buffer, opt *Opt) error {
+ switch opt.FloatInfHandleType {
+ default:
+ fallthrough
+ case FloatInfTreatAsError:
+ return fmt.Errorf("%w: %v", ErrUnsupportedFloat, math.Inf(1))
+
+ case FloatInfConvertToFloat:
+ if !isValidFloat(opt.FloatInfToFloat) {
+ return fmt.Errorf("%w: %v", ErrUnsupportedFloatInOpt, opt.FloatInfToFloat)
+ }
+ b, _ := json.Marshal(opt.FloatInfToFloat)
+ _, _ = buf.Write(b)
+
+ case FloatInfNull:
+ _, _ = buf.WriteString("null")
+
+ case FloatInfConvertToString:
+ if s := opt.FloatInfPositiveToString; s == "" {
+ _, _ = buf.WriteString(`"+Inf"`)
+ } else {
+ _ = buf.WriteByte('"')
+ escapeStringToBuff(s, buf, opt)
+ _ = buf.WriteByte('"')
+ }
+ }
+
+ return nil
+}
+
+func marshalInfN(buf buffer.Buffer, opt *Opt) error {
+ switch opt.FloatInfHandleType {
+ default:
+ fallthrough
+ case FloatInfTreatAsError:
+ return fmt.Errorf("%w: %v", ErrUnsupportedFloat, math.Inf(-1))
+
+ case FloatInfConvertToFloat:
+ if !isValidFloat(opt.FloatInfToFloat) {
+ return fmt.Errorf("%w: %v", ErrUnsupportedFloatInOpt, -opt.FloatInfToFloat)
+ }
+ b, _ := json.Marshal(-opt.FloatInfToFloat)
+ _, _ = buf.Write(b)
+
+ case FloatInfNull:
+ _, _ = buf.WriteString("null")
+
+ case FloatInfConvertToString:
+ _ = buf.WriteByte('"')
+ if s := opt.FloatInfNegativeToString; s != "" {
+ escapeStringToBuff(s, buf, opt)
+ } else if opt.FloatInfPositiveToString != "" {
+ s = "-" + strings.TrimLeft(opt.FloatInfPositiveToString, "+")
+ escapeStringToBuff(s, buf, opt)
+ } else {
+ _, _ = buf.WriteString(`-Inf`)
+ }
+ _ = buf.WriteByte('"')
+ }
+
+ return nil
+}
+
+func isValidFloat(f float64) bool {
+ if math.IsNaN(f) {
+ return false
+ }
+ if math.IsInf(f, 0) {
+ return false
+ }
+ return true
+}
+
+func marshalNull(buf buffer.Buffer) {
+ _, _ = buf.WriteString("null")
+}
+
+func marshalObject(v *V, parentInfo *ParentInfo, buf buffer.Buffer, opt *Opt) {
+ if len(v.children.object) == 0 {
+ _, _ = buf.WriteString("{}")
+ return
+ }
+
+ opt.indent.cnt++
+ _ = buf.WriteByte('{')
+
+ if opt.MarshalLessFunc != nil {
+ sov := newSortObjectV(v, parentInfo, opt)
+ sov.marshalObjectWithLessFunc(buf, opt)
+
+ } else if len(opt.MarshalKeySequence) > 0 {
+ sssv := newSortStringSliceV(v, opt)
+ sssv.marshalObjectWithStringSlice(buf, opt)
+
+ } else if opt.marshalBySetSequence {
+ sssv := newSortStringSliceVBySetSeq(v)
+ sssv.marshalObjectWithStringSlice(buf, opt)
+
+ } else {
+ writeObjectKVInRandomizedSequence(v, buf, opt)
+ }
+
+ opt.indent.cnt--
+ if opt.indent.enabled {
+ _ = buf.WriteByte('\n')
+ writeIndent(buf, opt)
+ }
+ _ = buf.WriteByte('}')
+}
+
+func writeObjectKVInRandomizedSequence(v *V, buf buffer.Buffer, opt *Opt) {
+ firstWritten := false
+ for k, child := range v.children.object {
+ firstWritten = writeObjectChildren(nil, buf, !firstWritten, k, child.v, opt)
+ }
+}
+
+func writeObjectChildren(
+ parentInfo *ParentInfo, buf buffer.Buffer, isFirstOne bool, key string, child *V, opt *Opt,
+) (written bool) {
+ if child.IsNull() && opt.OmitNull {
+ return false
+ }
+ if !isFirstOne {
+ _ = buf.WriteByte(',')
+ }
+
+ if opt.indent.enabled {
+ _ = buf.WriteByte('\n')
+ writeIndent(buf, opt)
+ }
+
+ _ = buf.WriteByte('"')
+ escapeStringToBuff(key, buf, opt)
+
+ if opt.indent.enabled {
+ _, _ = buf.WriteString("\": ")
+ } else {
+ _, _ = buf.WriteString("\":")
+ }
+
+ _ = marshalToBuffer(child, parentInfo, buf, opt)
+ return true
+}
+
+func writeIndent(buf buffer.Buffer, opt *Opt) {
+ _, _ = buf.WriteString(opt.indent.prefix)
+ for i := 0; i < opt.indent.cnt; i++ {
+ _, _ = buf.WriteString(opt.indent.indent)
+ }
+}
+
+func marshalArray(v *V, parentInfo *ParentInfo, buf buffer.Buffer, opt *Opt) {
+ if len(v.children.arr) == 0 {
+ _, _ = buf.WriteString("[]")
+ return
+ }
+
+ opt.indent.cnt++
+ _ = buf.WriteByte('[')
+
+ v.RangeArray(func(i int, child *V) bool {
+ if i > 0 {
+ _ = buf.WriteByte(',')
+ }
+ if opt.indent.enabled {
+ _ = buf.WriteByte('\n')
+ writeIndent(buf, opt)
+ }
+ if opt.MarshalLessFunc == nil {
+ _ = marshalToBuffer(child, nil, buf, opt)
+ } else {
+ _ = marshalToBuffer(child, newParentInfo(v, parentInfo, intKey(i)), buf, opt)
+ }
+ return true
+ })
+
+ opt.indent.cnt--
+ if opt.indent.enabled {
+ _ = buf.WriteByte('\n')
+ writeIndent(buf, opt)
+ }
+ _ = buf.WriteByte(']')
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/marshaler_unmarshaler.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/marshaler_unmarshaler.go
new file mode 100644
index 0000000..400ccfe
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/marshaler_unmarshaler.go
@@ -0,0 +1,44 @@
+package jsonvalue
+
+import (
+ "encoding"
+ "encoding/json"
+)
+
+var (
+ _ json.Marshaler = (*V)(nil)
+ _ json.Unmarshaler = (*V)(nil)
+
+ _ encoding.BinaryMarshaler = (*V)(nil)
+ _ encoding.BinaryUnmarshaler = (*V)(nil)
+)
+
+// MarshalJSON implements json.Marshaler
+func (v *V) MarshalJSON() ([]byte, error) {
+ return v.Marshal()
+}
+
+// UnmarshalJSON implements json.Unmarshaler
+func (v *V) UnmarshalJSON(b []byte) error {
+ res, err := Unmarshal(b)
+ if err != nil {
+ return err
+ }
+ *v = *res
+ return nil
+}
+
+// MarshalBinary implements encoding.BinaryMarshaler
+func (v *V) MarshalBinary() ([]byte, error) {
+ return v.Marshal()
+}
+
+// UnmarshalBinary implements encoding.BinaryUnmarshaler
+func (v *V) UnmarshalBinary(b []byte) error {
+ res, err := Unmarshal(b)
+ if err != nil {
+ return err
+ }
+ *v = *res
+ return nil
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/new.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/new.go
new file mode 100644
index 0000000..e2cb548
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/new.go
@@ -0,0 +1,273 @@
+package jsonvalue
+
+import (
+ "encoding/base64"
+ "fmt"
+ "math"
+ "reflect"
+ "strconv"
+)
+
+// New generate a new jsonvalue type via given type. If given type is not supported,
+// the returned type would equal to NotExist. If you are not sure whether given value
+// type is OK in runtime, use Import() instead.
+//
+// New 函数按照给定参数类型创建一个 jsonvalue 类型。如果给定参数不是 JSON 支持的类型, 那么返回的
+// *V 对象的类型为 NotExist。如果在代码中无法确定入参是否是 JSON 支持的类型, 请改用函数
+// Import()。
+func New(value any) *V {
+ v, _ := Import(value)
+ return v
+}
+
+// NewString returns an initialized string jsonvalue object
+//
+// NewString 用给定的 string 返回一个初始化好的字符串类型的 jsonvalue 值
+func NewString(s string) *V {
+ v := new(globalPool{}, String)
+ v.valueStr = s
+ return v
+}
+
+// NewBytes returns an initialized string with Base64 string by given bytes
+//
+// NewBytes 用给定的字节串,返回一个初始化好的字符串类型的 jsonvalue 值,内容是字节串 Base64 之后的字符串。
+func NewBytes(b []byte) *V {
+ s := base64.StdEncoding.EncodeToString(b)
+ return NewString(s)
+}
+
+// NewInt64 returns an initialized num jsonvalue object by int64 type
+//
+// NewInt64 用给定的 int64 返回一个初始化好的数字类型的 jsonvalue 值
+func NewInt64(i int64) *V {
+ v := new(globalPool{}, Number)
+ // v.num = &num{}
+ v.num.floated = false
+ v.num.negative = i < 0
+ v.num.f64 = float64(i)
+ v.num.i64 = i
+ v.num.u64 = uint64(i)
+ s := strconv.FormatInt(v.num.i64, 10)
+ v.srcByte = []byte(s)
+ return v
+}
+
+// NewUint64 returns an initialized num jsonvalue object by uint64 type
+//
+// NewUint64 用给定的 uint64 返回一个初始化好的数字类型的 jsonvalue 值
+func NewUint64(u uint64) *V {
+ v := new(globalPool{}, Number)
+ // v.num = &num{}
+ v.num.floated = false
+ v.num.negative = false
+ v.num.f64 = float64(u)
+ v.num.i64 = int64(u)
+ v.num.u64 = u
+ s := strconv.FormatUint(v.num.u64, 10)
+ v.srcByte = []byte(s)
+ return v
+}
+
+// NewInt returns an initialized num jsonvalue object by int type
+//
+// NewInt 用给定的 int 返回一个初始化好的数字类型的 jsonvalue 值
+func NewInt(i int) *V {
+ return NewInt64(int64(i))
+}
+
+// NewUint returns an initialized num jsonvalue object by uint type
+//
+// NewUint 用给定的 uint 返回一个初始化好的数字类型的 jsonvalue 值
+func NewUint(u uint) *V {
+ return NewUint64(uint64(u))
+}
+
+// NewInt32 returns an initialized num jsonvalue object by int32 type
+//
+// NewInt32 用给定的 int32 返回一个初始化好的数字类型的 jsonvalue 值
+func NewInt32(i int32) *V {
+ return NewInt64(int64(i))
+}
+
+// NewUint32 returns an initialized num jsonvalue object by uint32 type
+//
+// NewUint32 用给定的 uint32 返回一个初始化好的数字类型的 jsonvalue 值
+func NewUint32(u uint32) *V {
+ return NewUint64(uint64(u))
+}
+
+// NewBool returns an initialized boolean jsonvalue object
+//
+// NewBool 用给定的 bool 返回一个初始化好的布尔类型的 jsonvalue 值
+func NewBool(b bool) *V {
+ v := new(globalPool{}, Boolean)
+ v.valueBool = b
+ return v
+}
+
+// NewNull returns an initialized null jsonvalue object
+//
+// NewNull 返回一个初始化好的 null 类型的 jsonvalue 值
+func NewNull() *V {
+ v := new(globalPool{}, Null)
+ return v
+}
+
+// NewObject returns an object-typed jsonvalue object. If keyValues is specified, it will also create some key-values in
+// the object. Now we supports basic types only. Such as int/uint, int/int8/int16/int32/int64,
+// uint/uint8/uint16/uint32/uint64 series, string, bool, nil.
+//
+// NewObject 返回一个初始化好的 object 类型的 jsonvalue 值。可以使用可选的 map[string]any 类型参数初始化该 object 的下一级键值对,
+// 不过目前只支持基础类型,也就是: int/uint, int/int8/int16/int32/int64, uint/uint8/uint16/uint32/uint64, string, bool, nil。
+func NewObject(keyValues ...M) *V {
+ v := newObject(globalPool{})
+
+ if len(keyValues) > 0 {
+ kv := keyValues[0]
+ if kv != nil {
+ parseNewObjectKV(v, kv)
+ }
+ }
+
+ return v
+}
+
+// M is the alias of map[string]any
+type M map[string]any
+
+func parseNewObjectKV(v *V, kv M) {
+ for k, val := range kv {
+ rv := reflect.ValueOf(val)
+ switch rv.Kind() {
+ case reflect.Invalid:
+ v.MustSetNull().At(k)
+ case reflect.Bool:
+ v.MustSetBool(rv.Bool()).At(k)
+ case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
+ v.MustSetInt64(rv.Int()).At(k)
+ case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8:
+ v.MustSetUint64(rv.Uint()).At(k)
+ case reflect.Float32, reflect.Float64:
+ v.MustSetFloat64(rv.Float()).At(k)
+ case reflect.String:
+ v.MustSetString(rv.String()).At(k)
+ // case reflect.Map:
+ // if rv.Type().Key().Kind() == reflect.String && rv.Type().Elem().Kind() == reflect.Interface {
+ // if m, ok := rv.Interface().(M); ok {
+ // sub := NewObject(m)
+ // if sub != nil {
+ // v.Set(sub).At(k)
+ // }
+ // }
+ // }
+ default:
+ // continue
+ }
+ }
+}
+
+// NewArray returns an empty array-typed jsonvalue object
+//
+// NewArray 返回一个初始化好的 array 类型的 jsonvalue 值。
+func NewArray() *V {
+ return newArray(globalPool{})
+}
+
+// NewFloat64 returns an initialized num jsonvalue value by float64 type. The format and precision control is the same
+// with encoding/json: https://github.com/golang/go/blob/master/src/encoding/json/encode.go#L575
+//
+// NewFloat64 根据指定的 flout64 类型返回一个初始化好的数字类型的 jsonvalue 值。数字转出来的字符串格式参照 encoding/json 中的逻辑。
+func NewFloat64(f float64) *V {
+ abs := math.Abs(f)
+ format := byte('f')
+ if abs < 1e-6 || abs >= 1e21 {
+ format = byte('e')
+ }
+
+ return newFloat64f(globalPool{}, f, format, -1, 64)
+}
+
+// NewFloat64f returns an initialized num jsonvalue value by float64 type. The format and prec parameter are used in
+// strconv.FormatFloat(). Only 'f', 'E', 'e', 'G', 'g' formats are supported, other formats will be mapped to 'g'.
+//
+// NewFloat64f 根据指定的 float64 类型返回一个初始化好的数字类型的 jsonvalue 值。其中参数 format 和 prec 分别用于
+// strconv.FormatFloat() 函数. 只有 'f'、'E'、'e'、'G'、'g' 格式是支持的,其他配置均统一映射为 'g'。
+func NewFloat64f(f float64, format byte, prec int) *V {
+ if err := validateFloat64Format(format); err != nil {
+ format = 'g'
+ }
+ return newFloat64f(globalPool{}, f, format, prec, 64)
+}
+
+// NewFloat32 returns an initialized num jsonvalue value by float32 type. The format and precision control is the same
+// with encoding/json: https://github.com/golang/go/blob/master/src/encoding/json/encode.go#L575
+//
+// NewFloat32 根据指定的 float32 类型返回一个初始化好的数字类型的 jsonvalue 值。数字转出来的字符串格式参照 encoding/json 中的逻辑。
+func NewFloat32(f float32) *V {
+ f64 := float64(f)
+ abs := math.Abs(f64)
+ format := byte('f')
+ if abs < 1e-6 || abs >= 1e21 {
+ format = byte('e')
+ }
+
+ return newFloat64f(globalPool{}, f64, format, -1, 32)
+}
+
+// NewFloat32f returns an initialized num jsonvalue value by float64 type. The format and prec parameter are used in
+// strconv.FormatFloat(). Only 'f', 'E', 'e', 'G', 'g' formats are supported, other formats will be mapped to 'g'.
+//
+// NewFloat32f 根据指定的 float64 类型返回一个初始化好的数字类型的 jsonvalue 值。其中参数 format 和 prec 分别用于
+// strconv.FormatFloat() 函数. 只有 'f'、'E'、'e'、'G'、'g' 格式是支持的,其他配置均统一映射为 'g'。
+func NewFloat32f(f float32, format byte, prec int) *V {
+ if err := validateFloat64Format(format); err != nil {
+ format = 'g'
+ }
+ return newFloat64f(globalPool{}, float64(f), format, prec, 64)
+}
+
+// -------- internal functions --------
+
+func new(p pool, t ValueType) *V {
+ v := pool.get(p)
+ v.valueType = t
+ return v
+}
+
+func newObject(p pool) *V {
+ v := new(p, Object)
+ v.children.object = make(map[string]childWithProperty)
+ v.children.lowerCaseKeys = nil
+ return v
+}
+
+func newArray(p pool) *V {
+ v := new(p, Array)
+ return v
+}
+
+func newFloat64f(p pool, f float64, format byte, prec, bitSize int) *V {
+ v := new(p, Number)
+ // v.num = &num{}
+ v.num.negative = f < 0
+ v.num.f64 = f
+ v.num.i64 = int64(f)
+ v.num.u64 = uint64(f)
+
+ if isValidFloat(f) {
+ s := strconv.FormatFloat(f, format, prec, bitSize)
+ v.srcByte = []byte(s)
+ }
+
+ return v
+}
+
+func validateFloat64Format(f byte) error {
+ switch f {
+ case 'f', 'E', 'e', 'G', 'g':
+ return nil
+ default:
+ return fmt.Errorf("unsupported float value in option: %c", f)
+ }
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/option.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/option.go
new file mode 100644
index 0000000..163bff1
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/option.go
@@ -0,0 +1,634 @@
+package jsonvalue
+
+import "github.com/Andrew-M-C/go.jsonvalue/internal/buffer"
+
+const (
+ initialArrayCapacity = 32
+ asciiSize = 128
+)
+
+// Deprecated: Opt is the option of jsonvalue in marshaling. This type is deprecated,
+// please use OptXxxx() functions instead.
+//
+// Opt 表示序列化当前 jsonvalue 类型时的参数。这个类型后续可能不再迭代新字段了,请改用 OptXxxx() 函数进行配置。
+type Opt struct {
+ // OmitNull tells how to handle null json value. The default value is false.
+ // If OmitNull is true, null value will be omitted when marshaling.
+ //
+ // OmitNull 表示是否忽略 JSON 中的 null 类型值。默认为 false.
+ OmitNull bool
+
+ // ignoreJsonOmitempty ignore json tag "omitempty", which means that every data
+ // would be parsed into *jsonvalue.V
+ ignoreJsonOmitempty bool
+
+ // MarshalLessFunc is used to handle sequences of marshaling. Since object is
+ // implemented by hash map, the sequence of keys is unexpectable. For situations
+ // those need settled JSON key-value sequence, please use MarshalLessFunc.
+ //
+ // Note: Elements in an array value would NOT trigger this function as they are
+ // already sorted.
+ //
+ // We provides a example DefaultStringSequence. It is quite useful when calculating
+ // idempotence of a JSON text, as key-value sequences should be fixed.
+ //
+ // MarshalLessFunc 用于处理序列化 JSON 对象类型时,键值对的顺序。由于 object 类型是采用 go
+ // 原生的 map 类型,采用哈希算法实现,
+ // 因此其键值对的顺序是不可控的。而为了提高效率,jsonvalue 的内部实现中并不会刻意保存键值对的顺序。
+ // 如果有必要在序列化时固定键值对顺序的话,
+ // 可以使用这个函数。
+ //
+ // 注意:array 类型中键值对的顺序不受这个函数的影响
+ //
+ // 此外,我们提供了一个例子: DefaultStringSequence。当需要计算 JSON 文本的幂等值时,
+ // 由于需要不变的键值对顺序,因此这个函数是非常有用的。
+ MarshalLessFunc MarshalLessFunc
+
+ // MarshalKeySequence is used to handle sequance of marshaling. This is much simpler
+ // than MarshalLessFunc, just pass a string slice identifying key sequence. For keys
+ // those are not in this slice, they would be appended in the end according to result
+ // of Go string comparing. Therefore this parameter is useful for ensure idempotence.
+ //
+ // MarshalKeySequence 也用于处理序列化时的键值对顺序。与 MarshalLessFunc 不同,这个只需要用字符串
+ // 切片的形式指定键的顺序即可,实现上更为简易和直观。对于那些不在指定切片中的键,那么将会统一放在结尾,
+ // 并且按照 go 字符串对比的结果排序。也可以保证幂等。
+ MarshalKeySequence []string
+ keySequence map[string]int // generated from MarshalKeySequence
+
+ // marshalBySetSequence enables object key sequence by when it is set.
+ //
+ // 按照 key 被设置的顺序处理序列化时的 marshal 顺序
+ marshalBySetSequence bool
+
+ // FloatNaNHandleType tells what to deal with float NaN.
+ //
+ // FloatNaNHandleType 表示当处理 float 的时候,如果遇到了 NaN 的话,要如何处理。
+ FloatNaNHandleType FloatNaNHandleType
+ // FloatNaNToString works with FloatNaNHandleType = FloatNaNConvertToString. It tells
+ // what string to replace to with NaN. If not specified, NaN will be set as string "NaN".
+ //
+ // FloatNaNToString 搭配 FloatNaNHandleType = FloatNaNConvertToString 使用,表示将 NaN
+ // 映射为哪个字符串。这个值如果不指定,则默认会被设置为字符串 "NaN"
+ FloatNaNToString string
+ // FloatNaNToFloat works with FloatNaNHandleType = FloatNaNConvertToFloat. It tells
+ // what float number will be mapped to as for NaN. NaN, +Inf or -Inf are not allowed
+ // for this option.
+ //
+ // FloatNaNToFloat 搭配 FloatNaNHandleType = FloatNaNConvertToFloat 使用,表示将 NaN
+ // 映射为哪个 float64 值。不允许指定为 NaN, +Inf 或 -Inf。如果不指定,则映射为 0。
+ FloatNaNToFloat float64
+
+ // FloatInfHandleType tells what to deal with float +Inf and -Inf.
+ //
+ // FloatInfHandleType 表示当处理 float 的时候,如果遇到了 +Inf 和 -Inf 的话,要如何处理。
+ FloatInfHandleType FloatInfHandleType
+ // FloatInfPositiveToString works with FloatInfHandleType = FloatInfConvertToFloat.
+ // It tells what float number will be mapped to as for +Inf. If not specified, +Inf
+ // will be set as string "+Inf".
+ //
+ // FloatInfPositiveToString 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,
+ // 表示将 NaN 映射为哪个字符串。
+ // 这个值如果不指定,则默认会被设置为字符串 "+Inf"
+ FloatInfPositiveToString string
+ // FloatInfNegativeToString works with FloatInfHandleType = FloatInfConvertToFloat.
+ // It tells what float number will be mapped to as for -Inf. If not specified, -Inf
+ // will be set as string "-" + strings.TrimLeft(FloatInfPositiveToString, "+").
+ //
+ // FloatInfNegativeToString 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,
+ // 表示将 NaN 映射为哪个字符串。这个值如果不指定,则默认会被设置为字符串 "-" + strings.TrimLeft(FloatInfPositiveToString, "+")
+ FloatInfNegativeToString string
+ // FloatInfToFloat works with FloatInfHandleType = FloatInfConvertToFloat. It tells
+ // what float numbers will be mapped to as for +Inf. And -Inf will be specified as
+ // the negative value of this option. +Inf or -Inf are not allowed for this option.
+ //
+ // FloatInfToFloat 搭配 FloatInfHandleType = FloatInfConvertToFloat 使用,表示将 +Inf
+ // 映射为哪个 float64 值。而 -Inf 则会被映射为这个值的负数。不允许指定为 NaN, +Inf 或 -Inf。
+ // 如果不指定,则映射为 0
+ FloatInfToFloat float64
+
+ // unicodeEscapingFunc defines how to escaping a unicode greater than 0x7F to buffer.
+ unicodeEscapingFunc func(r rune, buf buffer.Buffer)
+
+ // asciiCharEscapingFunc defines how to marshal bytes lower than 0x80.
+ asciiCharEscapingFunc [asciiSize]func(b byte, buf buffer.Buffer)
+
+ // escProperties
+ escProperties escapingProperties
+
+ // indent
+ indent struct {
+ enabled bool
+ prefix string
+ indent string
+ cnt int
+ }
+}
+
+type FloatNaNHandleType uint8
+
+const (
+ // FloatNaNTreatAsError indicates that error will be returned when a float number
+ // is NaN when marshaling.
+ //
+ // FloatNaNTreatAsError 表示当 marshal 遇到 NaN 时,返回错误。这是默认选项。
+ FloatNaNTreatAsError FloatNaNHandleType = 0
+ // FloatNaNConvertToFloat indicates that NaN will be replaced as another float
+ // number when marshaling. This option works with option FloatNaNToFloat.
+ //
+ // FloatNaNConvertToFloat 表示当 marshal 遇到 NaN 时,将值置为另一个数。搭配 FloatNaNToFloat
+ // 选项使用。
+ FloatNaNConvertToFloat FloatNaNHandleType = 1
+ // FloatNaNNull indicates that NaN key-value pair will be set as null when marshaling.
+ //
+ // FloatNaNNull 表示当 marshal 遇到 NaN 时,则将值设置为 null
+ FloatNaNNull FloatNaNHandleType = 2
+ // FloatNaNConvertToString indicates that NaN will be replaced as a string when
+ // marshaling. This option works with option FloatNaNToString.
+ //
+ // FloatNaNConvertToString 表示当 marshal 遇到 NaN 时,将值设置为一个字符串。搭配
+ // FloatNaNToString 选项使用。
+ FloatNaNConvertToString FloatNaNHandleType = 3
+)
+
+type FloatInfHandleType uint8
+
+const (
+ // FloatInfTreatAsError indicates that error will be returned when a float number
+ // is Inf or -Inf when marshaling.
+ //
+ // FloatInfTreatAsError 表示当 marshal 遇到 Inf 或 -Inf 时,返回错误。这是默认选项。
+ FloatInfTreatAsError FloatInfHandleType = 0
+ // FloatInfConvertToFloat indicates that Inf and -Inf will be replaced as another
+ // float number when marshaling. This option works with option FloatInfToFloat.
+ //
+ // FloatInfConvertToFloat 表示当 marshal 遇到 Inf 或 -Inf 时,将值置为另一个数。搭配
+ // FloatInfToFloat 选项使用。
+ FloatInfConvertToFloat FloatInfHandleType = 1
+ // FloatInfNull indicates that Inf or -Inf key-value pair will be set as null
+ // when marshaling.
+ //
+ // FloatInfNull 表示当 marshal 遇到 Inf 和 -Inf 时,则将值设置为 null
+ FloatInfNull FloatInfHandleType = 2
+ // FloatInfConvertToString indicates that Inf anf -Inf will be replaced as a
+ // string when marshaling. This option works with option FloatInfPositiveToString
+ // and FloatInfNegativeToString.
+ //
+ // FloatInfConvertToString 表示当 marshal 遇到 Inf 和 -Inf 时,将值设置为一个字符串。
+ // 搭配 FloatInfPositiveToString FloatInfNegativeToString 选项使用。
+ FloatInfConvertToString FloatInfHandleType = 3
+)
+
+// Option is used for additional options when marshaling. Can be either a Opt{}
+// (not pointer to it) or other options generated by jsonvalue.OptXxxx() functions.
+//
+// Option 表示用于序列化的额外选项。可以是一个 Opt{} 结构体值(而不是它的指针),或者是使用
+// jsonvalue.OptXxxx() 函数生成的选项。
+type Option interface {
+ mergeTo(*Opt)
+}
+
+func (o Opt) mergeTo(tgt *Opt) {
+ *tgt = o
+}
+
+// SetDefaultMarshalOptions set default option for marshaling. It is quite
+// useful to invoke this function once in certern init funciton. Or you can
+// invoke it after main entry. It is goroutine-safe.
+//
+// Please keep in mind that it takes effect globally and affects ALL marshaling
+// behaviors in the future until the process ends. Please ensure that these
+// options are acceptable for ALL future marshaling.
+//
+// However, you can still add additional options in later marshaling.
+//
+// SetDefaultMarshalOptions 设置序列化时的默认参数。使用方可以在 init 函数阶段,或者是
+// main 函数启动后立刻调用该函数,以调整序列化时的默认行为。这个函数是协程安全的。
+//
+// 请记住,这个函数影响的是后续所有的序列化行为,请确保这个配置对后续的其他操作是可行的。
+//
+// 当然,你也可以在后续的操作中,基于原先配置的默认选项基础上,添加其他附加选项。
+func SetDefaultMarshalOptions(opts ...Option) {
+ opt := emptyOptions()
+ opt.combineOptionsFrom(opts)
+ internal.defaultMarshalOption = opt
+}
+
+// ResetDefaultMarshalOptions reset default marshaling options to system default.
+//
+// ResetDefaultMarshalOptions 重设序列化时的默认选项为系统最原始的版本。
+func ResetDefaultMarshalOptions() {
+ internal.defaultMarshalOption = emptyOptions()
+}
+
+func emptyOptions() *Opt {
+ return &Opt{}
+}
+
+func getDefaultOptions() *Opt {
+ res := *internal.defaultMarshalOption
+ return &res
+}
+
+func combineOptions(opts []Option) *Opt {
+ opt := getDefaultOptions()
+ opt.combineOptionsFrom(opts)
+ return opt
+}
+
+func (opt *Opt) combineOptionsFrom(opts []Option) {
+ for _, o := range opts {
+ o.mergeTo(opt)
+ }
+ opt.parseEscapingFuncs()
+}
+
+// ==== OmitNull ====
+
+// OptOmitNull configures OmitNull field in Opt{}, identifying whether null values
+// should be omitted when marshaling.
+//
+// OptOmitNull 配置 Opt{} 中的 OmitNull 字段,表示是否忽略 null 值。
+func OptOmitNull(b bool) Option {
+ return &optOmitNull{b: b}
+}
+
+type optOmitNull struct {
+ b bool
+}
+
+func (o *optOmitNull) mergeTo(opt *Opt) {
+ opt.OmitNull = o.b
+}
+
+// ==== IgnoreOmitempty ====
+
+// OptIgnoreOmitempty is used in Import() and New() function. This option tells
+// jsonvalue to ignore json tag "omitempty", which means that every field would
+// be parsed into *jsonvalue.V.
+//
+// OptIgnoreOmitempty 用在 Import 和 New() 函数中。这个选项将会忽略 json 标签中的
+// "omitempty" 参数。换句话说, 所有的字段都会被解析并包装到 *jsonvalue.V 值中。
+func OptIgnoreOmitempty() Option {
+ return optIgnoreOmitempty{}
+}
+
+type optIgnoreOmitempty struct{}
+
+func (optIgnoreOmitempty) mergeTo(opt *Opt) {
+ opt.ignoreJsonOmitempty = true
+}
+
+// ==== MarshalLessFunc ===
+
+// OptKeySequenceWithLessFunc configures MarshalLessFunc field in Opt{}, which defines
+// key sequence when marshaling.
+//
+// OptKeySequenceWithLessFunc 配置 Opt{} 中的 MarshalLessFunc 字段,配置序列化时的键顺序。
+func OptKeySequenceWithLessFunc(f MarshalLessFunc) Option {
+ return &optMarshalLessFunc{f: f}
+}
+
+// OptDefaultStringSequence configures MarshalLessFunc field in Opt{} as jsonvalue.DefaultStringSequence,
+// which is dictionary sequence.
+//
+// OptDefaultStringSequence 配置 Opt{} 中的 MarshalLessFunc 字段为 jsonvalue.DefaultStringSequence,也就是字典序。
+func OptDefaultStringSequence() Option {
+ return &optMarshalLessFunc{f: DefaultStringSequence}
+}
+
+type optMarshalLessFunc struct {
+ f MarshalLessFunc
+}
+
+func (o *optMarshalLessFunc) mergeTo(opt *Opt) {
+ if o.f != nil {
+ opt.MarshalLessFunc = o.f
+ opt.MarshalKeySequence = nil
+ opt.keySequence = nil
+ opt.marshalBySetSequence = false
+ }
+}
+
+// ==== MarshalKeySequence ====
+
+// OptKeySequence configures MarshalKeySequence field in Opt{}.
+//
+// OptKeySequence 配置 Opt{} 中的 MarshalKeySequence 字段。
+func OptKeySequence(seq []string) Option {
+ return &optMarshalKeySequence{seq: seq}
+}
+
+type optMarshalKeySequence struct {
+ seq []string
+}
+
+func (o *optMarshalKeySequence) mergeTo(opt *Opt) {
+ opt.MarshalLessFunc = nil
+ opt.MarshalKeySequence = o.seq
+ opt.keySequence = nil
+ opt.marshalBySetSequence = false
+}
+
+// ==== marshalBySetSequence ====
+
+// OptSetSequence tells that when marshaling an object, the key will be sorted by
+// the time they are added into or refreshed in its parent object. The later a key
+//
+// is set or updated, the later it and its value will be marshaled.
+//
+// OptSetSequence 指定在序列化 object 时,按照一个 key 被设置时的顺序进行序列化。如果一个
+// key 越晚添加到 object 类型,则在序列化的时候越靠后。
+func OptSetSequence() Option {
+ return optSetSequence{}
+}
+
+type optSetSequence struct{}
+
+func (optSetSequence) mergeTo(opt *Opt) {
+ opt.MarshalLessFunc = nil
+ opt.MarshalKeySequence = nil
+ opt.keySequence = nil
+ opt.marshalBySetSequence = true
+}
+
+// ==== FloatNaNConvertToFloat ====
+
+// OptFloatNaNToFloat tells that when marshaling float NaN, replace it as another
+// valid float number.
+//
+// OptFloatNaNToFloat 指定当遇到 NaN 时,将值替换成一个有效的 float 值。
+func OptFloatNaNToFloat(f float64) Option {
+ return &optFloatNaNConvertToFloat{f: f}
+}
+
+type optFloatNaNConvertToFloat struct {
+ f float64
+}
+
+func (o *optFloatNaNConvertToFloat) mergeTo(opt *Opt) {
+ opt.FloatNaNHandleType = FloatNaNConvertToFloat
+ opt.FloatNaNToFloat = o.f
+}
+
+// ==== FloatNaNNull ====
+
+// OptFloatNaNToNull will replace a float value to null if it is NaN.
+//
+// OptFloatNaNToNull 表示当遇到 NaN 时,将值替换成 null
+func OptFloatNaNToNull() Option {
+ return optFloatNaNNull{}
+}
+
+type optFloatNaNNull struct{}
+
+func (optFloatNaNNull) mergeTo(opt *Opt) {
+ opt.FloatNaNHandleType = FloatNaNNull
+}
+
+// ==== FloatNaNConvertToString ====
+
+// OptFloatNaNToStringNaN will replace a float value to string "NaN" if it is NaN.
+//
+// OptFloatNaNToStringNaN 表示遇到 NaN 时,将其替换成字符串 "NaN"
+func OptFloatNaNToStringNaN() Option {
+ return &optFloatNaNConvertToString{s: "NaN"}
+}
+
+// OptFloatNaNToString will replace a float value to specified string if it is NaN.
+// If empty string is given, will replace as "NaN".
+//
+// OptFloatNaNToString 表示当遇到 NaN 时,将其替换成指定的字符串。如果指定空字符串,则替换成 "NaN"
+func OptFloatNaNToString(s string) Option {
+ return &optFloatNaNConvertToString{s: s}
+}
+
+type optFloatNaNConvertToString struct {
+ s string
+}
+
+func (o *optFloatNaNConvertToString) mergeTo(opt *Opt) {
+ opt.FloatNaNHandleType = FloatNaNConvertToString
+ opt.FloatNaNToString = o.s
+}
+
+// ==== FloatInfConvertToFloat ====
+
+// OptFloatInfToFloat will replace a +Inf float value to specified f, while -f if
+// the value is -Inf.
+//
+// OptFloatInfToFloat 表示当遇到 +Inf 时,将其替换成另一个 float 值;如果是 -Inf,则会替换成其取负数。
+func OptFloatInfToFloat(f float64) Option {
+ return &optFloatInfConvertToFloat{f: f}
+}
+
+type optFloatInfConvertToFloat struct {
+ f float64
+}
+
+func (o *optFloatInfConvertToFloat) mergeTo(opt *Opt) {
+ opt.FloatInfHandleType = FloatInfConvertToFloat
+ opt.FloatInfToFloat = o.f
+}
+
+// ==== FloatInfNull ====
+
+// OptFloatInfToNull will replace a float value to null if it is +/-Inf.
+//
+// OptFloatInfToNull 表示当遇到 +/-Inf 时,将值替换成 null
+func OptFloatInfToNull() Option {
+ return optFloatInfNull{}
+}
+
+type optFloatInfNull struct{}
+
+func (optFloatInfNull) mergeTo(opt *Opt) {
+ opt.FloatInfHandleType = FloatInfNull
+}
+
+// ==== FloatInfConvertToString ====
+
+// OptFloatInfToStringInf will replace a +Inf value to string "+Inf", while -Inf to "-Inf"
+//
+// OptFloatInfToStringInf 表示遇到 +/-Inf 时,相应地将其替换成字符串 "+Inf" 和 "-Inf"
+func OptFloatInfToStringInf() Option {
+ return &optFloatInfConvertToString{}
+}
+
+// OptFloatInfToString tells what string to replace when marshaling +Inf and -Inf numbers.
+//
+// OptFloatInfToString 表示遇到 +/-Inf 时,将其替换成什么字符串。
+func OptFloatInfToString(positiveInf, negativeInf string) Option {
+ return &optFloatInfConvertToString{
+ positive: positiveInf,
+ negative: negativeInf,
+ }
+}
+
+type optFloatInfConvertToString struct {
+ positive string
+ negative string
+}
+
+func (o *optFloatInfConvertToString) mergeTo(opt *Opt) {
+ opt.FloatInfHandleType = FloatInfConvertToString
+ opt.FloatInfPositiveToString = o.positive
+ opt.FloatInfNegativeToString = o.negative
+}
+
+// ==== escapeHTML ====
+
+// OptEscapeHTML specifies whether problematic HTML characters should be escaped
+// inside JSON quoted strings. The default behavior is to escape &, <, and > to
+// \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when
+// embedding JSON in HTML. If not specified, HTML symbols above will be escaped by
+// default.
+//
+// OptEscapeHTML 指定部分 HTML 符号是否会被转义。相关的 HTML 符号为 &, <, > 三个。如无指定,
+// 则默认会被转义
+func OptEscapeHTML(on bool) Option {
+ return optEscapeHTML(on)
+}
+
+type optEscapeHTML bool
+
+func (o optEscapeHTML) mergeTo(opt *Opt) {
+ if o {
+ opt.escProperties = opt.escProperties.clear(escapeWithoutHTML)
+ } else {
+ opt.escProperties = opt.escProperties.set(escapeWithoutHTML)
+ }
+}
+
+// ==== do or do not not use ASCII escaping ====
+
+// OptUTF8 specifies that all unicodes greater than 0x7F, will NOT be escaped by
+// \uXXXX format but UTF-8.
+//
+// OptUTF8 指定使用 UTF-8 编码。也就是说针对大于 0x7F 的 unicode 字符,将不会使用默认的 \uXXXX
+// 格式进行编码,而是直接使用 UTF-8。
+func OptUTF8() Option {
+ return optUTF8(true)
+}
+
+type optUTF8 bool
+
+func (o optUTF8) mergeTo(opt *Opt) {
+ opt.escProperties = opt.escProperties.set(escapeUTF8)
+}
+
+// ==== ignore slash ====
+
+// OptEscapeSlash specifies whether we should escape slash (/) symbol. In JSON standard,
+// this character should be escaped as '\/'. But non-escaping will not affect anything.
+// If not specfied, slash will be escaped by default.
+//
+// OptEscapeSlash 指定是否需要转移斜杠 (/) 符号。在 JSON 标准中这个符号是需要被转移为 '\/' 的,
+//
+// 但是不转义这个符号也不会带来什么问题。如无明确指定,如无指定,默认情况下,斜杠是会被转义的。
+func OptEscapeSlash(on bool) Option {
+ return optEscSlash(on)
+}
+
+type optEscSlash bool
+
+func (o optEscSlash) mergeTo(opt *Opt) {
+ if o {
+ opt.escProperties = opt.escProperties.clear(escapeIgnoreSlash)
+ } else {
+ opt.escProperties = opt.escProperties.set(escapeIgnoreSlash)
+ }
+}
+
+// escapingProperties is a bit mask, showing the option for escaping
+// characters.
+//
+// escapingProperties 是一个位掩码,表明转义特殊字符的方法
+type escapingProperties uint8
+
+const (
+ escapeUTF8 = 0
+ escapeWithoutHTML = 1
+ escapeIgnoreSlash = 2
+)
+
+func (esc escapingProperties) set(mask escapingProperties) escapingProperties {
+ return esc | (1 << mask)
+}
+
+func (esc escapingProperties) clear(mask escapingProperties) escapingProperties {
+ return esc & ^(1 << mask)
+}
+
+func (esc escapingProperties) has(mask escapingProperties) bool {
+ return esc == esc.set(mask)
+}
+
+// parseEscapingFuncs parse escaping functions by escapingProperties.
+func (o *Opt) parseEscapingFuncs() {
+ // init bytes lower than 0x80
+ for i := range o.asciiCharEscapingFunc {
+ o.asciiCharEscapingFunc[i] = escapeNothing
+ }
+
+ iterate := func(from, to int, fu func(b byte, buf buffer.Buffer)) {
+ for i := from; i <= to; i++ {
+ o.asciiCharEscapingFunc[i] = fu
+ }
+ }
+
+ // ASCII control bytes should always escaped
+ iterate(0x00, 0x07, escAsciiControlChar)
+ // 0x08 is \b, encoding/json marshal as \u0008, but according to JSON standard, it should be "\b"
+ iterate(0x0E, 0x1F, escAsciiControlChar)
+ o.asciiCharEscapingFunc[0x7F] = escAsciiControlChar // encoding/json does not escape DEL
+
+ // ASCII characters always to be escaped
+ o.asciiCharEscapingFunc['"'] = escDoubleQuote
+ o.asciiCharEscapingFunc['/'] = escSlash
+ o.asciiCharEscapingFunc['\\'] = escBackslash
+ o.asciiCharEscapingFunc['\b'] = escBackspace
+ o.asciiCharEscapingFunc['\f'] = escVertTab
+ o.asciiCharEscapingFunc['\t'] = escTab
+ o.asciiCharEscapingFunc['\n'] = escNewLine
+ o.asciiCharEscapingFunc['\r'] = escReturn
+ o.asciiCharEscapingFunc['<'] = escLeftAngle
+ o.asciiCharEscapingFunc['>'] = escRightAngle
+ o.asciiCharEscapingFunc['&'] = escAnd
+ // o.asciiCharEscapingFunc['%'] = escPercent
+
+ // unicodes >= 0x80
+ if o.escProperties.has(escapeUTF8) {
+ o.unicodeEscapingFunc = escapeGreaterUnicodeToBuffByUTF8
+ } else {
+ o.unicodeEscapingFunc = escapeGreaterUnicodeToBuffByUTF16
+ }
+
+ // ignore slash?
+ if o.escProperties.has(escapeIgnoreSlash) {
+ o.asciiCharEscapingFunc['/'] = escapeNothing
+ }
+
+ // without HTML?
+ if o.escProperties.has(escapeWithoutHTML) {
+ o.asciiCharEscapingFunc['<'] = escapeNothing
+ o.asciiCharEscapingFunc['>'] = escapeNothing
+ o.asciiCharEscapingFunc['&'] = escapeNothing
+ }
+}
+
+// ==== indent ====
+
+// OptIndent appliesiIndent to format the output.
+//
+// OptIndent 指定序列化时的缩进。
+func OptIndent(prefix, indent string) Option {
+ return optionIndent{prefix, indent}
+}
+
+type optionIndent [2]string
+
+func (o optionIndent) mergeTo(opt *Opt) {
+ opt.indent.enabled = true
+ opt.indent.prefix = o[0]
+ opt.indent.indent = o[1]
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/set.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/set.go
new file mode 100644
index 0000000..3e4ba4a
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/set.go
@@ -0,0 +1,412 @@
+package jsonvalue
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// Setter type is for At() only.
+//
+// Setter 类型仅用于 At() 函数。
+type Setter interface {
+ // At completes the following operation of Set(). It defines position of value
+ // in Set() and return the new value set.
+ //
+ // The usage of At() is perhaps the most important. This function will recursively
+ // search for child value, and set the new value specified by Set() or SetXxx()
+ // series functions. Please unfold and read the following examples, they are important.
+ //
+ // At 完成 Set() 函数的后续操作并设置相应的子成员。其参数指定了应该在哪个位置设置子成员,
+ // 并且返回被设置的子成员对象。
+ //
+ // 该函数的用法恐怕是 jsonvalue 中最重要的内容了:该函数会按照给定的可变参数递归地一层一层查找
+ // JSON 值的子成员,并且设置到指定的位置上。设置的逻辑说明起来比较抽象,请打开以下的例子以了解,
+ // 这非常重要。
+ At(firstParam any, otherParams ...any) (*V, error)
+}
+
+type setter struct {
+ v *V
+ c *V // child
+
+ err error
+}
+
+// Set starts setting a child JSON value. Any legal JSON value typped parameter
+// is accepted, such as string, int, float, bool, nil, *jsonvalue.V, or even
+// a struct or map or slice.
+//
+// Please refer to examples of "func (set Setter) At(...)"
+//
+// https://godoc.org/github.com/Andrew-M-C/go.jsonvalue/#Set.At
+//
+// Set 开始设置一个 JSON 子成员。任何合法的 JSON 类型都可以作为参数, 比如 string, int,
+// float, bool, nil, *jsonvalue.V 等类型, 甚至也支持结构体、map、切片、数组。
+//
+// 请参见 "func (set Setter) At(...)" 例子.
+//
+// https://godoc.org/github.com/Andrew-M-C/go.jsonvalue/#Set.At
+func (v *V) Set(child any) Setter {
+ var ch *V
+ var err error
+
+ if child == nil {
+ ch = NewNull()
+ } else if childV, ok := child.(*V); ok {
+ ch = childV
+ } else {
+ ch, err = Import(child)
+ }
+
+ return &setter{
+ v: v,
+ c: ch,
+ err: err,
+ }
+}
+
+// SetString is equivalent to Set(jsonvalue.NewString(s))
+//
+// SetString 等效于 Set(jsonvalue.NewString(s))
+func (v *V) SetString(s string) Setter {
+ return v.Set(NewString(s))
+}
+
+// SetBytes is equivalent to Set(NewString(base64.StdEncoding.EncodeToString(b)))
+//
+// SetBytes 等效于 Set(NewString(base64.StdEncoding.EncodeToString(b)))
+func (v *V) SetBytes(b []byte) Setter {
+ s := internal.b64.EncodeToString(b)
+ return v.SetString(s)
+}
+
+// SetBool is equivalent to Set(jsonvalue.NewBool(b))
+//
+// SetBool 等效于 Set(jsonvalue.NewBool(b))
+func (v *V) SetBool(b bool) Setter {
+ return v.Set(NewBool(b))
+}
+
+// SetInt is equivalent to Set(jsonvalue.NewInt(b))
+//
+// SetInt 等效于 Set(jsonvalue.NewInt(b))
+func (v *V) SetInt(i int) Setter {
+ return v.Set(NewInt(i))
+}
+
+// SetInt64 is equivalent to Set(jsonvalue.NewInt64(b))
+//
+// SetInt64 等效于 Set(jsonvalue.NewInt64(b))
+func (v *V) SetInt64(i int64) Setter {
+ return v.Set(NewInt64(i))
+}
+
+// SetInt32 is equivalent to Set(jsonvalue.NewInt32(b))
+//
+// SetInt32 等效于 Set(jsonvalue.NewInt32(b))
+func (v *V) SetInt32(i int32) Setter {
+ return v.Set(NewInt32(i))
+}
+
+// SetUint is equivalent to Set(jsonvalue.NewUint(b))
+//
+// SetUint 等效于 Set(jsonvalue.NewUint(b))
+func (v *V) SetUint(u uint) Setter {
+ return v.Set(NewUint(u))
+}
+
+// SetUint64 is equivalent to Set(jsonvalue.NewUint64(b))
+//
+// SetUint64 is equivalent to Set(jsonvalue.NewUint64(b))
+func (v *V) SetUint64(u uint64) Setter {
+ return v.Set(NewUint64(u))
+}
+
+// SetUint32 is equivalent to Set(jsonvalue.NewUint32(b))
+//
+// SetUint32 等效于 Set(jsonvalue.NewUint32(b))
+func (v *V) SetUint32(u uint32) Setter {
+ return v.Set(NewUint32(u))
+}
+
+// SetFloat64 is equivalent to Set(jsonvalue.NewFloat64(b))
+//
+// SetFloat64 等效于 Set(jsonvalue.NewFloat64(b))
+func (v *V) SetFloat64(f float64) Setter {
+ return v.Set(NewFloat64(f))
+}
+
+// SetFloat32 is equivalent to Set(jsonvalue.NewFloat32(b))
+//
+// SetFloat32 等效于 Set(jsonvalue.NewFloat32(b))
+func (v *V) SetFloat32(f float32) Setter {
+ return v.Set(NewFloat32(f))
+}
+
+// SetNull is equivalent to Set(jsonvalue.NewNull())
+//
+// SetNull 等效于 Set(jsonvalue.NewNull())
+func (v *V) SetNull() Setter {
+ return v.Set(NewNull())
+}
+
+// SetObject is equivalent to Set(jsonvalue.NewObject())
+//
+// SetObject 等效于 Set(jsonvalue.NewObject())
+func (v *V) SetObject() Setter {
+ return v.Set(NewObject())
+}
+
+// SetArray is equivalent to Set(jsonvalue.NewArray())
+//
+// SetArray 等效于 Set(jsonvalue.NewArray())
+func (v *V) SetArray() Setter {
+ return v.Set(NewArray())
+}
+
+func setToObjectChildren(v *V, key string, child *V) {
+ v.children.incrID++
+ v.children.object[key] = childWithProperty{
+ id: v.children.incrID,
+ v: child,
+ }
+ addCaselessKey(v, key)
+}
+
+func (s *setter) At(firstParam any, otherParams ...any) (*V, error) {
+ if s.err != nil {
+ return &V{}, s.err
+ }
+ if ok, p1, p2 := isSliceAndExtractDividedParams(firstParam); ok {
+ if len(otherParams) > 0 {
+ return &V{}, ErrMultipleParamNotSupportedWithIfSliceOrArrayGiven
+ }
+ return s.At(p1, p2...)
+ }
+ v := s.v
+ c := s.c
+ if nil == v || v.valueType == NotExist {
+ return &V{}, ErrValueUninitialized
+ }
+ if nil == c || c.valueType == NotExist {
+ return &V{}, ErrValueUninitialized
+ }
+
+ // this is the last iteration
+ if len(otherParams) == 0 {
+ return s.atLastParam(firstParam)
+ }
+
+ // this is not the last iterarion
+ if v.valueType == Object {
+ return s.atObject(firstParam, otherParams)
+ }
+
+ // array type
+ if v.valueType == Array {
+ return s.atArray(firstParam, otherParams)
+ }
+
+ // illegal type
+ return &V{}, fmt.Errorf("%v type does not supports Set()", v.valueType)
+}
+
+func (s *setter) atLastParam(p any) (*V, error) {
+ v := s.v
+ c := s.c
+ switch v.valueType {
+ default:
+ return &V{}, fmt.Errorf("%v type does not supports Set()", v.valueType)
+
+ case Object:
+ var k string
+ k, err := anyToString(p)
+ if err != nil {
+ return &V{}, err
+ }
+ setToObjectChildren(v, k, c)
+ return c, nil
+
+ case Array:
+ pos, err := anyToInt(p)
+ if err != nil {
+ return &V{}, err
+ }
+ err = setAtIndex(v, c, pos)
+ if err != nil {
+ return &V{}, err
+ }
+ return c, nil
+ }
+}
+
+func (s *setter) atObject(firstParam any, otherParams []any) (*V, error) {
+ v := s.v
+ c := s.c
+ k, err := anyToString(firstParam)
+ if err != nil {
+ return &V{}, err
+ }
+ child, exist := getFromObjectChildren(v, false, k)
+ if !exist {
+ if _, err := anyToString(otherParams[0]); err == nil {
+ child = NewObject()
+ } else if i, err := anyToInt(otherParams[0]); err == nil {
+ if i != 0 {
+ return &V{}, ErrOutOfRange
+ }
+ child = NewArray()
+ } else {
+ return &V{}, fmt.Errorf("unexpected type %v for Set()", reflect.TypeOf(otherParams[0]))
+ }
+ }
+ next := &setter{
+ v: child,
+ c: c,
+ }
+ _, err = next.At(otherParams[0], otherParams[1:]...)
+ if err != nil {
+ return &V{}, err
+ }
+ if !exist {
+ setToObjectChildren(v, k, child)
+ }
+ return c, nil
+}
+
+func (s *setter) atArray(firstParam any, otherParams []any) (*V, error) {
+ v := s.v
+ c := s.c
+ pos, err := anyToInt(firstParam)
+ if err != nil {
+ return &V{}, err
+ }
+ child, ok := childAtIndex(v, pos)
+ isNewChild := false
+ if !ok {
+ isNewChild = true
+ if _, err := anyToString(otherParams[0]); err == nil {
+ child = NewObject()
+ } else if i, err := anyToInt(otherParams[0]); err == nil {
+ if i != 0 {
+ return &V{}, ErrOutOfRange
+ }
+ child = NewArray()
+ } else {
+ return &V{}, fmt.Errorf("unexpected type %v for Set()", reflect.TypeOf(otherParams[0]))
+ }
+ }
+ next := &setter{
+ v: child,
+ c: c,
+ }
+ _, err = next.At(otherParams[0], otherParams[1:]...)
+ if err != nil {
+ return &V{}, err
+ }
+ // OK to add this object
+ if isNewChild {
+ appendToArr(v, child)
+ }
+ return c, nil
+}
+
+func posAtIndexForSet(v *V, pos int) (newPos int, appendToEnd bool) {
+ if pos == len(v.children.arr) {
+ return pos, true
+ }
+ pos = posAtIndexForRead(v, pos)
+ return pos, false
+}
+
+func posAtIndexForInsertBefore(v *V, pos int) (newPos int) {
+ le := len(v.children.arr)
+ if le == 0 {
+ return -1
+ }
+
+ if pos == 0 {
+ return 0
+ }
+
+ if pos < 0 {
+ pos += le
+ if pos < 0 {
+ return -1
+ }
+ return pos
+ }
+
+ if pos >= le {
+ return -1
+ }
+
+ return pos
+}
+
+func posAtIndexForInsertAfter(v *V, pos int) (newPos int, appendToEnd bool) {
+ le := len(v.children.arr)
+ if le == 0 {
+ return -1, false
+ }
+
+ if pos == -1 {
+ return le, true
+ }
+
+ if pos < 0 {
+ pos += le
+ if pos < 0 {
+ return -1, false
+ }
+ return pos + 1, false
+ }
+
+ if pos >= le {
+ return -1, false
+ }
+
+ return pos + 1, false
+}
+
+func posAtIndexForRead(v *V, pos int) int {
+ le := len(v.children.arr)
+ if le == 0 {
+ return -1
+ }
+
+ if pos < 0 {
+ pos += le
+ if pos < 0 {
+ return -1
+ }
+ return pos
+ }
+
+ if pos >= le {
+ return -1
+ }
+
+ return pos
+}
+
+func childAtIndex(v *V, pos int) (*V, bool) { // if nil returned, means that just push
+ pos = posAtIndexForRead(v, pos)
+ if pos < 0 {
+ return &V{}, false
+ }
+ return v.children.arr[pos], true
+}
+
+func setAtIndex(v *V, child *V, pos int) error {
+ pos, appendToEnd := posAtIndexForSet(v, pos)
+ if pos < 0 {
+ return ErrOutOfRange
+ }
+ if appendToEnd {
+ v.children.arr = append(v.children.arr, child)
+ } else {
+ v.children.arr[pos] = child
+ }
+ return nil
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/set_must.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/set_must.go
new file mode 100644
index 0000000..2e91325
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/set_must.go
@@ -0,0 +1,162 @@
+package jsonvalue
+
+// MARK: v.MustSet(xxx).At(xxx)
+
+// MustSetter is just like Setter, but not returning sub-value or error.
+type MustSetter interface {
+ // At completes the following operation of Set(). It defines position of value
+ // in Set() and return the new value set.
+ //
+ // The usage of At() is perhaps the most important. This function will recursively
+ // search for child value, and set the new value specified by Set() or SetXxx()
+ // series functions. Please unfold and read the following examples, they are important.
+ //
+ // At 完成 Set() 函数的后续操作并设置相应的子成员。其参数指定了应该在哪个位置设置子成员,
+ // 并且返回被设置的子成员对象。
+ //
+ // 该函数的用法恐怕是 jsonvalue 中最重要的内容了:该函数会按照给定的可变参数递归地一层一层查找
+ // JSON 值的子成员,并且设置到指定的位置上。设置的逻辑说明起来比较抽象,请打开以下的例子以了解,
+ // 这非常重要。
+ At(firstParam any, otherParams ...any)
+}
+
+type mSetter struct {
+ setter Setter
+}
+
+// MustSet is just like Set, but not returning sub-value or error.
+func (v *V) MustSet(child any) MustSetter {
+ setter := v.Set(child)
+ return mSetter{
+ setter: setter,
+ }
+}
+
+// MustSetString is equivalent to Set(jsonvalue.NewString(s))
+//
+// MustSetString 等效于 Set(jsonvalue.NewString(s))
+func (v *V) MustSetString(s string) MustSetter {
+ return v.MustSet(NewString(s))
+}
+
+// MustSetBytes is equivalent to Set(NewString(base64.StdEncoding.EncodeToString(b)))
+//
+// MustSetBytes 等效于 Set(NewString(base64.StdEncoding.EncodeToString(b)))
+func (v *V) MustSetBytes(b []byte) MustSetter {
+ s := internal.b64.EncodeToString(b)
+ return v.MustSetString(s)
+}
+
+// MustSetBool is equivalent to Set(jsonvalue.NewBool(b))
+//
+// MustSetBool 等效于 Set(jsonvalue.NewBool(b))
+func (v *V) MustSetBool(b bool) MustSetter {
+ return v.MustSet(NewBool(b))
+}
+
+// MustSetInt is equivalent to Set(jsonvalue.NewInt(b))
+//
+// MustSetInt 等效于 Set(jsonvalue.NewInt(b))
+func (v *V) MustSetInt(i int) MustSetter {
+ return v.MustSet(NewInt(i))
+}
+
+// MustSetInt64 is equivalent to Set(jsonvalue.NewInt64(b))
+//
+// MustSetInt64 等效于 Set(jsonvalue.NewInt64(b))
+func (v *V) MustSetInt64(i int64) MustSetter {
+ return v.MustSet(NewInt64(i))
+}
+
+// MustSetInt32 is equivalent to Set(jsonvalue.NewInt32(b))
+//
+// MustSetInt32 等效于 Set(jsonvalue.NewInt32(b))
+func (v *V) MustSetInt32(i int32) MustSetter {
+ return v.MustSet(NewInt32(i))
+}
+
+// MustSetUint is equivalent to Set(jsonvalue.NewUint(b))
+//
+// MustSetUint 等效于 Set(jsonvalue.NewUint(b))
+func (v *V) MustSetUint(u uint) MustSetter {
+ return v.MustSet(NewUint(u))
+}
+
+// MustSetUint64 is equivalent to Set(jsonvalue.NewUint64(b))
+//
+// MustSetUint64 is equivalent to Set(jsonvalue.NewUint64(b))
+func (v *V) MustSetUint64(u uint64) MustSetter {
+ return v.MustSet(NewUint64(u))
+}
+
+// MustSetUint32 is equivalent to Set(jsonvalue.NewUint32(b))
+//
+// MustSetUint32 等效于 Set(jsonvalue.NewUint32(b))
+func (v *V) MustSetUint32(u uint32) MustSetter {
+ return v.MustSet(NewUint32(u))
+}
+
+// MustSetFloat64 is equivalent to Set(jsonvalue.NewFloat64(b))
+//
+// MustSetFloat64 等效于 Set(jsonvalue.NewFloat64(b))
+func (v *V) MustSetFloat64(f float64) MustSetter {
+ return v.MustSet(NewFloat64(f))
+}
+
+// MustSetFloat32 is equivalent to Set(jsonvalue.NewFloat32(b))
+//
+// MustSetFloat32 等效于 Set(jsonvalue.NewFloat32(b))
+func (v *V) MustSetFloat32(f float32) MustSetter {
+ return v.MustSet(NewFloat32(f))
+}
+
+// MustSetNull is equivalent to Set(jsonvalue.NewNull())
+//
+// MustSetNull 等效于 Set(jsonvalue.NewNull())
+func (v *V) MustSetNull() MustSetter {
+ return v.MustSet(NewNull())
+}
+
+// MustSetObject is equivalent to Set(jsonvalue.NewObject())
+//
+// MustSetObject 等效于 Set(jsonvalue.NewObject())
+func (v *V) MustSetObject() MustSetter {
+ return v.MustSet(NewObject())
+}
+
+// MustSetArray is equivalent to Set(jsonvalue.NewArray())
+//
+// MustSetArray 等效于 Set(jsonvalue.NewArray())
+func (v *V) MustSetArray() MustSetter {
+ return v.MustSet(NewArray())
+}
+
+func (s mSetter) At(firstParam any, otherParams ...any) {
+ _, _ = s.setter.At(firstParam, otherParams...)
+}
+
+// MARK: v.At(xxx).Set(xxx)
+
+// AtSetter works like v.MustSet(...).At(...), just with different sequence.
+type AtSetter interface {
+ Set(subValue any)
+}
+
+// At works like v.MustSet(...).At(...), just with different sequence.
+func (v *V) At(firstParam any, otherParams ...any) AtSetter {
+ return atSetter{
+ v: v,
+ firstParam: firstParam,
+ otherParams: otherParams,
+ }
+}
+
+type atSetter struct {
+ v *V
+ firstParam any
+ otherParams []any
+}
+
+func (a atSetter) Set(sub any) {
+ a.v.MustSet(sub).At(a.firstParam, a.otherParams...)
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/sort.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/sort.go
new file mode 100644
index 0000000..0ebfc8e
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/sort.go
@@ -0,0 +1,326 @@
+package jsonvalue
+
+import (
+ "bytes"
+ "sort"
+ "strconv"
+ "strings"
+
+ "github.com/Andrew-M-C/go.jsonvalue/internal/buffer"
+)
+
+// ---------------- array sorting ----------------
+
+// ArrayLessFunc is used in SortArray(), identifying which member is ahead.
+//
+// ArrayLessFunc 用于 SortArray() 函数中,指定两个成员谁在前面。
+type ArrayLessFunc func(v1, v2 *V) bool
+
+// SortArray is used to re-arrange sequence of the array. Invokers should pass less function for sorting.
+// Nothing would happens either lessFunc is nil or v is not an array.
+//
+// SortArray 用于对 array 类型的 JSON 的子成员进行重新排序。基本逻辑与 sort.Sort 函数相同。当 lessFunc 为 nil,或者当前 JSON 不是一个
+// array 类型时,什么变化都不会发生。
+func (v *V) SortArray(lessFunc ArrayLessFunc) {
+ if nil == lessFunc {
+ return
+ }
+ if !v.IsArray() {
+ return
+ }
+
+ sav := newSortV(v, lessFunc)
+ sav.Sort()
+}
+
+type sortArrayV struct {
+ v *V
+ lessFunc ArrayLessFunc
+}
+
+func newSortV(v *V, lessFunc ArrayLessFunc) *sortArrayV {
+ sav := sortArrayV{
+ v: v,
+ lessFunc: lessFunc,
+ }
+ return &sav
+}
+
+func (v *sortArrayV) Sort() {
+ sort.Sort(v)
+}
+
+func (v *sortArrayV) Len() int {
+ return len(v.v.children.arr)
+}
+
+func (v *sortArrayV) Less(i, j int) bool {
+ v1 := v.v.children.arr[i]
+ v2 := v.v.children.arr[j]
+ return v.lessFunc(v1, v2)
+}
+
+func (v *sortArrayV) Swap(i, j int) {
+ v.v.children.arr[i], v.v.children.arr[j] = v.v.children.arr[j], v.v.children.arr[i]
+}
+
+// ---------------- marshal sorting ----------------
+
+// Key is the element of KeyPath
+//
+// Key 是 KeyPath 类型的成员
+type Key struct {
+ s string
+ i int
+}
+
+func intKey(i int) Key {
+ return Key{i: i}
+}
+
+func stringKey(s string) Key {
+ return Key{s: s}
+}
+
+// String returns string value of a key
+//
+// String 返回当前键值对的键的描述
+func (k *Key) String() string {
+ if k.s != "" {
+ return k.s
+ }
+ return strconv.Itoa(k.i)
+}
+
+// IsString tells if current key is a string, which indicates a child of an object.
+//
+// IsString 判断当前的键是不是一个 string 类型,如果是的话,那么它是一个 object JSON 的子成员。
+func (k *Key) IsString() bool {
+ return k.s != ""
+}
+
+// Int returns int value of a key.
+//
+// Int 返回当前键值对的 int 值。
+func (k *Key) Int() int {
+ if k.s == "" {
+ return k.i
+ }
+ return 0
+}
+
+// IsInt tells if current key is a integer, which indicates a child of an array
+//
+// IsInt 判断当前的键是不是一个整型类型,如果是的话,那么它是一个 array JSON 的子成员。
+func (k *Key) IsInt() bool {
+ return k.s == ""
+}
+
+// KeyPath identifies a full path of keys of object in jsonvalue.
+//
+// KeyPath 表示一个对象在指定 jsonvalue 中的完整的键路径。
+type KeyPath []*Key
+
+// String returns last element of key path.
+//
+// String 返回 KeyPath 的最后一个成员的描述。
+func (p KeyPath) String() (s string) {
+ buff := bytes.Buffer{}
+ buff.WriteRune('[')
+
+ defer func() {
+ buff.WriteRune(']')
+ s = buff.String()
+ }()
+
+ for i, k := range p {
+ if i > 0 {
+ buff.WriteRune(' ')
+ }
+ if k.IsInt() {
+ s := strconv.Itoa(k.Int())
+ buff.WriteString(s)
+ } else {
+ buff.WriteRune('"')
+ escapeStringToBuff(k.String(), &buff, getDefaultOptions())
+ buff.WriteRune('"')
+ }
+ }
+
+ return
+}
+
+// ParentInfo show information of parent of a JSON value.
+//
+// ParentInfo 表示一个 JSON 值的父节点信息。
+type ParentInfo struct {
+ Parent *V
+ KeyPath KeyPath
+}
+
+func newParentInfo(v *V, nilableParentInfo *ParentInfo, key Key) *ParentInfo {
+ if nil == nilableParentInfo {
+ return &ParentInfo{
+ Parent: v,
+ KeyPath: KeyPath{&key},
+ }
+ }
+
+ return &ParentInfo{
+ Parent: v,
+ KeyPath: append(nilableParentInfo.KeyPath, &key),
+ }
+}
+
+// MarshalLessFunc is used in marshaling, for sorting marshaled data.
+//
+// MarshalLessFunc 用于序列化,指定 object 类型的 JSON 的键值对顺序。
+type MarshalLessFunc func(nilableParent *ParentInfo, key1, key2 string, v1, v2 *V) bool
+
+// DefaultStringSequence simply use strings.Compare() to define the sequence
+// of various key-value pairs of an object value.
+// This function is used in Opt.MarshalLessFunc.
+//
+// DefaultStringSequence 使用 strings.Compare() 函数来判断键值对的顺序。用于 Opt.MarshalLessFunc。
+func DefaultStringSequence(parent *ParentInfo, key1, key2 string, v1, v2 *V) bool {
+ return strings.Compare(key1, key2) <= 0
+}
+
+func (sov *sortObjectV) marshalObjectWithLessFunc(buf buffer.Buffer, opt *Opt) {
+ // sort
+ sort.Sort(sov)
+
+ // marshal
+ firstWritten := false
+ for i, key := range sov.keys {
+ child := sov.values[i]
+ par := newParentInfo(child, sov.parentInfo, stringKey(key))
+ firstWritten = writeObjectChildren(par, buf, !firstWritten, key, child, opt)
+ }
+}
+
+type sortObjectV struct {
+ parentInfo *ParentInfo
+ lessFunc MarshalLessFunc
+ keys []string
+ values []*V
+}
+
+func (sov *sortObjectV) Len() int {
+ return len(sov.values)
+}
+
+func (sov *sortObjectV) Less(i, j int) bool {
+ return sov.lessFunc(sov.parentInfo, sov.keys[i], sov.keys[j], sov.values[i], sov.values[j])
+}
+
+func (sov *sortObjectV) Swap(i, j int) {
+ sov.keys[i], sov.keys[j] = sov.keys[j], sov.keys[i]
+ sov.values[i], sov.values[j] = sov.values[j], sov.values[i]
+}
+
+func newSortObjectV(v *V, parentInfo *ParentInfo, opt *Opt) *sortObjectV {
+ sov := sortObjectV{
+ parentInfo: parentInfo,
+ lessFunc: opt.MarshalLessFunc,
+ keys: make([]string, 0, len(v.children.object)),
+ values: make([]*V, 0, len(v.children.object)),
+ }
+ for k, child := range v.children.object {
+ sov.keys = append(sov.keys, k)
+ sov.values = append(sov.values, child.v)
+ }
+
+ return &sov
+}
+
+// marshalObjectWithStringSlice use a slice to determine sequence of object
+func (sssv *sortStringSliceV) marshalObjectWithStringSlice(buf buffer.Buffer, opt *Opt) {
+ // sort
+ sort.Sort(sssv)
+
+ // marshal
+ firstWritten := false
+ for i, key := range sssv.keys {
+ child := sssv.values[i]
+ firstWritten = writeObjectChildren(nil, buf, !firstWritten, key, child, opt)
+ }
+}
+
+type sortStringSliceV struct {
+ v *V
+ seq map[string]int
+ keys []string
+ values []*V
+}
+
+func newSortStringSliceV(v *V, opt *Opt) *sortStringSliceV {
+ if nil == opt.keySequence {
+ opt.keySequence = make(map[string]int, len(opt.MarshalKeySequence))
+ for i, str := range opt.MarshalKeySequence {
+ opt.keySequence[str] = i
+ }
+ }
+
+ sssv := sortStringSliceV{
+ v: v,
+ seq: opt.keySequence,
+ keys: make([]string, 0, v.Len()),
+ values: make([]*V, 0, v.Len()),
+ }
+ for k, child := range v.children.object {
+ sssv.keys = append(sssv.keys, k)
+ sssv.values = append(sssv.values, child.v)
+ }
+
+ return &sssv
+}
+
+func newSortStringSliceVBySetSeq(v *V) *sortStringSliceV {
+ keySequence := make(map[string]int, len(v.children.object))
+ for k, child := range v.children.object {
+ keySequence[k] = int(child.id)
+ }
+
+ sssv := sortStringSliceV{
+ v: v,
+ seq: keySequence,
+ keys: make([]string, 0, v.Len()),
+ values: make([]*V, 0, v.Len()),
+ }
+ for k, child := range v.children.object {
+ sssv.keys = append(sssv.keys, k)
+ sssv.values = append(sssv.values, child.v)
+ }
+
+ return &sssv
+}
+
+func (sssv *sortStringSliceV) Len() int {
+ return len(sssv.values)
+}
+
+func (sssv *sortStringSliceV) Less(i, j int) bool {
+ k1 := sssv.keys[i]
+ k2 := sssv.keys[j]
+
+ seq1, exist1 := sssv.seq[k1]
+ seq2, exist2 := sssv.seq[k2]
+
+ if exist1 {
+ if exist2 {
+ return seq1 < seq2
+ }
+ return true
+ }
+ if exist2 {
+ return false
+ }
+
+ return k1 <= k2
+}
+
+func (sssv *sortStringSliceV) Swap(i, j int) {
+ sssv.keys[i], sssv.keys[j] = sssv.keys[j], sssv.keys[i]
+ sssv.values[i], sssv.values[j] = sssv.values[j], sssv.values[i]
+}
diff --git a/vendor/github.com/Andrew-M-C/go.jsonvalue/unmarshal.go b/vendor/github.com/Andrew-M-C/go.jsonvalue/unmarshal.go
new file mode 100644
index 0000000..249222a
--- /dev/null
+++ b/vendor/github.com/Andrew-M-C/go.jsonvalue/unmarshal.go
@@ -0,0 +1,900 @@
+package jsonvalue
+
+import (
+ "errors"
+ "fmt"
+ "strconv"
+
+ "github.com/Andrew-M-C/go.jsonvalue/internal/unsafe"
+)
+
+// ================ OUTER UNMARSHAL ================
+
+// unmarshalWithIter parse bytes with unknown value type.
+func unmarshalWithIter(p pool, it iter, offset int) (v *V, err error) {
+ end := len(it)
+ offset, reachEnd := it.skipBlanks(offset)
+ if reachEnd {
+ return &V{}, fmt.Errorf("%w, cannot find any symbol characters found", ErrRawBytesUnrecognized)
+ }
+
+ chr := it[offset]
+ switch chr {
+ case '{':
+ v, offset, err = unmarshalObjectWithIterUnknownEnd(p, it, offset, end)
+
+ case '[':
+ v, offset, err = unmarshalArrayWithIterUnknownEnd(p, it, offset, end)
+
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
+ var n *V
+ n, offset, _, err = it.parseNumber(p, offset)
+ if err == nil {
+ v = n
+ }
+
+ case '"':
+ var sectLenWithoutQuote int
+ var sectEnd int
+ sectLenWithoutQuote, sectEnd, err = it.parseStrFromBytesForwardWithQuote(offset)
+ if err == nil {
+ v, err = NewString(unsafe.BtoS(it[offset+1:offset+1+sectLenWithoutQuote])), nil
+ offset = sectEnd
+ }
+
+ case 't':
+ offset, err = it.parseTrue(offset)
+ if err == nil {
+ v = NewBool(true)
+ }
+
+ case 'f':
+ offset, err = it.parseFalse(offset)
+ if err == nil {
+ v = NewBool(false)
+ }
+
+ case 'n':
+ offset, err = it.parseNull(offset)
+ if err == nil {
+ v = NewNull()
+ }
+
+ default:
+ return &V{}, fmt.Errorf("%w, invalid character \\u%04X at Position %d", ErrRawBytesUnrecognized, chr, offset)
+ }
+
+ if err != nil {
+ return &V{}, err
+ }
+
+ if offset, reachEnd = it.skipBlanks(offset, end); !reachEnd {
+ return &V{}, fmt.Errorf("%w, unnecessary trailing data remains at Position %d", ErrRawBytesUnrecognized, offset)
+ }
+
+ return v, nil
+}
+
+// unmarshalArrayWithIterUnknownEnd is similar with unmarshalArrayWithIter, though should start with '[',
+// but it does not known where its ']' is
+func unmarshalArrayWithIterUnknownEnd(p pool, it iter, offset, right int) (_ *V, end int, err error) {
+ offset++
+ arr := newArray(p)
+
+ reachEnd := false
+
+ for offset < right {
+ // search for ending ']'
+ offset, reachEnd = it.skipBlanks(offset, right)
+ if reachEnd {
+ // ']' not found
+ return nil, -1, fmt.Errorf("%w, cannot find ']'", ErrNotArrayValue)
+ }
+
+ chr := it[offset]
+ switch chr {
+ case ']':
+ return arr, offset + 1, nil
+
+ case ',':
+ offset++
+
+ case '{':
+ v, sectEnd, err := unmarshalObjectWithIterUnknownEnd(p, it, offset, right)
+ if err != nil {
+ return nil, -1, err
+ }
+ appendToArr(arr, v)
+ offset = sectEnd
+
+ case '[':
+ v, sectEnd, err := unmarshalArrayWithIterUnknownEnd(p, it, offset, right)
+ if err != nil {
+ return nil, -1, err
+ }
+ appendToArr(arr, v)
+ offset = sectEnd
+
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
+ var v *V
+ v, sectEnd, _, err := it.parseNumber(p, offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ appendToArr(arr, v)
+ offset = sectEnd
+
+ case '"':
+ sectLenWithoutQuote, sectEnd, err := it.parseStrFromBytesForwardWithQuote(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ v := NewString(unsafe.BtoS(it[offset+1 : offset+1+sectLenWithoutQuote]))
+ appendToArr(arr, v)
+ offset = sectEnd
+
+ case 't':
+ sectEnd, err := it.parseTrue(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ appendToArr(arr, NewBool(true))
+ offset = sectEnd
+
+ case 'f':
+ sectEnd, err := it.parseFalse(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ appendToArr(arr, NewBool(false))
+ offset = sectEnd
+
+ case 'n':
+ sectEnd, err := it.parseNull(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ appendToArr(arr, NewNull())
+ offset = sectEnd
+
+ default:
+ return nil, -1, fmt.Errorf("%w, invalid character \\u%04X at Position %d", ErrRawBytesUnrecognized, chr, offset)
+ }
+ }
+
+ return nil, -1, fmt.Errorf("%w, cannot find ']'", ErrNotArrayValue)
+}
+
+func appendToArr(v *V, child *V) {
+ if v.children.arr == nil {
+ v.children.arr = make([]*V, 0, initialArrayCapacity)
+ }
+ v.children.arr = append(v.children.arr, child)
+}
+
+// unmarshalObjectWithIterUnknownEnd unmarshal object from raw bytes. it[offset] must be '{'
+func unmarshalObjectWithIterUnknownEnd(p pool, it iter, offset, right int) (_ *V, end int, err error) {
+ offset++
+ obj := newObject(p)
+
+ keyStart, keyEnd := 0, 0
+ colonFound := false
+
+ reachEnd := false
+
+ keyNotFoundErr := func() error {
+ if keyEnd == 0 {
+ return fmt.Errorf(
+ "%w, missing key for another value at Position %d", ErrNotObjectValue, offset,
+ )
+ }
+ if !colonFound {
+ return fmt.Errorf(
+ "%w, missing colon for key at Position %d", ErrNotObjectValue, offset,
+ )
+ }
+ return nil
+ }
+
+ valNotFoundErr := func() error {
+ if keyEnd > 0 {
+ return fmt.Errorf(
+ "%w, missing value for key '%s' at Position %d",
+ ErrNotObjectValue, unsafe.BtoS(it[keyStart:keyEnd]), keyStart,
+ )
+ }
+ return nil
+ }
+
+ for offset < right {
+ offset, reachEnd = it.skipBlanks(offset, right)
+ if reachEnd {
+ // '}' not found
+ return nil, -1, fmt.Errorf("%w, cannot find '}'", ErrNotObjectValue)
+ }
+
+ chr := it[offset]
+ switch chr {
+ case '}':
+ if err = valNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ return obj, offset + 1, nil
+
+ case ',':
+ if err = valNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ offset++
+ // continue
+
+ case ':':
+ if colonFound {
+ return nil, -1, fmt.Errorf("%w, duplicate colon at Position %d", ErrNotObjectValue, keyStart)
+ }
+ colonFound = true
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ offset++
+ // continue
+
+ case '{':
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ v, sectEnd, err := unmarshalObjectWithIterUnknownEnd(p, it, offset, right)
+ if err != nil {
+ return nil, -1, err
+ }
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), v)
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ case '[':
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ v, sectEnd, err := unmarshalArrayWithIterUnknownEnd(p, it, offset, right)
+ if err != nil {
+ return nil, -1, err
+ }
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), v)
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-':
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ var v *V
+ v, sectEnd, _, err := it.parseNumber(p, offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), v)
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ case '"':
+ if keyEnd > 0 {
+ // string value
+ if !colonFound {
+ return nil, -1, fmt.Errorf("%w, missing value for key '%s' at Position %d",
+ ErrNotObjectValue, unsafe.BtoS(it[keyStart:keyEnd]), keyStart,
+ )
+ }
+ sectLenWithoutQuote, sectEnd, err := it.parseStrFromBytesForwardWithQuote(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ v := NewString(unsafe.BtoS(it[offset+1 : offset+1+sectLenWithoutQuote]))
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), v)
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ } else {
+ // string key
+ sectLenWithoutQuote, sectEnd, err := it.parseStrFromBytesForwardWithQuote(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ keyStart, keyEnd = offset+1, offset+1+sectLenWithoutQuote
+ offset = sectEnd
+ }
+
+ case 't':
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ sectEnd, err := it.parseTrue(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), NewBool(true))
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ case 'f':
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ sectEnd, err := it.parseFalse(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), NewBool(false))
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ case 'n':
+ if err = keyNotFoundErr(); err != nil {
+ return nil, -1, err
+ }
+ sectEnd, err := it.parseNull(offset)
+ if err != nil {
+ return nil, -1, err
+ }
+ setToObjectChildren(obj, unsafe.BtoS(it[keyStart:keyEnd]), NewNull())
+ keyEnd, colonFound = 0, false
+ offset = sectEnd
+
+ default:
+ return nil, -1, fmt.Errorf("%w, invalid character \\u%04X at Position %d", ErrRawBytesUnrecognized, chr, offset)
+ }
+
+ }
+
+ return nil, -1, fmt.Errorf("%w, cannot find '}'", ErrNotObjectValue)
+}
+
+// parseNumber parse a number string. Reference:
+//
+// - [ECMA-404 The JSON Data Interchange Standard](https://www.json.org/json-en.html)
+func parseNumber(v *V, p pool) (err error) {
+ it := iter(v.srcByte)
+
+ parsed, end, reachEnd, err := it.parseNumber(p, 0)
+ if err != nil {
+ return err
+ }
+ if !reachEnd {
+ return fmt.Errorf("invalid character: 0x%02x", v.srcByte[end])
+ }
+
+ *v = *parsed
+ return nil
+}
+
+// ==== simple object parsing ====
+func newFromNumber(p pool, b []byte) (ret *V, err error) {
+ v := new(p, Number)
+ v.srcByte = b
+ return v, nil
+}
+
+// ================ GENERAL UNMARSHALING ================
+
+// iter is used to iterate []byte text
+type iter []byte
+
+func (it iter) parseStrFromBytesForwardWithQuote(offset int) (sectLenWithoutQuote int, sectEnd int, err error) {
+ offset++ // skip "
+ end := len(it)
+ sectEnd = offset
+
+ shift := func(i *int, le int) {
+ if end-*i < le {
+ err = fmt.Errorf(
+ "%w, expect at least %d remaining bytes, but got %d at Position %d",
+ ErrIllegalString, end-*i, le, *i,
+ )
+ return
+ }
+ it.memcpy(sectEnd, *i, le)
+ sectEnd += le
+ *i += le
+ }
+
+ // iterate every byte
+ for i := offset; i < end; {
+ chr := it[i]
+
+ // ACSII?
+ switch {
+ case chr == '\\':
+ err = it.handleEscapeStart(&i, §End)
+ case chr == '"':
+ // found end quote
+ return sectEnd - offset, i + 1, nil
+ case chr <= 0x7F:
+ // shift(&i, 1)
+ it[sectEnd] = it[i]
+ i++
+ sectEnd++
+ case runeIdentifyingBytes2(chr):
+ shift(&i, 2)
+ case runeIdentifyingBytes3(chr):
+ shift(&i, 3)
+ case runeIdentifyingBytes4(chr):
+ shift(&i, 4)
+ default:
+ err = fmt.Errorf("%w: illegal UTF8 string at Position %d", ErrIllegalString, i)
+ }
+ if err != nil {
+ return -1, -1, err
+ }
+ }
+
+ err = errors.New("ending double quote of a string is not found")
+ return
+}
+
+func (it iter) handleEscapeStart(i *int, sectEnd *int) error {
+ if len(it)-1-*i < 1 {
+ return errors.New("escape symbol not followed by another character")
+ }
+
+ chr := it[*i+1]
+ switch chr {
+ default:
+ return fmt.Errorf("unrecognized character 0x%02X after escape symbol", chr)
+ case '"', '\'', '/', '\\':
+ it[*sectEnd] = chr
+ *sectEnd++
+ *i += 2
+ case 'b':
+ it[*sectEnd] = '\b'
+ *sectEnd++
+ *i += 2
+ case 'f':
+ it[*sectEnd] = '\f'
+ *sectEnd++
+ *i += 2
+ case 'r':
+ it[*sectEnd] = '\r'
+ *sectEnd++
+ *i += 2
+ case 'n':
+ it[*sectEnd] = '\n'
+ *sectEnd++
+ *i += 2
+ case 't':
+ it[*sectEnd] = '\t'
+ *sectEnd++
+ *i += 2
+ case 'u':
+ return it.handleEscapeUnicodeStartWithEnd(i, len(it)-1, sectEnd)
+ }
+ return nil
+}
+
+func (it iter) handleEscapeUnicodeStartWithEnd(i *int, end int, sectEnd *int) (err error) {
+ if end-*i <= 5 {
+ return errors.New("escape symbol not followed by another character")
+ }
+
+ b3 := chrToHex(it[*i+2], &err)
+ b2 := chrToHex(it[*i+3], &err)
+ b1 := chrToHex(it[*i+4], &err)
+ b0 := chrToHex(it[*i+5], &err)
+ if err != nil {
+ return
+ }
+
+ r := (rune(b3) << 12) + (rune(b2) << 8) + (rune(b1) << 4) + rune(b0)
+
+ // this rune is smaller than 0x10000
+ if r <= 0xD7FF || r >= 0xE000 {
+ le := it.assignASCIICodedRune(*sectEnd, r)
+ *i += 6
+ *sectEnd += le
+ return nil
+ }
+
+ // reference: [JSON 序列化中的转义和 Unicode 编码](https://cloud.tencent.com/developer/article/1625557/)
+ // should get another unicode-escaped character
+ if end-*i <= 11 {
+ return fmt.Errorf("insufficient UTF-16 data at offset %d", *i)
+ }
+ if it[*i+6] != '\\' || it[*i+7] != 'u' {
+ return fmt.Errorf("expect unicode escape character at position %d but not", *i+6)
+ }
+
+ ex3 := chrToHex(it[*i+8], &err)
+ ex2 := chrToHex(it[*i+9], &err)
+ ex1 := chrToHex(it[*i+10], &err)
+ ex0 := chrToHex(it[*i+11], &err)
+ if err != nil {
+ return
+ }
+
+ ex := (rune(ex3) << 12) + (rune(ex2) << 8) + (rune(ex1) << 4) + rune(ex0)
+ if ex < 0xDC00 {
+ return fmt.Errorf(
+ "%w, expect second UTF-16 encoding but got 0x04%X at position %d",
+ ErrIllegalString, r, *i+8,
+ )
+ }
+ ex -= 0xDC00
+ if ex > 0x03FF {
+ return fmt.Errorf(
+ "%w, expect second UTF-16 encoding but got 0x04%X at position %d",
+ ErrIllegalString, r, *i+8,
+ )
+ }
+
+ r = ((r - 0xD800) << 10) + ex + 0x10000
+
+ le := it.assignASCIICodedRune(*sectEnd, r)
+ *i += 12
+ *sectEnd += le
+ return nil
+}
+
+func chrToHex(chr byte, errOut *error) byte {
+ if chr >= '0' && chr <= '9' {
+ return chr - '0'
+ }
+ if chr >= 'A' && chr <= 'F' {
+ return chr - 'A' + 10
+ }
+ if chr >= 'a' && chr <= 'f' {
+ return chr - 'a' + 10
+ }
+ *errOut = fmt.Errorf("invalid unicode value character: %c", rune(chr))
+ return 0
+}
+
+func (it iter) memcpy(dst, src, length int) {
+ if dst == src {
+ return
+ }
+ copy(it[dst:dst+length], it[src:src+length])
+ // ptr := unsafe.Pointer(&it[0])
+ // C.memcpy(
+ // unsafe.Pointer(uintptr(ptr)+uintptr(dst)),
+ // unsafe.Pointer(uintptr(ptr)+uintptr(src)),
+ // C.size_t(length),
+ // )
+}
+
+func (it iter) assignASCIICodedRune(dst int, r rune) (offset int) {
+ switch {
+ // 0zzzzzzz ==>
+ // 0zzzzzzz
+ case r <= 0x7F:
+ it[dst+0] = byte(r)
+ return 1
+ // 00000yyy yyzzzzzz ==>
+ // 110yyyyy 10zzzzzz
+ case r <= 0x7FF:
+ it[dst+1] = byte((r&0x03F)>>0) + 0x80
+ it[dst+0] = byte((r&0x7C0)>>6) + 0xC0
+ return 2
+ // xxxxyyyy yyzzzzzz ==>
+ // 1110xxxx 10yyyyyy 10zzzzzz
+ case r <= 0xFFFF:
+ it[dst+2] = byte((r&0x003F)>>0) + 0x80
+ it[dst+1] = byte((r&0x0FC0)>>6) + 0x80
+ it[dst+0] = byte((r&0xF000)>>12) + 0xE0
+ return 3
+ // 000wwwxx xxxxyyyy yyzzzzzz ==>
+ // 11110www 10xxxxxx 10yyyyyy 10zzzzzz
+ default:
+ it[dst+3] = byte((r&0x00003F)>>0) + 0x80
+ it[dst+2] = byte((r&0x000FC0)>>6) + 0x80
+ it[dst+1] = byte((r&0x03F000)>>12) + 0x80
+ it[dst+0] = byte((r&0x1C0000)>>18) + 0xF0
+ return 4
+ }
+}
+
+func runeIdentifyingBytes2(chr byte) bool {
+ return (chr & 0xE0) == 0xC0
+}
+
+func runeIdentifyingBytes3(chr byte) bool {
+ return (chr & 0xF0) == 0xE0
+}
+
+func runeIdentifyingBytes4(chr byte) bool {
+ return (chr & 0xF8) == 0xF0
+}
+
+func (it iter) parseTrue(offset int) (end int, err error) {
+ if len(it)-offset < 4 {
+ return -1, fmt.Errorf("%w, insufficient character from Position %d", ErrNotValidBoolValue, offset)
+ }
+
+ if it[offset] == 't' &&
+ it[offset+1] == 'r' &&
+ it[offset+2] == 'u' &&
+ it[offset+3] == 'e' {
+ return offset + 4, nil
+ }
+
+ return -1, fmt.Errorf("%w, not 'true' at Position %d", ErrNotValidBoolValue, offset)
+}
+
+func (it iter) parseFalse(offset int) (end int, err error) {
+ if len(it)-offset < 5 {
+ return -1, fmt.Errorf("%w, insufficient character from Position %d", ErrNotValidBoolValue, offset)
+ }
+
+ if it[offset] == 'f' &&
+ it[offset+1] == 'a' &&
+ it[offset+2] == 'l' &&
+ it[offset+3] == 's' &&
+ it[offset+4] == 'e' {
+ return offset + 5, nil
+ }
+
+ return -1, fmt.Errorf("%w, not 'false' at Position %d", ErrNotValidBoolValue, offset)
+}
+
+func (it iter) parseNull(offset int) (end int, err error) {
+ if len(it)-offset < 4 {
+ return -1, fmt.Errorf("%w, insufficient character from Position %d", ErrNotValidNullValue, offset)
+ }
+
+ if it[offset] == 'n' &&
+ it[offset+1] == 'u' &&
+ it[offset+2] == 'l' &&
+ it[offset+3] == 'l' {
+ return offset + 4, nil
+ }
+
+ return -1, fmt.Errorf("%w, not 'null' at Position %d", ErrNotValidBoolValue, offset)
+}
+
+// skipBlanks skip blank characters until end or reaching a non-blank character
+func (it iter) skipBlanks(offset int, endPos ...int) (newOffset int, reachEnd bool) {
+ end := 0
+ if len(endPos) > 0 {
+ end = endPos[0]
+ } else {
+ end = len(it)
+ }
+
+ for offset < end {
+ chr := it[offset]
+ switch chr {
+ case ' ', '\r', '\n', '\t', '\b':
+ offset++ // continue
+ default:
+ return offset, false
+ }
+ }
+
+ return end, true
+}
+
+// ================ FLOAT UNMARSHALING ================
+
+// For state machine chart, please refer to ./img/parse_float_state_chart.drawio
+
+func (it iter) parseNumber(
+ p pool, offset int,
+) (v *V, end int, reachEnd bool, err error) {
+
+ idx := offset
+ negative := false
+ floated := false
+ exponentGot := false
+ dotGot := false
+ intAfterDotGot := false
+ integer := uint64(0)
+ edgeFound := false
+
+ // len(it)-idx means remain bytes
+
+ for ; len(it)-idx > 0 && !edgeFound; idx++ {
+ b := it[idx]
+
+ switch b {
+ default:
+ edgeFound = true
+
+ case '0':
+ if idx == offset {
+ // OK
+ } else if exponentGot {
+ // OK
+ } else if dotGot {
+ intAfterDotGot = true
+ } else if negative {
+ if integer == 0 && idx != offset+1 {
+ err = it.numErrorf(idx, "unexpected zero")
+ return
+ }
+ } else if integer == 0 {
+ err = it.numErrorf(idx, "unexpected zero")
+ return
+ }
+ integer *= 10
+
+ case '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ if !floated {
+ integer = integer*10 + uint64(b) - '0'
+ } else if !exponentGot {
+ intAfterDotGot = true
+ }
+
+ case 'e', 'E':
+ if exponentGot {
+ err = it.numErrorf(idx, "unexpected exponent symbol")
+ return
+ }
+ exponentGot = true
+ floated = true
+
+ case '+':
+ if !exponentGot {
+ err = it.numErrorf(idx, "unexpected +")
+ return
+ }
+ // Codes below not needed because this error is caught in outer logic
+ // if !floated {
+ // err = it.numErrorf(idx, "unexpected positive symbol")
+ // return
+ // }
+
+ case '-':
+ if !floated {
+ if idx != offset {
+ err = it.numErrorf(idx, "unexpected negative symbol")
+ return
+ }
+ negative = true
+ }
+
+ case '.':
+ if idx == offset || floated || exponentGot || dotGot {
+ err = it.numErrorf(idx, "unexpected dot symbol")
+ return
+ }
+ dotGot = true
+ floated = true
+ }
+ }
+
+ if edgeFound {
+ idx--
+ }
+
+ if floated {
+ if dotGot && !intAfterDotGot {
+ err = it.numErrorf(offset, "integer after dot missing")
+ return
+ }
+ v, err = it.parseFloatResult(p, offset, idx)
+ } else {
+ if integer > 0 && it[offset] == '0' {
+ err = it.numErrorf(offset, "non-zero integer should not start with zero")
+ return
+ }
+
+ firstB := it[offset]
+ if idx-offset == 1 {
+ if firstB >= '0' && firstB <= '9' {
+ // OK
+ } else {
+ err = it.numErrorf(offset, "invalid number format")
+ return
+ }
+ }
+
+ if negative {
+ v, err = it.parseNegativeIntResult(p, offset, idx, integer)
+ } else {
+ v, err = it.parsePositiveIntResult(p, offset, idx, integer)
+ }
+ }
+
+ return v, idx, len(it)-idx == 0, err
+}
+
+func (it iter) numErrorf(offset int, f string, a ...any) error {
+ a = append([]any{offset}, a...)
+ return fmt.Errorf("parsing number at index %d: "+f, a...)
+
+ // debug ONLY below
+
+ // getCaller := func(skip int) string {
+ // pc, _, _, ok := runtime.Caller(skip + 1)
+ // if !ok {
+ // return ""
+ // }
+ // ca := runtime.CallersFrames([]uintptr{pc})
+ // fr, _ := ca.Next()
+
+ // fu := filepath.Ext(fr.Function)
+ // fu = strings.TrimLeft(fu, ".")
+ // li := fr.Line
+
+ // return fmt.Sprintf("%s(), Line %d", fu, li)
+ // }
+ // ca := getCaller(1)
+
+ // a = append([]any{ca, string(it), offset}, a...)
+ // return fmt.Errorf("%s - parsing number \"%s\" at index %d: "+f, a...)
+}
+
+const (
+ uintMaxStr = "18446744073709551615"
+ uintMaxDigits = 10000000000000000000
+ intMin = -9223372036854775808
+ intMinStr = "-9223372036854775808"
+ intMinAbs = 9223372036854775808
+)
+
+func (it iter) parseFloatResult(p pool, start, end int) (*V, error) {
+ f, err := strconv.ParseFloat(unsafe.BtoS(it[start:end]), 64)
+ if err != nil {
+ return nil, it.numErrorf(start, "%w", err)
+ }
+
+ v := new(p, Number)
+ v.srcByte = it[start:end]
+
+ v.num.negative = f < 0
+ v.num.floated = true
+ v.num.i64 = int64(f)
+ v.num.u64 = uint64(f)
+ v.num.f64 = f
+
+ return v, nil
+}
+
+func (it iter) parsePositiveIntResult(p pool, start, end int, integer uint64) (*V, error) {
+ le := end - start
+
+ if le > len(uintMaxStr) {
+ return nil, it.numErrorf(start, "value too large")
+ } else if le == len(uintMaxStr) {
+ if integer < uintMaxDigits {
+ return nil, it.numErrorf(start, "value too large")
+ }
+ }
+
+ v := new(p, Number)
+ v.srcByte = it[start:end]
+
+ v.num.negative = false
+ v.num.floated = false
+ v.num.i64 = int64(integer)
+ v.num.u64 = uint64(integer)
+ v.num.f64 = float64(integer)
+
+ return v, nil
+}
+
+func (it iter) parseNegativeIntResult(p pool, start, end int, integer uint64) (*V, error) {
+ le := end - start
+
+ if le > len(intMinStr) {
+ return nil, it.numErrorf(start, "absolute value too large")
+ } else if le == len(intMinStr) {
+ if integer > intMinAbs {
+ return nil, it.numErrorf(start, "absolute value too large")
+ }
+ }
+
+ v := new(p, Number)
+ v.srcByte = it[start:end]
+
+ v.num.negative = true
+ v.num.floated = false
+
+ if integer == intMinAbs {
+ v.num.i64 = intMin
+ } else {
+ v.num.i64 = -int64(integer)
+ }
+
+ v.num.u64 = uint64(v.num.i64)
+ v.num.f64 = -float64(integer)
+
+ return v, nil
+}
diff --git a/vendor/github.com/shopspring/decimal/.gitignore b/vendor/github.com/shopspring/decimal/.gitignore
new file mode 100644
index 0000000..ff36b98
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/.gitignore
@@ -0,0 +1,9 @@
+.git
+*.swp
+
+# IntelliJ
+.idea/
+*.iml
+
+# VS code
+*.code-workspace
diff --git a/vendor/github.com/shopspring/decimal/CHANGELOG.md b/vendor/github.com/shopspring/decimal/CHANGELOG.md
new file mode 100644
index 0000000..432d0fd
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/CHANGELOG.md
@@ -0,0 +1,76 @@
+## Decimal v1.4.0
+#### BREAKING
+- Drop support for Go version older than 1.10 [#361](https://github.com/shopspring/decimal/pull/361)
+
+#### FEATURES
+- Add implementation of natural logarithm [#339](https://github.com/shopspring/decimal/pull/339) [#357](https://github.com/shopspring/decimal/pull/357)
+- Add improved implementation of power operation [#358](https://github.com/shopspring/decimal/pull/358)
+- Add Compare method which forwards calls to Cmp [#346](https://github.com/shopspring/decimal/pull/346)
+- Add NewFromBigRat constructor [#288](https://github.com/shopspring/decimal/pull/288)
+- Add NewFromUint64 constructor [#352](https://github.com/shopspring/decimal/pull/352)
+
+#### ENHANCEMENTS
+- Migrate to Github Actions [#245](https://github.com/shopspring/decimal/pull/245) [#340](https://github.com/shopspring/decimal/pull/340)
+- Fix examples for RoundDown, RoundFloor, RoundUp, and RoundCeil [#285](https://github.com/shopspring/decimal/pull/285) [#328](https://github.com/shopspring/decimal/pull/328) [#341](https://github.com/shopspring/decimal/pull/341)
+- Use Godoc standard to mark deprecated Equals and StringScaled methods [#342](https://github.com/shopspring/decimal/pull/342)
+- Removed unnecessary min function for RescalePair method [#265](https://github.com/shopspring/decimal/pull/265)
+- Avoid reallocation of initial slice in MarshalBinary (GobEncode) [#355](https://github.com/shopspring/decimal/pull/355)
+- Optimize NumDigits method [#301](https://github.com/shopspring/decimal/pull/301) [#356](https://github.com/shopspring/decimal/pull/356)
+- Optimize BigInt method [#359](https://github.com/shopspring/decimal/pull/359)
+- Support scanning uint64 [#131](https://github.com/shopspring/decimal/pull/131) [#364](https://github.com/shopspring/decimal/pull/364)
+- Add docs section with alternative libraries [#363](https://github.com/shopspring/decimal/pull/363)
+
+#### BUGFIXES
+- Fix incorrect calculation of decimal modulo [#258](https://github.com/shopspring/decimal/pull/258) [#317](https://github.com/shopspring/decimal/pull/317)
+- Allocate new(big.Int) in Copy method to deeply clone it [#278](https://github.com/shopspring/decimal/pull/278)
+- Fix overflow edge case in QuoRem method [#322](https://github.com/shopspring/decimal/pull/322)
+
+## Decimal v1.3.1
+
+#### ENHANCEMENTS
+- Reduce memory allocation in case of initialization from big.Int [#252](https://github.com/shopspring/decimal/pull/252)
+
+#### BUGFIXES
+- Fix binary marshalling of decimal zero value [#253](https://github.com/shopspring/decimal/pull/253)
+
+## Decimal v1.3.0
+
+#### FEATURES
+- Add NewFromFormattedString initializer [#184](https://github.com/shopspring/decimal/pull/184)
+- Add NewNullDecimal initializer [#234](https://github.com/shopspring/decimal/pull/234)
+- Add implementation of natural exponent function (Taylor, Hull-Abraham) [#229](https://github.com/shopspring/decimal/pull/229)
+- Add RoundUp, RoundDown, RoundCeil, RoundFloor methods [#196](https://github.com/shopspring/decimal/pull/196) [#202](https://github.com/shopspring/decimal/pull/202) [#220](https://github.com/shopspring/decimal/pull/220)
+- Add XML support for NullDecimal [#192](https://github.com/shopspring/decimal/pull/192)
+- Add IsInteger method [#179](https://github.com/shopspring/decimal/pull/179)
+- Add Copy helper method [#123](https://github.com/shopspring/decimal/pull/123)
+- Add InexactFloat64 helper method [#205](https://github.com/shopspring/decimal/pull/205)
+- Add CoefficientInt64 helper method [#244](https://github.com/shopspring/decimal/pull/244)
+
+#### ENHANCEMENTS
+- Performance optimization of NewFromString init method [#198](https://github.com/shopspring/decimal/pull/198)
+- Performance optimization of Abs and Round methods [#240](https://github.com/shopspring/decimal/pull/240)
+- Additional tests (CI) for ppc64le architecture [#188](https://github.com/shopspring/decimal/pull/188)
+
+#### BUGFIXES
+- Fix rounding in FormatFloat fallback path (roundShortest method, fix taken from Go main repository) [#161](https://github.com/shopspring/decimal/pull/161)
+- Add slice range checks to UnmarshalBinary method [#232](https://github.com/shopspring/decimal/pull/232)
+
+## Decimal v1.2.0
+
+#### BREAKING
+- Drop support for Go version older than 1.7 [#172](https://github.com/shopspring/decimal/pull/172)
+
+#### FEATURES
+- Add NewFromInt and NewFromInt32 initializers [#72](https://github.com/shopspring/decimal/pull/72)
+- Add support for Go modules [#157](https://github.com/shopspring/decimal/pull/157)
+- Add BigInt, BigFloat helper methods [#171](https://github.com/shopspring/decimal/pull/171)
+
+#### ENHANCEMENTS
+- Memory usage optimization [#160](https://github.com/shopspring/decimal/pull/160)
+- Updated travis CI golang versions [#156](https://github.com/shopspring/decimal/pull/156)
+- Update documentation [#173](https://github.com/shopspring/decimal/pull/173)
+- Improve code quality [#174](https://github.com/shopspring/decimal/pull/174)
+
+#### BUGFIXES
+- Revert remove insignificant digits [#159](https://github.com/shopspring/decimal/pull/159)
+- Remove 15 interval for RoundCash [#166](https://github.com/shopspring/decimal/pull/166)
diff --git a/vendor/github.com/shopspring/decimal/LICENSE b/vendor/github.com/shopspring/decimal/LICENSE
new file mode 100644
index 0000000..ad2148a
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/LICENSE
@@ -0,0 +1,45 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Spring, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+- Based on https://github.com/oguzbilgic/fpd, which has the following license:
+"""
+The MIT License (MIT)
+
+Copyright (c) 2013 Oguz Bilgic
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"""
diff --git a/vendor/github.com/shopspring/decimal/README.md b/vendor/github.com/shopspring/decimal/README.md
new file mode 100644
index 0000000..318c9df
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/README.md
@@ -0,0 +1,139 @@
+# decimal
+
+[](https://github.com/shopspring/decimal/actions/workflows/ci.yml)
+[](https://godoc.org/github.com/shopspring/decimal)
+[](https://goreportcard.com/report/github.com/shopspring/decimal)
+
+Arbitrary-precision fixed-point decimal numbers in go.
+
+_Note:_ Decimal library can "only" represent numbers with a maximum of 2^31 digits after the decimal point.
+
+## Features
+
+ * The zero-value is 0, and is safe to use without initialization
+ * Addition, subtraction, multiplication with no loss of precision
+ * Division with specified precision
+ * Database/sql serialization/deserialization
+ * JSON and XML serialization/deserialization
+
+## Install
+
+Run `go get github.com/shopspring/decimal`
+
+## Requirements
+
+Decimal library requires Go version `>=1.10`
+
+## Documentation
+
+http://godoc.org/github.com/shopspring/decimal
+
+
+## Usage
+
+```go
+package main
+
+import (
+ "fmt"
+ "github.com/shopspring/decimal"
+)
+
+func main() {
+ price, err := decimal.NewFromString("136.02")
+ if err != nil {
+ panic(err)
+ }
+
+ quantity := decimal.NewFromInt(3)
+
+ fee, _ := decimal.NewFromString(".035")
+ taxRate, _ := decimal.NewFromString(".08875")
+
+ subtotal := price.Mul(quantity)
+
+ preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1)))
+
+ total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1)))
+
+ fmt.Println("Subtotal:", subtotal) // Subtotal: 408.06
+ fmt.Println("Pre-tax:", preTax) // Pre-tax: 422.3421
+ fmt.Println("Taxes:", total.Sub(preTax)) // Taxes: 37.482861375
+ fmt.Println("Total:", total) // Total: 459.824961375
+ fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
+}
+```
+
+## Alternative libraries
+
+When working with decimal numbers, you might face problems this library is not perfectly suited for.
+Fortunately, thanks to the wonderful community we have a dozen other libraries that you can choose from.
+Explore other alternatives to find the one that best fits your needs :)
+
+* [cockroachdb/apd](https://github.com/cockroachdb/apd) - arbitrary precision, mutable and rich API similar to `big.Int`, more performant than this library
+* [alpacahq/alpacadecimal](https://github.com/alpacahq/alpacadecimal) - high performance, low precision (12 digits), fully compatible API with this library
+* [govalues/decimal](https://github.com/govalues/decimal) - high performance, zero-allocation, low precision (19 digits)
+* [greatcloak/decimal](https://github.com/greatcloak/decimal) - fork focusing on billing and e-commerce web application related use cases, includes out-of-the-box BSON marshaling support
+
+## FAQ
+
+#### Why don't you just use float64?
+
+Because float64 (or any binary floating point type, actually) can't represent
+numbers such as `0.1` exactly.
+
+Consider this code: http://play.golang.org/p/TQBd4yJe6B You might expect that
+it prints out `10`, but it actually prints `9.999999999999831`. Over time,
+these small errors can really add up!
+
+#### Why don't you just use big.Rat?
+
+big.Rat is fine for representing rational numbers, but Decimal is better for
+representing money. Why? Here's a (contrived) example:
+
+Let's say you use big.Rat, and you have two numbers, x and y, both
+representing 1/3, and you have `z = 1 - x - y = 1/3`. If you print each one
+out, the string output has to stop somewhere (let's say it stops at 3 decimal
+digits, for simplicity), so you'll get 0.333, 0.333, and 0.333. But where did
+the other 0.001 go?
+
+Here's the above example as code: http://play.golang.org/p/lCZZs0w9KE
+
+With Decimal, the strings being printed out represent the number exactly. So,
+if you have `x = y = 1/3` (with precision 3), they will actually be equal to
+0.333, and when you do `z = 1 - x - y`, `z` will be equal to .334. No money is
+unaccounted for!
+
+You still have to be careful. If you want to split a number `N` 3 ways, you
+can't just send `N/3` to three different people. You have to pick one to send
+`N - (2/3*N)` to. That person will receive the fraction of a penny remainder.
+
+But, it is much easier to be careful with Decimal than with big.Rat.
+
+#### Why isn't the API similar to big.Int's?
+
+big.Int's API is built to reduce the number of memory allocations for maximal
+performance. This makes sense for its use-case, but the trade-off is that the
+API is awkward and easy to misuse.
+
+For example, to add two big.Ints, you do: `z := new(big.Int).Add(x, y)`. A
+developer unfamiliar with this API might try to do `z := a.Add(a, b)`. This
+modifies `a` and sets `z` as an alias for `a`, which they might not expect. It
+also modifies any other aliases to `a`.
+
+Here's an example of the subtle bugs you can introduce with big.Int's API:
+https://play.golang.org/p/x2R_78pa8r
+
+In contrast, it's difficult to make such mistakes with decimal. Decimals
+behave like other go numbers types: even though `a = b` will not deep copy
+`b` into `a`, it is impossible to modify a Decimal, since all Decimal methods
+return new Decimals and do not modify the originals. The downside is that
+this causes extra allocations, so Decimal is less performant. My assumption
+is that if you're using Decimals, you probably care more about correctness
+than performance.
+
+## License
+
+The MIT License (MIT)
+
+This is a heavily modified fork of [fpd.Decimal](https://github.com/oguzbilgic/fpd), which was also released under the MIT License.
diff --git a/vendor/github.com/shopspring/decimal/const.go b/vendor/github.com/shopspring/decimal/const.go
new file mode 100644
index 0000000..e5d6fa8
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/const.go
@@ -0,0 +1,63 @@
+package decimal
+
+import (
+ "strings"
+)
+
+const (
+ strLn10 = "2.302585092994045684017991454684364207601101488628772976033327900967572609677352480235997205089598298341967784042286248633409525465082806756666287369098781689482907208325554680843799894826233198528393505308965377732628846163366222287698219886746543667474404243274365155048934314939391479619404400222105101714174800368808401264708068556774321622835522011480466371565912137345074785694768346361679210180644507064800027750268491674655058685693567342067058113642922455440575892572420824131469568901675894025677631135691929203337658714166023010570308963457207544037084746994016826928280848118428931484852494864487192780967627127577539702766860595249671667418348570442250719796500471495105049221477656763693866297697952211071826454973477266242570942932258279850258550978526538320760672631716430950599508780752371033310119785754733154142180842754386359177811705430982748238504564801909561029929182431823752535770975053956518769751037497088869218020518933950723853920514463419726528728696511086257149219884997874887377134568620916705849807828059751193854445009978131146915934666241071846692310107598438319191292230792503747298650929009880391941702654416816335727555703151596113564846546190897042819763365836983716328982174407366009162177850541779276367731145041782137660111010731042397832521894898817597921798666394319523936855916447118246753245630912528778330963604262982153040874560927760726641354787576616262926568298704957954913954918049209069438580790032763017941503117866862092408537949861264933479354871737451675809537088281067452440105892444976479686075120275724181874989395971643105518848195288330746699317814634930000321200327765654130472621883970596794457943468343218395304414844803701305753674262153675579814770458031413637793236291560128185336498466942261465206459942072917119370602444929358037007718981097362533224548366988505528285966192805098447175198503666680874970496982273220244823343097169111136813588418696549323714996941979687803008850408979618598756579894836445212043698216415292987811742973332588607915912510967187510929248475023930572665446276200923068791518135803477701295593646298412366497023355174586195564772461857717369368404676577047874319780573853271810933883496338813069945569399346101090745616033312247949360455361849123333063704751724871276379140924398331810164737823379692265637682071706935846394531616949411701841938119405416449466111274712819705817783293841742231409930022911502362192186723337268385688273533371925103412930705632544426611429765388301822384091026198582888433587455960453004548370789052578473166283701953392231047527564998119228742789713715713228319641003422124210082180679525276689858180956119208391760721080919923461516952599099473782780648128058792731993893453415320185969711021407542282796298237068941764740642225757212455392526179373652434440560595336591539160312524480149313234572453879524389036839236450507881731359711238145323701508413491122324390927681724749607955799151363982881058285740538000653371655553014196332241918087621018204919492651483892"
+)
+
+var (
+ ln10 = newConstApproximation(strLn10)
+)
+
+type constApproximation struct {
+ exact Decimal
+ approximations []Decimal
+}
+
+func newConstApproximation(value string) constApproximation {
+ parts := strings.Split(value, ".")
+ coeff, fractional := parts[0], parts[1]
+
+ coeffLen := len(coeff)
+ maxPrecision := len(fractional)
+
+ var approximations []Decimal
+ for p := 1; p < maxPrecision; p *= 2 {
+ r := RequireFromString(value[:coeffLen+p])
+ approximations = append(approximations, r)
+ }
+
+ return constApproximation{
+ RequireFromString(value),
+ approximations,
+ }
+}
+
+// Returns the smallest approximation available that's at least as precise
+// as the passed precision (places after decimal point), i.e. Floor[ log2(precision) ] + 1
+func (c constApproximation) withPrecision(precision int32) Decimal {
+ i := 0
+
+ if precision >= 1 {
+ i++
+ }
+
+ for precision >= 16 {
+ precision /= 16
+ i += 4
+ }
+
+ for precision >= 2 {
+ precision /= 2
+ i++
+ }
+
+ if i >= len(c.approximations) {
+ return c.exact
+ }
+
+ return c.approximations[i]
+}
diff --git a/vendor/github.com/shopspring/decimal/decimal-go.go b/vendor/github.com/shopspring/decimal/decimal-go.go
new file mode 100644
index 0000000..9958d69
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/decimal-go.go
@@ -0,0 +1,415 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Multiprecision decimal numbers.
+// For floating-point formatting only; not general purpose.
+// Only operations are assign and (binary) left/right shift.
+// Can do binary floating point in multiprecision decimal precisely
+// because 2 divides 10; cannot do decimal floating point
+// in multiprecision binary precisely.
+
+package decimal
+
+type decimal struct {
+ d [800]byte // digits, big-endian representation
+ nd int // number of digits used
+ dp int // decimal point
+ neg bool // negative flag
+ trunc bool // discarded nonzero digits beyond d[:nd]
+}
+
+func (a *decimal) String() string {
+ n := 10 + a.nd
+ if a.dp > 0 {
+ n += a.dp
+ }
+ if a.dp < 0 {
+ n += -a.dp
+ }
+
+ buf := make([]byte, n)
+ w := 0
+ switch {
+ case a.nd == 0:
+ return "0"
+
+ case a.dp <= 0:
+ // zeros fill space between decimal point and digits
+ buf[w] = '0'
+ w++
+ buf[w] = '.'
+ w++
+ w += digitZero(buf[w : w+-a.dp])
+ w += copy(buf[w:], a.d[0:a.nd])
+
+ case a.dp < a.nd:
+ // decimal point in middle of digits
+ w += copy(buf[w:], a.d[0:a.dp])
+ buf[w] = '.'
+ w++
+ w += copy(buf[w:], a.d[a.dp:a.nd])
+
+ default:
+ // zeros fill space between digits and decimal point
+ w += copy(buf[w:], a.d[0:a.nd])
+ w += digitZero(buf[w : w+a.dp-a.nd])
+ }
+ return string(buf[0:w])
+}
+
+func digitZero(dst []byte) int {
+ for i := range dst {
+ dst[i] = '0'
+ }
+ return len(dst)
+}
+
+// trim trailing zeros from number.
+// (They are meaningless; the decimal point is tracked
+// independent of the number of digits.)
+func trim(a *decimal) {
+ for a.nd > 0 && a.d[a.nd-1] == '0' {
+ a.nd--
+ }
+ if a.nd == 0 {
+ a.dp = 0
+ }
+}
+
+// Assign v to a.
+func (a *decimal) Assign(v uint64) {
+ var buf [24]byte
+
+ // Write reversed decimal in buf.
+ n := 0
+ for v > 0 {
+ v1 := v / 10
+ v -= 10 * v1
+ buf[n] = byte(v + '0')
+ n++
+ v = v1
+ }
+
+ // Reverse again to produce forward decimal in a.d.
+ a.nd = 0
+ for n--; n >= 0; n-- {
+ a.d[a.nd] = buf[n]
+ a.nd++
+ }
+ a.dp = a.nd
+ trim(a)
+}
+
+// Maximum shift that we can do in one pass without overflow.
+// A uint has 32 or 64 bits, and we have to be able to accommodate 9<> 63)
+const maxShift = uintSize - 4
+
+// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow.
+func rightShift(a *decimal, k uint) {
+ r := 0 // read pointer
+ w := 0 // write pointer
+
+ // Pick up enough leading digits to cover first shift.
+ var n uint
+ for ; n>>k == 0; r++ {
+ if r >= a.nd {
+ if n == 0 {
+ // a == 0; shouldn't get here, but handle anyway.
+ a.nd = 0
+ return
+ }
+ for n>>k == 0 {
+ n = n * 10
+ r++
+ }
+ break
+ }
+ c := uint(a.d[r])
+ n = n*10 + c - '0'
+ }
+ a.dp -= r - 1
+
+ var mask uint = (1 << k) - 1
+
+ // Pick up a digit, put down a digit.
+ for ; r < a.nd; r++ {
+ c := uint(a.d[r])
+ dig := n >> k
+ n &= mask
+ a.d[w] = byte(dig + '0')
+ w++
+ n = n*10 + c - '0'
+ }
+
+ // Put down extra digits.
+ for n > 0 {
+ dig := n >> k
+ n &= mask
+ if w < len(a.d) {
+ a.d[w] = byte(dig + '0')
+ w++
+ } else if dig > 0 {
+ a.trunc = true
+ }
+ n = n * 10
+ }
+
+ a.nd = w
+ trim(a)
+}
+
+// Cheat sheet for left shift: table indexed by shift count giving
+// number of new digits that will be introduced by that shift.
+//
+// For example, leftcheats[4] = {2, "625"}. That means that
+// if we are shifting by 4 (multiplying by 16), it will add 2 digits
+// when the string prefix is "625" through "999", and one fewer digit
+// if the string prefix is "000" through "624".
+//
+// Credit for this trick goes to Ken.
+
+type leftCheat struct {
+ delta int // number of new digits
+ cutoff string // minus one digit if original < a.
+}
+
+var leftcheats = []leftCheat{
+ // Leading digits of 1/2^i = 5^i.
+ // 5^23 is not an exact 64-bit floating point number,
+ // so have to use bc for the math.
+ // Go up to 60 to be large enough for 32bit and 64bit platforms.
+ /*
+ seq 60 | sed 's/^/5^/' | bc |
+ awk 'BEGIN{ print "\t{ 0, \"\" }," }
+ {
+ log2 = log(2)/log(10)
+ printf("\t{ %d, \"%s\" },\t// * %d\n",
+ int(log2*NR+1), $0, 2**NR)
+ }'
+ */
+ {0, ""},
+ {1, "5"}, // * 2
+ {1, "25"}, // * 4
+ {1, "125"}, // * 8
+ {2, "625"}, // * 16
+ {2, "3125"}, // * 32
+ {2, "15625"}, // * 64
+ {3, "78125"}, // * 128
+ {3, "390625"}, // * 256
+ {3, "1953125"}, // * 512
+ {4, "9765625"}, // * 1024
+ {4, "48828125"}, // * 2048
+ {4, "244140625"}, // * 4096
+ {4, "1220703125"}, // * 8192
+ {5, "6103515625"}, // * 16384
+ {5, "30517578125"}, // * 32768
+ {5, "152587890625"}, // * 65536
+ {6, "762939453125"}, // * 131072
+ {6, "3814697265625"}, // * 262144
+ {6, "19073486328125"}, // * 524288
+ {7, "95367431640625"}, // * 1048576
+ {7, "476837158203125"}, // * 2097152
+ {7, "2384185791015625"}, // * 4194304
+ {7, "11920928955078125"}, // * 8388608
+ {8, "59604644775390625"}, // * 16777216
+ {8, "298023223876953125"}, // * 33554432
+ {8, "1490116119384765625"}, // * 67108864
+ {9, "7450580596923828125"}, // * 134217728
+ {9, "37252902984619140625"}, // * 268435456
+ {9, "186264514923095703125"}, // * 536870912
+ {10, "931322574615478515625"}, // * 1073741824
+ {10, "4656612873077392578125"}, // * 2147483648
+ {10, "23283064365386962890625"}, // * 4294967296
+ {10, "116415321826934814453125"}, // * 8589934592
+ {11, "582076609134674072265625"}, // * 17179869184
+ {11, "2910383045673370361328125"}, // * 34359738368
+ {11, "14551915228366851806640625"}, // * 68719476736
+ {12, "72759576141834259033203125"}, // * 137438953472
+ {12, "363797880709171295166015625"}, // * 274877906944
+ {12, "1818989403545856475830078125"}, // * 549755813888
+ {13, "9094947017729282379150390625"}, // * 1099511627776
+ {13, "45474735088646411895751953125"}, // * 2199023255552
+ {13, "227373675443232059478759765625"}, // * 4398046511104
+ {13, "1136868377216160297393798828125"}, // * 8796093022208
+ {14, "5684341886080801486968994140625"}, // * 17592186044416
+ {14, "28421709430404007434844970703125"}, // * 35184372088832
+ {14, "142108547152020037174224853515625"}, // * 70368744177664
+ {15, "710542735760100185871124267578125"}, // * 140737488355328
+ {15, "3552713678800500929355621337890625"}, // * 281474976710656
+ {15, "17763568394002504646778106689453125"}, // * 562949953421312
+ {16, "88817841970012523233890533447265625"}, // * 1125899906842624
+ {16, "444089209850062616169452667236328125"}, // * 2251799813685248
+ {16, "2220446049250313080847263336181640625"}, // * 4503599627370496
+ {16, "11102230246251565404236316680908203125"}, // * 9007199254740992
+ {17, "55511151231257827021181583404541015625"}, // * 18014398509481984
+ {17, "277555756156289135105907917022705078125"}, // * 36028797018963968
+ {17, "1387778780781445675529539585113525390625"}, // * 72057594037927936
+ {18, "6938893903907228377647697925567626953125"}, // * 144115188075855872
+ {18, "34694469519536141888238489627838134765625"}, // * 288230376151711744
+ {18, "173472347597680709441192448139190673828125"}, // * 576460752303423488
+ {19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976
+}
+
+// Is the leading prefix of b lexicographically less than s?
+func prefixIsLessThan(b []byte, s string) bool {
+ for i := 0; i < len(s); i++ {
+ if i >= len(b) {
+ return true
+ }
+ if b[i] != s[i] {
+ return b[i] < s[i]
+ }
+ }
+ return false
+}
+
+// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow.
+func leftShift(a *decimal, k uint) {
+ delta := leftcheats[k].delta
+ if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) {
+ delta--
+ }
+
+ r := a.nd // read index
+ w := a.nd + delta // write index
+
+ // Pick up a digit, put down a digit.
+ var n uint
+ for r--; r >= 0; r-- {
+ n += (uint(a.d[r]) - '0') << k
+ quo := n / 10
+ rem := n - 10*quo
+ w--
+ if w < len(a.d) {
+ a.d[w] = byte(rem + '0')
+ } else if rem != 0 {
+ a.trunc = true
+ }
+ n = quo
+ }
+
+ // Put down extra digits.
+ for n > 0 {
+ quo := n / 10
+ rem := n - 10*quo
+ w--
+ if w < len(a.d) {
+ a.d[w] = byte(rem + '0')
+ } else if rem != 0 {
+ a.trunc = true
+ }
+ n = quo
+ }
+
+ a.nd += delta
+ if a.nd >= len(a.d) {
+ a.nd = len(a.d)
+ }
+ a.dp += delta
+ trim(a)
+}
+
+// Binary shift left (k > 0) or right (k < 0).
+func (a *decimal) Shift(k int) {
+ switch {
+ case a.nd == 0:
+ // nothing to do: a == 0
+ case k > 0:
+ for k > maxShift {
+ leftShift(a, maxShift)
+ k -= maxShift
+ }
+ leftShift(a, uint(k))
+ case k < 0:
+ for k < -maxShift {
+ rightShift(a, maxShift)
+ k += maxShift
+ }
+ rightShift(a, uint(-k))
+ }
+}
+
+// If we chop a at nd digits, should we round up?
+func shouldRoundUp(a *decimal, nd int) bool {
+ if nd < 0 || nd >= a.nd {
+ return false
+ }
+ if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even
+ // if we truncated, a little higher than what's recorded - always round up
+ if a.trunc {
+ return true
+ }
+ return nd > 0 && (a.d[nd-1]-'0')%2 != 0
+ }
+ // not halfway - digit tells all
+ return a.d[nd] >= '5'
+}
+
+// Round a to nd digits (or fewer).
+// If nd is zero, it means we're rounding
+// just to the left of the digits, as in
+// 0.09 -> 0.1.
+func (a *decimal) Round(nd int) {
+ if nd < 0 || nd >= a.nd {
+ return
+ }
+ if shouldRoundUp(a, nd) {
+ a.RoundUp(nd)
+ } else {
+ a.RoundDown(nd)
+ }
+}
+
+// Round a down to nd digits (or fewer).
+func (a *decimal) RoundDown(nd int) {
+ if nd < 0 || nd >= a.nd {
+ return
+ }
+ a.nd = nd
+ trim(a)
+}
+
+// Round a up to nd digits (or fewer).
+func (a *decimal) RoundUp(nd int) {
+ if nd < 0 || nd >= a.nd {
+ return
+ }
+
+ // round up
+ for i := nd - 1; i >= 0; i-- {
+ c := a.d[i]
+ if c < '9' { // can stop after this digit
+ a.d[i]++
+ a.nd = i + 1
+ return
+ }
+ }
+
+ // Number is all 9s.
+ // Change to single 1 with adjusted decimal point.
+ a.d[0] = '1'
+ a.nd = 1
+ a.dp++
+}
+
+// Extract integer part, rounded appropriately.
+// No guarantees about overflow.
+func (a *decimal) RoundedInteger() uint64 {
+ if a.dp > 20 {
+ return 0xFFFFFFFFFFFFFFFF
+ }
+ var i int
+ n := uint64(0)
+ for i = 0; i < a.dp && i < a.nd; i++ {
+ n = n*10 + uint64(a.d[i]-'0')
+ }
+ for ; i < a.dp; i++ {
+ n *= 10
+ }
+ if shouldRoundUp(a, a.dp) {
+ n++
+ }
+ return n
+}
diff --git a/vendor/github.com/shopspring/decimal/decimal.go b/vendor/github.com/shopspring/decimal/decimal.go
new file mode 100644
index 0000000..a37a230
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/decimal.go
@@ -0,0 +1,2339 @@
+// Package decimal implements an arbitrary precision fixed-point decimal.
+//
+// The zero-value of a Decimal is 0, as you would expect.
+//
+// The best way to create a new Decimal is to use decimal.NewFromString, ex:
+//
+// n, err := decimal.NewFromString("-123.4567")
+// n.String() // output: "-123.4567"
+//
+// To use Decimal as part of a struct:
+//
+// type StructName struct {
+// Number Decimal
+// }
+//
+// Note: This can "only" represent numbers with a maximum of 2^31 digits after the decimal point.
+package decimal
+
+import (
+ "database/sql/driver"
+ "encoding/binary"
+ "fmt"
+ "math"
+ "math/big"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+// DivisionPrecision is the number of decimal places in the result when it
+// doesn't divide exactly.
+//
+// Example:
+//
+// d1 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3))
+// d1.String() // output: "0.6666666666666667"
+// d2 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(30000))
+// d2.String() // output: "0.0000666666666667"
+// d3 := decimal.NewFromFloat(20000).Div(decimal.NewFromFloat(3))
+// d3.String() // output: "6666.6666666666666667"
+// decimal.DivisionPrecision = 3
+// d4 := decimal.NewFromFloat(2).Div(decimal.NewFromFloat(3))
+// d4.String() // output: "0.667"
+var DivisionPrecision = 16
+
+// PowPrecisionNegativeExponent specifies the maximum precision of the result (digits after decimal point)
+// when calculating decimal power. Only used for cases where the exponent is a negative number.
+// This constant applies to Pow, PowInt32 and PowBigInt methods, PowWithPrecision method is not constrained by it.
+//
+// Example:
+//
+// d1, err := decimal.NewFromFloat(15.2).PowInt32(-2)
+// d1.String() // output: "0.0043282548476454"
+//
+// decimal.PowPrecisionNegativeExponent = 24
+// d2, err := decimal.NewFromFloat(15.2).PowInt32(-2)
+// d2.String() // output: "0.004328254847645429362881"
+var PowPrecisionNegativeExponent = 16
+
+// MarshalJSONWithoutQuotes should be set to true if you want the decimal to
+// be JSON marshaled as a number, instead of as a string.
+// WARNING: this is dangerous for decimals with many digits, since many JSON
+// unmarshallers (ex: Javascript's) will unmarshal JSON numbers to IEEE 754
+// double-precision floating point numbers, which means you can potentially
+// silently lose precision.
+var MarshalJSONWithoutQuotes = false
+
+// ExpMaxIterations specifies the maximum number of iterations needed to calculate
+// precise natural exponent value using ExpHullAbrham method.
+var ExpMaxIterations = 1000
+
+// Zero constant, to make computations faster.
+// Zero should never be compared with == or != directly, please use decimal.Equal or decimal.Cmp instead.
+var Zero = New(0, 1)
+
+var zeroInt = big.NewInt(0)
+var oneInt = big.NewInt(1)
+var twoInt = big.NewInt(2)
+var fourInt = big.NewInt(4)
+var fiveInt = big.NewInt(5)
+var tenInt = big.NewInt(10)
+var twentyInt = big.NewInt(20)
+
+var factorials = []Decimal{New(1, 0)}
+
+// Decimal represents a fixed-point decimal. It is immutable.
+// number = value * 10 ^ exp
+type Decimal struct {
+ value *big.Int
+
+ // NOTE(vadim): this must be an int32, because we cast it to float64 during
+ // calculations. If exp is 64 bit, we might lose precision.
+ // If we cared about being able to represent every possible decimal, we
+ // could make exp a *big.Int but it would hurt performance and numbers
+ // like that are unrealistic.
+ exp int32
+}
+
+// New returns a new fixed-point decimal, value * 10 ^ exp.
+func New(value int64, exp int32) Decimal {
+ return Decimal{
+ value: big.NewInt(value),
+ exp: exp,
+ }
+}
+
+// NewFromInt converts an int64 to Decimal.
+//
+// Example:
+//
+// NewFromInt(123).String() // output: "123"
+// NewFromInt(-10).String() // output: "-10"
+func NewFromInt(value int64) Decimal {
+ return Decimal{
+ value: big.NewInt(value),
+ exp: 0,
+ }
+}
+
+// NewFromInt32 converts an int32 to Decimal.
+//
+// Example:
+//
+// NewFromInt(123).String() // output: "123"
+// NewFromInt(-10).String() // output: "-10"
+func NewFromInt32(value int32) Decimal {
+ return Decimal{
+ value: big.NewInt(int64(value)),
+ exp: 0,
+ }
+}
+
+// NewFromUint64 converts an uint64 to Decimal.
+//
+// Example:
+//
+// NewFromUint64(123).String() // output: "123"
+func NewFromUint64(value uint64) Decimal {
+ return Decimal{
+ value: new(big.Int).SetUint64(value),
+ exp: 0,
+ }
+}
+
+// NewFromBigInt returns a new Decimal from a big.Int, value * 10 ^ exp
+func NewFromBigInt(value *big.Int, exp int32) Decimal {
+ return Decimal{
+ value: new(big.Int).Set(value),
+ exp: exp,
+ }
+}
+
+// NewFromBigRat returns a new Decimal from a big.Rat. The numerator and
+// denominator are divided and rounded to the given precision.
+//
+// Example:
+//
+// d1 := NewFromBigRat(big.NewRat(0, 1), 0) // output: "0"
+// d2 := NewFromBigRat(big.NewRat(4, 5), 1) // output: "0.8"
+// d3 := NewFromBigRat(big.NewRat(1000, 3), 3) // output: "333.333"
+// d4 := NewFromBigRat(big.NewRat(2, 7), 4) // output: "0.2857"
+func NewFromBigRat(value *big.Rat, precision int32) Decimal {
+ return Decimal{
+ value: new(big.Int).Set(value.Num()),
+ exp: 0,
+ }.DivRound(Decimal{
+ value: new(big.Int).Set(value.Denom()),
+ exp: 0,
+ }, precision)
+}
+
+// NewFromString returns a new Decimal from a string representation.
+// Trailing zeroes are not trimmed.
+//
+// Example:
+//
+// d, err := NewFromString("-123.45")
+// d2, err := NewFromString(".0001")
+// d3, err := NewFromString("1.47000")
+func NewFromString(value string) (Decimal, error) {
+ originalInput := value
+ var intString string
+ var exp int64
+
+ // Check if number is using scientific notation
+ eIndex := strings.IndexAny(value, "Ee")
+ if eIndex != -1 {
+ expInt, err := strconv.ParseInt(value[eIndex+1:], 10, 32)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok && e.Err == strconv.ErrRange {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal: fractional part too long", value)
+ }
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal: exponent is not numeric", value)
+ }
+ value = value[:eIndex]
+ exp = expInt
+ }
+
+ pIndex := -1
+ vLen := len(value)
+ for i := 0; i < vLen; i++ {
+ if value[i] == '.' {
+ if pIndex > -1 {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal: too many .s", value)
+ }
+ pIndex = i
+ }
+ }
+
+ if pIndex == -1 {
+ // There is no decimal point, we can just parse the original string as
+ // an int
+ intString = value
+ } else {
+ if pIndex+1 < vLen {
+ intString = value[:pIndex] + value[pIndex+1:]
+ } else {
+ intString = value[:pIndex]
+ }
+ expInt := -len(value[pIndex+1:])
+ exp += int64(expInt)
+ }
+
+ var dValue *big.Int
+ // strconv.ParseInt is faster than new(big.Int).SetString so this is just a shortcut for strings we know won't overflow
+ if len(intString) <= 18 {
+ parsed64, err := strconv.ParseInt(intString, 10, 64)
+ if err != nil {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal", value)
+ }
+ dValue = big.NewInt(parsed64)
+ } else {
+ dValue = new(big.Int)
+ _, ok := dValue.SetString(intString, 10)
+ if !ok {
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal", value)
+ }
+ }
+
+ if exp < math.MinInt32 || exp > math.MaxInt32 {
+ // NOTE(vadim): I doubt a string could realistically be this long
+ return Decimal{}, fmt.Errorf("can't convert %s to decimal: fractional part too long", originalInput)
+ }
+
+ return Decimal{
+ value: dValue,
+ exp: int32(exp),
+ }, nil
+}
+
+// NewFromFormattedString returns a new Decimal from a formatted string representation.
+// The second argument - replRegexp, is a regular expression that is used to find characters that should be
+// removed from given decimal string representation. All matched characters will be replaced with an empty string.
+//
+// Example:
+//
+// r := regexp.MustCompile("[$,]")
+// d1, err := NewFromFormattedString("$5,125.99", r)
+//
+// r2 := regexp.MustCompile("[_]")
+// d2, err := NewFromFormattedString("1_000_000", r2)
+//
+// r3 := regexp.MustCompile("[USD\\s]")
+// d3, err := NewFromFormattedString("5000 USD", r3)
+func NewFromFormattedString(value string, replRegexp *regexp.Regexp) (Decimal, error) {
+ parsedValue := replRegexp.ReplaceAllString(value, "")
+ d, err := NewFromString(parsedValue)
+ if err != nil {
+ return Decimal{}, err
+ }
+ return d, nil
+}
+
+// RequireFromString returns a new Decimal from a string representation
+// or panics if NewFromString had returned an error.
+//
+// Example:
+//
+// d := RequireFromString("-123.45")
+// d2 := RequireFromString(".0001")
+func RequireFromString(value string) Decimal {
+ dec, err := NewFromString(value)
+ if err != nil {
+ panic(err)
+ }
+ return dec
+}
+
+// NewFromFloat converts a float64 to Decimal.
+//
+// The converted number will contain the number of significant digits that can be
+// represented in a float with reliable roundtrip.
+// This is typically 15 digits, but may be more in some cases.
+// See https://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ for more information.
+//
+// For slightly faster conversion, use NewFromFloatWithExponent where you can specify the precision in absolute terms.
+//
+// NOTE: this will panic on NaN, +/-inf
+func NewFromFloat(value float64) Decimal {
+ if value == 0 {
+ return New(0, 0)
+ }
+ return newFromFloat(value, math.Float64bits(value), &float64info)
+}
+
+// NewFromFloat32 converts a float32 to Decimal.
+//
+// The converted number will contain the number of significant digits that can be
+// represented in a float with reliable roundtrip.
+// This is typically 6-8 digits depending on the input.
+// See https://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ for more information.
+//
+// For slightly faster conversion, use NewFromFloatWithExponent where you can specify the precision in absolute terms.
+//
+// NOTE: this will panic on NaN, +/-inf
+func NewFromFloat32(value float32) Decimal {
+ if value == 0 {
+ return New(0, 0)
+ }
+ // XOR is workaround for https://github.com/golang/go/issues/26285
+ a := math.Float32bits(value) ^ 0x80808080
+ return newFromFloat(float64(value), uint64(a)^0x80808080, &float32info)
+}
+
+func newFromFloat(val float64, bits uint64, flt *floatInfo) Decimal {
+ if math.IsNaN(val) || math.IsInf(val, 0) {
+ panic(fmt.Sprintf("Cannot create a Decimal from %v", val))
+ }
+ exp := int(bits>>flt.mantbits) & (1<>(flt.expbits+flt.mantbits) != 0
+
+ roundShortest(&d, mant, exp, flt)
+ // If less than 19 digits, we can do calculation in an int64.
+ if d.nd < 19 {
+ tmp := int64(0)
+ m := int64(1)
+ for i := d.nd - 1; i >= 0; i-- {
+ tmp += m * int64(d.d[i]-'0')
+ m *= 10
+ }
+ if d.neg {
+ tmp *= -1
+ }
+ return Decimal{value: big.NewInt(tmp), exp: int32(d.dp) - int32(d.nd)}
+ }
+ dValue := new(big.Int)
+ dValue, ok := dValue.SetString(string(d.d[:d.nd]), 10)
+ if ok {
+ return Decimal{value: dValue, exp: int32(d.dp) - int32(d.nd)}
+ }
+
+ return NewFromFloatWithExponent(val, int32(d.dp)-int32(d.nd))
+}
+
+// NewFromFloatWithExponent converts a float64 to Decimal, with an arbitrary
+// number of fractional digits.
+//
+// Example:
+//
+// NewFromFloatWithExponent(123.456, -2).String() // output: "123.46"
+func NewFromFloatWithExponent(value float64, exp int32) Decimal {
+ if math.IsNaN(value) || math.IsInf(value, 0) {
+ panic(fmt.Sprintf("Cannot create a Decimal from %v", value))
+ }
+
+ bits := math.Float64bits(value)
+ mant := bits & (1<<52 - 1)
+ exp2 := int32((bits >> 52) & (1<<11 - 1))
+ sign := bits >> 63
+
+ if exp2 == 0 {
+ // specials
+ if mant == 0 {
+ return Decimal{}
+ }
+ // subnormal
+ exp2++
+ } else {
+ // normal
+ mant |= 1 << 52
+ }
+
+ exp2 -= 1023 + 52
+
+ // normalizing base-2 values
+ for mant&1 == 0 {
+ mant = mant >> 1
+ exp2++
+ }
+
+ // maximum number of fractional base-10 digits to represent 2^N exactly cannot be more than -N if N<0
+ if exp < 0 && exp < exp2 {
+ if exp2 < 0 {
+ exp = exp2
+ } else {
+ exp = 0
+ }
+ }
+
+ // representing 10^M * 2^N as 5^M * 2^(M+N)
+ exp2 -= exp
+
+ temp := big.NewInt(1)
+ dMant := big.NewInt(int64(mant))
+
+ // applying 5^M
+ if exp > 0 {
+ temp = temp.SetInt64(int64(exp))
+ temp = temp.Exp(fiveInt, temp, nil)
+ } else if exp < 0 {
+ temp = temp.SetInt64(-int64(exp))
+ temp = temp.Exp(fiveInt, temp, nil)
+ dMant = dMant.Mul(dMant, temp)
+ temp = temp.SetUint64(1)
+ }
+
+ // applying 2^(M+N)
+ if exp2 > 0 {
+ dMant = dMant.Lsh(dMant, uint(exp2))
+ } else if exp2 < 0 {
+ temp = temp.Lsh(temp, uint(-exp2))
+ }
+
+ // rounding and downscaling
+ if exp > 0 || exp2 < 0 {
+ halfDown := new(big.Int).Rsh(temp, 1)
+ dMant = dMant.Add(dMant, halfDown)
+ dMant = dMant.Quo(dMant, temp)
+ }
+
+ if sign == 1 {
+ dMant = dMant.Neg(dMant)
+ }
+
+ return Decimal{
+ value: dMant,
+ exp: exp,
+ }
+}
+
+// Copy returns a copy of decimal with the same value and exponent, but a different pointer to value.
+func (d Decimal) Copy() Decimal {
+ d.ensureInitialized()
+ return Decimal{
+ value: new(big.Int).Set(d.value),
+ exp: d.exp,
+ }
+}
+
+// rescale returns a rescaled version of the decimal. Returned
+// decimal may be less precise if the given exponent is bigger
+// than the initial exponent of the Decimal.
+// NOTE: this will truncate, NOT round
+//
+// Example:
+//
+// d := New(12345, -4)
+// d2 := d.rescale(-1)
+// d3 := d2.rescale(-4)
+// println(d1)
+// println(d2)
+// println(d3)
+//
+// Output:
+//
+// 1.2345
+// 1.2
+// 1.2000
+func (d Decimal) rescale(exp int32) Decimal {
+ d.ensureInitialized()
+
+ if d.exp == exp {
+ return Decimal{
+ new(big.Int).Set(d.value),
+ d.exp,
+ }
+ }
+
+ // NOTE(vadim): must convert exps to float64 before - to prevent overflow
+ diff := math.Abs(float64(exp) - float64(d.exp))
+ value := new(big.Int).Set(d.value)
+
+ expScale := new(big.Int).Exp(tenInt, big.NewInt(int64(diff)), nil)
+ if exp > d.exp {
+ value = value.Quo(value, expScale)
+ } else if exp < d.exp {
+ value = value.Mul(value, expScale)
+ }
+
+ return Decimal{
+ value: value,
+ exp: exp,
+ }
+}
+
+// Abs returns the absolute value of the decimal.
+func (d Decimal) Abs() Decimal {
+ if !d.IsNegative() {
+ return d
+ }
+ d.ensureInitialized()
+ d2Value := new(big.Int).Abs(d.value)
+ return Decimal{
+ value: d2Value,
+ exp: d.exp,
+ }
+}
+
+// Add returns d + d2.
+func (d Decimal) Add(d2 Decimal) Decimal {
+ rd, rd2 := RescalePair(d, d2)
+
+ d3Value := new(big.Int).Add(rd.value, rd2.value)
+ return Decimal{
+ value: d3Value,
+ exp: rd.exp,
+ }
+}
+
+// Sub returns d - d2.
+func (d Decimal) Sub(d2 Decimal) Decimal {
+ rd, rd2 := RescalePair(d, d2)
+
+ d3Value := new(big.Int).Sub(rd.value, rd2.value)
+ return Decimal{
+ value: d3Value,
+ exp: rd.exp,
+ }
+}
+
+// Neg returns -d.
+func (d Decimal) Neg() Decimal {
+ d.ensureInitialized()
+ val := new(big.Int).Neg(d.value)
+ return Decimal{
+ value: val,
+ exp: d.exp,
+ }
+}
+
+// Mul returns d * d2.
+func (d Decimal) Mul(d2 Decimal) Decimal {
+ d.ensureInitialized()
+ d2.ensureInitialized()
+
+ expInt64 := int64(d.exp) + int64(d2.exp)
+ if expInt64 > math.MaxInt32 || expInt64 < math.MinInt32 {
+ // NOTE(vadim): better to panic than give incorrect results, as
+ // Decimals are usually used for money
+ panic(fmt.Sprintf("exponent %v overflows an int32!", expInt64))
+ }
+
+ d3Value := new(big.Int).Mul(d.value, d2.value)
+ return Decimal{
+ value: d3Value,
+ exp: int32(expInt64),
+ }
+}
+
+// Shift shifts the decimal in base 10.
+// It shifts left when shift is positive and right if shift is negative.
+// In simpler terms, the given value for shift is added to the exponent
+// of the decimal.
+func (d Decimal) Shift(shift int32) Decimal {
+ d.ensureInitialized()
+ return Decimal{
+ value: new(big.Int).Set(d.value),
+ exp: d.exp + shift,
+ }
+}
+
+// Div returns d / d2. If it doesn't divide exactly, the result will have
+// DivisionPrecision digits after the decimal point.
+func (d Decimal) Div(d2 Decimal) Decimal {
+ return d.DivRound(d2, int32(DivisionPrecision))
+}
+
+// QuoRem does division with remainder
+// d.QuoRem(d2,precision) returns quotient q and remainder r such that
+//
+// d = d2 * q + r, q an integer multiple of 10^(-precision)
+// 0 <= r < abs(d2) * 10 ^(-precision) if d>=0
+// 0 >= r > -abs(d2) * 10 ^(-precision) if d<0
+//
+// Note that precision<0 is allowed as input.
+func (d Decimal) QuoRem(d2 Decimal, precision int32) (Decimal, Decimal) {
+ d.ensureInitialized()
+ d2.ensureInitialized()
+ if d2.value.Sign() == 0 {
+ panic("decimal division by 0")
+ }
+ scale := -precision
+ e := int64(d.exp) - int64(d2.exp) - int64(scale)
+ if e > math.MaxInt32 || e < math.MinInt32 {
+ panic("overflow in decimal QuoRem")
+ }
+ var aa, bb, expo big.Int
+ var scalerest int32
+ // d = a 10^ea
+ // d2 = b 10^eb
+ if e < 0 {
+ aa = *d.value
+ expo.SetInt64(-e)
+ bb.Exp(tenInt, &expo, nil)
+ bb.Mul(d2.value, &bb)
+ scalerest = d.exp
+ // now aa = a
+ // bb = b 10^(scale + eb - ea)
+ } else {
+ expo.SetInt64(e)
+ aa.Exp(tenInt, &expo, nil)
+ aa.Mul(d.value, &aa)
+ bb = *d2.value
+ scalerest = scale + d2.exp
+ // now aa = a ^ (ea - eb - scale)
+ // bb = b
+ }
+ var q, r big.Int
+ q.QuoRem(&aa, &bb, &r)
+ dq := Decimal{value: &q, exp: scale}
+ dr := Decimal{value: &r, exp: scalerest}
+ return dq, dr
+}
+
+// DivRound divides and rounds to a given precision
+// i.e. to an integer multiple of 10^(-precision)
+//
+// for a positive quotient digit 5 is rounded up, away from 0
+// if the quotient is negative then digit 5 is rounded down, away from 0
+//
+// Note that precision<0 is allowed as input.
+func (d Decimal) DivRound(d2 Decimal, precision int32) Decimal {
+ // QuoRem already checks initialization
+ q, r := d.QuoRem(d2, precision)
+ // the actual rounding decision is based on comparing r*10^precision and d2/2
+ // instead compare 2 r 10 ^precision and d2
+ var rv2 big.Int
+ rv2.Abs(r.value)
+ rv2.Lsh(&rv2, 1)
+ // now rv2 = abs(r.value) * 2
+ r2 := Decimal{value: &rv2, exp: r.exp + precision}
+ // r2 is now 2 * r * 10 ^ precision
+ var c = r2.Cmp(d2.Abs())
+
+ if c < 0 {
+ return q
+ }
+
+ if d.value.Sign()*d2.value.Sign() < 0 {
+ return q.Sub(New(1, -precision))
+ }
+
+ return q.Add(New(1, -precision))
+}
+
+// Mod returns d % d2.
+func (d Decimal) Mod(d2 Decimal) Decimal {
+ _, r := d.QuoRem(d2, 0)
+ return r
+}
+
+// Pow returns d to the power of d2.
+// When exponent is negative the returned decimal will have maximum precision of PowPrecisionNegativeExponent places after decimal point.
+//
+// Pow returns 0 (zero-value of Decimal) instead of error for power operation edge cases, to handle those edge cases use PowWithPrecision
+// Edge cases not handled by Pow:
+// - 0 ** 0 => undefined value
+// - 0 ** y, where y < 0 => infinity
+// - x ** y, where x < 0 and y is non-integer decimal => imaginary value
+//
+// Example:
+//
+// d1 := decimal.NewFromFloat(4.0)
+// d2 := decimal.NewFromFloat(4.0)
+// res1 := d1.Pow(d2)
+// res1.String() // output: "256"
+//
+// d3 := decimal.NewFromFloat(5.0)
+// d4 := decimal.NewFromFloat(5.73)
+// res2 := d3.Pow(d4)
+// res2.String() // output: "10118.08037125"
+func (d Decimal) Pow(d2 Decimal) Decimal {
+ baseSign := d.Sign()
+ expSign := d2.Sign()
+
+ if baseSign == 0 {
+ if expSign == 0 {
+ return Decimal{}
+ }
+ if expSign == 1 {
+ return Decimal{zeroInt, 0}
+ }
+ if expSign == -1 {
+ return Decimal{}
+ }
+ }
+
+ if expSign == 0 {
+ return Decimal{oneInt, 0}
+ }
+
+ // TODO: optimize extraction of fractional part
+ one := Decimal{oneInt, 0}
+ expIntPart, expFracPart := d2.QuoRem(one, 0)
+
+ if baseSign == -1 && !expFracPart.IsZero() {
+ return Decimal{}
+ }
+
+ intPartPow, _ := d.PowBigInt(expIntPart.value)
+
+ // if exponent is an integer we don't need to calculate d1**frac(d2)
+ if expFracPart.value.Sign() == 0 {
+ return intPartPow
+ }
+
+ // TODO: optimize NumDigits for more performant precision adjustment
+ digitsBase := d.NumDigits()
+ digitsExponent := d2.NumDigits()
+
+ precision := digitsBase
+
+ if digitsExponent > precision {
+ precision += digitsExponent
+ }
+
+ precision += 6
+
+ // Calculate x ** frac(y), where
+ // x ** frac(y) = exp(ln(x ** frac(y)) = exp(ln(x) * frac(y))
+ fracPartPow, err := d.Abs().Ln(-d.exp + int32(precision))
+ if err != nil {
+ return Decimal{}
+ }
+
+ fracPartPow = fracPartPow.Mul(expFracPart)
+
+ fracPartPow, err = fracPartPow.ExpTaylor(-d.exp + int32(precision))
+ if err != nil {
+ return Decimal{}
+ }
+
+ // Join integer and fractional part,
+ // base ** (expBase + expFrac) = base ** expBase * base ** expFrac
+ res := intPartPow.Mul(fracPartPow)
+
+ return res
+}
+
+// PowWithPrecision returns d to the power of d2.
+// Precision parameter specifies minimum precision of the result (digits after decimal point).
+// Returned decimal is not rounded to 'precision' places after decimal point.
+//
+// PowWithPrecision returns error when:
+// - 0 ** 0 => undefined value
+// - 0 ** y, where y < 0 => infinity
+// - x ** y, where x < 0 and y is non-integer decimal => imaginary value
+//
+// Example:
+//
+// d1 := decimal.NewFromFloat(4.0)
+// d2 := decimal.NewFromFloat(4.0)
+// res1, err := d1.PowWithPrecision(d2, 2)
+// res1.String() // output: "256"
+//
+// d3 := decimal.NewFromFloat(5.0)
+// d4 := decimal.NewFromFloat(5.73)
+// res2, err := d3.PowWithPrecision(d4, 5)
+// res2.String() // output: "10118.080371595015625"
+//
+// d5 := decimal.NewFromFloat(-3.0)
+// d6 := decimal.NewFromFloat(-6.0)
+// res3, err := d5.PowWithPrecision(d6, 10)
+// res3.String() // output: "0.0013717421"
+func (d Decimal) PowWithPrecision(d2 Decimal, precision int32) (Decimal, error) {
+ baseSign := d.Sign()
+ expSign := d2.Sign()
+
+ if baseSign == 0 {
+ if expSign == 0 {
+ return Decimal{}, fmt.Errorf("cannot represent undefined value of 0**0")
+ }
+ if expSign == 1 {
+ return Decimal{zeroInt, 0}, nil
+ }
+ if expSign == -1 {
+ return Decimal{}, fmt.Errorf("cannot represent infinity value of 0 ** y, where y < 0")
+ }
+ }
+
+ if expSign == 0 {
+ return Decimal{oneInt, 0}, nil
+ }
+
+ // TODO: optimize extraction of fractional part
+ one := Decimal{oneInt, 0}
+ expIntPart, expFracPart := d2.QuoRem(one, 0)
+
+ if baseSign == -1 && !expFracPart.IsZero() {
+ return Decimal{}, fmt.Errorf("cannot represent imaginary value of x ** y, where x < 0 and y is non-integer decimal")
+ }
+
+ intPartPow, _ := d.powBigIntWithPrecision(expIntPart.value, precision)
+
+ // if exponent is an integer we don't need to calculate d1**frac(d2)
+ if expFracPart.value.Sign() == 0 {
+ return intPartPow, nil
+ }
+
+ // TODO: optimize NumDigits for more performant precision adjustment
+ digitsBase := d.NumDigits()
+ digitsExponent := d2.NumDigits()
+
+ if int32(digitsBase) > precision {
+ precision = int32(digitsBase)
+ }
+ if int32(digitsExponent) > precision {
+ precision += int32(digitsExponent)
+ }
+ // increase precision by 10 to compensate for errors in further calculations
+ precision += 10
+
+ // Calculate x ** frac(y), where
+ // x ** frac(y) = exp(ln(x ** frac(y)) = exp(ln(x) * frac(y))
+ fracPartPow, err := d.Abs().Ln(precision)
+ if err != nil {
+ return Decimal{}, err
+ }
+
+ fracPartPow = fracPartPow.Mul(expFracPart)
+
+ fracPartPow, err = fracPartPow.ExpTaylor(precision)
+ if err != nil {
+ return Decimal{}, err
+ }
+
+ // Join integer and fractional part,
+ // base ** (expBase + expFrac) = base ** expBase * base ** expFrac
+ res := intPartPow.Mul(fracPartPow)
+
+ return res, nil
+}
+
+// PowInt32 returns d to the power of exp, where exp is int32.
+// Only returns error when d and exp is 0, thus result is undefined.
+//
+// When exponent is negative the returned decimal will have maximum precision of PowPrecisionNegativeExponent places after decimal point.
+//
+// Example:
+//
+// d1, err := decimal.NewFromFloat(4.0).PowInt32(4)
+// d1.String() // output: "256"
+//
+// d2, err := decimal.NewFromFloat(3.13).PowInt32(5)
+// d2.String() // output: "300.4150512793"
+func (d Decimal) PowInt32(exp int32) (Decimal, error) {
+ if d.IsZero() && exp == 0 {
+ return Decimal{}, fmt.Errorf("cannot represent undefined value of 0**0")
+ }
+
+ isExpNeg := exp < 0
+ exp = abs(exp)
+
+ n, result := d, New(1, 0)
+
+ for exp > 0 {
+ if exp%2 == 1 {
+ result = result.Mul(n)
+ }
+ exp /= 2
+
+ if exp > 0 {
+ n = n.Mul(n)
+ }
+ }
+
+ if isExpNeg {
+ return New(1, 0).DivRound(result, int32(PowPrecisionNegativeExponent)), nil
+ }
+
+ return result, nil
+}
+
+// PowBigInt returns d to the power of exp, where exp is big.Int.
+// Only returns error when d and exp is 0, thus result is undefined.
+//
+// When exponent is negative the returned decimal will have maximum precision of PowPrecisionNegativeExponent places after decimal point.
+//
+// Example:
+//
+// d1, err := decimal.NewFromFloat(3.0).PowBigInt(big.NewInt(3))
+// d1.String() // output: "27"
+//
+// d2, err := decimal.NewFromFloat(629.25).PowBigInt(big.NewInt(5))
+// d2.String() // output: "98654323103449.5673828125"
+func (d Decimal) PowBigInt(exp *big.Int) (Decimal, error) {
+ return d.powBigIntWithPrecision(exp, int32(PowPrecisionNegativeExponent))
+}
+
+func (d Decimal) powBigIntWithPrecision(exp *big.Int, precision int32) (Decimal, error) {
+ if d.IsZero() && exp.Sign() == 0 {
+ return Decimal{}, fmt.Errorf("cannot represent undefined value of 0**0")
+ }
+
+ tmpExp := new(big.Int).Set(exp)
+ isExpNeg := exp.Sign() < 0
+
+ if isExpNeg {
+ tmpExp.Abs(tmpExp)
+ }
+
+ n, result := d, New(1, 0)
+
+ for tmpExp.Sign() > 0 {
+ if tmpExp.Bit(0) == 1 {
+ result = result.Mul(n)
+ }
+ tmpExp.Rsh(tmpExp, 1)
+
+ if tmpExp.Sign() > 0 {
+ n = n.Mul(n)
+ }
+ }
+
+ if isExpNeg {
+ return New(1, 0).DivRound(result, precision), nil
+ }
+
+ return result, nil
+}
+
+// ExpHullAbrham calculates the natural exponent of decimal (e to the power of d) using Hull-Abraham algorithm.
+// OverallPrecision argument specifies the overall precision of the result (integer part + decimal part).
+//
+// ExpHullAbrham is faster than ExpTaylor for small precision values, but it is much slower for large precision values.
+//
+// Example:
+//
+// NewFromFloat(26.1).ExpHullAbrham(2).String() // output: "220000000000"
+// NewFromFloat(26.1).ExpHullAbrham(20).String() // output: "216314672147.05767284"
+func (d Decimal) ExpHullAbrham(overallPrecision uint32) (Decimal, error) {
+ // Algorithm based on Variable precision exponential function.
+ // ACM Transactions on Mathematical Software by T. E. Hull & A. Abrham.
+ if d.IsZero() {
+ return Decimal{oneInt, 0}, nil
+ }
+
+ currentPrecision := overallPrecision
+
+ // Algorithm does not work if currentPrecision * 23 < |x|.
+ // Precision is automatically increased in such cases, so the value can be calculated precisely.
+ // If newly calculated precision is higher than ExpMaxIterations the currentPrecision will not be changed.
+ f := d.Abs().InexactFloat64()
+ if ncp := f / 23; ncp > float64(currentPrecision) && ncp < float64(ExpMaxIterations) {
+ currentPrecision = uint32(math.Ceil(ncp))
+ }
+
+ // fail if abs(d) beyond an over/underflow threshold
+ overflowThreshold := New(23*int64(currentPrecision), 0)
+ if d.Abs().Cmp(overflowThreshold) > 0 {
+ return Decimal{}, fmt.Errorf("over/underflow threshold, exp(x) cannot be calculated precisely")
+ }
+
+ // Return 1 if abs(d) small enough; this also avoids later over/underflow
+ overflowThreshold2 := New(9, -int32(currentPrecision)-1)
+ if d.Abs().Cmp(overflowThreshold2) <= 0 {
+ return Decimal{oneInt, d.exp}, nil
+ }
+
+ // t is the smallest integer >= 0 such that the corresponding abs(d/k) < 1
+ t := d.exp + int32(d.NumDigits()) // Add d.NumDigits because the paper assumes that d.value [0.1, 1)
+
+ if t < 0 {
+ t = 0
+ }
+
+ k := New(1, t) // reduction factor
+ r := Decimal{new(big.Int).Set(d.value), d.exp - t} // reduced argument
+ p := int32(currentPrecision) + t + 2 // precision for calculating the sum
+
+ // Determine n, the number of therms for calculating sum
+ // use first Newton step (1.435p - 1.182) / log10(p/abs(r))
+ // for solving appropriate equation, along with directed
+ // roundings and simple rational bound for log10(p/abs(r))
+ rf := r.Abs().InexactFloat64()
+ pf := float64(p)
+ nf := math.Ceil((1.453*pf - 1.182) / math.Log10(pf/rf))
+ if nf > float64(ExpMaxIterations) || math.IsNaN(nf) {
+ return Decimal{}, fmt.Errorf("exact value cannot be calculated in <=ExpMaxIterations iterations")
+ }
+ n := int64(nf)
+
+ tmp := New(0, 0)
+ sum := New(1, 0)
+ one := New(1, 0)
+ for i := n - 1; i > 0; i-- {
+ tmp.value.SetInt64(i)
+ sum = sum.Mul(r.DivRound(tmp, p))
+ sum = sum.Add(one)
+ }
+
+ ki := k.IntPart()
+ res := New(1, 0)
+ for i := ki; i > 0; i-- {
+ res = res.Mul(sum)
+ }
+
+ resNumDigits := int32(res.NumDigits())
+
+ var roundDigits int32
+ if resNumDigits > abs(res.exp) {
+ roundDigits = int32(currentPrecision) - resNumDigits - res.exp
+ } else {
+ roundDigits = int32(currentPrecision)
+ }
+
+ res = res.Round(roundDigits)
+
+ return res, nil
+}
+
+// ExpTaylor calculates the natural exponent of decimal (e to the power of d) using Taylor series expansion.
+// Precision argument specifies how precise the result must be (number of digits after decimal point).
+// Negative precision is allowed.
+//
+// ExpTaylor is much faster for large precision values than ExpHullAbrham.
+//
+// Example:
+//
+// d, err := NewFromFloat(26.1).ExpTaylor(2).String()
+// d.String() // output: "216314672147.06"
+//
+// NewFromFloat(26.1).ExpTaylor(20).String()
+// d.String() // output: "216314672147.05767284062928674083"
+//
+// NewFromFloat(26.1).ExpTaylor(-10).String()
+// d.String() // output: "220000000000"
+func (d Decimal) ExpTaylor(precision int32) (Decimal, error) {
+ // Note(mwoss): Implementation can be optimized by exclusively using big.Int API only
+ if d.IsZero() {
+ return Decimal{oneInt, 0}.Round(precision), nil
+ }
+
+ var epsilon Decimal
+ var divPrecision int32
+ if precision < 0 {
+ epsilon = New(1, -1)
+ divPrecision = 8
+ } else {
+ epsilon = New(1, -precision-1)
+ divPrecision = precision + 1
+ }
+
+ decAbs := d.Abs()
+ pow := d.Abs()
+ factorial := New(1, 0)
+
+ result := New(1, 0)
+
+ for i := int64(1); ; {
+ step := pow.DivRound(factorial, divPrecision)
+ result = result.Add(step)
+
+ // Stop Taylor series when current step is smaller than epsilon
+ if step.Cmp(epsilon) < 0 {
+ break
+ }
+
+ pow = pow.Mul(decAbs)
+
+ i++
+
+ // Calculate next factorial number or retrieve cached value
+ if len(factorials) >= int(i) && !factorials[i-1].IsZero() {
+ factorial = factorials[i-1]
+ } else {
+ // To avoid any race conditions, firstly the zero value is appended to a slice to create
+ // a spot for newly calculated factorial. After that, the zero value is replaced by calculated
+ // factorial using the index notation.
+ factorial = factorials[i-2].Mul(New(i, 0))
+ factorials = append(factorials, Zero)
+ factorials[i-1] = factorial
+ }
+ }
+
+ if d.Sign() < 0 {
+ result = New(1, 0).DivRound(result, precision+1)
+ }
+
+ result = result.Round(precision)
+ return result, nil
+}
+
+// Ln calculates natural logarithm of d.
+// Precision argument specifies how precise the result must be (number of digits after decimal point).
+// Negative precision is allowed.
+//
+// Example:
+//
+// d1, err := NewFromFloat(13.3).Ln(2)
+// d1.String() // output: "2.59"
+//
+// d2, err := NewFromFloat(579.161).Ln(10)
+// d2.String() // output: "6.3615805046"
+func (d Decimal) Ln(precision int32) (Decimal, error) {
+ // Algorithm based on The Use of Iteration Methods for Approximating the Natural Logarithm,
+ // James F. Epperson, The American Mathematical Monthly, Vol. 96, No. 9, November 1989, pp. 831-835.
+ if d.IsNegative() {
+ return Decimal{}, fmt.Errorf("cannot calculate natural logarithm for negative decimals")
+ }
+
+ if d.IsZero() {
+ return Decimal{}, fmt.Errorf("cannot represent natural logarithm of 0, result: -infinity")
+ }
+
+ calcPrecision := precision + 2
+ z := d.Copy()
+
+ var comp1, comp3, comp2, comp4, reduceAdjust Decimal
+ comp1 = z.Sub(Decimal{oneInt, 0})
+ comp3 = Decimal{oneInt, -1}
+
+ // for decimal in range [0.9, 1.1] where ln(d) is close to 0
+ usePowerSeries := false
+
+ if comp1.Abs().Cmp(comp3) <= 0 {
+ usePowerSeries = true
+ } else {
+ // reduce input decimal to range [0.1, 1)
+ expDelta := int32(z.NumDigits()) + z.exp
+ z.exp -= expDelta
+
+ // Input decimal was reduced by factor of 10^expDelta, thus we will need to add
+ // ln(10^expDelta) = expDelta * ln(10)
+ // to the result to compensate that
+ ln10 := ln10.withPrecision(calcPrecision)
+ reduceAdjust = NewFromInt32(expDelta)
+ reduceAdjust = reduceAdjust.Mul(ln10)
+
+ comp1 = z.Sub(Decimal{oneInt, 0})
+
+ if comp1.Abs().Cmp(comp3) <= 0 {
+ usePowerSeries = true
+ } else {
+ // initial estimate using floats
+ zFloat := z.InexactFloat64()
+ comp1 = NewFromFloat(math.Log(zFloat))
+ }
+ }
+
+ epsilon := Decimal{oneInt, -calcPrecision}
+
+ if usePowerSeries {
+ // Power Series - https://en.wikipedia.org/wiki/Logarithm#Power_series
+ // Calculating n-th term of formula: ln(z+1) = 2 sum [ 1 / (2n+1) * (z / (z+2))^(2n+1) ]
+ // until the difference between current and next term is smaller than epsilon.
+ // Coverage quite fast for decimals close to 1.0
+
+ // z + 2
+ comp2 = comp1.Add(Decimal{twoInt, 0})
+ // z / (z + 2)
+ comp3 = comp1.DivRound(comp2, calcPrecision)
+ // 2 * (z / (z + 2))
+ comp1 = comp3.Add(comp3)
+ comp2 = comp1.Copy()
+
+ for n := 1; ; n++ {
+ // 2 * (z / (z+2))^(2n+1)
+ comp2 = comp2.Mul(comp3).Mul(comp3)
+
+ // 1 / (2n+1) * 2 * (z / (z+2))^(2n+1)
+ comp4 = NewFromInt(int64(2*n + 1))
+ comp4 = comp2.DivRound(comp4, calcPrecision)
+
+ // comp1 = 2 sum [ 1 / (2n+1) * (z / (z+2))^(2n+1) ]
+ comp1 = comp1.Add(comp4)
+
+ if comp4.Abs().Cmp(epsilon) <= 0 {
+ break
+ }
+ }
+ } else {
+ // Halley's Iteration.
+ // Calculating n-th term of formula: a_(n+1) = a_n - 2 * (exp(a_n) - z) / (exp(a_n) + z),
+ // until the difference between current and next term is smaller than epsilon
+ var prevStep Decimal
+ maxIters := calcPrecision*2 + 10
+
+ for i := int32(0); i < maxIters; i++ {
+ // exp(a_n)
+ comp3, _ = comp1.ExpTaylor(calcPrecision)
+ // exp(a_n) - z
+ comp2 = comp3.Sub(z)
+ // 2 * (exp(a_n) - z)
+ comp2 = comp2.Add(comp2)
+ // exp(a_n) + z
+ comp4 = comp3.Add(z)
+ // 2 * (exp(a_n) - z) / (exp(a_n) + z)
+ comp3 = comp2.DivRound(comp4, calcPrecision)
+ // comp1 = a_(n+1) = a_n - 2 * (exp(a_n) - z) / (exp(a_n) + z)
+ comp1 = comp1.Sub(comp3)
+
+ if prevStep.Add(comp3).IsZero() {
+ // If iteration steps oscillate we should return early and prevent an infinity loop
+ // NOTE(mwoss): This should be quite a rare case, returning error is not necessary
+ break
+ }
+
+ if comp3.Abs().Cmp(epsilon) <= 0 {
+ break
+ }
+
+ prevStep = comp3
+ }
+ }
+
+ comp1 = comp1.Add(reduceAdjust)
+
+ return comp1.Round(precision), nil
+}
+
+// NumDigits returns the number of digits of the decimal coefficient (d.Value)
+func (d Decimal) NumDigits() int {
+ if d.value == nil {
+ return 1
+ }
+
+ if d.value.IsInt64() {
+ i64 := d.value.Int64()
+ // restrict fast path to integers with exact conversion to float64
+ if i64 <= (1<<53) && i64 >= -(1<<53) {
+ if i64 == 0 {
+ return 1
+ }
+ return int(math.Log10(math.Abs(float64(i64)))) + 1
+ }
+ }
+
+ estimatedNumDigits := int(float64(d.value.BitLen()) / math.Log2(10))
+
+ // estimatedNumDigits (lg10) may be off by 1, need to verify
+ digitsBigInt := big.NewInt(int64(estimatedNumDigits))
+ errorCorrectionUnit := digitsBigInt.Exp(tenInt, digitsBigInt, nil)
+
+ if d.value.CmpAbs(errorCorrectionUnit) >= 0 {
+ return estimatedNumDigits + 1
+ }
+
+ return estimatedNumDigits
+}
+
+// IsInteger returns true when decimal can be represented as an integer value, otherwise, it returns false.
+func (d Decimal) IsInteger() bool {
+ // The most typical case, all decimal with exponent higher or equal 0 can be represented as integer
+ if d.exp >= 0 {
+ return true
+ }
+ // When the exponent is negative we have to check every number after the decimal place
+ // If all of them are zeroes, we are sure that given decimal can be represented as an integer
+ var r big.Int
+ q := new(big.Int).Set(d.value)
+ for z := abs(d.exp); z > 0; z-- {
+ q.QuoRem(q, tenInt, &r)
+ if r.Cmp(zeroInt) != 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Abs calculates absolute value of any int32. Used for calculating absolute value of decimal's exponent.
+func abs(n int32) int32 {
+ if n < 0 {
+ return -n
+ }
+ return n
+}
+
+// Cmp compares the numbers represented by d and d2 and returns:
+//
+// -1 if d < d2
+// 0 if d == d2
+// +1 if d > d2
+func (d Decimal) Cmp(d2 Decimal) int {
+ d.ensureInitialized()
+ d2.ensureInitialized()
+
+ if d.exp == d2.exp {
+ return d.value.Cmp(d2.value)
+ }
+
+ rd, rd2 := RescalePair(d, d2)
+
+ return rd.value.Cmp(rd2.value)
+}
+
+// Compare compares the numbers represented by d and d2 and returns:
+//
+// -1 if d < d2
+// 0 if d == d2
+// +1 if d > d2
+func (d Decimal) Compare(d2 Decimal) int {
+ return d.Cmp(d2)
+}
+
+// Equal returns whether the numbers represented by d and d2 are equal.
+func (d Decimal) Equal(d2 Decimal) bool {
+ return d.Cmp(d2) == 0
+}
+
+// Deprecated: Equals is deprecated, please use Equal method instead.
+func (d Decimal) Equals(d2 Decimal) bool {
+ return d.Equal(d2)
+}
+
+// GreaterThan (GT) returns true when d is greater than d2.
+func (d Decimal) GreaterThan(d2 Decimal) bool {
+ return d.Cmp(d2) == 1
+}
+
+// GreaterThanOrEqual (GTE) returns true when d is greater than or equal to d2.
+func (d Decimal) GreaterThanOrEqual(d2 Decimal) bool {
+ cmp := d.Cmp(d2)
+ return cmp == 1 || cmp == 0
+}
+
+// LessThan (LT) returns true when d is less than d2.
+func (d Decimal) LessThan(d2 Decimal) bool {
+ return d.Cmp(d2) == -1
+}
+
+// LessThanOrEqual (LTE) returns true when d is less than or equal to d2.
+func (d Decimal) LessThanOrEqual(d2 Decimal) bool {
+ cmp := d.Cmp(d2)
+ return cmp == -1 || cmp == 0
+}
+
+// Sign returns:
+//
+// -1 if d < 0
+// 0 if d == 0
+// +1 if d > 0
+func (d Decimal) Sign() int {
+ if d.value == nil {
+ return 0
+ }
+ return d.value.Sign()
+}
+
+// IsPositive return
+//
+// true if d > 0
+// false if d == 0
+// false if d < 0
+func (d Decimal) IsPositive() bool {
+ return d.Sign() == 1
+}
+
+// IsNegative return
+//
+// true if d < 0
+// false if d == 0
+// false if d > 0
+func (d Decimal) IsNegative() bool {
+ return d.Sign() == -1
+}
+
+// IsZero return
+//
+// true if d == 0
+// false if d > 0
+// false if d < 0
+func (d Decimal) IsZero() bool {
+ return d.Sign() == 0
+}
+
+// Exponent returns the exponent, or scale component of the decimal.
+func (d Decimal) Exponent() int32 {
+ return d.exp
+}
+
+// Coefficient returns the coefficient of the decimal. It is scaled by 10^Exponent()
+func (d Decimal) Coefficient() *big.Int {
+ d.ensureInitialized()
+ // we copy the coefficient so that mutating the result does not mutate the Decimal.
+ return new(big.Int).Set(d.value)
+}
+
+// CoefficientInt64 returns the coefficient of the decimal as int64. It is scaled by 10^Exponent()
+// If coefficient cannot be represented in an int64, the result will be undefined.
+func (d Decimal) CoefficientInt64() int64 {
+ d.ensureInitialized()
+ return d.value.Int64()
+}
+
+// IntPart returns the integer component of the decimal.
+func (d Decimal) IntPart() int64 {
+ scaledD := d.rescale(0)
+ return scaledD.value.Int64()
+}
+
+// BigInt returns integer component of the decimal as a BigInt.
+func (d Decimal) BigInt() *big.Int {
+ scaledD := d.rescale(0)
+ return scaledD.value
+}
+
+// BigFloat returns decimal as BigFloat.
+// Be aware that casting decimal to BigFloat might cause a loss of precision.
+func (d Decimal) BigFloat() *big.Float {
+ f := &big.Float{}
+ f.SetString(d.String())
+ return f
+}
+
+// Rat returns a rational number representation of the decimal.
+func (d Decimal) Rat() *big.Rat {
+ d.ensureInitialized()
+ if d.exp <= 0 {
+ // NOTE(vadim): must negate after casting to prevent int32 overflow
+ denom := new(big.Int).Exp(tenInt, big.NewInt(-int64(d.exp)), nil)
+ return new(big.Rat).SetFrac(d.value, denom)
+ }
+
+ mul := new(big.Int).Exp(tenInt, big.NewInt(int64(d.exp)), nil)
+ num := new(big.Int).Mul(d.value, mul)
+ return new(big.Rat).SetFrac(num, oneInt)
+}
+
+// Float64 returns the nearest float64 value for d and a bool indicating
+// whether f represents d exactly.
+// For more details, see the documentation for big.Rat.Float64
+func (d Decimal) Float64() (f float64, exact bool) {
+ return d.Rat().Float64()
+}
+
+// InexactFloat64 returns the nearest float64 value for d.
+// It doesn't indicate if the returned value represents d exactly.
+func (d Decimal) InexactFloat64() float64 {
+ f, _ := d.Float64()
+ return f
+}
+
+// String returns the string representation of the decimal
+// with the fixed point.
+//
+// Example:
+//
+// d := New(-12345, -3)
+// println(d.String())
+//
+// Output:
+//
+// -12.345
+func (d Decimal) String() string {
+ return d.string(true)
+}
+
+// StringFixed returns a rounded fixed-point string with places digits after
+// the decimal point.
+//
+// Example:
+//
+// NewFromFloat(0).StringFixed(2) // output: "0.00"
+// NewFromFloat(0).StringFixed(0) // output: "0"
+// NewFromFloat(5.45).StringFixed(0) // output: "5"
+// NewFromFloat(5.45).StringFixed(1) // output: "5.5"
+// NewFromFloat(5.45).StringFixed(2) // output: "5.45"
+// NewFromFloat(5.45).StringFixed(3) // output: "5.450"
+// NewFromFloat(545).StringFixed(-1) // output: "550"
+func (d Decimal) StringFixed(places int32) string {
+ rounded := d.Round(places)
+ return rounded.string(false)
+}
+
+// StringFixedBank returns a banker rounded fixed-point string with places digits
+// after the decimal point.
+//
+// Example:
+//
+// NewFromFloat(0).StringFixedBank(2) // output: "0.00"
+// NewFromFloat(0).StringFixedBank(0) // output: "0"
+// NewFromFloat(5.45).StringFixedBank(0) // output: "5"
+// NewFromFloat(5.45).StringFixedBank(1) // output: "5.4"
+// NewFromFloat(5.45).StringFixedBank(2) // output: "5.45"
+// NewFromFloat(5.45).StringFixedBank(3) // output: "5.450"
+// NewFromFloat(545).StringFixedBank(-1) // output: "540"
+func (d Decimal) StringFixedBank(places int32) string {
+ rounded := d.RoundBank(places)
+ return rounded.string(false)
+}
+
+// StringFixedCash returns a Swedish/Cash rounded fixed-point string. For
+// more details see the documentation at function RoundCash.
+func (d Decimal) StringFixedCash(interval uint8) string {
+ rounded := d.RoundCash(interval)
+ return rounded.string(false)
+}
+
+// Round rounds the decimal to places decimal places.
+// If places < 0, it will round the integer part to the nearest 10^(-places).
+//
+// Example:
+//
+// NewFromFloat(5.45).Round(1).String() // output: "5.5"
+// NewFromFloat(545).Round(-1).String() // output: "550"
+func (d Decimal) Round(places int32) Decimal {
+ if d.exp == -places {
+ return d
+ }
+ // truncate to places + 1
+ ret := d.rescale(-places - 1)
+
+ // add sign(d) * 0.5
+ if ret.value.Sign() < 0 {
+ ret.value.Sub(ret.value, fiveInt)
+ } else {
+ ret.value.Add(ret.value, fiveInt)
+ }
+
+ // floor for positive numbers, ceil for negative numbers
+ _, m := ret.value.DivMod(ret.value, tenInt, new(big.Int))
+ ret.exp++
+ if ret.value.Sign() < 0 && m.Cmp(zeroInt) != 0 {
+ ret.value.Add(ret.value, oneInt)
+ }
+
+ return ret
+}
+
+// RoundCeil rounds the decimal towards +infinity.
+//
+// Example:
+//
+// NewFromFloat(545).RoundCeil(-2).String() // output: "600"
+// NewFromFloat(500).RoundCeil(-2).String() // output: "500"
+// NewFromFloat(1.1001).RoundCeil(2).String() // output: "1.11"
+// NewFromFloat(-1.454).RoundCeil(1).String() // output: "-1.4"
+func (d Decimal) RoundCeil(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+
+ if d.value.Sign() > 0 {
+ rescaled.value.Add(rescaled.value, oneInt)
+ }
+
+ return rescaled
+}
+
+// RoundFloor rounds the decimal towards -infinity.
+//
+// Example:
+//
+// NewFromFloat(545).RoundFloor(-2).String() // output: "500"
+// NewFromFloat(-500).RoundFloor(-2).String() // output: "-500"
+// NewFromFloat(1.1001).RoundFloor(2).String() // output: "1.1"
+// NewFromFloat(-1.454).RoundFloor(1).String() // output: "-1.5"
+func (d Decimal) RoundFloor(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+
+ if d.value.Sign() < 0 {
+ rescaled.value.Sub(rescaled.value, oneInt)
+ }
+
+ return rescaled
+}
+
+// RoundUp rounds the decimal away from zero.
+//
+// Example:
+//
+// NewFromFloat(545).RoundUp(-2).String() // output: "600"
+// NewFromFloat(500).RoundUp(-2).String() // output: "500"
+// NewFromFloat(1.1001).RoundUp(2).String() // output: "1.11"
+// NewFromFloat(-1.454).RoundUp(1).String() // output: "-1.5"
+func (d Decimal) RoundUp(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+
+ if d.value.Sign() > 0 {
+ rescaled.value.Add(rescaled.value, oneInt)
+ } else if d.value.Sign() < 0 {
+ rescaled.value.Sub(rescaled.value, oneInt)
+ }
+
+ return rescaled
+}
+
+// RoundDown rounds the decimal towards zero.
+//
+// Example:
+//
+// NewFromFloat(545).RoundDown(-2).String() // output: "500"
+// NewFromFloat(-500).RoundDown(-2).String() // output: "-500"
+// NewFromFloat(1.1001).RoundDown(2).String() // output: "1.1"
+// NewFromFloat(-1.454).RoundDown(1).String() // output: "-1.4"
+func (d Decimal) RoundDown(places int32) Decimal {
+ if d.exp >= -places {
+ return d
+ }
+
+ rescaled := d.rescale(-places)
+ if d.Equal(rescaled) {
+ return d
+ }
+ return rescaled
+}
+
+// RoundBank rounds the decimal to places decimal places.
+// If the final digit to round is equidistant from the nearest two integers the
+// rounded value is taken as the even number
+//
+// If places < 0, it will round the integer part to the nearest 10^(-places).
+//
+// Examples:
+//
+// NewFromFloat(5.45).RoundBank(1).String() // output: "5.4"
+// NewFromFloat(545).RoundBank(-1).String() // output: "540"
+// NewFromFloat(5.46).RoundBank(1).String() // output: "5.5"
+// NewFromFloat(546).RoundBank(-1).String() // output: "550"
+// NewFromFloat(5.55).RoundBank(1).String() // output: "5.6"
+// NewFromFloat(555).RoundBank(-1).String() // output: "560"
+func (d Decimal) RoundBank(places int32) Decimal {
+
+ round := d.Round(places)
+ remainder := d.Sub(round).Abs()
+
+ half := New(5, -places-1)
+ if remainder.Cmp(half) == 0 && round.value.Bit(0) != 0 {
+ if round.value.Sign() < 0 {
+ round.value.Add(round.value, oneInt)
+ } else {
+ round.value.Sub(round.value, oneInt)
+ }
+ }
+
+ return round
+}
+
+// RoundCash aka Cash/Penny/öre rounding rounds decimal to a specific
+// interval. The amount payable for a cash transaction is rounded to the nearest
+// multiple of the minimum currency unit available. The following intervals are
+// available: 5, 10, 25, 50 and 100; any other number throws a panic.
+//
+// 5: 5 cent rounding 3.43 => 3.45
+// 10: 10 cent rounding 3.45 => 3.50 (5 gets rounded up)
+// 25: 25 cent rounding 3.41 => 3.50
+// 50: 50 cent rounding 3.75 => 4.00
+// 100: 100 cent rounding 3.50 => 4.00
+//
+// For more details: https://en.wikipedia.org/wiki/Cash_rounding
+func (d Decimal) RoundCash(interval uint8) Decimal {
+ var iVal *big.Int
+ switch interval {
+ case 5:
+ iVal = twentyInt
+ case 10:
+ iVal = tenInt
+ case 25:
+ iVal = fourInt
+ case 50:
+ iVal = twoInt
+ case 100:
+ iVal = oneInt
+ default:
+ panic(fmt.Sprintf("Decimal does not support this Cash rounding interval `%d`. Supported: 5, 10, 25, 50, 100", interval))
+ }
+ dVal := Decimal{
+ value: iVal,
+ }
+
+ // TODO: optimize those calculations to reduce the high allocations (~29 allocs).
+ return d.Mul(dVal).Round(0).Div(dVal).Truncate(2)
+}
+
+// Floor returns the nearest integer value less than or equal to d.
+func (d Decimal) Floor() Decimal {
+ d.ensureInitialized()
+
+ if d.exp >= 0 {
+ return d
+ }
+
+ exp := big.NewInt(10)
+
+ // NOTE(vadim): must negate after casting to prevent int32 overflow
+ exp.Exp(exp, big.NewInt(-int64(d.exp)), nil)
+
+ z := new(big.Int).Div(d.value, exp)
+ return Decimal{value: z, exp: 0}
+}
+
+// Ceil returns the nearest integer value greater than or equal to d.
+func (d Decimal) Ceil() Decimal {
+ d.ensureInitialized()
+
+ if d.exp >= 0 {
+ return d
+ }
+
+ exp := big.NewInt(10)
+
+ // NOTE(vadim): must negate after casting to prevent int32 overflow
+ exp.Exp(exp, big.NewInt(-int64(d.exp)), nil)
+
+ z, m := new(big.Int).DivMod(d.value, exp, new(big.Int))
+ if m.Cmp(zeroInt) != 0 {
+ z.Add(z, oneInt)
+ }
+ return Decimal{value: z, exp: 0}
+}
+
+// Truncate truncates off digits from the number, without rounding.
+//
+// NOTE: precision is the last digit that will not be truncated (must be >= 0).
+//
+// Example:
+//
+// decimal.NewFromString("123.456").Truncate(2).String() // "123.45"
+func (d Decimal) Truncate(precision int32) Decimal {
+ d.ensureInitialized()
+ if precision >= 0 && -precision > d.exp {
+ return d.rescale(-precision)
+ }
+ return d
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (d *Decimal) UnmarshalJSON(decimalBytes []byte) error {
+ if string(decimalBytes) == "null" {
+ return nil
+ }
+
+ str, err := unquoteIfQuoted(decimalBytes)
+ if err != nil {
+ return fmt.Errorf("error decoding string '%s': %s", decimalBytes, err)
+ }
+
+ decimal, err := NewFromString(str)
+ *d = decimal
+ if err != nil {
+ return fmt.Errorf("error decoding string '%s': %s", str, err)
+ }
+ return nil
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (d Decimal) MarshalJSON() ([]byte, error) {
+ var str string
+ if MarshalJSONWithoutQuotes {
+ str = d.String()
+ } else {
+ str = "\"" + d.String() + "\""
+ }
+ return []byte(str), nil
+}
+
+// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. As a string representation
+// is already used when encoding to text, this method stores that string as []byte
+func (d *Decimal) UnmarshalBinary(data []byte) error {
+ // Verify we have at least 4 bytes for the exponent. The GOB encoded value
+ // may be empty.
+ if len(data) < 4 {
+ return fmt.Errorf("error decoding binary %v: expected at least 4 bytes, got %d", data, len(data))
+ }
+
+ // Extract the exponent
+ d.exp = int32(binary.BigEndian.Uint32(data[:4]))
+
+ // Extract the value
+ d.value = new(big.Int)
+ if err := d.value.GobDecode(data[4:]); err != nil {
+ return fmt.Errorf("error decoding binary %v: %s", data, err)
+ }
+
+ return nil
+}
+
+// MarshalBinary implements the encoding.BinaryMarshaler interface.
+func (d Decimal) MarshalBinary() (data []byte, err error) {
+ // exp is written first, but encode value first to know output size
+ var valueData []byte
+ if valueData, err = d.value.GobEncode(); err != nil {
+ return nil, err
+ }
+
+ // Write the exponent in front, since it's a fixed size
+ expData := make([]byte, 4, len(valueData)+4)
+ binary.BigEndian.PutUint32(expData, uint32(d.exp))
+
+ // Return the byte array
+ return append(expData, valueData...), nil
+}
+
+// Scan implements the sql.Scanner interface for database deserialization.
+func (d *Decimal) Scan(value interface{}) error {
+ // first try to see if the data is stored in database as a Numeric datatype
+ switch v := value.(type) {
+
+ case float32:
+ *d = NewFromFloat(float64(v))
+ return nil
+
+ case float64:
+ // numeric in sqlite3 sends us float64
+ *d = NewFromFloat(v)
+ return nil
+
+ case int64:
+ // at least in sqlite3 when the value is 0 in db, the data is sent
+ // to us as an int64 instead of a float64 ...
+ *d = New(v, 0)
+ return nil
+
+ case uint64:
+ // while clickhouse may send 0 in db as uint64
+ *d = NewFromUint64(v)
+ return nil
+
+ default:
+ // default is trying to interpret value stored as string
+ str, err := unquoteIfQuoted(v)
+ if err != nil {
+ return err
+ }
+ *d, err = NewFromString(str)
+ return err
+ }
+}
+
+// Value implements the driver.Valuer interface for database serialization.
+func (d Decimal) Value() (driver.Value, error) {
+ return d.String(), nil
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface for XML
+// deserialization.
+func (d *Decimal) UnmarshalText(text []byte) error {
+ str := string(text)
+
+ dec, err := NewFromString(str)
+ *d = dec
+ if err != nil {
+ return fmt.Errorf("error decoding string '%s': %s", str, err)
+ }
+
+ return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface for XML
+// serialization.
+func (d Decimal) MarshalText() (text []byte, err error) {
+ return []byte(d.String()), nil
+}
+
+// GobEncode implements the gob.GobEncoder interface for gob serialization.
+func (d Decimal) GobEncode() ([]byte, error) {
+ return d.MarshalBinary()
+}
+
+// GobDecode implements the gob.GobDecoder interface for gob serialization.
+func (d *Decimal) GobDecode(data []byte) error {
+ return d.UnmarshalBinary(data)
+}
+
+// StringScaled first scales the decimal then calls .String() on it.
+//
+// Deprecated: buggy and unintuitive. Use StringFixed instead.
+func (d Decimal) StringScaled(exp int32) string {
+ return d.rescale(exp).String()
+}
+
+func (d Decimal) string(trimTrailingZeros bool) string {
+ if d.exp >= 0 {
+ return d.rescale(0).value.String()
+ }
+
+ abs := new(big.Int).Abs(d.value)
+ str := abs.String()
+
+ var intPart, fractionalPart string
+
+ // NOTE(vadim): this cast to int will cause bugs if d.exp == INT_MIN
+ // and you are on a 32-bit machine. Won't fix this super-edge case.
+ dExpInt := int(d.exp)
+ if len(str) > -dExpInt {
+ intPart = str[:len(str)+dExpInt]
+ fractionalPart = str[len(str)+dExpInt:]
+ } else {
+ intPart = "0"
+
+ num0s := -dExpInt - len(str)
+ fractionalPart = strings.Repeat("0", num0s) + str
+ }
+
+ if trimTrailingZeros {
+ i := len(fractionalPart) - 1
+ for ; i >= 0; i-- {
+ if fractionalPart[i] != '0' {
+ break
+ }
+ }
+ fractionalPart = fractionalPart[:i+1]
+ }
+
+ number := intPart
+ if len(fractionalPart) > 0 {
+ number += "." + fractionalPart
+ }
+
+ if d.value.Sign() < 0 {
+ return "-" + number
+ }
+
+ return number
+}
+
+func (d *Decimal) ensureInitialized() {
+ if d.value == nil {
+ d.value = new(big.Int)
+ }
+}
+
+// Min returns the smallest Decimal that was passed in the arguments.
+//
+// To call this function with an array, you must do:
+//
+// Min(arr[0], arr[1:]...)
+//
+// This makes it harder to accidentally call Min with 0 arguments.
+func Min(first Decimal, rest ...Decimal) Decimal {
+ ans := first
+ for _, item := range rest {
+ if item.Cmp(ans) < 0 {
+ ans = item
+ }
+ }
+ return ans
+}
+
+// Max returns the largest Decimal that was passed in the arguments.
+//
+// To call this function with an array, you must do:
+//
+// Max(arr[0], arr[1:]...)
+//
+// This makes it harder to accidentally call Max with 0 arguments.
+func Max(first Decimal, rest ...Decimal) Decimal {
+ ans := first
+ for _, item := range rest {
+ if item.Cmp(ans) > 0 {
+ ans = item
+ }
+ }
+ return ans
+}
+
+// Sum returns the combined total of the provided first and rest Decimals
+func Sum(first Decimal, rest ...Decimal) Decimal {
+ total := first
+ for _, item := range rest {
+ total = total.Add(item)
+ }
+
+ return total
+}
+
+// Avg returns the average value of the provided first and rest Decimals
+func Avg(first Decimal, rest ...Decimal) Decimal {
+ count := New(int64(len(rest)+1), 0)
+ sum := Sum(first, rest...)
+ return sum.Div(count)
+}
+
+// RescalePair rescales two decimals to common exponential value (minimal exp of both decimals)
+func RescalePair(d1 Decimal, d2 Decimal) (Decimal, Decimal) {
+ d1.ensureInitialized()
+ d2.ensureInitialized()
+
+ if d1.exp < d2.exp {
+ return d1, d2.rescale(d1.exp)
+ } else if d1.exp > d2.exp {
+ return d1.rescale(d2.exp), d2
+ }
+
+ return d1, d2
+}
+
+func unquoteIfQuoted(value interface{}) (string, error) {
+ var bytes []byte
+
+ switch v := value.(type) {
+ case string:
+ bytes = []byte(v)
+ case []byte:
+ bytes = v
+ default:
+ return "", fmt.Errorf("could not convert value '%+v' to byte array of type '%T'", value, value)
+ }
+
+ // If the amount is quoted, strip the quotes
+ if len(bytes) > 2 && bytes[0] == '"' && bytes[len(bytes)-1] == '"' {
+ bytes = bytes[1 : len(bytes)-1]
+ }
+ return string(bytes), nil
+}
+
+// NullDecimal represents a nullable decimal with compatibility for
+// scanning null values from the database.
+type NullDecimal struct {
+ Decimal Decimal
+ Valid bool
+}
+
+func NewNullDecimal(d Decimal) NullDecimal {
+ return NullDecimal{
+ Decimal: d,
+ Valid: true,
+ }
+}
+
+// Scan implements the sql.Scanner interface for database deserialization.
+func (d *NullDecimal) Scan(value interface{}) error {
+ if value == nil {
+ d.Valid = false
+ return nil
+ }
+ d.Valid = true
+ return d.Decimal.Scan(value)
+}
+
+// Value implements the driver.Valuer interface for database serialization.
+func (d NullDecimal) Value() (driver.Value, error) {
+ if !d.Valid {
+ return nil, nil
+ }
+ return d.Decimal.Value()
+}
+
+// UnmarshalJSON implements the json.Unmarshaler interface.
+func (d *NullDecimal) UnmarshalJSON(decimalBytes []byte) error {
+ if string(decimalBytes) == "null" {
+ d.Valid = false
+ return nil
+ }
+ d.Valid = true
+ return d.Decimal.UnmarshalJSON(decimalBytes)
+}
+
+// MarshalJSON implements the json.Marshaler interface.
+func (d NullDecimal) MarshalJSON() ([]byte, error) {
+ if !d.Valid {
+ return []byte("null"), nil
+ }
+ return d.Decimal.MarshalJSON()
+}
+
+// UnmarshalText implements the encoding.TextUnmarshaler interface for XML
+// deserialization
+func (d *NullDecimal) UnmarshalText(text []byte) error {
+ str := string(text)
+
+ // check for empty XML or XML without body e.g.,
+ if str == "" {
+ d.Valid = false
+ return nil
+ }
+ if err := d.Decimal.UnmarshalText(text); err != nil {
+ d.Valid = false
+ return err
+ }
+ d.Valid = true
+ return nil
+}
+
+// MarshalText implements the encoding.TextMarshaler interface for XML
+// serialization.
+func (d NullDecimal) MarshalText() (text []byte, err error) {
+ if !d.Valid {
+ return []byte{}, nil
+ }
+ return d.Decimal.MarshalText()
+}
+
+// Trig functions
+
+// Atan returns the arctangent, in radians, of x.
+func (d Decimal) Atan() Decimal {
+ if d.Equal(NewFromFloat(0.0)) {
+ return d
+ }
+ if d.GreaterThan(NewFromFloat(0.0)) {
+ return d.satan()
+ }
+ return d.Neg().satan().Neg()
+}
+
+func (d Decimal) xatan() Decimal {
+ P0 := NewFromFloat(-8.750608600031904122785e-01)
+ P1 := NewFromFloat(-1.615753718733365076637e+01)
+ P2 := NewFromFloat(-7.500855792314704667340e+01)
+ P3 := NewFromFloat(-1.228866684490136173410e+02)
+ P4 := NewFromFloat(-6.485021904942025371773e+01)
+ Q0 := NewFromFloat(2.485846490142306297962e+01)
+ Q1 := NewFromFloat(1.650270098316988542046e+02)
+ Q2 := NewFromFloat(4.328810604912902668951e+02)
+ Q3 := NewFromFloat(4.853903996359136964868e+02)
+ Q4 := NewFromFloat(1.945506571482613964425e+02)
+ z := d.Mul(d)
+ b1 := P0.Mul(z).Add(P1).Mul(z).Add(P2).Mul(z).Add(P3).Mul(z).Add(P4).Mul(z)
+ b2 := z.Add(Q0).Mul(z).Add(Q1).Mul(z).Add(Q2).Mul(z).Add(Q3).Mul(z).Add(Q4)
+ z = b1.Div(b2)
+ z = d.Mul(z).Add(d)
+ return z
+}
+
+// satan reduces its argument (known to be positive)
+// to the range [0, 0.66] and calls xatan.
+func (d Decimal) satan() Decimal {
+ Morebits := NewFromFloat(6.123233995736765886130e-17) // pi/2 = PIO2 + Morebits
+ Tan3pio8 := NewFromFloat(2.41421356237309504880) // tan(3*pi/8)
+ pi := NewFromFloat(3.14159265358979323846264338327950288419716939937510582097494459)
+
+ if d.LessThanOrEqual(NewFromFloat(0.66)) {
+ return d.xatan()
+ }
+ if d.GreaterThan(Tan3pio8) {
+ return pi.Div(NewFromFloat(2.0)).Sub(NewFromFloat(1.0).Div(d).xatan()).Add(Morebits)
+ }
+ return pi.Div(NewFromFloat(4.0)).Add((d.Sub(NewFromFloat(1.0)).Div(d.Add(NewFromFloat(1.0)))).xatan()).Add(NewFromFloat(0.5).Mul(Morebits))
+}
+
+// sin coefficients
+var _sin = [...]Decimal{
+ NewFromFloat(1.58962301576546568060e-10), // 0x3de5d8fd1fd19ccd
+ NewFromFloat(-2.50507477628578072866e-8), // 0xbe5ae5e5a9291f5d
+ NewFromFloat(2.75573136213857245213e-6), // 0x3ec71de3567d48a1
+ NewFromFloat(-1.98412698295895385996e-4), // 0xbf2a01a019bfdf03
+ NewFromFloat(8.33333333332211858878e-3), // 0x3f8111111110f7d0
+ NewFromFloat(-1.66666666666666307295e-1), // 0xbfc5555555555548
+}
+
+// Sin returns the sine of the radian argument x.
+func (d Decimal) Sin() Decimal {
+ PI4A := NewFromFloat(7.85398125648498535156e-1) // 0x3fe921fb40000000, Pi/4 split into three parts
+ PI4B := NewFromFloat(3.77489470793079817668e-8) // 0x3e64442d00000000,
+ PI4C := NewFromFloat(2.69515142907905952645e-15) // 0x3ce8469898cc5170,
+ M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
+
+ if d.Equal(NewFromFloat(0.0)) {
+ return d
+ }
+ // make argument positive but save the sign
+ sign := false
+ if d.LessThan(NewFromFloat(0.0)) {
+ d = d.Neg()
+ sign = true
+ }
+
+ j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
+ y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
+
+ // map zeros to origin
+ if j&1 == 1 {
+ j++
+ y = y.Add(NewFromFloat(1.0))
+ }
+ j &= 7 // octant modulo 2Pi radians (360 degrees)
+ // reflect in x axis
+ if j > 3 {
+ sign = !sign
+ j -= 4
+ }
+ z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
+ zz := z.Mul(z)
+
+ if j == 1 || j == 2 {
+ w := zz.Mul(zz).Mul(_cos[0].Mul(zz).Add(_cos[1]).Mul(zz).Add(_cos[2]).Mul(zz).Add(_cos[3]).Mul(zz).Add(_cos[4]).Mul(zz).Add(_cos[5]))
+ y = NewFromFloat(1.0).Sub(NewFromFloat(0.5).Mul(zz)).Add(w)
+ } else {
+ y = z.Add(z.Mul(zz).Mul(_sin[0].Mul(zz).Add(_sin[1]).Mul(zz).Add(_sin[2]).Mul(zz).Add(_sin[3]).Mul(zz).Add(_sin[4]).Mul(zz).Add(_sin[5])))
+ }
+ if sign {
+ y = y.Neg()
+ }
+ return y
+}
+
+// cos coefficients
+var _cos = [...]Decimal{
+ NewFromFloat(-1.13585365213876817300e-11), // 0xbda8fa49a0861a9b
+ NewFromFloat(2.08757008419747316778e-9), // 0x3e21ee9d7b4e3f05
+ NewFromFloat(-2.75573141792967388112e-7), // 0xbe927e4f7eac4bc6
+ NewFromFloat(2.48015872888517045348e-5), // 0x3efa01a019c844f5
+ NewFromFloat(-1.38888888888730564116e-3), // 0xbf56c16c16c14f91
+ NewFromFloat(4.16666666666665929218e-2), // 0x3fa555555555554b
+}
+
+// Cos returns the cosine of the radian argument x.
+func (d Decimal) Cos() Decimal {
+
+ PI4A := NewFromFloat(7.85398125648498535156e-1) // 0x3fe921fb40000000, Pi/4 split into three parts
+ PI4B := NewFromFloat(3.77489470793079817668e-8) // 0x3e64442d00000000,
+ PI4C := NewFromFloat(2.69515142907905952645e-15) // 0x3ce8469898cc5170,
+ M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
+
+ // make argument positive
+ sign := false
+ if d.LessThan(NewFromFloat(0.0)) {
+ d = d.Neg()
+ }
+
+ j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
+ y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
+
+ // map zeros to origin
+ if j&1 == 1 {
+ j++
+ y = y.Add(NewFromFloat(1.0))
+ }
+ j &= 7 // octant modulo 2Pi radians (360 degrees)
+ // reflect in x axis
+ if j > 3 {
+ sign = !sign
+ j -= 4
+ }
+ if j > 1 {
+ sign = !sign
+ }
+
+ z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
+ zz := z.Mul(z)
+
+ if j == 1 || j == 2 {
+ y = z.Add(z.Mul(zz).Mul(_sin[0].Mul(zz).Add(_sin[1]).Mul(zz).Add(_sin[2]).Mul(zz).Add(_sin[3]).Mul(zz).Add(_sin[4]).Mul(zz).Add(_sin[5])))
+ } else {
+ w := zz.Mul(zz).Mul(_cos[0].Mul(zz).Add(_cos[1]).Mul(zz).Add(_cos[2]).Mul(zz).Add(_cos[3]).Mul(zz).Add(_cos[4]).Mul(zz).Add(_cos[5]))
+ y = NewFromFloat(1.0).Sub(NewFromFloat(0.5).Mul(zz)).Add(w)
+ }
+ if sign {
+ y = y.Neg()
+ }
+ return y
+}
+
+var _tanP = [...]Decimal{
+ NewFromFloat(-1.30936939181383777646e+4), // 0xc0c992d8d24f3f38
+ NewFromFloat(1.15351664838587416140e+6), // 0x413199eca5fc9ddd
+ NewFromFloat(-1.79565251976484877988e+7), // 0xc1711fead3299176
+}
+var _tanQ = [...]Decimal{
+ NewFromFloat(1.00000000000000000000e+0),
+ NewFromFloat(1.36812963470692954678e+4), //0x40cab8a5eeb36572
+ NewFromFloat(-1.32089234440210967447e+6), //0xc13427bc582abc96
+ NewFromFloat(2.50083801823357915839e+7), //0x4177d98fc2ead8ef
+ NewFromFloat(-5.38695755929454629881e+7), //0xc189afe03cbe5a31
+}
+
+// Tan returns the tangent of the radian argument x.
+func (d Decimal) Tan() Decimal {
+
+ PI4A := NewFromFloat(7.85398125648498535156e-1) // 0x3fe921fb40000000, Pi/4 split into three parts
+ PI4B := NewFromFloat(3.77489470793079817668e-8) // 0x3e64442d00000000,
+ PI4C := NewFromFloat(2.69515142907905952645e-15) // 0x3ce8469898cc5170,
+ M4PI := NewFromFloat(1.273239544735162542821171882678754627704620361328125) // 4/pi
+
+ if d.Equal(NewFromFloat(0.0)) {
+ return d
+ }
+
+ // make argument positive but save the sign
+ sign := false
+ if d.LessThan(NewFromFloat(0.0)) {
+ d = d.Neg()
+ sign = true
+ }
+
+ j := d.Mul(M4PI).IntPart() // integer part of x/(Pi/4), as integer for tests on the phase angle
+ y := NewFromFloat(float64(j)) // integer part of x/(Pi/4), as float
+
+ // map zeros to origin
+ if j&1 == 1 {
+ j++
+ y = y.Add(NewFromFloat(1.0))
+ }
+
+ z := d.Sub(y.Mul(PI4A)).Sub(y.Mul(PI4B)).Sub(y.Mul(PI4C)) // Extended precision modular arithmetic
+ zz := z.Mul(z)
+
+ if zz.GreaterThan(NewFromFloat(1e-14)) {
+ w := zz.Mul(_tanP[0].Mul(zz).Add(_tanP[1]).Mul(zz).Add(_tanP[2]))
+ x := zz.Add(_tanQ[1]).Mul(zz).Add(_tanQ[2]).Mul(zz).Add(_tanQ[3]).Mul(zz).Add(_tanQ[4])
+ y = z.Add(z.Mul(w.Div(x)))
+ } else {
+ y = z
+ }
+ if j&2 == 2 {
+ y = NewFromFloat(-1.0).Div(y)
+ }
+ if sign {
+ y = y.Neg()
+ }
+ return y
+}
diff --git a/vendor/github.com/shopspring/decimal/rounding.go b/vendor/github.com/shopspring/decimal/rounding.go
new file mode 100644
index 0000000..d4b0cd0
--- /dev/null
+++ b/vendor/github.com/shopspring/decimal/rounding.go
@@ -0,0 +1,160 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Multiprecision decimal numbers.
+// For floating-point formatting only; not general purpose.
+// Only operations are assign and (binary) left/right shift.
+// Can do binary floating point in multiprecision decimal precisely
+// because 2 divides 10; cannot do decimal floating point
+// in multiprecision binary precisely.
+
+package decimal
+
+type floatInfo struct {
+ mantbits uint
+ expbits uint
+ bias int
+}
+
+var float32info = floatInfo{23, 8, -127}
+var float64info = floatInfo{52, 11, -1023}
+
+// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits
+// that will let the original floating point value be precisely reconstructed.
+func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) {
+ // If mantissa is zero, the number is zero; stop now.
+ if mant == 0 {
+ d.nd = 0
+ return
+ }
+
+ // Compute upper and lower such that any decimal number
+ // between upper and lower (possibly inclusive)
+ // will round to the original floating point number.
+
+ // We may see at once that the number is already shortest.
+ //
+ // Suppose d is not denormal, so that 2^exp <= d < 10^dp.
+ // The closest shorter number is at least 10^(dp-nd) away.
+ // The lower/upper bounds computed below are at distance
+ // at most 2^(exp-mantbits).
+ //
+ // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits),
+ // or equivalently log2(10)*(dp-nd) > exp-mantbits.
+ // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32).
+ minexp := flt.bias + 1 // minimum possible exponent
+ if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) {
+ // The number is already shortest.
+ return
+ }
+
+ // d = mant << (exp - mantbits)
+ // Next highest floating point number is mant+1 << exp-mantbits.
+ // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1.
+ upper := new(decimal)
+ upper.Assign(mant*2 + 1)
+ upper.Shift(exp - int(flt.mantbits) - 1)
+
+ // d = mant << (exp - mantbits)
+ // Next lowest floating point number is mant-1 << exp-mantbits,
+ // unless mant-1 drops the significant bit and exp is not the minimum exp,
+ // in which case the next lowest is mant*2-1 << exp-mantbits-1.
+ // Either way, call it mantlo << explo-mantbits.
+ // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1.
+ var mantlo uint64
+ var explo int
+ if mant > 1<= d.nd {
+ break
+ }
+ li := ui - upper.dp + lower.dp
+ l := byte('0') // lower digit
+ if li >= 0 && li < lower.nd {
+ l = lower.d[li]
+ }
+ m := byte('0') // middle digit
+ if mi >= 0 {
+ m = d.d[mi]
+ }
+ u := byte('0') // upper digit
+ if ui < upper.nd {
+ u = upper.d[ui]
+ }
+
+ // Okay to round down (truncate) if lower has a different digit
+ // or if lower is inclusive and is exactly the result of rounding
+ // down (i.e., and we have reached the final digit of lower).
+ okdown := l != m || inclusive && li+1 == lower.nd
+
+ switch {
+ case upperdelta == 0 && m+1 < u:
+ // Example:
+ // m = 12345xxx
+ // u = 12347xxx
+ upperdelta = 2
+ case upperdelta == 0 && m != u:
+ // Example:
+ // m = 12345xxx
+ // u = 12346xxx
+ upperdelta = 1
+ case upperdelta == 1 && (m != '9' || u != '0'):
+ // Example:
+ // m = 1234598x
+ // u = 1234600x
+ upperdelta = 2
+ }
+ // Okay to round up if upper has a different digit and either upper
+ // is inclusive or upper is bigger than the result of rounding up.
+ okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd)
+
+ // If it's okay to do either, then round to the nearest one.
+ // If it's okay to do only one, do it.
+ switch {
+ case okdown && okup:
+ d.Round(mi + 1)
+ return
+ case okdown:
+ d.RoundDown(mi + 1)
+ return
+ case okup:
+ d.RoundUp(mi + 1)
+ return
+ }
+ }
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index d67e4e0..465e84b 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -2,6 +2,11 @@
## explicit; go 1.20
filippo.io/edwards25519
filippo.io/edwards25519/field
+# github.com/Andrew-M-C/go.jsonvalue v1.4.1
+## explicit; go 1.13
+github.com/Andrew-M-C/go.jsonvalue
+github.com/Andrew-M-C/go.jsonvalue/internal/buffer
+github.com/Andrew-M-C/go.jsonvalue/internal/unsafe
# github.com/Esword618/unioffice v1.4.1
## explicit; go 1.12
github.com/Esword618/unioffice
@@ -76,6 +81,9 @@ github.com/lxn/win
## explicit; go 1.22
github.com/playwright-community/playwright-go
github.com/playwright-community/playwright-go/internal/safe
+# github.com/shopspring/decimal v1.4.0
+## explicit; go 1.10
+github.com/shopspring/decimal
# github.com/stretchr/testify v1.9.0
## explicit; go 1.17
# github.com/super-l/machine-code v0.0.0-20241121142923-4cb40646deba