diff --git a/go.mod b/go.mod index 96e25ca90d..d76d501de5 100644 --- a/go.mod +++ b/go.mod @@ -86,7 +86,7 @@ require ( moul.io/http2curl/v2 v2.3.0 yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230428051538-2fa935f30d76 yunion.io/x/executor v0.0.0-20211018100936-39a2cd966656 - yunion.io/x/jsonutils v1.0.1-0.20230417123225-5dcde3e4598b + yunion.io/x/jsonutils v1.0.1-0.20230428104347-7c2fdff8e8e7 yunion.io/x/log v1.0.1-0.20230411060016-feb3f46ab361 yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 yunion.io/x/pkg v1.0.1-0.20230427104242-202edd119017 diff --git a/go.sum b/go.sum index 900b3ca581..5c74d91b9c 100644 --- a/go.sum +++ b/go.sum @@ -1191,8 +1191,8 @@ yunion.io/x/executor v0.0.0-20211018100936-39a2cd966656 h1:0zlZD5uhZoIHgLVAWCz2a yunion.io/x/executor v0.0.0-20211018100936-39a2cd966656/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= yunion.io/x/jsonutils v0.0.0-20220106020632-953b71a4c3a8/go.mod h1:p0nyMqGA/apTxxyLIU/o1k4V7Vujl2O6ey30L594sYE= -yunion.io/x/jsonutils v1.0.1-0.20230417123225-5dcde3e4598b h1:lkxyU8Tl0BkA1cgM/psn6+TUWMDgNhc0B+YrVHXAKKU= -yunion.io/x/jsonutils v1.0.1-0.20230417123225-5dcde3e4598b/go.mod h1:L5QYTYqiL+f56wzir14TWHurE3Vcn9elaFiQpPWhXsg= +yunion.io/x/jsonutils v1.0.1-0.20230428104347-7c2fdff8e8e7 h1:ljrmhhK/gxwCTC2Tcqu4NdimZbozzgrRRoXpjDG2rw8= +yunion.io/x/jsonutils v1.0.1-0.20230428104347-7c2fdff8e8e7/go.mod h1:L5QYTYqiL+f56wzir14TWHurE3Vcn9elaFiQpPWhXsg= yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE= yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U= yunion.io/x/log v1.0.0/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U= diff --git a/vendor/modules.txt b/vendor/modules.txt index 5a1e32a1d2..dfed373238 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1536,7 +1536,7 @@ yunion.io/x/cloudmux/pkg/multicloud/zstack/provider yunion.io/x/executor/apis yunion.io/x/executor/client yunion.io/x/executor/server -# yunion.io/x/jsonutils v1.0.1-0.20230417123225-5dcde3e4598b +# yunion.io/x/jsonutils v1.0.1-0.20230428104347-7c2fdff8e8e7 ## explicit; go 1.12 yunion.io/x/jsonutils # yunion.io/x/log v1.0.1-0.20230411060016-feb3f46ab361 diff --git a/vendor/yunion.io/x/jsonutils/json_pointer_trace.go b/vendor/yunion.io/x/jsonutils/json_pointer_trace.go new file mode 100644 index 0000000000..465cf11777 --- /dev/null +++ b/vendor/yunion.io/x/jsonutils/json_pointer_trace.go @@ -0,0 +1,79 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package jsonutils + +import ( + "fmt" + "strings" +) + +type sJsonPointerNode struct { + pointer *sJSONPointer + inf interface{} + refcnt int +} + +func (n *sJsonPointerNode) String() string { + return fmt.Sprintf("<%d>", n.pointer.nodeId) +} + +type sJsonPointerTrace struct { + trace []*sJsonPointerNode +} + +func newJsonPointerTrace() *sJsonPointerTrace { + return &sJsonPointerTrace{ + trace: make([]*sJsonPointerNode, 0, 10), + } +} + +func (t *sJsonPointerTrace) push(inf interface{}, ptr *sJSONPointer) *sJsonPointerNode { + node := &sJsonPointerNode{ + pointer: ptr, + inf: inf, + refcnt: 1, + } + t.trace = append(t.trace, node) + // log.Debugf("push: %s", t.String()) + return node +} + +func (t *sJsonPointerTrace) find(inf interface{}) *sJsonPointerNode { + var ret *sJsonPointerNode + for i := range t.trace { + if t.trace[i].inf == inf { + ret = t.trace[i] + } + if ret != nil { + t.trace[i].refcnt++ + } + } + return ret +} + +func (t *sJsonPointerTrace) pop() { + if len(t.trace) > 0 && t.trace[len(t.trace)-1].refcnt == 1 { + t.trace = t.trace[0 : len(t.trace)-1] + } + // log.Debugf("pop: %s", t.String()) +} + +func (t *sJsonPointerTrace) String() string { + buf := &strings.Builder{} + for i := range t.trace { + buf.WriteString(t.trace[i].String()) + } + return buf.String() +} diff --git a/vendor/yunion.io/x/jsonutils/jsonpointer.go b/vendor/yunion.io/x/jsonutils/jsonpointer.go index b8f3ff0ab9..b525c7c257 100644 --- a/vendor/yunion.io/x/jsonutils/jsonpointer.go +++ b/vendor/yunion.io/x/jsonutils/jsonpointer.go @@ -18,6 +18,7 @@ import ( "fmt" "reflect" "strings" + "time" ) const ( @@ -25,42 +26,32 @@ const ( ) type sJSONPointer struct { - JSONValue + node JSONObject nodeId int } +var _ JSONObject = (*sJSONPointer)(nil) + func (s *sJsonMarshalSession) newJsonPointer(inf interface{}) *sJSONPointer { s.nodeIndex++ jsonPtr := &sJSONPointer{ nodeId: s.nodeIndex, } - s.objectMap[inf] = jsonPtr - s.nodeMap[jsonPtr.nodeId] = &sJsonPointerRefCount{refCnt: 1} + s.nodeMap[s.nodeIndex] = s.objectTrace.push(inf, jsonPtr) return jsonPtr } func (s *sJsonMarshalSession) setJsonObject(ptr *sJSONPointer, obj JSONObject) { - if jsonDict, ok := obj.(*JSONDict); ok { - if jr, ok := s.nodeMap[ptr.nodeId]; ok { - jr.node = jsonDict - } else { - panic(fmt.Sprintf("nodeId %d should exists!", ptr.nodeId)) - } - } -} - -func (s *sJsonMarshalSession) addPointerReferer(ptr *sJSONPointer) { - if jr, ok := s.nodeMap[ptr.nodeId]; ok { - jr.refCnt++ - } else { - panic(fmt.Sprintf("fail to find nodeId %d???", ptr.nodeId)) + if _, ok := obj.(*JSONDict); ok { + ptr.node = obj } + s.objectTrace.pop() } func (s *sJsonMarshalSession) setAllNodeId() { - for nodeId, refer := range s.nodeMap { - if refer.node != nil && refer.refCnt > 1 { - refer.node.setNodeId(nodeId) + for nodeId, jsonPtrNode := range s.nodeMap { + if jsonPtrNode.refcnt > 1 && jsonPtrNode.pointer.node != nil { + jsonPtrNode.pointer.node.(*JSONDict).setNodeId(nodeId) } } } @@ -84,3 +75,102 @@ func (dict *JSONDict) setNodeId(nodeId int) { func (ptr *sJSONPointer) unmarshalValue(s *sJsonUnmarshalSession, val reflect.Value) error { return s.setPointerValue(ptr.nodeId, val) } + +func (ptr *sJSONPointer) IsZero() bool { + if ptr.node != nil { + return ptr.node.IsZero() + } + return true +} + +func (ptr *sJSONPointer) parse(s *sJsonParseSession, str []byte, offset int) (int, error) { + // null ops + return -1, nil +} + +func (ptr *sJSONPointer) prettyString(level int) string { + return jsonPrettyString(ptr, level) +} + +func (ptr *sJSONPointer) YAMLString() string { + return ptr.String() +} + +func (ptr *sJSONPointer) QueryString() string { + return "" +} + +func (ptr *sJSONPointer) _queryString(key string) string { + return "" +} + +func (ptr *sJSONPointer) getNode() JSONObject { + if ptr.node != nil { + return ptr.node + } + return JSONNull +} + +func (ptr *sJSONPointer) Contains(keys ...string) bool { + return ptr.getNode().Contains(keys...) +} + +func (ptr *sJSONPointer) ContainsIgnoreCases(keys ...string) bool { + return ptr.getNode().ContainsIgnoreCases(keys...) +} + +func (ptr *sJSONPointer) Get(keys ...string) (JSONObject, error) { + return ptr.getNode().Get(keys...) +} + +func (ptr *sJSONPointer) GetIgnoreCases(keys ...string) (JSONObject, error) { + return ptr.getNode().GetIgnoreCases(keys...) +} + +func (ptr *sJSONPointer) GetAt(i int, keys ...string) (JSONObject, error) { + return ptr.getNode().GetAt(i, keys...) +} + +func (ptr *sJSONPointer) Int(keys ...string) (int64, error) { + return ptr.getNode().Int(keys...) +} + +func (ptr *sJSONPointer) Float(keys ...string) (float64, error) { + return ptr.getNode().Float(keys...) +} + +func (ptr *sJSONPointer) Bool(keys ...string) (bool, error) { + return ptr.getNode().Bool(keys...) +} + +func (ptr *sJSONPointer) GetMap(keys ...string) (map[string]JSONObject, error) { + return ptr.getNode().GetMap(keys...) +} + +func (ptr *sJSONPointer) GetArray(keys ...string) ([]JSONObject, error) { + return ptr.getNode().GetArray(keys...) +} + +func (ptr *sJSONPointer) GetTime(keys ...string) (time.Time, error) { + return ptr.getNode().GetTime(keys...) +} + +func (ptr *sJSONPointer) GetString(keys ...string) (string, error) { + return ptr.getNode().GetString(keys...) +} + +func (ptr *sJSONPointer) Unmarshal(obj interface{}, keys ...string) error { + return ptr.getNode().Unmarshal(obj, keys...) +} + +func (ptr *sJSONPointer) Equals(obj JSONObject) bool { + return ptr.getNode().Equals(obj) +} + +func (ptr *sJSONPointer) Interface() interface{} { + return ptr.getNode().Interface() +} + +func (ptr *sJSONPointer) isCompond() bool { + return ptr.getNode().isCompond() +} diff --git a/vendor/yunion.io/x/jsonutils/marshal.go b/vendor/yunion.io/x/jsonutils/marshal.go index c8d5151539..12d6c1e508 100644 --- a/vendor/yunion.io/x/jsonutils/marshal.go +++ b/vendor/yunion.io/x/jsonutils/marshal.go @@ -252,7 +252,6 @@ func Marshal(obj interface{}) JSONObject { return JSONNull } s := newJsonMarshalSession() - // objValue := reflect.Indirect(val) mval := s.marshalValue(val, nil, true) s.setAllNodeId() if mval == nil { @@ -272,15 +271,16 @@ func (s *sJsonMarshalSession) marshalValueWithObjectMap(objValue reflect.Value, if objValue.Kind() == reflect.Ptr { inf := objValue.Interface() if !gotypes.IsNil(inf) { - if jsonPtr, ok := s.objectMap[inf]; ok { - s.addPointerReferer(jsonPtr) - return jsonPtr + jsonPtrNode := s.objectTrace.find(inf) + if jsonPtrNode != nil { + // loop detected! + return jsonPtrNode.pointer } jsonPtr = s.newJsonPointer(inf) } } jsonObj := s._marshalValue(objValue, info, omitEmpty) - if jsonPtr != nil && jsonObj != nil { + if jsonPtr != nil { s.setJsonObject(jsonPtr, jsonObj) } return jsonObj diff --git a/vendor/yunion.io/x/jsonutils/marshal_session.go b/vendor/yunion.io/x/jsonutils/marshal_session.go index 424672cfc4..7c1f869c4f 100644 --- a/vendor/yunion.io/x/jsonutils/marshal_session.go +++ b/vendor/yunion.io/x/jsonutils/marshal_session.go @@ -14,22 +14,16 @@ package jsonutils -type sJsonPointerRefCount struct { - node *JSONDict - refCnt int -} - type sJsonMarshalSession struct { - nodeIndex int - objectMap map[interface{}]*sJSONPointer - - nodeMap map[int]*sJsonPointerRefCount + nodeIndex int + objectTrace *sJsonPointerTrace + nodeMap map[int]*sJsonPointerNode } func newJsonMarshalSession() *sJsonMarshalSession { return &sJsonMarshalSession{ - nodeIndex: 0, - objectMap: make(map[interface{}]*sJSONPointer), - nodeMap: make(map[int]*sJsonPointerRefCount), + nodeIndex: 0, + objectTrace: newJsonPointerTrace(), + nodeMap: make(map[int]*sJsonPointerNode), } }