radiotap: Updates to the radiotap dissector to avoid confusion.
[metze/wireshark/wip.git] / epan / tvbuff_subset.c
1 /* tvbuff_real.c
2  *
3  * Copyright (c) 2000 by Gilbert Ramirez <gram@alumni.rice.edu>
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include "config.h"
25
26 #include "tvbuff.h"
27 #include "tvbuff-int.h"
28 #include "proto.h"      /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
29 #include "exceptions.h"
30
31 typedef struct {
32         /** The backing tvbuff_t */
33         struct tvbuff   *tvb;
34
35         /** The offset of 'tvb' to which I'm privy */
36         guint           offset;
37         /** The length of 'tvb' to which I'm privy */
38         guint           length;
39
40 } tvb_backing_t;
41
42 struct tvb_subset {
43         struct tvbuff tvb;
44
45         tvb_backing_t   subset;
46 };
47
48 static guint
49 subset_offset(const tvbuff_t *tvb, const guint counter)
50 {
51         const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
52         const tvbuff_t *member = subset_tvb->subset.tvb;
53
54         return tvb_offset_from_real_beginning_counter(member, counter + subset_tvb->subset.offset);
55 }
56
57 static void *
58 subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
59 {
60         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
61
62         return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
63 }
64
65 static const guint8 *
66 subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
67 {
68         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
69
70         return tvb_get_ptr(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
71 }
72
73 static gint
74 subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
75 {
76         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
77
78         return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
79 }
80
81 static gint
82 subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
83 {
84         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
85
86         return tvb_ws_mempbrk_pattern_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, pattern, found_needle);
87 }
88
89 static tvbuff_t *
90 subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
91 {
92         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
93
94         return tvb_clone_offset_len(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
95 }
96
97 static const struct tvb_ops tvb_subset_ops = {
98         sizeof(struct tvb_subset), /* size */
99
100         NULL,                 /* free */
101         subset_offset,        /* offset */
102         subset_get_ptr,       /* get_ptr */
103         subset_memcpy,        /* memcpy */
104         subset_find_guint8,   /* find_guint8 */
105         subset_pbrk_guint8,   /* pbrk_guint8 */
106         subset_clone,         /* clone */
107 };
108
109 static tvbuff_t *
110 tvb_new_with_subset(tvbuff_t *backing, const gint reported_length,
111     const guint subset_tvb_offset, const guint subset_tvb_length)
112 {
113         tvbuff_t *tvb = tvb_new(&tvb_subset_ops);
114         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
115
116         subset_tvb->subset.offset = subset_tvb_offset;
117         subset_tvb->subset.length = subset_tvb_length;
118
119         subset_tvb->subset.tvb       = backing;
120         tvb->length                  = subset_tvb_length;
121         tvb->flags                   = backing->flags;
122
123         if (reported_length == -1) {
124                 tvb->reported_length = backing->reported_length - subset_tvb_offset;
125         }
126         else {
127                 tvb->reported_length = reported_length;
128         }
129         tvb->initialized             = TRUE;
130
131         /* Optimization. If the backing buffer has a pointer to contiguous, real data,
132          * then we can point directly to our starting offset in that buffer */
133         if (backing->real_data != NULL) {
134                 tvb->real_data = backing->real_data + subset_tvb_offset;
135         }
136
137         /*
138          * The top-level data source of this tvbuff is the top-level
139          * data source of its parent.
140          */
141         tvb->ds_tvb = backing->ds_tvb;
142
143         return tvb;
144 }
145
146 tvbuff_t *
147 tvb_new_subset_length_caplen(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
148 {
149         tvbuff_t *tvb;
150         guint     subset_tvb_offset;
151         guint     subset_tvb_length;
152
153         DISSECTOR_ASSERT(backing && backing->initialized);
154
155         THROW_ON(reported_length < -1, ReportedBoundsError);
156
157         tvb_check_offset_length(backing, backing_offset, backing_length,
158                                 &subset_tvb_offset,
159                                 &subset_tvb_length);
160
161         tvb = tvb_new_with_subset(backing, reported_length,
162             subset_tvb_offset, subset_tvb_length);
163
164         tvb_add_to_chain(backing, tvb);
165
166         return tvb;
167 }
168
169 tvbuff_t *
170 tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint backing_length)
171 {
172         gint      captured_length;
173         tvbuff_t *tvb;
174         guint     subset_tvb_offset;
175         guint     subset_tvb_length;
176
177         DISSECTOR_ASSERT(backing && backing->initialized);
178
179         THROW_ON(backing_length < 0, ReportedBoundsError);
180
181         /*
182          * Give the next dissector only captured_length bytes.
183          */
184         captured_length = tvb_captured_length_remaining(backing, backing_offset);
185         THROW_ON(captured_length < 0, BoundsError);
186         if (captured_length > backing_length)
187                 captured_length = backing_length;
188
189         tvb_check_offset_length(backing, backing_offset, captured_length,
190                                 &subset_tvb_offset,
191                                 &subset_tvb_length);
192
193         tvb = tvb_new_with_subset(backing, backing_length,
194             subset_tvb_offset, subset_tvb_length);
195
196         tvb_add_to_chain(backing, tvb);
197
198         return tvb;
199 }
200
201 tvbuff_t *
202 tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
203 {
204         tvbuff_t *tvb;
205         guint     subset_tvb_offset;
206         guint     subset_tvb_length;
207
208         tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
209                                 &subset_tvb_offset,
210                                 &subset_tvb_length);
211
212         tvb = tvb_new_with_subset(backing, -1 /* reported_length */,
213             subset_tvb_offset, subset_tvb_length);
214
215         tvb_add_to_chain(backing, tvb);
216
217         return tvb;
218 }
219
220 tvbuff_t *
221 tvb_new_proxy(tvbuff_t *backing)
222 {
223         tvbuff_t *tvb;
224
225         if (backing)
226                 tvb = tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
227         else
228                 tvb = tvb_new_real_data(NULL, 0, 0);
229
230         tvb->ds_tvb = tvb;
231
232         return tvb;
233 }
234
235
236 /*
237  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
238  *
239  * Local variables:
240  * c-basic-offset: 8
241  * tab-width: 8
242  * indent-tabs-mode: t
243  * End:
244  *
245  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
246  * :indentSize=8:tabSize=8:noTabs=false:
247  */