stack.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package winman
  2. // Stack represents a stack of unique items
  3. type Stack []interface{}
  4. // Push puts an element on the stack
  5. // if the item is already in the stack, this operation does nothing
  6. func (s *Stack) Push(newItem interface{}) {
  7. if newItem == nil {
  8. panic("cannot add nil item to stack")
  9. }
  10. for _, item := range *s {
  11. if item == newItem {
  12. return
  13. }
  14. }
  15. *s = append(*s, newItem)
  16. }
  17. // Pop pops the stack returning and removing the topmost element
  18. func (s *Stack) Pop() interface{} {
  19. lenItems := len(*s)
  20. if lenItems == 0 {
  21. return nil
  22. }
  23. var item interface{}
  24. item, *s = (*s)[lenItems-1], (*s)[:lenItems-1]
  25. return item
  26. }
  27. // Remove removes the given item from the stack
  28. // if the item does not exist, this function does nothing
  29. func (s *Stack) Remove(item interface{}) {
  30. i := s.IndexOf(item)
  31. if i != -1 {
  32. *s = append((*s)[:i], (*s)[i+1:]...)
  33. }
  34. }
  35. // Item returns the given item from the stack
  36. // returns nil if the index is out of bounds
  37. func (s Stack) Item(i int) interface{} {
  38. if i < 0 || i >= len(s) {
  39. return nil
  40. }
  41. return s[i]
  42. }
  43. // IndexOf searches the stack for the given item and returns its index
  44. func (s Stack) IndexOf(searchItem interface{}) int {
  45. for i, item := range s {
  46. if item == searchItem {
  47. return i
  48. }
  49. }
  50. return -1
  51. }
  52. // Move finds an item in the stack and places it at the given index,
  53. // shifting items up or down to make space
  54. func (s *Stack) Move(item interface{}, targetIndex int) {
  55. oldIndex := s.IndexOf(item)
  56. if oldIndex == -1 {
  57. return
  58. }
  59. lenS := len(*s)
  60. if targetIndex < 0 || targetIndex >= lenS {
  61. targetIndex = lenS - 1
  62. }
  63. newStack := make([]interface{}, lenS)
  64. for i, j := 0, 0; i < lenS; j++ {
  65. if j == oldIndex {
  66. j++
  67. }
  68. if i == targetIndex {
  69. j--
  70. } else {
  71. newStack[i] = (*s)[j]
  72. }
  73. i++
  74. }
  75. newStack[targetIndex] = item
  76. *s = newStack
  77. }
  78. // Find searches the stack top down for an item that meets the custom
  79. // criteria specified by the passed function
  80. func (s Stack) Find(f func(item interface{}) bool) interface{} {
  81. for i := len(s) - 1; i >= 0; i-- {
  82. item := s[i]
  83. if f(item) {
  84. return item
  85. }
  86. }
  87. return nil
  88. }