// simple-list project slist.go package slist import ( "fmt" "portale-stac.it/packages/collections" ) type SNode struct { data interface{} next *SNode } func (self *SNode) Data() interface{} { return self.data } type SList struct { count uint32 first *SNode last *SNode } func NewSimpleList() (list *SList) { list = &SList{0, nil, nil} return } func (self *SList) Len() uint32 { return self.count } func (self *SList) Empty() bool { return self.count == 0 } func (self *SList) PushFront(data interface{}) *SNode { self.first = &SNode{data, self.first} if self.last == nil { self.last = self.first } self.count++ return self.first } func (self *SList) PushBack(data interface{}) (node *SNode) { node = &SNode{data, nil} if self.last != nil { self.last.next = node } self.last = node if self.first == nil { self.first = node } self.count++ return } func (self *SList) FirstNode() (node *SNode, err error) { if self.first != nil { node = self.first } else { err = errorListEmpty() } return } func (self *SList) First() (data interface{}, err error) { node, err := self.FirstNode() if err == nil { data = node.data } else { err = errorListEmpty() } return } func (self *SList) LastNode() (node *SNode, err error) { if self.last != nil { node = self.last } else { err = errorListEmpty() } return } func (self *SList) Last() (data interface{}, err error) { node, err := self.LastNode() if err == nil { data = node.data } return } func (self *SList) NodeAt(index uint32) (node *SNode, err error) { if self.count == 0 { err = errorListEmpty() } else if index > self.count { err = errorOutOfRange() } else if index == self.count-1 { node = self.last } else { current := self.first for pos := uint32(0); pos < index; pos++ { current = current.next } node = current } return } func (self *SList) At(index uint32) (data interface{}, err error) { node, err := self.NodeAt(index) if err == nil { data = node.data } return } func (self *SList) Insert(index uint32, data interface{}) *SNode { var prev *SNode prev = nil current := self.first for pos := uint32(0); current != nil && pos < index; pos++ { prev = current current = current.next } node := &SNode{data, current} if prev != nil { prev.next = node } if self.first == current { self.first = node } if node.next == nil { self.last = node } self.count++ return node } func (self *SList) PushBackStringArray(items []string) { for _, v := range items { self.PushBack(v) } } type TraverseOperator func(index uint32, elem interface{}, userData interface{}) (err error) func (self *SList) Traverse(op TraverseOperator, user_data interface{}) (err error) { index := uint32(0) for current := self.first; current != nil; current = current.next { err = op(index, current.data, user_data) if err != nil { break } index++ } return } func (self *SList) Traverse2(observer collections.Observer, abortOnError bool) (err error) { index := uint32(0) for current := self.first; current != nil; current = current.next { err = observer.Observe(current, index) if err != nil && abortOnError { break } index++ } return } type EqualFunc func(current, target any) bool func (self *SList) FindFirst(eqFunc EqualFunc, targetData any) (targetNode *SNode) { for current := self.first; current != nil && targetNode == nil; current = current.next { if eqFunc(current.data, targetData) { targetNode = current } } return } func (self *SList) FindNext(eqFunc EqualFunc, startNode *SNode) (targetNode *SNode) { if startNode != nil { for current := startNode.next; current != nil && targetNode == nil; current = current.next { if eqFunc(current.data, startNode.Data()) { targetNode = current } } } return } type DataFeeder func(user_data interface{}) interface{} type NodeObserver func(node *SNode, index uint32, userData interface{}) func (self *SList) FeedTail(feeder DataFeeder, feederUserData interface{}, observer NodeObserver, observerUserData interface{}) (count uint32) { count = 0 for item := feeder(feederUserData); item != nil; item = feeder(feederUserData) { // fmt.Println("Item", count, item) node := self.PushBack(item) if observer != nil { observer(node, count, observerUserData) } count++ } return } func (self *SList) FeedTail2(feeder collections.Feeder, observer collections.Observer, abortOnError bool) (count uint32, err error) { count = 0 // item := feeder.Next() for item, err1 := feeder.Next(); item != nil; item, err1 = feeder.Next() { if err1 != nil { if err == nil { err = err1 } if abortOnError { break } } // fmt.Println("Item", count, item) node := self.PushBack(item) if observer != nil { observer.Observe(node, count) } count++ } return } // func (self *SList) FeedTail2(feeder collections.Feeder, observer NodeObserver, observerUserData interface{}, abortOnError bool) (count uint32, err error) { // count = 0 // // item := feeder.Next() // for item, err1 := feeder.Next(); item != nil; item, err1 = feeder.Next() { // if err1 != nil { // if err == nil { // err = err1 // } // if abortOnError { // break // } // } // // fmt.Println("Item", count, item) // node := self.PushBack(item) // if observer != nil { // observer(node, count, observerUserData) // } // count++ // } // return // } func errorListEmpty() error { return fmt.Errorf("List is empty") } func errorOutOfRange() error { return fmt.Errorf("Out of range") }