/* * reimplementation of Daniel Bernstein's buffer library. * placed in the public domain by Uwe Ohse, uwe@ohse.de. */ #include "buffer.h" #include "str.h" #include "byte.h" #include "error.h" static int do_op (buffer_op op, int fd, const char *cbuf, unsigned int len) { union { const char *cc; char *c; } x; char *buf; x.cc=cbuf; buf=x.c; while (len) { int w; w = op (fd, buf, len); if (w == -1) { if (errno == error_intr) /* EAGAIN? */ continue; return -1; /* the file may be corrupted. */ } buf += w; len -= w; } return 0; } int buffer_flush (buffer * b) { int ret; if (!b->pos) return 0; ret=do_op (b->op, b->fd, b->buf, b->pos); b->pos=0; return ret; } /* buffer_putalign fills all available space with data before calling buffer_flush. */ /* when there isn't enough space for new data, buffer_put calls buffer_flush before copying any data, */ int buffer_put (buffer * b, const char *buf, unsigned int len) { if (len > b->len - b->pos) { if (buffer_flush (b) == -1) return -1; while (len > b->len) { unsigned int n=len; if (n>BUFFER_OUTSIZE) n=BUFFER_OUTSIZE; if (do_op (b->op, b->fd, buf, n) == -1) return -1; buf+=n; len-=n; } } byte_copy (b->buf + b->pos, len, buf); b->pos += len; return 0; } /* buffer_putflush is similar to buffer_put followed by buffer_flush. */ /* which isn't how DJB implemented it (first flush, then write new data, * then flush again) */ int buffer_putflush(buffer *b,const char *buf,unsigned int len) { if (-1==buffer_put(b,buf,len)) return -1; return buffer_flush(b); } int buffer_puts(buffer *b,const char *buf) { return buffer_put(b,buf,str_len(buf)); } int buffer_putsflush(buffer *b,const char *buf) { return buffer_putflush(b,buf,str_len(buf)); } int buffer_putalign (buffer * b, const char *buf, unsigned int len) { unsigned int isfree=b->len - b->pos; if (len > isfree) { if (-1==buffer_put(b,buf,isfree)) return -1; len-=isfree; buf+=isfree; } return buffer_put(b,buf,len); } int buffer_putsalign(buffer *b,const char *buf) { return buffer_putalign(b,buf,str_len(buf)); }