vendor: Add golang-set dependency
Golang-set library is added to make it easier to support set operations.
This commit is contained in:
parent
dca2d4e597
commit
34d0e516e0
6
glide.lock
generated
6
glide.lock
generated
@ -1,5 +1,5 @@
|
|||||||
hash: 9bf7ad53b92119a17068b8724d9b406a7ca84b5bfcd0baba44b08c696a538b14
|
hash: 3fd0e471868863d6ef4cd32bbcdc9b3d061911a15b458e7edd26cfba4faa62db
|
||||||
updated: 2018-09-06T15:58:19.234504-04:00
|
updated: 2018-09-17T13:13:44.344244-04:00
|
||||||
imports:
|
imports:
|
||||||
- name: github.com/beorn7/perks
|
- name: github.com/beorn7/perks
|
||||||
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
@ -15,6 +15,8 @@ imports:
|
|||||||
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||||
subpackages:
|
subpackages:
|
||||||
- spew
|
- spew
|
||||||
|
- name: github.com/deckarep/golang-set
|
||||||
|
version: cbaa98ba5575e67703b32b4b19f73c91f3c4159e
|
||||||
- name: github.com/fernet/fernet-go
|
- name: github.com/fernet/fernet-go
|
||||||
version: 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
|
version: 1b2437bc582b3cfbb341ee5a29f8ef5b42912ff2
|
||||||
- name: github.com/golang/protobuf
|
- name: github.com/golang/protobuf
|
||||||
|
@ -28,3 +28,5 @@ import:
|
|||||||
- assert
|
- assert
|
||||||
- package: gopkg.in/yaml.v2
|
- package: gopkg.in/yaml.v2
|
||||||
- package: github.com/cockroachdb/cmux
|
- package: github.com/cockroachdb/cmux
|
||||||
|
- package: github.com/deckarep/golang-set
|
||||||
|
version: ^1.7.1
|
||||||
|
22
vendor/github.com/deckarep/golang-set/.gitignore
generated
vendored
Normal file
22
vendor/github.com/deckarep/golang-set/.gitignore
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
11
vendor/github.com/deckarep/golang-set/.travis.yml
generated
vendored
Normal file
11
vendor/github.com/deckarep/golang-set/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.8
|
||||||
|
- 1.9
|
||||||
|
- tip
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test -race ./...
|
||||||
|
- go test -bench=.
|
||||||
|
|
22
vendor/github.com/deckarep/golang-set/LICENSE
generated
vendored
Normal file
22
vendor/github.com/deckarep/golang-set/LICENSE
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
95
vendor/github.com/deckarep/golang-set/README.md
generated
vendored
Normal file
95
vendor/github.com/deckarep/golang-set/README.md
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
[![Build Status](https://travis-ci.org/deckarep/golang-set.svg?branch=master)](https://travis-ci.org/deckarep/golang-set)
|
||||||
|
[![Go Report Card](https://goreportcard.com/badge/github.com/deckarep/golang-set)](https://goreportcard.com/report/github.com/deckarep/golang-set)
|
||||||
|
[![GoDoc](https://godoc.org/github.com/deckarep/golang-set?status.svg)](http://godoc.org/github.com/deckarep/golang-set)
|
||||||
|
|
||||||
|
## golang-set
|
||||||
|
|
||||||
|
|
||||||
|
The missing set collection for the Go language. Until Go has sets built-in...use this.
|
||||||
|
|
||||||
|
Coming from Python one of the things I miss is the superbly wonderful set collection. This is my attempt to mimic the primary features of the set from Python.
|
||||||
|
You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library. To those I say simply ignore this repository
|
||||||
|
and carry-on and to the rest that find this useful please contribute in helping me make it better by:
|
||||||
|
|
||||||
|
* Helping to make more idiomatic improvements to the code.
|
||||||
|
* Helping to increase the performance of it. ~~(So far, no attempt has been made, but since it uses a map internally, I expect it to be mostly performant.)~~
|
||||||
|
* Helping to make the unit-tests more robust and kick-ass.
|
||||||
|
* Helping to fill in the [documentation.](http://godoc.org/github.com/deckarep/golang-set)
|
||||||
|
* Simply offering feedback and suggestions. (Positive, constructive feedback is appreciated.)
|
||||||
|
|
||||||
|
I have to give some credit for helping seed the idea with this post on [stackoverflow.](http://programmers.stackexchange.com/questions/177428/sets-data-structure-in-golang)
|
||||||
|
|
||||||
|
*Update* - as of 3/9/2014, you can use a compile-time generic version of this package in the [gen](http://clipperhouse.github.io/gen/) framework. This framework allows you to use the golang-set in a completely generic and type-safe way by allowing you to generate a supporting .go file based on your custom types.
|
||||||
|
|
||||||
|
## Features (as of 9/22/2014)
|
||||||
|
|
||||||
|
* a CartesianProduct() method has been added with unit-tests: [Read more about the cartesian product](http://en.wikipedia.org/wiki/Cartesian_product)
|
||||||
|
|
||||||
|
## Features (as of 9/15/2014)
|
||||||
|
|
||||||
|
* a PowerSet() method has been added with unit-tests: [Read more about the Power set](http://en.wikipedia.org/wiki/Power_set)
|
||||||
|
|
||||||
|
## Features (as of 4/22/2014)
|
||||||
|
|
||||||
|
* One common interface to both implementations
|
||||||
|
* Two set implementations to choose from
|
||||||
|
* a thread-safe implementation designed for concurrent use
|
||||||
|
* a non-thread-safe implementation designed for performance
|
||||||
|
* 75 benchmarks for both implementations
|
||||||
|
* 35 unit tests for both implementations
|
||||||
|
* 14 concurrent tests for the thread-safe implementation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Please see the unit test file for additional usage examples. The Python set documentation will also do a better job than I can of explaining how a set typically [works.](http://docs.python.org/2/library/sets.html) Please keep in mind
|
||||||
|
however that the Python set is a built-in type and supports additional features and syntax that make it awesome.
|
||||||
|
|
||||||
|
## Examples but not exhaustive:
|
||||||
|
|
||||||
|
```go
|
||||||
|
requiredClasses := mapset.NewSet()
|
||||||
|
requiredClasses.Add("Cooking")
|
||||||
|
requiredClasses.Add("English")
|
||||||
|
requiredClasses.Add("Math")
|
||||||
|
requiredClasses.Add("Biology")
|
||||||
|
|
||||||
|
scienceSlice := []interface{}{"Biology", "Chemistry"}
|
||||||
|
scienceClasses := mapset.NewSetFromSlice(scienceSlice)
|
||||||
|
|
||||||
|
electiveClasses := mapset.NewSet()
|
||||||
|
electiveClasses.Add("Welding")
|
||||||
|
electiveClasses.Add("Music")
|
||||||
|
electiveClasses.Add("Automotive")
|
||||||
|
|
||||||
|
bonusClasses := mapset.NewSet()
|
||||||
|
bonusClasses.Add("Go Programming")
|
||||||
|
bonusClasses.Add("Python Programming")
|
||||||
|
|
||||||
|
//Show me all the available classes I can take
|
||||||
|
allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
|
||||||
|
fmt.Println(allClasses) //Set{Cooking, English, Math, Chemistry, Welding, Biology, Music, Automotive, Go Programming, Python Programming}
|
||||||
|
|
||||||
|
|
||||||
|
//Is cooking considered a science class?
|
||||||
|
fmt.Println(scienceClasses.Contains("Cooking")) //false
|
||||||
|
|
||||||
|
//Show me all classes that are not science classes, since I hate science.
|
||||||
|
fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding}
|
||||||
|
|
||||||
|
//Which science classes are also required classes?
|
||||||
|
fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology}
|
||||||
|
|
||||||
|
//How many bonus classes do you offer?
|
||||||
|
fmt.Println(bonusClasses.Cardinality()) //2
|
||||||
|
|
||||||
|
//Do you have the following classes? Welding, Automotive and English?
|
||||||
|
fmt.Println(allClasses.IsSuperset(mapset.NewSetFromSlice([]interface{}{"Welding", "Automotive", "English"}))) //true
|
||||||
|
```
|
||||||
|
|
||||||
|
Thanks!
|
||||||
|
|
||||||
|
-Ralph
|
||||||
|
|
||||||
|
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/deckarep/golang-set/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
||||||
|
|
||||||
|
[![Analytics](https://ga-beacon.appspot.com/UA-42584447-2/deckarep/golang-set)](https://github.com/igrigorik/ga-beacon)
|
674
vendor/github.com/deckarep/golang-set/bench_test.go
generated
vendored
Normal file
674
vendor/github.com/deckarep/golang-set/bench_test.go
generated
vendored
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
package mapset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func nrand(n int) []int {
|
||||||
|
i := make([]int, n)
|
||||||
|
for ind := range i {
|
||||||
|
i[ind] = rand.Int()
|
||||||
|
}
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
func toInterfaces(i []int) []interface{} {
|
||||||
|
ifs := make([]interface{}, len(i))
|
||||||
|
for ind, v := range i {
|
||||||
|
ifs[ind] = v
|
||||||
|
}
|
||||||
|
return ifs
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchAdd(b *testing.B, s Set) {
|
||||||
|
nums := nrand(b.N)
|
||||||
|
b.ResetTimer()
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAddSafe(b *testing.B) {
|
||||||
|
benchAdd(b, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkAddUnsafe(b *testing.B) {
|
||||||
|
benchAdd(b, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchRemove(b *testing.B, s Set) {
|
||||||
|
nums := nrand(b.N)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Remove(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRemoveSafe(b *testing.B) {
|
||||||
|
benchRemove(b, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkRemoveUnsafe(b *testing.B) {
|
||||||
|
benchRemove(b, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchCardinality(b *testing.B, s Set) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Cardinality()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCardinalitySafe(b *testing.B) {
|
||||||
|
benchCardinality(b, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkCardinalityUnsafe(b *testing.B) {
|
||||||
|
benchCardinality(b, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchClear(b *testing.B, s Set) {
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClearSafe(b *testing.B) {
|
||||||
|
benchClear(b, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClearUnsafe(b *testing.B) {
|
||||||
|
benchClear(b, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchClone(b *testing.B, n int, s Set) {
|
||||||
|
nums := toInterfaces(nrand(n))
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClone1Safe(b *testing.B) {
|
||||||
|
benchClone(b, 1, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClone1Unsafe(b *testing.B) {
|
||||||
|
benchClone(b, 1, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClone10Safe(b *testing.B) {
|
||||||
|
benchClone(b, 10, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClone10Unsafe(b *testing.B) {
|
||||||
|
benchClone(b, 10, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClone100Safe(b *testing.B) {
|
||||||
|
benchClone(b, 100, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkClone100Unsafe(b *testing.B) {
|
||||||
|
benchClone(b, 100, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchContains(b *testing.B, n int, s Set) {
|
||||||
|
nums := toInterfaces(nrand(n))
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
nums[n-1] = -1 // Definitely not in s
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Contains(nums...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains1Safe(b *testing.B) {
|
||||||
|
benchContains(b, 1, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains1Unsafe(b *testing.B) {
|
||||||
|
benchContains(b, 1, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains10Safe(b *testing.B) {
|
||||||
|
benchContains(b, 10, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains10Unsafe(b *testing.B) {
|
||||||
|
benchContains(b, 10, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains100Safe(b *testing.B) {
|
||||||
|
benchContains(b, 100, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkContains100Unsafe(b *testing.B) {
|
||||||
|
benchContains(b, 100, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchEqual(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Equal(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual1Safe(b *testing.B) {
|
||||||
|
benchEqual(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual1Unsafe(b *testing.B) {
|
||||||
|
benchEqual(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual10Safe(b *testing.B) {
|
||||||
|
benchEqual(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual10Unsafe(b *testing.B) {
|
||||||
|
benchEqual(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual100Safe(b *testing.B) {
|
||||||
|
benchEqual(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEqual100Unsafe(b *testing.B) {
|
||||||
|
benchEqual(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchDifference(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
for _, v := range nums[:n/2] {
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Difference(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIsSubset(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.IsSubset(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSubset1Safe(b *testing.B) {
|
||||||
|
benchIsSubset(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSubset1Unsafe(b *testing.B) {
|
||||||
|
benchIsSubset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSubset10Safe(b *testing.B) {
|
||||||
|
benchIsSubset(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSubset10Unsafe(b *testing.B) {
|
||||||
|
benchIsSubset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSubset100Safe(b *testing.B) {
|
||||||
|
benchIsSubset(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSubset100Unsafe(b *testing.B) {
|
||||||
|
benchIsSubset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIsSuperset(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.IsSuperset(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSuperset1Safe(b *testing.B) {
|
||||||
|
benchIsSuperset(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSuperset1Unsafe(b *testing.B) {
|
||||||
|
benchIsSuperset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSuperset10Safe(b *testing.B) {
|
||||||
|
benchIsSuperset(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSuperset10Unsafe(b *testing.B) {
|
||||||
|
benchIsSuperset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSuperset100Safe(b *testing.B) {
|
||||||
|
benchIsSuperset(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsSuperset100Unsafe(b *testing.B) {
|
||||||
|
benchIsSuperset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIsProperSubset(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.IsProperSubset(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSubset1Safe(b *testing.B) {
|
||||||
|
benchIsProperSubset(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSubset1Unsafe(b *testing.B) {
|
||||||
|
benchIsProperSubset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSubset10Safe(b *testing.B) {
|
||||||
|
benchIsProperSubset(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSubset10Unsafe(b *testing.B) {
|
||||||
|
benchIsProperSubset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSubset100Safe(b *testing.B) {
|
||||||
|
benchIsProperSubset(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSubset100Unsafe(b *testing.B) {
|
||||||
|
benchIsProperSubset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIsProperSuperset(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.IsProperSuperset(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSuperset1Safe(b *testing.B) {
|
||||||
|
benchIsProperSuperset(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSuperset1Unsafe(b *testing.B) {
|
||||||
|
benchIsProperSuperset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSuperset10Safe(b *testing.B) {
|
||||||
|
benchIsProperSuperset(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSuperset10Unsafe(b *testing.B) {
|
||||||
|
benchIsProperSuperset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSuperset100Safe(b *testing.B) {
|
||||||
|
benchIsProperSuperset(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIsProperSuperset100Unsafe(b *testing.B) {
|
||||||
|
benchIsProperSuperset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference1Safe(b *testing.B) {
|
||||||
|
benchDifference(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference1Unsafe(b *testing.B) {
|
||||||
|
benchDifference(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference10Safe(b *testing.B) {
|
||||||
|
benchDifference(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference10Unsafe(b *testing.B) {
|
||||||
|
benchDifference(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference100Safe(b *testing.B) {
|
||||||
|
benchDifference(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDifference100Unsafe(b *testing.B) {
|
||||||
|
benchDifference(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIntersect(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(int(float64(n) * float64(1.5)))
|
||||||
|
for _, v := range nums[:n] {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
for _, v := range nums[n/2:] {
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Intersect(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntersect1Safe(b *testing.B) {
|
||||||
|
benchIntersect(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntersect1Unsafe(b *testing.B) {
|
||||||
|
benchIntersect(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntersect10Safe(b *testing.B) {
|
||||||
|
benchIntersect(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntersect10Unsafe(b *testing.B) {
|
||||||
|
benchIntersect(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntersect100Safe(b *testing.B) {
|
||||||
|
benchIntersect(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIntersect100Unsafe(b *testing.B) {
|
||||||
|
benchIntersect(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchSymmetricDifference(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(int(float64(n) * float64(1.5)))
|
||||||
|
for _, v := range nums[:n] {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
for _, v := range nums[n/2:] {
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.SymmetricDifference(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSymmetricDifference1Safe(b *testing.B) {
|
||||||
|
benchSymmetricDifference(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSymmetricDifference1Unsafe(b *testing.B) {
|
||||||
|
benchSymmetricDifference(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSymmetricDifference10Safe(b *testing.B) {
|
||||||
|
benchSymmetricDifference(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSymmetricDifference10Unsafe(b *testing.B) {
|
||||||
|
benchSymmetricDifference(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSymmetricDifference100Safe(b *testing.B) {
|
||||||
|
benchSymmetricDifference(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSymmetricDifference100Unsafe(b *testing.B) {
|
||||||
|
benchSymmetricDifference(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchUnion(b *testing.B, n int, s, t Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums[:n/2] {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
for _, v := range nums[n/2:] {
|
||||||
|
t.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Union(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnion1Safe(b *testing.B) {
|
||||||
|
benchUnion(b, 1, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnion1Unsafe(b *testing.B) {
|
||||||
|
benchUnion(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnion10Safe(b *testing.B) {
|
||||||
|
benchUnion(b, 10, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnion10Unsafe(b *testing.B) {
|
||||||
|
benchUnion(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnion100Safe(b *testing.B) {
|
||||||
|
benchUnion(b, 100, NewSet(), NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkUnion100Unsafe(b *testing.B) {
|
||||||
|
benchUnion(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchEach(b *testing.B, n int, s Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Each(func(elem interface{}) bool {
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEach1Safe(b *testing.B) {
|
||||||
|
benchEach(b, 1, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEach1Unsafe(b *testing.B) {
|
||||||
|
benchEach(b, 1, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEach10Safe(b *testing.B) {
|
||||||
|
benchEach(b, 10, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEach10Unsafe(b *testing.B) {
|
||||||
|
benchEach(b, 10, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEach100Safe(b *testing.B) {
|
||||||
|
benchEach(b, 100, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkEach100Unsafe(b *testing.B) {
|
||||||
|
benchEach(b, 100, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIter(b *testing.B, n int, s Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
c := s.Iter()
|
||||||
|
for range c {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIter1Safe(b *testing.B) {
|
||||||
|
benchIter(b, 1, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIter1Unsafe(b *testing.B) {
|
||||||
|
benchIter(b, 1, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIter10Safe(b *testing.B) {
|
||||||
|
benchIter(b, 10, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIter10Unsafe(b *testing.B) {
|
||||||
|
benchIter(b, 10, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIter100Safe(b *testing.B) {
|
||||||
|
benchIter(b, 100, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIter100Unsafe(b *testing.B) {
|
||||||
|
benchIter(b, 100, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchIterator(b *testing.B, n int, s Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
c := s.Iterator().C
|
||||||
|
for range c {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIterator1Safe(b *testing.B) {
|
||||||
|
benchIterator(b, 1, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIterator1Unsafe(b *testing.B) {
|
||||||
|
benchIterator(b, 1, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIterator10Safe(b *testing.B) {
|
||||||
|
benchIterator(b, 10, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIterator10Unsafe(b *testing.B) {
|
||||||
|
benchIterator(b, 10, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIterator100Safe(b *testing.B) {
|
||||||
|
benchIterator(b, 100, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIterator100Unsafe(b *testing.B) {
|
||||||
|
benchIterator(b, 100, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchString(b *testing.B, n int, s Set) {
|
||||||
|
nums := nrand(n)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = s.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkString1Safe(b *testing.B) {
|
||||||
|
benchString(b, 1, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkString1Unsafe(b *testing.B) {
|
||||||
|
benchString(b, 1, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkString10Safe(b *testing.B) {
|
||||||
|
benchString(b, 10, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkString10Unsafe(b *testing.B) {
|
||||||
|
benchString(b, 10, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkString100Safe(b *testing.B) {
|
||||||
|
benchString(b, 100, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkString100Unsafe(b *testing.B) {
|
||||||
|
benchString(b, 100, NewThreadUnsafeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchToSlice(b *testing.B, s Set) {
|
||||||
|
nums := nrand(b.N)
|
||||||
|
for _, v := range nums {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.ToSlice()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkToSliceSafe(b *testing.B) {
|
||||||
|
benchToSlice(b, NewSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkToSliceUnsafe(b *testing.B) {
|
||||||
|
benchToSlice(b, NewThreadUnsafeSet())
|
||||||
|
}
|
58
vendor/github.com/deckarep/golang-set/iterator.go
generated
vendored
Normal file
58
vendor/github.com/deckarep/golang-set/iterator.go
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
|
||||||
|
// elements.
|
||||||
|
type Iterator struct {
|
||||||
|
C <-chan interface{}
|
||||||
|
stop chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
|
||||||
|
func (i *Iterator) Stop() {
|
||||||
|
// Allows for Stop() to be called multiple times
|
||||||
|
// (close() panics when called on already closed channel)
|
||||||
|
defer func() {
|
||||||
|
recover()
|
||||||
|
}()
|
||||||
|
|
||||||
|
close(i.stop)
|
||||||
|
|
||||||
|
// Exhaust any remaining elements.
|
||||||
|
for range i.C {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// newIterator returns a new Iterator instance together with its item and stop channels.
|
||||||
|
func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) {
|
||||||
|
itemChan := make(chan interface{})
|
||||||
|
stopChan := make(chan struct{})
|
||||||
|
return &Iterator{
|
||||||
|
C: itemChan,
|
||||||
|
stop: stopChan,
|
||||||
|
}, itemChan, stopChan
|
||||||
|
}
|
32
vendor/github.com/deckarep/golang-set/iterator_example_test.go
generated
vendored
Normal file
32
vendor/github.com/deckarep/golang-set/iterator_example_test.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package mapset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type YourType struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleIterator() {
|
||||||
|
set := NewSetFromSlice([]interface{}{
|
||||||
|
&YourType{Name: "Alise"},
|
||||||
|
&YourType{Name: "Bob"},
|
||||||
|
&YourType{Name: "John"},
|
||||||
|
&YourType{Name: "Nick"},
|
||||||
|
})
|
||||||
|
|
||||||
|
var found *YourType
|
||||||
|
it := set.Iterator()
|
||||||
|
|
||||||
|
for elem := range it.C {
|
||||||
|
if elem.(*YourType).Name == "John" {
|
||||||
|
found = elem.(*YourType)
|
||||||
|
it.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Found %+v\n", found)
|
||||||
|
|
||||||
|
// Output: Found &{Name:John}
|
||||||
|
}
|
217
vendor/github.com/deckarep/golang-set/set.go
generated
vendored
Normal file
217
vendor/github.com/deckarep/golang-set/set.go
generated
vendored
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Package mapset implements a simple and generic set collection.
|
||||||
|
// Items stored within it are unordered and unique. It supports
|
||||||
|
// typical set operations: membership testing, intersection, union,
|
||||||
|
// difference, symmetric difference and cloning.
|
||||||
|
//
|
||||||
|
// Package mapset provides two implementations of the Set
|
||||||
|
// interface. The default implementation is safe for concurrent
|
||||||
|
// access, but a non-thread-safe implementation is also provided for
|
||||||
|
// programs that can benefit from the slight speed improvement and
|
||||||
|
// that can enforce mutual exclusion through other means.
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
// Set is the primary interface provided by the mapset package. It
|
||||||
|
// represents an unordered set of data and a large number of
|
||||||
|
// operations that can be applied to that set.
|
||||||
|
type Set interface {
|
||||||
|
// Adds an element to the set. Returns whether
|
||||||
|
// the item was added.
|
||||||
|
Add(i interface{}) bool
|
||||||
|
|
||||||
|
// Returns the number of elements in the set.
|
||||||
|
Cardinality() int
|
||||||
|
|
||||||
|
// Removes all elements from the set, leaving
|
||||||
|
// the empty set.
|
||||||
|
Clear()
|
||||||
|
|
||||||
|
// Returns a clone of the set using the same
|
||||||
|
// implementation, duplicating all keys.
|
||||||
|
Clone() Set
|
||||||
|
|
||||||
|
// Returns whether the given items
|
||||||
|
// are all in the set.
|
||||||
|
Contains(i ...interface{}) bool
|
||||||
|
|
||||||
|
// Returns the difference between this set
|
||||||
|
// and other. The returned set will contain
|
||||||
|
// all elements of this set that are not also
|
||||||
|
// elements of other.
|
||||||
|
//
|
||||||
|
// Note that the argument to Difference
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, Difference will
|
||||||
|
// panic.
|
||||||
|
Difference(other Set) Set
|
||||||
|
|
||||||
|
// Determines if two sets are equal to each
|
||||||
|
// other. If they have the same cardinality
|
||||||
|
// and contain the same elements, they are
|
||||||
|
// considered equal. The order in which
|
||||||
|
// the elements were added is irrelevant.
|
||||||
|
//
|
||||||
|
// Note that the argument to Equal must be
|
||||||
|
// of the same type as the receiver of the
|
||||||
|
// method. Otherwise, Equal will panic.
|
||||||
|
Equal(other Set) bool
|
||||||
|
|
||||||
|
// Returns a new set containing only the elements
|
||||||
|
// that exist only in both sets.
|
||||||
|
//
|
||||||
|
// Note that the argument to Intersect
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, Intersect will
|
||||||
|
// panic.
|
||||||
|
Intersect(other Set) Set
|
||||||
|
|
||||||
|
// Determines if every element in this set is in
|
||||||
|
// the other set but the two sets are not equal.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsProperSubset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsProperSubset
|
||||||
|
// will panic.
|
||||||
|
IsProperSubset(other Set) bool
|
||||||
|
|
||||||
|
// Determines if every element in the other set
|
||||||
|
// is in this set but the two sets are not
|
||||||
|
// equal.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsSuperset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsSuperset will
|
||||||
|
// panic.
|
||||||
|
IsProperSuperset(other Set) bool
|
||||||
|
|
||||||
|
// Determines if every element in this set is in
|
||||||
|
// the other set.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsSubset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsSubset will
|
||||||
|
// panic.
|
||||||
|
IsSubset(other Set) bool
|
||||||
|
|
||||||
|
// Determines if every element in the other set
|
||||||
|
// is in this set.
|
||||||
|
//
|
||||||
|
// Note that the argument to IsSuperset
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, IsSuperset will
|
||||||
|
// panic.
|
||||||
|
IsSuperset(other Set) bool
|
||||||
|
|
||||||
|
// Iterates over elements and executes the passed func against each element.
|
||||||
|
// If passed func returns true, stop iteration at the time.
|
||||||
|
Each(func(interface{}) bool)
|
||||||
|
|
||||||
|
// Returns a channel of elements that you can
|
||||||
|
// range over.
|
||||||
|
Iter() <-chan interface{}
|
||||||
|
|
||||||
|
// Returns an Iterator object that you can
|
||||||
|
// use to range over the set.
|
||||||
|
Iterator() *Iterator
|
||||||
|
|
||||||
|
// Remove a single element from the set.
|
||||||
|
Remove(i interface{})
|
||||||
|
|
||||||
|
// Provides a convenient string representation
|
||||||
|
// of the current state of the set.
|
||||||
|
String() string
|
||||||
|
|
||||||
|
// Returns a new set with all elements which are
|
||||||
|
// in either this set or the other set but not in both.
|
||||||
|
//
|
||||||
|
// Note that the argument to SymmetricDifference
|
||||||
|
// must be of the same type as the receiver
|
||||||
|
// of the method. Otherwise, SymmetricDifference
|
||||||
|
// will panic.
|
||||||
|
SymmetricDifference(other Set) Set
|
||||||
|
|
||||||
|
// Returns a new set with all elements in both sets.
|
||||||
|
//
|
||||||
|
// Note that the argument to Union must be of the
|
||||||
|
|
||||||
|
// same type as the receiver of the method.
|
||||||
|
// Otherwise, IsSuperset will panic.
|
||||||
|
Union(other Set) Set
|
||||||
|
|
||||||
|
// Pop removes and returns an arbitrary item from the set.
|
||||||
|
Pop() interface{}
|
||||||
|
|
||||||
|
// Returns all subsets of a given set (Power Set).
|
||||||
|
PowerSet() Set
|
||||||
|
|
||||||
|
// Returns the Cartesian Product of two sets.
|
||||||
|
CartesianProduct(other Set) Set
|
||||||
|
|
||||||
|
// Returns the members of the set as a slice.
|
||||||
|
ToSlice() []interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSet creates and returns a reference to an empty set. Operations
|
||||||
|
// on the resulting set are thread-safe.
|
||||||
|
func NewSet(s ...interface{}) Set {
|
||||||
|
set := newThreadSafeSet()
|
||||||
|
for _, item := range s {
|
||||||
|
set.Add(item)
|
||||||
|
}
|
||||||
|
return &set
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetWith creates and returns a new set with the given elements.
|
||||||
|
// Operations on the resulting set are thread-safe.
|
||||||
|
func NewSetWith(elts ...interface{}) Set {
|
||||||
|
return NewSetFromSlice(elts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSetFromSlice creates and returns a reference to a set from an
|
||||||
|
// existing slice. Operations on the resulting set are thread-safe.
|
||||||
|
func NewSetFromSlice(s []interface{}) Set {
|
||||||
|
a := NewSet(s...)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewThreadUnsafeSet creates and returns a reference to an empty set.
|
||||||
|
// Operations on the resulting set are not thread-safe.
|
||||||
|
func NewThreadUnsafeSet() Set {
|
||||||
|
set := newThreadUnsafeSet()
|
||||||
|
return &set
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewThreadUnsafeSetFromSlice creates and returns a reference to a
|
||||||
|
// set from an existing slice. Operations on the resulting set are
|
||||||
|
// not thread-safe.
|
||||||
|
func NewThreadUnsafeSetFromSlice(s []interface{}) Set {
|
||||||
|
a := NewThreadUnsafeSet()
|
||||||
|
for _, item := range s {
|
||||||
|
a.Add(item)
|
||||||
|
}
|
||||||
|
return a
|
||||||
|
}
|
1200
vendor/github.com/deckarep/golang-set/set_test.go
generated
vendored
Normal file
1200
vendor/github.com/deckarep/golang-set/set_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
283
vendor/github.com/deckarep/golang-set/threadsafe.go
generated
vendored
Normal file
283
vendor/github.com/deckarep/golang-set/threadsafe.go
generated
vendored
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
import "sync"
|
||||||
|
|
||||||
|
type threadSafeSet struct {
|
||||||
|
s threadUnsafeSet
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func newThreadSafeSet() threadSafeSet {
|
||||||
|
return threadSafeSet{s: newThreadUnsafeSet()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Add(i interface{}) bool {
|
||||||
|
set.Lock()
|
||||||
|
ret := set.s.Add(i)
|
||||||
|
set.Unlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Contains(i ...interface{}) bool {
|
||||||
|
set.RLock()
|
||||||
|
ret := set.s.Contains(i...)
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsSubset(other Set) bool {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
ret := set.s.IsSubset(&o.s)
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsProperSubset(other Set) bool {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
defer set.RUnlock()
|
||||||
|
o.RLock()
|
||||||
|
defer o.RUnlock()
|
||||||
|
|
||||||
|
return set.s.IsProperSubset(&o.s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsSuperset(other Set) bool {
|
||||||
|
return other.IsSubset(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) IsProperSuperset(other Set) bool {
|
||||||
|
return other.IsProperSubset(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Union(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeUnion}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Intersect(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeIntersection}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Difference(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeDifference}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) SymmetricDifference(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeDifference}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Clear() {
|
||||||
|
set.Lock()
|
||||||
|
set.s = newThreadUnsafeSet()
|
||||||
|
set.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Remove(i interface{}) {
|
||||||
|
set.Lock()
|
||||||
|
delete(set.s, i)
|
||||||
|
set.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Cardinality() int {
|
||||||
|
set.RLock()
|
||||||
|
defer set.RUnlock()
|
||||||
|
return len(set.s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Each(cb func(interface{}) bool) {
|
||||||
|
set.RLock()
|
||||||
|
for elem := range set.s {
|
||||||
|
if cb(elem) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set.RUnlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Iter() <-chan interface{} {
|
||||||
|
ch := make(chan interface{})
|
||||||
|
go func() {
|
||||||
|
set.RLock()
|
||||||
|
|
||||||
|
for elem := range set.s {
|
||||||
|
ch <- elem
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
set.RUnlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Iterator() *Iterator {
|
||||||
|
iterator, ch, stopCh := newIterator()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
set.RLock()
|
||||||
|
L:
|
||||||
|
for elem := range set.s {
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
break L
|
||||||
|
case ch <- elem:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
set.RUnlock()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Equal(other Set) bool {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
ret := set.s.Equal(&o.s)
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Clone() Set {
|
||||||
|
set.RLock()
|
||||||
|
|
||||||
|
unsafeClone := set.s.Clone().(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeClone}
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) String() string {
|
||||||
|
set.RLock()
|
||||||
|
ret := set.s.String()
|
||||||
|
set.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) PowerSet() Set {
|
||||||
|
set.RLock()
|
||||||
|
unsafePowerSet := set.s.PowerSet().(*threadUnsafeSet)
|
||||||
|
set.RUnlock()
|
||||||
|
|
||||||
|
ret := &threadSafeSet{s: newThreadUnsafeSet()}
|
||||||
|
for subset := range unsafePowerSet.Iter() {
|
||||||
|
unsafeSubset := subset.(*threadUnsafeSet)
|
||||||
|
ret.Add(&threadSafeSet{s: *unsafeSubset})
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) Pop() interface{} {
|
||||||
|
set.Lock()
|
||||||
|
defer set.Unlock()
|
||||||
|
return set.s.Pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) CartesianProduct(other Set) Set {
|
||||||
|
o := other.(*threadSafeSet)
|
||||||
|
|
||||||
|
set.RLock()
|
||||||
|
o.RLock()
|
||||||
|
|
||||||
|
unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
|
||||||
|
ret := &threadSafeSet{s: *unsafeCartProduct}
|
||||||
|
set.RUnlock()
|
||||||
|
o.RUnlock()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) ToSlice() []interface{} {
|
||||||
|
keys := make([]interface{}, 0, set.Cardinality())
|
||||||
|
set.RLock()
|
||||||
|
for elem := range set.s {
|
||||||
|
keys = append(keys, elem)
|
||||||
|
}
|
||||||
|
set.RUnlock()
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) MarshalJSON() ([]byte, error) {
|
||||||
|
set.RLock()
|
||||||
|
b, err := set.s.MarshalJSON()
|
||||||
|
set.RUnlock()
|
||||||
|
|
||||||
|
return b, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadSafeSet) UnmarshalJSON(p []byte) error {
|
||||||
|
set.RLock()
|
||||||
|
err := set.s.UnmarshalJSON(p)
|
||||||
|
set.RUnlock()
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
524
vendor/github.com/deckarep/golang-set/threadsafe_test.go
generated
vendored
Normal file
524
vendor/github.com/deckarep/golang-set/threadsafe_test.go
generated
vendored
Normal file
@ -0,0 +1,524 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"math/rand"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const N = 1000
|
||||||
|
|
||||||
|
func Test_AddConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(ints))
|
||||||
|
for i := 0; i < len(ints); i++ {
|
||||||
|
go func(i int) {
|
||||||
|
s.Add(i)
|
||||||
|
wg.Done()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
for _, i := range ints {
|
||||||
|
if !s.Contains(i) {
|
||||||
|
t.Errorf("Set is missing element: %v", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_CardinalityConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
elems := s.Cardinality()
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
newElems := s.Cardinality()
|
||||||
|
if newElems < elems {
|
||||||
|
t.Errorf("Cardinality shrunk from %v to %v", elems, newElems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
for i := 0; i < N; i++ {
|
||||||
|
s.Add(rand.Int())
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_ClearConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(ints))
|
||||||
|
for i := 0; i < len(ints); i++ {
|
||||||
|
go func() {
|
||||||
|
s.Clear()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
go func(i int) {
|
||||||
|
s.Add(i)
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_CloneConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(ints))
|
||||||
|
for i := range ints {
|
||||||
|
go func(i int) {
|
||||||
|
s.Remove(i)
|
||||||
|
wg.Done()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_ContainsConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
interfaces := make([]interface{}, 0)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
interfaces = append(interfaces, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.Contains(interfaces...)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_DifferenceConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.Difference(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EqualConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.Equal(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IntersectConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.Intersect(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IsSubsetConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.IsSubset(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IsProperSubsetConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.IsProperSubset(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IsSupersetConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.IsSuperset(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IsProperSupersetConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.IsProperSuperset(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_EachConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
concurrent := 10
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
wg := new(sync.WaitGroup)
|
||||||
|
wg.Add(concurrent)
|
||||||
|
for n := 0; n < concurrent; n++ {
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
s.Each(func(elem interface{}) bool {
|
||||||
|
atomic.AddInt64(&count, 1)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if count != int64(N*concurrent) {
|
||||||
|
t.Errorf("%v != %v", count, int64(N*concurrent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_IterConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := make([]<-chan interface{}, 0)
|
||||||
|
for range ints {
|
||||||
|
cs = append(cs, s.Iter())
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan interface{})
|
||||||
|
go func() {
|
||||||
|
for n := 0; n < len(ints)*N; {
|
||||||
|
for _, d := range cs {
|
||||||
|
select {
|
||||||
|
case <-d:
|
||||||
|
n++
|
||||||
|
c <- nil
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(c)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for range c {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_RemoveConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(ints))
|
||||||
|
for _, v := range ints {
|
||||||
|
go func(i int) {
|
||||||
|
s.Remove(i)
|
||||||
|
wg.Done()
|
||||||
|
}(v)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if s.Cardinality() != 0 {
|
||||||
|
t.Errorf("Expected cardinality 0; got %v", s.Cardinality())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_StringConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(ints))
|
||||||
|
for range ints {
|
||||||
|
go func() {
|
||||||
|
_ = s.String()
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_SymmetricDifferenceConcurrent(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s, ss := NewSet(), NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
for _, v := range ints {
|
||||||
|
s.Add(v)
|
||||||
|
ss.Add(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for range ints {
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
s.SymmetricDifference(ss)
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_ToSlice(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
s := NewSet()
|
||||||
|
ints := rand.Perm(N)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(ints))
|
||||||
|
for i := 0; i < len(ints); i++ {
|
||||||
|
go func(i int) {
|
||||||
|
s.Add(i)
|
||||||
|
wg.Done()
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
setAsSlice := s.ToSlice()
|
||||||
|
if len(setAsSlice) != s.Cardinality() {
|
||||||
|
t.Errorf("Set length is incorrect: %v", len(setAsSlice))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, i := range setAsSlice {
|
||||||
|
if !s.Contains(i) {
|
||||||
|
t.Errorf("Set is missing element: %v", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test_ToSliceDeadlock - fixes issue: https://github.com/deckarep/golang-set/issues/36
|
||||||
|
// This code reveals the deadlock however it doesn't happen consistently.
|
||||||
|
func Test_ToSliceDeadlock(t *testing.T) {
|
||||||
|
runtime.GOMAXPROCS(2)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
set := NewSet()
|
||||||
|
workers := 10
|
||||||
|
wg.Add(workers)
|
||||||
|
for i := 1; i <= workers; i++ {
|
||||||
|
go func() {
|
||||||
|
for j := 0; j < 1000; j++ {
|
||||||
|
set.Add(1)
|
||||||
|
set.ToSlice()
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_UnmarshalJSON(t *testing.T) {
|
||||||
|
s := []byte(`["test", 1, 2, 3, ["4,5,6"]]`)
|
||||||
|
expected := NewSetFromSlice(
|
||||||
|
[]interface{}{
|
||||||
|
json.Number("1"),
|
||||||
|
json.Number("2"),
|
||||||
|
json.Number("3"),
|
||||||
|
"test",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
actual := NewSet()
|
||||||
|
err := json.Unmarshal(s, actual)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error should be nil: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !expected.Equal(actual) {
|
||||||
|
t.Errorf("Expected no difference, got: %v", expected.Difference(actual))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_MarshalJSON(t *testing.T) {
|
||||||
|
expected := NewSetFromSlice(
|
||||||
|
[]interface{}{
|
||||||
|
json.Number("1"),
|
||||||
|
"test",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
b, err := json.Marshal(
|
||||||
|
NewSetFromSlice(
|
||||||
|
[]interface{}{
|
||||||
|
1,
|
||||||
|
"test",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error should be nil: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := NewSet()
|
||||||
|
err = json.Unmarshal(b, actual)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error should be nil: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !expected.Equal(actual) {
|
||||||
|
t.Errorf("Expected no difference, got: %v", expected.Difference(actual))
|
||||||
|
}
|
||||||
|
}
|
337
vendor/github.com/deckarep/golang-set/threadunsafe.go
generated
vendored
Normal file
337
vendor/github.com/deckarep/golang-set/threadunsafe.go
generated
vendored
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
Open Source Initiative OSI - The MIT License (MIT):Licensing
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mapset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type threadUnsafeSet map[interface{}]struct{}
|
||||||
|
|
||||||
|
// An OrderedPair represents a 2-tuple of values.
|
||||||
|
type OrderedPair struct {
|
||||||
|
First interface{}
|
||||||
|
Second interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newThreadUnsafeSet() threadUnsafeSet {
|
||||||
|
return make(threadUnsafeSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Equal says whether two 2-tuples contain the same values in the same order.
|
||||||
|
func (pair *OrderedPair) Equal(other OrderedPair) bool {
|
||||||
|
if pair.First == other.First &&
|
||||||
|
pair.Second == other.Second {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Add(i interface{}) bool {
|
||||||
|
_, found := (*set)[i]
|
||||||
|
if found {
|
||||||
|
return false //False if it existed already
|
||||||
|
}
|
||||||
|
|
||||||
|
(*set)[i] = struct{}{}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Contains(i ...interface{}) bool {
|
||||||
|
for _, val := range i {
|
||||||
|
if _, ok := (*set)[val]; !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsSubset(other Set) bool {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
for elem := range *set {
|
||||||
|
if !other.Contains(elem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsProperSubset(other Set) bool {
|
||||||
|
return set.IsSubset(other) && !set.Equal(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsSuperset(other Set) bool {
|
||||||
|
return other.IsSubset(set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) IsProperSuperset(other Set) bool {
|
||||||
|
return set.IsSuperset(other) && !set.Equal(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Union(other Set) Set {
|
||||||
|
o := other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
unionedSet := newThreadUnsafeSet()
|
||||||
|
|
||||||
|
for elem := range *set {
|
||||||
|
unionedSet.Add(elem)
|
||||||
|
}
|
||||||
|
for elem := range *o {
|
||||||
|
unionedSet.Add(elem)
|
||||||
|
}
|
||||||
|
return &unionedSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Intersect(other Set) Set {
|
||||||
|
o := other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
intersection := newThreadUnsafeSet()
|
||||||
|
// loop over smaller set
|
||||||
|
if set.Cardinality() < other.Cardinality() {
|
||||||
|
for elem := range *set {
|
||||||
|
if other.Contains(elem) {
|
||||||
|
intersection.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for elem := range *o {
|
||||||
|
if set.Contains(elem) {
|
||||||
|
intersection.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &intersection
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Difference(other Set) Set {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
difference := newThreadUnsafeSet()
|
||||||
|
for elem := range *set {
|
||||||
|
if !other.Contains(elem) {
|
||||||
|
difference.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &difference
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) SymmetricDifference(other Set) Set {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
aDiff := set.Difference(other)
|
||||||
|
bDiff := other.Difference(set)
|
||||||
|
return aDiff.Union(bDiff)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Clear() {
|
||||||
|
*set = newThreadUnsafeSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Remove(i interface{}) {
|
||||||
|
delete(*set, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Cardinality() int {
|
||||||
|
return len(*set)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Each(cb func(interface{}) bool) {
|
||||||
|
for elem := range *set {
|
||||||
|
if cb(elem) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Iter() <-chan interface{} {
|
||||||
|
ch := make(chan interface{})
|
||||||
|
go func() {
|
||||||
|
for elem := range *set {
|
||||||
|
ch <- elem
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Iterator() *Iterator {
|
||||||
|
iterator, ch, stopCh := newIterator()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
L:
|
||||||
|
for elem := range *set {
|
||||||
|
select {
|
||||||
|
case <-stopCh:
|
||||||
|
break L
|
||||||
|
case ch <- elem:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return iterator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Equal(other Set) bool {
|
||||||
|
_ = other.(*threadUnsafeSet)
|
||||||
|
|
||||||
|
if set.Cardinality() != other.Cardinality() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for elem := range *set {
|
||||||
|
if !other.Contains(elem) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Clone() Set {
|
||||||
|
clonedSet := newThreadUnsafeSet()
|
||||||
|
for elem := range *set {
|
||||||
|
clonedSet.Add(elem)
|
||||||
|
}
|
||||||
|
return &clonedSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) String() string {
|
||||||
|
items := make([]string, 0, len(*set))
|
||||||
|
|
||||||
|
for elem := range *set {
|
||||||
|
items = append(items, fmt.Sprintf("%v", elem))
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
|
||||||
|
}
|
||||||
|
|
||||||
|
// String outputs a 2-tuple in the form "(A, B)".
|
||||||
|
func (pair OrderedPair) String() string {
|
||||||
|
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) Pop() interface{} {
|
||||||
|
for item := range *set {
|
||||||
|
delete(*set, item)
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) PowerSet() Set {
|
||||||
|
powSet := NewThreadUnsafeSet()
|
||||||
|
nullset := newThreadUnsafeSet()
|
||||||
|
powSet.Add(&nullset)
|
||||||
|
|
||||||
|
for es := range *set {
|
||||||
|
u := newThreadUnsafeSet()
|
||||||
|
j := powSet.Iter()
|
||||||
|
for er := range j {
|
||||||
|
p := newThreadUnsafeSet()
|
||||||
|
if reflect.TypeOf(er).Name() == "" {
|
||||||
|
k := er.(*threadUnsafeSet)
|
||||||
|
for ek := range *(k) {
|
||||||
|
p.Add(ek)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.Add(er)
|
||||||
|
}
|
||||||
|
p.Add(es)
|
||||||
|
u.Add(&p)
|
||||||
|
}
|
||||||
|
|
||||||
|
powSet = powSet.Union(&u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return powSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) CartesianProduct(other Set) Set {
|
||||||
|
o := other.(*threadUnsafeSet)
|
||||||
|
cartProduct := NewThreadUnsafeSet()
|
||||||
|
|
||||||
|
for i := range *set {
|
||||||
|
for j := range *o {
|
||||||
|
elem := OrderedPair{First: i, Second: j}
|
||||||
|
cartProduct.Add(elem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cartProduct
|
||||||
|
}
|
||||||
|
|
||||||
|
func (set *threadUnsafeSet) ToSlice() []interface{} {
|
||||||
|
keys := make([]interface{}, 0, set.Cardinality())
|
||||||
|
for elem := range *set {
|
||||||
|
keys = append(keys, elem)
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON creates a JSON array from the set, it marshals all elements
|
||||||
|
func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) {
|
||||||
|
items := make([]string, 0, set.Cardinality())
|
||||||
|
|
||||||
|
for elem := range *set {
|
||||||
|
b, err := json.Marshal(elem)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
items = append(items, string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON recreates a set from a JSON array, it only decodes
|
||||||
|
// primitive types. Numbers are decoded as json.Number.
|
||||||
|
func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error {
|
||||||
|
var i []interface{}
|
||||||
|
|
||||||
|
d := json.NewDecoder(bytes.NewReader(b))
|
||||||
|
d.UseNumber()
|
||||||
|
err := d.Decode(&i)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range i {
|
||||||
|
switch t := v.(type) {
|
||||||
|
case []interface{}, map[string]interface{}:
|
||||||
|
continue
|
||||||
|
default:
|
||||||
|
set.Add(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user