Skip to content

Commit

Permalink
refactor(terminal): improve stack, prepare for CSIU, #74
Browse files Browse the repository at this point in the history
  • Loading branch information
ericwq committed Aug 15, 2024
1 parent fad5dd1 commit bf55ef3
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 9 deletions.
37 changes: 30 additions & 7 deletions terminal/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,24 @@ import (

var (
ErrEmptyStack = errors.New("empty stack")
ErrLastData = errors.New("last data in stack")
ErrLastItem = errors.New("last item in stack")
)

type stack[V any] struct {
type stack[V comparable] struct {
data []V
max int
sync.Mutex
}

// create stack with max items,
func NewStack[V any](max int) *stack[V] {
// create LIFO stack with max items
func NewStack[V comparable](max int) *stack[V] {
s := &stack[V]{}
s.max = max
s.data = make([]V, 0, max)
return s
}

// push the new data item.
// push new item input stack.
//
// If a push request is received and the stack is full, the oldest entry from
// the stack is evicted.
Expand All @@ -45,7 +45,7 @@ func (s *stack[V]) Push(v V) int {
return len(s.data)
}

// pop the last data item.
// pop last item from stack.
//
// If a pop request is received that empties the stack, report ErrLastData.
// if a pop request is received and the stack is empty, report ErrEmptyStack.
Expand All @@ -61,8 +61,31 @@ func (s *stack[V]) Pop() (last V, err error) {
last = s.data[pos-1]
s.data = s.data[:pos-1]
if len(s.data) == 0 {
err = ErrLastData
err = ErrLastItem
}

return last, err
}

func (s *stack[V]) Clone() *stack[V] {
clone := NewStack[V](s.max)
clone.data = make([]V, s.max)
copy(clone.data, s.data)
return clone
}

func (s *stack[V]) Equal(c *stack[V]) bool {
if s.max != c.max {
return false
}
if len(s.data) != len(c.data) {
return false
}
for i := range s.data {
if s.data[i] != c.data[i] {
return false
}
}

return true
}
48 changes: 46 additions & 2 deletions terminal/stack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,57 @@ func TestStack_Oversie_Empty(t *testing.T) {
for i := len(expect) - 1; i >= 0; i-- {
got, _ := s.Pop()
if got != expect[i] {
t.Errorf("stack oversize expect %d pop %c, got %c\n", i, expect[i], got)
t.Errorf("stack oversize: expect %d pop %c, got %c\n", i, expect[i], got)
}
}

// empty pop
_, err := s.Pop()
if !errors.Is(err, ErrEmptyStack) {
t.Errorf("stack empty pop expect %s, got %s\n", ErrEmptyStack, err)
t.Errorf("stack empty pop: expect %s, got %s\n", ErrEmptyStack, err)
}

// push one item into stack
s.Push('x')

x, err := s.Pop()
if !errors.Is(err, ErrLastItem) {
t.Errorf("stack pop last item: expect %s, got %s\n", ErrLastItem, err)
}
if x != 'x' {
t.Errorf("stack pop last item: expect %c, got %c\n", 'x', x)
}
}

func TestStack_Equal(t *testing.T) {
data := []string{"first", "second", "third"}
s := NewStack[string](len(data))
for i := range data {
s.Push(data[i])
}

s2 := s.Clone()

// same stack compare
if !s.Equal(s2) {
t.Errorf("stack equal: expect true, got false\n")
}

// empty stack compare
s3 := NewStack[string](len(data))
if s.Equal(s3) {
t.Errorf("stack equal: expect false, got true\n")
}

// different item compare
s2.data[2] = "forth"
if s.Equal(s2) {
t.Errorf("stack equal: expect false, got true\n")
}

// diff max compare
s4 := NewStack[string](len(data) - 1)
if s.Equal(s4) {
t.Errorf("stack equal: expect false, got true\n")
}
}

0 comments on commit bf55ef3

Please sign in to comment.