Fix bug in schro_buflist_extract where bytes equal in length to the
previous parse unit were being skipped when using the autoparse API.
schro_buflist_peekbytes already invokes schro_buflist_internal_seek to
skip buflist->offset bytes so we don't need to pass an offset to it when
the parse unit spans several buffers.
Regards,
Anu
On Tue, 2009-01-20 at 23:48 +0000, [email protected] wrote:
> From: David Flynn <[email protected]>
>
> Bufferlists are lists of buffers, intended for doing synchronisation and
> extraction operations over multiple buffers
>
> includes:
> - fix pessimistic off by one error in find (comment was correct, code not)
> - fix case when find on empty list wraps offset
>
> Signed-off-by: David Flynn <[email protected]>
> ---
> schroedinger/Makefile.am | 2 +
> schroedinger/schrobufferlist.c | 230
> ++++++++++++++++++++++++++++++++++++++++
> schroedinger/schrobufferlist.h | 51 +++++++++
> 3 files changed, 283 insertions(+), 0 deletions(-)
> create mode 100644 schroedinger/schrobufferlist.c
> create mode 100644 schroedinger/schrobufferlist.h
>
> diff --git a/schroedinger/Makefile.am b/schroedinger/Makefile.am
> index 020d26d..1d22f09 100644
> --- a/schroedinger/Makefile.am
> +++ b/schroedinger/Makefile.am
> @@ -20,6 +20,7 @@ EXTRA_DIST = schroarith-i386.c \
> pkginclude_HEADERS = \
> schro.h \
> schrobuffer.h \
> + schrobufferlist.h \
> schrocog.h \
> schrodecoder.h \
> schroencoder.h \
> @@ -84,6 +85,7 @@ libschroeding...@schro_majorminor@_la_SOURCES = \
> schroframe.c \
> schrohistogram.c \
> schrobuffer.c \
> + schrobufferlist.c \
> schrolowdelay.c \
> schromotion.c \
> schrooil.c \
> diff --git a/schroedinger/schrobufferlist.c b/schroedinger/schrobufferlist.c
> new file mode 100644
> index 0000000..39dd21e
> --- /dev/null
> +++ b/schroedinger/schrobufferlist.c
> @@ -0,0 +1,230 @@
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include <schroedinger/schrobufferlist.h>
> +#include <schroedinger/schrodebug.h>
> +#include <string.h>
> +
> +#ifndef _MIN
> +#define _MIN(x,y) (((x) < (y)) ? (x) : (y))
> +#endif
> +
> +#ifndef _MAX
> +#define _MAX(x,y) (((x) > (y)) ? (x) : (y))
> +#endif
> +
> +SchroBufferList *
> +schro_buflist_new (void)
> +{
> + SchroList *list = schro_list_new_full
> ((SchroListFreeFunc)schro_buffer_unref, NULL);
> + SchroBufferList *buflist = realloc (list, sizeof(*buflist));
> +
> + buflist->offset = 0;
> + return buflist;
> +}
> +
> +int
> +schro_buflist_peekbytes (uint8_t *dst, unsigned len, SchroBufferList
> *buflist, unsigned offset)
> +{
> + SchroBuffer *buf;
> + int bufidx = 0;
> + int coppied = 0;
> +
> + if (!dst || !len) {
> + return 0;
> + }
> +
> + /* skip over any discarded data at start of buflist */
> + offset += buflist->offset;
> +
> + /* find buffer offset starts in */
> + for (bufidx = 0; bufidx < buflist->list.n; bufidx++) {
> + buf = buflist->list.members[bufidx];
> + if( offset < buf->length ) {
> + /* found */
> + break;
> + }
> + offset -= buf->length;
> + }
> +
> + /* copy out upto len worth of bytes. NB, this may cross
> + * buffer boundries */
> + for (; bufidx < buflist->list.n; bufidx++) {
> + buf = buflist->list.members[bufidx];
> + unsigned size = _MIN(len, buf->length - offset);
> + memcpy(dst + coppied, buf->data + offset, size);
> + offset = 0;
> + coppied += size;
> + len -= size;
> + if (!len) {
> + break;
> + }
> + }
> +
> + return coppied;
> +}
> +
> +int
> +schro_buflist_findbytes (SchroBufferList *buflist, unsigned *start, const
> uint8_t *needle, unsigned needle_len)
> +{
> + SchroBuffer *buf;
> + unsigned bufidx = 0;
> + unsigned where = *start;
> + unsigned offset;
> + unsigned n = 0;
> + unsigned backtrack_bufidx = 0, backtrack_where = 0, backtrack_i = 0;
> +
> + if (!needle || !needle_len) {
> + return 0;
> + }
> +
> + /* skip over any discarded data at start of buflist */
> + offset = buflist->offset + *start;
> +
> + /* find buffer offset starts in */
> + for (bufidx = 0; bufidx < buflist->list.n; bufidx++) {
> + buf = buflist->list.members[bufidx];
> + if( offset < buf->length ) {
> + /* found */
> + break;
> + }
> + offset -= buf->length;
> + }
> +
> + /* search for what[], NB this may span multiple buffers */
> + /* NB, if a search fails, it must be backtracked */
> + for (; bufidx < buflist->list.n; bufidx++) {
> + /* todo, maybe add memmem call ? */
> +#if 0
> + if (!n) {
> + /* not in the middle of a search that spans buffers */
> + uint8_t *pos = memmem(buf->data + offset
> + ,buf->length - offset
> + ,needle, needle_len);
> + if (pos) {
> + /* found */
> + where += pos - buf->data - offset;
> + return where;
> + }
> + offset = _MAX(offset, buf->length - needle_len);
> + /* ^^^ +1 required ? */
> + }
> +#endif
> + unsigned i = offset;
> + buf = buflist->list.members[bufidx];
> + for (; i < buf->length; i++) {
> + if (needle[n] == buf->data[i]) {
> + if (!n) {
> + /* save back tracking point */
> + backtrack_where = where;
> + backtrack_i = i;
> + backtrack_bufidx = bufidx;
> + }
> + n++;
> + if (n == needle_len) {
> + *start = backtrack_where;
> + return 1;
> + }
> + }
> + else if (n) {
> + n = 0;
> + /* restore backtracking point */
> + i = backtrack_i;
> + where = backtrack_where;
> + bufidx = backtrack_bufidx;
> + }
> + }
> + where += buf->length - offset;
> + offset = 0;
> + }
> +
> + /* not found */
> + /* NB, to make it possible to resume a search where this failed,
> + * must move where back by (needle_len-1), but don't go past start */
> + /* but avoid unsigned wraparound */
> + if (needle_len <= where)
> + *start = _MAX(where - needle_len + 1, *start);
> + return 0;
> +}
> +
> +void
> +schro_buflist_flush (SchroBufferList *buflist, unsigned amount)
> +{
> + SchroBuffer *buf;
> + int bufidx = 0;
> +
> + /* include any discarded data at start of buflist */
> + buflist->offset += amount;
> +
> + /* pop and unref all buffers that end before ammount */
> + for (bufidx = 0; bufidx < buflist->list.n; bufidx++) {
> + buf = buflist->list.members[bufidx];
> + if( buflist->offset < buf->length ) {
> + /* found */
> + break;
> + }
> + buflist->offset -= buf->length;
> + schro_list_delete (&buflist->list, 0);
> + bufidx--;
> + }
> +}
> +
> +SchroBuffer *
> +schro_buflist_extract (SchroBufferList *buflist, unsigned start, unsigned
> len)
> +{
> + SchroBuffer *buf, *dst;
> + int bufidx = 0;
> + uint8_t tmp;
> + int done = 0;
> +
> + SCHRO_ASSERT(buflist);
> +
> + if (!len) {
> + return NULL;
> + }
> +
> + /* first check that the (start + len)th byte is avaliable */
> + if (!schro_buflist_peekbytes (&tmp, 1, buflist, start + len -1)) {
> + return NULL;
> + }
> +
> + /* skip over any discarded data at start of buflist */
> + start += buflist->offset;
> +
> + /* find buffer offset starts in */
> + /* guaranteed that we wont run off the list of buffers */
> + for (bufidx = 0; bufidx < buflist->list.n; bufidx++) {
> + buf = buflist->list.members[bufidx];
> + if (start < buf->length) {
> + /* found */
> + break;
> + }
> + start -= buf->length;
> + }
> +
> + SCHRO_ASSERT(bufidx < buflist->list.n);
> +
> + if (start + len <= buf->length) {
> + /* Special case, if the requested range is contained within a single
> + * buffer, then use a subbuffer */
> + return schro_buffer_new_subbuffer (buf, start, len);
> + }
> +
> + dst = schro_buffer_new_and_alloc (len);
> + for (; bufidx < buflist->list.n; bufidx++) {
> + buf = buflist->list.members[bufidx];
> + int size = _MIN(len, buf->length - start);
> + memcpy(dst->data + done, buf->data + start, size);
> + start = 0;
> + done += size;
> + len -= size;
> + if (!len)
> + return dst;
> + }
> +
> + /* not reachable */
> + SCHRO_ASSERT(!len);
> + return NULL;
> +}
> diff --git a/schroedinger/schrobufferlist.h b/schroedinger/schrobufferlist.h
> new file mode 100644
> index 0000000..13d0b59
> --- /dev/null
> +++ b/schroedinger/schrobufferlist.h
> @@ -0,0 +1,51 @@
> +#ifndef __SCHRO_BUFFERLIST_H__
> +#define __SCHRO_BUFFERLIST_H__
> +
> +#include <schroedinger/schroutils.h>
> +#include <schroedinger/schrobuffer.h>
> +#include <schroedinger/schrolist.h>
> +
> +SCHRO_BEGIN_DECLS
> +
> +#ifdef SCHRO_ENABLE_UNSTABLE_API
> +
> +typedef struct _SchroBufferList SchroBufferList;
> +
> +struct _SchroBufferList
> +{
> + SchroList list;
> + /* private */
> + unsigned offset;
> +};
> +
> +SchroBufferList *schro_buflist_new (void);
> +int schro_buflist_peekbytes (uint8_t *dst, unsigned len, SchroBufferList
> *buflist, unsigned offset);
> +int schro_buflist_findbytes (SchroBufferList *buflist, unsigned *start,
> const uint8_t *needle, unsigned needle_len);
> +void schro_buflist_flush (SchroBufferList *buflist, unsigned amount);
> +SchroBuffer * schro_buflist_extract (SchroBufferList *buflist, unsigned
> start, unsigned len);
> +
> +static inline
> +void schro_buflist_free (SchroBufferList *buflist)
> +{
> + schro_list_free (&buflist->list);
> +}
> +
> +static inline
> +void schro_buflist_append (SchroBufferList *buflist, SchroBuffer *buf)
> +{
> + schro_list_append (&buflist->list, buf);
> +}
> +
> +#if 0
> +static inline
> +SchroBuffer *schro_buflist_remove_head (SchroBufferList *buflist)
> +{
> + return schro_list_remove(&buflist->list, 0);
> +}
> +#endif
> +
> +#endif
> +
> +SCHRO_END_DECLS
> +
> +#endif
diff --git a/schroedinger/schrobufferlist.c b/schroedinger/schrobufferlist.c
index e8664e2..2caa8f1 100644
--- a/schroedinger/schrobufferlist.c
+++ b/schroedinger/schrobufferlist.c
@@ -260,7 +260,7 @@ schro_buflist_extract (SchroBufferList *buflist, unsigned start, unsigned len)
}
buf = schro_buffer_new_and_alloc (len);
- schro_buflist_peekbytes (buf->data, len, buflist, start);
+ schro_buflist_peekbytes (buf->data, len, buflist, 0);
return buf;
}
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Schrodinger-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/schrodinger-devel