gitlab.com/evatix-go/core@v1.3.55/coredata/corestr/Hashset.go (about)

     1  package corestr
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"sort"
     7  	"strings"
     8  	"sync"
     9  
    10  	"gitlab.com/evatix-go/core/constants"
    11  	"gitlab.com/evatix-go/core/converters"
    12  	"gitlab.com/evatix-go/core/coredata/corejson"
    13  	"gitlab.com/evatix-go/core/coredata/stringslice"
    14  	"gitlab.com/evatix-go/core/internal/mapdiffinternal"
    15  	"gitlab.com/evatix-go/core/internal/strutilinternal"
    16  )
    17  
    18  type Hashset struct {
    19  	hasMapUpdated bool
    20  	isEmptySet    bool
    21  	length        int
    22  	items         map[string]bool
    23  	cachedList    []string
    24  	sync.Mutex
    25  }
    26  
    27  func (it *Hashset) IsEmpty() bool {
    28  	if it == nil {
    29  		return true
    30  	}
    31  
    32  	if it.hasMapUpdated {
    33  		it.isEmptySet = len(it.items) == 0
    34  	}
    35  
    36  	return it.isEmptySet
    37  }
    38  
    39  func (it *Hashset) HasItems() bool {
    40  	return !it.IsEmpty()
    41  }
    42  
    43  // AddCapacitiesLock Changing capacity creates new map and points to it.
    44  // There is memory copy and loop is performed.
    45  func (it *Hashset) AddCapacitiesLock(
    46  	capacities ...int,
    47  ) *Hashset {
    48  	length := it.LengthLock()
    49  
    50  	if len(capacities) == 0 {
    51  		return it
    52  	}
    53  
    54  	for _, capacity := range capacities {
    55  		length += capacity
    56  	}
    57  
    58  	return it.ResizeLock(length)
    59  }
    60  
    61  // AddCapacities Changing capacity creates new map and points to it.
    62  // There is memory copy and loop is performed.
    63  func (it *Hashset) AddCapacities(
    64  	capacities ...int,
    65  ) *Hashset {
    66  	length := it.Length()
    67  
    68  	if len(capacities) == 0 {
    69  		return it
    70  	}
    71  
    72  	for _, capacity := range capacities {
    73  		length += capacity
    74  	}
    75  
    76  	return it.Resize(length)
    77  }
    78  
    79  // Resize Changing capacity creates new map and points to it.
    80  // There is memory copy and loop is performed.
    81  func (it *Hashset) Resize(capacity int) *Hashset {
    82  	length := it.Length()
    83  
    84  	if length > capacity {
    85  		return it
    86  	}
    87  
    88  	newItemsMap := make(map[string]bool, capacity)
    89  
    90  	for val := range it.items {
    91  		newItemsMap[val] = true
    92  	}
    93  
    94  	it.items = newItemsMap
    95  
    96  	return it
    97  }
    98  
    99  // ResizeLock Changing capacity creates new map and points to it.
   100  // There is memory copy and loop is performed.
   101  func (it *Hashset) ResizeLock(capacity int) *Hashset {
   102  	length := it.LengthLock()
   103  
   104  	if length > capacity {
   105  		return it
   106  	}
   107  
   108  	newItemsMap := make(map[string]bool, capacity)
   109  
   110  	for val := range it.items {
   111  		newItemsMap[val] = true
   112  	}
   113  
   114  	it.Lock()
   115  	it.items = newItemsMap
   116  	it.Unlock()
   117  
   118  	return it
   119  }
   120  
   121  func (it *Hashset) Collection() *Collection {
   122  	return New.Collection.StringsOptions(false, it.List())
   123  }
   124  
   125  func (it *Hashset) IsEmptyLock() bool {
   126  	it.Lock()
   127  	defer it.Unlock()
   128  
   129  	return it.IsEmpty()
   130  }
   131  
   132  func (it *Hashset) ConcatNewHashsets(
   133  	isCloneCurrentOnEmpty bool,
   134  	hashsets ...*Hashset,
   135  ) *Hashset {
   136  	isEmpty := hashsets == nil || len(hashsets) == 0
   137  
   138  	if isEmpty {
   139  		return New.Hashset.UsingMapOption(
   140  			constants.Zero,
   141  			isCloneCurrentOnEmpty,
   142  			it.items,
   143  		)
   144  	}
   145  
   146  	length := it.Length() + constants.Capacity4
   147  
   148  	for _, h := range hashsets {
   149  		if h == nil {
   150  			continue
   151  		}
   152  
   153  		length += h.Length()
   154  	}
   155  
   156  	newHashset := New.Hashset.UsingMapOption(
   157  		length,
   158  		isCloneCurrentOnEmpty,
   159  		it.items,
   160  	)
   161  
   162  	newHashset.AddHashsetItems(it)
   163  
   164  	for _, h := range hashsets {
   165  		newHashset.AddHashsetItems(h)
   166  	}
   167  
   168  	return newHashset
   169  }
   170  
   171  func (it *Hashset) ConcatNewStringsPointers(
   172  	isCloneCurrentOnEmpty bool,
   173  	stringsOfStringsItems ...*[]string,
   174  ) *Hashset {
   175  	isEmpty := len(stringsOfStringsItems) == 0
   176  
   177  	if isEmpty {
   178  		return New.Hashset.UsingMapOption(
   179  			constants.Zero,
   180  			isCloneCurrentOnEmpty,
   181  			it.items,
   182  		)
   183  	}
   184  
   185  	length := AllIndividualItemsStringsOfStringsPointerLength(&stringsOfStringsItems) +
   186  		it.Length() +
   187  		constants.Capacity4
   188  
   189  	newHashset := New.Hashset.UsingMapOption(
   190  		length,
   191  		isCloneCurrentOnEmpty,
   192  		it.items,
   193  	)
   194  
   195  	newHashset.AddHashsetItems(it)
   196  
   197  	for _, stringsItems := range stringsOfStringsItems {
   198  		newHashset.AddStringsPtr(stringsItems)
   199  	}
   200  
   201  	return newHashset
   202  }
   203  
   204  func (it *Hashset) ConcatNewStrings(
   205  	isCloneCurrentOnEmpty bool,
   206  	stringsOfStringsItems ...[]string,
   207  ) *Hashset {
   208  	isEmpty := len(stringsOfStringsItems) == 0
   209  
   210  	if isEmpty {
   211  		return New.Hashset.UsingMapOption(
   212  			constants.Zero,
   213  			isCloneCurrentOnEmpty,
   214  			it.items,
   215  		)
   216  	}
   217  
   218  	length := AllIndividualStringsOfStringsLength(&stringsOfStringsItems) +
   219  		it.Length() +
   220  		constants.Capacity4
   221  	newHashset := New.Hashset.UsingMapOption(
   222  		length,
   223  		true,
   224  		it.items,
   225  	)
   226  
   227  	newHashset.AddHashsetItems(it)
   228  
   229  	for _, stringsItems := range stringsOfStringsItems {
   230  		newHashset.AddStrings(stringsItems)
   231  	}
   232  
   233  	return newHashset
   234  }
   235  
   236  func (it *Hashset) AddPtr(key *string) *Hashset {
   237  	it.items[*key] = true
   238  	it.hasMapUpdated = true
   239  
   240  	return it
   241  }
   242  
   243  func (it *Hashset) AddWithWgLock(
   244  	key string,
   245  	group *sync.WaitGroup,
   246  ) *Hashset {
   247  	it.Lock()
   248  	it.items[key] = true
   249  	it.Unlock()
   250  
   251  	it.hasMapUpdated = true
   252  
   253  	group.Done()
   254  
   255  	return it
   256  }
   257  
   258  func (it *Hashset) AddPtrLock(key *string) *Hashset {
   259  	it.Lock()
   260  	it.items[*key] = true
   261  	it.Unlock()
   262  
   263  	it.hasMapUpdated = true
   264  
   265  	return it
   266  }
   267  
   268  func (it *Hashset) Add(key string) *Hashset {
   269  	it.items[key] = true
   270  	it.hasMapUpdated = true
   271  
   272  	return it
   273  }
   274  
   275  func (it *Hashset) AddBool(key string) (isExist bool) {
   276  	_, has := it.items[key]
   277  
   278  	if !has {
   279  		it.items[key] = true
   280  	}
   281  
   282  	return has
   283  }
   284  
   285  func (it *Hashset) AddNonEmpty(str string) *Hashset {
   286  	if str == "" {
   287  		return it
   288  	}
   289  
   290  	return it
   291  }
   292  
   293  func (it *Hashset) AddNonEmptyWhitespace(str string) *Hashset {
   294  	if strutilinternal.IsEmptyOrWhitespace(str) {
   295  		return it
   296  	}
   297  
   298  	return it.Add(str)
   299  }
   300  
   301  func (it *Hashset) AddIf(isAdd bool, addingString string) *Hashset {
   302  	if !isAdd {
   303  		return it
   304  	}
   305  
   306  	return it.Add(addingString)
   307  }
   308  
   309  func (it *Hashset) AddIfMany(
   310  	isAdd bool,
   311  	addingStrings ...string,
   312  ) *Hashset {
   313  	if !isAdd {
   314  		return it
   315  	}
   316  
   317  	return it.Adds(addingStrings...)
   318  }
   319  
   320  func (it *Hashset) AddFunc(f func() string) *Hashset {
   321  	return it.Add(f())
   322  }
   323  
   324  func (it *Hashset) AddFuncErr(
   325  	funcReturnsError func() (result string, err error),
   326  	errHandler func(errInput error),
   327  ) *Hashset {
   328  	r, err := funcReturnsError()
   329  
   330  	if err != nil {
   331  		errHandler(err)
   332  
   333  		return it
   334  	}
   335  
   336  	return it.Add(r)
   337  }
   338  
   339  func (it *Hashset) AddStringsPtrWgLock(
   340  	keys *[]string, wg *sync.WaitGroup,
   341  ) *Hashset {
   342  	if keys == nil {
   343  		return it
   344  	}
   345  
   346  	length := len(*keys)
   347  
   348  	if length > it.length || length > constants.ArbitraryCapacity100 {
   349  		it.AddCapacitiesLock(length*2, constants.ArbitraryCapacity100)
   350  	}
   351  
   352  	it.Lock()
   353  	for _, key := range *keys {
   354  		it.items[key] = true
   355  	}
   356  
   357  	it.Unlock()
   358  	wg.Done()
   359  
   360  	it.hasMapUpdated = true
   361  
   362  	return it
   363  }
   364  
   365  func (it *Hashset) AddHashsetItems(
   366  	hashsetAdd *Hashset,
   367  ) *Hashset {
   368  	if hashsetAdd == nil {
   369  		return it
   370  	}
   371  
   372  	length := hashsetAdd.Length()
   373  
   374  	if length > it.length || length > constants.ArbitraryCapacity100 {
   375  		it.AddCapacities(length*2, constants.ArbitraryCapacity100)
   376  	}
   377  
   378  	for k := range hashsetAdd.items {
   379  		it.items[k] = true
   380  	}
   381  
   382  	it.hasMapUpdated = true
   383  
   384  	return it
   385  }
   386  
   387  // AddItemsMap only add if the value is true
   388  func (it *Hashset) AddItemsMap(
   389  	itemsMap map[string]bool,
   390  ) *Hashset {
   391  	if itemsMap == nil {
   392  		return it
   393  	}
   394  
   395  	length := len(itemsMap)
   396  
   397  	if length > it.length || length > constants.ArbitraryCapacity100 {
   398  		it.AddCapacities(length*2, constants.ArbitraryCapacity100)
   399  	}
   400  
   401  	for k, isEnabled := range itemsMap {
   402  		if !isEnabled {
   403  			continue
   404  		}
   405  
   406  		it.items[k] = true
   407  	}
   408  
   409  	it.hasMapUpdated = true
   410  
   411  	return it
   412  }
   413  
   414  // AddItemsMapWgLock only add if the value is true
   415  // Assume that wg already enqueued the job as wg.Add(...) done already.
   416  func (it *Hashset) AddItemsMapWgLock(
   417  	itemsMap *map[string]bool,
   418  	wg *sync.WaitGroup,
   419  ) *Hashset {
   420  	if itemsMap == nil {
   421  		return it
   422  	}
   423  
   424  	length := len(*itemsMap)
   425  
   426  	if length > it.length || length > constants.ArbitraryCapacity100 {
   427  		it.AddCapacitiesLock(length*2, constants.ArbitraryCapacity100)
   428  	}
   429  
   430  	for k, isEnabled := range *itemsMap {
   431  		if !isEnabled {
   432  			continue
   433  		}
   434  
   435  		it.Lock()
   436  		it.items[k] = true
   437  		it.Unlock()
   438  	}
   439  
   440  	wg.Done()
   441  
   442  	it.hasMapUpdated = true
   443  
   444  	return it
   445  }
   446  
   447  func (it *Hashset) AddHashsetWgLock(
   448  	hashsetAdd *Hashset,
   449  	wg *sync.WaitGroup,
   450  ) *Hashset {
   451  	if hashsetAdd == nil {
   452  		return it
   453  	}
   454  
   455  	length := hashsetAdd.LengthLock()
   456  
   457  	if length > it.length || length > constants.ArbitraryCapacity100 {
   458  		it.AddCapacitiesLock(length*2, constants.ArbitraryCapacity100)
   459  	}
   460  
   461  	it.Lock()
   462  	for k := range hashsetAdd.items {
   463  		it.items[k] = true
   464  	}
   465  
   466  	it.Unlock()
   467  	wg.Done()
   468  
   469  	it.hasMapUpdated = true
   470  
   471  	return it
   472  }
   473  
   474  func (it *Hashset) AddStringsPtr(keys *[]string) *Hashset {
   475  	if keys == nil {
   476  		return it
   477  	}
   478  
   479  	for _, key := range *keys {
   480  		it.items[key] = true
   481  	}
   482  
   483  	it.hasMapUpdated = true
   484  
   485  	return it
   486  }
   487  
   488  func (it *Hashset) AddStrings(keys []string) *Hashset {
   489  	if len(keys) == 0 {
   490  		return it
   491  	}
   492  
   493  	return it.AddStringsPtr(&keys)
   494  }
   495  
   496  func (it *Hashset) AddSimpleSlice(simpleSlice *SimpleSlice) *Hashset {
   497  	if simpleSlice.IsEmpty() {
   498  		return it
   499  	}
   500  
   501  	return it.AddStringsPtr(&simpleSlice.Items)
   502  }
   503  
   504  func (it *Hashset) AddStringsPtrLock(keys *[]string) *Hashset {
   505  	if keys == nil {
   506  		return it
   507  	}
   508  
   509  	it.Lock()
   510  	for _, key := range *keys {
   511  		it.items[key] = true
   512  	}
   513  
   514  	it.Unlock()
   515  
   516  	it.hasMapUpdated = true
   517  
   518  	return it
   519  }
   520  
   521  func (it *Hashset) Adds(keys ...string) *Hashset {
   522  	if keys == nil {
   523  		return it
   524  	}
   525  
   526  	for _, key := range keys {
   527  		it.items[key] = true
   528  	}
   529  
   530  	it.hasMapUpdated = true
   531  
   532  	return it
   533  }
   534  
   535  func (it *Hashset) AddCollection(
   536  	collection *Collection,
   537  ) *Hashset {
   538  	if collection == nil || collection.IsEmpty() {
   539  		return it
   540  	}
   541  
   542  	for _, element := range collection.items {
   543  		it.items[element] = true
   544  	}
   545  
   546  	it.hasMapUpdated = true
   547  
   548  	return it
   549  }
   550  
   551  func (it *Hashset) AddCollections(
   552  	collections ...*Collection,
   553  ) *Hashset {
   554  	if collections == nil {
   555  		return it
   556  	}
   557  
   558  	for _, collection := range collections {
   559  		if collection == nil || collection.IsEmpty() {
   560  			continue
   561  		}
   562  
   563  		for _, element := range collection.items {
   564  			it.items[element] = true
   565  		}
   566  	}
   567  
   568  	it.hasMapUpdated = true
   569  
   570  	return it
   571  }
   572  
   573  func (it *Hashset) AddsAnyUsingFilter(
   574  	filter IsStringFilter,
   575  	anys ...interface{},
   576  ) *Hashset {
   577  	if anys == nil {
   578  		return it
   579  	}
   580  
   581  	for i, any := range anys {
   582  		if any == nil {
   583  			continue
   584  		}
   585  
   586  		anyStr := fmt.Sprintf(constants.SprintValueFormat, any)
   587  		result, isKeep, isBreak := filter(anyStr, i)
   588  
   589  		if isKeep {
   590  			it.items[result] = true
   591  			it.hasMapUpdated = true
   592  		}
   593  
   594  		if isBreak {
   595  			return it
   596  		}
   597  	}
   598  
   599  	return it
   600  }
   601  
   602  func (it *Hashset) AddsAnyUsingFilterLock(
   603  	filter IsStringFilter,
   604  	anys ...interface{},
   605  ) *Hashset {
   606  	if anys == nil {
   607  		return it
   608  	}
   609  
   610  	for i, any := range anys {
   611  		if any == nil {
   612  			continue
   613  		}
   614  
   615  		anyStr := fmt.Sprintf(
   616  			constants.SprintValueFormat,
   617  			any)
   618  
   619  		result, isKeep, isBreak := filter(anyStr, i)
   620  
   621  		if isKeep {
   622  			it.Lock()
   623  			it.items[result] = true
   624  			it.Unlock()
   625  
   626  			it.hasMapUpdated = true
   627  		}
   628  
   629  		if isBreak {
   630  			return it
   631  		}
   632  	}
   633  
   634  	return it
   635  }
   636  
   637  func (it *Hashset) AddsUsingFilter(
   638  	filter IsStringFilter,
   639  	keys ...string,
   640  ) *Hashset {
   641  	if keys == nil {
   642  		return it
   643  	}
   644  
   645  	for i, key := range keys {
   646  		result, isKeep, isBreak := filter(key, i)
   647  
   648  		if isKeep {
   649  			it.items[result] = true
   650  			it.hasMapUpdated = true
   651  		}
   652  
   653  		if isBreak {
   654  			return it
   655  		}
   656  	}
   657  
   658  	return it
   659  }
   660  
   661  func (it *Hashset) AddLock(key string) *Hashset {
   662  	it.Lock()
   663  	defer it.Unlock()
   664  
   665  	it.items[key] = true
   666  	it.hasMapUpdated = true
   667  
   668  	return it
   669  }
   670  
   671  func (it *Hashset) HasAnyItem() bool {
   672  	return it != nil && it.Length() > 0
   673  }
   674  
   675  func (it *Hashset) IsMissing(key string) bool {
   676  	_, isFound := it.items[key]
   677  
   678  	return !isFound
   679  }
   680  
   681  func (it *Hashset) IsMissingLock(key string) bool {
   682  	it.Lock()
   683  	_, isFound := it.items[key]
   684  	it.Unlock()
   685  
   686  	return !isFound
   687  }
   688  
   689  func (it *Hashset) Has(key string) bool {
   690  	isSet, isFound := it.items[key]
   691  
   692  	return isFound && isSet
   693  }
   694  
   695  func (it *Hashset) HasLock(key string) bool {
   696  	it.Lock()
   697  	isSet, isFound := it.items[key]
   698  	it.Unlock()
   699  
   700  	return isFound && isSet
   701  }
   702  
   703  func (it *Hashset) HasAllStrings(keys []string) bool {
   704  	for _, key := range keys {
   705  		isSet, isFound := it.items[key]
   706  
   707  		if !(isFound && isSet) {
   708  			// not found
   709  			return false
   710  		}
   711  	}
   712  
   713  	// all found.
   714  	return true
   715  }
   716  
   717  // HasAllCollectionItems return false on items is nil or Empty.
   718  func (it *Hashset) HasAllCollectionItems(
   719  	collection *Collection,
   720  ) bool {
   721  	if collection == nil || collection.IsEmpty() {
   722  		return false
   723  	}
   724  
   725  	return it.HasAllStrings(collection.List())
   726  }
   727  
   728  func (it *Hashset) HasAll(keys ...string) bool {
   729  	for _, key := range keys {
   730  		isSet, isFound := it.items[key]
   731  
   732  		if !(isFound && isSet) {
   733  			// not found
   734  			return false
   735  		}
   736  	}
   737  
   738  	// all found.
   739  	return true
   740  }
   741  
   742  func (it *Hashset) IsAllMissing(keys ...string) bool {
   743  	for _, key := range keys {
   744  		isSet, isFound := it.items[key]
   745  
   746  		if isFound && isSet {
   747  			// found
   748  			return false
   749  		}
   750  	}
   751  
   752  	// all not found.
   753  	return true
   754  }
   755  
   756  func (it *Hashset) HasAny(keys ...string) bool {
   757  	for _, key := range keys {
   758  		isSet, isFound := it.items[key]
   759  
   760  		if isFound && isSet {
   761  			// any found
   762  			return true
   763  		}
   764  	}
   765  
   766  	// all not found.
   767  	return false
   768  }
   769  
   770  func (it *Hashset) HasWithLock(key string) bool {
   771  	it.Lock()
   772  	defer it.Unlock()
   773  
   774  	isSet, isFound := it.items[key]
   775  
   776  	return isFound && isSet
   777  }
   778  
   779  func (it *Hashset) OrderedList() []string {
   780  	if it.IsEmpty() {
   781  		return []string{}
   782  	}
   783  
   784  	return it.
   785  		Collection().
   786  		SortedAsc().
   787  		items
   788  }
   789  
   790  func (it *Hashset) SafeStrings() []string {
   791  	if it.IsEmpty() {
   792  		return []string{}
   793  	}
   794  
   795  	return it.List()
   796  }
   797  
   798  func (it *Hashset) Lines() []string {
   799  	if it.IsEmpty() {
   800  		return []string{}
   801  	}
   802  
   803  	return it.List()
   804  }
   805  
   806  // GetFilteredItems must return slice.
   807  func (it *Hashset) GetFilteredItems(
   808  	filter IsStringFilter,
   809  ) *[]string {
   810  	if it.IsEmpty() {
   811  		return &([]string{})
   812  	}
   813  
   814  	filteredList := make(
   815  		[]string,
   816  		0,
   817  		it.Length())
   818  
   819  	i := 0
   820  	for key := range it.items {
   821  		result, isKeep, isBreak := filter(key, i)
   822  		i++
   823  
   824  		if !isKeep {
   825  			continue
   826  		}
   827  
   828  		filteredList = append(
   829  			filteredList,
   830  			result)
   831  
   832  		if isBreak {
   833  			return &filteredList
   834  		}
   835  	}
   836  
   837  	return &filteredList
   838  }
   839  
   840  // GetFilteredCollection must return items.
   841  func (it *Hashset) GetFilteredCollection(
   842  	filter IsStringFilter,
   843  ) *Collection {
   844  	if it.IsEmpty() {
   845  		return Empty.Collection()
   846  	}
   847  
   848  	filteredList := make(
   849  		[]string,
   850  		0,
   851  		it.Length())
   852  
   853  	i := 0
   854  	for key := range it.items {
   855  		result, isKeep, isBreak := filter(key, i)
   856  		i++
   857  
   858  		if !isKeep {
   859  			continue
   860  		}
   861  
   862  		filteredList = append(
   863  			filteredList,
   864  			result)
   865  
   866  		if isBreak {
   867  			return New.Collection.StringsOptions(
   868  				false,
   869  				filteredList)
   870  		}
   871  	}
   872  
   873  	return New.Collection.StringsOptions(
   874  		false,
   875  		filteredList)
   876  }
   877  
   878  // GetAllExceptHashset Get all hashset items except the mentioned ones in anotherHashset.
   879  // Always returns a copy of new strings.
   880  // It is like set A - B
   881  // Set A = this Hashset
   882  // Set B = anotherHashset given in parameters.
   883  func (it *Hashset) GetAllExceptHashset(
   884  	anotherHashset *Hashset,
   885  ) []string {
   886  	if anotherHashset == nil || anotherHashset.IsEmpty() {
   887  		return it.List()
   888  	}
   889  
   890  	finalList := make(
   891  		[]string,
   892  		0,
   893  		it.Length())
   894  
   895  	for item := range it.items {
   896  		if anotherHashset.Has(item) {
   897  			continue
   898  		}
   899  
   900  		finalList = append(
   901  			finalList,
   902  			item)
   903  	}
   904  
   905  	return finalList
   906  }
   907  
   908  // GetAllExcept Get all hashset items except the mentioned ones in items.
   909  // Always returns a copy of new strings.
   910  // It is like set A - B
   911  // Set A = this Hashset
   912  // Set B = items given in parameters.
   913  func (it *Hashset) GetAllExcept(
   914  	items []string,
   915  ) []string {
   916  	if items == nil {
   917  		return it.List()
   918  	}
   919  
   920  	newHashset := New.Hashset.Strings(
   921  		items)
   922  
   923  	return it.GetAllExceptHashset(
   924  		newHashset)
   925  }
   926  
   927  func (it *Hashset) GetAllExceptSpread(
   928  	items ...string,
   929  ) []string {
   930  	if items == nil {
   931  		return it.List()
   932  	}
   933  
   934  	newHashset := New.Hashset.Strings(
   935  		items)
   936  
   937  	return it.GetAllExceptHashset(
   938  		newHashset)
   939  }
   940  
   941  // GetAllExceptCollection Get all hashset items except the mentioned ones in collection.
   942  // Always returns a copy of new strings.
   943  // It is like set A - B
   944  // Set A = this Hashset
   945  // Set B = collection given in parameters.
   946  func (it *Hashset) GetAllExceptCollection(
   947  	collection *Collection,
   948  ) []string {
   949  	if collection == nil {
   950  		return it.List()
   951  	}
   952  
   953  	return it.GetAllExceptHashset(
   954  		collection.HashsetAsIs())
   955  }
   956  
   957  // GetAllExceptCollectionPtr Get all hashset items except the mentioned ones in collectionPtr.
   958  // Always returns a copy of new strings.
   959  // It is like set A - B
   960  // Set A = this Hashset
   961  // Set B = collectionPtr given in parameters.
   962  func (it *Hashset) GetAllExceptCollectionPtr(
   963  	collectionPtr *CollectionPtr,
   964  ) []string {
   965  	if collectionPtr == nil {
   966  		return it.List()
   967  	}
   968  
   969  	return it.GetAllExceptHashset(
   970  		collectionPtr.HashsetAsIs())
   971  }
   972  
   973  func (it *Hashset) Items() map[string]bool {
   974  	return it.items
   975  }
   976  
   977  func (it *Hashset) List() []string {
   978  	return *it.ListPtr()
   979  }
   980  
   981  func (it *Hashset) MapStringAny() map[string]interface{} {
   982  	if it.IsEmpty() {
   983  		return map[string]interface{}{}
   984  	}
   985  
   986  	newMap := make(
   987  		map[string]interface{},
   988  		it.Length()+1)
   989  
   990  	for name, isSet := range it.items {
   991  		newMap[name] = isSet
   992  	}
   993  
   994  	return newMap
   995  }
   996  
   997  func (it *Hashset) MapStringAnyDiff() mapdiffinternal.MapStringAnyDiff {
   998  	return it.MapStringAny()
   999  }
  1000  
  1001  func (it *Hashset) JoinSorted(joiner string) string {
  1002  	if it.IsEmpty() {
  1003  		return constants.EmptyString
  1004  	}
  1005  
  1006  	list := it.ListPtr()
  1007  	sort.Strings(*list)
  1008  
  1009  	return strings.Join(*list, joiner)
  1010  }
  1011  
  1012  func (it *Hashset) ListPtrSortedAsc() []string {
  1013  	list := it.ListPtr()
  1014  	sort.Strings(*list)
  1015  
  1016  	return *list
  1017  }
  1018  
  1019  func (it *Hashset) ListPtrSortedDsc() []string {
  1020  	list := it.ListPtr()
  1021  	sort.Strings(*list)
  1022  
  1023  	return *stringslice.InPlaceReverse(list)
  1024  }
  1025  
  1026  func (it *Hashset) ListPtr() *[]string {
  1027  	if it.hasMapUpdated || it.cachedList == nil {
  1028  		it.setCached()
  1029  	}
  1030  
  1031  	return &it.cachedList
  1032  }
  1033  
  1034  func (it *Hashset) Clear() *Hashset {
  1035  	if it == nil {
  1036  		return it
  1037  	}
  1038  
  1039  	it.items = nil
  1040  	it.items = make(map[string]bool)
  1041  	it.cachedList = []string{}
  1042  	it.hasMapUpdated = true
  1043  
  1044  	return it
  1045  }
  1046  
  1047  func (it *Hashset) Dispose() {
  1048  	if it == nil {
  1049  		return
  1050  	}
  1051  
  1052  	it.Clear()
  1053  	it.items = nil
  1054  	it.cachedList = nil
  1055  }
  1056  
  1057  // ListCopyPtrLock a slice must returned
  1058  func (it *Hashset) ListCopyPtrLock() *[]string {
  1059  	it.Lock()
  1060  	defer it.Unlock()
  1061  	cloned := *it.ListPtr()
  1062  
  1063  	return &cloned
  1064  }
  1065  
  1066  func (it *Hashset) setCached() {
  1067  	length := it.Length()
  1068  	list := make([]string, length)
  1069  
  1070  	i := 0
  1071  
  1072  	for key := range it.items {
  1073  		list[i] = key
  1074  		i++
  1075  	}
  1076  
  1077  	it.hasMapUpdated = false
  1078  	it.cachedList = list
  1079  }
  1080  
  1081  // ToLowerSet CreateUsingAliasMap a new items with all lower strings
  1082  func (it *Hashset) ToLowerSet() *Hashset {
  1083  	length := it.Length()
  1084  	newMap := make(map[string]bool, length)
  1085  
  1086  	var toLower string
  1087  	for key, isEnabled := range it.items {
  1088  		toLower = strings.ToLower(key)
  1089  		newMap[toLower] = isEnabled
  1090  	}
  1091  
  1092  	return New.Hashset.UsingMapOption(
  1093  		length,
  1094  		false,
  1095  		newMap,
  1096  	)
  1097  }
  1098  
  1099  func (it *Hashset) Length() int {
  1100  	if it == nil {
  1101  		return 0
  1102  	}
  1103  
  1104  	if it.hasMapUpdated {
  1105  		it.length = len(it.items)
  1106  	}
  1107  
  1108  	return it.length
  1109  }
  1110  
  1111  func (it *Hashset) LengthLock() int {
  1112  	it.Lock()
  1113  	defer it.Unlock()
  1114  
  1115  	return it.Length()
  1116  }
  1117  
  1118  func (it *Hashset) IsEqualsPtrLock(another *Hashset) bool {
  1119  	it.Lock()
  1120  	defer it.Unlock()
  1121  
  1122  	return it.IsEqualsPtr(another)
  1123  }
  1124  
  1125  func (it *Hashset) IsEqualsPtr(another *Hashset) bool {
  1126  	if it == nil && another == nil {
  1127  		return true
  1128  	}
  1129  
  1130  	if it == nil || another == nil {
  1131  		return false
  1132  	}
  1133  
  1134  	if it == another {
  1135  		// ptr same
  1136  		return true
  1137  	}
  1138  
  1139  	if it.IsEmpty() && another.IsEmpty() {
  1140  		return true
  1141  	}
  1142  
  1143  	if it.IsEmpty() || another.IsEmpty() {
  1144  		return false
  1145  	}
  1146  
  1147  	leftLength := it.Length()
  1148  	rightLength := another.Length()
  1149  
  1150  	if leftLength != rightLength {
  1151  		return false
  1152  	}
  1153  
  1154  	for key := range it.items {
  1155  		isRes, has := another.items[key]
  1156  
  1157  		if !has || !isRes {
  1158  			return false
  1159  		}
  1160  	}
  1161  
  1162  	return true
  1163  }
  1164  
  1165  func (it *Hashset) Remove(key string) *Hashset {
  1166  	delete(it.items, key)
  1167  	it.hasMapUpdated = true
  1168  
  1169  	return it
  1170  }
  1171  
  1172  func (it *Hashset) SafeRemove(key string) *Hashset {
  1173  	if it.Has(key) {
  1174  		delete(it.items, key)
  1175  		it.hasMapUpdated = true
  1176  	}
  1177  
  1178  	return it
  1179  }
  1180  
  1181  func (it *Hashset) RemoveWithLock(key string) *Hashset {
  1182  	it.Lock()
  1183  	defer it.Unlock()
  1184  
  1185  	it.Remove(key)
  1186  
  1187  	return it
  1188  }
  1189  
  1190  func (it Hashset) String() string {
  1191  	if it.IsEmpty() {
  1192  		return commonJoiner + NoElements
  1193  	}
  1194  
  1195  	return commonJoiner +
  1196  		strings.Join(
  1197  			it.List(),
  1198  			commonJoiner)
  1199  }
  1200  
  1201  func (it *Hashset) StringLock() string {
  1202  	if it.IsEmptyLock() {
  1203  		return commonJoiner + NoElements
  1204  	}
  1205  
  1206  	it.Lock()
  1207  	defer it.Unlock()
  1208  
  1209  	return commonJoiner +
  1210  		strings.Join(
  1211  			*it.ListPtr(),
  1212  			commonJoiner)
  1213  }
  1214  
  1215  func (it Hashset) Join(
  1216  	joiner string,
  1217  ) string {
  1218  	return strings.Join(*it.ListPtr(), joiner)
  1219  }
  1220  
  1221  func (it Hashset) NonEmptyJoins(
  1222  	joiner string,
  1223  ) string {
  1224  	return stringslice.NonEmptyJoinPtr(
  1225  		it.ListPtr(),
  1226  		joiner)
  1227  }
  1228  
  1229  func (it Hashset) NonWhitespaceJoins(
  1230  	joiner string,
  1231  ) string {
  1232  	return stringslice.NonWhitespaceJoinPtr(
  1233  		it.ListPtr(),
  1234  		joiner)
  1235  }
  1236  
  1237  //goland:noinspection GoLinterLocal
  1238  func (it Hashset) JsonModel() map[string]bool {
  1239  	if it.IsEmpty() {
  1240  		return map[string]bool{}
  1241  	}
  1242  
  1243  	return it.items
  1244  }
  1245  
  1246  //goland:noinspection GoLinterLocal
  1247  func (it Hashset) JsonModelAny() interface{} {
  1248  	return it.JsonModel()
  1249  }
  1250  
  1251  func (it Hashset) MarshalJSON() ([]byte, error) {
  1252  	return json.Marshal(it.JsonModel())
  1253  }
  1254  
  1255  func (it *Hashset) UnmarshalJSON(data []byte) error {
  1256  	var dataModelItems map[string]bool
  1257  	err := json.Unmarshal(data, &dataModelItems)
  1258  
  1259  	if err == nil {
  1260  		it.items = dataModelItems
  1261  		it.length = -1
  1262  		it.hasMapUpdated = true
  1263  		it.isEmptySet = false
  1264  	}
  1265  
  1266  	return err
  1267  }
  1268  
  1269  func (it Hashset) Json() corejson.Result {
  1270  	return corejson.New(it)
  1271  }
  1272  
  1273  func (it Hashset) JsonPtr() *corejson.Result {
  1274  	return corejson.NewPtr(it)
  1275  }
  1276  
  1277  // ParseInjectUsingJson It will not update the self but creates a new one.
  1278  func (it *Hashset) ParseInjectUsingJson(
  1279  	jsonResult *corejson.Result,
  1280  ) (*Hashset, error) {
  1281  	err := jsonResult.Unmarshal(it)
  1282  
  1283  	if err != nil {
  1284  		return New.Hashset.Empty(), err
  1285  	}
  1286  
  1287  	return it, nil
  1288  }
  1289  
  1290  // ParseInjectUsingJsonMust Panic if error
  1291  func (it *Hashset) ParseInjectUsingJsonMust(
  1292  	jsonResult *corejson.Result,
  1293  ) *Hashset {
  1294  	hashSet, err := it.ParseInjectUsingJson(jsonResult)
  1295  
  1296  	if err != nil {
  1297  		panic(err)
  1298  	}
  1299  
  1300  	return hashSet
  1301  }
  1302  
  1303  func (it *Hashset) AsJsonContractsBinder() corejson.JsonContractsBinder {
  1304  	return it
  1305  }
  1306  
  1307  func (it *Hashset) AsJsoner() corejson.Jsoner {
  1308  	return it
  1309  }
  1310  
  1311  func (it *Hashset) JsonParseSelfInject(
  1312  	jsonResult *corejson.Result,
  1313  ) error {
  1314  	_, err := it.ParseInjectUsingJson(
  1315  		jsonResult,
  1316  	)
  1317  
  1318  	return err
  1319  }
  1320  
  1321  func (it *Hashset) AsJsonParseSelfInjector() corejson.JsonParseSelfInjector {
  1322  	return it
  1323  }
  1324  
  1325  func (it *Hashset) AsJsonMarshaller() corejson.JsonMarshaller {
  1326  	return it
  1327  }
  1328  
  1329  func (it *Hashset) DistinctDiffLinesRaw(
  1330  	rightLines ...string,
  1331  ) []string {
  1332  	isLeftEmpty := it.IsEmpty()
  1333  
  1334  	if isLeftEmpty && len(rightLines) == 0 {
  1335  		return []string{}
  1336  	}
  1337  
  1338  	if !isLeftEmpty && len(rightLines) == 0 {
  1339  		return it.List()
  1340  	}
  1341  
  1342  	if isLeftEmpty && len(rightLines) > 0 {
  1343  		return rightLines
  1344  	}
  1345  
  1346  	diffLines := make(
  1347  		[]string,
  1348  		0,
  1349  		it.Length()+len(rightLines))
  1350  
  1351  	for _, rightItem := range rightLines {
  1352  		_, has := it.items[rightItem]
  1353  
  1354  		if !has {
  1355  			diffLines = append(diffLines, rightItem)
  1356  		}
  1357  	}
  1358  
  1359  	rightHashset := converters.StringsTo.Hashset(
  1360  		rightLines)
  1361  
  1362  	for leftItem := range it.items {
  1363  		_, has := rightHashset[leftItem]
  1364  
  1365  		if !has {
  1366  			diffLines = append(diffLines, leftItem)
  1367  		}
  1368  	}
  1369  
  1370  	return diffLines
  1371  }
  1372  
  1373  func (it *Hashset) DistinctDiffHashset(
  1374  	rightHashset *Hashset,
  1375  ) map[string]bool {
  1376  	return it.DistinctDiffLines(
  1377  		rightHashset.Lines()...)
  1378  }
  1379  
  1380  func (it *Hashset) DistinctDiffLines(
  1381  	rightLines ...string,
  1382  ) map[string]bool {
  1383  	isLeftEmpty := it.IsEmpty()
  1384  
  1385  	if isLeftEmpty && len(rightLines) == 0 {
  1386  		return map[string]bool{}
  1387  	}
  1388  
  1389  	if !isLeftEmpty && len(rightLines) == 0 {
  1390  		return it.Items()
  1391  	}
  1392  
  1393  	if isLeftEmpty && len(rightLines) > 0 {
  1394  		return converters.StringsTo.Hashset(rightLines)
  1395  	}
  1396  
  1397  	diffMap := make(
  1398  		map[string]bool,
  1399  		it.Length()+len(rightLines))
  1400  
  1401  	for _, rightItem := range rightLines {
  1402  		_, has := it.items[rightItem]
  1403  
  1404  		if !has {
  1405  			diffMap[rightItem] = true
  1406  		}
  1407  	}
  1408  
  1409  	rightHashset := converters.StringsTo.Hashset(
  1410  		rightLines)
  1411  
  1412  	for leftItem := range it.items {
  1413  		_, has := rightHashset[leftItem]
  1414  
  1415  		if !has {
  1416  			diffMap[leftItem] = true
  1417  		}
  1418  	}
  1419  
  1420  	return diffMap
  1421  }
  1422  
  1423  func (it *Hashset) Serialize() ([]byte, error) {
  1424  	return corejson.Serialize.Raw(it)
  1425  }
  1426  
  1427  func (it *Hashset) Deserialize(toPtr interface{}) (parsingErr error) {
  1428  	return it.JsonPtr().Deserialize(toPtr)
  1429  }