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 }