From 724d915e9586aad746f67341c1f34f05c7c418d9 Mon Sep 17 00:00:00 2001 From: Alberto Bertogli Date: Fri, 6 May 2016 22:49:16 +0100 Subject: [PATCH] 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 ++++++++++++++++++++++++++++++++ internal/set/set_test.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 internal/set/set.go create mode 100644 internal/set/set_test.go 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) + } + } +}