2 * Copyright © 2006,2007,2008 Pierre Habouzit
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The names of its contributors may not be used to endorse or promote
14 * products derived from this software without specific prior written
17 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 #ifndef AWESOME_COMMON_BUFFER_H
31 #define AWESOME_COMMON_BUFFER_H
33 #include "common/util.h"
35 typedef struct buffer_t
43 extern char buffer_slop
[1];
45 #define BUFFER_INIT (buffer_t) { .s = buffer_slop, .size = 1 }
47 #define buffer_inita(b, sz) \
48 ({ int __sz = (sz); assert (__sz < (64 << 10)); \
49 buffer_init_buf((b), alloca(__sz), __sz); })
51 /** Initialize a buffer.
52 * \param buf A buffer pointer.
53 * \return The same buffer pointer.
55 static inline buffer_t
*
56 buffer_init(buffer_t
*buf
)
62 /** Initialize a buffer with data.
63 * \param b The buffer to ini.
64 * \param buf The data to set.
65 * \param size Data size.
68 buffer_init_buf(buffer_t
*b
, void *buf
, int size
)
70 *b
= (buffer_t
){ .s
= buf
, .size
= size
};
75 * \param buf The buffer.
78 buffer_wipe(buffer_t
*buf
)
81 free(buf
->s
- buf
->offs
);
86 * \return A new allocatedbuffer.
88 static inline buffer_t
*
91 return buffer_init(p_new(buffer_t
, 1));
95 * \param buf A pointer to a buffer pointer to free.
98 buffer_delete(buffer_t
**buf
)
107 char *buffer_detach(buffer_t
*buf
);
108 void buffer_ensure(buffer_t
*buf
, int len
);
111 * \param buf The buffer to grow.
112 * \param extra The number to add to length.
115 buffer_grow(buffer_t
*buf
, int extra
)
118 if (buf
->len
+ extra
> buf
->size
)
120 buffer_ensure(buf
, buf
->len
+ extra
);
124 /** Add data in the buffer.
125 * \param buf Buffer where to add.
126 * \param pos Position where to add.
128 * \param data Data to add.
129 * \param dlen Data length.
132 buffer_splice(buffer_t
*buf
, int pos
, int len
, const void *data
, int dlen
)
134 assert (pos
>= 0 && len
>= 0 && dlen
>= 0);
136 if (unlikely(pos
> buf
->len
))
138 if (unlikely(len
> buf
->len
- pos
))
139 len
= buf
->len
- pos
;
140 if (pos
== 0 && len
+ buf
->offs
>= dlen
)
142 buf
->offs
+= len
- dlen
;
143 buf
->s
+= len
- dlen
;
144 buf
->size
-= len
- dlen
;
145 buf
->len
-= len
- dlen
;
148 else if (len
!= dlen
)
150 buffer_ensure(buf
, buf
->len
+ dlen
- len
);
151 memmove(buf
->s
+ pos
+ dlen
, buf
->s
+ pos
+ len
, buf
->len
- pos
- len
);
152 buf
->len
+= dlen
- len
;
153 buf
->s
[buf
->len
] = '\0';
155 memcpy(buf
->s
+ pos
, data
, dlen
);
158 /** Add data at the end of buffer.
159 * \param buf Buffer where to add.
160 * \param data Data to add.
161 * \param len Data length.
164 buffer_add(buffer_t
*buf
, const void *data
, int len
)
166 buffer_splice(buf
, buf
->len
, 0, data
, len
);
169 /** Add a string to the and of a buffer.
170 * \param buf The buffer where to add.
171 * \param s The string to add.
173 static inline void buffer_adds(buffer_t
*buf
, const char *s
)
175 buffer_splice(buf
, buf
->len
, 0, s
, strlen(s
));
178 /** Add a char at the end of a buffer.
179 * \param buf The buffer where to add.
180 * \param c The char to add.
182 static inline void buffer_addc(buffer_t
*buf
, int c
)
185 buf
->s
[buf
->len
++] = c
;
186 buf
->s
[buf
->len
] = '\0';
189 void buffer_addvf(buffer_t
*buf
, const char *fmt
, va_list)
190 __attribute__((format(printf
, 2, 0)));
192 void buffer_addf(buffer_t
*buf
, const char *fmt
, ...)
193 __attribute__((format(printf
, 2, 3)));
196 void buffer_add_xmlescaped(buffer_t
*buf
, const char *s
);