123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- package bytes
- import "core:io"
- import "core:unicode/utf8"
- MIN_READ :: 512;
- @(private)
- SMALL_BUFFER_SIZE :: 64;
- // A Buffer is a variable-sized buffer of bytes with a io.Stream interface
- // The zero value for Buffer is an empty buffer ready to use.
- Buffer :: struct {
- buf: [dynamic]byte,
- off: int,
- last_read: Read_Op,
- }
- @(private)
- Read_Op :: enum i8 {
- Read = -1,
- Invalid = 0,
- Read_Rune1 = 1,
- Read_Rune2 = 2,
- Read_Rune3 = 3,
- Read_Rune4 = 4,
- }
- buffer_init :: proc(b: ^Buffer, buf: []byte) {
- resize(&b.buf, len(buf));
- copy(b.buf[:], buf);
- }
- buffer_init_string :: proc(b: ^Buffer, s: string) {
- resize(&b.buf, len(s));
- copy(b.buf[:], s);
- }
- buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
- b.buf.allocator = allocator;
- reserve(&b.buf, cap);
- resize(&b.buf, len);
- }
- buffer_destroy :: proc(b: ^Buffer) {
- delete(b.buf);
- buffer_reset(b);
- }
- buffer_to_bytes :: proc(b: ^Buffer) -> []byte {
- return b.buf[b.off:];
- }
- buffer_to_string :: proc(b: ^Buffer) -> string {
- if b == nil {
- return "<nil>";
- }
- return string(b.buf[b.off:]);
- }
- buffer_is_empty :: proc(b: ^Buffer) -> bool {
- return len(b.buf) <= b.off;
- }
- buffer_length :: proc(b: ^Buffer) -> int {
- return len(b.buf) - b.off;
- }
- buffer_capacity :: proc(b: ^Buffer) -> int {
- return cap(b.buf);
- }
- buffer_reset :: proc(b: ^Buffer) {
- clear(&b.buf);
- b.off = 0;
- b.last_read = .Invalid;
- }
- buffer_truncate :: proc(b: ^Buffer, n: int) {
- if n == 0 {
- buffer_reset(b);
- return;
- }
- b.last_read = .Invalid;
- if n < 0 || n > buffer_length(b) {
- panic("bytes.truncate: truncation out of range");
- }
- resize(&b.buf, b.off+n);
- }
- @(private)
- _buffer_try_grow :: proc(b: ^Buffer, n: int) -> (int, bool) {
- if l := len(b.buf); n <= cap(b.buf)-l {
- resize(&b.buf, l+n);
- return l, true;
- }
- return 0, false;
- }
- @(private)
- _buffer_grow :: proc(b: ^Buffer, n: int) -> int {
- m := buffer_length(b);
- if m == 0 && b.off != 0 {
- buffer_reset(b);
- }
- if i, ok := _buffer_try_grow(b, n); ok {
- return i;
- }
- if b.buf == nil && n <= SMALL_BUFFER_SIZE {
- b.buf = make([dynamic]byte, n, SMALL_BUFFER_SIZE);
- return 0;
- }
- c := cap(b.buf);
- if n <= c/2 - m {
- copy(b.buf[:], b.buf[b.off:]);
- } else if c > max(int) - c - n {
- panic("bytes.Buffer: too large");
- } else {
- resize(&b.buf, 2*c + n);
- copy(b.buf[:], b.buf[b.off:]);
- }
- b.off = 0;
- resize(&b.buf, m+n);
- return m;
- }
- buffer_grow :: proc(b: ^Buffer, n: int) {
- if n < 0 {
- panic("bytes.buffer_grow: negative count");
- }
- m := _buffer_grow(b, n);
- resize(&b.buf, m);
- }
- buffer_write_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
- b.last_read = .Invalid;
- if offset < 0 {
- err = .Invalid_Offset;
- return;
- }
- _, ok := _buffer_try_grow(b, offset+len(p));
- if !ok {
- _ = _buffer_grow(b, offset+len(p));
- }
- if len(b.buf) <= offset {
- return 0, .Short_Write;
- }
- return copy(b.buf[offset:], p), nil;
- }
- buffer_write :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
- b.last_read = .Invalid;
- m, ok := _buffer_try_grow(b, len(p));
- if !ok {
- m = _buffer_grow(b, len(p));
- }
- return copy(b.buf[m:], p), nil;
- }
- buffer_write_string :: proc(b: ^Buffer, s: string) -> (n: int, err: io.Error) {
- b.last_read = .Invalid;
- m, ok := _buffer_try_grow(b, len(s));
- if !ok {
- m = _buffer_grow(b, len(s));
- }
- return copy(b.buf[m:], s), nil;
- }
- buffer_write_byte :: proc(b: ^Buffer, c: byte) -> io.Error {
- b.last_read = .Invalid;
- m, ok := _buffer_try_grow(b, 1);
- if !ok {
- m = _buffer_grow(b, 1);
- }
- b.buf[m] = c;
- return nil;
- }
- buffer_write_rune :: proc(b: ^Buffer, r: rune) -> (n: int, err: io.Error) {
- if r < utf8.RUNE_SELF {
- buffer_write_byte(b, byte(r));
- return 1, nil;
- }
- b.last_read = .Invalid;
- m, ok := _buffer_try_grow(b, utf8.UTF_MAX);
- if !ok {
- m = _buffer_grow(b, utf8.UTF_MAX);
- }
- res: [4]byte;
- res, n = utf8.encode_rune(r);
- copy(b.buf[m:][:utf8.UTF_MAX], res[:n]);
- resize(&b.buf, m+n);
- return;
- }
- buffer_next :: proc(b: ^Buffer, n: int) -> []byte {
- n := n;
- b.last_read = .Invalid;
- m := buffer_length(b);
- if n > m {
- n = m;
- }
- data := b.buf[b.off : b.off + n];
- b.off += n;
- if n > 0 {
- b.last_read = .Read;
- }
- return data;
- }
- buffer_read :: proc(b: ^Buffer, p: []byte) -> (n: int, err: io.Error) {
- b.last_read = .Invalid;
- if buffer_is_empty(b) {
- buffer_reset(b);
- if len(p) == 0 {
- return 0, nil;
- }
- return 0, .EOF;
- }
- n = copy(p, b.buf[b.off:]);
- b.off += n;
- if n > 0 {
- b.last_read = .Read;
- }
- return;
- }
- buffer_read_at :: proc(b: ^Buffer, p: []byte, offset: int) -> (n: int, err: io.Error) {
- b.last_read = .Invalid;
- if offset < 0 || offset >= len(b.buf) {
- err = .Invalid_Offset;
- return;
- }
- if 0 <= offset && offset < len(b.buf) {
- n = copy(p, b.buf[offset:]);
- }
- if n > 0 {
- b.last_read = .Read;
- }
- return;
- }
- buffer_read_byte :: proc(b: ^Buffer) -> (byte, io.Error) {
- if buffer_is_empty(b) {
- buffer_reset(b);
- return 0, .EOF;
- }
- c := b.buf[b.off];
- b.off += 1;
- b.last_read = .Read;
- return c, nil;
- }
- buffer_read_rune :: proc(b: ^Buffer) -> (r: rune, size: int, err: io.Error) {
- if buffer_is_empty(b) {
- buffer_reset(b);
- return 0, 0, .EOF;
- }
- c := b.buf[b.off];
- if c < utf8.RUNE_SELF {
- b.off += 1;
- b.last_read = .Read_Rune1;
- return rune(c), 1, nil;
- }
- r, size = utf8.decode_rune(b.buf[b.off:]);
- b.off += size;
- b.last_read = Read_Op(i8(size));
- return;
- }
- buffer_unread_byte :: proc(b: ^Buffer) -> io.Error {
- if b.last_read == .Invalid {
- return .Invalid_Unread;
- }
- b.last_read = .Invalid;
- if b.off > 0 {
- b.off -= 1;
- }
- return nil;
- }
- buffer_unread_rune :: proc(b: ^Buffer) -> io.Error {
- if b.last_read <= .Invalid {
- return .Invalid_Unread;
- }
- if b.off >= int(b.last_read) {
- b.off -= int(i8(b.last_read));
- }
- b.last_read = .Invalid;
- return nil;
- }
- buffer_read_bytes :: proc(b: ^Buffer, delim: byte) -> (line: []byte, err: io.Error) {
- i := index_byte(b.buf[b.off:], delim);
- end := b.off + i + 1;
- if i < 0 {
- end = len(b.buf);
- err = .EOF;
- }
- line = b.buf[b.off:end];
- b.off = end;
- b.last_read = .Read;
- return;
- }
- buffer_read_string :: proc(b: ^Buffer, delim: byte) -> (line: string, err: io.Error) {
- slice: []byte;
- slice, err = buffer_read_bytes(b, delim);
- return string(slice), err;
- }
- buffer_write_to :: proc(b: ^Buffer, w: io.Writer) -> (n: i64, err: io.Error) {
- b.last_read = .Invalid;
- if byte_count := buffer_length(b); byte_count > 0 {
- m, e := io.write(w, b.buf[b.off:]);
- if m > byte_count {
- panic("bytes.buffer_write_to: invalid io.write count");
- }
- b.off += m;
- n = i64(m);
- if e != nil {
- err = e;
- return;
- }
- if m != byte_count {
- err = .Short_Write;
- return;
- }
- }
- buffer_reset(b);
- return;
- }
- buffer_read_from :: proc(b: ^Buffer, r: io.Reader) -> (n: i64, err: io.Error) #no_bounds_check {
- b.last_read = .Invalid;
- for {
- i := _buffer_grow(b, MIN_READ);
- resize(&b.buf, i);
- m, e := io.read(r, b.buf[i:cap(b.buf)]);
- if m < 0 {
- err = .Negative_Read;
- return;
- }
- resize(&b.buf, i+m);
- n += i64(m);
- if e == .EOF {
- return;
- }
- if e != nil {
- err = e;
- return;
- }
- }
- return;
- }
- buffer_to_stream :: proc(b: ^Buffer) -> (s: io.Stream) {
- s.stream_data = b;
- s.stream_vtable = _buffer_vtable;
- return;
- }
- @(private)
- _buffer_vtable := &io.Stream_VTable{
- impl_size = proc(s: io.Stream) -> i64 {
- b := (^Buffer)(s.stream_data);
- return i64(buffer_capacity(b));
- },
- impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_read(b, p);
- },
- impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_read_at(b, p, int(offset));
- },
- impl_read_byte = proc(s: io.Stream) -> (byte, io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_read_byte(b);
- },
- impl_read_rune = proc(s: io.Stream) -> (r: rune, size: int, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_read_rune(b);
- },
- impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_write(b, p);
- },
- impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_write_at(b, p, int(offset));
- },
- impl_write_byte = proc(s: io.Stream, c: byte) -> io.Error {
- b := (^Buffer)(s.stream_data);
- return buffer_write_byte(b, c);
- },
- impl_write_rune = proc(s: io.Stream, r: rune) -> (int, io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_write_rune(b, r);
- },
- impl_unread_byte = proc(s: io.Stream) -> io.Error {
- b := (^Buffer)(s.stream_data);
- return buffer_unread_byte(b);
- },
- impl_unread_rune = proc(s: io.Stream) -> io.Error {
- b := (^Buffer)(s.stream_data);
- return buffer_unread_rune(b);
- },
- impl_destroy = proc(s: io.Stream) -> io.Error {
- b := (^Buffer)(s.stream_data);
- buffer_destroy(b);
- return nil;
- },
- impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_write_to(b, w);
- },
- impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
- b := (^Buffer)(s.stream_data);
- return buffer_read_from(b, r);
- },
- };
|