2 * Routines for providing general range support to the dfilter library
4 * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu>
6 * Wireshark - Network traffic analyzer
8 * Copyright 1999 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
20 /* drange_node constructor */
24 drange_node
* new_range_node
;
26 new_range_node
= g_new(drange_node
,1);
27 new_range_node
->start_offset
= 0;
28 new_range_node
->length
= 0;
29 new_range_node
->end_offset
= 0;
30 new_range_node
->ending
= DRANGE_NODE_END_T_UNINITIALIZED
;
31 return new_range_node
;
35 drange_str_to_int32(const char *s
, int32_t *pint
, char **endptr
, char **err_ptr
)
40 integer
= strtol(s
, endptr
, 0);
41 if (errno
== EINVAL
|| *endptr
== s
) {
42 /* This isn't a valid number. */
43 *err_ptr
= ws_strdup_printf("\"%s\" is not a valid number.", s
);
46 if (errno
== ERANGE
|| integer
> INT32_MAX
|| integer
< INT32_MIN
) {
47 *err_ptr
= ws_strdup_printf("\"%s\" causes an integer overflow.", s
);
50 *pint
= (int32_t)integer
;
54 /* drange_node constructor from string */
56 drange_node_from_str(const char *range_str
, char **err_ptr
)
60 int32_t lower
, upper
= 0;
61 drange_node_end_t end
= DRANGE_NODE_END_T_UNINITIALIZED
;
66 * The following syntax governs slices:
67 * [i:j] i = start_offset, j = length
68 * [i-j] i = start_offset, j = end_offset, inclusive.
69 * [i] i = start_offset, length = 1
70 * [:j] start_offset = 0, length = j
71 * [i:] start_offset = i, end_offset = end_of_field
77 /* Do not advance 'str' here. */
80 if (!drange_str_to_int32(str
, &lower
, &endptr
, err_ptr
))
85 while (*str
!= '\0' && g_ascii_isspace(*str
))
90 end
= DRANGE_NODE_END_T_OFFSET
;
91 ok
= drange_str_to_int32(str
, &upper
, &endptr
, err_ptr
);
94 else if (*str
== ':') {
97 end
= DRANGE_NODE_END_T_TO_THE_END
;
101 end
= DRANGE_NODE_END_T_LENGTH
;
102 ok
= drange_str_to_int32(str
, &upper
, &endptr
, err_ptr
);
106 else if (*str
== '\0') {
107 end
= DRANGE_NODE_END_T_LENGTH
;
115 while (*str
!= '\0' && g_ascii_isspace(*str
))
118 if (!ok
|| *str
!= '\0') {
119 *err_ptr
= ws_strdup_printf("\"%s\" is not a valid range.", range_str
);
123 dn
= drange_node_new();
124 drange_node_set_start_offset(dn
, lower
);
126 case DRANGE_NODE_END_T_LENGTH
:
128 *err_ptr
= ws_strdup_printf("Range %s isn't valid "
129 "because length %d isn't positive",
131 drange_node_free(dn
);
134 drange_node_set_length(dn
, upper
);
136 case DRANGE_NODE_END_T_OFFSET
:
137 if ((lower
< 0 && upper
> 0) || (lower
> 0 && upper
< 0)) {
138 *err_ptr
= ws_strdup_printf("Range %s isn't valid "
139 "because %d and %d have different signs",
140 range_str
, lower
, upper
);
141 drange_node_free(dn
);
144 if (upper
<= lower
) {
145 *err_ptr
= ws_strdup_printf("Range %s isn't valid "
146 "because %d is greater or equal than %d",
147 range_str
, lower
, upper
);
148 drange_node_free(dn
);
151 drange_node_set_end_offset(dn
, upper
);
153 case DRANGE_NODE_END_T_TO_THE_END
:
154 drange_node_set_to_the_end(dn
);
157 ws_assert_not_reached();
165 drange_node_dup(drange_node
*org
)
167 drange_node
*new_range_node
;
172 new_range_node
= g_new(drange_node
,1);
173 new_range_node
->start_offset
= org
->start_offset
;
174 new_range_node
->length
= org
->length
;
175 new_range_node
->end_offset
= org
->end_offset
;
176 new_range_node
->ending
= org
->ending
;
177 return new_range_node
;
180 /* drange_node destructor */
182 drange_node_free(drange_node
* drnode
)
187 /* drange_node accessors */
189 drange_node_get_start_offset(drange_node
* drnode
)
191 ws_assert(drnode
->ending
!= DRANGE_NODE_END_T_UNINITIALIZED
);
192 return drnode
->start_offset
;
196 drange_node_get_length(drange_node
* drnode
)
198 ws_assert(drnode
->ending
== DRANGE_NODE_END_T_LENGTH
);
199 return drnode
->length
;
203 drange_node_get_end_offset(drange_node
* drnode
)
205 ws_assert(drnode
->ending
== DRANGE_NODE_END_T_OFFSET
);
206 return drnode
->end_offset
;
210 drange_node_get_ending(drange_node
* drnode
)
212 ws_assert(drnode
->ending
!= DRANGE_NODE_END_T_UNINITIALIZED
);
213 return drnode
->ending
;
216 /* drange_node mutators */
218 drange_node_set_start_offset(drange_node
* drnode
, int offset
)
220 drnode
->start_offset
= offset
;
224 drange_node_set_length(drange_node
* drnode
, int length
)
226 drnode
->length
= length
;
227 drnode
->ending
= DRANGE_NODE_END_T_LENGTH
;
231 drange_node_set_end_offset(drange_node
* drnode
, int offset
)
233 drnode
->end_offset
= offset
;
234 drnode
->ending
= DRANGE_NODE_END_T_OFFSET
;
239 drange_node_set_to_the_end(drange_node
* drnode
)
241 drnode
->ending
= DRANGE_NODE_END_T_TO_THE_END
;
244 /* drange constructor */
246 drange_new(drange_node
* drnode
)
248 drange_t
* new_drange
;
249 new_drange
= g_new(drange_t
,1);
250 new_drange
->range_list
= NULL
;
251 new_drange
->has_total_length
= true;
252 new_drange
->total_length
= 0;
253 new_drange
->min_start_offset
= INT_MAX
;
254 new_drange
->max_start_offset
= INT_MIN
;
257 drange_append_drange_node(new_drange
, drnode
);
263 drange_append_wrapper(void *data
, void *user_data
)
265 drange_node
*drnode
= (drange_node
*)data
;
266 drange_t
*dr
= (drange_t
*)user_data
;
268 drange_append_drange_node(dr
, drnode
);
272 drange_new_from_list(GSList
*list
)
274 drange_t
*new_drange
;
276 new_drange
= drange_new(NULL
);
277 g_slist_foreach(list
, drange_append_wrapper
, new_drange
);
282 drange_dup(drange_t
*org
)
284 drange_t
*new_drange
;
290 new_drange
= drange_new(NULL
);
291 for (p
= org
->range_list
; p
; p
= p
->next
) {
292 drange_node
*drnode
= (drange_node
*)p
->data
;
293 drange_append_drange_node(new_drange
, drange_node_dup(drnode
));
299 /* drange destructor */
301 drange_free(drange_t
* dr
)
303 drange_node_free_list(dr
->range_list
);
307 /* Call drange_node destructor on all list items */
309 drange_node_free_list(GSList
* list
)
311 g_slist_free_full(list
, g_free
);
314 /* drange accessors */
315 bool drange_has_total_length(drange_t
* dr
) { return dr
->has_total_length
; }
316 int drange_get_total_length(drange_t
* dr
) { return dr
->total_length
; }
317 int drange_get_min_start_offset(drange_t
* dr
) { return dr
->min_start_offset
; }
318 int drange_get_max_start_offset(drange_t
* dr
) { return dr
->max_start_offset
; }
321 update_drange_with_node(drange_t
*dr
, drange_node
*drnode
)
323 if(drnode
->ending
== DRANGE_NODE_END_T_TO_THE_END
){
324 dr
->has_total_length
= false;
326 else if(dr
->has_total_length
){
327 dr
->total_length
+= drnode
->length
;
329 if(drnode
->start_offset
< dr
->min_start_offset
){
330 dr
->min_start_offset
= drnode
->start_offset
;
332 if(drnode
->start_offset
> dr
->max_start_offset
){
333 dr
->max_start_offset
= drnode
->start_offset
;
337 /* drange mutators */
339 drange_prepend_drange_node(drange_t
* dr
, drange_node
* drnode
)
342 dr
->range_list
= g_slist_prepend(dr
->range_list
,drnode
);
343 update_drange_with_node(dr
, drnode
);
348 drange_append_drange_node(drange_t
* dr
, drange_node
* drnode
)
351 dr
->range_list
= g_slist_append(dr
->range_list
,drnode
);
352 update_drange_with_node(dr
, drnode
);
357 drange_foreach_drange_node(drange_t
* dr
, GFunc func
, void *funcdata
)
359 g_slist_foreach(dr
->range_list
,func
,funcdata
);
363 drange_node_tostr(const drange_node
*rn
)
365 if (rn
->ending
== DRANGE_NODE_END_T_TO_THE_END
)
366 return ws_strdup_printf("%d:", rn
->start_offset
);
367 else if(rn
->ending
== DRANGE_NODE_END_T_OFFSET
)
368 return ws_strdup_printf("%d-%d", rn
->start_offset
, rn
->end_offset
);
369 else if (rn
->ending
== DRANGE_NODE_END_T_LENGTH
)
370 return ws_strdup_printf("%d:%d", rn
->start_offset
, rn
->length
);
372 return ws_strdup_printf("%d/%d/%d/U", rn
->start_offset
, rn
->length
, rn
->end_offset
);
376 drange_tostr(const drange_t
*dr
)
378 GString
*repr
= g_string_new("");
379 GSList
*range_list
= dr
->range_list
;
383 s
= drange_node_tostr(range_list
->data
);
384 g_string_append(repr
, s
);
386 range_list
= g_slist_next(range_list
);
387 if (range_list
!= NULL
) {
388 g_string_append_c(repr
, ',');
392 return g_string_free(repr
, FALSE
);
396 * Editor modelines - https://www.wireshark.org/tools/modelines.html
401 * indent-tabs-mode: nil
404 * vi: set shiftwidth=4 tabstop=8 expandtab:
405 * :indentSize=4:tabSize=8:noTabs=true: