You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
50 lines
1.6 KiB
50 lines
1.6 KiB
/* |
|
* strbuf.h — safe growable printf buffer |
|
* |
|
* Replaces snprintf(buf+off, sizeof(buf)-off, ...) chains that crash |
|
* on overflow (snprintf returns un-truncated size, offset exceeds buffer, |
|
* next call gets negative size → FORTIFY abort on Bionic/Android). |
|
* |
|
* Usage: |
|
* struct strbuf sb = strbuf_new(); |
|
* strbuf_addf(&sb, "{\"ver\":\"%d\"", ver); |
|
* strbuf_addf(&sb, ",\"name\":\"%s\"", name); |
|
* strbuf_addf(&sb, "}"); |
|
* // use strbuf_str(&sb) or strbuf_detach(&sb) |
|
* strbuf_free(&sb); |
|
*/ |
|
#ifndef STRBUF_H |
|
#define STRBUF_H |
|
|
|
#include <stddef.h> |
|
#include <stdarg.h> |
|
|
|
struct strbuf { |
|
char *buf; /* allocated buffer, always null-terminated */ |
|
size_t cap; /* total capacity (including '\0') */ |
|
size_t len; /* current length (excluding '\0') */ |
|
}; |
|
|
|
/* zero-init on stack: struct strbuf sb = {0}; */ |
|
#define strbuf_new() ((struct strbuf){NULL, 0, 0}) |
|
|
|
void strbuf_init(struct strbuf *sb, size_t initial_cap); |
|
void strbuf_free(struct strbuf *sb); |
|
|
|
/* returns buf and detaches — caller must u_free(). sb is reset to empty */ |
|
char *strbuf_detach(struct strbuf *sb); |
|
|
|
/* reset len=0, keep allocation */ |
|
void strbuf_reset(struct strbuf *sb); |
|
|
|
/* printf-like append. auto-grows. returns written bytes or -1 on OOM */ |
|
int strbuf_addf(struct strbuf *sb, const char *fmt, ...) |
|
__attribute__((format(printf, 2, 3))); |
|
|
|
void strbuf_addc(struct strbuf *sb, char c); |
|
void strbuf_adds(struct strbuf *sb, const char *s); |
|
|
|
/* safe accessor — never returns NULL */ |
|
#define strbuf_str(sb) ((sb)->buf ? (sb)->buf : "") |
|
|
|
#endif /* STRBUF_H */
|
|
|