mirror of
https://github.com/aquasecurity/trivy.git
synced 2025-12-21 14:50:53 -08:00
107 lines
3.3 KiB
Go
107 lines
3.3 KiB
Go
package set
|
|
|
|
import (
|
|
"iter"
|
|
"maps"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
// caseInsensitiveStringSet represents a case-insensitive string set implementation
|
|
// It stores strings with case-insensitive comparison while preserving the original casing
|
|
// of the first occurrence of each unique string (case-insensitive).
|
|
// The map key is the lowercase version, and the value is the original string.
|
|
// WARNING: This implementation is not thread-safe
|
|
type caseInsensitiveStringSet map[string]string //nolint: gocritic
|
|
|
|
// NewCaseInsensitive creates a new empty case-insensitive string set with optional initial values
|
|
// The first occurrence of each unique string (case-insensitive) will be preserved.
|
|
// For example: NewCaseInsensitive("Hello", "HELLO", "world") will contain "Hello" and "world"
|
|
func NewCaseInsensitive(values ...string) Set[string] {
|
|
s := make(caseInsensitiveStringSet, len(values))
|
|
s.Append(values...)
|
|
return s
|
|
}
|
|
|
|
// Append adds multiple items to the set and returns the new size
|
|
// If an item already exists (case-insensitive), it will not be added again
|
|
// and the original casing is preserved
|
|
func (s caseInsensitiveStringSet) Append(values ...string) int {
|
|
for _, v := range values {
|
|
key := strings.ToLower(v)
|
|
if _, exists := s[key]; !exists {
|
|
s[key] = v
|
|
}
|
|
}
|
|
return len(s)
|
|
}
|
|
|
|
// Remove removes an item from the set (case-insensitive)
|
|
func (s caseInsensitiveStringSet) Remove(item string) {
|
|
delete(s, strings.ToLower(item))
|
|
}
|
|
|
|
// Contains checks if an item exists in the set (case-insensitive)
|
|
func (s caseInsensitiveStringSet) Contains(item string) bool {
|
|
_, exists := s[strings.ToLower(item)]
|
|
return exists
|
|
}
|
|
|
|
// Size returns the number of items in the set
|
|
func (s caseInsensitiveStringSet) Size() int {
|
|
return len(s)
|
|
}
|
|
|
|
// Clear removes all items from the set
|
|
func (s caseInsensitiveStringSet) Clear() {
|
|
clear(s)
|
|
}
|
|
|
|
// Clone returns a new set with a copy of all items
|
|
func (s caseInsensitiveStringSet) Clone() Set[string] {
|
|
return maps.Clone(s)
|
|
}
|
|
|
|
// Items returns all items in the set as a slice with their original casing
|
|
func (s caseInsensitiveStringSet) Items() []string {
|
|
return slices.Collect(s.Iter())
|
|
}
|
|
|
|
// Iter returns an iterator over the set values with their original casing
|
|
func (s caseInsensitiveStringSet) Iter() iter.Seq[string] {
|
|
return maps.Values(s)
|
|
}
|
|
|
|
// Union returns a new case-insensitive set containing all items from both sets
|
|
// If the same item (case-insensitive) exists in both sets, the casing from this set is preserved
|
|
func (s caseInsensitiveStringSet) Union(other Set[string]) Set[string] {
|
|
result := make(caseInsensitiveStringSet, s.Size()+other.Size())
|
|
maps.Copy(result, s)
|
|
result.Append(other.Items()...)
|
|
return result
|
|
}
|
|
|
|
// Intersection returns a new case-insensitive set containing items present in both sets
|
|
// The casing from this set is preserved for matching items
|
|
func (s caseInsensitiveStringSet) Intersection(other Set[string]) Set[string] {
|
|
result := make(caseInsensitiveStringSet)
|
|
for _, v := range s {
|
|
if other.Contains(v) {
|
|
result.Append(v)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Difference returns a new case-insensitive set containing items present in this set but not in the other
|
|
// The casing from this set is preserved
|
|
func (s caseInsensitiveStringSet) Difference(other Set[string]) Set[string] {
|
|
result := make(caseInsensitiveStringSet)
|
|
for _, v := range s {
|
|
if !other.Contains(v) {
|
|
result.Append(v)
|
|
}
|
|
}
|
|
return result
|
|
}
|