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