give se_trees names so that it is easier to debug and to log how often certain...
[metze/wireshark/wip.git] / epan / emem.h
1 /* emem.h
2  * Definitions for ethereal memory management and garbage collection
3  * Ronnie Sahlberg 2005
4  *
5  * $Id$
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifndef __EMEM_H__
27 #define __EMEM_H__
28
29 #include "gnuc_format_check.h"
30
31 /* Functions for handling memory allocation and garbage collection with 
32  * a packet lifetime scope.
33  * These functions are used to allocate memory that will only remain persistent
34  * until ethereal starts dissecting the next packet in the list.
35  * Everytime ethereal starts decoding the next packet all memory allocated
36  * through these functions will be released back to the free pool.
37  *
38  * These functions are very fast and offer automatic garbage collection:
39  * Everytime a new packet is dissected, all memory allocations done in
40  * the previous packet is freed.
41  */
42 /* Initialize packet-lifetime memory allocation pool. This function is called 
43  * once when [t]ethereal is initialized to set up the required structures.
44  */
45 void ep_init_chunk(void);
46
47 /* Allocate memory with a packet lifetime scope */
48 void *ep_alloc(size_t size);
49 #define ep_new(type) ((type*)ep_alloc(sizeof(type)))
50
51 /* Allocate memory with a packet lifetime scope and fill it with zeros*/
52 void* ep_alloc0(size_t size);
53 #define ep_new0(type) ((type*)ep_alloc0(sizeof(type)))
54
55 /* Duplicate a string with a packet lifetime scope */
56 gchar* ep_strdup(const gchar* src);
57
58 /* Duplicate at most n characters of a string with a packet lifetime scope */
59 gchar* ep_strndup(const gchar* src, size_t len);
60
61 /* Duplicate a buffer with a packet lifetime scope */
62 void* ep_memdup(const void* src, size_t len);
63
64 /* Create a formatted string with a packet lifetime scope */
65 gchar* ep_strdup_vprintf(const gchar* fmt, va_list ap);
66 gchar* ep_strdup_printf(const gchar* fmt, ...)
67     GNUC_FORMAT_CHECK(printf, 1, 2);
68
69 /* allocates with a packet lifetime scope an array of type made of num elements */
70 #define ep_alloc_array(type,num) (type*)ep_alloc(sizeof(type)*(num))
71
72 /* 
73  * Splits a string into a maximum of max_tokens pieces, using the given
74  * delimiter. If max_tokens is reached, the remainder of string is appended
75  * to the last token. Consecutive delimiters are treated as a single delimiter.
76  *
77  * the vector and all the strings are allocated with packet lifetime scope
78  */
79 gchar** ep_strsplit(const gchar* string, const gchar* delimiter, int max_tokens);
80
81 /* release all memory allocated in the previous packet dissector */
82 void ep_free_all(void);
83
84
85 /* a stack implemented using ephemeral allocators */
86
87 typedef struct _ep_stack_frame_t** ep_stack_t;
88
89 struct _ep_stack_frame_t {
90     void* payload;
91     struct _ep_stack_frame_t* below;
92     struct _ep_stack_frame_t* above;
93 };
94
95 /*
96  * creates an empty stack with a packet lifetime scope
97  */
98 ep_stack_t ep_stack_new(void);
99
100 /*
101  * pushes item into stack, returns item
102  */
103 void* ep_stack_push(ep_stack_t stack, void* item);
104
105 /*
106  * pops an item from the stack
107  */
108 void* ep_stack_pop(ep_stack_t stack);
109
110 /*
111  * returns the item on top of the stack without popping it
112  */
113 #define ep_stack_peek(stack) ((*(stack))->payload)
114
115
116 /* Functions for handling memory allocation and garbage collection with 
117  * a capture lifetime scope.
118  * These functions are used to allocate memory that will only remain persistent
119  * until ethereal opens a new capture or capture file.
120  * Everytime ethereal starts a new capture or opens a new capture file
121  * all the data allocated through these functions will be released back 
122  * to the free pool.
123  *
124  * These functions are very fast and offer automatic garbage collection.
125  */
126 /* Initialize capture-lifetime memory allocation pool. This function is called 
127  * once when [t]ethereal is initialized to set up the required structures.
128  */
129 void se_init_chunk(void);
130
131 /* Allocate memory with a capture lifetime scope */
132 void *se_alloc(size_t size);
133
134 /* Allocate memory with a capture lifetime scope and fill it with zeros*/
135 void* se_alloc0(size_t size);
136
137 /* Duplicate a string with a capture lifetime scope */
138 gchar* se_strdup(const gchar* src);
139
140 /* Duplicate at most n characters of a string with a capture lifetime scope */
141 gchar* se_strndup(const gchar* src, size_t len);
142
143 /* Duplicate a buffer with a capture lifetime scope */
144 void* se_memdup(const void* src, size_t len);
145
146 /* Create a formatted string with a capture lifetime scope */
147 gchar* se_strdup_vprintf(const gchar* fmt, va_list ap);
148 gchar* se_strdup_printf(const gchar* fmt, ...)
149     GNUC_FORMAT_CHECK(printf, 1, 2);
150
151 /* allocates with a capture lifetime scope an array of type made of num elements */
152 #define se_alloc_array(type,num) (type*)se_alloc(sizeof(type)*(num))
153
154 /* release all memory allocated */
155 void se_free_all(void);
156
157
158
159
160 /**************************************************************
161  * binary trees with SE allocation 
162  **************************************************************/
163 #define SE_TREE_RB_COLOR_RED    0x00
164 #define SE_TREE_RB_COLOR_BLACK  0x01
165 typedef struct _se_tree_node_t {
166         struct _se_tree_node_t *parent;
167         struct _se_tree_node_t *left;
168         struct _se_tree_node_t *right;
169         union {
170                 guint32 rb_color;
171         };
172         guint32 key32;
173         void *data;
174 } se_tree_node_t;
175
176 /* list of all se trees so they can all be reset automatically when
177  * we free all se memory
178  */
179 /* Right now we only do basic red/black trees   but in the future we might want
180  * to try something different, such as a tree where each node keeps track
181  * of how many times it has been looked up, and letting often looked up
182  * nodes bubble upwards in the tree using rotate_right/left.
183  * That would probably be good for things like nfs filehandles 
184  */
185 #define SE_TREE_TYPE_RED_BLACK  1
186 typedef struct _se_tree_t {
187         struct _se_tree_t *next;
188         int type;
189         char *name;    /* just a string to make debugging easier */
190         se_tree_node_t *tree;
191 } se_tree_t;
192 extern se_tree_t *se_trees;
193
194
195 /* This function is used to create a se based tree with monitoring.
196  * When the SE heap is released back to the system the pointer to the 
197  * tree is automatically reset to NULL.
198  *
199  * type is : SE_TREE_TYPE_RED_BLACK for a standard red/black tree.
200  */
201 se_tree_t *se_tree_create(int type, char *name);
202
203 /* This function is used to insert a node indexed by a guint32 key value.
204  * The data pointer should be allocated by SE allocators so that the
205  * data will be released at the same time as the tree itself is destroyed.
206  */
207 void se_tree_insert32(se_tree_t *se_tree, guint32 key, void *data);
208
209 /* This function will look up a node in the tree indexed by a guint32 integer
210  * value.
211  */
212 void *se_tree_lookup32(se_tree_t *se_tree, guint32 key);
213
214
215 /* This function is similar to the se_tree_create() call but with the
216  * difference that when the se memory is release everything including the 
217  * pointer to the tree itself will be released.
218  * This tree will not be just reset to zero  it will be completely forgotten
219  * by the allocator.
220  * Use this function for when you want to store the pointer to a tree inside
221  * another structure that is also se allocated so that when the structure is
222  * released, the tree will be completely released as well.
223  */
224 se_tree_t *se_tree_create_non_persistent(int type, char *name);
225
226 typedef struct _se_tree_key_t {
227         guint32 length;                 /*length in guint32 words */
228         guint32 *key;
229 } se_tree_key_t;
230
231 /* This function is used to insert a node indexed by a sequence of guint32 
232  * key values.
233  * The data pointer should be allocated by SE allocators so that the
234  * data will be released at the same time as the tree itself is destroyed.
235  *
236  * If you use ...32_array() calls you MUST make sure that every single node
237  * you add to a specific tree always has a key of exactly the same number of 
238  * keylen words or things will most likely crash. Or at least that every single
239  * item that sits behind the same top level node always have exactly the same
240  * number of words.
241  *
242  * One way to guarantee this is the way that NFS does this for the
243  * nfs_name_snoop_known  tree which holds filehandles for both v2 and v3.
244  * v2 filehandles are always 32 bytes (8 words) while v3 filehandles can have
245  * any length (though 32bytes are most common).
246  * The NFS dissector handles this by providing a guint32 containing the length
247  * as the very first item in this vector :
248  *
249  *                      se_tree_key_t fhkey[3];
250  *
251  *                      fhlen=nns->fh_length;
252  *                      fhkey[0].length=1;
253  *                      fhkey[0].key=&fhlen;
254  *                      fhkey[1].length=fhlen/4;
255  *                      fhkey[1].key=nns->fh;
256  *                      fhkey[2].length=0;
257  */
258 void se_tree_insert32_array(se_tree_t *se_tree, se_tree_key_t *key, void *data);
259
260 /* This function will look up a node in the tree indexed by a sequence of
261  * guint32 integer values.
262  */
263 void *se_tree_lookup32_array(se_tree_t *se_tree, se_tree_key_t *key);
264
265 /*
266  * A hash table with string keys based on the red/black tree
267  */
268 typedef struct _se_tree_t se_string_hash_t;
269
270 /* Create a new string based hash table */
271 #define se_tree_create_string() se_tree_create(SE_TREE_TYPE_RED_BLACK)
272
273 /* Insert a new value under a string key */
274 void se_tree_insert_string(se_string_hash_t* h, const gchar* k, void* v);
275
276 /* Lookup the value under a string key */
277 void* se_tree_lookup_string(se_string_hash_t* h, const gchar* k);
278
279
280 #endif /* emem.h */