1 /* frame_data_sequence.c
2 * Implements a sequence of frame_data structures
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <epan/packet.h>
31 #include "frame_data_sequence.h"
34 * We store the frame_data structures in a radix tree, with 1024
35 * elements per level. The leaf nodes are arrays of 1024 frame_data
36 * structures; the nodes above them are arrays of 1024 pointers to
37 * the nodes below them. The capture_file structure has a pointer
40 * As frame numbers are 32 bits, and as 1024 is 2^10, that gives us
41 * up to 4 levels of tree.
43 #define LOG2_NODES_PER_LEVEL 10
44 #define NODES_PER_LEVEL (1<<LOG2_NODES_PER_LEVEL)
46 struct _frame_data_sequence
{
47 guint32 count
; /* Total number of frames */
48 void *ptree_root
; /* Pointer to the root node */
52 * For a given frame number, calculate the indices into a level 3
53 * node, a level 2 node, a level 1 node, and a leaf node.
55 #define LEVEL_3_INDEX(framenum) \
56 ((framenum) >> (3*LOG2_NODES_PER_LEVEL))
57 #define LEVEL_2_INDEX(framenum) \
58 (((framenum) >> (2*LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1))
59 #define LEVEL_1_INDEX(framenum) \
60 (((framenum) >> (1*LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1))
61 #define LEAF_INDEX(framenum) \
62 (((framenum) >> (0*LOG2_NODES_PER_LEVEL)) & (NODES_PER_LEVEL - 1))
65 new_frame_data_sequence(void)
67 frame_data_sequence
*fds
;
69 fds
= (frame_data_sequence
*)g_malloc(sizeof *fds
);
71 fds
->ptree_root
= NULL
;
76 * Add a new frame_data structure to a frame_data_sequence.
79 frame_data_sequence_add(frame_data_sequence
*fds
, frame_data
*fdata
)
84 frame_data
****level3
;
88 * The current value of fds->count is the index value for the new frame,
89 * because the index value for a frame is the frame number - 1, and
90 * if we currently have fds->count frames, the the frame number of
91 * the last frame in the collection is fds->count, so its index value
94 if (fds
->count
== 0) {
95 /* The tree is empty; allocate the first leaf node, which will be
97 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
99 fds
->ptree_root
= leaf
;
100 } else if (fds
->count
< NODES_PER_LEVEL
) {
101 /* It's a 1-level tree, and is going to stay that way for now. */
102 leaf
= (frame_data
*)fds
->ptree_root
;
103 node
= &leaf
[fds
->count
];
104 } else if (fds
->count
== NODES_PER_LEVEL
) {
105 /* It's a 1-level tree that will turn into a 2-level tree. */
106 level1
= (frame_data
**)g_malloc0((sizeof *level1
)*NODES_PER_LEVEL
);
107 level1
[0] = (frame_data
*)fds
->ptree_root
;
108 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
111 fds
->ptree_root
= level1
;
112 } else if (fds
->count
< NODES_PER_LEVEL
*NODES_PER_LEVEL
) {
113 /* It's a 2-level tree, and is going to stay that way for now. */
114 level1
= (frame_data
**)fds
->ptree_root
;
115 leaf
= level1
[fds
->count
>> LOG2_NODES_PER_LEVEL
];
117 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
118 level1
[fds
->count
>> LOG2_NODES_PER_LEVEL
] = leaf
;
120 node
= &leaf
[LEAF_INDEX(fds
->count
)];
121 } else if (fds
->count
== NODES_PER_LEVEL
*NODES_PER_LEVEL
) {
122 /* It's a 2-level tree that will turn into a 3-level tree */
123 level2
= (frame_data
***)g_malloc0((sizeof *level2
)*NODES_PER_LEVEL
);
124 level2
[0] = (frame_data
**)fds
->ptree_root
;
125 level1
= (frame_data
**)g_malloc0((sizeof *level1
)*NODES_PER_LEVEL
);
127 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
130 fds
->ptree_root
= level2
;
131 } else if (fds
->count
< NODES_PER_LEVEL
*NODES_PER_LEVEL
*NODES_PER_LEVEL
) {
132 /* It's a 3-level tree, and is going to stay that way for now. */
133 level2
= (frame_data
***)fds
->ptree_root
;
134 level1
= level2
[fds
->count
>> (LOG2_NODES_PER_LEVEL
+LOG2_NODES_PER_LEVEL
)];
135 if (level1
== NULL
) {
136 level1
= (frame_data
**)g_malloc0((sizeof *level1
)*NODES_PER_LEVEL
);
137 level2
[fds
->count
>> (LOG2_NODES_PER_LEVEL
+LOG2_NODES_PER_LEVEL
)] = level1
;
139 leaf
= level1
[LEVEL_1_INDEX(fds
->count
)];
141 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
142 level1
[LEVEL_1_INDEX(fds
->count
)] = leaf
;
144 node
= &leaf
[LEAF_INDEX(fds
->count
)];
145 } else if (fds
->count
== NODES_PER_LEVEL
*NODES_PER_LEVEL
*NODES_PER_LEVEL
) {
146 /* It's a 3-level tree that will turn into a 4-level tree */
147 level3
= (frame_data
****)g_malloc0((sizeof *level3
)*NODES_PER_LEVEL
);
148 level3
[0] = (frame_data
***)fds
->ptree_root
;
149 level2
= (frame_data
***)g_malloc0((sizeof *level2
)*NODES_PER_LEVEL
);
151 level1
= (frame_data
**)g_malloc0((sizeof *level1
)*NODES_PER_LEVEL
);
153 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
156 fds
->ptree_root
= level3
;
158 /* fds->count is 2^32-1 at most, and NODES_PER_LEVEL^4
159 2^(LOG2_NODES_PER_LEVEL*4), and LOG2_NODES_PER_LEVEL is 10,
160 so fds->count is always less < NODES_PER_LEVEL^4.
162 XXX - we should fail if fds->count is 2^31-1, or should
163 make the frame numbers 64-bit and just let users run
164 themselves out of address space or swap space. :-) */
165 /* It's a 4-level tree, and is going to stay that way forever. */
166 level3
= (frame_data
****)fds
->ptree_root
;
167 level2
= level3
[LEVEL_3_INDEX(fds
->count
)];
168 if (level2
== NULL
) {
169 level2
= (frame_data
***)g_malloc0((sizeof *level2
)*NODES_PER_LEVEL
);
170 level3
[LEVEL_3_INDEX(fds
->count
)] = level2
;
172 level1
= level2
[LEVEL_2_INDEX(fds
->count
)];
173 if (level1
== NULL
) {
174 level1
= (frame_data
**)g_malloc0((sizeof *level1
)*NODES_PER_LEVEL
);
175 level2
[LEVEL_2_INDEX(fds
->count
)] = level1
;
177 leaf
= level1
[LEVEL_1_INDEX(fds
->count
)];
179 leaf
= (frame_data
*)g_malloc((sizeof *leaf
)*NODES_PER_LEVEL
);
180 level1
[LEVEL_1_INDEX(fds
->count
)] = leaf
;
182 node
= &leaf
[LEAF_INDEX(fds
->count
)];
190 * Find the frame_data for the specified frame number.
193 frame_data_sequence_find(frame_data_sequence
*fds
, guint32 num
)
197 frame_data
***level2
;
198 frame_data
****level3
;
201 /* There is no frame number 0 */
205 /* Convert it into an index number. */
207 if (num
>= fds
->count
) {
208 /* There aren't that many frames. */
212 if (fds
->count
<= NODES_PER_LEVEL
) {
213 /* It's a 1-level tree. */
214 leaf
= (frame_data
*)fds
->ptree_root
;
217 if (fds
->count
<= NODES_PER_LEVEL
*NODES_PER_LEVEL
) {
218 /* It's a 2-level tree. */
219 level1
= (frame_data
**)fds
->ptree_root
;
220 leaf
= level1
[num
>> LOG2_NODES_PER_LEVEL
];
221 return &leaf
[LEAF_INDEX(num
)];
223 if (fds
->count
<= NODES_PER_LEVEL
*NODES_PER_LEVEL
*NODES_PER_LEVEL
) {
224 /* It's a 3-level tree. */
225 level2
= (frame_data
***)fds
->ptree_root
;
226 level1
= level2
[num
>> (LOG2_NODES_PER_LEVEL
+LOG2_NODES_PER_LEVEL
)];
227 leaf
= level1
[(num
>> LOG2_NODES_PER_LEVEL
) & (NODES_PER_LEVEL
- 1)];
228 return &leaf
[LEAF_INDEX(num
)];
230 /* fds->count is 2^32-1 at most, and NODES_PER_LEVEL^4
231 2^(LOG2_NODES_PER_LEVEL*4), and LOG2_NODES_PER_LEVEL is 10,
232 so fds->count is always less < NODES_PER_LEVEL^4. */
233 /* It's a 4-level tree, and is going to stay that way forever. */
234 level3
= (frame_data
****)fds
->ptree_root
;
235 level2
= level3
[num
>> (LOG2_NODES_PER_LEVEL
+LOG2_NODES_PER_LEVEL
+LOG2_NODES_PER_LEVEL
)];
236 level1
= level2
[(num
>> (LOG2_NODES_PER_LEVEL
+LOG2_NODES_PER_LEVEL
)) & (NODES_PER_LEVEL
- 1)];
237 leaf
= level1
[(num
>> LOG2_NODES_PER_LEVEL
) & (NODES_PER_LEVEL
- 1)];
238 return &leaf
[LEAF_INDEX(num
)];
241 /* recursively frees a frame_data radix level */
243 free_frame_data_array(void *array
, guint count
, guint level
, gboolean last
)
245 guint i
, level_count
;
248 /* if we are the last in our given parent's row, we may not have
249 * exactly a full row, so do the bit twiddling to figure out exactly
250 * how many fields we have */
251 level_count
= (count
>> ((level
- 1) * LOG2_NODES_PER_LEVEL
)) &
252 (NODES_PER_LEVEL
- 1);
253 /* the above calculation rounds down, so make sure we count correctly
254 * if count is not an even multiple of NODES_PER_LEVEL */
255 if (count
& ((1 << ((level
- 1) * LOG2_NODES_PER_LEVEL
)) - 1)) {
260 /* if we're not the last in our parent, then we're guaranteed to have
262 level_count
= NODES_PER_LEVEL
;
267 /* recurse on every sub-array, passing on our own 'last' value
268 * specially to our last child */
269 frame_data
**real_array
= (frame_data
**) array
;
271 for (i
=0; i
< level_count
-1; i
++) {
272 free_frame_data_array(real_array
[i
], count
, level
-1, FALSE
);
275 free_frame_data_array(real_array
[level_count
-1], count
, level
-1, last
);
277 else if (level
== 1) {
278 /* bottom level, so just clean up all the frame data */
279 frame_data
*real_array
= (frame_data
*) array
;
281 for (i
=0; i
< level_count
; i
++) {
282 frame_data_destroy(&real_array
[i
]);
286 /* free the array itself */
291 * Free a frame_data_sequence and all the frame_data structures in it.
294 free_frame_data_sequence(frame_data_sequence
*fds
)
296 guint32 count
= fds
->count
;
299 /* calculate how many levels we have */
302 count
>>= LOG2_NODES_PER_LEVEL
;
305 /* call the recursive free function */
307 free_frame_data_array(fds
->ptree_root
, fds
->count
, levels
, TRUE
);
310 /* free the header struct */
315 find_and_mark_frame_depended_upon(gpointer data
, gpointer user_data
)
317 frame_data
*dependent_fd
;
318 guint32 dependent_frame
= GPOINTER_TO_UINT(data
);
319 frame_data_sequence
*frames
= (frame_data_sequence
*)user_data
;
321 if (dependent_frame
&& frames
) {
322 dependent_fd
= frame_data_sequence_find(frames
, dependent_frame
);
323 dependent_fd
->flags
.dependent_of_displayed
= 1;
328 * Editor modelines - http://www.wireshark.org/tools/modelines.html
333 * indent-tabs-mode: nil
336 * vi: set shiftwidth=2 tabstop=8 expandtab:
337 * :indentSize=2:tabSize=8:noTabs=true: