1 /* multi-purpose string _strbuf, will be initialized to be
2 * at least 1024 bytes long.
14 #include "fmtmacros.h"
19 size_t sz; /* allocated size */
20 size_t end; /* offset to terminating null byte */
23 static inline void realloc_strbuf(struct _strbuf *str, size_t nusz, const char* what)
26 REALLOC(str->buf, nusz, what);
31 static inline void reset_strbuf(struct _strbuf *str)
34 if (str->buf) str->buf[0] = '\0';
37 static inline void init_strbuf(struct _strbuf *str, const char *what)
41 realloc_strbuf(str, 1024, what);
45 static inline void free_strbuf(struct _strbuf *str)
52 static inline void strbuf_append(const char *what, struct _strbuf *str, const char *fmt, ...)
55 size_t room = str->sz - str->end - 1;
58 /* write if we have room */
60 written = vsnprintf(str->buf + str->end, room, fmt, ap);
63 /* if we would have written more, we need to expand the storage */
64 if (written >= room) {
65 realloc_strbuf(str, str->end + written + 1, what);
66 room = str->sz - str->end;
70 written = vsnprintf(str->buf + str->end, room, fmt, ap);
76 static inline void strbuf_append_str_len(const char *what, struct _strbuf *str,
77 const char *to_append, /* string to append */
78 size_t len) /* length of string to append */
80 size_t room = str->sz - str->end - 1;
83 realloc_strbuf(str, str->end + len + 1, what);
85 /* copy up to the terminating NULL */
86 memcpy(str->buf + str->end, to_append, len);
88 /* ensure we have a NULL in last position, since len may have been used
89 * to override the original string length */
90 str->buf[str->end] = '\0';
93 static inline void strbuf_append_str(const char *what, struct _strbuf *str, const char *to_append)
95 strbuf_append_str_len(what, str, to_append, strlen(to_append));
98 #define GET_STRING(str, err, cmd, param, param_str, ...) do { \
100 err = cmd(__VA_ARGS__, param, 0, NULL, &nusz); \
101 if (REPORT_ERROR(str, err, "get " param_str " size")) break; \
102 realloc_strbuf(str, nusz, #param); \
103 err = cmd(__VA_ARGS__, param, (str)->sz, (str)->buf, NULL); \
104 if (REPORT_ERROR(str, err, "get " param_str)) break; \
108 #define GET_STRING_LOC(ret, loc, cmd, ...) do { \
110 ret->err = REPORT_ERROR_LOC(ret, \
111 cmd(__VA_ARGS__, 0, NULL, &nusz), \
112 loc, "get %s size"); \
114 realloc_strbuf(&ret->str, nusz, loc->sname); \
115 ret->err = REPORT_ERROR_LOC(ret, \
116 cmd(__VA_ARGS__, ret->str.sz, ret->str.buf, NULL), \
120 ret->str.end = nusz; \
124 /* Skip leading whitespace in a string */
125 static inline const char* skip_leading_ws(const char *str)
127 const char *ret = str;
128 while (isspace((unsigned char) *ret)) ++ret;
132 /* Separators: we want to be able to prepend separators as needed to _strbuf,
133 * which we do only if halfway through the buffer. The callers should first
134 * call a 'set_separator' and then use add_separator(&offset) to add it, where szval
135 * is an offset inside the buffer, which will be incremented as needed
141 void set_separator(const char* _sep)