[WIP] Initial commit
This commit is contained in:
415
vendor/github.com/hjson/hjson-go/v4/node.go
generated
vendored
Normal file
415
vendor/github.com/hjson/hjson-go/v4/node.go
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
package hjson
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Comments struct {
|
||||
// Comment/whitespace on line(s) before the value, and before the value on
|
||||
// the same line. If not empty, is expected to end with a line feed +
|
||||
// indentation for the value.
|
||||
Before string
|
||||
// Comment/whitespace between the key and this value, if this value is an
|
||||
// element in a map/object.
|
||||
Key string
|
||||
// Comment/whitespace after (but still on the same line as) the leading
|
||||
// bracket ({ or [) for this value, if this value is a slice/array or
|
||||
// map/object. Is not expected to contain any line feed.
|
||||
InsideFirst string
|
||||
// Comment/whitespace from the beginning of the first line after all child
|
||||
// values belonging to this value, until the closing bracket (} or ]), if
|
||||
// this value is a slice/array or map/object. If not empty, is expected to
|
||||
// end with a line feed + indentation for the closing bracket.
|
||||
InsideLast string
|
||||
// Comment/whitespace after (but still on the same line as) the value. Is not
|
||||
// expected to contain any line feed. hjson.Unmarshal() will try to assign
|
||||
// comments/whitespace from lines between values to `Before` on the value
|
||||
// after those lines, or to `InsideLast` on the slice/map if the lines
|
||||
// containing comments appear after the last element inside a slice/map.
|
||||
After string
|
||||
}
|
||||
|
||||
// Node must be used as destination for Unmarshal() or UnmarshalWithOptions()
|
||||
// whenever comments should be read from the input. The struct is simply a
|
||||
// wrapper for the actual values and a helper struct containing any comments.
|
||||
// The Value in the destination Node will be overwritten in the call to
|
||||
// Unmarshal() or UnmarshalWithOptions(), i.e. node trees are not merged.
|
||||
// After the unmarshal, Node.Value will contain any of these types:
|
||||
//
|
||||
// nil (no type)
|
||||
// float64 (if UseJSONNumber == false)
|
||||
// json.Number (if UseJSONNumber == true)
|
||||
// string
|
||||
// bool
|
||||
// []interface{}
|
||||
// *hjson.OrderedMap
|
||||
//
|
||||
// All elements in an []interface{} or *hjson.OrderedMap will be of the type
|
||||
// *hjson.Node, so that they can contain comments.
|
||||
//
|
||||
// This example shows unmarshalling input with comments, changing the value on
|
||||
// a single key (the input is assumed to have an object/map as root) and then
|
||||
// marshalling the node tree again, including comments and with preserved key
|
||||
// order in the object/map.
|
||||
//
|
||||
// var node hjson.Node
|
||||
// err := hjson.Unmarshal(input, &node)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// _, err = node.SetKey("setting1", 3)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// output, err := hjson.Marshal(node)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
type Node struct {
|
||||
Value interface{}
|
||||
Cm Comments
|
||||
}
|
||||
|
||||
// Len returns the length of the value wrapped by this Node, if the value is of
|
||||
// type *hjson.OrderedMap, []interface{} or string. Otherwise 0 is returned.
|
||||
func (c *Node) Len() int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
return cont.Len()
|
||||
case []interface{}:
|
||||
return len(cont)
|
||||
case string:
|
||||
return len(cont)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// AtIndex returns the key (if any) and value (unwrapped from its Node) found
|
||||
// at the specified index, if this Node contains a value of type
|
||||
// *hjson.OrderedMap or []interface{}. Returns an error for unexpected types.
|
||||
// Panics if index < 0 or index >= Len().
|
||||
func (c *Node) AtIndex(index int) (string, interface{}, error) {
|
||||
if c == nil {
|
||||
return "", nil, fmt.Errorf("Node is nil")
|
||||
}
|
||||
var key string
|
||||
var elem interface{}
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
key = cont.Keys[index]
|
||||
elem = cont.Map[key]
|
||||
case []interface{}:
|
||||
elem = cont[index]
|
||||
default:
|
||||
return "", nil, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
node, ok := elem.(*Node)
|
||||
if !ok {
|
||||
return "", nil, fmt.Errorf("Unexpected element type: %v", reflect.TypeOf(elem))
|
||||
}
|
||||
return key, node.Value, nil
|
||||
}
|
||||
|
||||
// AtKey returns the value (unwrapped from its Node) found for the specified
|
||||
// key, if this Node contains a value of type *hjson.OrderedMap. An error is
|
||||
// returned for unexpected types. The second returned value is true if the key
|
||||
// was found, false otherwise.
|
||||
func (c *Node) AtKey(key string) (interface{}, bool, error) {
|
||||
if c == nil {
|
||||
return nil, false, nil
|
||||
}
|
||||
om, ok := c.Value.(*OrderedMap)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
elem, ok := om.Map[key]
|
||||
if !ok {
|
||||
return nil, false, nil
|
||||
}
|
||||
node, ok := elem.(*Node)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("Unexpected element type: %v", reflect.TypeOf(elem))
|
||||
}
|
||||
return node.Value, true, nil
|
||||
}
|
||||
|
||||
// Append adds the input value to the end of the []interface{} wrapped by this
|
||||
// Node. If this Node contains nil without a type, an empty []interface{} is
|
||||
// first created. If this Node contains a value of any other type, an error is
|
||||
// returned.
|
||||
func (c *Node) Append(value interface{}) error {
|
||||
if c == nil {
|
||||
return fmt.Errorf("Node is nil")
|
||||
}
|
||||
var arr []interface{}
|
||||
if c.Value == nil {
|
||||
arr = []interface{}{}
|
||||
} else {
|
||||
var ok bool
|
||||
arr, ok = c.Value.([]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
}
|
||||
c.Value = append(arr, &Node{Value: value})
|
||||
return nil
|
||||
}
|
||||
|
||||
// Insert inserts a new key/value pair at the specified index, if this Node
|
||||
// contains a value of type *hjson.OrderedMap or []interface{}. Returns an error
|
||||
// for unexpected types. Panics if index < 0 or index > c.Len(). If the key
|
||||
// already exists in the OrderedMap, the new value is set but the position of
|
||||
// the key is not changed. Otherwise the value to insert is wrapped in a new
|
||||
// Node. If this Node contains []interface{}, the key is ignored. Returns the
|
||||
// old value and true if the key already exists in the/ OrderedMap, nil and
|
||||
// false otherwise.
|
||||
func (c *Node) Insert(index int, key string, value interface{}) (interface{}, bool, error) {
|
||||
if c == nil {
|
||||
return nil, false, fmt.Errorf("Node is nil")
|
||||
}
|
||||
var oldVal interface{}
|
||||
var found bool
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
oldVal, found := cont.Map[key]
|
||||
if found {
|
||||
if node, ok := oldVal.(*Node); ok {
|
||||
oldVal = node.Value
|
||||
node.Value = value
|
||||
} else {
|
||||
cont.Map[key] = &Node{Value: value}
|
||||
}
|
||||
} else {
|
||||
oldVal, found = cont.Insert(index, key, &Node{Value: value})
|
||||
}
|
||||
case []interface{}:
|
||||
value = &Node{Value: value}
|
||||
if index == len(cont) {
|
||||
c.Value = append(cont, value)
|
||||
} else {
|
||||
cont = append(cont[:index+1], cont[index:]...)
|
||||
cont[index] = value
|
||||
c.Value = cont
|
||||
}
|
||||
default:
|
||||
return nil, false, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
return oldVal, found, nil
|
||||
}
|
||||
|
||||
// SetIndex assigns the specified value to the child Node found at the specified
|
||||
// index, if this Node contains a value of type *hjson.OrderedMap or
|
||||
// []interface{}. Returns an error for unexpected types. Returns the key (if
|
||||
// any) and value previously found at the specified index. Panics if index < 0
|
||||
// or index >= Len().
|
||||
func (c *Node) SetIndex(index int, value interface{}) (string, interface{}, error) {
|
||||
if c == nil {
|
||||
return "", nil, fmt.Errorf("Node is nil")
|
||||
}
|
||||
var key string
|
||||
var elem interface{}
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
key = cont.Keys[index]
|
||||
elem = cont.Map[key]
|
||||
case []interface{}:
|
||||
elem = cont[index]
|
||||
default:
|
||||
return "", nil, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
var oldVal interface{}
|
||||
node, ok := elem.(*Node)
|
||||
if ok {
|
||||
oldVal = node.Value
|
||||
node.Value = value
|
||||
} else {
|
||||
oldVal = elem
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
cont.Map[key] = &Node{Value: value}
|
||||
case []interface{}:
|
||||
cont[index] = &Node{Value: value}
|
||||
}
|
||||
}
|
||||
return key, oldVal, nil
|
||||
}
|
||||
|
||||
// SetKey assigns the specified value to the child Node identified by the
|
||||
// specified key, if this Node contains a value of the type *hjson.OrderedMap.
|
||||
// If this Node contains nil without a type, an empty *hjson.OrderedMap is
|
||||
// first created. If this Node contains a value of any other type an error is
|
||||
// returned. If the key cannot be found in the OrderedMap, a new Node is
|
||||
// created, wrapping the specified value, and appended to the end of the
|
||||
// OrderedMap. Returns the old value and true if the key already existed in
|
||||
// the OrderedMap, nil and false otherwise.
|
||||
func (c *Node) SetKey(key string, value interface{}) (interface{}, bool, error) {
|
||||
if c == nil {
|
||||
return nil, false, fmt.Errorf("Node is nil")
|
||||
}
|
||||
var om *OrderedMap
|
||||
if c.Value == nil {
|
||||
om = NewOrderedMap()
|
||||
c.Value = om
|
||||
} else {
|
||||
var ok bool
|
||||
om, ok = c.Value.(*OrderedMap)
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
}
|
||||
var oldVal interface{}
|
||||
elem, ok := om.Map[key]
|
||||
if ok {
|
||||
var node *Node
|
||||
node, ok = elem.(*Node)
|
||||
if ok {
|
||||
oldVal = node.Value
|
||||
node.Value = value
|
||||
}
|
||||
}
|
||||
foundKey := true
|
||||
if !ok {
|
||||
oldVal, foundKey = om.Set(key, &Node{Value: value})
|
||||
}
|
||||
return oldVal, foundKey, nil
|
||||
}
|
||||
|
||||
// DeleteIndex deletes the value or key/value pair found at the specified index,
|
||||
// if this Node contains a value of type *hjson.OrderedMap or []interface{}.
|
||||
// Returns an error for unexpected types. Panics if index < 0 or
|
||||
// index >= c.Len(). Returns the deleted key (if any) and value.
|
||||
func (c *Node) DeleteIndex(index int) (string, interface{}, error) {
|
||||
if c == nil {
|
||||
return "", nil, fmt.Errorf("Node is nil")
|
||||
}
|
||||
var key string
|
||||
var value interface{}
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
key, value = cont.DeleteIndex(index)
|
||||
case []interface{}:
|
||||
value = cont[index]
|
||||
cont = append(cont[:index], cont[index+1:]...)
|
||||
c.Value = cont
|
||||
default:
|
||||
return "", nil, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
if node, ok := value.(*Node); ok {
|
||||
value = node.Value
|
||||
}
|
||||
return key, value, nil
|
||||
}
|
||||
|
||||
// DeleteKey deletes the key/value pair with the specified key, if found and if
|
||||
// this Node contains a value of type *hjson.OrderedMap. Returns an error for
|
||||
// unexpected types. Returns the deleted value and true if the key was found,
|
||||
// nil and false otherwise.
|
||||
func (c *Node) DeleteKey(key string) (interface{}, bool, error) {
|
||||
if c == nil {
|
||||
return nil, false, fmt.Errorf("Node is nil")
|
||||
}
|
||||
if om, ok := c.Value.(*OrderedMap); ok {
|
||||
oldValue, found := om.DeleteKey(key)
|
||||
if node, ok := oldValue.(*Node); ok {
|
||||
oldValue = node.Value
|
||||
}
|
||||
return oldValue, found, nil
|
||||
}
|
||||
return nil, false, fmt.Errorf("Unexpected value type: %v", reflect.TypeOf(c.Value))
|
||||
}
|
||||
|
||||
// NI is an acronym formed from "get Node pointer by Index". Returns the *Node
|
||||
// element found at the specified index, if this Node contains a value of type
|
||||
// *hjson.OrderedMap or []interface{}. Returns nil otherwise. Panics if
|
||||
// index < 0 or index >= Len(). Does not create or alter any value.
|
||||
func (c *Node) NI(index int) *Node {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
var elem interface{}
|
||||
switch cont := c.Value.(type) {
|
||||
case *OrderedMap:
|
||||
elem = cont.AtIndex(index)
|
||||
case []interface{}:
|
||||
elem = cont[index]
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
if node, ok := elem.(*Node); ok {
|
||||
return node
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NK is an acronym formed from "get Node pointer by Key". Returns the *Node
|
||||
// element found for the specified key, if this Node contains a value of type
|
||||
// *hjson.OrderedMap. Returns nil otherwise. Does not create or alter anything.
|
||||
func (c *Node) NK(key string) *Node {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
om, ok := c.Value.(*OrderedMap)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if elem, ok := om.Map[key]; ok {
|
||||
if node, ok := elem.(*Node); ok {
|
||||
return node
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NKC is an acronym formed from "get Node pointer by Key, Create if not found".
|
||||
// Returns the *Node element found for the specified key, if this Node contains
|
||||
// a value of type *hjson.OrderedMap. If this Node contains nil without a type,
|
||||
// an empty *hjson.OrderedMap is first created. If this Node contains a value of
|
||||
// any other type or if the element idendified by the specified key is not of
|
||||
// type *Node, an error is returned. If the key cannot be found in the
|
||||
// OrderedMap, a new Node is created for the specified key. Example usage:
|
||||
//
|
||||
// var node hjson.Node
|
||||
// node.NKC("rootKey1").NKC("subKey1").SetKey("valKey1", "my value")
|
||||
func (c *Node) NKC(key string) *Node {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
var om *OrderedMap
|
||||
if c.Value == nil {
|
||||
om = NewOrderedMap()
|
||||
c.Value = om
|
||||
} else {
|
||||
var ok bool
|
||||
om, ok = c.Value.(*OrderedMap)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if elem, ok := om.Map[key]; ok {
|
||||
if node, ok := elem.(*Node); ok {
|
||||
return node
|
||||
}
|
||||
} else {
|
||||
node := &Node{}
|
||||
om.Set(key, node)
|
||||
return node
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON is an implementation of the json.Marshaler interface, enabling
|
||||
// hjson.Node trees to be used as input for json.Marshal().
|
||||
func (c Node) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(c.Value)
|
||||
}
|
||||
|
||||
// UnmarshalJSON is an implementation of the json.Unmarshaler interface,
|
||||
// enabling hjson.Node to be used as destination for json.Unmarshal().
|
||||
func (c *Node) UnmarshalJSON(b []byte) error {
|
||||
return Unmarshal(b, c)
|
||||
}
|
||||
Reference in New Issue
Block a user