2 * Ethereal memory management and garbage collection functions
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@ethereal.com>
9 * Copyright 1998 Gerald Combs
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.
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.
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.
37 /* When required, allocate more memory from the OS in this size chunks */
38 #define EMEM_PACKET_CHUNK_SIZE 10485760
40 typedef struct _emem_chunk_t {
41 struct _emem_chunk_t *next;
42 unsigned int amount_free;
43 unsigned int free_offset;
47 typedef struct _emem_header_t {
48 emem_chunk_t *free_list;
49 emem_chunk_t *used_list;
52 static emem_header_t emem_packet_mem;
54 /* Initialize the packet-lifetime memory allocation pool.
55 * This function should be called only once when Etehreal or Tethereal starts
61 emem_packet_mem.free_list=NULL;
62 emem_packet_mem.used_list=NULL;
65 /* allocate 'size' amount of memory with an allocation lifetime until the
73 /* round up to 8 byte boundary */
75 size=(size+7)&0xfffffff8;
78 /* make sure we dont try to allocate too much (arbitrary limit) */
79 DISSECTOR_ASSERT(size<(EMEM_PACKET_CHUNK_SIZE>>2));
81 /* we dont have any free data, so we must allocate a new one */
82 if(!emem_packet_mem.free_list){
84 npc=g_malloc(sizeof(emem_chunk_t));
86 npc->amount_free=EMEM_PACKET_CHUNK_SIZE;
88 npc->buf=g_malloc(EMEM_PACKET_CHUNK_SIZE);
89 emem_packet_mem.free_list=npc;
92 /* oops, we need to allocate more memory to serve this request
93 * than we have free. move this node to the used list and try again
95 if(size>emem_packet_mem.free_list->amount_free){
97 npc=emem_packet_mem.free_list;
98 emem_packet_mem.free_list=emem_packet_mem.free_list->next;
99 npc->next=emem_packet_mem.used_list;
100 emem_packet_mem.used_list=npc;
103 /* we dont have any free data, so we must allocate a new one */
104 if(!emem_packet_mem.free_list){
106 npc=g_malloc(sizeof(emem_chunk_t));
108 npc->amount_free=EMEM_PACKET_CHUNK_SIZE;
110 npc->buf=g_malloc(EMEM_PACKET_CHUNK_SIZE);
111 emem_packet_mem.free_list=npc;
115 buf=emem_packet_mem.free_list->buf+emem_packet_mem.free_list->free_offset;
117 emem_packet_mem.free_list->amount_free-=size;
118 emem_packet_mem.free_list->free_offset+=size;
123 void* ep_alloc0(size_t size) {
124 return memset(ep_alloc(size),'\0',size);
127 gchar* ep_strdup(const gchar* src) {
128 guint len = strlen(src);
131 dst = strncpy(ep_alloc(len+1), src, len);
138 gchar* ep_strndup(const gchar* src, size_t len) {
139 guint actual_len = strlen(src);
142 if (len > actual_len)
145 dst = strncpy(ep_alloc(len+1), src, len);
152 guint8* ep_memdup(const guint8* src, size_t len) {
153 return memcpy(ep_alloc(len), src, len);
156 gchar* ep_strdup_printf(const gchar* fmt, ...) {
162 len = g_printf_string_upper_bound (fmt, ap);
164 dst = ep_alloc(len+1);
165 g_vsnprintf (dst, len, fmt, ap);
171 gchar** ep_strsplit(const gchar* string, const gchar* sep, int max_tokens) {
175 guint str_len = strlen(splitted);
176 guint sep_len = strlen(sep);
179 enum { AT_START, IN_PAD, IN_TOKEN } state;
187 s = splitted = ep_strdup(string);
188 str_len = strlen(splitted);
189 sep_len = strlen(sep);
191 if (max_tokens < 1) max_tokens = INT_MAX;
196 while (tokens <= (guint)max_tokens && ( s = strstr(s,sep) )) {
199 for(i=0; i < sep_len; i++ )
206 vec = ep_alloc_array(gchar,tokens+1);
209 for (i=0; i< str_len; i++) {
212 switch(splitted[i]) {
217 vec[curr_tok] = &(splitted[i]);
223 switch(splitted[i]) {
230 switch(splitted[i]) {
232 vec[curr_tok] = &(splitted[i]);
241 vec[curr_tok] = NULL;
246 /* release all allocated memory back to the pool.
253 /* move all used chunks ove to the free list */
254 while(emem_packet_mem.used_list){
255 npc=emem_packet_mem.used_list;
256 emem_packet_mem.used_list=emem_packet_mem.used_list->next;
257 npc->next=emem_packet_mem.free_list;
258 emem_packet_mem.free_list=npc;
261 /* clear them all out */
262 for(npc=emem_packet_mem.free_list;npc;npc=npc->next){
263 npc->amount_free=EMEM_PACKET_CHUNK_SIZE;