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