X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=string.c;h=38e25b09c5f3ff2b289d6e943a0f7bde3bfc23ad;hp=dfcfa2cdf6eb776c63afdaec981aed55147a31b1;hb=75602d559d3dd57d704839b817377646722bfed8;hpb=2f07d34b5d4c37606be5849b6ee51e0443707898 diff --git a/string.c b/string.c index dfcfa2cd..38e25b09 100644 --- a/string.c +++ b/string.c @@ -142,15 +142,18 @@ __must_check __malloc char *para_strdup(const char *s) __printf_2_0 unsigned xvasprintf(char **result, const char *fmt, va_list ap) { int ret; - size_t size; + size_t size = 150; va_list aq; + *result = para_malloc(size + 1); va_copy(aq, ap); - ret = vsnprintf(NULL, 0, fmt, aq); + ret = vsnprintf(*result, size, fmt, aq); va_end(aq); assert(ret >= 0); + if (ret < size) /* OK */ + return ret; size = ret + 1; - *result = para_malloc(size); + *result = para_realloc(*result, size); va_copy(aq, ap); ret = vsnprintf(*result, size, fmt, aq); va_end(aq); @@ -356,19 +359,35 @@ __malloc char *para_hostname(void) } /** - * Used to distinguish between read-only and read-write mode. + * Call a custom function for each complete line. + * + * \param flags Any combination of flags defined in \ref for_each_line_flags. + * \param buf The buffer containing data separated by newlines. + * \param size The number of bytes in \a buf. + * \param line_handler The custom function. + * \param private_data Pointer passed to \a line_handler. + * + * For each complete line in \p buf, \p line_handler is called. The first + * argument to \p line_handler is (a copy of) the current line, and \p + * private_data is passed as the second argument. If the \p FELF_READ_ONLY + * flag is unset, a pointer into \a buf is passed to the line handler, + * otherwise a pointer to a copy of the current line is passed instead. This + * copy is freed immediately after the line handler returns. + * + * The function returns if \p line_handler returns a negative value or no more + * lines are in the buffer. The rest of the buffer (last chunk containing an + * incomplete line) is moved to the beginning of the buffer if FELF_READ_ONLY is + * unset. * - * \sa for_each_line(), for_each_line_ro(). + * \return On success this function returns the number of bytes not handled to + * \p line_handler. The only possible error is a negative return value from the + * line handler. In this case processing stops and the return value of the line + * handler is returned to indicate failure. + * + * \sa \ref for_each_line_flags. */ -enum for_each_line_modes{ - /** Activate read-only mode. */ - LINE_MODE_RO, - /** Activate read-write mode. */ - LINE_MODE_RW -}; - -static int for_each_complete_line(enum for_each_line_modes mode, char *buf, - size_t size, line_handler_t *line_handler, void *private_data) +int for_each_line(unsigned flags, char *buf, size_t size, + line_handler_t *line_handler, void *private_data) { char *start = buf, *end; int ret, i, num_lines = 0; @@ -389,85 +408,29 @@ static int for_each_complete_line(enum for_each_line_modes mode, char *buf, } else end = next_cr; num_lines++; - if (!line_handler) { - start = ++end; - continue; - } - if (mode == LINE_MODE_RO) { - size_t s = end - start; - char *b = para_malloc(s + 1); - memcpy(b, start, s); - b[s] = '\0'; -// PARA_NOTICE_LOG("b: %s, start: %s\n", b, start); - ret = line_handler(b, private_data); - free(b); - } else { - *end = '\0'; - ret = line_handler(start, private_data); + if (!(flags & FELF_DISCARD_FIRST) || start != buf) { + if (flags & FELF_READ_ONLY) { + size_t s = end - start; + char *b = para_malloc(s + 1); + memcpy(b, start, s); + b[s] = '\0'; + ret = line_handler(b, private_data); + free(b); + } else { + *end = '\0'; + ret = line_handler(start, private_data); + } + if (ret < 0) + return ret; } - if (ret < 0) - return ret; start = ++end; } - if (!line_handler || mode == LINE_MODE_RO) - return num_lines; i = buf + size - start; - if (i && i != size) + if (i && i != size && !(flags & FELF_READ_ONLY)) memmove(buf, start, i); return i; } -/** - * Call a custom function for each complete line. - * - * \param buf The buffer containing data separated by newlines. - * \param size The number of bytes in \a buf. - * \param line_handler The custom function. - * \param private_data Pointer passed to \a line_handler. - * - * If \p line_handler is \p NULL, the function returns the number of complete - * lines in \p buf. Otherwise, \p line_handler is called for each complete - * line in \p buf. The first argument to \p line_handler is the current line, - * and \p private_data is passed as the second argument. The function returns - * if \p line_handler returns a negative value or no more lines are in the - * buffer. The rest of the buffer (last chunk containing an incomplete line) - * is moved to the beginning of the buffer. - * - * \return If \p line_handler is not \p NULL, this function returns the number - * of bytes not handled to \p line_handler on success, or the negative return - * value of the \p line_handler on errors. - * - * \sa for_each_line_ro(). - */ -int for_each_line(char *buf, size_t size, line_handler_t *line_handler, - void *private_data) -{ - return for_each_complete_line(LINE_MODE_RW, buf, size, line_handler, - private_data); -} - -/** - * Call a custom function for each complete line. - * - * \param buf Same meaning as in \p for_each_line(). - * \param size Same meaning as in \p for_each_line(). - * \param line_handler Same meaning as in \p for_each_line(). - * \param private_data Same meaning as in \p for_each_line(). - * - * This function behaves like \p for_each_line(), but \a buf is left unchanged. - * - * \return On success, the function returns the number of complete lines in \p - * buf, otherwise the (negative) return value of \p line_handler is returned. - * - * \sa for_each_line(). - */ -int for_each_line_ro(char *buf, size_t size, line_handler_t *line_handler, - void *private_data) -{ - return for_each_complete_line(LINE_MODE_RO, buf, size, line_handler, - private_data); -} - /** Return the hex characters of the lower 4 bits. */ #define hex(a) (hexchar[(a) & 15])