Sigrid Solveig Haflínudóttirfix warnings on macos m68k build13902081 year agoHistory
179 lines · 6.6 KB · C
RawDownload
// this flag controls when data actually moves out to the underlying I/O// channel. in-memory io is a special case of this where the data// never moves out.typedef enum {	bm_none,	bm_line,	bm_block,	bm_memory,}ios_bm; typedef enum {	bst_none,	bst_rd,	bst_wr,	bst_closed,}ios_bst; #define IOS_INLSIZE 128#define IOS_BUFSIZE 32768 typedef struct {	u32int lineno;	u32int colno;}ios_loc; typedef struct {	u8int *buf; // start of buffer	usize maxsize; // space allocated to buffer	usize size; // length of valid data in buf, >=ndirty	usize bpos; // current position in buffer	usize ndirty; // # bytes at &buf[0] that need to be written	soffset fpos; // cached file pos	char *filename;	ios_loc loc;	ios_bm bm;	int colnowait; 	// the state only indicates where the underlying file position is relative	// to the buffer. reading: at the end. writing: at the beginning.	// in general, you can do any operation in any state.	ios_bst state; 	int fd; 	bool readonly;	bool writeonly;	bool ownbuf;	bool ownfd;	bool _eof; 	// this means you can read, seek back, then read the same data	// again any number of times. usually only true for files and strings.	bool rereadable; 	u8int local[IOS_INLSIZE];}ios; void *llt_memrchr(const void *s, int c, usize n) sl_purefn; /* low-level interface functions */usize ios_read(ios *s, void *dest, usize n) sl_nonnull(1, 2);usize ios_write(ios *s, const void *data, usize n) sl_nonnull(1, 2);soffset ios_seek(ios *s, soffset pos) sl_nonnull(1);   // absolute seeksoffset ios_seek_end(ios *s) sl_nonnull(1);soffset ios_skip(ios *s, soffset offs, bool end) sl_nonnull(1);  // relative seekint ios_trunc(ios *s, soffset size) sl_nonnull(1);bool ios_eof(ios *s) sl_purefn sl_nonnull(1);int ios_flush(ios *s) sl_nonnull(1);void ios_close(ios *s) sl_nonnull(1);void ios_free(ios *s) sl_nonnull(1);u8int *ios_takebuf(ios *s, usize *psize) sl_nonnull(1, 2);  // null-terminate and release buffer to caller// set buffer space to useint ios_setbuf(ios *s, u8int *buf, usize size, bool own) sl_nonnull(1, 2);int ios_bufmode(ios *s, ios_bm mode) sl_nonnull(1);void ios_set_readonly(ios *s) sl_nonnull(1);usize ios_copy(ios *to, ios *from, usize nbytes) sl_nonnull(1, 2);usize ios_copyall(ios *to, ios *from) sl_nonnull(1, 2);usize ios_copyuntil(ios *to, ios *from, Rune delim) sl_nonnull(1, 2); /* io creation */ios *ios_file(ios *s, char *fname, bool rd, bool wr, bool create, bool trunc, usize mode) sl_nonnull(1, 2);ios *ios_mem(ios *s, usize initsize) sl_nonnull(1);ios *ios_static_buffer(ios *s, const u8int *buf, usize sz) sl_nonnull(1, 2);ios *ios_fd(ios *s, int fd, const char *name, bool isfile, bool own) sl_nonnull(1, 3); extern ios *ios_stdin;extern ios *ios_stdout;extern ios *ios_stderr; void ios_init_std(void); /* high-level functions - output */int ios_putrune(ios *s, Rune r) sl_nonnull(1);int ios_printf(ios *s, const char *format, ...) sl_printfmt(2, 3) sl_nonnull(1, 2);int ios_vprintf(ios *s, const char *format, va_list args) sl_printfmt(2, 0) sl_nonnull(1, 2); /* high-level io functions - input */int ios_peekrune(ios *s, Rune *r) sl_nonnull(1, 2);int ios_getrune(ios *s, Rune *r) sl_nonnull(1, 2); // discard data buffered for readingvoid ios_purge(ios *s) sl_nonnull(1); /* stdio-style functions */#define IOS_EOF (-1)int ios_putc(ios *s, int c) sl_nonnull(1);int ios_getc(ios *s) sl_nonnull(1);int ios_peekc(ios *s) sl_nonnull(1);#define ios_puts(s, str) ios_write(s, str, strlen(str)) /*  With in-memory io, mixed reads and writes are equivalent to performing  sequences of *p++, as either an lvalue or rvalue. File ios behave  similarly, but other ios might not support this. Using unbuffered  mode makes this more predictable.   Note on "unget" functions:  There are two kinds of functions here: those that operate on sized  blocks of bytes and those that operate on logical units like "character"  or "integer". The "unget" functions only work on logical units. There  is no "unget n bytes". You can only do an unget after a matching get.  However, data pushed back by an unget is available to all read operations.  The reason for this is that unget is defined in terms of its effect on  the underlying buffer (namely, it rebuffers data as if it had been  buffered but not read yet). IOS reserves the right to perform large block  operations directly, bypassing the buffer. In such a case data was  never buffered, so "rebuffering" has no meaning (i.e. there is no  correspondence between the buffer and the physical io).   Single-bit I/O is able to write partial bytes ONLY IF the io supports  seeking. Also, line buffering is not well-defined in the context of  single-bit I/O, so it might not do what you expect.   implementation notes:  in order to know where we are in a file, we must ensure the buffer  is only populated from the underlying io starting with p==buf.   to switch from writing to reading: flush, set p=buf, cnt=0  to switch from reading to writing: seek backwards cnt bytes, p=buf, cnt=0   when writing: buf starts at curr. physical io pos, p - buf is how  many bytes we've written logically. cnt==0   dirty == (bitpos>0 && state==iost_wr), EXCEPT right after switching from  reading to writing, where we might be in the middle of a byte without  having changed it.   to write a bit: if !dirty, read up to maxsize-(p-buf) into buffer, then  seek back by the same amount (undo it). write onto those bits. now set  the dirty bit. in this state, we can bit-read up to the end of the byte,  then formally switch to the read state using flush.   design points:  - data-source independence, including in-memory io  - expose buffer to user, allow user-owned buffers  - allow direct I/O, don't always go through buffer  - buffer-internal seeking. makes seeking back 1-2 bytes very fast,	and makes it possible for sockets where it otherwise wouldn't be  - tries to allow switching between reading and writing  - support 64-bit and large files  - efficient, low-latency buffering  - special support for utf8  - type-aware functions with byte-order swapping service  - position counter for meaningful data offsets with sockets   theory of operation:   the buffer is a view of part of a file/stream. you can seek, read, and  write around in it as much as you like, as if it were just a string.   we keep track of the part of the buffer that's invalid (written to).  we remember whether the position of the underlying io is aligned  with the end of the buffer (reading mode) or the beginning (writing mode).   based on this info, we might have to seek back before doing a flush.   as optimizations, we do no writing if the buffer isn't "dirty", and we  do no reading if the data will only be overwritten.*/

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t