diff --git a/debug/buffer/buffer.go b/debug/buffer/buffer.go new file mode 100644 index 00000000..20856582 --- /dev/null +++ b/debug/buffer/buffer.go @@ -0,0 +1,58 @@ +// Package buffer provides a simple ring buffer for storing local data +package buffer + +import ( + "sync" +) + +type Buffer struct { + size int + sync.RWMutex + vals []interface{} +} + +func (b *Buffer) Put(v interface{}) { + b.Lock() + defer b.Unlock() + + // append to values + b.vals = append(b.vals, v) + + // trim if bigger than size required + if len(b.vals) > b.size { + b.vals = b.vals[1:] + } +} + +// Get returns the last n entries +func (b *Buffer) Get(n int) []interface{} { + // reset any invalid values + if n > b.size || n < 0 { + n = b.size + } + + b.RLock() + defer b.RUnlock() + + // create a delta + delta := b.size - n + + // if all the values are less than delta + if len(b.vals) < delta { + return b.vals + } + + // return the delta set + return b.vals[delta:] +} + +func (b *Buffer) Size() int { + return b.size +} + +// New returns a new buffer of the given size +func New(i int) *Buffer { + return &Buffer{ + size: i, + } +} diff --git a/debug/buffer/buffer_test.go b/debug/buffer/buffer_test.go new file mode 100644 index 00000000..c70935ef --- /dev/null +++ b/debug/buffer/buffer_test.go @@ -0,0 +1,52 @@ +package buffer + +import ( + "testing" +) + +func TestBuffer(t *testing.T) { + b := New(10) + + // test one value + b.Put("foo") + v := b.Get(1) + + if val := v[0].(string); val != "foo" { + t.Fatalf("expected foo got %v", val) + } + + b = New(10) + + // test 10 values + for i := 0; i < 10; i++ { + b.Put(i) + } + + v = b.Get(10) + + for i := 0; i < 10; i++ { + val := v[i].(int) + + if val != i { + t.Fatalf("expected %d got %d", i, val) + } + } + + // test more values + + for i := 0; i < 10; i++ { + v := i * 2 + b.Put(v) + } + + v = b.Get(10) + + for i := 0; i < 10; i++ { + val := v[i].(int) + expect := i * 2 + if val != expect { + t.Fatalf("expected %d got %d", expect, val) + } + } + +}