------------------------------------------ implement copy reader ------------------------------------------ readCopy copies up to len(p) bytes from the buffer into p without exposing the underlying buffer to user code (flagReadExposed is not set). After copying, it releases consumed nodes where read
(p []byte)
| 87 | // After copying, it releases consumed nodes where readExposed is false. |
| 88 | // Nodes with readExposed are left for the next Release call. |
| 89 | func (b *UnsafeLinkBuffer) readCopy(p []byte) (n int) { |
| 90 | l := len(p) |
| 91 | if l == 0 || b.Len() == 0 { |
| 92 | return 0 |
| 93 | } |
| 94 | if has := b.Len(); has < l { |
| 95 | l = has |
| 96 | } |
| 97 | b.recalLen(-l) |
| 98 | |
| 99 | // copy from nodes |
| 100 | for ack := l; ack > 0; { |
| 101 | if b.read.Len() == 0 { |
| 102 | b.read = b.read.next |
| 103 | continue |
| 104 | } |
| 105 | rd := b.read.Len() |
| 106 | if rd >= ack { |
| 107 | n += copy(p[n:], b.read.buf[b.read.off:b.read.off+ack]) |
| 108 | b.read.off += ack |
| 109 | break |
| 110 | } |
| 111 | n += copy(p[n:], b.read.buf[b.read.off:]) |
| 112 | ack -= rd |
| 113 | b.read = b.read.next |
| 114 | } |
| 115 | |
| 116 | // advance read past empty nodes |
| 117 | for b.read != b.flush && b.read.Len() == 0 { |
| 118 | b.read = b.read.next |
| 119 | } |
| 120 | // release consumed nodes that are not readExposed. |
| 121 | // exposed nodes stay in the chain so Release() can free them later. |
| 122 | // |
| 123 | // Example: [exposed/consumed] → [not-exposed/consumed] → [read/partial] |
| 124 | // After: head → [exposed] → [read/partial] |
| 125 | // the middle node is detached and released. |
| 126 | var prev *linkBufferNode |
| 127 | newHead := b.read |
| 128 | for cur := b.head; cur != b.read; { |
| 129 | next := cur.next |
| 130 | if cur.readExposed() { |
| 131 | if prev == nil { |
| 132 | newHead = cur |
| 133 | } |
| 134 | prev = cur |
| 135 | } else { |
| 136 | cur.Release() |
| 137 | if prev != nil { |
| 138 | prev.next = next |
| 139 | } |
| 140 | } |
| 141 | cur = next |
| 142 | } |
| 143 | b.head = newHead |
| 144 | return n |
| 145 | } |
| 146 |