1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
.TH buffer 3
.SH NAME
buffer \- generic read/write buffering
.SH SYNTAX
.B #include \(dqbuffer.h\(dq
buffer* buffer_0; /* like stdio's stdin */
.br
buffer* buffer_1; /* like stdio's stdout */
.br
buffer* buffer_2; /* like stdio's stderr */
void \fBbuffer_init\fR(buffer &\fIb\fR,ssize_t (*\fIop\fR)(int,char *,size_t),
int \fIfd\fR, char *\fIy\fR, size_t \fIylen\fR);
.br
ssize_t \fBbuffer_get\fP(buffer *\fIb\fR,char *\fIx\fR,size_t \fIlen\fR);
int \fBbuffer_put\fP(buffer *\fIb\fR,const char *\fIx\fR,size_t \fIlen\fR);
.br
int \fBbuffer_puts\fP(buffer *\fIb\fR,const char *\fIx\fR);
.br
int \fBbuffer_putalign\fP(buffer *\fIb\fR,char *\fIx\fR,unsigned int \fIlen\fR);
.br
int \fBbuffer_putsalign\fP(buffer *\fIb\fR,char *\fIx\fR);
int \fBbuffer_putflush\fP(buffer *\fIb\fR,char *\fIx\fR,unsigned int \fIlen\fR);
.br
int \fBbuffer_putsflush\fP(buffer *\fIb\fR,char *\fIx\fR);
int \fBbuffer_flush\fP(buffer *\fIb\fR);
.br
int \fBbuffer_copy\fP(buffer *\fIbo\fR,buffer *\fIbi\fR);
int \fBbuffer_unixread\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR);
.br
int \fBbuffer_unixwrite\fP(int \fIfd\fR,char *\fIbuf\fR,size_t \fIlen\fR);
.SH DESCRIPTION
.B buffer.h
describes a generic buffer interface that can be used for
read and write buffering. Buffers must be initialized with
\fBbuffer_init\fR.
A buffer can only be used for reading or writing at the same time, not
both.
Unlike
.BR stdio ,
these write buffers are not flushed automatically at
program termination; you must manually call \fBbuffer_flush\fR,
\fBbuffer_putflush\fR, or \fBbuffer_putsflush\fR.
.B buffer_init
prepares \fIb\fR to store a string in \fIy\fR[0], \fIy\fR[1], ...,
\fIy\fR[\fIylen\fR-1]. Initially the string is empty.
.B buffer_init
also prepares \fIb\fR to use the read/write operation specified by
\fIop\fR and \fIfd\fR.
You can use
buffer \fIb\fR = BUFFER_INIT(\fIop\fR,\fIfd\fR,\fIy\fR,\fIylen\fR);
to initialize \fIb\fR statically if \fIop\fR, \fIfd\fR, \fIy\fR, and \fIylen\fR
are compile-time constants.
You can call
.B buffer_init
again at any time. Note that this discards the currently buffered string.
.B buffer_get
copies data to \fIx\fR[0], \fIx\fR[1], ...,
\fIx\fR[\fIlen\fR-1] from the beginning of a string stored in
preallocated space; removes these \fIlen\fR bytes from the string; and
returns \fIlen\fR.
If, however, the string has fewer than \fIlen\fR (but more than 0)
bytes,
.I buffer_get
copies only that many bytes, and returns that number.
If the string is empty,
.B buffer_get
first uses a \fBread operation\fR to
feed data into the string. The \fBread operation\fR may indicate end of
input.
The preallocated space and the \fBread operation\fR are specified by
\fIb\fR. You must initialize \fBb\fR using
.B buffer_init
before calling
.B buffer_get
(or use the pre-initialized \fIbuffer_0\fR).
.B buffer_put
writes \fIlen\fR bytes from \fIx\fR to \fIb\fR.
The difference to
.B buffer_putalign
is that, when there isn't enough space
for new data,
.B buffer_put
calls
.B buffer_flush
before copying any data, while
.B buffer_putalign
fills all available space with data before calling
.B buffer_flush.
.B buffer_copy
copies one buffer to other one.
The output buffer needs to have at least the
preallocated size of the input buffer.
.B buffer_unixread
and
.B buffer_unixwrite
perform the same operation like standard Unix
.B read
or
.BR write.
.SH MACROS
Apart from this basic usage, some helpful macro
definitions are provided:
.B BUFFER_INIT(op,fd,buf,len)
uses
.I op
function to operate (read/write) on
.I buf
with
.I len
to file descriptor
.IR fd .
.B buffer_GETC(buf,c)
returns the upmost position of character
.I c
within buffer
.I buf
or 0.
.B buffer_PUTC(buf,c)
adds character
.I c
to buffer
.IR buf.
.SH EXAMPLE
#include <buffer.h>
#include <open.h>
char buf[BUFFER_INSIZE]; // defined in buffer.h
int fd = open_read("/etc/services");
buffer input;
if (fd >= 0) {
char x;
buffer_init(&input,read,fd,buf,sizeof buf);
while (buffer_get(&input,&x,1) == 1) {
buffer_put(buffer_1,&x,1);
if (x == '\\n') break;
}
buffer_flush(buffer_1);
}
.SH "RETURN CODES"
.B buffer_put
and
.B buffer_get
return
.I 0
if everything was fine,
.IR -1 ,
on error (setting \fIerrno\fR).
.B buffer_copy
returns
.IR -2 ,
if the input buffer can't be read, and
.IR -3 ,
if the data can't successfully copied
to the output buffer. On success
.B buffer_copy
returns
.IR 0 .
.SH "REFERENCES"
https://cr.yp.to/lib/buffer_get.html
https://cr.yp.to/lib/buffer_put.html
.SH "SEE ALSO"
stdio(3)
|