71 lines
1.4 KiB
Odin
71 lines
1.4 KiB
Odin
|
|
package main
|
||
|
|
|
||
|
|
import "core:strings"
|
||
|
|
|
||
|
|
Frame_Error :: enum {
|
||
|
|
None,
|
||
|
|
Too_Large,
|
||
|
|
}
|
||
|
|
|
||
|
|
Line_Framer :: struct {
|
||
|
|
buffer: [dynamic]byte,
|
||
|
|
}
|
||
|
|
|
||
|
|
framer_init :: proc(framer: ^Line_Framer, allocator := context.allocator) {
|
||
|
|
framer.buffer = make([dynamic]byte, 0, 256, allocator)
|
||
|
|
}
|
||
|
|
|
||
|
|
framer_destroy :: proc(framer: ^Line_Framer) {
|
||
|
|
delete(framer.buffer)
|
||
|
|
framer.buffer = nil
|
||
|
|
}
|
||
|
|
|
||
|
|
destroy_frames :: proc(frames: [dynamic]string) {
|
||
|
|
for frame in frames {
|
||
|
|
delete(frame)
|
||
|
|
}
|
||
|
|
delete(frames)
|
||
|
|
}
|
||
|
|
|
||
|
|
framer_push :: proc(
|
||
|
|
framer: ^Line_Framer,
|
||
|
|
data: []byte,
|
||
|
|
allocator := context.allocator,
|
||
|
|
) -> (frames: [dynamic]string, err: Frame_Error) {
|
||
|
|
frames = make([dynamic]string, 0, allocator)
|
||
|
|
append(&framer.buffer, ..data)
|
||
|
|
|
||
|
|
start := 0
|
||
|
|
for i := 0; i < len(framer.buffer); i += 1 {
|
||
|
|
if framer.buffer[i] != '\n' {
|
||
|
|
if i-start >= MAX_FRAME_BYTES {
|
||
|
|
return frames, .Too_Large
|
||
|
|
}
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
|
||
|
|
end := i
|
||
|
|
if end > start && framer.buffer[end-1] == '\r' {
|
||
|
|
end -= 1
|
||
|
|
}
|
||
|
|
if end-start > MAX_FRAME_BYTES {
|
||
|
|
return frames, .Too_Large
|
||
|
|
}
|
||
|
|
frame := strings.clone(string(framer.buffer[start:end]), allocator)
|
||
|
|
append(&frames, frame)
|
||
|
|
start = i+1
|
||
|
|
}
|
||
|
|
|
||
|
|
if start > 0 {
|
||
|
|
remaining := len(framer.buffer)-start
|
||
|
|
if remaining > 0 {
|
||
|
|
copy(framer.buffer[:remaining], framer.buffer[start:])
|
||
|
|
}
|
||
|
|
resize(&framer.buffer, remaining)
|
||
|
|
}
|
||
|
|
if len(framer.buffer) > MAX_FRAME_BYTES {
|
||
|
|
return frames, .Too_Large
|
||
|
|
}
|
||
|
|
return frames, .None
|
||
|
|
}
|