6 * Dick Gooris <gooris@lucent.com>
7 * Ulf Lamping <ulf.lamping@web.de>
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
37 #include <epan/frame_data.h>
39 #include <epan/range.h>
40 #include <epan/emem.h>
44 * Size of the header of a range_t.
46 #define RANGE_HDR_SIZE (sizeof (range_t) - sizeof (range_admin_t))
48 /* Allocate an empty range. */
49 range_t
*range_empty(void)
53 range
= (range_t
*)g_malloc(RANGE_HDR_SIZE
);
58 /******************** Range Entry Parser *********************************/
60 /* Converts a range string to a fast comparable array of ranges.
61 * The parameter 'es' points to the string to be converted.
62 * The parameter 'max_value' specifies the maximum value in a
65 * This function allocates a range_t large enough to hold the number
66 * of ranges specified, and fills the array range->ranges containing
67 * low and high values with the number of ranges being range->nranges.
68 * After having called this function, the function value_is_in_range()
69 * determines whether a given number is within the range or not.
71 * In case of a single number, we make a range where low is equal to high.
72 * We take care on wrongly entered ranges; opposite order will be taken
75 * The following syntax is accepted :
77 * 1-20,30-40 Range from 1 to 20, and packets 30 to 40
78 * -20,30 Range from 1 to 20, and packet 30
79 * 20,30,40- 20, 30, and the range from 40 to the end
80 * 20-10,30-25 Range from 10 to 20, and from 25 to 30
85 range_convert_str(range_t
**rangep
, const gchar
*es
, guint32 max_value
)
87 return range_convert_str_work(rangep
, es
, max_value
, TRUE
);
90 /* This version of range_convert_str() allows the caller to specify whether
91 * values in excess of the range's specified maximum should cause an error or
92 * be silently lowered.
93 * XXX - both the function and the variable could probably use better names.
96 range_convert_str_work(range_t
**rangep
, const gchar
*es
, guint32 max_value
,
109 if ( (rangep
== NULL
) || (es
== NULL
) )
110 return CVT_SYNTAX_ERROR
;
112 /* Allocate a range; this has room for one subrange. */
113 range
= (range_t
*)g_malloc(RANGE_HDR_SIZE
+ sizeof (range_admin_t
));
117 /* Process the ranges separately until we get a comma or end of string.
119 * We build a structure array called ranges of high and low values. After the
120 * following loop, we have the nranges variable which tells how many ranges
121 * were found. The number of individual ranges is limited to 'MaxRanges'
126 /* Skip white space. */
127 while ((c
= *p
) == ' ' || c
== '\t')
132 /* This must be a subrange. Make sure we have room for it. */
133 if (range
->nranges
>= nranges
) {
134 /* Grow the structure.
135 * 4 is an arbitrarily chosen number.
136 * We start with 1, under the assumption that people
137 * will often give a single number or range, and then
138 * proceed to keep it a multiple of 4.
144 range
= (range_t
*)g_realloc(range
, RANGE_HDR_SIZE
+
145 nranges
*sizeof (range_admin_t
));
149 /* Subrange starts with 1. */
150 range
->ranges
[range
->nranges
].low
= 1;
151 } else if (isdigit((unsigned char)c
)) {
152 /* Subrange starts with the specified number */
154 val
= strtoul(p
, &endp
, 10);
156 /* That wasn't a valid number. */
158 return CVT_SYNTAX_ERROR
;
160 if (errno
== ERANGE
|| val
> max_value
) {
161 /* That was valid, but it's too big. Return an error if requested
162 * (e.g., except when reading from the preferences file).
166 return CVT_NUMBER_TOO_BIG
;
168 /* Silently use the range's maximum value */
173 range
->ranges
[range
->nranges
].low
= (guint32
)val
;
175 /* Skip white space. */
176 while ((c
= *p
) == ' ' || c
== '\t')
179 /* Neither empty nor a number. */
181 return CVT_SYNTAX_ERROR
;
185 /* There's a hyphen in the range. Skip past it. */
188 /* Skip white space. */
189 while ((c
= *p
) == ' ' || c
== '\t')
192 if (c
== ',' || c
== '\0') {
193 /* End of subrange string; that means the subrange ends
196 range
->ranges
[range
->nranges
].high
= max_value
;
197 } else if (isdigit((unsigned char)c
)) {
198 /* Subrange ends with the specified number. */
200 val
= strtoul(p
, &endp
, 10);
202 /* That wasn't a valid number. */
204 return CVT_SYNTAX_ERROR
;
206 if (errno
== ERANGE
|| val
> max_value
) {
207 /* That was valid, but it's too big. Return an error if requested
208 * (e.g., except when reading from the preferences file).
212 return CVT_NUMBER_TOO_BIG
;
214 /* Silently use the range's maximum value */
219 range
->ranges
[range
->nranges
].high
= (guint32
)val
;
221 /* Skip white space. */
222 while ((c
= *p
) == ' ' || c
== '\t')
225 /* Neither empty nor a number. */
227 return CVT_SYNTAX_ERROR
;
229 } else if (c
== ',' || c
== '\0') {
230 /* End of subrange string; that means there's no hyphen
231 * in the subrange, so the start and the end are the same.
233 range
->ranges
[range
->nranges
].high
= range
->ranges
[range
->nranges
].low
;
235 /* Invalid character. */
237 return CVT_SYNTAX_ERROR
;
242 /* Subrange is followed by a comma; skip it. */
247 /* Now we are going through the low and high values, and check
248 * whether they are in a proper order. Low should be equal or lower
249 * than high. So, go through the loop and swap if needed.
251 for (i
=0; i
< range
->nranges
; i
++) {
252 if (range
->ranges
[i
].low
> range
->ranges
[i
].high
) {
253 tmp
= range
->ranges
[i
].low
;
254 range
->ranges
[i
].low
= range
->ranges
[i
].high
;
255 range
->ranges
[i
].high
= tmp
;
259 /* In case we want to know what the result ranges are :
261 * for (i=0; i < range->nranges; i++) {
262 * printf("Function : range_convert_str L=%u \t H=%u\n",range->ranges[i].low,range->ranges[i].high);
268 } /* range_convert_str */
270 /* This function returns TRUE if a given value is within one of the ranges
271 * stored in the ranges array.
274 value_is_in_range(range_t
*range
, guint32 val
)
279 for (i
=0; i
< range
->nranges
; i
++) {
280 if (val
>= range
->ranges
[i
].low
&& val
<= range
->ranges
[i
].high
)
287 /* This function returns TRUE if the two given range_t's are equal.
290 ranges_are_equal(range_t
*a
, range_t
*b
)
294 if ( (a
== NULL
) || (b
== NULL
) )
297 if (a
->nranges
!= b
->nranges
)
300 for (i
=0; i
< a
->nranges
; i
++) {
301 if (a
->ranges
[i
].low
!= b
->ranges
[i
].low
)
304 if (a
->ranges
[i
].high
!= b
->ranges
[i
].high
)
312 /* This function calls the provided callback function for each value in
316 range_foreach(range_t
*range
, void (*callback
)(guint32 val
))
320 if (range
&& callback
) {
321 for (i
=0; i
< range
->nranges
; i
++) {
322 for (j
= range
->ranges
[i
].low
; j
<= range
->ranges
[i
].high
; j
++)
328 /* This function converts a range_t to a (ep_alloc()-allocated) string. */
330 range_convert_range(range_t
*range
)
333 gboolean prepend_comma
= FALSE
;
334 emem_strbuf_t
*strbuf
;
336 strbuf
=ep_strbuf_new(NULL
);
339 for (i
=0; i
< range
->nranges
; i
++) {
340 if (range
->ranges
[i
].low
== range
->ranges
[i
].high
) {
341 ep_strbuf_append_printf(strbuf
, "%s%u", prepend_comma
?",":"", range
->ranges
[i
].low
);
343 ep_strbuf_append_printf(strbuf
, "%s%u-%u", prepend_comma
?",":"", range
->ranges
[i
].low
, range
->ranges
[i
].high
);
345 prepend_comma
= TRUE
;
351 /* Create a copy of a range. */
353 range_copy(range_t
*src
)
361 range_size
= RANGE_HDR_SIZE
+ src
->nranges
*sizeof (range_admin_t
);
362 dst
= (range_t
*)g_malloc(range_size
);
363 memcpy(dst
, src
, range_size
);
368 /* This is a debug function to check the range functionality */
370 value_is_in_range_check(range_t
*range
, guint32 val
)
372 /* Print the result for a given value */
373 printf("Function : value_is_in_range_check Number %u\t",val
);
375 if (value_is_in_range(range
, val
)) {
376 printf("is in range\n");
378 printf("is not in range\n");