chiark / gitweb /
more efficient utf32_iterator_set()
[disorder] / lib / mem.c
1 /*
2  * This file is part of DisOrder.
3  * Copyright (C) 2004, 2005, 2006, 2007 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 2 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, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * 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, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20 /** @file lib/mem.c
21  * @brief Memory management
22  */
23
24 #include <config.h>
25 #include "types.h"
26
27 #if GC
28 #include <gc.h>
29 #endif
30 #include <errno.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35
36 #include "mem.h"
37 #include "log.h"
38 #include "printf.h"
39
40 #include "disorder.h"
41
42 /** @brief Allocate and zero out
43  * @param n Number of bytes to allocate
44  * @return Pointer to allocated memory,  or 0
45  */
46 static void *malloc_and_zero(size_t n) {
47   void *ptr = malloc(n);
48
49   if(ptr) memset(ptr, 0, n);
50   return ptr;
51 }
52
53 #if GC
54 static void *(*do_malloc)(size_t) = GC_malloc;
55 static void *(*do_realloc)(void *, size_t) = GC_realloc;
56 static void *(*do_malloc_atomic)(size_t) = GC_malloc_atomic;
57 static void (*do_free)(void *) = GC_free;
58 #else
59 static void *(*do_malloc)(size_t) = malloc_and_zero;
60 static void *(*do_realloc)(void *, size_t) = realloc;
61 static void *(*do_malloc_atomic)(size_t) = malloc;
62 static void (*do_free)(void *) = free;
63 #endif
64
65 /** @brief Initialize memory management
66  *
67  * Must be called by all programs that use garbage collection.  Define
68  * @c ${DISORDER_GC} to @c no to suppress use of the collector
69  * (e.g. for debugging purposes).
70  */
71 void mem_init(void) {
72 #if GC
73   const char *e;
74   
75   if(((e = getenv("DISORDER_GC")) && !strcmp(e, "no"))) {
76     do_malloc = malloc_and_zero;
77     do_malloc_atomic = malloc;
78     do_realloc = realloc;
79     do_free = free;
80   } else {
81     GC_init();
82     assert(GC_all_interior_pointers);
83   }
84 #endif
85 }
86
87 /** @brief Allocate memory
88  * @param n Bytes to allocate
89  * @return Pointer to allocated memory
90  *
91  * Terminates the process on error.  The allocated memory is always
92  * 0-filled.
93  */
94 void *xmalloc(size_t n) {
95   void *ptr;
96
97   if(!(ptr = do_malloc(n)) && n)
98     fatal(errno, "error allocating memory");
99   return ptr;
100 }
101
102 /** @brief Reallocate memory
103  * @param ptr Block to reallocated
104  * @param n Bytes to allocate
105  * @return Pointer to allocated memory
106  *
107  * Terminates the process on error.  It is NOT guaranteed that any
108  * additional memory allocated is 0-filled.
109  */
110 void *xrealloc(void *ptr, size_t n) {
111   if(!(ptr = do_realloc(ptr, n)) && n)
112     fatal(errno, "error allocating memory");
113   return ptr;
114 }
115
116 /** @brief Allocate memory
117  * @param count Number of objects to allocate
118  * @param size Size of one object
119  * @return Pointer to allocated memory
120  *
121  * Terminates the process on error.  The allocated memory is always
122  * 0-filled.
123  */
124 void *xcalloc(size_t count, size_t size) {
125   if(count > SIZE_MAX / size)
126     fatal(0, "excessively large calloc");
127   return xmalloc(count * size);
128 }
129
130 /** @brief Allocate memory
131  * @param n Bytes to allocate
132  * @return Pointer to allocated memory
133  *
134  * Terminates the process on error.  The allocated memory is not
135  * guaranteed to be 0-filled and is not suitable for storing pointers
136  * in.
137  */
138 void *xmalloc_noptr(size_t n) {
139   void *ptr;
140
141   if(!(ptr = do_malloc_atomic(n)) && n)
142     fatal(errno, "error allocating memory");
143   return ptr;
144 }
145
146 /** @brief Reallocate memory
147  * @param ptr Block to reallocated
148  * @param n Bytes to allocate
149  * @return Pointer to allocated memory
150  *
151  * Terminates the processf on error.  It is NOT guaranteed that any
152  * additional memory allocated is 0-filled.  The block must have been
153  * allocated with xmalloc_noptr() (or xrealloc_noptr()) initially.
154  */
155 void *xrealloc_noptr(void *ptr, size_t n) {
156   if(ptr == 0)
157     return xmalloc_noptr(n);
158   if(!(ptr = do_realloc(ptr, n)) && n)
159     fatal(errno, "error allocating memory");
160   return ptr;
161 }
162
163 /** @brief Duplicate a string
164  * @param s String to copy
165  * @return New copy of string
166  *
167  * This uses the equivalent of xmalloc_noptr() to allocate the new string.
168  */
169 char *xstrdup(const char *s) {
170   char *t;
171
172   if(!(t = do_malloc_atomic(strlen(s) + 1)))
173     fatal(errno, "error allocating memory");
174   return strcpy(t, s);
175 }
176
177 /** @brief Duplicate a prefix of a string
178  * @param s String to copy
179  * @param n Prefix of string to copy
180  * @return New copy of string
181  *
182  * This uses the equivalent of xmalloc_noptr() to allocate the new string.
183  * @p n must not exceed the length of the string.
184  */
185 char *xstrndup(const char *s, size_t n) {
186   char *t;
187
188   if(!(t = do_malloc_atomic(n + 1)))
189     fatal(errno, "error allocating memory");
190   memcpy(t, s, n);
191   t[n] = 0;
192   return t;
193 }
194
195 /** @brief Free memory
196  * @param ptr Block to free or 0
197  */
198 void xfree(void *ptr) {
199   do_free(ptr);
200 }
201
202 /*
203 Local Variables:
204 c-basic-offset:2
205 comment-column:40
206 End:
207 */