From 6ef77158e3dc8939e89c015d1e592f5e798948f8 Mon Sep 17 00:00:00 2001 From: Simone Gotti Date: Thu, 21 Feb 2019 16:32:27 +0100 Subject: [PATCH] Add slice utils --- go.sum | 9 ---- internal/util/slice.go | 85 +++++++++++++++++++++++++++++++ internal/util/slice_test.go | 99 +++++++++++++++++++++++++++++++++++++ internal/util/string.go | 44 +++++++++++++++++ 4 files changed, 228 insertions(+), 9 deletions(-) create mode 100644 internal/util/slice.go create mode 100644 internal/util/slice_test.go create mode 100644 internal/util/string.go diff --git a/go.sum b/go.sum index 99af4af..54a3c3f 100644 --- a/go.sum +++ b/go.sum @@ -2,7 +2,6 @@ github.com/Masterminds/squirrel v1.1.0 h1:baP1qLdoQCeTw3ifCdOq2dkYc6vGcmRdaociKL github.com/Masterminds/squirrel v1.1.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -16,7 +15,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumC github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -50,13 +48,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.4.1 h1:pX7cnDwSSmG0dR9yNjCQSSpmsJOqFdT github.com/grpc-ecosystem/grpc-gateway v1.4.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jtolds/gls v4.2.1+incompatible h1:fSuqC+Gmlu6l/ZYAoZzx2pyucC8Xza35fpRVWLVmUEE= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kr/pty v1.0.0 h1:jR04h3bskdxb8xt+5B6MoxPwDhMCe0oEgxug4Ca1YSA= github.com/kr/pty v1.0.0/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= @@ -64,9 +60,7 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= @@ -104,7 +98,6 @@ github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c h1:Ho+uVpke github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -131,11 +124,9 @@ golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9 h1:mKdxBk7AujPs8kU4m80U72y/zjbZ3UcXC7dClwKbUI0= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/internal/util/slice.go b/internal/util/slice.go new file mode 100644 index 0000000..4bfd609 --- /dev/null +++ b/internal/util/slice.go @@ -0,0 +1,85 @@ +// Copyright 2019 Sorint.lab +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import "sort" + +func StringInSlice(s []string, e string) bool { + for _, v := range s { + if v == e { + return true + } + } + return false +} + +// CompareStringSlice compares two slices of strings, a nil slice is considered an empty one +func CompareStringSlice(a []string, b []string) bool { + if len(a) != len(b) { + return false + } + + for i, v := range a { + if v != b[i] { + return false + } + } + return true +} + +// CompareStringSliceNoOrder compares two slices of strings regardless of their order, a nil slice is considered an empty one +func CompareStringSliceNoOrder(a []string, b []string) bool { + if len(a) != len(b) { + return false + } + + // This isn't the faster way but it's cleaner and enough for us + + // Take a copy of the original slice + a = append([]string(nil), a...) + b = append([]string(nil), b...) + + sort.Sort(sort.StringSlice(a)) + sort.Sort(sort.StringSlice(b)) + + for i, v := range a { + if v != b[i] { + return false + } + } + return true +} + +// CommonElements return the common elements in two slices of strings +func CommonElements(a []string, b []string) []string { + common := []string{} + for _, v := range a { + if StringInSlice(b, v) { + common = append(common, v) + } + } + return common +} + +// Difference returns elements in a - b +func Difference(a []string, b []string) []string { + diff := []string{} + for _, v := range a { + if !StringInSlice(b, v) { + diff = append(diff, v) + } + } + return diff +} diff --git a/internal/util/slice_test.go b/internal/util/slice_test.go new file mode 100644 index 0000000..ead2b5e --- /dev/null +++ b/internal/util/slice_test.go @@ -0,0 +1,99 @@ +// Copyright 2019 Sorint.lab +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import "testing" + +func TestCompareStringSlice(t *testing.T) { + tests := []struct { + a []string + b []string + ok bool + }{ + {[]string{}, []string{}, true}, + {[]string{"", ""}, []string{""}, false}, + {[]string{"", ""}, []string{"", ""}, true}, + {[]string{"a", "b"}, []string{"a", "b"}, true}, + {[]string{"a", "b"}, []string{"b", "a"}, false}, + {[]string{"a", "b", "c"}, []string{"a", "b"}, false}, + {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, true}, + {[]string{"a", "b", "c"}, []string{"b", "c", "a"}, false}, + {[]string{"a", "b", "c", "a"}, []string{"a", "c", "b", "b"}, false}, + {[]string{"a", "b", "c", "a"}, []string{"a", "c", "b", "b"}, false}, + } + + for i, tt := range tests { + ok := CompareStringSlice(tt.a, tt.b) + if ok != tt.ok { + t.Errorf("%d: got %t but wanted: %t a: %v, b: %v", i, ok, tt.ok, tt.a, tt.b) + } + } +} + +func TestCompareStringSliceNoOrder(t *testing.T) { + tests := []struct { + a []string + b []string + ok bool + }{ + {[]string{}, []string{}, true}, + {[]string{"", ""}, []string{""}, false}, + {[]string{"", ""}, []string{"", ""}, true}, + {[]string{"a", "b"}, []string{"a", "b"}, true}, + {[]string{"a", "b"}, []string{"b", "a"}, true}, + {[]string{"a", "b", "c"}, []string{"a", "b"}, false}, + {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, true}, + {[]string{"a", "b", "c"}, []string{"b", "c", "a"}, true}, + {[]string{"a", "b", "c", "a"}, []string{"a", "c", "b", "b"}, false}, + {[]string{"a", "b", "c", "a"}, []string{"a", "c", "b", "b"}, false}, + } + + for i, tt := range tests { + ok := CompareStringSliceNoOrder(tt.a, tt.b) + if ok != tt.ok { + t.Errorf("%d: got %t but wanted: %t a: %v, b: %v", i, ok, tt.ok, tt.a, tt.b) + } + } +} + +func TestDifference(t *testing.T) { + tests := []struct { + a []string + b []string + r []string + }{ + {[]string{}, []string{}, []string{}}, + {[]string{"", ""}, []string{""}, []string{}}, + {[]string{"", ""}, []string{"", ""}, []string{}}, + {[]string{"", ""}, []string{"a", "", "b"}, []string{}}, + {[]string{"a", "b"}, []string{"a", "b"}, []string{}}, + {[]string{"a", "b"}, []string{"b", "a"}, []string{}}, + {[]string{"a", "b", "c"}, []string{}, []string{"a", "b", "c"}}, + {[]string{"a", "b", "c"}, []string{"a", "b"}, []string{"c"}}, + {[]string{"a", "b"}, []string{"a", "b", "c"}, []string{}}, + {[]string{"a", "b"}, []string{"c", "a", "b"}, []string{}}, + {[]string{"a", "b", "c"}, []string{"a", "b", "c"}, []string{}}, + {[]string{"a", "b", "c"}, []string{"b", "c", "a"}, []string{}}, + {[]string{"a", "b", "c", "a"}, []string{"a", "c", "b", "b"}, []string{}}, + {[]string{"a", "b", "c", "a"}, []string{"a", "c", "b", "b"}, []string{}}, + } + + for i, tt := range tests { + r := Difference(tt.a, tt.b) + if !CompareStringSliceNoOrder(r, tt.r) { + t.Errorf("%d: got %v but wanted: %v a: %v, b: %v", i, r, tt.r, tt.a, tt.b) + } + } +} diff --git a/internal/util/string.go b/internal/util/string.go new file mode 100644 index 0000000..18e7c87 --- /dev/null +++ b/internal/util/string.go @@ -0,0 +1,44 @@ +// Copyright 2019 Sorint.lab +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied +// See the License for the specific language governing permissions and +// limitations under the License. + +package util + +import ( + "bufio" + "io" + "strings" +) + +func CountLines(s string) (uint, error) { + count := uint(0) + + // use a reader instead of a scanner + br := bufio.NewReader(strings.NewReader(s)) + + stop := false + for { + if stop { + break + } + _, err := br.ReadBytes('\n') + if err != nil { + if err != io.EOF { + return 0, err + } + stop = true + } + count++ + } + return count, nil +}