1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
package hjson
import (
"bytes"
"encoding/json"
)
// OrderedMap wraps a map and a slice containing all of the keys from the map,
// so that the order of the keys can be specified. The Keys slice can be sorted
// or rearranged like any other slice, but do not add or remove keys manually
// on it. Use OrderedMap.Insert(), OrderedMap.Set(), OrderedMap.DeleteIndex() or
// OrderedMap.DeleteKey() instead.
//
// Example of how to iterate through the elements of an OrderedMap in order:
//
// for _, key := range om.Keys {
// fmt.Printf("%v\n", om.Map[key])
// }
//
// Always use the functions Insert() or Set() instead of setting values
// directly on OrderedMap.Map, because any new keys must also be added to
// OrderedMap.Keys. Otherwise those keys will be ignored when iterating through
// the elements of the OrderedMap in order, as for example happens in the
// function hjson.Marshal().
type OrderedMap struct {
Keys []string
Map map[string]interface{}
}
// KeyValue is only used as input to NewOrderedMapFromSlice().
type KeyValue struct {
Key string
Value interface{}
}
// NewOrderedMap returns a pointer to a new OrderedMap. An OrderedMap should
// always be passed by reference, never by value. If an OrderedMap is passed
// by value then appending new keys won't affect all of the copies of the
// OrderedMap.
func NewOrderedMap() *OrderedMap {
return &OrderedMap{
Keys: nil,
Map: map[string]interface{}{},
}
}
// NewOrderedMapFromSlice is like NewOrderedMap but with initial values.
// Example:
//
// om := NewOrderedMapFromSlice([]KeyValue{
// {"B", "first"},
// {"A", "second"},
// })
func NewOrderedMapFromSlice(args []KeyValue) *OrderedMap {
c := NewOrderedMap()
for _, elem := range args {
c.Set(elem.Key, elem.Value)
}
return c
}
// Len returns the number of values contained in the OrderedMap.
func (c *OrderedMap) Len() int {
return len(c.Keys)
}
// AtIndex returns the value found at the specified index. Panics if
// index < 0 or index >= c.Len().
func (c *OrderedMap) AtIndex(index int) interface{} {
return c.Map[c.Keys[index]]
}
// AtKey returns the value found for the specified key, and true if the value
// was found. Returns nil and false if the value was not found.
func (c *OrderedMap) AtKey(key string) (interface{}, bool) {
ret, ok := c.Map[key]
return ret, ok
}
// Insert inserts a new key/value pair at the specified index. 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. Returns
// the old value and true if the key already exists in the OrderedMap, nil and
// false otherwise.
func (c *OrderedMap) Insert(index int, key string, value interface{}) (interface{}, bool) {
oldValue, exists := c.Map[key]
c.Map[key] = value
if exists {
return oldValue, true
}
if index == len(c.Keys) {
c.Keys = append(c.Keys, key)
} else {
c.Keys = append(c.Keys[:index+1], c.Keys[index:]...)
c.Keys[index] = key
}
return nil, false
}
// Set sets the specified value for the specified key. If the key does not
// already exist in the OrderedMap it is appended to the end of the OrderedMap.
// If the key already exists in the OrderedMap, the new value is set but the
// position of the key is not changed. Returns the old value and true if the
// key already exists in the OrderedMap, nil and false otherwise.
func (c *OrderedMap) Set(key string, value interface{}) (interface{}, bool) {
return c.Insert(len(c.Keys), key, value)
}
// DeleteIndex deletes the key/value pair found at the specified index.
// Returns the deleted key and value. Panics if index < 0 or index >= c.Len().
func (c *OrderedMap) DeleteIndex(index int) (string, interface{}) {
key := c.Keys[index]
value := c.Map[key]
delete(c.Map, key)
c.Keys = append(c.Keys[:index], c.Keys[index+1:]...)
return key, value
}
// DeleteKey deletes the key/value pair with the specified key, if found.
// Returns the deleted value and true if the key was found, nil and false
// otherwise.
func (c *OrderedMap) DeleteKey(key string) (interface{}, bool) {
for index, ck := range c.Keys {
if ck == key {
_, value := c.DeleteIndex(index)
return value, true
}
}
return nil, false
}
// MarshalJSON is an implementation of the json.Marshaler interface, enabling
// hjson.OrderedMap to be used as input for json.Marshal().
func (c *OrderedMap) MarshalJSON() ([]byte, error) {
var b bytes.Buffer
b.WriteString("{")
for index, key := range c.Keys {
if index > 0 {
b.WriteString(",")
}
jbuf, err := json.Marshal(key)
if err != nil {
return nil, err
}
b.Write(jbuf)
b.WriteString(":")
jbuf, err = json.Marshal(c.Map[key])
if err != nil {
return nil, err
}
b.Write(jbuf)
}
b.WriteString("}")
return b.Bytes(), nil
}
// UnmarshalJSON is an implementation of the json.Unmarshaler interface,
// enabling hjson.OrderedMap to be used as destination for json.Unmarshal().
func (c *OrderedMap) UnmarshalJSON(b []byte) error {
c.Keys = nil
c.Map = map[string]interface{}{}
return Unmarshal(b, c)
}
|