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