X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=string.c;h=d23e43c1eecb1d34e4eaefda77423da076ab412a;hp=bd53e8d24462d1bbde5045f7b0b80de939460588;hb=6442f07bb08eb6e557086587f997b1785ea18ef7;hpb=df743de3c09a9f02c95bd3ff50e19a401b957efe diff --git a/string.c b/string.c index bd53e8d2..d23e43c1 100644 --- a/string.c +++ b/string.c @@ -59,9 +59,10 @@ __must_check __malloc void *para_realloc(void *p, size_t size) */ __must_check __malloc void *para_malloc(size_t size) { - assert(size); - void *p = malloc(size); + void *p; + assert(size); + p = malloc(size); if (!p) { PARA_EMERG_LOG("malloc failed (size = %zu), aborting\n", size); @@ -484,7 +485,15 @@ int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler, * * This function prints into the buffer given by \a b at the offset which is * also given by \a b. If there is not enough space to hold the result, the - * buffer size is doubled until the underlying call to vsnprintf() succeeds. + * buffer size is doubled until the underlying call to vsnprintf() succeeds + * or the size of the buffer exceeds the maximal size specified in \a pb. + * + * In the latter case the unmodified \a buf and \a offset values as well as the + * private_data pointer of \a b are passed to the \a max_size_handler of \a b. + * If this function succeeds, i.e. returns a non-negative value, the offset of + * \a b is reset to zero and the given data is written to the beginning of the + * buffer. + * * Upon return, the offset of \a b is adjusted accordingly so that subsequent * calls to this function append data to what is already contained in the * buffer. @@ -505,26 +514,35 @@ __printf_2_3 int para_printf(struct para_buffer *b, const char *fmt, ...) b->buf = para_malloc(128); b->size = 128; b->offset = 0; - } else if (b->size <= b->offset + 1) { - b->size *= 2; - b->buf = para_realloc(b->buf, b->size); } while (1) { char *p = b->buf + b->offset; size_t size = b->size - b->offset; va_list ap; - va_start(ap, fmt); - ret = vsnprintf(p, size, fmt, ap); - va_end(ap); - if (ret > -1 && ret < size) { /* success */ - b->offset += ret; - break; + if (size) { + va_start(ap, fmt); + ret = vsnprintf(p, size, fmt, ap); + va_end(ap); + if (ret > -1 && ret < size) { /* success */ + b->offset += ret; + return ret; + } } - /* try again with more space */ - b->size *= 2; - b->buf = para_realloc(b->buf, b->size); + /* check if we may grow the buffer */ + if (!b->max_size || 2 * b->size < b->max_size) { /* yes */ + /* try again with more space */ + b->size *= 2; + b->buf = para_realloc(b->buf, b->size); + continue; + } + /* can't grow buffer */ + if (!b->offset || !b->max_size_handler) /* message too large */ + return -ERRNO_TO_PARA_ERROR(ENOSPC); + ret = b->max_size_handler(b->buf, b->offset, b->private_data); + if (ret < 0) + return ret; + b->offset = 0; } - return ret; } /** \cond LLONG_MAX and LLONG_LIN might not be defined. */