Qt: Add copy from another profile in UAT dialogs
[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  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include "config.h"
13
14 #include "tvbuff.h"
15 #include "tvbuff-int.h"
16 #include "proto.h"      /* XXX - only used for DISSECTOR_ASSERT, probably a new header file? */
17 #include "exceptions.h"
18
19 typedef struct {
20         /** The backing tvbuff_t */
21         struct tvbuff   *tvb;
22
23         /** The offset of 'tvb' to which I'm privy */
24         guint           offset;
25         /** The length of 'tvb' to which I'm privy */
26         guint           length;
27
28 } tvb_backing_t;
29
30 struct tvb_subset {
31         struct tvbuff tvb;
32
33         tvb_backing_t   subset;
34 };
35
36 static guint
37 subset_offset(const tvbuff_t *tvb, const guint counter)
38 {
39         const struct tvb_subset *subset_tvb = (const struct tvb_subset *) tvb;
40         const tvbuff_t *member = subset_tvb->subset.tvb;
41
42         return tvb_offset_from_real_beginning_counter(member, counter + subset_tvb->subset.offset);
43 }
44
45 static void *
46 subset_memcpy(tvbuff_t *tvb, void *target, guint abs_offset, guint abs_length)
47 {
48         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
49
50         return tvb_memcpy(subset_tvb->subset.tvb, target, subset_tvb->subset.offset + abs_offset, abs_length);
51 }
52
53 static const guint8 *
54 subset_get_ptr(tvbuff_t *tvb, guint abs_offset, guint abs_length)
55 {
56         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
57
58         return tvb_get_ptr(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
59 }
60
61 static gint
62 subset_find_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, guint8 needle)
63 {
64         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
65
66         return tvb_find_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, needle);
67 }
68
69 static gint
70 subset_pbrk_guint8(tvbuff_t *tvb, guint abs_offset, guint limit, const ws_mempbrk_pattern* pattern, guchar *found_needle)
71 {
72         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
73
74         return tvb_ws_mempbrk_pattern_guint8(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, limit, pattern, found_needle);
75 }
76
77 static tvbuff_t *
78 subset_clone(tvbuff_t *tvb, guint abs_offset, guint abs_length)
79 {
80         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
81
82         return tvb_clone_offset_len(subset_tvb->subset.tvb, subset_tvb->subset.offset + abs_offset, abs_length);
83 }
84
85 static const struct tvb_ops tvb_subset_ops = {
86         sizeof(struct tvb_subset), /* size */
87
88         NULL,                 /* free */
89         subset_offset,        /* offset */
90         subset_get_ptr,       /* get_ptr */
91         subset_memcpy,        /* memcpy */
92         subset_find_guint8,   /* find_guint8 */
93         subset_pbrk_guint8,   /* pbrk_guint8 */
94         subset_clone,         /* clone */
95 };
96
97 static tvbuff_t *
98 tvb_new_with_subset(tvbuff_t *backing, const guint reported_length,
99     const guint subset_tvb_offset, const guint subset_tvb_length)
100 {
101         tvbuff_t *tvb = tvb_new(&tvb_subset_ops);
102         struct tvb_subset *subset_tvb = (struct tvb_subset *) tvb;
103
104         subset_tvb->subset.offset = subset_tvb_offset;
105         subset_tvb->subset.length = subset_tvb_length;
106
107         subset_tvb->subset.tvb       = backing;
108         tvb->length                  = subset_tvb_length;
109         /*
110          * The contained length must not exceed what remains in the
111          * backing tvbuff.
112          */
113         tvb->contained_length        = MIN(reported_length, backing->contained_length - subset_tvb_offset);
114         tvb->flags                   = backing->flags;
115
116         tvb->reported_length         = reported_length;
117         tvb->initialized             = TRUE;
118
119         /* Optimization. If the backing buffer has a pointer to contiguous, real data,
120          * then we can point directly to our starting offset in that buffer */
121         if (backing->real_data != NULL) {
122                 tvb->real_data = backing->real_data + subset_tvb_offset;
123         }
124
125         /*
126          * The top-level data source of this tvbuff is the top-level
127          * data source of its parent.
128          */
129         tvb->ds_tvb = backing->ds_tvb;
130
131         return tvb;
132 }
133
134 tvbuff_t *
135 tvb_new_subset_length_caplen(tvbuff_t *backing, const gint backing_offset, const gint backing_length, const gint reported_length)
136 {
137         tvbuff_t *tvb;
138         guint     subset_tvb_offset;
139         guint     subset_tvb_length;
140         guint     actual_reported_length;
141
142         DISSECTOR_ASSERT(backing && backing->initialized);
143
144         THROW_ON(reported_length < -1, ReportedBoundsError);
145
146         tvb_check_offset_length(backing, backing_offset, backing_length,
147                                 &subset_tvb_offset,
148                                 &subset_tvb_length);
149
150         if (reported_length == -1)
151                 actual_reported_length = backing->reported_length - subset_tvb_offset;
152         else
153                 actual_reported_length = (guint)reported_length;
154
155         tvb = tvb_new_with_subset(backing, actual_reported_length,
156             subset_tvb_offset, subset_tvb_length);
157
158         tvb_add_to_chain(backing, tvb);
159
160         return tvb;
161 }
162
163 tvbuff_t *
164 tvb_new_subset_length(tvbuff_t *backing, const gint backing_offset, const gint reported_length)
165 {
166         gint      captured_length;
167         gint      actual_reported_length;
168         tvbuff_t *tvb;
169         guint     subset_tvb_offset;
170         guint     subset_tvb_length;
171
172         DISSECTOR_ASSERT(backing && backing->initialized);
173
174         THROW_ON(reported_length < -1, ReportedBoundsError);
175
176         if (reported_length == -1)
177                 actual_reported_length = backing->reported_length;
178         else
179                 actual_reported_length = reported_length;
180
181         /*
182          * Cut the captured length short, so it doesn't go past the subset's
183          * reported length.
184          */
185         captured_length = tvb_captured_length_remaining(backing, backing_offset);
186         THROW_ON(captured_length < 0, BoundsError);
187         if (captured_length > actual_reported_length)
188                 captured_length = actual_reported_length;
189
190         tvb_check_offset_length(backing, backing_offset, captured_length,
191                                 &subset_tvb_offset,
192                                 &subset_tvb_length);
193
194         tvb = tvb_new_with_subset(backing, (guint)actual_reported_length,
195             subset_tvb_offset, subset_tvb_length);
196
197         tvb_add_to_chain(backing, tvb);
198
199         return tvb;
200 }
201
202 tvbuff_t *
203 tvb_new_subset_remaining(tvbuff_t *backing, const gint backing_offset)
204 {
205         tvbuff_t *tvb;
206         guint     subset_tvb_offset;
207         guint     subset_tvb_length;
208         guint     reported_length;
209
210         tvb_check_offset_length(backing, backing_offset, -1 /* backing_length */,
211                                 &subset_tvb_offset,
212                                 &subset_tvb_length);
213
214         THROW_ON(backing->reported_length < subset_tvb_offset, ReportedBoundsError);
215         reported_length = backing->reported_length - subset_tvb_offset;
216
217         tvb = tvb_new_with_subset(backing, reported_length,
218             subset_tvb_offset, subset_tvb_length);
219
220         tvb_add_to_chain(backing, tvb);
221
222         return tvb;
223 }
224
225 tvbuff_t *
226 tvb_new_proxy(tvbuff_t *backing)
227 {
228         tvbuff_t *tvb;
229
230         if (backing)
231                 tvb = tvb_new_with_subset(backing, backing->reported_length, 0, backing->length);
232         else
233                 tvb = tvb_new_real_data(NULL, 0, 0);
234
235         tvb->ds_tvb = tvb;
236
237         return tvb;
238 }
239
240
241 /*
242  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
243  *
244  * Local variables:
245  * c-basic-offset: 8
246  * tab-width: 8
247  * indent-tabs-mode: t
248  * End:
249  *
250  * vi: set shiftwidth=8 tabstop=8 noexpandtab:
251  * :indentSize=8:tabSize=8:noTabs=false:
252  */