mirror of
https://github.com/weaveworks/scope.git
synced 2026-02-14 18:09:59 +00:00
135 lines
2.9 KiB
Go
135 lines
2.9 KiB
Go
package report
|
|
|
|
import (
|
|
"sort"
|
|
)
|
|
|
|
// StringSet is a sorted set of unique strings. Clients must use the Add
|
|
// method to add strings.
|
|
type StringSet []string
|
|
|
|
var emptyStringSet StringSet
|
|
|
|
// MakeStringSet makes a new StringSet with the given strings.
|
|
func MakeStringSet(strs ...string) StringSet {
|
|
if len(strs) <= 0 {
|
|
return nil
|
|
}
|
|
result := make([]string, len(strs))
|
|
copy(result, strs)
|
|
sort.Strings(result)
|
|
for i := 1; i < len(result); { // shuffle down any duplicates
|
|
if result[i-1] == result[i] {
|
|
result = append(result[:i-1], result[i:]...)
|
|
continue
|
|
}
|
|
i++
|
|
}
|
|
return StringSet(result)
|
|
}
|
|
|
|
// Contains returns true if the string set includes the given string
|
|
func (s StringSet) Contains(str string) bool {
|
|
i := sort.Search(len(s), func(i int) bool { return s[i] >= str })
|
|
return i < len(s) && s[i] == str
|
|
}
|
|
|
|
// Intersection returns the intersections of a and b
|
|
func (s StringSet) Intersection(b StringSet) StringSet {
|
|
result, i, j := emptyStringSet, 0, 0
|
|
for i < len(s) && j < len(b) {
|
|
if s[i] == b[j] {
|
|
result = result.Add(s[i])
|
|
}
|
|
if s[i] < b[j] {
|
|
i++
|
|
} else {
|
|
j++
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Equal returns true if a and b have the same contents
|
|
func (s StringSet) Equal(b StringSet) bool {
|
|
if len(s) != len(b) {
|
|
return false
|
|
}
|
|
for i := range s {
|
|
if s[i] != b[i] {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Add adds the strings to the StringSet. Add is the only valid way to grow a
|
|
// StringSet. Add returns the StringSet to enable chaining.
|
|
func (s StringSet) Add(strs ...string) StringSet {
|
|
for _, str := range strs {
|
|
i := sort.Search(len(s), func(i int) bool { return s[i] >= str })
|
|
if i < len(s) && s[i] == str {
|
|
// The list already has the element.
|
|
continue
|
|
}
|
|
// It a new element, insert it in order.
|
|
s = append(s, "")
|
|
copy(s[i+1:], s[i:])
|
|
s[i] = str
|
|
}
|
|
return s
|
|
}
|
|
|
|
// Merge combines the two StringSets and returns a new result.
|
|
// Second return value is true if the return value is s
|
|
func (s StringSet) Merge(other StringSet) (StringSet, bool) {
|
|
switch {
|
|
case len(other) <= 0: // Optimise special case, to avoid allocating
|
|
return s, true // (note unit test DeepEquals breaks if we don't do this)
|
|
case len(s) <= 0:
|
|
return other, false
|
|
}
|
|
|
|
i, j := 0, 0
|
|
loop:
|
|
for i < len(s) {
|
|
switch {
|
|
case j >= len(other):
|
|
return s, true
|
|
case s[i] == other[j]:
|
|
i++
|
|
j++
|
|
case s[i] < other[j]:
|
|
i++
|
|
default:
|
|
break loop
|
|
}
|
|
}
|
|
if i >= len(s) && j >= len(other) {
|
|
return s, true
|
|
}
|
|
|
|
result := make(StringSet, i, len(s)+len(other))
|
|
copy(result, s[:i])
|
|
|
|
for i < len(s) {
|
|
switch {
|
|
case j >= len(other):
|
|
result = append(result, s[i:]...)
|
|
return result, false
|
|
case s[i] == other[j]:
|
|
result = append(result, s[i])
|
|
i++
|
|
j++
|
|
case s[i] < other[j]:
|
|
result = append(result, s[i])
|
|
i++
|
|
default:
|
|
result = append(result, other[j])
|
|
j++
|
|
}
|
|
}
|
|
result = append(result, other[j:]...)
|
|
return result, false
|
|
}
|