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
|
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "macro.h"
/*
* Buffer abstract data type
*/
struct strbuf {
char *bytes;
size_t size;
size_t used;
bool heap;
};
/*
* Declare and initialize strbuf without any initial storage
*/
#define DECLARE_STRBUF(name__) \
_cleanup_strbuf_ struct strbuf name__ = { \
.heap = true, \
}
/*
* Declare and initialize strbuf with an initial buffer on stack. The @sz__ must be a
* build-time constant, as if the buffer had been declared on stack.
*/
#define DECLARE_STRBUF_WITH_STACK(name__, sz__) \
assert_cc(__builtin_constant_p(sz__)); \
char name__##_storage__[sz__]; \
_cleanup_strbuf_ struct strbuf name__ = { \
.bytes = name__##_storage__, \
.size = sz__, \
}
void strbuf_init(struct strbuf *buf);
void strbuf_release(struct strbuf *buf);
#define _cleanup_strbuf_ _cleanup_(strbuf_release)
void strbuf_clear(struct strbuf *buf);
/*
* Return a copy as a C string, guaranteed to be nul-terminated. On success, the @buf
* becomes invalid and shouldn't be used anymore, except for an (optional) call to
* strbuf_release() which still does the right thing on an invalidated buffer. On failure,
* NULL is returned and the buffer remains valid: strbuf_release() should be called.
* Consider using _cleanup_strbuf_ attribute to release the buffer as needed.
*
* The copy may use the same underlying storage as the buffer and should be free'd later
* with free().
*/
char *strbuf_steal(struct strbuf *buf);
/*
* Return a C string owned by the buffer. It becomes an invalid
* pointer if strbuf is changed. It may also not survive a return
* from current function if it was initialized with stack space
*/
const char *strbuf_str(struct strbuf *buf);
/*
* Reserve enough space for @n bytes, ensuring additional pushes up to @n bytes
* don't cause re-allocations
*/
bool strbuf_reserve_extra(struct strbuf *buf, size_t n);
bool strbuf_pushchar(struct strbuf *buf, char ch);
size_t strbuf_pushmem(struct strbuf *buf, const char *src, size_t sz);
static inline size_t strbuf_pushchars(struct strbuf *buf, const char *str)
{
return strbuf_pushmem(buf, str, strlen(str));
}
/*
* Remove the last char from buf.
*
* No reallocation is done, so it's guaranteed @buf will have at least 1 char available to
* be filled after this call, as long as @buf wasn't empty.
*/
void strbuf_popchar(struct strbuf *buf);
/*
* Remove the last @n chars from buf.
*
* No reallocation is done, so it's guaranteed @buf will have at least @n chars available
* to be filled after this call, as long as @buf had @n chars allocated before.
*
* Example:
*
* struct strbuf buf;
* strbuf_init(&buf);
* strbuf_pushchars(&buf, "foobar");
* strbuf_popchars(&buf, 5);
*
* After these calls @buf is [ 'f', x, x, x, ... ], where "x" means undefined. However it's
* guaranteed to have (at least) 5 chars available without needing to reallocate.
*/
void strbuf_popchars(struct strbuf *buf, size_t n);
/*
* Shrink buffer to the final size @sz, which must be less or equal the current size.
*/
void strbuf_shrink_to(struct strbuf *buf, size_t sz);
/*
* Return number of used chars. This may different than calling strlen() in a C string
* since '\0' is considered a valid char - this only keeps track of how many slots are
* used in the underlying storage.
*
* If used knows '\0' has not been added (e.g. when calling just strbuf_pushchars() and
* similar), then the result matches the output of strlen().
*/
static inline size_t strbuf_used(struct strbuf *buf)
{
return buf->used;
}
|