xalloc: use stdnoreturn.h
[pspp] / lib / xalloc.h
1 /* xalloc.h -- malloc with out-of-memory checking
2
3    Copyright (C) 1990-2000, 2003-2004, 2006-2011 Free Software Foundation, Inc.
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 #ifndef XALLOC_H_
19 # define XALLOC_H_
20
21 # include <stddef.h>
22 # include <stdnoreturn.h>
23
24 # include "xalloc-oversized.h"
25
26 # ifdef __cplusplus
27 extern "C" {
28 # endif
29
30
31 # if __GNUC__ >= 3
32 #  define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
33 # else
34 #  define _GL_ATTRIBUTE_MALLOC
35 # endif
36
37 # if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
38 #  define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
39 # else
40 #  define _GL_ATTRIBUTE_ALLOC_SIZE(args)
41 # endif
42
43 /* This function is always triggered when memory is exhausted.
44    It must be defined by the application, either explicitly
45    or by using gnulib's xalloc-die module.  This is the
46    function to call when one wants the program to die because of a
47    memory allocation failure.  */
48 extern noreturn void xalloc_die (void);
49
50 void *xmalloc (size_t s)
51       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
52 void *xzalloc (size_t s)
53       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
54 void *xcalloc (size_t n, size_t s)
55       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
56 void *xrealloc (void *p, size_t s)
57       _GL_ATTRIBUTE_ALLOC_SIZE ((2));
58 void *x2realloc (void *p, size_t *pn);
59 void *xmemdup (void const *p, size_t s)
60       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((2));
61 char *xstrdup (char const *str)
62       _GL_ATTRIBUTE_MALLOC;
63
64 /* In the following macros, T must be an elementary or structure/union or
65    typedef'ed type, or a pointer to such a type.  To apply one of the
66    following macros to a function pointer or array type, you need to typedef
67    it first and use the typedef name.  */
68
69 /* Allocate an object of type T dynamically, with error checking.  */
70 /* extern t *XMALLOC (typename t); */
71 # define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
72
73 /* Allocate memory for N elements of type T, with error checking.  */
74 /* extern t *XNMALLOC (size_t n, typename t); */
75 # define XNMALLOC(n, t) \
76     ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
77
78 /* Allocate an object of type T dynamically, with error checking,
79    and zero it.  */
80 /* extern t *XZALLOC (typename t); */
81 # define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
82
83 /* Allocate memory for N elements of type T, with error checking,
84    and zero it.  */
85 /* extern t *XCALLOC (size_t n, typename t); */
86 # define XCALLOC(n, t) \
87     ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
88
89
90 # if HAVE_INLINE
91 #  define static_inline static inline
92 # else
93 void *xnmalloc (size_t n, size_t s)
94       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
95 void *xnrealloc (void *p, size_t n, size_t s)
96       _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
97 void *x2nrealloc (void *p, size_t *pn, size_t s);
98 char *xcharalloc (size_t n)
99       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
100 # endif
101
102 # ifdef static_inline
103
104 /* Allocate an array of N objects, each with S bytes of memory,
105    dynamically, with error checking.  S must be nonzero.  */
106
107 static_inline void *xnmalloc (size_t n, size_t s)
108                     _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
109 static_inline void *
110 xnmalloc (size_t n, size_t s)
111 {
112   if (xalloc_oversized (n, s))
113     xalloc_die ();
114   return xmalloc (n * s);
115 }
116
117 /* Change the size of an allocated block of memory P to an array of N
118    objects each of S bytes, with error checking.  S must be nonzero.  */
119
120 static_inline void *xnrealloc (void *p, size_t n, size_t s)
121                     _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
122 static_inline void *
123 xnrealloc (void *p, size_t n, size_t s)
124 {
125   if (xalloc_oversized (n, s))
126     xalloc_die ();
127   return xrealloc (p, n * s);
128 }
129
130 /* If P is null, allocate a block of at least *PN such objects;
131    otherwise, reallocate P so that it contains more than *PN objects
132    each of S bytes.  *PN must be nonzero unless P is null, and S must
133    be nonzero.  Set *PN to the new number of objects, and return the
134    pointer to the new block.  *PN is never set to zero, and the
135    returned pointer is never null.
136
137    Repeated reallocations are guaranteed to make progress, either by
138    allocating an initial block with a nonzero size, or by allocating a
139    larger block.
140
141    In the following implementation, nonzero sizes are increased by a
142    factor of approximately 1.5 so that repeated reallocations have
143    O(N) overall cost rather than O(N**2) cost, but the
144    specification for this function does not guarantee that rate.
145
146    Here is an example of use:
147
148      int *p = NULL;
149      size_t used = 0;
150      size_t allocated = 0;
151
152      void
153      append_int (int value)
154        {
155          if (used == allocated)
156            p = x2nrealloc (p, &allocated, sizeof *p);
157          p[used++] = value;
158        }
159
160    This causes x2nrealloc to allocate a block of some nonzero size the
161    first time it is called.
162
163    To have finer-grained control over the initial size, set *PN to a
164    nonzero value before calling this function with P == NULL.  For
165    example:
166
167      int *p = NULL;
168      size_t used = 0;
169      size_t allocated = 0;
170      size_t allocated1 = 1000;
171
172      void
173      append_int (int value)
174        {
175          if (used == allocated)
176            {
177              p = x2nrealloc (p, &allocated1, sizeof *p);
178              allocated = allocated1;
179            }
180          p[used++] = value;
181        }
182
183    */
184
185 static_inline void *
186 x2nrealloc (void *p, size_t *pn, size_t s)
187 {
188   size_t n = *pn;
189
190   if (! p)
191     {
192       if (! n)
193         {
194           /* The approximate size to use for initial small allocation
195              requests, when the invoking code specifies an old size of
196              zero.  64 bytes is the largest "small" request for the
197              GNU C library malloc.  */
198           enum { DEFAULT_MXFAST = 64 };
199
200           n = DEFAULT_MXFAST / s;
201           n += !n;
202         }
203     }
204   else
205     {
206       /* Set N = ceil (1.5 * N) so that progress is made if N == 1.
207          Check for overflow, so that N * S stays in size_t range.
208          The check is slightly conservative, but an exact check isn't
209          worth the trouble.  */
210       if ((size_t) -1 / 3 * 2 / s <= n)
211         xalloc_die ();
212       n += (n + 1) / 2;
213     }
214
215   *pn = n;
216   return xrealloc (p, n * s);
217 }
218
219 /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
220    except it returns char *.  */
221
222 static_inline char *xcharalloc (size_t n)
223                     _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
224 static_inline char *
225 xcharalloc (size_t n)
226 {
227   return XNMALLOC (n, char);
228 }
229
230 # endif
231
232 # ifdef __cplusplus
233 }
234
235 /* C++ does not allow conversions from void * to other pointer types
236    without a cast.  Use templates to work around the problem when
237    possible.  */
238
239 template <typename T> inline T *
240 xrealloc (T *p, size_t s)
241 {
242   return (T *) xrealloc ((void *) p, s);
243 }
244
245 template <typename T> inline T *
246 xnrealloc (T *p, size_t n, size_t s)
247 {
248   return (T *) xnrealloc ((void *) p, n, s);
249 }
250
251 template <typename T> inline T *
252 x2realloc (T *p, size_t *pn)
253 {
254   return (T *) x2realloc ((void *) p, pn);
255 }
256
257 template <typename T> inline T *
258 x2nrealloc (T *p, size_t *pn, size_t s)
259 {
260   return (T *) x2nrealloc ((void *) p, pn, s);
261 }
262
263 template <typename T> inline T *
264 xmemdup (T const *p, size_t s)
265 {
266   return (T *) xmemdup ((void const *) p, s);
267 }
268
269 # endif
270
271
272 #endif /* !XALLOC_H_ */