github.com/GuanceCloud/cliutils@v1.1.21/point/key.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 package point 7 8 import ( 9 "fmt" 10 "hash/fnv" 11 "sort" 12 "strings" 13 ) 14 15 // Key is the key-name and it's type composite. 16 type Key struct { 17 key string // key-name + key-type 18 t KeyType 19 def any 20 } 21 22 // NewKey create Key. 23 func NewKey(k string, t KeyType, defaultVal ...any) *Key { 24 var def any 25 if len(defaultVal) > 0 { 26 def = defaultVal[0] 27 } 28 29 return &Key{ 30 key: k, 31 t: t, 32 def: def, 33 } 34 } 35 36 // NewTagKey create tag key with type string. 37 func NewTagKey(k string, defaultVal string) *Key { 38 return NewKey(k, S, defaultVal) 39 } 40 41 // Key get key-name. 42 func (k *Key) Key() string { 43 return k.key 44 } 45 46 // Type get key-type. 47 func (k *Key) Type() KeyType { 48 switch len(k.key) { 49 case 0: 50 return X 51 52 case 1: 53 return KeyType(k.key[0]) 54 55 default: 56 return KeyType(k.key[len(k.key)-1]) 57 } 58 } 59 60 // Default get key's default value. 61 func (k *Key) Default() any { 62 return k.def 63 } 64 65 // Keys is sorted Keys. 66 type Keys struct { 67 hashed bool 68 hash uint64 69 arr []*Key 70 } 71 72 func (x *Keys) Len() int { return len(x.arr) } 73 74 func (x *Keys) Swap(i, j int) { 75 arr := x.arr 76 arr[i], arr[j] = arr[j], arr[i] 77 } 78 79 func (x *Keys) Less(i, j int) bool { 80 return strings.Compare(x.arr[i].key, x.arr[j].key) < 0 81 } 82 83 // Has test if k exist. 84 func (x *Keys) Has(k *Key) bool { 85 // TODO: should replaced by sort.Search() 86 for _, item := range x.arr { 87 if k.key == item.key { 88 return true 89 } 90 } 91 92 return false 93 } 94 95 // Add add specific k. if key & type exist, do nothing. 96 func (x *Keys) Add(k *Key) { 97 if x.Has(k) { 98 return 99 } 100 101 x.arr = append(x.arr, k) 102 x.hashed = false 103 } 104 105 // Del remove specific k. 106 func (x *Keys) Del(k *Key) { 107 i := 0 108 for _, key := range x.arr { 109 if key.key != k.key { 110 x.arr[i] = key 111 i++ 112 } 113 } 114 115 if i != len(x.arr) { 116 x.hashed = false 117 x.arr = x.arr[:i] 118 } 119 } 120 121 // Pretty get pretty showing of all keys. 122 func (x *Keys) Pretty() string { 123 arr := []string{} 124 for _, k := range x.arr { 125 arr = append(arr, fmt.Sprintf("% 4s: %q", KeyType(k.key[len(k.key)-1]), k.key[:len(k.key)-1])) 126 } 127 128 arr = append(arr, fmt.Sprintf("-----\nhashed: %v", x.hashed)) 129 130 return strings.Join(arr, "\n") 131 } 132 133 // Hash calculate x's hash. 134 func (x *Keys) Hash() uint64 { 135 if !x.hashed { 136 sort.Sort(x) 137 h := fnv.New64a() 138 if _, err := h.Write(func() []byte { 139 var arr []byte 140 for _, k := range x.arr { 141 arr = append(arr, k.key...) 142 } 143 return arr 144 }()); err == nil { 145 x.hash = h.Sum64() 146 x.hashed = true 147 } 148 } 149 150 return x.hash 151 }