blob: 5537fae1565afc0f7ba682126e5be3b270a58619 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package deque implements a deque using a circular array.
package deque
const (
initialQueueSize = 4
)
// T is the type of queues.
type T struct {
contents []interface{}
// Boundary cases.
// o If full, size==len and fx==bx
// o If empty, size==0 and fx==bx
// o On initialization, contents=nil, size==0, fx==bx.
size int // Number of elements in the queue.
fx int // Index of the first element.
bx int // Index one past the last element (the index of the last element is (bx-1)%len).
}
// Size returns the number of items in the queue.
func (q *T) Size() int {
return q.size
}
// Clear removes all the elements of the queue.
func (q *T) Clear() {
q.fx = 0
q.bx = 0
q.size = 0
q.contents = nil
}
// PushBack adds an element to the back of the queue.
func (q *T) PushBack(item interface{}) {
q.reserve()
q.contents[q.bx] = item
q.bx = (q.bx + 1) % len(q.contents)
q.size++
}
// PushFront adds an element to the front of the deque.
func (q *T) PushFront(item interface{}) {
q.reserve()
q.fx = (q.fx + len(q.contents) - 1) % len(q.contents)
q.contents[q.fx] = item
q.size++
}
// Front returns the first element of the deque, or nil if there is none.
func (q *T) Front() interface{} {
if q.size == 0 {
return nil
}
return q.contents[q.fx]
}
// Back returns the last element of the deque, or nil if there is none.
func (q *T) Back() interface{} {
if q.size == 0 {
return nil
}
return q.contents[(q.bx+len(q.contents)-1)%len(q.contents)]
}
// PopFront removes an element from the front of the queue and returns it.
func (q *T) PopFront() interface{} {
if q.size == 0 {
return nil
}
item := q.contents[q.fx]
q.contents[q.fx] = nil
q.fx = (q.fx + 1) % len(q.contents)
q.size--
return item
}
// PopBack removes an element from the front of the queue and returns it.
func (q *T) PopBack() interface{} {
if q.size == 0 {
return nil
}
q.bx = (q.bx + len(q.contents) - 1) % len(q.contents)
item := q.contents[q.bx]
q.contents[q.bx] = nil
q.size--
return item
}
// Iter iterates over the elements of the deque. f should return false to
// terminate the iteration early.
func (q *T) Iter(f func(item interface{}) bool) {
for i := 0; i != q.size; i++ {
ix := (q.fx + i) % len(q.contents)
if !f(q.contents[ix]) {
break
}
}
}
// Reserve space for at least one additional element.
func (q *T) reserve() {
if q.size == len(q.contents) {
if q.contents == nil {
q.contents = make([]interface{}, initialQueueSize)
return
}
contents := make([]interface{}, q.size*2)
i := copy(contents[:], q.contents[q.fx:])
copy(contents[i:], q.contents[:q.fx])
q.contents = contents
q.fx = 0
q.bx = q.size
}
}