chiark / gitweb /
plugins/tracklength-gstreamer.c: Rewrite to use `GstDiscoverer'.
[disorder] / lib / mem.c
1 /*
2  * This file is part of DisOrder.
3  * Copyright (C) 2004, 2005, 2006, 2007, 2009 Richard Kettlewell
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file lib/mem.c
19  * @brief Memory management
20  */
21
22 #include "common.h"
23
24 #if GC
25 #include <gc.h>
26 #endif
27 #include <errno.h>
28
29 #include "mem.h"
30 #include "log.h"
31 #include "printf.h"
32
33 #include "disorder.h"
34
35 /** @brief Allocate and zero out
36  * @param n Number of bytes to allocate
37  * @return Pointer to allocated memory,  or 0
38  */
39 static void *malloc_and_zero(size_t n) {
40   void *ptr = malloc(n);
41
42   if(ptr) memset(ptr, 0, n);
43   return ptr;
44 }
45
46 #if GC
47 static void *(*do_malloc)(size_t) = GC_malloc;
48 static void *(*do_realloc)(void *, size_t) = GC_realloc;
49 static void *(*do_malloc_atomic)(size_t) = GC_malloc_atomic;
50 static void (*do_free)(void *) = GC_free;
51 #else
52 static void *(*do_malloc)(size_t) = malloc_and_zero;
53 static void *(*do_realloc)(void *, size_t) = realloc;
54 static void *(*do_malloc_atomic)(size_t) = malloc;
55 static void (*do_free)(void *) = free;
56 #endif
57
58 /** @brief Initialize memory management
59  *
60  * Must be called by all programs that use garbage collection.  Define
61  * @c ${DISORDER_GC} to @c no to suppress use of the collector
62  * (e.g. for debugging purposes).
63  */
64 void mem_init(void) {
65 #if GC
66   const char *e;
67   
68   if(((e = getenv("DISORDER_GC")) && !strcmp(e, "no"))) {
69     do_malloc = malloc_and_zero;
70     do_malloc_atomic = malloc;
71     do_realloc = realloc;
72     do_free = free;
73   } else {
74     GC_init();
75 #ifdef HAVE_GC_GET_ALL_INTERIOR_POINTERS
76     assert(GC_get_all_interior_pointers());
77 #else
78     assert(GC_all_interior_pointers);
79 #endif
80   }
81 #endif
82 }
83
84 /** @brief Allocate memory
85  * @param n Bytes to allocate
86  * @return Pointer to allocated memory
87  *
88  * Terminates the process on error.  The allocated memory is always
89  * 0-filled.
90  */
91 void *xmalloc(size_t n) {
92   void *ptr;
93
94   if(!(ptr = do_malloc(n)) && n)
95     disorder_fatal(errno, "error allocating memory");
96   return ptr;
97 }
98
99 /** @brief Reallocate memory
100  * @param ptr Block to reallocated
101  * @param n Bytes to allocate
102  * @return Pointer to allocated memory
103  *
104  * Terminates the process on error.  It is NOT guaranteed that any
105  * additional memory allocated is 0-filled.
106  */
107 void *xrealloc(void *ptr, size_t n) {
108   if(!(ptr = do_realloc(ptr, n)) && n)
109     disorder_fatal(errno, "error allocating memory");
110   return ptr;
111 }
112
113 /** @brief Allocate memory
114  * @param count Number of objects to allocate
115  * @param size Size of one object
116  * @return Pointer to allocated memory
117  *
118  * Terminates the process on error.  The allocated memory is always
119  * 0-filled.
120  */
121 void *xcalloc(size_t count, size_t size) {
122   if(count > SIZE_MAX / size)
123     disorder_fatal(0, "excessively large calloc");
124   return xmalloc(count * size);
125 }
126
127 /** @brief Allocate memory
128  * @param n Bytes to allocate
129  * @return Pointer to allocated memory
130  *
131  * Terminates the process on error.  The allocated memory is not
132  * guaranteed to be 0-filled and is not suitable for storing pointers
133  * in.
134  */
135 void *xmalloc_noptr(size_t n) {
136   void *ptr;
137
138   if(!(ptr = do_malloc_atomic(n)) && n)
139     disorder_fatal(errno, "error allocating memory");
140   return ptr;
141 }
142
143 /** @brief Allocate memory
144  * @param count Number of objects to allocate
145  * @param size Size of one object
146  * @return Pointer to allocated memory
147  *
148  * Terminates the process on error.  IMPORTANT: the allocated memory is NOT
149  * 0-filled (unlike @c calloc()).
150  */
151 void *xcalloc_noptr(size_t count, size_t size) {
152   if(count > SIZE_MAX / size)
153     disorder_fatal(0, "excessively large calloc");
154   return xmalloc_noptr(count * size);
155 }
156
157 /** @brief Reallocate memory
158  * @param ptr Block to reallocated
159  * @param n Bytes to allocate
160  * @return Pointer to allocated memory
161  *
162  * Terminates the processf on error.  It is NOT guaranteed that any
163  * additional memory allocated is 0-filled.  The block must have been
164  * allocated with xmalloc_noptr() (or xrealloc_noptr()) initially.
165  */
166 void *xrealloc_noptr(void *ptr, size_t n) {
167   if(ptr == 0)
168     return xmalloc_noptr(n);
169   if(!(ptr = do_realloc(ptr, n)) && n)
170     disorder_fatal(errno, "error allocating memory");
171   return ptr;
172 }
173
174 /** @brief Duplicate a string
175  * @param s String to copy
176  * @return New copy of string
177  *
178  * This uses the equivalent of xmalloc_noptr() to allocate the new string.
179  */
180 char *xstrdup(const char *s) {
181   char *t;
182
183   if(!(t = do_malloc_atomic(strlen(s) + 1)))
184     disorder_fatal(errno, "error allocating memory");
185   return strcpy(t, s);
186 }
187
188 /** @brief Duplicate a prefix of a string
189  * @param s String to copy
190  * @param n Prefix of string to copy
191  * @return New copy of string
192  *
193  * This uses the equivalent of xmalloc_noptr() to allocate the new string.
194  * @p n must not exceed the length of the string.
195  */
196 char *xstrndup(const char *s, size_t n) {
197   char *t;
198
199   if(!(t = do_malloc_atomic(n + 1)))
200     disorder_fatal(errno, "error allocating memory");
201   memcpy(t, s, n);
202   t[n] = 0;
203   return t;
204 }
205
206 /** @brief Free memory
207  * @param ptr Block to free or 0
208  */
209 void xfree(void *ptr) {
210   do_free(ptr);
211 }
212
213 /*
214 Local Variables:
215 c-basic-offset:2
216 comment-column:40
217 fill-column:79
218 indent-tabs-mode:nil
219 End:
220 */