#ifndef foostrbufhfoo #define foostrbufhfoo #include #include #include #include #include #include struct chunk { struct chunk *next; char text[]; }; struct strbuf { size_t length; struct chunk *head, *tail; }; struct strbuf *strbuf_new(void) { struct strbuf *sb = malloc(sizeof(struct strbuf)); assert(sb); sb->length = 0; sb->head = sb->tail = NULL; return sb; } void strbuf_free(struct strbuf *sb) { assert(sb); while (sb->head) { struct chunk *c = sb->head; sb->head = sb->head->next; free(c); } free(sb); } char *strbuf_tostring(struct strbuf *sb) { char *t, *e; struct chunk *c; assert(sb); t = malloc(sb->length+1); assert(t); e = t; *e = 0; for (c = sb->head; c; c = c->next) { strcpy(e, c->text); e = strchr(e, 0); } return t; } void strbuf_puts(struct strbuf *sb, const char *t) { struct chunk *c; size_t l; assert(sb && t); l = strlen(t); c = malloc(sizeof(struct chunk)+l); assert(c); c->next = NULL; strcpy(c->text, t); if (sb->tail) { assert(sb->head); sb->tail->next = c; } else { assert(!sb->head); sb->head = c; } sb->tail = c; sb->length += l; } int strbuf_printf(struct strbuf *sb, const char *format, ...) { int r, size = 100; struct chunk *c = NULL; assert(sb); for(;;) { va_list ap; c = realloc(c, sizeof(struct chunk)+size); assert(c); va_start(ap, format); r = vsnprintf(c->text, size, format, ap); va_end(ap); if (r > -1 && r < size) { c->next = NULL; if (sb->tail) { assert(sb->head); sb->tail->next = c; } else { assert(!sb->head); sb->head = c; } sb->tail = c; sb->length += r; return r; } if (r > -1) /* glibc 2.1 */ size = r+1; else /* glibc 2.0 */ size *= 2; } } #endif