5 * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <epan/emem.h>
31 #include "tvbuff-int.h"
32 #include "proto.h" /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
33 #include "exceptions.h"
36 /** The backing tvbuff_t */
39 /** The offset of 'tvb' to which I'm privy */
41 /** The length of 'tvb' to which I'm privy */
53 subset_offset(const tvbuff_t
*tvb
, const guint counter
)
55 const struct tvb_subset
*subset_tvb
= (const struct tvb_subset
*) tvb
;
56 const tvbuff_t
*member
= subset_tvb
->subset
.tvb
;
58 return tvb_offset_from_real_beginning_counter(member
, counter
+ subset_tvb
->subset
.offset
);
62 subset_memcpy(tvbuff_t
*tvb
, void *target
, guint abs_offset
, guint abs_length
)
64 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
66 return tvb_memcpy(subset_tvb
->subset
.tvb
, target
, subset_tvb
->subset
.offset
+ abs_offset
, abs_length
);
70 subset_get_ptr(tvbuff_t
*tvb
, guint abs_offset
, guint abs_length
)
72 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
74 return tvb_get_ptr(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, abs_length
);
78 subset_find_guint8(tvbuff_t
*tvb
, guint abs_offset
, guint limit
, guint8 needle
)
80 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
82 return tvb_find_guint8(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, limit
, needle
);
86 subset_pbrk_guint8(tvbuff_t
*tvb
, guint abs_offset
, guint limit
, const guint8
*needles
, guchar
*found_needle
)
88 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
90 return tvb_pbrk_guint8(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, limit
, needles
, found_needle
);
94 subset_clone(tvbuff_t
*tvb
, guint abs_offset
, guint abs_length
)
96 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
98 return tvb_clone_offset_len(subset_tvb
->subset
.tvb
, subset_tvb
->subset
.offset
+ abs_offset
, abs_length
);
101 static const struct tvb_ops tvb_subset_ops
= {
102 sizeof(struct tvb_subset
), /* size */
105 subset_offset
, /* offset */
106 subset_get_ptr
, /* get_ptr */
107 subset_memcpy
, /* memcpy */
108 subset_find_guint8
, /* find_guint8 */
109 subset_pbrk_guint8
, /* pbrk_guint8 */
110 subset_clone
, /* clone */
114 tvb_new_with_subset(tvbuff_t
*backing
, const gint reported_length
,
115 const guint subset_tvb_offset
, const guint subset_tvb_length
)
117 tvbuff_t
*tvb
= tvb_new(&tvb_subset_ops
);
118 struct tvb_subset
*subset_tvb
= (struct tvb_subset
*) tvb
;
120 subset_tvb
->subset
.offset
= subset_tvb_offset
;
121 subset_tvb
->subset
.length
= subset_tvb_length
;
123 subset_tvb
->subset
.tvb
= backing
;
124 tvb
->length
= subset_tvb_length
;
125 tvb
->flags
= backing
->flags
;
127 if (reported_length
== -1) {
128 tvb
->reported_length
= backing
->reported_length
- subset_tvb_offset
;
131 tvb
->reported_length
= reported_length
;
133 tvb
->initialized
= TRUE
;
135 /* Optimization. If the backing buffer has a pointer to contiguous, real data,
136 * then we can point directly to our starting offset in that buffer */
137 if (backing
->real_data
!= NULL
) {
138 tvb
->real_data
= backing
->real_data
+ subset_tvb_offset
;
142 * The top-level data source of this tvbuff is the top-level
143 * data source of its parent.
145 tvb
->ds_tvb
= backing
->ds_tvb
;
151 tvb_new_subset(tvbuff_t
*backing
, const gint backing_offset
, const gint backing_length
, const gint reported_length
)
154 guint subset_tvb_offset
;
155 guint subset_tvb_length
;
157 DISSECTOR_ASSERT(backing
&& backing
->initialized
);
159 THROW_ON(reported_length
< -1, ReportedBoundsError
);
161 tvb_check_offset_length(backing
, backing_offset
, backing_length
,
165 tvb
= tvb_new_with_subset(backing
, reported_length
,
166 subset_tvb_offset
, subset_tvb_length
);
168 tvb_add_to_chain(backing
, tvb
);
174 tvb_new_subset_length(tvbuff_t
*backing
, const gint backing_offset
, const gint backing_length
)
176 gint captured_length
;
178 guint subset_tvb_offset
;
179 guint subset_tvb_length
;
181 DISSECTOR_ASSERT(backing
&& backing
->initialized
);
183 THROW_ON(backing_length
< 0, ReportedBoundsError
);
186 * Give the next dissector only captured_length bytes.
188 captured_length
= tvb_length_remaining(backing
, backing_offset
);
189 THROW_ON(captured_length
< 0, BoundsError
);
190 if (captured_length
> backing_length
)
191 captured_length
= backing_length
;
193 tvb_check_offset_length(backing
, backing_offset
, captured_length
,
197 tvb
= tvb_new_with_subset(backing
, backing_length
,
198 subset_tvb_offset
, subset_tvb_length
);
200 tvb_add_to_chain(backing
, tvb
);
206 tvb_new_subset_remaining(tvbuff_t
*backing
, const gint backing_offset
)
209 guint subset_tvb_offset
;
210 guint subset_tvb_length
;
212 tvb_check_offset_length(backing
, backing_offset
, -1 /* backing_length */,
216 tvb
= tvb_new_with_subset(backing
, -1 /* reported_length */,
217 subset_tvb_offset
, subset_tvb_length
);
219 tvb_add_to_chain(backing
, tvb
);
225 tvb_new_proxy(tvbuff_t
*backing
)
230 tvb
= tvb_new_with_subset(backing
, backing
->reported_length
, 0, backing
->length
);
232 tvb
= tvb_new_real_data(NULL
, 0, 0);