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  }