From eb26d597c6d526f84077afdc141b0a5d585c7da3 Mon Sep 17 00:00:00 2001 From: NeonXP Date: Wed, 16 Nov 2022 21:35:48 +0300 Subject: [PATCH] Utility methods --- README.md | 15 +++++++++++++ model/array.go | 10 +++++++++ model/condition.go | 55 ++++++++++++++++++++++++++++++++++++++++++++++ model/map.go | 9 ++++++++ model/node.go | 30 +++++++++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 model/condition.go diff --git a/README.md b/README.md index fb99e4b..72d4d2b 100644 --- a/README.md +++ b/README.md @@ -62,4 +62,19 @@ func (n *Node) Value() any // MarshalJSON to []byte func (n *Node) MarshalJSON() ([]byte, error) + +// Merge two object or array nodes +func (n *Node) Merge(node *Node) error + +// Len returns length of object or array nodes +func (n *Node) Len() (int, error) + +// Compare current node with another node +func (n *Node) Compare(op Operand, node *Node) bool + +// Remove by key from object +func (n *Node) Remove(key string) error + +// RemoveIndex from array +func (n *Node) RemoveIndex(idx int) error ``` diff --git a/model/array.go b/model/array.go index b3d2586..5d64209 100644 --- a/model/array.go +++ b/model/array.go @@ -30,3 +30,13 @@ func (n *Node) Each(cb func(idx int, value *Node) error) error { } return nil } + +// RemoveIndex from array +func (n *Node) RemoveIndex(idx int) error { + arrlen := len(n.arrayValue) + if idx >= arrlen { + return fmt.Errorf("index %d out of range (len=%d)", idx, arrlen) + } + n.arrayValue = append(n.arrayValue[:idx], n.arrayValue[idx:]...) + return nil +} diff --git a/model/condition.go b/model/condition.go new file mode 100644 index 0000000..0b558b4 --- /dev/null +++ b/model/condition.go @@ -0,0 +1,55 @@ +package model + +// Compare current node with another node +func (n *Node) Compare(op Operand, node *Node) bool { + switch op { + case OpEq: + return n.Value() == node.Value() + case OpNeq: + return n.Value() != node.Value() + case OpLess: + return less(n, node) + case OpGt: + return less(node, n) + case OpLessEq: + return less(n, node) || n.Value() == node.Value() + case OpGtEq: + return less(node, n) || n.Value() == node.Value() + case OpIn: + if n.Type != ArrayNode { + return false + } + for _, v := range n.arrayValue { + if v.Value() == node.Value() { + return true + } + } + } + return false +} + +func less(n1 *Node, n2 *Node) bool { + if n1.Type != n2.Type { + return false + } + switch n1.Type { + case NumberNode: + return n1.numberValue < n2.numberValue + case StringNode: + return n1.stringValue < n2.stringValue + default: + return false + } +} + +type Operand int + +const ( + OpEq Operand = iota + OpNeq + OpLess + OpLessEq + OpGt + OpGtEq + OpIn +) diff --git a/model/map.go b/model/map.go index 59ba2d8..7bfdaa3 100644 --- a/model/map.go +++ b/model/map.go @@ -41,3 +41,12 @@ func (n *Node) Map(cb func(key string, value *Node) (*Node, error)) error { } return nil } + +// Remove by key from object +func (n *Node) Remove(key string) error { + if n.Type != ObjectNode { + return fmt.Errorf("node must be object, got %s", n.Type) + } + delete(n.objectValue, key) + return nil +} diff --git a/model/node.go b/model/node.go index 1483eaf..fea8fcd 100644 --- a/model/node.go +++ b/model/node.go @@ -113,3 +113,33 @@ func (n *Node) MarshalJSON() ([]byte, error) { return []byte("null"), nil } } + +// Merge two object or array nodes +func (n *Node) Merge(node *Node) error { + if n.Type != node.Type { + return fmt.Errorf("can't merge nodes of different types") + } + switch n.Type { + case ObjectNode: + for k, v := range node.objectValue { + n.objectValue[k] = v + } + case ArrayNode: + n.arrayValue = append(n.arrayValue, node.arrayValue...) + default: + return fmt.Errorf("merge not implemented for type %s", n.Type) + } + return nil +} + +// Len returns length of object or array nodes +func (n *Node) Len() (int, error) { + switch n.Type { + case ObjectNode: + return len(n.objectValue), nil + case ArrayNode: + return len(n.arrayValue), nil + default: + return 0, fmt.Errorf("merge not implemented for type %s", n.Type) + } +}