From: Andre Noll Date: Tue, 9 Aug 2011 18:00:12 +0000 (+0200) Subject: btr: Introduce btr_next_buffer_omit(). X-Git-Tag: v0.4.9~2^2~4 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=4c5110988155bd46629a0833a1887f2075257e38 btr: Introduce btr_next_buffer_omit(). This function is useful for the flac decoder. --- diff --git a/buffer_tree.c b/buffer_tree.c index 88fb8362..cb9d514f 100644 --- a/buffer_tree.c +++ b/buffer_tree.c @@ -563,40 +563,95 @@ static size_t btr_get_buffer_by_reference(struct btr_buffer_reference *br, char } /** - * Obtain the next buffer of the input queue of a buffer tree node. + * Obtain the next buffer of the input queue, omitting data. * * \param btrn The node whose input queue is to be queried. + * \param omit Number of bytes to be omitted. * \param bufp Result pointer. * - * \return The number of bytes that can be read from buf. Zero if the input - * buffer queue is empty. In this case the value of \a bufp is undefined. + * If a buffer tree node needs more input data but can not consume the data it + * already has (because it might be needed again later) this function can be + * used instead of btr_next_buffer() to get a reference to the buffer obtained + * by skipping the given number of bytes. Skipped input bytes are not consumed. + * + * With a zero \a omit argument, this function is equivalent to \ref + * btr_next_buffer(). + * + * \return Number of bytes in \a bufp. If there are less than or equal to \a + * omit many bytes available in the input queue of the buffer tree node pointed + * to by \a btrn, the function returns zero and the value of \a bufp is + * undefined. */ -size_t btr_next_buffer(struct btr_node *btrn, char **bufp) +size_t btr_next_buffer_omit(struct btr_node *btrn, size_t omit, char **bufp) { struct btr_buffer_reference *br; + size_t wrap_count, sz, rv = 0; char *buf, *result = NULL; - size_t sz, rv = 0; - FOR_EACH_BUFFER_REF(br, btrn) { + br = get_first_input_br(btrn); + if (!br) + return 0; + wrap_count = br->wrap_count; + if (wrap_count > 0) { /* we have a wrap buffer */ sz = btr_get_buffer_by_reference(br, &buf); - if (!result) { - result = buf; - rv = sz; - if (!br->btrb->pool) - break; - continue; + if (sz > omit) { /* and it's big enough */ + result = buf + omit; + rv = sz - omit; + /* + * Wrap buffers are allocated by malloc(), so the next + * buffer ref will not align nicely, so we return the + * tail of the wrap buffer. + */ + goto out; } - if (!br->btrb->pool) - break; - if (result + rv != buf) - break; - rv += sz; + /* + * The next wrap_count bytes exist twice, in the wrap buffer + * and as a buffer reference in the buffer tree pool. + */ + omit += wrap_count; + } + /* + * For buffer tree pools, the buffers in the list align, i.e. the next + * buffer in the list starts directly at the end of its predecessor. In + * this case we merge adjacent buffers and return one larger buffer + * instead. + */ + FOR_EACH_BUFFER_REF(br, btrn) { + sz = btr_get_buffer_by_reference(br, &buf); + if (result) { + if (result + rv != buf) + goto out; + rv += sz; + } else if (sz > omit) { + result = buf + omit; + rv = sz - omit; + } else + omit -= sz; } + if (!result) + return 0; +out: if (bufp) *bufp = result; return rv; } +/** + * Obtain the next buffer of the input queue of a buffer tree node. + * + * \param btrn The node whose input queue is to be queried. + * \param bufp Result pointer. + * + * \return The number of bytes that can be read from buf. + * + * The call of this function is is equivalent to calling \ref + * btr_next_buffer_omit() with an \a omit value of zero. + */ +size_t btr_next_buffer(struct btr_node *btrn, char **bufp) +{ + return btr_next_buffer_omit(btrn, 0, bufp); +} + /** * Deallocate the given number of bytes from the input queue. * diff --git a/buffer_tree.h b/buffer_tree.h index fcf9df62..b60751e5 100644 --- a/buffer_tree.h +++ b/buffer_tree.h @@ -189,6 +189,7 @@ size_t btr_get_input_queue_size(struct btr_node *btrn); size_t btr_get_output_queue_size(struct btr_node *btrn); bool btr_no_parent(struct btr_node *btrn); size_t btr_next_buffer(struct btr_node *btrn, char **bufp); +size_t btr_next_buffer_omit(struct btr_node *btrn, size_t omit, char **bufp); void btr_consume(struct btr_node *btrn, size_t numbytes); int btr_exec_up(struct btr_node *btrn, const char *command, char **value_result); void btr_splice_out_node(struct btr_node *btrn);