Add x2realloc, x2nrealloc. Port to C99 inline.
[gnulib.git] / lib / xmalloc.c
1 /* xmalloc.c -- malloc with out of memory checking
2
3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2003,
4    1999, 2000, 2002, 2003 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19
20 #if HAVE_CONFIG_H
21 # include <config.h>
22 #endif
23
24 #include "xalloc.h"
25
26 #include <stdbool.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "gettext.h"
31 #define _(msgid) gettext (msgid)
32 #define N_(msgid) msgid
33
34 #include "error.h"
35 #include "exitfail.h"
36
37 #ifndef SIZE_MAX
38 # define SIZE_MAX ((size_t) -1)
39 #endif
40
41 #ifndef HAVE_MALLOC
42 "you must run the autoconf test for a GNU libc compatible malloc"
43 #endif
44
45 #ifndef HAVE_REALLOC
46 "you must run the autoconf test for a GNU libc compatible realloc"
47 #endif
48
49 /* If non NULL, call this function when memory is exhausted. */
50 void (*xalloc_fail_func) (void) = 0;
51
52 /* Return true if array of N objects, each of size S, cannot exist due
53    to arithmetic overflow.  S must be nonzero.  */
54
55 static inline bool
56 array_size_overflow (size_t n, size_t s)
57 {
58   return SIZE_MAX / s < n;
59 }
60
61 /* If XALLOC_FAIL_FUNC is NULL, or does return, display this message
62    before exiting when memory is exhausted.  Goes through gettext. */
63 char const xalloc_msg_memory_exhausted[] = N_("memory exhausted");
64
65 void
66 xalloc_die (void)
67 {
68   if (xalloc_fail_func)
69     (*xalloc_fail_func) ();
70   error (exit_failure, 0, "%s", _(xalloc_msg_memory_exhausted));
71   /* The `noreturn' cannot be given to error, since it may return if
72      its first argument is 0.  To help compilers understand the
73      xalloc_die does terminate, call abort.  */
74   abort ();
75 }
76
77 /* Allocate an array of N objects, each with S bytes of memory,
78    dynamically, with error checking.  S must be nonzero.  */
79
80 static inline void *
81 xnmalloc_inline (size_t n, size_t s)
82 {
83   void *p;
84   if (array_size_overflow (n, s) || ! (p = malloc (n * s)))
85     xalloc_die ();
86   return p;
87 }
88
89 void *
90 xnmalloc (size_t n, size_t s)
91 {
92   return xnmalloc_inline (n, s);
93 }
94
95 /* Allocate N bytes of memory dynamically, with error checking.  */
96
97 void *
98 xmalloc (size_t n)
99 {
100   return xnmalloc_inline (n, 1);
101 }
102
103 /* Change the size of an allocated block of memory P to an array of N
104    objects each of S bytes, with error checking.  S must be nonzero.  */
105
106 static inline void *
107 xnrealloc_inline (void *p, size_t n, size_t s)
108 {
109   if (array_size_overflow (n, s) || ! (p = realloc (p, n * s)))
110     xalloc_die ();
111   return p;
112 }
113
114 void *
115 xnrealloc (void *p, size_t n, size_t s)
116 {
117   return xnrealloc_inline (p, n, s);
118 }
119
120 /* Change the size of an allocated block of memory P to N bytes,
121    with error checking.  */
122
123 void *
124 xrealloc (void *p, size_t n)
125 {
126   return xnrealloc_inline (p, n, 1);
127 }
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 doubled so that
142    repeated reallocations have O(N log N) overall cost rather than
143    O(N**2) cost, but the specification for this function does not
144    guarantee that sizes are doubled.
145
146    Here is an example of use:
147
148      int *p = NULL;
149      size used = 0;
150      size 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 used = 0;
169      size allocated = 0;
170      size 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_inline (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       if (SIZE_MAX / 2 / s < n)
207         xalloc_die ();
208       n *= 2;
209     }
210
211   *pn = n;
212   return xrealloc (p, n * s);
213 }
214
215 void *
216 x2nrealloc (void *p, size_t *pn, size_t s)
217 {
218   return x2nrealloc_inline (p, pn, s);
219 }
220
221 /* If P is null, allocate a block of at least *PN bytes; otherwise,
222    reallocate P so that it contains more than *PN bytes.  *PN must be
223    nonzero unless P is null.  Set *PN to the new block's size, and
224    return the pointer to the new block.  *PN is never set to zero, and
225    the returned pointer is never null.  */
226
227 void *
228 x2realloc (void *p, size_t *pn)
229 {
230   return x2nrealloc_inline (p, pn, 1);
231 }
232
233 /* Allocate S bytes of zeroed memory dynamically, with error checking.
234    There's no need for xnzalloc (N, S), since it would be equivalent
235    to xcalloc (N, S).  */
236
237 void *
238 xzalloc (size_t s)
239 {
240   return memset (xmalloc (s), 0, s);
241 }
242
243 /* Allocate zeroed memory for N elements of S bytes, with error
244    checking.  S must be nonzero.  */
245
246 void *
247 xcalloc (size_t n, size_t s)
248 {
249   void *p;
250   /* Test for overflow, since some calloc implementations don't have
251      proper overflow checks.  */
252   if (array_size_overflow (n, s) || ! (p = calloc (n, s)))
253     xalloc_die ();
254   return p;
255 }
256
257 /* Clone an object P of size S, with error checking.  There's no need
258    for xnclone (P, N, S), since xclone (P, N * S) works without any
259    need for an arithmetic overflow check.  */
260
261 void *
262 xclone (void const *p, size_t s)
263 {
264   return memcpy (xmalloc (s), p, s);
265 }