Move tvb real and subset implementations to seperate files.
svn path=/trunk/; revision=50569
This commit is contained in:
parent
c089afca5c
commit
0d85b75305
|
@ -1498,6 +1498,8 @@ set(LIBWIRESHARK_FILES
|
|||
to_str.c
|
||||
tvbparse.c
|
||||
tvbuff.c
|
||||
tvbuff_real.c
|
||||
tvbuff_subset.c
|
||||
uat.c
|
||||
value_string.c
|
||||
xdlc.c
|
||||
|
|
|
@ -98,6 +98,8 @@ LIBWIRESHARK_SRC = \
|
|||
tfs.c \
|
||||
to_str.c \
|
||||
tvbparse.c \
|
||||
tvbuff_real.c \
|
||||
tvbuff_subset.c \
|
||||
tvbuff.c \
|
||||
uat.c \
|
||||
value_string.c \
|
||||
|
|
|
@ -97,13 +97,6 @@ struct tvbuff {
|
|||
gint raw_offset;
|
||||
};
|
||||
|
||||
struct tvb_real {
|
||||
struct tvbuff tvb;
|
||||
|
||||
/** Func to call when actually freed */
|
||||
tvbuff_free_cb_t free_cb;
|
||||
};
|
||||
|
||||
struct tvb_subset {
|
||||
struct tvbuff tvb;
|
||||
|
||||
|
@ -118,4 +111,9 @@ struct tvb_composite {
|
|||
|
||||
WS_DLL_PUBLIC tvbuff_t *tvb_new(const struct tvb_ops *ops);
|
||||
|
||||
void tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child);
|
||||
|
||||
guint tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const guint counter);
|
||||
|
||||
void tvb_check_offset_length(const tvbuff_t *tvb, const gint offset, gint const length_val, guint *offset_ptr, guint *length_ptr);
|
||||
#endif
|
||||
|
|
263
epan/tvbuff.c
263
epan/tvbuff.c
|
@ -51,8 +51,6 @@
|
|||
#include "charsets.h"
|
||||
#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
|
||||
|
||||
static inline const struct tvb_ops *get_tvb_real_ops(void);
|
||||
static inline const struct tvb_ops *get_tvb_subset_ops(void);
|
||||
static inline const struct tvb_ops *get_tvb_composite_ops(void);
|
||||
|
||||
static const guint8*
|
||||
|
@ -86,19 +84,6 @@ tvb_new(const struct tvb_ops *ops)
|
|||
return tvb;
|
||||
}
|
||||
|
||||
static void
|
||||
real_free(tvbuff_t *tvb)
|
||||
{
|
||||
struct tvb_real *real_tvb = (struct tvb_real *) tvb;
|
||||
|
||||
if (real_tvb->free_cb) {
|
||||
/*
|
||||
* XXX - do this with a union?
|
||||
*/
|
||||
real_tvb->free_cb((gpointer)tvb->real_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
composite_free(tvbuff_t *tvb)
|
||||
{
|
||||
|
@ -158,17 +143,7 @@ tvb_free_chain(tvbuff_t *tvb)
|
|||
}
|
||||
|
||||
void
|
||||
tvb_set_free_cb(tvbuff_t *tvb, const tvbuff_free_cb_t func)
|
||||
{
|
||||
struct tvb_real *real_tvb = (struct tvb_real *) tvb;
|
||||
|
||||
DISSECTOR_ASSERT(tvb);
|
||||
DISSECTOR_ASSERT(tvb->ops == get_tvb_real_ops());
|
||||
real_tvb->free_cb = func;
|
||||
}
|
||||
|
||||
static void
|
||||
add_to_chain(tvbuff_t *parent, tvbuff_t *child)
|
||||
tvb_add_to_chain(tvbuff_t *parent, tvbuff_t *child)
|
||||
{
|
||||
DISSECTOR_ASSERT(parent && child);
|
||||
DISSECTOR_ASSERT(!child->next && !child->previous);
|
||||
|
@ -179,43 +154,6 @@ add_to_chain(tvbuff_t *parent, tvbuff_t *child)
|
|||
parent->next = child;
|
||||
}
|
||||
|
||||
void
|
||||
tvb_set_child_real_data_tvbuff(tvbuff_t *parent, tvbuff_t *child)
|
||||
{
|
||||
DISSECTOR_ASSERT(parent && child);
|
||||
DISSECTOR_ASSERT(parent->initialized);
|
||||
DISSECTOR_ASSERT(child->initialized);
|
||||
DISSECTOR_ASSERT(child->ops == get_tvb_real_ops());
|
||||
add_to_chain(parent, child);
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_real_data(const guint8* data, const guint length, const gint reported_length)
|
||||
{
|
||||
tvbuff_t *tvb;
|
||||
struct tvb_real *real_tvb;
|
||||
|
||||
THROW_ON(reported_length < -1, ReportedBoundsError);
|
||||
|
||||
tvb = tvb_new(get_tvb_real_ops());
|
||||
|
||||
tvb->real_data = data;
|
||||
tvb->length = length;
|
||||
tvb->reported_length = reported_length;
|
||||
tvb->initialized = TRUE;
|
||||
|
||||
/*
|
||||
* This is the top-level real tvbuff for this data source,
|
||||
* so its data source tvbuff is itself.
|
||||
*/
|
||||
tvb->ds_tvb = tvb;
|
||||
|
||||
real_tvb = (struct tvb_real *) tvb;
|
||||
real_tvb->free_cb = NULL;
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_child_real_data(tvbuff_t *parent, const guint8* data, const guint length, const gint reported_length)
|
||||
{
|
||||
|
@ -349,110 +287,12 @@ check_offset_length(const tvbuff_t *tvb,
|
|||
THROW(exception);
|
||||
}
|
||||
|
||||
static tvbuff_t *
|
||||
tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
|
||||
const guint subset_tvb_offset, const guint subset_tvb_length)
|
||||
void
|
||||
tvb_check_offset_length(const tvbuff_t *tvb,
|
||||
const gint offset, gint const length_val,
|
||||
guint *offset_ptr, guint *length_ptr)
|
||||
{
|
||||
tvbuff_t *tvb = tvb_new(get_tvb_subset_ops());
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
subset_tvb->subset.offset = subset_tvb_offset;
|
||||
subset_tvb->subset.length = subset_tvb_length;
|
||||
|
||||
subset_tvb->subset.tvb = backing;
|
||||
tvb->length = subset_tvb_length;
|
||||
tvb->flags = backing->flags;
|
||||
|
||||
if (reported_length == -1) {
|
||||
tvb->reported_length = backing->reported_length - subset_tvb_offset;
|
||||
}
|
||||
else {
|
||||
tvb->reported_length = reported_length;
|
||||
}
|
||||
tvb->initialized = TRUE;
|
||||
add_to_chain(backing, tvb);
|
||||
|
||||
/* Optimization. If the backing buffer has a pointer to contiguous, real data,
|
||||
* then we can point directly to our starting offset in that buffer */
|
||||
if (backing->real_data != NULL) {
|
||||
tvb->real_data = backing->real_data + subset_tvb_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* The top-level data source of this tvbuff is the top-level
|
||||
* data source of its parent.
|
||||
*/
|
||||
tvb->ds_tvb = backing->ds_tvb;
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
|
||||
{
|
||||
tvbuff_t *tvb;
|
||||
guint subset_tvb_offset;
|
||||
guint subset_tvb_length;
|
||||
|
||||
DISSECTOR_ASSERT(backing && backing->initialized);
|
||||
|
||||
THROW_ON(reported_length < -1, ReportedBoundsError);
|
||||
|
||||
check_offset_length(backing, backing_offset, backing_length,
|
||||
&subset_tvb_offset,
|
||||
&subset_tvb_length);
|
||||
|
||||
tvb = tvb_new_with_subset(backing, reported_length,
|
||||
subset_tvb_offset, subset_tvb_length);
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint backing_length)
|
||||
{
|
||||
gint captured_length;
|
||||
tvbuff_t *tvb;
|
||||
guint subset_tvb_offset;
|
||||
guint subset_tvb_length;
|
||||
|
||||
DISSECTOR_ASSERT(backing && backing->initialized);
|
||||
|
||||
THROW_ON(backing_length < 0, ReportedBoundsError);
|
||||
|
||||
/*
|
||||
* Give the next dissector only captured_length bytes.
|
||||
*/
|
||||
captured_length = tvb_length_remaining(backing, backing_offset);
|
||||
THROW_ON(captured_length < 0, BoundsError);
|
||||
if (captured_length > backing_length)
|
||||
captured_length = backing_length;
|
||||
|
||||
check_offset_length(backing, backing_offset, captured_length,
|
||||
&subset_tvb_offset,
|
||||
&subset_tvb_length);
|
||||
|
||||
tvb = tvb_new_with_subset(backing, backing_length,
|
||||
subset_tvb_offset, subset_tvb_length);
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
|
||||
{
|
||||
tvbuff_t *tvb;
|
||||
guint subset_tvb_offset;
|
||||
guint subset_tvb_length;
|
||||
|
||||
check_offset_length(backing, backing_offset, -1 /* backing_length */,
|
||||
&subset_tvb_offset,
|
||||
&subset_tvb_length);
|
||||
|
||||
tvb = tvb_new_with_subset(backing, -1 /* reported_length */,
|
||||
subset_tvb_offset, subset_tvb_length);
|
||||
|
||||
return tvb;
|
||||
check_offset_length(tvb, offset, length_val, offset_ptr, length_ptr);
|
||||
}
|
||||
|
||||
static const unsigned char left_aligned_bitmask[] = {
|
||||
|
@ -625,7 +465,7 @@ tvb_composite_finalize(tvbuff_t *tvb)
|
|||
composite->end_offsets[i] = tvb->length - 1;
|
||||
i++;
|
||||
}
|
||||
add_to_chain((tvbuff_t *)composite->tvbs->data, tvb); /* chain composite tvb to first member */
|
||||
tvb_add_to_chain((tvbuff_t *)composite->tvbs->data, tvb); /* chain composite tvb to first member */
|
||||
tvb->initialized = TRUE;
|
||||
}
|
||||
|
||||
|
@ -849,8 +689,8 @@ first_real_data_ptr(tvbuff_t *tvb)
|
|||
}
|
||||
#endif
|
||||
|
||||
static guint
|
||||
offset_from_real_beginning(const tvbuff_t *tvb, const guint counter)
|
||||
guint
|
||||
tvb_offset_from_real_beginning_counter(const tvbuff_t *tvb, const guint counter)
|
||||
{
|
||||
if (tvb->ops->tvb_offset)
|
||||
return tvb->ops->tvb_offset(tvb, counter);
|
||||
|
@ -859,34 +699,19 @@ offset_from_real_beginning(const tvbuff_t *tvb, const guint counter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static guint
|
||||
real_offset(const tvbuff_t *tvb _U_, const guint counter)
|
||||
{
|
||||
return counter;
|
||||
}
|
||||
|
||||
static guint
|
||||
subset_offset(const tvbuff_t *tvb, const guint counter)
|
||||
{
|
||||
const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
|
||||
const tvbuff_t *member = subset_tvb->subset.tvb;
|
||||
|
||||
return offset_from_real_beginning(member, counter + subset_tvb->subset.offset);
|
||||
}
|
||||
|
||||
static guint
|
||||
composite_offset(const tvbuff_t *tvb, const guint counter)
|
||||
{
|
||||
const struct tvb_composite *composite_tvb = (const struct tvb_composite *) tvb;
|
||||
const tvbuff_t *member = (const tvbuff_t *)composite_tvb->composite.tvbs->data;
|
||||
|
||||
return offset_from_real_beginning(member, counter);
|
||||
return tvb_offset_from_real_beginning_counter(member, counter);
|
||||
}
|
||||
|
||||
guint
|
||||
tvb_offset_from_real_beginning(const tvbuff_t *tvb)
|
||||
{
|
||||
return offset_from_real_beginning(tvb, 0);
|
||||
return tvb_offset_from_real_beginning_counter(tvb, 0);
|
||||
}
|
||||
|
||||
static const guint8*
|
||||
|
@ -963,14 +788,6 @@ ensure_contiguous_no_exception(tvbuff_t *tvb, const gint offset, const gint leng
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const guint8 *
|
||||
subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return ensure_contiguous_no_exception(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length, NULL);
|
||||
}
|
||||
|
||||
static const guint8*
|
||||
ensure_contiguous(tvbuff_t *tvb, const gint offset, const gint length)
|
||||
{
|
||||
|
@ -1109,14 +926,6 @@ composite_memcpy(tvbuff_t *tvb, void* _target, guint abs_offset, size_t abs_leng
|
|||
DISSECTOR_ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
static void *
|
||||
subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
|
||||
}
|
||||
|
||||
void *
|
||||
tvb_memcpy(tvbuff_t *tvb, void *target, const gint offset, size_t length)
|
||||
{
|
||||
|
@ -1962,14 +1771,6 @@ tvb_find_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu
|
|||
return -1;
|
||||
}
|
||||
|
||||
static gint
|
||||
subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
|
||||
}
|
||||
|
||||
/* Find first occurrence of any of the needles in tvbuff, starting at offset.
|
||||
* Searches at most maxlength number of bytes; if maxlength is -1, searches
|
||||
* to end of tvbuff.
|
||||
|
@ -2025,20 +1826,6 @@ tvb_pbrk_guint8(tvbuff_t *tvb, const gint offset, const gint maxlength, const gu
|
|||
return -1;
|
||||
}
|
||||
|
||||
static gint
|
||||
subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_pbrk_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needles, found_needle);
|
||||
}
|
||||
|
||||
static tvbuff_t *
|
||||
subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
||||
{
|
||||
return tvb_clone_offset_len(tvb, abs_offset, abs_length);
|
||||
}
|
||||
|
||||
/* Find size of stringz (NUL-terminated string) by looking for terminating
|
||||
* NUL. The size of the string includes the terminating NUL.
|
||||
*
|
||||
|
@ -3672,36 +3459,8 @@ tvb_get_ds_tvb(tvbuff_t *tvb)
|
|||
return(tvb->ds_tvb);
|
||||
}
|
||||
|
||||
static gsize real_sizeof(void) { return sizeof(struct tvb_real); }
|
||||
static gsize subset_sizeof(void) { return sizeof(struct tvb_subset); }
|
||||
static gsize composite_sizeof(void) { return sizeof(struct tvb_composite); }
|
||||
|
||||
static const struct tvb_ops tvb_real_ops = {
|
||||
real_sizeof, /* size */
|
||||
real_free, /* free */
|
||||
real_offset, /* offset */
|
||||
NULL, /* get_ptr */
|
||||
NULL, /* memcpy */
|
||||
NULL, /* find_guint8 */
|
||||
NULL, /* pbrk_guint8 */
|
||||
NULL, /* clone */
|
||||
};
|
||||
|
||||
static inline const struct tvb_ops *get_tvb_real_ops(void) { return &tvb_real_ops; }
|
||||
|
||||
static const struct tvb_ops tvb_subset_ops = {
|
||||
subset_sizeof, /* size */
|
||||
NULL, /* free */
|
||||
subset_offset, /* offset */
|
||||
subset_get_ptr, /* get_ptr */
|
||||
subset_memcpy, /* memcpy */
|
||||
subset_find_guint8, /* find_guint8 */
|
||||
subset_pbrk_guint8, /* pbrk_guint8 */
|
||||
subset_clone, /* clone */
|
||||
};
|
||||
|
||||
static inline const struct tvb_ops *get_tvb_subset_ops(void) { return &tvb_subset_ops; }
|
||||
|
||||
static const struct tvb_ops tvb_composite_ops = {
|
||||
composite_sizeof, /* size */
|
||||
composite_free, /* free */
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/* tvbuff_real.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tvbuff.h"
|
||||
#include "tvbuff-int.h"
|
||||
#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
|
||||
|
||||
struct tvb_real {
|
||||
struct tvbuff tvb;
|
||||
|
||||
/** Func to call when actually freed */
|
||||
tvbuff_free_cb_t free_cb;
|
||||
};
|
||||
|
||||
static gsize
|
||||
real_sizeof(void)
|
||||
{
|
||||
return sizeof(struct tvb_real);
|
||||
}
|
||||
|
||||
static void
|
||||
real_free(tvbuff_t *tvb)
|
||||
{
|
||||
struct tvb_real *real_tvb = (struct tvb_real *) tvb;
|
||||
|
||||
if (real_tvb->free_cb) {
|
||||
/*
|
||||
* XXX - do this with a union?
|
||||
*/
|
||||
real_tvb->free_cb((gpointer)tvb->real_data);
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
real_offset(const tvbuff_t *tvb _U_, const guint counter)
|
||||
{
|
||||
return counter;
|
||||
}
|
||||
|
||||
static const struct tvb_ops tvb_real_ops = {
|
||||
real_sizeof, /* size */
|
||||
real_free, /* free */
|
||||
real_offset, /* offset */
|
||||
NULL, /* get_ptr */
|
||||
NULL, /* memcpy */
|
||||
NULL, /* find_guint8 */
|
||||
NULL, /* pbrk_guint8 */
|
||||
NULL, /* clone */
|
||||
};
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_real_data(const guint8* data, const guint length, const gint reported_length)
|
||||
{
|
||||
tvbuff_t *tvb;
|
||||
struct tvb_real *real_tvb;
|
||||
|
||||
THROW_ON(reported_length < -1, ReportedBoundsError);
|
||||
|
||||
tvb = tvb_new(&tvb_real_ops);
|
||||
|
||||
tvb->real_data = data;
|
||||
tvb->length = length;
|
||||
tvb->reported_length = reported_length;
|
||||
tvb->initialized = TRUE;
|
||||
|
||||
/*
|
||||
* This is the top-level real tvbuff for this data source,
|
||||
* so its data source tvbuff is itself.
|
||||
*/
|
||||
tvb->ds_tvb = tvb;
|
||||
|
||||
real_tvb = (struct tvb_real *) tvb;
|
||||
real_tvb->free_cb = NULL;
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
void
|
||||
tvb_set_free_cb(tvbuff_t *tvb, const tvbuff_free_cb_t func)
|
||||
{
|
||||
struct tvb_real *real_tvb = (struct tvb_real *) tvb;
|
||||
|
||||
DISSECTOR_ASSERT(tvb);
|
||||
DISSECTOR_ASSERT(tvb->ops == &tvb_real_ops);
|
||||
real_tvb->free_cb = func;
|
||||
}
|
||||
|
||||
void
|
||||
tvb_set_child_real_data_tvbuff(tvbuff_t *parent, tvbuff_t *child)
|
||||
{
|
||||
DISSECTOR_ASSERT(parent && child);
|
||||
DISSECTOR_ASSERT(parent->initialized);
|
||||
DISSECTOR_ASSERT(child->initialized);
|
||||
DISSECTOR_ASSERT(child->ops == &tvb_real_ops);
|
||||
tvb_add_to_chain(parent, child);
|
||||
}
|
|
@ -0,0 +1,200 @@
|
|||
/* tvbuff_real.c
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
|
||||
*
|
||||
* Wireshark - Network traffic analyzer
|
||||
* By Gerald Combs <gerald@wireshark.org>
|
||||
* Copyright 1998 Gerald Combs
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tvbuff.h"
|
||||
#include "tvbuff-int.h"
|
||||
#include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
|
||||
|
||||
static gsize
|
||||
subset_sizeof(void)
|
||||
{
|
||||
return sizeof(struct tvb_subset);
|
||||
}
|
||||
|
||||
static guint
|
||||
subset_offset(const tvbuff_t *tvb, const guint counter)
|
||||
{
|
||||
const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
|
||||
const tvbuff_t *member = subset_tvb->subset.tvb;
|
||||
|
||||
return tvb_offset_from_real_beginning_counter(member, counter + subset_tvb->subset.offset);
|
||||
}
|
||||
|
||||
static void *
|
||||
subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
|
||||
}
|
||||
|
||||
static const guint8 *
|
||||
subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_get_ptr(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
|
||||
}
|
||||
|
||||
static gint
|
||||
subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
|
||||
}
|
||||
|
||||
static gint
|
||||
subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const guint8 *needles, guchar *found_needle)
|
||||
{
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
return tvb_pbrk_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needles, found_needle);
|
||||
}
|
||||
|
||||
static tvbuff_t *
|
||||
subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
|
||||
{
|
||||
return tvb_clone_offset_len(tvb, abs_offset, abs_length);
|
||||
}
|
||||
|
||||
static const struct tvb_ops tvb_subset_ops = {
|
||||
subset_sizeof, /* size */
|
||||
NULL, /* free */
|
||||
subset_offset, /* offset */
|
||||
subset_get_ptr, /* get_ptr */
|
||||
subset_memcpy, /* memcpy */
|
||||
subset_find_guint8, /* find_guint8 */
|
||||
subset_pbrk_guint8, /* pbrk_guint8 */
|
||||
subset_clone, /* clone */
|
||||
};
|
||||
|
||||
static tvbuff_t *
|
||||
tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
|
||||
const guint subset_tvb_offset, const guint subset_tvb_length)
|
||||
{
|
||||
tvbuff_t *tvb = tvb_new(&tvb_subset_ops);
|
||||
struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
|
||||
|
||||
subset_tvb->subset.offset = subset_tvb_offset;
|
||||
subset_tvb->subset.length = subset_tvb_length;
|
||||
|
||||
subset_tvb->subset.tvb = backing;
|
||||
tvb->length = subset_tvb_length;
|
||||
tvb->flags = backing->flags;
|
||||
|
||||
if (reported_length == -1) {
|
||||
tvb->reported_length = backing->reported_length - subset_tvb_offset;
|
||||
}
|
||||
else {
|
||||
tvb->reported_length = reported_length;
|
||||
}
|
||||
tvb->initialized = TRUE;
|
||||
tvb_add_to_chain(backing, tvb);
|
||||
|
||||
/* Optimization. If the backing buffer has a pointer to contiguous, real data,
|
||||
* then we can point directly to our starting offset in that buffer */
|
||||
if (backing->real_data != NULL) {
|
||||
tvb->real_data = backing->real_data + subset_tvb_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* The top-level data source of this tvbuff is the top-level
|
||||
* data source of its parent.
|
||||
*/
|
||||
tvb->ds_tvb = backing->ds_tvb;
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
|
||||
{
|
||||
tvbuff_t *tvb;
|
||||
guint subset_tvb_offset;
|
||||
guint subset_tvb_length;
|
||||
|
||||
DISSECTOR_ASSERT(backing && backing->initialized);
|
||||
|
||||
THROW_ON(reported_length < -1, ReportedBoundsError);
|
||||
|
||||
tvb_check_offset_length(backing, backing_offset, backing_length,
|
||||
&subset_tvb_offset,
|
||||
&subset_tvb_length);
|
||||
|
||||
tvb = tvb_new_with_subset(backing, reported_length,
|
||||
subset_tvb_offset, subset_tvb_length);
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint backing_length)
|
||||
{
|
||||
gint captured_length;
|
||||
tvbuff_t *tvb;
|
||||
guint subset_tvb_offset;
|
||||
guint subset_tvb_length;
|
||||
|
||||
DISSECTOR_ASSERT(backing && backing->initialized);
|
||||
|
||||
THROW_ON(backing_length < 0, ReportedBoundsError);
|
||||
|
||||
/*
|
||||
* Give the next dissector only captured_length bytes.
|
||||
*/
|
||||
captured_length = tvb_length_remaining(backing, backing_offset);
|
||||
THROW_ON(captured_length < 0, BoundsError);
|
||||
if (captured_length > backing_length)
|
||||
captured_length = backing_length;
|
||||
|
||||
tvb_check_offset_length(backing, backing_offset, captured_length,
|
||||
&subset_tvb_offset,
|
||||
&subset_tvb_length);
|
||||
|
||||
tvb = tvb_new_with_subset(backing, backing_length,
|
||||
subset_tvb_offset, subset_tvb_length);
|
||||
|
||||
return tvb;
|
||||
}
|
||||
|
||||
tvbuff_t *
|
||||
tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
|
||||
{
|
||||
tvbuff_t *tvb;
|
||||
guint subset_tvb_offset;
|
||||
guint subset_tvb_length;
|
||||
|
||||
tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
|
||||
&subset_tvb_offset,
|
||||
&subset_tvb_length);
|
||||
|
||||
tvb = tvb_new_with_subset(backing, -1 /* reported_length */,
|
||||
subset_tvb_offset, subset_tvb_length);
|
||||
|
||||
return tvb;
|
||||
}
|
Loading…
Reference in New Issue