1e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#ifndef __PERF_STRBUF_H 2e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define __PERF_STRBUF_H 3e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 4e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* 5e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Strbuf's can be use in many ways: as a byte array, or to store arbitrary 6e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * long, overflow safe strings. 7e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 8e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Strbufs has some invariants that are very important to keep in mind: 9e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 10e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 1. the ->buf member is always malloc-ed, hence strbuf's can be used to 11e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * build complex strings/buffers whose final size isn't easily known. 12e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 13e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * It is NOT legal to copy the ->buf pointer away. 14e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * `strbuf_detach' is the operation that detachs a buffer from its shell 15e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * while keeping the shell valid wrt its invariants. 16e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 17e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 2. the ->buf member is a byte array that has at least ->len + 1 bytes 18e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * allocated. The extra byte is used to store a '\0', allowing the ->buf 19e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * member to be a valid C-string. Every strbuf function ensure this 20e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * invariant is preserved. 21e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 22e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Note that it is OK to "play" with the buffer directly if you work it 23e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * that way: 24e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 25e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * strbuf_grow(sb, SOME_SIZE); 26e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * ... Here, the memory array starting at sb->buf, and of length 27e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * ... strbuf_avail(sb) is all yours, and you are sure that 28e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * ... strbuf_avail(sb) is at least SOME_SIZE. 29e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * strbuf_setlen(sb, sb->len + SOME_OTHER_SIZE); 30e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 31e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Of course, SOME_OTHER_SIZE must be smaller or equal to strbuf_avail(sb). 32e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 33e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * Doing so is safe, though if it has to be done in many places, adding the 34e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * missing API to the strbuf module is the way to go. 35e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * 36e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * XXX: do _not_ assume that the area that is yours is of size ->alloc - 1 37e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * even if it's true in the current implementation. Alloc is somehow a 38e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng * "private" member that should not be messed with. 39e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng */ 40e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 41e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#include <assert.h> 42e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 43e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern char strbuf_slopbuf[]; 44e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstruct strbuf { 45e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t alloc; 46e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng size_t len; 47e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng char *buf; 48e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng}; 49e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 50e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#define STRBUF_INIT { 0, 0, strbuf_slopbuf } 51e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 52e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*----- strbuf life cycle -----*/ 53e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern void strbuf_init(struct strbuf *buf, ssize_t hint); 54e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern void strbuf_release(struct strbuf *); 55e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern char *strbuf_detach(struct strbuf *, size_t *); 56e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 57e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*----- strbuf size related -----*/ 58e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline ssize_t strbuf_avail(const struct strbuf *sb) { 59e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng return sb->alloc ? sb->alloc - sb->len - 1 : 0; 60e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 61e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 62e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern void strbuf_grow(struct strbuf *, size_t); 63e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 64e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void strbuf_setlen(struct strbuf *sb, size_t len) { 65e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng if (!sb->alloc) 66e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_grow(sb, 0); 67e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng assert(len < sb->alloc); 68e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sb->len = len; 69e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sb->buf[len] = '\0'; 70e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 71e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 72e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/*----- add data in your buffer -----*/ 73e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void strbuf_addch(struct strbuf *sb, int c) { 74e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_grow(sb, 1); 75e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sb->buf[sb->len++] = c; 76e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng sb->buf[sb->len] = '\0'; 77e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 78e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 79e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern void strbuf_remove(struct strbuf *, size_t pos, size_t len); 80e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 81e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern void strbuf_add(struct strbuf *, const void *, size_t); 82e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengstatic inline void strbuf_addstr(struct strbuf *sb, const char *s) { 83e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng strbuf_add(sb, s, strlen(s)); 84e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng} 85e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 86e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng__attribute__((format(printf,2,3))) 87e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern void strbuf_addf(struct strbuf *sb, const char *fmt, ...); 88e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 89e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng/* XXX: if read fails, any partial read is undone */ 90e6817ec1d8ab31fc7b01906e305f848542df6413Ben Chengextern ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); 91e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng 92e6817ec1d8ab31fc7b01906e305f848542df6413Ben Cheng#endif /* __PERF_STRBUF_H */ 93