git » chasquid » commit 724d915

Implement a string set data type

author Alberto Bertogli
2016-05-06 21:49:16 UTC
committer Alberto Bertogli
2016-05-06 22:00:55 UTC
parent 17c536f5e3aa52746d118150ea2603258a8a7c25

Implement a string set data type

We will need a few string sets in different places, create it as a separate
package for convenience.

For now, it only implements strings, but it may be extended to other data
types in the future.

internal/set/set.go +32 -0
internal/set/set_test.go +40 -0

diff --git a/internal/set/set.go b/internal/set/set.go
new file mode 100644
index 0000000..e53308a
--- /dev/null
+++ b/internal/set/set.go
@@ -0,0 +1,32 @@
+// Package set implement sets for various types. Well, only string for now :)
+package set
+
+type String struct {
+	m map[string]struct{}
+}
+
+func NewString(values ...string) *String {
+	s := &String{}
+	s.Add(values...)
+	return s
+}
+
+func (s *String) Add(values ...string) {
+	if s.m == nil {
+		s.m = map[string]struct{}{}
+	}
+
+	for _, v := range values {
+		s.m[v] = struct{}{}
+	}
+}
+
+func (s *String) Has(value string) bool {
+	// We explicitly allow s to be nil *in this function* to simplify callers'
+	// code.  Note that Add will not tolerate it, and will panic.
+	if s == nil || s.m == nil {
+		return false
+	}
+	_, ok := s.m[value]
+	return ok
+}
diff --git a/internal/set/set_test.go b/internal/set/set_test.go
new file mode 100644
index 0000000..e66dfc8
--- /dev/null
+++ b/internal/set/set_test.go
@@ -0,0 +1,40 @@
+package set
+
+import "testing"
+
+func TestString(t *testing.T) {
+	s1 := &String{}
+
+	// Test that Has works on a new set.
+	if s1.Has("x") {
+		t.Error("'x' is in the empty set")
+	}
+
+	s1.Add("a")
+	s1.Add("b", "ccc")
+
+	expectStrings(s1, []string{"a", "b", "ccc"}, []string{"notin"}, t)
+
+	s2 := NewString("a", "b", "c")
+	expectStrings(s2, []string{"a", "b", "c"}, []string{"notin"}, t)
+
+	// Test that Has works (and not panics) on a nil set.
+	var s3 *String
+	if s3.Has("x") {
+		t.Error("'x' is in the nil set")
+	}
+}
+
+func expectStrings(s *String, in []string, notIn []string, t *testing.T) {
+	for _, str := range in {
+		if !s.Has(str) {
+			t.Errorf("String %q not in set, it should be", str)
+		}
+	}
+
+	for _, str := range notIn {
+		if s.Has(str) {
+			t.Errorf("String %q is in the set, should not be", str)
+		}
+	}
+}