#ifndef BYTEIO_H #define BYTEIO_H struct byte_writer { struct buffer buff; b32 overflowed; u8 *at; }; struct byte_reader { struct buffer buff; b32 overflowed; u8 *at; }; /* ========================== * * Constructor utils * ========================== */ INLINE struct byte_writer bw_create_from_buffer(struct buffer buff) { return (struct byte_writer) { .buff = buff, .overflowed = false, .at = buff.data }; } INLINE struct byte_reader br_create_from_buffer(struct buffer buff) { return (struct byte_reader) { .buff = buff, .overflowed = false, .at = buff.data }; } INLINE struct byte_writer bw_copy(struct byte_writer *bw) { return *bw; } INLINE struct byte_reader br_copy(struct byte_reader *br) { return *br; } /* Generate a buffer struct containing written bytes only */ INLINE struct buffer bw_get_written_buffer(struct byte_writer *bw) { return (struct buffer) { .data = bw->buff.data, .size = bw->at - bw->buff.data }; } INLINE u64 bw_pos(struct byte_reader *bw) { return bw->at - bw->buff.data; } /* ========================== * * Overflow utils * ========================== */ INLINE b32 bw_overflow_check(struct byte_writer *bw, u64 amount) { if (bw->overflowed || bw->at + amount > bw->buff.data + bw->buff.size) { ASSERT(false); bw->overflowed = true; return true; } return false; } INLINE b32 br_overflow_check(struct byte_reader *br, u64 amount) { if (br->overflowed || br->at + amount > br->buff.data + br->buff.size) { ASSERT(false); br->overflowed = true; return true; } return false; } /* ========================== * * Write * ========================== */ void bw_seek(struct byte_writer *bw, u64 amount); void bw_seek_to(struct byte_writer *bw, u64 pos); void bw_write_buffer(struct byte_writer *bw, struct buffer buff); void bw_write_u8(struct byte_writer *bw, u8 v); void bw_write_u16(struct byte_writer *bw, u16 v); void bw_write_u32(struct byte_writer *bw, u32 v); void bw_write_u64(struct byte_writer *bw, u64 v); void bw_write_i8(struct byte_writer *bw, i8 v); void bw_write_i16(struct byte_writer *bw, i16 v); void bw_write_i32(struct byte_writer *bw, i32 v); void bw_write_i64(struct byte_writer *bw, i64 v); void bw_write_var_uint(struct byte_writer *bw, u64 v); void bw_write_var_sint(struct byte_writer *bw, i64 v); INLINE u64 bw_bytes_left(struct byte_writer *bw) { return bw->overflowed ? 0 : bw->buff.size - (bw->at - bw->buff.data); } /* ========================== * * Read * ========================== */ void br_seek(struct byte_reader *br, u64 amount); void br_seek_to(struct byte_reader *br, u64 pos); /* Will not read any data on overflow */ #define br_read_to_struct(br_ptr, var_ptr) (br_read_to_buffer(br_ptr, BUFFER(sizeof(*var_ptr), (u8 *)var_ptr))) void *br_read_raw(struct byte_reader *br, u64 size); void br_read_to_buffer(struct byte_reader *br, struct buffer buff); u8 br_read_u8(struct byte_reader *br); u16 br_read_u16(struct byte_reader *br); u32 br_read_u32(struct byte_reader *br); u64 br_read_u64(struct byte_reader *br); i8 br_read_i8(struct byte_reader *br); i16 br_read_i16(struct byte_reader *br); i32 br_read_i32(struct byte_reader *br); i64 br_read_i64(struct byte_reader *br); u64 br_read_var_uint(struct byte_reader *br); i64 br_read_var_sint(struct byte_reader *br); INLINE u64 br_bytes_left(const struct byte_reader *br) { return br->overflowed ? 0 : br->buff.size - (br->at - br->buff.data); } INLINE u64 br_pos(struct byte_reader *br) { return br->at - br->buff.data; } #endif