10 #define BUFFER_SIZE 1024
13 void buffer_init(Buffer
*buf
) {
14 memset(buf
, 0, sizeof *buf
);
17 bool buffer_reserve(Buffer
*buf
, size_t size
) {
18 /* ensure minimal buffer size, to avoid repeated realloc(3) calls */
19 if (size
< BUFFER_SIZE
)
21 if (buf
->size
< size
) {
22 size
= MAX(size
, buf
->size
*2);
23 char *data
= realloc(buf
->data
, size
);
32 bool buffer_grow(Buffer
*buf
, size_t len
) {
34 if (!addu(buf
->len
, len
, &size
))
36 return buffer_reserve(buf
, size
);
39 bool buffer_terminate(Buffer
*buf
) {
40 return !buf
->data
|| buf
->len
== 0 || buf
->data
[buf
->len
-1] == '\0' ||
41 buffer_append(buf
, "\0", 1);
44 void buffer_release(Buffer
*buf
) {
51 void buffer_clear(Buffer
*buf
) {
55 bool buffer_put(Buffer
*buf
, const void *data
, size_t len
) {
56 if (!buffer_reserve(buf
, len
))
58 memmove(buf
->data
, data
, len
);
63 bool buffer_put0(Buffer
*buf
, const char *data
) {
64 return buffer_put(buf
, data
, strlen(data
)+1);
67 bool buffer_remove(Buffer
*buf
, size_t pos
, size_t len
) {
71 if (!addu(pos
, len
, &end
) || end
> buf
->len
)
73 memmove(buf
->data
+ pos
, buf
->data
+ pos
+ len
, buf
->len
- pos
- len
);
78 bool buffer_insert(Buffer
*buf
, size_t pos
, const void *data
, size_t len
) {
83 if (!buffer_grow(buf
, len
))
85 size_t move
= buf
->len
- pos
;
87 memmove(buf
->data
+ pos
+ len
, buf
->data
+ pos
, move
);
88 memcpy(buf
->data
+ pos
, data
, len
);
93 bool buffer_insert0(Buffer
*buf
, size_t pos
, const char *data
) {
95 return buffer_prepend0(buf
, data
);
97 return buffer_append0(buf
, data
);
98 return buffer_insert(buf
, pos
, data
, strlen(data
));
101 bool buffer_append(Buffer
*buf
, const void *data
, size_t len
) {
102 return buffer_insert(buf
, buf
->len
, data
, len
);
105 bool buffer_append0(Buffer
*buf
, const char *data
) {
106 size_t nul
= (buf
->len
> 0 && buf
->data
[buf
->len
-1] == '\0') ? 1 : 0;
108 bool ret
= buffer_append(buf
, data
, strlen(data
)+1);
114 bool buffer_prepend(Buffer
*buf
, const void *data
, size_t len
) {
115 return buffer_insert(buf
, 0, data
, len
);
118 bool buffer_prepend0(Buffer
*buf
, const char *data
) {
119 return buffer_prepend(buf
, data
, strlen(data
) + (buf
->len
== 0));
122 static bool buffer_vappendf(Buffer
*buf
, const char *fmt
, va_list ap
) {
124 va_copy(ap_save
, ap
);
125 int len
= vsnprintf(NULL
, 0, fmt
, ap
);
126 if (len
== -1 || !buffer_grow(buf
, len
+1)) {
130 size_t nul
= (buf
->len
> 0 && buf
->data
[buf
->len
-1] == '\0') ? 1 : 0;
132 bool ret
= vsnprintf(buf
->data
+buf
->len
, len
+1, fmt
, ap_save
) == len
;
133 buf
->len
+= ret
? (size_t)len
+1 : nul
;
138 bool buffer_appendf(Buffer
*buf
, const char *fmt
, ...) {
141 bool ret
= buffer_vappendf(buf
, fmt
, ap
);
146 bool buffer_printf(Buffer
*buf
, const char *fmt
, ...) {
150 bool ret
= buffer_vappendf(buf
, fmt
, ap
);
155 size_t buffer_length0(Buffer
*buf
) {
156 size_t len
= buf
->len
;
157 if (len
> 0 && buf
->data
[len
-1] == '\0')
162 size_t buffer_length(Buffer
*buf
) {
166 size_t buffer_capacity(Buffer
*buf
) {
170 const char *buffer_content(Buffer
*buf
) {
174 const char *buffer_content0(Buffer
*buf
) {
175 if (buf
->len
== 0 || !buffer_terminate(buf
))
180 char *buffer_move(Buffer
*buf
) {
181 char *data
= buf
->data
;