Sigrid Solveig Haflínudóttirremove redundant castse4486dc1 month agoHistory
904 lines · 18.6 KB · C
RawDownload
#include "inc/priv.h"#include "inc/str.h"#include "inc/time.h" #define MOST_OF(x) ((x) - ((x)>>4)) ios *ios_stdin = nil;ios *ios_stdout = nil;ios *ios_stderr = nil; /* OS-level primitive wrappers */ void *sl_memrchr(const void *s, int c, usize n){	const u8int *src = (const u8int*)s + n;	u8int uc = c;	while(--src >= (const u8int*)s)		if(*src == uc)			return (void *)src;	return nil;} sl_fd_wr(1) sl_rd(2, 3) sl_wr(4) sl_nonnull(2, 4)static intwrite_all(int fd, const u8int *buf, usize n, usize *nwritten){	usize wrote; 	*nwritten = 0;	while(n > 0){		wrote = 0;		int err = sys_write(fd, buf, n, &wrote);		n -= wrote;		*nwritten += wrote;		buf += wrote;		if(err)			return err;	}	return 0;} /* internal utility functions */ sl_nonnull(1)static u8int *buf_realloc(ios *s, usize sz){	u8int *temp; 	if((s->buf == nil || s->buf == &s->local[0]) && sz <= IOS_INLSIZE){		/* TODO: if we want to allow shrinking, see if the buffer shrank		   down to this size, in which case we need to copy. */		s->buf = &s->local[0];		s->maxsize = IOS_INLSIZE;		s->flags |= IOS_FL_OWNBUF;		return s->buf;	} 	if(sz <= s->maxsize)		return s->buf; 	if((s->flags & IOS_FL_OWNBUF) != 0 && s->buf != &s->local[0]){		// if we own the buffer we're free to resize it		// always allocate 1 bigger in case user wants to add a NUL		// terminator after taking over the buffer		temp = MEM_REALLOC(s->buf, sz);		if(temp == nil)			return nil;	}else{		temp = MEM_ALLOC(sz);		if(temp == nil)			return nil;		s->flags |= IOS_FL_OWNBUF;		if(s->buf != nil)			memcpy(temp, s->buf, s->size);	} 	s->buf = temp;	s->maxsize = sz;	return s->buf;} // write a block of data into the buffer at the current position, resizing// if necessary. returns # written.sl_nonnull(1, 2) sl_rd(2, 3)static usizewrite_grow(ios *s, const void *data, usize n){	usize amt;	usize newsize; 	if(sl_unlikely(n == 0))		return 0; 	if(sl_likely(s->bpos + n > s->size)){		if(sl_unlikely(s->bpos + n > s->maxsize)){			/* TODO: here you might want to add a mechanism for limiting			   the growth of the io. */			newsize = s->maxsize ? s->maxsize * 2 : 8;			while(s->bpos + n > newsize)				newsize *= 2;			if(buf_realloc(s, newsize) == nil){				/* no more space; write as much as we can */				amt = s->maxsize - s->bpos;				if(amt > 0)					memcpy(&s->buf[s->bpos], data, amt);				s->bpos += amt;				s->size = s->maxsize;				return amt;			}		}		s->size = s->bpos + n;	}	memcpy(s->buf + s->bpos, data, n);	s->bpos += n; 	return n;}  /* interface functions, low level */ usizeios_read(ios *s, void *dest, usize n){	usize tot = 0;	usize got, avail; 	if(s->state == IOS_STATE_CLOSED || (s->flags & IOS_FL_WRONLY) != 0)		return 0; 	while(n > 0){		avail = s->size - s->bpos; 		if(avail > 0){			usize ncopy = avail >= n ? n : avail;			memcpy(dest, s->buf + s->bpos, ncopy);			s->bpos += ncopy;			if(ncopy >= n){				s->state = IOS_STATE_RD;				return tot+ncopy;			}		}		if(s->bm == IOS_BUF_MEM || s->fd == -1){			// can't get any more data			s->state = IOS_STATE_RD;			if(avail == 0)				s->flags |= IOS_FL_EOF;			return avail;		} 		dest = (u8int*)dest + avail;		n -= avail;		tot += avail; 		ios_flush(s);		s->bpos = s->size = 0;		s->state = IOS_STATE_RD; 		got = 0;		if(n > MOST_OF(s->maxsize)){			// doesn't fit comfortably in buffer; go direct			sys_read(s->fd, dest, n, &got);			tot += got;			if(got == 0)				s->flags |= IOS_FL_EOF;			return tot;		}		// refill buffer		if(sys_read(s->fd, s->buf, s->maxsize, &got) != 0 || got == 0){			s->flags |= IOS_FL_EOF;			return tot;		}		s->size = got;	} 	return tot;} // ensure at least n bytes are buffered if possible. returns # available.usizeios_readprep(ios *s, usize n){	if((s->flags & IOS_FL_WRONLY) != 0)		return 0;	if(s->state == IOS_STATE_WR && s->bm != IOS_BUF_MEM){		ios_flush(s);		s->bpos = s->size = 0;	}	usize space = s->size - s->bpos;	s->state = IOS_STATE_RD;	if(space >= n || s->bm == IOS_BUF_MEM || s->fd == -1)		return space;	if(s->maxsize < s->bpos+n){		// it won't fit. grow buffer or move data back.		if(n <= s->maxsize && space <= ((s->maxsize)>>2)){			if(space)				memmove(s->buf, s->buf+s->bpos, space);			s->size -= s->bpos;			s->bpos = 0;		}		else {			if(buf_realloc(s, s->bpos + n) == nil)				return space;		}	}	usize got;	int result = sys_read(s->fd, s->buf+s->size, s->maxsize - s->size, &got);	if(result != 0)		return space;	s->size += got;	return s->size - s->bpos;} sl_nonnull(1)static voidwrite_update_pos(ios *s){	if(sl_likely(s->bpos > s->ndirty))		s->ndirty = s->bpos;	if(s->bpos > s->size)		s->size = s->bpos;} usizeios_write(ios *s, const void *data, usize n){	if(sl_unlikely((s->flags & IOS_FL_RDONLY) != 0 || s->state == IOS_STATE_CLOSED || n == 0))		return 0;	usize space, wrote = 0; 	if(sl_unlikely(s->state == IOS_STATE_NONE))		s->state = IOS_STATE_WR;	if(sl_unlikely(s->state == IOS_STATE_RD)){		if((s->flags & IOS_FL_REREADABLE) == 0){			s->size = 0;			s->bpos = 0;		}		space = s->size - s->bpos;	}else{		space = s->maxsize - s->bpos;	} 	if(sl_likely(s->bm == IOS_BUF_MEM)){		wrote = write_grow(s, data, n);	}else if(sl_unlikely(s->bm == IOS_BUF_NONE)){		write_all(s->fd, data, n, &wrote);		return wrote;	}else if(sl_likely(n <= space)){		if(s->bm == IOS_BUF_LINE){			const char *nl;			if(sl_unlikely((nl = sl_memrchr(data, '\n', n)) != nil)){				usize linesz = nl-(const char*)data+1;				s->bm = IOS_BUF_BLOCK;				wrote += ios_write(s, data, linesz);				ios_flush(s);				s->bm = IOS_BUF_LINE;				n -= linesz;				data = (const char*)data + linesz;			}		}		memcpy(s->buf + s->bpos, data, n);		s->bpos += n;		wrote += n;	}else{		s->state = IOS_STATE_WR;		ios_flush(s);		if(n > MOST_OF(s->maxsize)){			write_all(s->fd, data, n, &wrote);			return wrote;		}		return ios_write(s, data, n);	}	write_update_pos(s);	return wrote;} soffsetios_seek(ios *s, soffset pos){	if(sl_unlikely(s->state == IOS_STATE_CLOSED || pos < 0))		return -1;	s->flags &= ~IOS_FL_EOF;	if(sl_likely(s->bm == IOS_BUF_MEM)){		if((usize)pos >= s->size)			pos = s->size;		s->bpos = pos;	}else{		ios_flush(s);		s->bpos = s->size = 0;		soffset fdpos = sys_seek(s->fd, pos, SEEK_SET);		if(fdpos < 0)			return -1;		pos = fdpos;	}	s->loc.lineno = 1;	s->loc.colno = 0;	return pos;} soffsetios_seek_end(ios *s){	if(sl_unlikely(s->state == IOS_STATE_CLOSED))		return -1;	s->flags |= IOS_FL_EOF;	if(s->bm == IOS_BUF_MEM)		s->bpos = s->size;	else{		ios_flush(s);		soffset fdpos = sys_seek(s->fd, 0, SEEK_END);		if(fdpos == (soffset)-1)			return fdpos;		s->bpos = s->size = 0;	}	s->loc.lineno = 1;	s->loc.colno = 0;	return 0;} soffsetios_skip(ios *s, soffset offs, bool end){	if(sl_unlikely(s->state == IOS_STATE_CLOSED))		return -1;	if(sl_unlikely(end && ios_seek_end(s) < 0))		return -1;	s->flags &= ~IOS_FL_EOF;	if(s->bm == IOS_BUF_MEM){		if(offs > 0){			if(offs <= (soffset)(s->size-s->bpos))				s->bpos += offs;			else				s->bpos = s->size;		}else if(offs < 0){			if((soffset)s->bpos+offs >= 0)				s->bpos += offs;			else				s->bpos = 0;		}		return s->bpos;	}	ios_flush(s);	s->bpos = s->size = 0;	return sys_seek(s->fd, offs, SEEK_CUR);} intios_trunc(ios *s, soffset size){	if(sl_unlikely(s->state == IOS_STATE_CLOSED || (s->flags & IOS_FL_RDONLY) != 0 || size < 0))		return -1;	if(s->bm == IOS_BUF_MEM){		if(sl_unlikely((usize)size == s->size))			return 0;		if(sl_likely((usize)size < s->size)){			if(s->bpos > (usize)size)				s->bpos = size;		}else if(sl_unlikely(buf_realloc(s, size) == nil))			return -1;		s->size = size;		return 0;	}	return sl_likely(ios_flush(s) == 0) ? ftruncate(s->fd, size) : -1;} intios_flush(ios *s){	if(s->ndirty == 0 || s->bm == IOS_BUF_MEM || s->buf == nil)		return 0;	if(sl_unlikely(s->fd == -1))		return -1; 	if(sl_unlikely(s->state == IOS_STATE_RD)){		if(sys_seek(s->fd, -(soffset)s->size, SEEK_CUR) == (soffset)-1){			// FIXME eh?		}		return -1;	} 	usize nw, ntowrite = s->ndirty;	int err = write_all(s->fd, s->buf, ntowrite, &nw);	// todo: try recovering from some kinds of errors (e.g. retry) 	if(sl_unlikely(s->state == IOS_STATE_RD)){		if(sys_seek(s->fd, s->size - nw, SEEK_CUR) == (soffset)-1){			// FIXME eh?		}		return -1;	}else if(s->state == IOS_STATE_WR){		if(s->bpos != nw && sys_seek(s->fd, (soffset)s->bpos - (soffset)nw, SEEK_CUR) == (soffset)-1){			// FIXME eh?		}		// now preserve the invariant that data to write		// begins at the beginning of the buffer, and s->size refers		// to how much valid file data is stored in the buffer.		if(sl_unlikely(s->size > s->ndirty)){			usize delta = s->size - s->ndirty;			memmove(s->buf, s->buf + s->ndirty, delta);		}		s->size -= s->ndirty;		s->bpos = 0;	} 	s->ndirty = 0; 	if(sl_unlikely(err))		return err;	if(sl_unlikely(nw < ntowrite))		return -1;	return 0;} voidios_close(ios *s){	if(sl_unlikely(s->state == IOS_STATE_CLOSED))		return;	ios_flush(s);	if(sl_unlikely(s->fd != -1 && (s->flags & IOS_FL_OWNFD) != 0))		sys_close(s->fd);	s->fd = -1;	s->data = sl_nil;	if((s->flags & IOS_FL_OWNBUF) != 0 && s->buf != &s->local[0])		MEM_FREE(s->buf);	s->buf = nil;	s->size = s->maxsize = s->bpos = 0;	s->state = IOS_STATE_CLOSED;} voidios_free(ios *s){	MEM_FREE(s->filename);	s->filename = nil;} sl_nonnull(1)static voidbuf_init(ios *s, ios_buf_mode bm){	s->bm = bm;	if(s->bm == IOS_BUF_MEM || s->bm == IOS_BUF_NONE){		s->buf = &s->local[0];		s->maxsize = IOS_INLSIZE;	}else{		s->buf = nil;		buf_realloc(s, IOS_BUFSIZE);	}	s->size = s->bpos = 0;} u8int *ios_takebuf(ios *s, usize *psize){	u8int *buf; 	ios_flush(s); 	if(sl_unlikely(s->buf == &s->local[0] || s->buf == nil || ((s->flags & IOS_FL_OWNBUF) == 0 && s->size == s->maxsize))){		buf = MEM_ALLOC(s->size+1);		if(buf == nil)			return nil;		if(s->buf != nil)			memcpy(buf, s->buf, s->size);	}else if(sl_unlikely(s->size == s->maxsize)){		buf = MEM_REALLOC(s->buf, s->size + 1);		if(sl_unlikely(buf == nil))			return nil;	}else{		buf = s->buf;	}	buf[s->size] = '\0';	*psize = s->size + 1; 	/* empty io and reinitialize */	buf_init(s, s->bm); 	return buf;} intios_setbuf(ios *s, u8int *buf, usize size, bool own){	ios_flush(s);	usize nvalid = size < s->size ? size : s->size;	if(nvalid > 0)		memcpy(buf, s->buf, nvalid);	if(s->bpos > nvalid){		// truncated		s->bpos = nvalid;	}	s->size = nvalid; 	if((s->flags & IOS_FL_OWNBUF) != 0 && s->buf != &s->local[0])		MEM_FREE(s->buf);	s->buf = buf;	s->maxsize = size;

Lines 1–500 of 904.

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