github.com/gogf/gf@v1.16.9/container/gmap/gmap_hash_int_any_map.go (about) 1 // Copyright GoFrame Author(https://goframe.org). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with gm file, 5 // You can obtain one at https://github.com/gogf/gf. 6 // 7 8 package gmap 9 10 import ( 11 "github.com/gogf/gf/internal/json" 12 13 "github.com/gogf/gf/internal/empty" 14 15 "github.com/gogf/gf/container/gvar" 16 "github.com/gogf/gf/internal/rwmutex" 17 "github.com/gogf/gf/util/gconv" 18 ) 19 20 type IntAnyMap struct { 21 mu rwmutex.RWMutex 22 data map[int]interface{} 23 } 24 25 // NewIntAnyMap returns an empty IntAnyMap object. 26 // The parameter <safe> is used to specify whether using map in concurrent-safety, 27 // which is false in default. 28 func NewIntAnyMap(safe ...bool) *IntAnyMap { 29 return &IntAnyMap{ 30 mu: rwmutex.Create(safe...), 31 data: make(map[int]interface{}), 32 } 33 } 34 35 // NewIntAnyMapFrom creates and returns a hash map from given map <data>. 36 // Note that, the param <data> map will be set as the underlying data map(no deep copy), 37 // there might be some concurrent-safe issues when changing the map outside. 38 func NewIntAnyMapFrom(data map[int]interface{}, safe ...bool) *IntAnyMap { 39 return &IntAnyMap{ 40 mu: rwmutex.Create(safe...), 41 data: data, 42 } 43 } 44 45 // Iterator iterates the hash map readonly with custom callback function <f>. 46 // If <f> returns true, then it continues iterating; or false to stop. 47 func (m *IntAnyMap) Iterator(f func(k int, v interface{}) bool) { 48 m.mu.RLock() 49 defer m.mu.RUnlock() 50 for k, v := range m.data { 51 if !f(k, v) { 52 break 53 } 54 } 55 } 56 57 // Clone returns a new hash map with copy of current map data. 58 func (m *IntAnyMap) Clone() *IntAnyMap { 59 return NewIntAnyMapFrom(m.MapCopy(), m.mu.IsSafe()) 60 } 61 62 // Map returns the underlying data map. 63 // Note that, if it's in concurrent-safe usage, it returns a copy of underlying data, 64 // or else a pointer to the underlying data. 65 func (m *IntAnyMap) Map() map[int]interface{} { 66 m.mu.RLock() 67 defer m.mu.RUnlock() 68 if !m.mu.IsSafe() { 69 return m.data 70 } 71 data := make(map[int]interface{}, len(m.data)) 72 for k, v := range m.data { 73 data[k] = v 74 } 75 return data 76 } 77 78 // MapStrAny returns a copy of the underlying data of the map as map[string]interface{}. 79 func (m *IntAnyMap) MapStrAny() map[string]interface{} { 80 m.mu.RLock() 81 data := make(map[string]interface{}, len(m.data)) 82 for k, v := range m.data { 83 data[gconv.String(k)] = v 84 } 85 m.mu.RUnlock() 86 return data 87 } 88 89 // MapCopy returns a copy of the underlying data of the hash map. 90 func (m *IntAnyMap) MapCopy() map[int]interface{} { 91 m.mu.RLock() 92 defer m.mu.RUnlock() 93 data := make(map[int]interface{}, len(m.data)) 94 for k, v := range m.data { 95 data[k] = v 96 } 97 return data 98 } 99 100 // FilterEmpty deletes all key-value pair of which the value is empty. 101 // Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty. 102 func (m *IntAnyMap) FilterEmpty() { 103 m.mu.Lock() 104 for k, v := range m.data { 105 if empty.IsEmpty(v) { 106 delete(m.data, k) 107 } 108 } 109 m.mu.Unlock() 110 } 111 112 // FilterNil deletes all key-value pair of which the value is nil. 113 func (m *IntAnyMap) FilterNil() { 114 m.mu.Lock() 115 defer m.mu.Unlock() 116 for k, v := range m.data { 117 if empty.IsNil(v) { 118 delete(m.data, k) 119 } 120 } 121 } 122 123 // Set sets key-value to the hash map. 124 func (m *IntAnyMap) Set(key int, val interface{}) { 125 m.mu.Lock() 126 if m.data == nil { 127 m.data = make(map[int]interface{}) 128 } 129 m.data[key] = val 130 m.mu.Unlock() 131 } 132 133 // Sets batch sets key-values to the hash map. 134 func (m *IntAnyMap) Sets(data map[int]interface{}) { 135 m.mu.Lock() 136 if m.data == nil { 137 m.data = data 138 } else { 139 for k, v := range data { 140 m.data[k] = v 141 } 142 } 143 m.mu.Unlock() 144 } 145 146 // Search searches the map with given <key>. 147 // Second return parameter <found> is true if key was found, otherwise false. 148 func (m *IntAnyMap) Search(key int) (value interface{}, found bool) { 149 m.mu.RLock() 150 if m.data != nil { 151 value, found = m.data[key] 152 } 153 m.mu.RUnlock() 154 return 155 } 156 157 // Get returns the value by given <key>. 158 func (m *IntAnyMap) Get(key int) (value interface{}) { 159 m.mu.RLock() 160 if m.data != nil { 161 value, _ = m.data[key] 162 } 163 m.mu.RUnlock() 164 return 165 } 166 167 // Pop retrieves and deletes an item from the map. 168 func (m *IntAnyMap) Pop() (key int, value interface{}) { 169 m.mu.Lock() 170 defer m.mu.Unlock() 171 for key, value = range m.data { 172 delete(m.data, key) 173 return 174 } 175 return 176 } 177 178 // Pops retrieves and deletes <size> items from the map. 179 // It returns all items if size == -1. 180 func (m *IntAnyMap) Pops(size int) map[int]interface{} { 181 m.mu.Lock() 182 defer m.mu.Unlock() 183 if size > len(m.data) || size == -1 { 184 size = len(m.data) 185 } 186 if size == 0 { 187 return nil 188 } 189 var ( 190 index = 0 191 newMap = make(map[int]interface{}, size) 192 ) 193 for k, v := range m.data { 194 delete(m.data, k) 195 newMap[k] = v 196 index++ 197 if index == size { 198 break 199 } 200 } 201 return newMap 202 } 203 204 // doSetWithLockCheck checks whether value of the key exists with mutex.Lock, 205 // if not exists, set value to the map with given <key>, 206 // or else just return the existing value. 207 // 208 // When setting value, if <value> is type of <func() interface {}>, 209 // it will be executed with mutex.Lock of the hash map, 210 // and its return value will be set to the map with <key>. 211 // 212 // It returns value with given <key>. 213 func (m *IntAnyMap) doSetWithLockCheck(key int, value interface{}) interface{} { 214 m.mu.Lock() 215 defer m.mu.Unlock() 216 if m.data == nil { 217 m.data = make(map[int]interface{}) 218 } 219 if v, ok := m.data[key]; ok { 220 return v 221 } 222 if f, ok := value.(func() interface{}); ok { 223 value = f() 224 } 225 if value != nil { 226 m.data[key] = value 227 } 228 return value 229 } 230 231 // GetOrSet returns the value by key, 232 // or sets value with given <value> if it does not exist and then returns this value. 233 func (m *IntAnyMap) GetOrSet(key int, value interface{}) interface{} { 234 if v, ok := m.Search(key); !ok { 235 return m.doSetWithLockCheck(key, value) 236 } else { 237 return v 238 } 239 } 240 241 // GetOrSetFunc returns the value by key, 242 // or sets value with returned value of callback function <f> if it does not exist and returns this value. 243 func (m *IntAnyMap) GetOrSetFunc(key int, f func() interface{}) interface{} { 244 if v, ok := m.Search(key); !ok { 245 return m.doSetWithLockCheck(key, f()) 246 } else { 247 return v 248 } 249 } 250 251 // GetOrSetFuncLock returns the value by key, 252 // or sets value with returned value of callback function <f> if it does not exist and returns this value. 253 // 254 // GetOrSetFuncLock differs with GetOrSetFunc function is that it executes function <f> 255 // with mutex.Lock of the hash map. 256 func (m *IntAnyMap) GetOrSetFuncLock(key int, f func() interface{}) interface{} { 257 if v, ok := m.Search(key); !ok { 258 return m.doSetWithLockCheck(key, f) 259 } else { 260 return v 261 } 262 } 263 264 // GetVar returns a Var with the value by given <key>. 265 // The returned Var is un-concurrent safe. 266 func (m *IntAnyMap) GetVar(key int) *gvar.Var { 267 return gvar.New(m.Get(key)) 268 } 269 270 // GetVarOrSet returns a Var with result from GetVarOrSet. 271 // The returned Var is un-concurrent safe. 272 func (m *IntAnyMap) GetVarOrSet(key int, value interface{}) *gvar.Var { 273 return gvar.New(m.GetOrSet(key, value)) 274 } 275 276 // GetVarOrSetFunc returns a Var with result from GetOrSetFunc. 277 // The returned Var is un-concurrent safe. 278 func (m *IntAnyMap) GetVarOrSetFunc(key int, f func() interface{}) *gvar.Var { 279 return gvar.New(m.GetOrSetFunc(key, f)) 280 } 281 282 // GetVarOrSetFuncLock returns a Var with result from GetOrSetFuncLock. 283 // The returned Var is un-concurrent safe. 284 func (m *IntAnyMap) GetVarOrSetFuncLock(key int, f func() interface{}) *gvar.Var { 285 return gvar.New(m.GetOrSetFuncLock(key, f)) 286 } 287 288 // SetIfNotExist sets <value> to the map if the <key> does not exist, and then returns true. 289 // It returns false if <key> exists, and <value> would be ignored. 290 func (m *IntAnyMap) SetIfNotExist(key int, value interface{}) bool { 291 if !m.Contains(key) { 292 m.doSetWithLockCheck(key, value) 293 return true 294 } 295 return false 296 } 297 298 // SetIfNotExistFunc sets value with return value of callback function <f>, and then returns true. 299 // It returns false if <key> exists, and <value> would be ignored. 300 func (m *IntAnyMap) SetIfNotExistFunc(key int, f func() interface{}) bool { 301 if !m.Contains(key) { 302 m.doSetWithLockCheck(key, f()) 303 return true 304 } 305 return false 306 } 307 308 // SetIfNotExistFuncLock sets value with return value of callback function <f>, and then returns true. 309 // It returns false if <key> exists, and <value> would be ignored. 310 // 311 // SetIfNotExistFuncLock differs with SetIfNotExistFunc function is that 312 // it executes function <f> with mutex.Lock of the hash map. 313 func (m *IntAnyMap) SetIfNotExistFuncLock(key int, f func() interface{}) bool { 314 if !m.Contains(key) { 315 m.doSetWithLockCheck(key, f) 316 return true 317 } 318 return false 319 } 320 321 // Removes batch deletes values of the map by keys. 322 func (m *IntAnyMap) Removes(keys []int) { 323 m.mu.Lock() 324 if m.data != nil { 325 for _, key := range keys { 326 delete(m.data, key) 327 } 328 } 329 m.mu.Unlock() 330 } 331 332 // Remove deletes value from map by given <key>, and return this deleted value. 333 func (m *IntAnyMap) Remove(key int) (value interface{}) { 334 m.mu.Lock() 335 if m.data != nil { 336 var ok bool 337 if value, ok = m.data[key]; ok { 338 delete(m.data, key) 339 } 340 } 341 m.mu.Unlock() 342 return 343 } 344 345 // Keys returns all keys of the map as a slice. 346 func (m *IntAnyMap) Keys() []int { 347 m.mu.RLock() 348 var ( 349 keys = make([]int, len(m.data)) 350 index = 0 351 ) 352 for key := range m.data { 353 keys[index] = key 354 index++ 355 } 356 m.mu.RUnlock() 357 return keys 358 } 359 360 // Values returns all values of the map as a slice. 361 func (m *IntAnyMap) Values() []interface{} { 362 m.mu.RLock() 363 var ( 364 values = make([]interface{}, len(m.data)) 365 index = 0 366 ) 367 for _, value := range m.data { 368 values[index] = value 369 index++ 370 } 371 m.mu.RUnlock() 372 return values 373 } 374 375 // Contains checks whether a key exists. 376 // It returns true if the <key> exists, or else false. 377 func (m *IntAnyMap) Contains(key int) bool { 378 var ok bool 379 m.mu.RLock() 380 if m.data != nil { 381 _, ok = m.data[key] 382 } 383 m.mu.RUnlock() 384 return ok 385 } 386 387 // Size returns the size of the map. 388 func (m *IntAnyMap) Size() int { 389 m.mu.RLock() 390 length := len(m.data) 391 m.mu.RUnlock() 392 return length 393 } 394 395 // IsEmpty checks whether the map is empty. 396 // It returns true if map is empty, or else false. 397 func (m *IntAnyMap) IsEmpty() bool { 398 return m.Size() == 0 399 } 400 401 // Clear deletes all data of the map, it will remake a new underlying data map. 402 func (m *IntAnyMap) Clear() { 403 m.mu.Lock() 404 m.data = make(map[int]interface{}) 405 m.mu.Unlock() 406 } 407 408 // Replace the data of the map with given <data>. 409 func (m *IntAnyMap) Replace(data map[int]interface{}) { 410 m.mu.Lock() 411 m.data = data 412 m.mu.Unlock() 413 } 414 415 // LockFunc locks writing with given callback function <f> within RWMutex.Lock. 416 func (m *IntAnyMap) LockFunc(f func(m map[int]interface{})) { 417 m.mu.Lock() 418 defer m.mu.Unlock() 419 f(m.data) 420 } 421 422 // RLockFunc locks reading with given callback function <f> within RWMutex.RLock. 423 func (m *IntAnyMap) RLockFunc(f func(m map[int]interface{})) { 424 m.mu.RLock() 425 defer m.mu.RUnlock() 426 f(m.data) 427 } 428 429 // Flip exchanges key-value of the map to value-key. 430 func (m *IntAnyMap) Flip() { 431 m.mu.Lock() 432 defer m.mu.Unlock() 433 n := make(map[int]interface{}, len(m.data)) 434 for k, v := range m.data { 435 n[gconv.Int(v)] = k 436 } 437 m.data = n 438 } 439 440 // Merge merges two hash maps. 441 // The <other> map will be merged into the map <m>. 442 func (m *IntAnyMap) Merge(other *IntAnyMap) { 443 m.mu.Lock() 444 defer m.mu.Unlock() 445 if m.data == nil { 446 m.data = other.MapCopy() 447 return 448 } 449 if other != m { 450 other.mu.RLock() 451 defer other.mu.RUnlock() 452 } 453 for k, v := range other.data { 454 m.data[k] = v 455 } 456 } 457 458 // String returns the map as a string. 459 func (m *IntAnyMap) String() string { 460 b, _ := m.MarshalJSON() 461 return string(b) 462 } 463 464 // MarshalJSON implements the interface MarshalJSON for json.Marshal. 465 func (m *IntAnyMap) MarshalJSON() ([]byte, error) { 466 m.mu.RLock() 467 defer m.mu.RUnlock() 468 return json.Marshal(m.data) 469 } 470 471 // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal. 472 func (m *IntAnyMap) UnmarshalJSON(b []byte) error { 473 m.mu.Lock() 474 defer m.mu.Unlock() 475 if m.data == nil { 476 m.data = make(map[int]interface{}) 477 } 478 if err := json.UnmarshalUseNumber(b, &m.data); err != nil { 479 return err 480 } 481 return nil 482 } 483 484 // UnmarshalValue is an interface implement which sets any type of value for map. 485 func (m *IntAnyMap) UnmarshalValue(value interface{}) (err error) { 486 m.mu.Lock() 487 defer m.mu.Unlock() 488 if m.data == nil { 489 m.data = make(map[int]interface{}) 490 } 491 switch value.(type) { 492 case string, []byte: 493 return json.UnmarshalUseNumber(gconv.Bytes(value), &m.data) 494 default: 495 for k, v := range gconv.Map(value) { 496 m.data[gconv.Int(k)] = v 497 } 498 } 499 return 500 }