summaryrefslogtreecommitdiff
path: root/vendor/github.com/c4milo/gotoolkit/stack.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/c4milo/gotoolkit/stack.go')
-rw-r--r--vendor/github.com/c4milo/gotoolkit/stack.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/vendor/github.com/c4milo/gotoolkit/stack.go b/vendor/github.com/c4milo/gotoolkit/stack.go
new file mode 100644
index 00000000..8314cb37
--- /dev/null
+++ b/vendor/github.com/c4milo/gotoolkit/stack.go
@@ -0,0 +1,110 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+package gotoolkit
+
+import "errors"
+
+// Stack defines an interface for implementing Stack data structures.
+type Stack interface {
+ Push(item interface{})
+ Pop() (interface{}, error)
+ Peek() (interface{}, error)
+ IsEmpty() bool
+ Size() uint64
+}
+
+type node struct {
+ item interface{}
+ next *node
+}
+
+// ListStack is a stack backed by a linked list, it may be faster than SliceStack
+// but consumes more memory and has worse cache locality than SliceQueue.
+type ListStack struct {
+ first *node
+ size uint64
+}
+
+// Push adds an element to the top of the stack.
+func (s *ListStack) Push(item interface{}) {
+ oldFirst := s.first
+ s.first = new(node)
+ s.first.item = item
+ s.first.next = oldFirst
+ s.size++
+}
+
+// Peek returns the latest added element without removing it from the stack.
+func (s *ListStack) Peek() (interface{}, error) {
+ if s.IsEmpty() {
+ return nil, errors.New("unable to peek element, stack is empty")
+ }
+
+ return s.first.item, nil
+}
+
+// Pop removes and return the latest added element from the stack.
+func (s *ListStack) Pop() (interface{}, error) {
+ if s.IsEmpty() {
+ return nil, errors.New("unable to pop element, stack is empty")
+ }
+ item := s.first.item
+ s.first = s.first.next
+ s.size--
+ return item, nil
+}
+
+// IsEmpty returns whether or not the stack is empty.
+func (s *ListStack) IsEmpty() bool {
+ return s.first == nil
+}
+
+// Size returns the number of elements in the stack.
+func (s *ListStack) Size() uint64 {
+ return s.size
+}
+
+// SliceStack implements a stack backed by a growing slice. Useful for memory
+// constrained environments. It also has better cache locality.
+type SliceStack struct {
+ size uint64
+ backing []interface{}
+}
+
+// Push adds an element to the top of the stack.
+func (s *SliceStack) Push(item interface{}) {
+ s.size++
+ s.backing = append(s.backing, item)
+}
+
+// Peek returns the latest added element without removing it from the stack.
+func (s *SliceStack) Peek() (interface{}, error) {
+ if s.IsEmpty() {
+ return nil, errors.New("unable to peek element, stack is empty")
+ }
+ return s.backing[s.size-1], nil
+}
+
+// Pop removes and return the latest added element from the stack.
+func (s *SliceStack) Pop() (interface{}, error) {
+ if s.IsEmpty() {
+ return nil, errors.New("unable to pop element, stack is empty")
+ }
+
+ s.size--
+ item := s.backing[s.size]
+ s.backing = s.backing[0:s.size]
+ return item, nil
+}
+
+// IsEmpty returns whether or not the stack is empty.
+func (s *SliceStack) IsEmpty() bool {
+ return len(s.backing) == 0
+}
+
+// Size returns the number of elements in the stack.
+func (s *SliceStack) Size() uint64 {
+ return s.size
+}