summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/zfjagann/golang-ring/ring.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zfjagann/golang-ring/ring.go')
-rw-r--r--vendor/github.com/zfjagann/golang-ring/ring.go53
1 files changed, 49 insertions, 4 deletions
diff --git a/vendor/github.com/zfjagann/golang-ring/ring.go b/vendor/github.com/zfjagann/golang-ring/ring.go
index 345ee8cd..308c97cc 100644
--- a/vendor/github.com/zfjagann/golang-ring/ring.go
+++ b/vendor/github.com/zfjagann/golang-ring/ring.go
@@ -160,7 +160,11 @@ func (r *Ring) get(p int) interface{} {
// returns the modified index of an unmodified index
func (r *Ring) mod(p int) int {
- return p % len(r.buff)
+ v := p % len(r.buff)
+ for v < 0 { // this bit fixes negative indices
+ v += len(r.buff)
+ }
+ return v
}
func (r *Ring) checkInit() {
@@ -178,12 +182,53 @@ func (r *Ring) checkInit() {
func (r *Ring) extend(size int) {
if size == len(r.buff) {
return
- } else if size < len(r.buff) {
- r.buff = r.buff[0:size]
}
+
+ if size < len(r.buff) {
+ // shrink the buffer
+ if r.head == -1 {
+ // nothing in the buffer, so just shrink it directly
+ r.buff = r.buff[0:size]
+ } else {
+ newb := make([]interface{}, 0, size)
+ // buffer has stuff in it, so save the most recent stuff...
+ // start at HEAD-SIZE-1 and walk forwards
+ for i := size - 1; i >= 0; i-- {
+ idx := r.mod(r.head - i)
+ newb = append(newb, r.buff[idx])
+ }
+ // reset head and tail to proper values
+ r.head = len(newb) - 1
+ r.tail = 0
+ r.buff = newb
+ }
+ return
+ }
+
+ // grow the buffer
newb := make([]interface{}, size-len(r.buff))
for i := range newb {
newb[i] = nil
}
- r.buff = append(r.buff, newb...)
+ if r.head == -1 {
+ // nothing in the buffer
+ r.buff = append(r.buff, newb...)
+ } else if r.head >= r.tail {
+ // growing at the end is safe
+ r.buff = append(r.buff, newb...)
+ } else {
+ // buffer has stuff that wraps around the end
+ // have to rearrange the buffer so the contents are still in order
+ part1 := make([]interface{}, len(r.buff[:r.head+1]))
+ copy(part1, r.buff[:r.head+1])
+ part2 := make([]interface{}, len(r.buff[r.tail:]))
+ copy(part2, r.buff[r.tail:])
+ r.buff = append(r.buff, newb...)
+ newTail := r.mod(r.tail + len(newb))
+ r.tail = newTail
+ copy(r.buff[:r.head+1], part1)
+ copy(r.buff[r.head+1:r.tail], newb)
+ copy(r.buff[r.tail:], part2)
+
+ }
}