diff --git a/go.mod b/go.mod new file mode 100755 index 0000000..4f7f683 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module github.com/bloeys/nlookup + +go 1.18 diff --git a/nlookup.go b/nlookup.go new file mode 100644 index 0000000..b8e934b --- /dev/null +++ b/nlookup.go @@ -0,0 +1,108 @@ +package nlookup + +import ( + "fmt" + "strings" +) + +var _ fmt.Stringer = &NLookup[uint]{} + +type StorageType uint64 + +const StorageTypeBits = 64 + +type IntsIf interface { + uint | uint8 | uint16 | uint32 | uint64 +} + +type NLookup[T IntsIf] struct { + Data []StorageType +} + +func (n *NLookup[T]) Add(x T) { + + unitIndex := n.GetStorageUnitIndex(x) + if unitIndex >= n.Size() { + storageUnitsToAdd := unitIndex - n.Size() + 1 + n.Data = append(n.Data, make([]StorageType, storageUnitsToAdd)...) + } + + n.Data[unitIndex] |= 1 << (x % StorageTypeBits) +} + +func (n *NLookup[T]) Remove(x T) { + + unitIndex := n.GetStorageUnitIndex(x) + if unitIndex >= n.Size() { + return + } + + n.Data[unitIndex] ^= 1 << (x % StorageTypeBits) +} + +func (n *NLookup[T]) Contains(x T) bool { + + unitIndex := n.GetStorageUnitIndex(x) + if unitIndex >= n.Size() { + return false + } + + return n.Data[unitIndex]&(1<= 0 { + + byteToShow := uint8(x >> shiftAmount) + if shiftAmount > 0 { + b.WriteString(fmt.Sprintf("%08b ", byteToShow)) + } else { + b.WriteString(fmt.Sprintf("%08b", byteToShow)) + } + + shiftAmount -= 8 + } + b.WriteString(", ") + } + + return b.String() +} + +func NewNLookup[T IntsIf]() NLookup[T] { + + return NLookup[T]{ + Data: make([]StorageType, 1), + } +} + +func NewNLookupWithSize[T IntsIf](largestNum T) NLookup[T] { + return NLookup[T]{ + Data: make([]StorageType, largestNum/StorageTypeBits+1), + } +} diff --git a/nlookup_test.go b/nlookup_test.go new file mode 100755 index 0000000..d4f7916 --- /dev/null +++ b/nlookup_test.go @@ -0,0 +1,36 @@ +package nlookup_test + +import ( + "testing" + + "github.com/bloeys/nlookup" +) + +func TestNLookup(t *testing.T) { + + n := nlookup.NewNLookup[uint]() + + IsEq(t, 1, cap(n.Data)) + +} + +func AllTrue(t *testing.T, values ...bool) bool { + + for i := 0; i < len(values); i++ { + if !values[i] { + t.Errorf("Expected 'true' but got 'false'\n") + } + } + + return true +} + +func IsEq[T comparable](t *testing.T, expected, val T) bool { + + if val == expected { + return true + } + + t.Errorf("Expected '%v' but got '%v'\n", expected, val) + return false +}