1bcdc6a3bSJan Kneschke #ifndef _BUFFER_H_
2bcdc6a3bSJan Kneschke #define _BUFFER_H_
38abd06a7SGlenn Strauss #include "first.h"
4bcdc6a3bSJan Kneschke
504d76e7aSGlenn Strauss struct tm; /* declaration */
66afad87dSStefan Bühler
7e1bb5793SGlenn Strauss /**
8e1bb5793SGlenn Strauss * max size of a buffer which will just be reset
9e1bb5793SGlenn Strauss * to ->used = 0 instead of really freeing the buffer
10e1bb5793SGlenn Strauss */
11e1bb5793SGlenn Strauss #define BUFFER_MAX_REUSE_SIZE 4096
12e1bb5793SGlenn Strauss
136afad87dSStefan Bühler /* generic string + binary data container; contains a terminating 0 in both
146afad87dSStefan Bühler * cases
156afad87dSStefan Bühler *
16af3df29aSGlenn Strauss * used == 0 indicates a special "empty" state (unset config values);
17af3df29aSGlenn Strauss * ptr might be NULL, too.
186afad87dSStefan Bühler *
19af3df29aSGlenn Strauss * copy/append functions will ensure used >= 1
20af3df29aSGlenn Strauss * (i.e. never leave it in the special empty state)
216afad87dSStefan Bühler */
22bcdc6a3bSJan Kneschke typedef struct {
23bcdc6a3bSJan Kneschke char *ptr;
24bcdc6a3bSJan Kneschke
256afad87dSStefan Bühler /* "used" includes a terminating 0 */
2610d71279SGlenn Strauss uint32_t used;
276afad87dSStefan Bühler /* size of allocated buffer at *ptr */
2810d71279SGlenn Strauss uint32_t size;
29bcdc6a3bSJan Kneschke } buffer;
30bcdc6a3bSJan Kneschke
316afad87dSStefan Bühler /* create new buffer; either empty or copy given data */
32b38817b6SGlenn Strauss __attribute_malloc__
335c0c4936SGlenn Strauss __attribute_returns_nonnull__
34bcdc6a3bSJan Kneschke buffer* buffer_init(void);
355c0c4936SGlenn Strauss
366afad87dSStefan Bühler void buffer_free(buffer *b); /* b can be NULL */
37bcdc6a3bSJan Kneschke
386afad87dSStefan Bühler /* reset b. if NULL != b && NULL != src, move src content to b. reset src. */
39575665adSGlenn Strauss __attribute_nonnull__()
409914bb29SGlenn Strauss void buffer_move(buffer * restrict b, buffer * restrict src);
41bcdc6a3bSJan Kneschke
424365bdbeSStefan Bühler /* make sure buffer is large enough to store a string of given size
434365bdbeSStefan Bühler * and a terminating zero.
444365bdbeSStefan Bühler * sets b to an empty string, and may drop old content.
456afad87dSStefan Bühler * @return b->ptr
466afad87dSStefan Bühler */
47575665adSGlenn Strauss __attribute_nonnull__()
485c0c4936SGlenn Strauss __attribute_returns_nonnull__
491be163b4SStefan Bühler char* buffer_string_prepare_copy(buffer *b, size_t size);
504365bdbeSStefan Bühler
514365bdbeSStefan Bühler /* allocate buffer large enough to be able to append a string of given size
524365bdbeSStefan Bühler * if b was empty (used == 0) it will contain an empty string (used == 1)
534365bdbeSStefan Bühler * afterwards
544365bdbeSStefan Bühler * "used" data is preserved; if not empty buffer must contain a
554365bdbeSStefan Bühler * zero terminated string.
564365bdbeSStefan Bühler */
57575665adSGlenn Strauss __attribute_nonnull__()
585c0c4936SGlenn Strauss __attribute_returns_nonnull__
591be163b4SStefan Bühler char* buffer_string_prepare_append(buffer *b, size_t size);
601be163b4SStefan Bühler
6138c87358SGlenn Strauss /* extend and modify buffer for immediate addition of x bytes (differs from
6238c87358SGlenn Strauss * buffer_string_prepare_append() which only ensures space is available)
6338c87358SGlenn Strauss * returns pointer to which callers should immediately write x bytes
6438c87358SGlenn Strauss */
65575665adSGlenn Strauss __attribute_nonnull__()
6638c87358SGlenn Strauss __attribute_returns_nonnull__
6738c87358SGlenn Strauss char* buffer_extend(buffer * const restrict b, size_t x);
6838c87358SGlenn Strauss
696afad87dSStefan Bühler /* use after prepare_(copy,append) when you have written data to the buffer
706afad87dSStefan Bühler * to increase the buffer length by size. also sets the terminating zero.
716afad87dSStefan Bühler * requires enough space is present for the terminating zero (prepare with the
726afad87dSStefan Bühler * same size to be sure).
736afad87dSStefan Bühler */
74575665adSGlenn Strauss __attribute_nonnull__()
756afad87dSStefan Bühler void buffer_commit(buffer *b, size_t size);
76bcdc6a3bSJan Kneschke
77f69bd9cdSGlenn Strauss /* clear buffer
78f69bd9cdSGlenn Strauss * - invalidate buffer contents
79f69bd9cdSGlenn Strauss * - unsets used chars but does not modify existing ptr contents
80f69bd9cdSGlenn Strauss * (b->ptr *is not* set to an empty, '\0'-terminated string "")
81f69bd9cdSGlenn Strauss */
82575665adSGlenn Strauss __attribute_nonnull__()
83f69bd9cdSGlenn Strauss static inline void buffer_clear(buffer *b);
84f69bd9cdSGlenn Strauss
85b600b75fSGlenn Strauss /* reset buffer
86b600b75fSGlenn Strauss * - invalidate buffer contents
87b600b75fSGlenn Strauss * - unsets used chars
88b600b75fSGlenn Strauss * - keeps smaller buffer (unmodified) for reuse
89b600b75fSGlenn Strauss * (b->ptr *is not* set to an empty, '\0'-terminated string "")
90b600b75fSGlenn Strauss * - frees larger buffer (b->size > BUFFER_MAX_REUSE_SIZE)
91b600b75fSGlenn Strauss */
92575665adSGlenn Strauss __attribute_nonnull__()
93b600b75fSGlenn Strauss static inline void buffer_reset(buffer *b);
94b600b75fSGlenn Strauss
95b600b75fSGlenn Strauss /* free buffer ptr
96b600b75fSGlenn Strauss * - invalidate buffer contents; free ptr; reset ptr, used, size to 0
97b600b75fSGlenn Strauss */
98b600b75fSGlenn Strauss __attribute_cold__
99575665adSGlenn Strauss __attribute_nonnull__()
100b600b75fSGlenn Strauss void buffer_free_ptr(buffer *b);
101b600b75fSGlenn Strauss
1029914bb29SGlenn Strauss void buffer_copy_string(buffer * restrict b, const char * restrict s);
10338c87358SGlenn Strauss void buffer_copy_string_len(buffer * restrict b, const char * restrict s, size_t len);
104f490078dSGlenn Strauss void buffer_copy_string_len_lc(buffer * restrict b, const char * restrict s, size_t len);
10575fae49eSJan Kneschke
1069914bb29SGlenn Strauss void buffer_append_string(buffer * restrict b, const char * restrict s);
10738c87358SGlenn Strauss void buffer_append_string_len(buffer * restrict b, const char * restrict s, size_t len);
108e7464babSGlenn Strauss void buffer_append_str2(buffer * restrict b, const char *s1, size_t len1, const char *s2, size_t len2);
109e7464babSGlenn Strauss void buffer_append_str3(buffer * restrict b, const char *s1, size_t len1, const char *s2, size_t len2, const char *s3, size_t len3);
110bcdc6a3bSJan Kneschke
111db4af125SGlenn Strauss #ifndef LI_CONST_IOVEC
112db4af125SGlenn Strauss #define LI_CONST_IOVEC
113e7464babSGlenn Strauss struct const_iovec {
114e7464babSGlenn Strauss const void *iov_base;
115e7464babSGlenn Strauss size_t iov_len;
116e7464babSGlenn Strauss };
117db4af125SGlenn Strauss #endif
118e7464babSGlenn Strauss
119575665adSGlenn Strauss __attribute_nonnull__()
120e7464babSGlenn Strauss void buffer_append_iovec(buffer * restrict b, const struct const_iovec *iov, size_t n);
121e7464babSGlenn Strauss
1223d880810SGlenn Strauss #define buffer_append_uint_hex(b,len) buffer_append_uint_hex_lc((b),(len))
123575665adSGlenn Strauss __attribute_nonnull__()
1243d880810SGlenn Strauss void buffer_append_uint_hex_lc(buffer *b, uintmax_t len);
125575665adSGlenn Strauss __attribute_nonnull__()
1266afad87dSStefan Bühler void buffer_append_int(buffer *b, intmax_t val);
1276afad87dSStefan Bühler
1289914bb29SGlenn Strauss void buffer_append_strftime(buffer * restrict b, const char * restrict format, const struct tm * restrict tm);
129ad3e93eaSStefan Bühler
1306afad87dSStefan Bühler /* '-', log_10 (2^bits) = bits * log 2 / log 10 < bits * 0.31, terminating 0 */
1316afad87dSStefan Bühler #define LI_ITOSTRING_LENGTH (2 + (8 * sizeof(intmax_t) * 31 + 99) / 100)
1326afad87dSStefan Bühler
133575665adSGlenn Strauss __attribute_nonnull__()
134f24e6d69SGlenn Strauss size_t li_itostrn(char *buf, size_t buf_len, intmax_t val);
135575665adSGlenn Strauss __attribute_nonnull__()
136f24e6d69SGlenn Strauss size_t li_utostrn(char *buf, size_t buf_len, uintmax_t val);
137bcdc6a3bSJan Kneschke
138ad3e93eaSStefan Bühler /* buf must be (at least) 2*s_len + 1 big. uses lower-case hex letters. */
139d3cf141dSGlenn Strauss #define li_tohex(buf,buf_len,s,s_len) li_tohex_lc((buf),(buf_len),(s),(s_len))
140575665adSGlenn Strauss __attribute_nonnull__()
1419914bb29SGlenn Strauss void li_tohex_lc(char * restrict buf, size_t buf_len, const char * restrict s, size_t s_len);
142575665adSGlenn Strauss __attribute_nonnull__()
1439914bb29SGlenn Strauss void li_tohex_uc(char * restrict buf, size_t buf_len, const char * restrict s, size_t s_len);
144ad3e93eaSStefan Bühler
145575665adSGlenn Strauss __attribute_nonnull__()
146ac8444f2SGlenn Strauss __attribute_pure__
147ac8444f2SGlenn Strauss int buffer_eq_icase_ssn(const char * const a, const char * const b, const size_t len);
148ac8444f2SGlenn Strauss
149575665adSGlenn Strauss __attribute_nonnull__()
150ac8444f2SGlenn Strauss __attribute_pure__
151ac8444f2SGlenn Strauss int buffer_eq_icase_ss(const char * const a, const size_t alen, const char * const b, const size_t blen);
152ac8444f2SGlenn Strauss
153575665adSGlenn Strauss __attribute_nonnull__()
154ac8444f2SGlenn Strauss __attribute_pure__
155ac8444f2SGlenn Strauss int buffer_eq_icase_slen(const buffer * const b, const char * const s, const size_t slen);
156ac8444f2SGlenn Strauss
157575665adSGlenn Strauss __attribute_nonnull__()
158ac8444f2SGlenn Strauss __attribute_pure__
159ac8444f2SGlenn Strauss int buffer_eq_slen(const buffer * const b, const char * const s, const size_t slen);
160ac8444f2SGlenn Strauss
161575665adSGlenn Strauss __attribute_nonnull__()
16272d4fe74SGlenn Strauss __attribute_pure__
16366ad587fSStefan Bühler int buffer_is_equal(const buffer *a, const buffer *b);
16472d4fe74SGlenn Strauss
165575665adSGlenn Strauss __attribute_nonnull__()
1669914bb29SGlenn Strauss void buffer_substr_replace (buffer * restrict b, size_t offset, size_t len, const buffer * restrict replace);
16705c34ce4SGlenn Strauss
168575665adSGlenn Strauss __attribute_nonnull__()
1699914bb29SGlenn Strauss void buffer_append_string_encoded_hex_lc(buffer * restrict b, const char * restrict s, size_t len);
170575665adSGlenn Strauss __attribute_nonnull__()
1719914bb29SGlenn Strauss void buffer_append_string_encoded_hex_uc(buffer * restrict b, const char * restrict s, size_t len);
172936db51fSGlenn Strauss
173976f3218SJan Kneschke typedef enum {
174976f3218SJan Kneschke ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
175976f3218SJan Kneschke ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
176976f3218SJan Kneschke ENCODING_HTML, /* & becomes & and so on */
17783cdf286SGlenn Strauss ENCODING_MINIMAL_XML /* minimal encoding for xml */
178976f3218SJan Kneschke } buffer_encoding_t;
179976f3218SJan Kneschke
1809914bb29SGlenn Strauss void buffer_append_string_encoded(buffer * restrict b, const char * restrict s, size_t s_len, buffer_encoding_t encoding);
181bcdc6a3bSJan Kneschke
182427120b4SStefan Bühler /* escape non-printable characters; simple escapes for \t, \r, \n; fallback to \xCC */
183575665adSGlenn Strauss __attribute_nonnull__()
1849914bb29SGlenn Strauss void buffer_append_string_c_escaped(buffer * restrict b, const char * restrict s, size_t s_len);
185427120b4SStefan Bühler
186d22e88b7SGlenn Strauss /* escape non-printable chars, '"', '\\', and chars which high bit set */
187*91ce3b08SGlenn Strauss void buffer_append_bs_escaped (buffer * restrict b, const char * restrict s, size_t len);
188*91ce3b08SGlenn Strauss void buffer_append_bs_escaped_json (buffer * restrict b, const char * restrict s, size_t len);
189d22e88b7SGlenn Strauss
190575665adSGlenn Strauss __attribute_nonnull__()
191006c5efcSGlenn Strauss void buffer_urldecode_path(buffer *b);
19219bc8885SGlenn Strauss
193575665adSGlenn Strauss __attribute_nonnull__()
19419bc8885SGlenn Strauss __attribute_pure__
19580638252SGlenn Strauss int buffer_is_valid_UTF8(const buffer *b);
19619bc8885SGlenn Strauss
197575665adSGlenn Strauss __attribute_nonnull__()
198980554bcSGlenn Strauss void buffer_path_simplify(buffer *b);
199bcdc6a3bSJan Kneschke
200575665adSGlenn Strauss __attribute_nonnull__()
2016afad87dSStefan Bühler void buffer_to_lower(buffer *b);
202575665adSGlenn Strauss __attribute_nonnull__()
2036afad87dSStefan Bühler void buffer_to_upper(buffer *b);
2046afad87dSStefan Bühler
205f8687d3fSJan Kneschke
206bcdc6a3bSJan Kneschke /** deprecated */
20719bc8885SGlenn Strauss __attribute_const__
208bcdc6a3bSJan Kneschke char hex2int(unsigned char c);
209bcdc6a3bSJan Kneschke
210e110b062SGlenn Strauss int li_hex2bin (unsigned char *bin, size_t binlen, const char *hexstr, size_t len);
211e110b062SGlenn Strauss
21272d4fe74SGlenn Strauss __attribute_pure__
2136ebd2897SGlenn Strauss static inline int light_isdigit(int c);
light_isdigit(int c)2146ebd2897SGlenn Strauss static inline int light_isdigit(int c) {
215c58b95f2SGlenn Strauss return ((uint32_t)c-'0' <= '9'-'0');
2166ebd2897SGlenn Strauss }
2176ebd2897SGlenn Strauss
21872d4fe74SGlenn Strauss __attribute_pure__
21972d4fe74SGlenn Strauss static inline int light_isxdigit(int c);
light_isxdigit(int c)2206ebd2897SGlenn Strauss static inline int light_isxdigit(int c) {
221c58b95f2SGlenn Strauss return light_isdigit(c) || (((uint32_t)c | 0x20)-'a' <= 'f'-'a');
2226ebd2897SGlenn Strauss }
2236ebd2897SGlenn Strauss
22472d4fe74SGlenn Strauss __attribute_pure__
22572d4fe74SGlenn Strauss static inline int light_isalpha(int c);
light_isalpha(int c)2266ebd2897SGlenn Strauss static inline int light_isalpha(int c) {
227c58b95f2SGlenn Strauss return (((uint32_t)c | 0x20)-'a' <= 'z'-'a');
2286ebd2897SGlenn Strauss }
2296ebd2897SGlenn Strauss
23072d4fe74SGlenn Strauss __attribute_pure__
23172d4fe74SGlenn Strauss static inline int light_isalnum(int c);
light_isalnum(int c)2326ebd2897SGlenn Strauss static inline int light_isalnum(int c) {
2336ebd2897SGlenn Strauss return light_isdigit(c) || light_isalpha(c);
2346ebd2897SGlenn Strauss }
2356ebd2897SGlenn Strauss
236c58b95f2SGlenn Strauss #define light_isupper(c) ((uint32_t)(c)-'A' <= 'Z'-'A')
237c58b95f2SGlenn Strauss #define light_islower(c) ((uint32_t)(c)-'a' <= 'z'-'a')
238c58b95f2SGlenn Strauss
239367f30a6SGlenn Strauss #define light_bshift(b) ((uint64_t)1uL << (b))
240367f30a6SGlenn Strauss #define light_btst(a,b) ((a) & ((uint64_t)1uL << (b)))
241367f30a6SGlenn Strauss #define light_bclr(a,b) ((a) &= ~((uint64_t)1uL << (b)))
242367f30a6SGlenn Strauss #define light_bset(a,b) ((a) |= ((uint64_t)1uL << (b)))
2439c8981a7SGlenn Strauss
244bcdc6a3bSJan Kneschke
2459914bb29SGlenn Strauss void buffer_append_path_len(buffer * restrict b, const char * restrict a, size_t alen); /* join strings with '/', if '/' not present */
246680e6b3bSGlenn Strauss void buffer_copy_path_len2(buffer * restrict b, const char * restrict s1, size_t len1, const char * restrict s2, size_t len2);
2476afad87dSStefan Bühler
248575665adSGlenn Strauss __attribute_nonnull__()
24981ef66eaSGlenn Strauss __attribute_pure__
25081ef66eaSGlenn Strauss static inline int buffer_has_slash_suffix (const buffer * const b);
25181ef66eaSGlenn Strauss
252575665adSGlenn Strauss __attribute_nonnull__()
25381ef66eaSGlenn Strauss __attribute_pure__
25481ef66eaSGlenn Strauss static inline int buffer_has_pathsep_suffix (const buffer * const b);
25581ef66eaSGlenn Strauss
256af3df29aSGlenn Strauss #define BUFFER_INTLEN_PTR(x) (int)buffer_clen(x), (x)->ptr
257af3df29aSGlenn Strauss #define BUF_PTR_LEN(x) (x)->ptr, buffer_clen(x)
2584183e723SGlenn Strauss
259be04c123SGlenn Strauss #define CONST_LEN_STR(x) (uint32_t)sizeof(x)-1, x
260be04c123SGlenn Strauss #define CONST_STR_LEN(x) x, (uint32_t)sizeof(x) - 1
261bcdc6a3bSJan Kneschke
262bcdc6a3bSJan Kneschke
2636afad87dSStefan Bühler /* inline implementations */
2646afad87dSStefan Bühler
265575665adSGlenn Strauss __attribute_nonnull__()
266af3df29aSGlenn Strauss __attribute_pure__
267af3df29aSGlenn Strauss static inline int buffer_is_unset(const buffer *b);
buffer_is_unset(const buffer * b)268af3df29aSGlenn Strauss static inline int buffer_is_unset(const buffer *b) {
269af3df29aSGlenn Strauss return 0 == b->used;
270ac143eadSGlenn Strauss }
271ac143eadSGlenn Strauss
272575665adSGlenn Strauss __attribute_nonnull__()
273af3df29aSGlenn Strauss __attribute_pure__
274af3df29aSGlenn Strauss static inline int buffer_is_blank(const buffer *b);
buffer_is_blank(const buffer * b)275af3df29aSGlenn Strauss static inline int buffer_is_blank(const buffer *b) {
276af3df29aSGlenn Strauss return b->used < 2; /* buffer_is_blank() || buffer_is_unset() */
2776afad87dSStefan Bühler }
2786afad87dSStefan Bühler
279af3df29aSGlenn Strauss /* buffer "C" len (bytes) */
280575665adSGlenn Strauss __attribute_nonnull__()
281af3df29aSGlenn Strauss __attribute_pure__
282af3df29aSGlenn Strauss static inline uint32_t buffer_clen (const buffer *b);
buffer_clen(const buffer * b)283af3df29aSGlenn Strauss static inline uint32_t buffer_clen (const buffer *b) {
284af3df29aSGlenn Strauss return b->used - (0 != b->used);
285af3df29aSGlenn Strauss }
286af3df29aSGlenn Strauss
287af3df29aSGlenn Strauss /* buffer space remaining to append string without reallocating */
288575665adSGlenn Strauss __attribute_nonnull__()
289af3df29aSGlenn Strauss __attribute_pure__
290af3df29aSGlenn Strauss static inline uint32_t buffer_string_space(const buffer *b);
buffer_string_space(const buffer * b)29110d71279SGlenn Strauss static inline uint32_t buffer_string_space(const buffer *b) {
292cfc8eeb5SGlenn Strauss return b->size ? b->size - (b->used | (0 == b->used)) : 0;
2931be163b4SStefan Bühler }
2941be163b4SStefan Bühler
295575665adSGlenn Strauss __attribute_nonnull__()
296af3df29aSGlenn Strauss static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src);
buffer_copy_buffer(buffer * restrict b,const buffer * restrict src)2979914bb29SGlenn Strauss static inline void buffer_copy_buffer(buffer * restrict b, const buffer * restrict src) {
298af3df29aSGlenn Strauss buffer_copy_string_len(b, BUF_PTR_LEN(src));
299cf93e91cSGlenn Strauss }
300cf93e91cSGlenn Strauss
301575665adSGlenn Strauss __attribute_nonnull__()
302af3df29aSGlenn Strauss static inline void buffer_append_buffer(buffer * restrict b, const buffer * restrict src);
buffer_append_buffer(buffer * restrict b,const buffer * restrict src)303af3df29aSGlenn Strauss static inline void buffer_append_buffer(buffer * restrict b, const buffer * restrict src) {
304af3df29aSGlenn Strauss buffer_append_string_len(b, BUF_PTR_LEN(src));
3055fe93399SGlenn Strauss }
3065fe93399SGlenn Strauss
307575665adSGlenn Strauss __attribute_nonnull__()
308af3df29aSGlenn Strauss static inline void buffer_truncate(buffer *b, uint32_t len);
buffer_truncate(buffer * b,uint32_t len)309af3df29aSGlenn Strauss static inline void buffer_truncate(buffer *b, uint32_t len) {
310af3df29aSGlenn Strauss b->ptr[len] = '\0'; /* b->ptr must exist; use buffer_blank() for trunc 0 */
311af3df29aSGlenn Strauss b->used = len + 1;
312af3df29aSGlenn Strauss }
313af3df29aSGlenn Strauss
314575665adSGlenn Strauss __attribute_nonnull__()
315af3df29aSGlenn Strauss static inline void buffer_blank(buffer *b);
buffer_blank(buffer * b)316af3df29aSGlenn Strauss static inline void buffer_blank(buffer *b) {
317af3df29aSGlenn Strauss b->ptr ? buffer_truncate(b, 0) : (void)buffer_extend(b, 0);
318af3df29aSGlenn Strauss }
319af3df29aSGlenn Strauss
320f70409d2SGlenn Strauss __attribute_nonnull__()
321f70409d2SGlenn Strauss static inline void buffer_append_char (buffer *b, char c);
buffer_append_char(buffer * b,char c)322f70409d2SGlenn Strauss static inline void buffer_append_char (buffer *b, char c) {
323f70409d2SGlenn Strauss *(buffer_extend(b, 1)) = c;
324f70409d2SGlenn Strauss }
325f70409d2SGlenn Strauss
326af3df29aSGlenn Strauss /* append '/' to non-empty strings not ending in '/' */
327575665adSGlenn Strauss __attribute_nonnull__()
328af3df29aSGlenn Strauss static inline void buffer_append_slash(buffer *b);
buffer_append_slash(buffer * b)3296afad87dSStefan Bühler static inline void buffer_append_slash(buffer *b) {
330af3df29aSGlenn Strauss const uint32_t len = buffer_clen(b);
331af3df29aSGlenn Strauss if (len > 0 && '/' != b->ptr[len-1])
332f70409d2SGlenn Strauss buffer_append_char(b, '/');
3336afad87dSStefan Bühler }
3346afad87dSStefan Bühler
buffer_clear(buffer * b)335f69bd9cdSGlenn Strauss static inline void buffer_clear(buffer *b) {
336f69bd9cdSGlenn Strauss b->used = 0;
337f69bd9cdSGlenn Strauss }
338f69bd9cdSGlenn Strauss
buffer_reset(buffer * b)339b600b75fSGlenn Strauss static inline void buffer_reset(buffer *b) {
340b600b75fSGlenn Strauss b->used = 0;
341b600b75fSGlenn Strauss /* release buffer larger than BUFFER_MAX_REUSE_SIZE bytes */
342b600b75fSGlenn Strauss if (b->size > BUFFER_MAX_REUSE_SIZE) buffer_free_ptr(b);
343b600b75fSGlenn Strauss }
344b600b75fSGlenn Strauss
buffer_has_slash_suffix(const buffer * const b)34581ef66eaSGlenn Strauss static inline int buffer_has_slash_suffix (const buffer * const b) {
34681ef66eaSGlenn Strauss return (b->used > 1 && b->ptr[b->used-2] == '/');
34781ef66eaSGlenn Strauss }
34881ef66eaSGlenn Strauss
buffer_has_pathsep_suffix(const buffer * const b)34981ef66eaSGlenn Strauss static inline int buffer_has_pathsep_suffix (const buffer * const b) {
35081ef66eaSGlenn Strauss return (b->used > 1 && b->ptr[b->used-2] == '/');
35181ef66eaSGlenn Strauss }
352b600b75fSGlenn Strauss
353af3df29aSGlenn Strauss
354af3df29aSGlenn Strauss /* backwards compat (deprecated; older interfaces) */
355af3df29aSGlenn Strauss
356af3df29aSGlenn Strauss #define buffer_append_string_buffer buffer_append_buffer
357af3df29aSGlenn Strauss #define buffer_is_equal_caseless_string buffer_eq_icase_slen
358af3df29aSGlenn Strauss #define buffer_is_equal_string buffer_eq_slen
359af3df29aSGlenn Strauss
360af3df29aSGlenn Strauss #define BUFFER_APPEND_STRING_CONST(x, y) \
361af3df29aSGlenn Strauss buffer_append_string_len(x, y, sizeof(y) - 1)
362af3df29aSGlenn Strauss
363af3df29aSGlenn Strauss #define BUFFER_COPY_STRING_CONST(x, y) \
364af3df29aSGlenn Strauss buffer_copy_string_len(x, y, sizeof(y) - 1)
365af3df29aSGlenn Strauss
366af3df29aSGlenn Strauss #define CONST_BUF_LEN(x) ((x) ? (x)->ptr : NULL), buffer_string_length(x)
367af3df29aSGlenn Strauss
368af3df29aSGlenn Strauss /* NULL buffer or empty buffer (used == 0);
369af3df29aSGlenn Strauss * unset "string" (buffer) config options are initialized to used == 0,
370af3df29aSGlenn Strauss * while setting an empty string leads to used == 1
371af3df29aSGlenn Strauss */
372af3df29aSGlenn Strauss __attribute_pure__
373af3df29aSGlenn Strauss static inline int buffer_is_empty(const buffer *b);
buffer_is_empty(const buffer * b)374af3df29aSGlenn Strauss static inline int buffer_is_empty(const buffer *b) {
375af3df29aSGlenn Strauss return NULL == b || buffer_is_unset(b);
376af3df29aSGlenn Strauss }
377af3df29aSGlenn Strauss /* NULL buffer, empty buffer (used == 0) or empty string (used == 1) */
378af3df29aSGlenn Strauss __attribute_pure__
379af3df29aSGlenn Strauss static inline int buffer_string_is_empty(const buffer *b);
buffer_string_is_empty(const buffer * b)380af3df29aSGlenn Strauss static inline int buffer_string_is_empty(const buffer *b) {
381af3df29aSGlenn Strauss return NULL == b || buffer_is_blank(b);
382af3df29aSGlenn Strauss }
383af3df29aSGlenn Strauss
384af3df29aSGlenn Strauss /* buffer string length without terminating 0 */
385af3df29aSGlenn Strauss __attribute_pure__
386af3df29aSGlenn Strauss static inline uint32_t buffer_string_length(const buffer *b);
buffer_string_length(const buffer * b)387af3df29aSGlenn Strauss static inline uint32_t buffer_string_length(const buffer *b) {
388af3df29aSGlenn Strauss return NULL != b ? buffer_clen(b) : 0;
389af3df29aSGlenn Strauss }
390af3df29aSGlenn Strauss
391af3df29aSGlenn Strauss /* sets string length:
392af3df29aSGlenn Strauss * - deprecated; use buffer_truncate() or buffer_extend() instead
393af3df29aSGlenn Strauss * - always stores a terminating zero to terminate the "new" string
394af3df29aSGlenn Strauss * - does not modify the string data apart from terminating zero
395af3df29aSGlenn Strauss * - reallocates the buffer iff needed
396af3df29aSGlenn Strauss */
397575665adSGlenn Strauss __attribute_nonnull__()
398af3df29aSGlenn Strauss static inline void buffer_string_set_length(buffer *b, uint32_t len);
buffer_string_set_length(buffer * b,uint32_t len)399af3df29aSGlenn Strauss static inline void buffer_string_set_length(buffer *b, uint32_t len) {
400af3df29aSGlenn Strauss if (len < b->size)
401af3df29aSGlenn Strauss buffer_truncate(b, len);
402af3df29aSGlenn Strauss else
403af3df29aSGlenn Strauss buffer_extend(b, len - buffer_clen(b));
404af3df29aSGlenn Strauss }
405af3df29aSGlenn Strauss
406af3df29aSGlenn Strauss
4071cd73b08SGlenn Strauss #include "ck.h"
4081cd73b08SGlenn Strauss #define force_assert(x) ck_assert(x)
4091cd73b08SGlenn Strauss #define log_failed_assert(file,line,msg) ck_bt_abort((file),(line),(msg))
4101cd73b08SGlenn Strauss #define SEGFAULT() ck_bt_abort(__FILE__, __LINE__, "aborted")
4111cd73b08SGlenn Strauss
4121cd73b08SGlenn Strauss
413bcdc6a3bSJan Kneschke #endif
414