Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dfilter / drange.c
blobc82b48bd045345916e9079f049bb1fe0e487591a
1 /* drange.c
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
7 * By Gerald Combs
8 * Copyright 1999 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 #include "config.h"
14 #include "drange.h"
16 #include <errno.h>
17 #include <stdlib.h>
20 /* drange_node constructor */
21 drange_node*
22 drange_node_new(void)
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;
34 static bool
35 drange_str_to_int32(const char *s, int32_t *pint, char **endptr, char **err_ptr)
37 long integer;
39 errno = 0;
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);
44 return false;
46 if (errno == ERANGE || integer > INT32_MAX || integer < INT32_MIN) {
47 *err_ptr = ws_strdup_printf("\"%s\" causes an integer overflow.", s);
48 return false;
50 *pint = (int32_t)integer;
51 return true;
54 /* drange_node constructor from string */
55 drange_node*
56 drange_node_from_str(const char *range_str, char **err_ptr)
58 const char *str;
59 char *endptr;
60 int32_t lower, upper = 0;
61 drange_node_end_t end = DRANGE_NODE_END_T_UNINITIALIZED;
62 drange_node *dn;
63 bool ok;
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
74 str = range_str;
75 if (*str == ':') {
76 lower = 0;
77 /* Do not advance 'str' here. */
79 else {
80 if (!drange_str_to_int32(str, &lower, &endptr, err_ptr))
81 return NULL;
82 str = endptr;
85 while (*str != '\0' && g_ascii_isspace(*str))
86 str++;
88 if (*str == '-') {
89 str++;
90 end = DRANGE_NODE_END_T_OFFSET;
91 ok = drange_str_to_int32(str, &upper, &endptr, err_ptr);
92 str = endptr;
94 else if (*str == ':') {
95 str++;
96 if (*str == '\0') {
97 end = DRANGE_NODE_END_T_TO_THE_END;
98 ok = true;
100 else {
101 end = DRANGE_NODE_END_T_LENGTH;
102 ok = drange_str_to_int32(str, &upper, &endptr, err_ptr);
103 str = endptr;
106 else if (*str == '\0') {
107 end = DRANGE_NODE_END_T_LENGTH;
108 upper = 1;
109 ok = true;
111 else {
112 ok = false;
115 while (*str != '\0' && g_ascii_isspace(*str))
116 str++;
118 if (!ok || *str != '\0') {
119 *err_ptr = ws_strdup_printf("\"%s\" is not a valid range.", range_str);
120 return NULL;
123 dn = drange_node_new();
124 drange_node_set_start_offset(dn, lower);
125 switch (end) {
126 case DRANGE_NODE_END_T_LENGTH:
127 if (upper <= 0) {
128 *err_ptr = ws_strdup_printf("Range %s isn't valid "
129 "because length %d isn't positive",
130 range_str, upper);
131 drange_node_free(dn);
132 return NULL;
134 drange_node_set_length(dn, upper);
135 break;
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);
142 return NULL;
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);
149 return NULL;
151 drange_node_set_end_offset(dn, upper);
152 break;
153 case DRANGE_NODE_END_T_TO_THE_END:
154 drange_node_set_to_the_end(dn);
155 break;
156 default:
157 ws_assert_not_reached();
158 break;
161 return dn;
164 static drange_node*
165 drange_node_dup(drange_node *org)
167 drange_node *new_range_node;
169 if (!org)
170 return NULL;
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 */
181 void
182 drange_node_free(drange_node* drnode)
184 g_free(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;
209 drange_node_end_t
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 */
217 void
218 drange_node_set_start_offset(drange_node* drnode, int offset)
220 drnode->start_offset = offset;
223 void
224 drange_node_set_length(drange_node* drnode, int length)
226 drnode->length = length;
227 drnode->ending = DRANGE_NODE_END_T_LENGTH;
230 void
231 drange_node_set_end_offset(drange_node* drnode, int offset)
233 drnode->end_offset = offset;
234 drnode->ending = DRANGE_NODE_END_T_OFFSET;
238 void
239 drange_node_set_to_the_end(drange_node* drnode)
241 drnode->ending = DRANGE_NODE_END_T_TO_THE_END;
244 /* drange constructor */
245 drange_t *
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;
256 if (drnode)
257 drange_append_drange_node(new_drange, drnode);
259 return new_drange;
262 static void
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);
271 drange_t *
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);
278 return new_drange;
281 drange_t *
282 drange_dup(drange_t *org)
284 drange_t *new_drange;
285 GSList *p;
287 if (!org)
288 return NULL;
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));
295 return new_drange;
299 /* drange destructor */
300 void
301 drange_free(drange_t * dr)
303 drange_node_free_list(dr->range_list);
304 g_free(dr);
307 /* Call drange_node destructor on all list items */
308 void
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; }
320 static void
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 */
338 void
339 drange_prepend_drange_node(drange_t * dr, drange_node* drnode)
341 if(drnode != NULL){
342 dr->range_list = g_slist_prepend(dr->range_list,drnode);
343 update_drange_with_node(dr, drnode);
347 void
348 drange_append_drange_node(drange_t * dr, drange_node* drnode)
350 if(drnode != NULL){
351 dr->range_list = g_slist_append(dr->range_list,drnode);
352 update_drange_with_node(dr, drnode);
356 void
357 drange_foreach_drange_node(drange_t * dr, GFunc func, void *funcdata)
359 g_slist_foreach(dr->range_list,func,funcdata);
362 char *
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);
371 else
372 return ws_strdup_printf("%d/%d/%d/U", rn->start_offset, rn->length, rn->end_offset);
375 char *
376 drange_tostr(const drange_t *dr)
378 GString *repr = g_string_new("");
379 GSList *range_list = dr->range_list;
380 char *s;
382 while (range_list) {
383 s = drange_node_tostr(range_list->data);
384 g_string_append(repr, s);
385 g_free(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
398 * Local variables:
399 * c-basic-offset: 4
400 * tab-width: 8
401 * indent-tabs-mode: nil
402 * End:
404 * vi: set shiftwidth=4 tabstop=8 expandtab:
405 * :indentSize=4:tabSize=8:noTabs=true: