Browse Source

Buffer.Prepend()

v2ray 9 năm trước cách đây
mục cha
commit
97a85f04ce
2 tập tin đã thay đổi với 43 bổ sung7 xóa
  1. 27 7
      common/alloc/buffer.go
  2. 16 0
      common/alloc/buffer_test.go

+ 27 - 7
common/alloc/buffer.go

@@ -5,6 +5,10 @@ import (
 	"sync"
 )
 
+const (
+	DefaultOffset = 16
+)
+
 func Release(buffer *Buffer) {
 	if buffer != nil {
 		buffer.Release()
@@ -22,9 +26,10 @@ func Len(buffer *Buffer) int {
 // the buffer into an internal buffer pool, in order to recreate a buffer more
 // quickly.
 type Buffer struct {
-	head  []byte
-	pool  *bufferPool
-	Value []byte
+	head   []byte
+	pool   *bufferPool
+	Value  []byte
+	offset int
 }
 
 // Release recycles the buffer into an internal buffer pool.
@@ -38,7 +43,8 @@ func (b *Buffer) Release() {
 // Clear clears the content of the buffer, results an empty buffer with
 // Len() = 0.
 func (b *Buffer) Clear() *Buffer {
-	b.Value = b.head[:0]
+	b.offset = DefaultOffset
+	b.Value = b.head[b.offset:b.offset]
 	return b
 }
 
@@ -54,6 +60,19 @@ func (b *Buffer) Append(data []byte) *Buffer {
 	return b
 }
 
+// Prepend prepends bytes in front of the buffer. Caller must ensure total bytes prepended is
+// no more than 16 bytes.
+func (b *Buffer) Prepend(data []byte) *Buffer {
+	newoffset := b.offset - len(data)
+	if newoffset < 0 {
+		newoffset = 0
+	}
+	copy(b.head[newoffset:], data)
+	b.Value = b.head[newoffset : b.offset+len(b.Value)]
+	b.offset = newoffset
+	return b
+}
+
 func (b *Buffer) Bytes() []byte {
 	return b.Value
 }
@@ -125,9 +144,10 @@ func (p *bufferPool) allocate() *Buffer {
 		b = p.allocator.Get().([]byte)
 	}
 	return &Buffer{
-		head:  b,
-		pool:  p,
-		Value: b,
+		head:   b,
+		pool:   p,
+		Value:  b[DefaultOffset:],
+		offset: DefaultOffset,
 	}
 }
 

+ 16 - 0
common/alloc/buffer_test.go

@@ -32,3 +32,19 @@ func TestBufferIsFull(t *testing.T) {
 	buffer.Clear()
 	assert.Bool(buffer.IsFull()).IsFalse()
 }
+
+func TestBufferPrepend(t *testing.T) {
+	v2testing.Current(t)
+
+	buffer := NewBuffer().Clear()
+	defer buffer.Release()
+
+	buffer.Append([]byte{'a', 'b', 'c'})
+	buffer.Prepend([]byte{'x', 'y', 'z'})
+
+	assert.Int(buffer.Len()).Equals(6)
+	assert.Bytes(buffer.Value).Equals([]byte("xyzabc"))
+
+	buffer.Prepend([]byte{'u', 'v', 'w'})
+	assert.Bytes(buffer.Value).Equals([]byte("uvwxyzabc"))
+}