mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-22 07:14:15 +08:00
Feature: Add Go TCP server framework
This commit is contained in:
185
server/go/buffer/buffer.go
Normal file
185
server/go/buffer/buffer.go
Normal file
@@ -0,0 +1,185 @@
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Buffer is a thread-safe dynamic buffer for network I/O
|
||||
type Buffer struct {
|
||||
data []byte
|
||||
mu sync.RWMutex
|
||||
offset int // read offset for lazy compaction
|
||||
}
|
||||
|
||||
// New creates a new buffer with optional initial capacity
|
||||
func New(capacity ...int) *Buffer {
|
||||
cap := 4096
|
||||
if len(capacity) > 0 && capacity[0] > 0 {
|
||||
cap = capacity[0]
|
||||
}
|
||||
return &Buffer{
|
||||
data: make([]byte, 0, cap),
|
||||
}
|
||||
}
|
||||
|
||||
// Write appends data to the buffer
|
||||
func (b *Buffer) Write(p []byte) (int, error) {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
b.data = append(b.data, p...)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// WriteUint32 writes a uint32 in little-endian format
|
||||
func (b *Buffer) WriteUint32(v uint32) {
|
||||
buf := make([]byte, 4)
|
||||
binary.LittleEndian.PutUint32(buf, v)
|
||||
b.Write(buf)
|
||||
}
|
||||
|
||||
// Read reads and removes data from the buffer
|
||||
func (b *Buffer) Read(n int) []byte {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
available := len(b.data) - b.offset
|
||||
if n > available {
|
||||
n = available
|
||||
}
|
||||
if n <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]byte, n)
|
||||
copy(result, b.data[b.offset:b.offset+n])
|
||||
b.offset += n
|
||||
|
||||
// Compact when offset is large enough
|
||||
if b.offset > len(b.data)/2 && b.offset > 1024 {
|
||||
b.compact()
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// Peek returns data without removing it
|
||||
func (b *Buffer) Peek(n int) []byte {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
|
||||
available := len(b.data) - b.offset
|
||||
if n > available {
|
||||
n = available
|
||||
}
|
||||
if n <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]byte, n)
|
||||
copy(result, b.data[b.offset:b.offset+n])
|
||||
return result
|
||||
}
|
||||
|
||||
// PeekAt returns data at a specific offset without removing it
|
||||
func (b *Buffer) PeekAt(offset, n int) []byte {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
|
||||
start := b.offset + offset
|
||||
if start >= len(b.data) {
|
||||
return nil
|
||||
}
|
||||
|
||||
end := start + n
|
||||
if end > len(b.data) {
|
||||
end = len(b.data)
|
||||
}
|
||||
|
||||
result := make([]byte, end-start)
|
||||
copy(result, b.data[start:end])
|
||||
return result
|
||||
}
|
||||
|
||||
// Skip removes n bytes from the beginning
|
||||
func (b *Buffer) Skip(n int) int {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
|
||||
available := len(b.data) - b.offset
|
||||
if n > available {
|
||||
n = available
|
||||
}
|
||||
b.offset += n
|
||||
|
||||
// Compact when offset is large enough
|
||||
if b.offset > len(b.data)/2 && b.offset > 1024 {
|
||||
b.compact()
|
||||
}
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
// Len returns the length of unread data
|
||||
func (b *Buffer) Len() int {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
return len(b.data) - b.offset
|
||||
}
|
||||
|
||||
// Bytes returns all unread data without removing it
|
||||
func (b *Buffer) Bytes() []byte {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
|
||||
n := len(b.data) - b.offset
|
||||
if n <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make([]byte, n)
|
||||
copy(result, b.data[b.offset:])
|
||||
return result
|
||||
}
|
||||
|
||||
// Clear removes all data from the buffer
|
||||
func (b *Buffer) Clear() {
|
||||
b.mu.Lock()
|
||||
defer b.mu.Unlock()
|
||||
b.data = b.data[:0]
|
||||
b.offset = 0
|
||||
}
|
||||
|
||||
// compact moves remaining data to the beginning
|
||||
func (b *Buffer) compact() {
|
||||
if b.offset > 0 {
|
||||
remaining := len(b.data) - b.offset
|
||||
copy(b.data[:remaining], b.data[b.offset:])
|
||||
b.data = b.data[:remaining]
|
||||
b.offset = 0
|
||||
}
|
||||
}
|
||||
|
||||
// GetByte returns a single byte at offset
|
||||
func (b *Buffer) GetByte(offset int) byte {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
|
||||
idx := b.offset + offset
|
||||
if idx >= len(b.data) {
|
||||
return 0
|
||||
}
|
||||
return b.data[idx]
|
||||
}
|
||||
|
||||
// GetUint32 returns a uint32 at offset in little-endian format
|
||||
func (b *Buffer) GetUint32(offset int) uint32 {
|
||||
b.mu.RLock()
|
||||
defer b.mu.RUnlock()
|
||||
|
||||
idx := b.offset + offset
|
||||
if idx+4 > len(b.data) {
|
||||
return 0
|
||||
}
|
||||
return binary.LittleEndian.Uint32(b.data[idx : idx+4])
|
||||
}
|
||||
Reference in New Issue
Block a user