X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fmempool-fmt.c;h=397a7721da18c473505da893f49dd50e72fee7cb;hb=1d8112cb590e458baa899805908a8ac910f58163;hp=c8b1e4c823ecb9d04f81a6adf391e4e0d102a894;hpb=2860df435bc0ec1601bf2e7eedacc63258b932aa;p=libucw.git diff --git a/lib/mempool-fmt.c b/lib/mempool-fmt.c index c8b1e4c8..397a7721 100644 --- a/lib/mempool-fmt.c +++ b/lib/mempool-fmt.c @@ -2,6 +2,7 @@ * UCW Library -- Memory Pools (Formatting) * * (c) 2005 Martin Mares + * (c) 2007 Pavel Charvat * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -14,45 +15,47 @@ #include #include -char * -mp_vprintf(struct mempool *p, char *fmt, va_list args) +static char * +mp_vprintf_at(struct mempool *mp, uns ofs, const char *fmt, va_list args) { - char *ret = p->free; - int free = p->last - p->free; - if (!free) - { - ret = mp_alloc(p, 1); - free = p->last - p->free; - } - int cnt = vsnprintf(ret, free, fmt, args); + char *ret = mp_grow(mp, ofs + 1) + ofs; + va_list args2; + va_copy(args2, args); + int cnt = vsnprintf(ret, mp_avail(mp) - 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 */ - uns len = 128; - char *buf; do { - len *= 2; - buf = alloca(len); - cnt = vsnprintf(buf, len, fmt, args); + ret = mp_expand(mp) + ofs; + va_copy(args2, args); + cnt = vsnprintf(ret, mp_avail(mp) - ofs, fmt, args2); + va_end(args2); } while (cnt < 0); - ret = mp_alloc(p, cnt+1); - memcpy(ret, buf, cnt+1); } - else if (cnt < free) - p->free += cnt + 1; - else + else if ((uns)cnt >= mp_avail(mp) - ofs) { - ret = mp_alloc(p, cnt+1); - int cnt2 = vsnprintf(ret, cnt+1, fmt, args); + ret = mp_grow(mp, cnt + 1) + ofs; + va_copy(args2, args); + int cnt2 = vsnprintf(ret, cnt + 1, fmt, args2); + va_end(args2); ASSERT(cnt2 == cnt); } - return ret; + mp_end(mp, ret + cnt + 1); + return ret - ofs; +} + +char * +mp_vprintf(struct mempool *mp, const char *fmt, va_list args) +{ + mp_start(mp, 1); + return mp_vprintf_at(mp, 0, fmt, args); } char * -mp_printf(struct mempool *p, char *fmt, ...) +mp_printf(struct mempool *p, const char *fmt, ...) { va_list args; va_start(args, fmt); @@ -61,6 +64,24 @@ mp_printf(struct mempool *p, char *fmt, ...) return res; } +char * +mp_vprintf_append(struct mempool *mp, char *ptr, const char *fmt, va_list args) +{ + uns ofs = mp_open(mp, ptr); + ASSERT(ofs); + return mp_vprintf_at(mp, ofs - 1, fmt, args); +} + +char * +mp_printf_append(struct mempool *mp, char *ptr, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + char *res = mp_vprintf_append(mp, ptr, fmt, args); + va_end(args); + return res; +} + #ifdef TEST int main(void) @@ -68,6 +89,8 @@ int main(void) struct mempool *mp = mp_new(64); char *x = mp_printf(mp, "", "World"); fputs(x, stdout); + x = mp_printf_append(mp, x, ""); + fputs(x, stdout); x = mp_printf(mp, "\n", "World"); fputs(x, stdout); return 0;