1 /* drange.c
2  * Routines for providing general range support to the dfilter library
3  *
4  * Copyright (c) 2000 by Ed Warnicke <hagbard@physics.rutgers.edu>
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs
8  * Copyright 1999 Gerald Combs
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11 
12 #include "config.h"
13 
14 #include "drange.h"
15 #include <wsutil/ws_assert.h>
16 
17 /* drange_node constructor */
18 drange_node*
drange_node_new(void)19 drange_node_new(void)
20 {
21     drange_node* new_range_node;
22 
23     new_range_node = g_new(drange_node,1);
24     new_range_node->start_offset = 0;
25     new_range_node->length = 0;
26     new_range_node->end_offset = 0;
27     new_range_node->ending = DRANGE_NODE_END_T_UNINITIALIZED;
28     return new_range_node;
29 }
30 
31 static drange_node*
drange_node_dup(drange_node * org)32 drange_node_dup(drange_node *org)
33 {
34     drange_node *new_range_node;
35 
36     if (!org)
37         return NULL;
38 
39     new_range_node = g_new(drange_node,1);
40     new_range_node->start_offset = org->start_offset;
41     new_range_node->length = org->length;
42     new_range_node->end_offset = org->end_offset;
43     new_range_node->ending = org->ending;
44     return new_range_node;
45 }
46 
47 /* drange_node destructor */
48 void
drange_node_free(drange_node * drnode)49 drange_node_free(drange_node* drnode)
50 {
51     g_free(drnode);
52 }
53 
54 /* drange_node accessors */
55 gint
drange_node_get_start_offset(drange_node * drnode)56 drange_node_get_start_offset(drange_node* drnode)
57 {
58     ws_assert(drnode->ending != DRANGE_NODE_END_T_UNINITIALIZED);
59     return drnode->start_offset;
60 }
61 
62 gint
drange_node_get_length(drange_node * drnode)63 drange_node_get_length(drange_node* drnode)
64 {
65     ws_assert(drnode->ending == DRANGE_NODE_END_T_LENGTH);
66     return drnode->length;
67 }
68 
69 gint
drange_node_get_end_offset(drange_node * drnode)70 drange_node_get_end_offset(drange_node* drnode)
71 {
72     ws_assert(drnode->ending == DRANGE_NODE_END_T_OFFSET);
73     return drnode->end_offset;
74 }
75 
76 drange_node_end_t
drange_node_get_ending(drange_node * drnode)77 drange_node_get_ending(drange_node* drnode)
78 {
79     ws_assert(drnode->ending != DRANGE_NODE_END_T_UNINITIALIZED);
80     return drnode->ending;
81 }
82 
83 /* drange_node mutators */
84 void
drange_node_set_start_offset(drange_node * drnode,gint offset)85 drange_node_set_start_offset(drange_node* drnode, gint offset)
86 {
87     drnode->start_offset = offset;
88 }
89 
90 void
drange_node_set_length(drange_node * drnode,gint length)91 drange_node_set_length(drange_node* drnode, gint length)
92 {
93     drnode->length = length;
94     drnode->ending = DRANGE_NODE_END_T_LENGTH;
95 }
96 
97 void
drange_node_set_end_offset(drange_node * drnode,gint offset)98 drange_node_set_end_offset(drange_node* drnode, gint offset)
99 {
100     drnode->end_offset = offset;
101     drnode->ending = DRANGE_NODE_END_T_OFFSET;
102 }
103 
104 
105 void
drange_node_set_to_the_end(drange_node * drnode)106 drange_node_set_to_the_end(drange_node* drnode)
107 {
108     drnode->ending = DRANGE_NODE_END_T_TO_THE_END;
109 }
110 
111 /* drange constructor */
112 drange_t *
drange_new(void)113 drange_new(void)
114 {
115     drange_t * new_drange;
116     new_drange = g_new(drange_t,1);
117     new_drange->range_list = NULL;
118     new_drange->has_total_length = TRUE;
119     new_drange->total_length = 0;
120     new_drange->min_start_offset = G_MAXINT;
121     new_drange->max_start_offset = G_MININT;
122     return new_drange;
123 }
124 
125 static void
drange_append_wrapper(gpointer data,gpointer user_data)126 drange_append_wrapper(gpointer data, gpointer user_data)
127 {
128     drange_node *drnode = (drange_node *)data;
129     drange_t    *dr             = (drange_t *)user_data;
130 
131     drange_append_drange_node(dr, drnode);
132 }
133 
134 drange_t *
drange_new_from_list(GSList * list)135 drange_new_from_list(GSList *list)
136 {
137     drange_t    *new_drange;
138 
139     new_drange = drange_new();
140     g_slist_foreach(list, drange_append_wrapper, new_drange);
141     return new_drange;
142 }
143 
144 drange_t *
drange_dup(drange_t * org)145 drange_dup(drange_t *org)
146 {
147     drange_t *new_drange;
148     GSList *p;
149 
150     if (!org)
151         return NULL;
152 
153     new_drange = drange_new();
154     for (p = org->range_list; p; p = p->next) {
155         drange_node *drnode = (drange_node *)p->data;
156         drange_append_drange_node(new_drange, drange_node_dup(drnode));
157     }
158     return new_drange;
159 }
160 
161 
162 /* drange destructor */
163 void
drange_free(drange_t * dr)164 drange_free(drange_t * dr)
165 {
166     drange_node_free_list(dr->range_list);
167     g_free(dr);
168 }
169 
170 /* Call drange_node destructor on all list items */
171 void
drange_node_free_list(GSList * list)172 drange_node_free_list(GSList* list)
173 {
174     g_slist_free_full(list, g_free);
175 }
176 
177 /* drange accessors */
drange_has_total_length(drange_t * dr)178 gboolean drange_has_total_length(drange_t * dr) { return dr->has_total_length; }
drange_get_total_length(drange_t * dr)179 gint drange_get_total_length(drange_t * dr)     { return dr->total_length; }
drange_get_min_start_offset(drange_t * dr)180 gint drange_get_min_start_offset(drange_t * dr) { return dr->min_start_offset; }
drange_get_max_start_offset(drange_t * dr)181 gint drange_get_max_start_offset(drange_t * dr) { return dr->max_start_offset; }
182 
183 static void
update_drange_with_node(drange_t * dr,drange_node * drnode)184 update_drange_with_node(drange_t *dr, drange_node *drnode)
185 {
186     if(drnode->ending == DRANGE_NODE_END_T_TO_THE_END){
187         dr->has_total_length = FALSE;
188     }
189     else if(dr->has_total_length){
190         dr->total_length += drnode->length;
191     }
192     if(drnode->start_offset < dr->min_start_offset){
193         dr->min_start_offset = drnode->start_offset;
194     }
195     if(drnode->start_offset > dr->max_start_offset){
196         dr->max_start_offset = drnode->start_offset;
197     }
198 }
199 
200 /* drange mutators */
201 void
drange_prepend_drange_node(drange_t * dr,drange_node * drnode)202 drange_prepend_drange_node(drange_t * dr, drange_node* drnode)
203 {
204     if(drnode != NULL){
205         dr->range_list = g_slist_prepend(dr->range_list,drnode);
206         update_drange_with_node(dr, drnode);
207     }
208 }
209 
210 void
drange_append_drange_node(drange_t * dr,drange_node * drnode)211 drange_append_drange_node(drange_t * dr, drange_node* drnode)
212 {
213     if(drnode != NULL){
214         dr->range_list = g_slist_append(dr->range_list,drnode);
215         update_drange_with_node(dr, drnode);
216     }
217 }
218 
219 void
drange_foreach_drange_node(drange_t * dr,GFunc func,gpointer funcdata)220 drange_foreach_drange_node(drange_t * dr, GFunc func, gpointer funcdata)
221 {
222     g_slist_foreach(dr->range_list,func,funcdata);
223 }
224 
225 static void
_sprint_drange_node(GString * repr,drange_node * rn)226 _sprint_drange_node(GString *repr, drange_node *rn)
227 {
228     if (rn->ending == DRANGE_NODE_END_T_TO_THE_END)
229         g_string_append_printf(repr, "%d:",
230                             rn->start_offset);
231     else if(rn->ending == DRANGE_NODE_END_T_OFFSET)
232         g_string_append_printf(repr, "%d-%d",
233                             rn->start_offset, rn->end_offset);
234     else if (rn->ending == DRANGE_NODE_END_T_LENGTH)
235         g_string_append_printf(repr, "%d:%d",
236                             rn->start_offset, rn->length);
237     else
238         g_string_append_printf(repr, "%d/%d/%d/U",
239                             rn->start_offset, rn->length, rn->end_offset);
240 }
241 
242 char *
drange_tostr(drange_t * dr)243 drange_tostr(drange_t *dr)
244 {
245     GString *repr = g_string_new("");
246     GSList *range_list = dr->range_list;
247 
248     while (range_list) {
249         _sprint_drange_node(repr, (drange_node *)(range_list->data));
250         range_list = g_slist_next(range_list);
251         if (range_list != NULL) {
252             g_string_append_c(repr, ',');
253         }
254     }
255 
256     return g_string_free(repr, FALSE);
257 }
258 
259 /*
260  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
261  *
262  * Local variables:
263  * c-basic-offset: 4
264  * tab-width: 8
265  * indent-tabs-mode: nil
266  * End:
267  *
268  * vi: set shiftwidth=4 tabstop=8 expandtab:
269  * :indentSize=4:tabSize=8:noTabs=true:
270  */
271