1 /*
2  * reimplementation of Daniel Bernstein's buffer library.
3  * placed in the public domain by Uwe Ohse, uwe@ohse.de.
4  */
5 #include "buffer.h"
6 #include "str.h"
7 #include "byte.h"
8 #include "error.h"
9 
10 static int
do_op(buffer_op op,int fd,const char * cbuf,unsigned int len)11 do_op (buffer_op op, int fd, const char *cbuf, unsigned int len)
12 {
13 	union { const char *cc; char *c; } x;
14 	char *buf;
15 	x.cc=cbuf;
16 	buf=x.c;
17 	while (len) {
18 		int w;
19 		w = op (fd, buf, len);
20 		if (w == -1) {
21 			if (errno == error_intr) /* EAGAIN? */
22 				continue;
23 			return -1; /* the file may be corrupted. */
24 		}
25 		buf += w;
26 		len -= w;
27 	}
28 	return 0;
29 }
30 
31 int
buffer_flush(buffer * b)32 buffer_flush (buffer * b)
33 {
34 	int ret;
35 	if (!b->pos)
36 		return 0;
37 	ret=do_op (b->op, b->fd, b->buf, b->pos);
38 	b->pos=0;
39 	return ret;
40 }
41 
42 /* buffer_putalign fills all available
43    space with data before calling buffer_flush.
44  */
45 
46 /* when there isn't enough space for new data, buffer_put calls buffer_flush
47    before copying any data,
48  */
49 int
buffer_put(buffer * b,const char * buf,unsigned int len)50 buffer_put (buffer * b, const char *buf, unsigned int len)
51 {
52 	if (len > b->len - b->pos) {
53 		if (buffer_flush (b) == -1)
54 			return -1;
55 		while (len > b->len) {
56 			unsigned int n=len;
57 			if (n>BUFFER_OUTSIZE)
58 				n=BUFFER_OUTSIZE;
59 			if (do_op (b->op, b->fd, buf, n) == -1)
60 				return -1;
61 			buf+=n;
62 			len-=n;
63 		}
64 	}
65 	byte_copy (b->buf + b->pos, len, buf);
66 	b->pos += len;
67 	return 0;
68 }
69 
70 /* buffer_putflush is similar to buffer_put followed by buffer_flush. */
71 /* which isn't how DJB implemented it (first flush, then write new data,
72  * then flush again) */
73 int
buffer_putflush(buffer * b,const char * buf,unsigned int len)74 buffer_putflush(buffer *b,const char *buf,unsigned int len)
75 {
76 	if (-1==buffer_put(b,buf,len))
77 		return -1;
78 	return buffer_flush(b);
79 }
80 
81 int
buffer_puts(buffer * b,const char * buf)82 buffer_puts(buffer *b,const char *buf)
83 {
84 	return buffer_put(b,buf,str_len(buf));
85 }
86 
buffer_putsflush(buffer * b,const char * buf)87 int buffer_putsflush(buffer *b,const char *buf)
88 {
89 	return buffer_putflush(b,buf,str_len(buf));
90 }
91 
92 int
buffer_putalign(buffer * b,const char * buf,unsigned int len)93 buffer_putalign (buffer * b, const char *buf, unsigned int len)
94 {
95 	unsigned int isfree=b->len - b->pos;
96 
97 	if (len > isfree) {
98 		if (-1==buffer_put(b,buf,isfree))
99 			return -1;
100 		len-=isfree;
101 		buf+=isfree;
102 	}
103 	return buffer_put(b,buf,len);
104 }
105 
106 int
buffer_putsalign(buffer * b,const char * buf)107 buffer_putsalign(buffer *b,const char *buf)
108 {
109 	return buffer_putalign(b,buf,str_len(buf));
110 }
111