Witness: add pidl output
[wireshark-wip.git] / epan / tvbuff_subset.c
blob3370ee070f181a911b12af028906a70cef0ae5ed
1 /* tvbuff_real.c
3 * $Id$
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.
26 #include "config.h"
28 #include <epan/emem.h>
30 #include "tvbuff.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"
35 typedef struct {
36 /** The backing tvbuff_t */
37 struct tvbuff *tvb;
39 /** The offset of 'tvb' to which I'm privy */
40 guint offset;
41 /** The length of 'tvb' to which I'm privy */
42 guint length;
44 } tvb_backing_t;
46 struct tvb_subset {
47 struct tvbuff tvb;
49 tvb_backing_t subset;
52 static guint
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);
61 static void *
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);
69 static const guint8 *
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);
77 static gint
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);
85 static gint
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);
93 static tvbuff_t *
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 */
104 NULL, /* free */
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 */
113 static tvbuff_t *
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;
130 else {
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;
147 return tvb;
150 tvbuff_t *
151 tvb_new_subset(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
153 tvbuff_t *tvb;
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,
162 &subset_tvb_offset,
163 &subset_tvb_length);
165 tvb = tvb_new_with_subset(backing, reported_length,
166 subset_tvb_offset, subset_tvb_length);
168 tvb_add_to_chain(backing, tvb);
170 return tvb;
173 tvbuff_t *
174 tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint backing_length)
176 gint captured_length;
177 tvbuff_t *tvb;
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,
194 &subset_tvb_offset,
195 &subset_tvb_length);
197 tvb = tvb_new_with_subset(backing, backing_length,
198 subset_tvb_offset, subset_tvb_length);
200 tvb_add_to_chain(backing, tvb);
202 return tvb;
205 tvbuff_t *
206 tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
208 tvbuff_t *tvb;
209 guint subset_tvb_offset;
210 guint subset_tvb_length;
212 tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
213 &subset_tvb_offset,
214 &subset_tvb_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);
221 return tvb;
224 tvbuff_t *
225 tvb_new_proxy(tvbuff_t *backing)
227 tvbuff_t *tvb;
229 if (backing)
230 tvb = tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
231 else
232 tvb = tvb_new_real_data(NULL, 0, 0);
234 tvb->ds_tvb = tvb;
236 return tvb;