117 lines
1.6 KiB
Go
117 lines
1.6 KiB
Go
package dataext
|
|
|
|
import (
|
|
"errors"
|
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
|
"sync"
|
|
)
|
|
|
|
var ErrEmptyStack = errors.New("stack is empty")
|
|
|
|
type Stack[T any] struct {
|
|
lock *sync.Mutex
|
|
data []T
|
|
}
|
|
|
|
func NewStack[T any](threadsafe bool, initialCapacity int) *Stack[T] {
|
|
var lck *sync.Mutex = nil
|
|
if threadsafe {
|
|
lck = &sync.Mutex{}
|
|
}
|
|
return &Stack[T]{
|
|
lock: lck,
|
|
data: make([]T, 0, initialCapacity),
|
|
}
|
|
}
|
|
|
|
func (s *Stack[T]) Push(v T) {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
s.data = append(s.data, v)
|
|
}
|
|
|
|
func (s *Stack[T]) Pop() (T, error) {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
l := len(s.data)
|
|
if l == 0 {
|
|
return *new(T), ErrEmptyStack
|
|
}
|
|
|
|
result := s.data[l-1]
|
|
s.data = s.data[:l-1]
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (s *Stack[T]) OptPop() *T {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
l := len(s.data)
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
|
|
result := s.data[l-1]
|
|
s.data = s.data[:l-1]
|
|
|
|
return langext.Ptr(result)
|
|
}
|
|
|
|
func (s *Stack[T]) Peek() (T, error) {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
l := len(s.data)
|
|
|
|
if l == 0 {
|
|
return *new(T), ErrEmptyStack
|
|
}
|
|
|
|
return s.data[l-1], nil
|
|
}
|
|
|
|
func (s *Stack[T]) OptPeek() *T {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
l := len(s.data)
|
|
|
|
if l == 0 {
|
|
return nil
|
|
}
|
|
|
|
return langext.Ptr(s.data[l-1])
|
|
}
|
|
|
|
func (s *Stack[T]) Length() int {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
return len(s.data)
|
|
}
|
|
|
|
func (s *Stack[T]) Empty() bool {
|
|
if s.lock != nil {
|
|
s.lock.Lock()
|
|
defer s.lock.Unlock()
|
|
}
|
|
|
|
return len(s.data) == 0
|
|
}
|