/* * UCW Library -- A simple growing buffers for byte-sized items * * (c) 2006 Pavel Charvat * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ #include #include #include char * bb_vprintf_at(bb_t *bb, size_t ofs, const char *fmt, va_list args) { bb_grow(bb, ofs + 1); va_list args2; va_copy(args2, args); int cnt = vsnprintf(bb->ptr + ofs, bb->len - ofs, fmt, args2); va_end(args2); if (cnt < 0) { /* Our C library doesn't support C99 return value of vsnprintf, so we need to iterate */ do { bb_do_grow(bb, bb->len + 1); va_copy(args2, args); cnt = vsnprintf(bb->ptr + ofs, bb->len - ofs, fmt, args2); va_end(args2); } while (cnt < 0); } else if ((uint)cnt >= bb->len - ofs) { bb_do_grow(bb, ofs + cnt + 1); va_copy(args2, args); int cnt2 = vsnprintf(bb->ptr + ofs, bb->len - ofs, fmt, args2); va_end(args2); ASSERT(cnt2 == cnt); } return bb->ptr + ofs; } char * bb_printf_at(bb_t *bb, size_t ofs, const char *fmt, ...) { va_list args; va_start(args, fmt); char *res = bb_vprintf_at(bb, ofs, fmt, args); va_end(args); return res; } char * bb_vprintf(bb_t *bb, const char *fmt, va_list args) { return bb_vprintf_at(bb, 0, fmt, args); } char * bb_printf(bb_t *bb, const char *fmt, ...) { va_list args; va_start(args, fmt); char *res = bb_vprintf_at(bb, 0, fmt, args); va_end(args); return res; } #ifdef TEST int main(void) { bb_t bb; bb_init(&bb); char *x = bb_printf(&bb, "", "World"); fputs(x, stdout); x = bb_printf_at(&bb, 5, "\n", "World"); fputs(x, stdout); bb_done(&bb); return 0; } #endif