package ring_buffer
//import "core:fmt"
Ring_Buffer :: struct {
buf: []u8,
off: int,
len: int,
cap: int,
}
init :: proc(rb: ^Ring_Buffer, initial_size := 4096) {
rb.buf = make([]u8, initial_size)
rb.cap = initial_size
}
destroy :: proc(rb: ^Ring_Buffer) {
if rb.buf != nil {
delete(rb.buf)
}
}
append :: proc(rb: ^Ring_Buffer, buf: []u8, allocator := context.allocator) {
for rb.len + len(buf) > rb.cap {
grow(rb)
}
for i in 0 ..< len(buf) {
rb.buf[(rb.off + i) % rb.cap] = buf[i]
rb.len += 1
}
//fmt.printf("%v\nappended %d bytes, off: %d, len: %d\n", buf, len(buf), rb.off, rb.len)
}
grow :: proc(rb: ^Ring_Buffer, grow_mul := 2, allocator := context.allocator) {
cap := rb.cap * grow_mul
buf := make([]u8, cap)
if rb.off + rb.len <= rb.cap {
copy(buf, rb.buf[rb.off:rb.off + rb.len])
} else {
copied := copy(buf[0:], rb.buf[rb.off:])
copy(buf[copied:], rb.buf[:rb.len - copied])
}
rb.cap = cap
rb.off = 0
delete(rb.buf)
rb.buf = buf
//fmt.printf("grew by %d bytes, off: %d, len: %d, cap: %d\n", cap, rb.off, rb.len, rb.cap)
}
consume_front :: proc(rb: ^Ring_Buffer, n: int, allocator := context.allocator) -> []u8 {
//fmt.printf("consume %d\n", n)
if n <= 0 {
return nil
}
if n > rb.len {
rb.off = 0
rb.len = 0
return nil
}
result := make([]u8, rb.len)
if rb.off + n <= rb.cap {
copy(result, rb.buf[rb.off:rb.off + n])
} else {
copied := copy(result[0:], rb.buf[rb.off:])
copy(result[copied:], rb.buf[:n - copied])
}
rb.off = (rb.off + n) % rb.cap
rb.len -= n
//fmt.printf("%v\nconsumed %d bytes, off: %d, len: %d\n", result, n, rb.off, rb.len)
return result
}