github.com/vpnishe/netstack@v1.10.6/tcpip/transport/icmp/icmp_packet_list.go (about) 1 package icmp 2 3 // ElementMapper provides an identity mapping by default. 4 // 5 // This can be replaced to provide a struct that maps elements to linker 6 // objects, if they are not the same. An ElementMapper is not typically 7 // required if: Linker is left as is, Element is left as is, or Linker and 8 // Element are the same type. 9 type icmpPacketElementMapper struct{} 10 11 // linkerFor maps an Element to a Linker. 12 // 13 // This default implementation should be inlined. 14 // 15 //go:nosplit 16 func (icmpPacketElementMapper) linkerFor(elem *icmpPacket) *icmpPacket { return elem } 17 18 // List is an intrusive list. Entries can be added to or removed from the list 19 // in O(1) time and with no additional memory allocations. 20 // 21 // The zero value for List is an empty list ready to use. 22 // 23 // To iterate over a list (where l is a List): 24 // for e := l.Front(); e != nil; e = e.Next() { 25 // // do something with e. 26 // } 27 // 28 // +stateify savable 29 type icmpPacketList struct { 30 head *icmpPacket 31 tail *icmpPacket 32 } 33 34 // Reset resets list l to the empty state. 35 func (l *icmpPacketList) Reset() { 36 l.head = nil 37 l.tail = nil 38 } 39 40 // Empty returns true iff the list is empty. 41 func (l *icmpPacketList) Empty() bool { 42 return l.head == nil 43 } 44 45 // Front returns the first element of list l or nil. 46 func (l *icmpPacketList) Front() *icmpPacket { 47 return l.head 48 } 49 50 // Back returns the last element of list l or nil. 51 func (l *icmpPacketList) Back() *icmpPacket { 52 return l.tail 53 } 54 55 // PushFront inserts the element e at the front of list l. 56 func (l *icmpPacketList) PushFront(e *icmpPacket) { 57 icmpPacketElementMapper{}.linkerFor(e).SetNext(l.head) 58 icmpPacketElementMapper{}.linkerFor(e).SetPrev(nil) 59 60 if l.head != nil { 61 icmpPacketElementMapper{}.linkerFor(l.head).SetPrev(e) 62 } else { 63 l.tail = e 64 } 65 66 l.head = e 67 } 68 69 // PushBack inserts the element e at the back of list l. 70 func (l *icmpPacketList) PushBack(e *icmpPacket) { 71 icmpPacketElementMapper{}.linkerFor(e).SetNext(nil) 72 icmpPacketElementMapper{}.linkerFor(e).SetPrev(l.tail) 73 74 if l.tail != nil { 75 icmpPacketElementMapper{}.linkerFor(l.tail).SetNext(e) 76 } else { 77 l.head = e 78 } 79 80 l.tail = e 81 } 82 83 // PushBackList inserts list m at the end of list l, emptying m. 84 func (l *icmpPacketList) PushBackList(m *icmpPacketList) { 85 if l.head == nil { 86 l.head = m.head 87 l.tail = m.tail 88 } else if m.head != nil { 89 icmpPacketElementMapper{}.linkerFor(l.tail).SetNext(m.head) 90 icmpPacketElementMapper{}.linkerFor(m.head).SetPrev(l.tail) 91 92 l.tail = m.tail 93 } 94 95 m.head = nil 96 m.tail = nil 97 } 98 99 // InsertAfter inserts e after b. 100 func (l *icmpPacketList) InsertAfter(b, e *icmpPacket) { 101 a := icmpPacketElementMapper{}.linkerFor(b).Next() 102 icmpPacketElementMapper{}.linkerFor(e).SetNext(a) 103 icmpPacketElementMapper{}.linkerFor(e).SetPrev(b) 104 icmpPacketElementMapper{}.linkerFor(b).SetNext(e) 105 106 if a != nil { 107 icmpPacketElementMapper{}.linkerFor(a).SetPrev(e) 108 } else { 109 l.tail = e 110 } 111 } 112 113 // InsertBefore inserts e before a. 114 func (l *icmpPacketList) InsertBefore(a, e *icmpPacket) { 115 b := icmpPacketElementMapper{}.linkerFor(a).Prev() 116 icmpPacketElementMapper{}.linkerFor(e).SetNext(a) 117 icmpPacketElementMapper{}.linkerFor(e).SetPrev(b) 118 icmpPacketElementMapper{}.linkerFor(a).SetPrev(e) 119 120 if b != nil { 121 icmpPacketElementMapper{}.linkerFor(b).SetNext(e) 122 } else { 123 l.head = e 124 } 125 } 126 127 // Remove removes e from l. 128 func (l *icmpPacketList) Remove(e *icmpPacket) { 129 prev := icmpPacketElementMapper{}.linkerFor(e).Prev() 130 next := icmpPacketElementMapper{}.linkerFor(e).Next() 131 132 if prev != nil { 133 icmpPacketElementMapper{}.linkerFor(prev).SetNext(next) 134 } else { 135 l.head = next 136 } 137 138 if next != nil { 139 icmpPacketElementMapper{}.linkerFor(next).SetPrev(prev) 140 } else { 141 l.tail = prev 142 } 143 } 144 145 // Entry is a default implementation of Linker. Users can add anonymous fields 146 // of this type to their structs to make them automatically implement the 147 // methods needed by List. 148 // 149 // +stateify savable 150 type icmpPacketEntry struct { 151 next *icmpPacket 152 prev *icmpPacket 153 } 154 155 // Next returns the entry that follows e in the list. 156 func (e *icmpPacketEntry) Next() *icmpPacket { 157 return e.next 158 } 159 160 // Prev returns the entry that precedes e in the list. 161 func (e *icmpPacketEntry) Prev() *icmpPacket { 162 return e.prev 163 } 164 165 // SetNext assigns 'entry' as the entry that follows e in the list. 166 func (e *icmpPacketEntry) SetNext(elem *icmpPacket) { 167 e.next = elem 168 } 169 170 // SetPrev assigns 'entry' as the entry that precedes e in the list. 171 func (e *icmpPacketEntry) SetPrev(elem *icmpPacket) { 172 e.prev = elem 173 }