#include #include #include #include #include GBuf* uc_new_gbuf(size_t initsz) { GBuf *p; p = malloc(sizeof *p); if (p == NULL) return NULL; p->used = 0; p->len = initsz; p->buf = NULL; p->ref_cnt = 1; if (initsz != 0 && (p->buf = malloc(initsz)) == NULL) { free(p); return NULL; } return p; } void uc_gbuf_ref(GBuf *buf) { buf->ref_cnt++; } void uc_gbuf_unref(GBuf *buf) { buf->ref_cnt--; if (buf->ref_cnt == 0) { free(buf->buf); free(buf); } } int uc_gbuf_append(GBuf *buf,const void *data,size_t len) { unsigned char *gbuf; if (buf->len - buf->used < len) if (uc_gbuf_grow(buf, len + len/2)) return -1; gbuf = buf->buf; memcpy(gbuf + buf->used, data, len); buf->used += len; return 0; } int uc_gbuf_printf(GBuf *buf, const char *fmt, ...) { va_list ap; va_list apc; int rc = 0; int remaining; va_start(ap, fmt); //increment buffer if snprintf indicates the results were truncated do { va_copy(apc, ap); char *gbuf; remaining = uc_gbuf_remaining(buf); if (rc >= remaining) { if (uc_gbuf_grow(buf, buf->len + (rc - remaining) + 1)) { rc = -1; va_end(apc); break; } remaining = uc_gbuf_remaining(buf); } gbuf = buf->buf; rc = vsnprintf(gbuf + buf->used, remaining, fmt, apc); va_end(apc); } while (rc >= remaining); if(rc > 0) { buf->used += rc; } va_end(ap); return rc; } int uc_gbuf_grow(GBuf *buf, size_t addlen) { void *tmp; size_t newsz; newsz = buf->len + addlen; tmp = realloc(buf->buf,newsz); if (tmp == NULL) return -1; buf->buf = tmp; buf->len = newsz; return 0; }