rewrite: update default dumb and smart prefixes
[elinks/elinks-j605.git] / src / util / memlist.c
blob8a7c10b9c7eef358123ef238a4a972592412fc9e
1 /** These routines represent handling of struct memory_list.
2 * @file */
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
8 #include <stdarg.h>
9 #include <stdlib.h>
11 #include "elinks.h"
13 #include "util/error.h"
14 #include "util/memlist.h"
15 #include "util/memory.h"
18 /**
19 * @struct memory_list
20 * memory_list is used to track information about all allocated memory
21 * belonging to something. Then we can free it when we won't need it
22 * anymore, but the one who allocated it won't be able to get control
23 * back in order to free it himself.
26 #define ML_SIZE(n) (sizeof(struct memory_list) + (n) * sizeof(void *))
28 /** Create a memory list. If @a p is NULL or allocation fails, it will
29 * return NULL.
30 * It always stops at first NULL element.
31 * @relates memory_list */
32 #if defined(DEBUG_MEMLIST) && defined(HAVE_VARIADIC_MACROS)
33 struct memory_list *
34 debug_getml(unsigned char *file, int line, void *p, ...)
35 #else
36 struct memory_list *
37 getml(void *p, ...)
38 #endif
40 struct memory_list *ml;
41 va_list ap;
42 void *q;
43 int n = 1;
45 /* If first element is NULL, there's no need to allocate memory, so
46 * just return. */
47 if (!p) return NULL;
49 /* How many elements ? */
50 va_start(ap, p);
51 while ((q = va_arg(ap, void *))) n++;
52 va_end(ap);
54 /* Allocate space for memory list. */
55 ml = mem_alloc(ML_SIZE(n));
56 if (!ml) return NULL;
58 /* First element. */
59 ml->n = 1;
60 ml->p[0] = p;
62 /* Next ones. */
63 va_start(ap, p);
64 while ((q = va_arg(ap, void *))) ml->p[ml->n++] = q;
65 va_end(ap);
67 /* The end. */
68 return ml;
71 /** Add elements to a memory list.
72 * If memory list exists, it enlarges it, else it creates it.
73 * if there's no elements or first element is NULL, it does nothing.
74 * It always stops at first NULL element.
75 * @relates memory_list */
76 #if defined(DEBUG_MEMLIST) && defined(HAVE_VARIADIC_MACROS)
77 void
78 debug_add_to_ml(unsigned char *file, int line, struct memory_list **ml, ...)
79 #else
80 void
81 add_to_ml(struct memory_list **ml, ...)
82 #endif
84 va_list ap;
85 void *q;
86 int n = 0;
88 /* How many new elements ? */
89 va_start(ap, ml);
90 while ((q = va_arg(ap, void *))) n++;
91 va_end(ap);
93 /* None, so just return. */
94 if (!n) {
95 #ifdef DEBUG_MEMLIST
96 #ifdef HAVE_VARIADIC_MACROS
97 errline = line, errfile = file;
98 #else
99 errline = 0, errfile = "?";
100 #endif
101 elinks_error("add_to_ml(%p, NULL, ...)", ml);
102 #endif
103 return;
106 if (!*ml) {
107 /* If getml() wasn't called before or returned NULL,
108 * then we create it. */
109 *ml = mem_alloc(ML_SIZE(n));
110 if (!*ml) return;
112 (*ml)->n = 0;
113 } else {
114 /* Enlarge existing ml. */
115 struct memory_list *nml;
117 nml = mem_realloc(*ml, ML_SIZE(n + (*ml)->n));
118 if (!nml) return;
120 *ml = nml;
123 /* Set ml with new elements and update count. */
124 va_start(ap, ml);
125 while ((q = va_arg(ap, void *))) (*ml)->p[(*ml)->n++] = q;
126 va_end(ap);
129 /** @relates memory_list */
130 #ifdef DEBUG_MEMLIST
131 void
132 debug_add_one_to_ml(unsigned char *file, int line, struct memory_list **ml, void *p)
133 #else
134 void
135 add_one_to_ml(struct memory_list **ml, void *p)
136 #endif
138 /* None, so just return. */
139 if (!p) {
140 #ifdef DEBUG_MEMLIST
141 errline = line, errfile = file;
142 elinks_error("add_one_to_ml(%p, NULL)", ml);
143 #endif
144 return;
147 if (!*ml) {
148 /* If getml() wasn't called before or returned NULL,
149 * then we create it. */
150 *ml = mem_alloc(ML_SIZE(1));
151 if (!*ml) return;
153 (*ml)->n = 0;
154 } else {
155 /* Enlarge existing ml. */
156 struct memory_list *nml;
158 nml = mem_realloc(*ml, ML_SIZE(1 + (*ml)->n));
159 if (!nml) return;
161 *ml = nml;
164 /* Set ml with new element and update count. */
165 (*ml)->p[(*ml)->n++] = p;
169 /** Free elements and memory list.
170 * It returns safely if passed a NULL pointer.
171 * @relates memory_list */
172 void
173 freeml(struct memory_list *ml)
175 int i;
177 if (!ml) return;
179 for (i = 0; i < ml->n; i++)
180 mem_free(ml->p[i]);
182 mem_free(ml);
185 #undef ML_SIZE