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 }