xref: /dragonfly/contrib/grep/lib/xalloc.h (revision 09d4459f)
195b7b453SJohn Marino /* xalloc.h -- malloc with out-of-memory checking
295b7b453SJohn Marino 
3*09d4459fSDaniel Fojt    Copyright (C) 1990-2000, 2003-2004, 2006-2020 Free Software Foundation, Inc.
495b7b453SJohn Marino 
595b7b453SJohn Marino    This program is free software: you can redistribute it and/or modify
695b7b453SJohn Marino    it under the terms of the GNU General Public License as published by
795b7b453SJohn Marino    the Free Software Foundation; either version 3 of the License, or
895b7b453SJohn Marino    (at your option) any later version.
995b7b453SJohn Marino 
1095b7b453SJohn Marino    This program is distributed in the hope that it will be useful,
1195b7b453SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
1295b7b453SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1395b7b453SJohn Marino    GNU General Public License for more details.
1495b7b453SJohn Marino 
1595b7b453SJohn Marino    You should have received a copy of the GNU General Public License
16*09d4459fSDaniel Fojt    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
1795b7b453SJohn Marino 
1895b7b453SJohn Marino #ifndef XALLOC_H_
1995b7b453SJohn Marino #define XALLOC_H_
2095b7b453SJohn Marino 
2195b7b453SJohn Marino #include <stddef.h>
22*09d4459fSDaniel Fojt #include <stdint.h>
2395b7b453SJohn Marino 
24200fbe8dSJohn Marino #include "xalloc-oversized.h"
2595b7b453SJohn Marino 
26680a9cb8SJohn Marino #ifndef _GL_INLINE_HEADER_BEGIN
27680a9cb8SJohn Marino  #error "Please include config.h first."
28680a9cb8SJohn Marino #endif
29680a9cb8SJohn Marino _GL_INLINE_HEADER_BEGIN
30680a9cb8SJohn Marino #ifndef XALLOC_INLINE
31680a9cb8SJohn Marino # define XALLOC_INLINE _GL_INLINE
32680a9cb8SJohn Marino #endif
33680a9cb8SJohn Marino 
3495b7b453SJohn Marino #ifdef __cplusplus
3595b7b453SJohn Marino extern "C" {
3695b7b453SJohn Marino #endif
3795b7b453SJohn Marino 
3895b7b453SJohn Marino 
39dc7c36e4SJohn Marino #if ! defined __clang__ && \
40dc7c36e4SJohn Marino     (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
41200fbe8dSJohn Marino # define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
42200fbe8dSJohn Marino #else
43200fbe8dSJohn Marino # define _GL_ATTRIBUTE_ALLOC_SIZE(args)
4495b7b453SJohn Marino #endif
4595b7b453SJohn Marino 
4695b7b453SJohn Marino /* This function is always triggered when memory is exhausted.
4795b7b453SJohn Marino    It must be defined by the application, either explicitly
4895b7b453SJohn Marino    or by using gnulib's xalloc-die module.  This is the
4995b7b453SJohn Marino    function to call when one wants the program to die because of a
5095b7b453SJohn Marino    memory allocation failure.  */
51cf28ed85SJohn Marino extern _Noreturn void xalloc_die (void);
5295b7b453SJohn Marino 
53200fbe8dSJohn Marino void *xmalloc (size_t s)
54200fbe8dSJohn Marino       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
55200fbe8dSJohn Marino void *xzalloc (size_t s)
56200fbe8dSJohn Marino       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
57200fbe8dSJohn Marino void *xcalloc (size_t n, size_t s)
58200fbe8dSJohn Marino       _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
59200fbe8dSJohn Marino void *xrealloc (void *p, size_t s)
60200fbe8dSJohn Marino       _GL_ATTRIBUTE_ALLOC_SIZE ((2));
6195b7b453SJohn Marino void *x2realloc (void *p, size_t *pn);
62200fbe8dSJohn Marino void *xmemdup (void const *p, size_t s)
63680a9cb8SJohn Marino       _GL_ATTRIBUTE_ALLOC_SIZE ((2));
64200fbe8dSJohn Marino char *xstrdup (char const *str)
65200fbe8dSJohn Marino       _GL_ATTRIBUTE_MALLOC;
6695b7b453SJohn Marino 
6795b7b453SJohn Marino /* In the following macros, T must be an elementary or structure/union or
6895b7b453SJohn Marino    typedef'ed type, or a pointer to such a type.  To apply one of the
6995b7b453SJohn Marino    following macros to a function pointer or array type, you need to typedef
7095b7b453SJohn Marino    it first and use the typedef name.  */
7195b7b453SJohn Marino 
7295b7b453SJohn Marino /* Allocate an object of type T dynamically, with error checking.  */
7395b7b453SJohn Marino /* extern t *XMALLOC (typename t); */
7495b7b453SJohn Marino #define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
7595b7b453SJohn Marino 
7695b7b453SJohn Marino /* Allocate memory for N elements of type T, with error checking.  */
7795b7b453SJohn Marino /* extern t *XNMALLOC (size_t n, typename t); */
7895b7b453SJohn Marino #define XNMALLOC(n, t) \
7995b7b453SJohn Marino    ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
8095b7b453SJohn Marino 
8195b7b453SJohn Marino /* Allocate an object of type T dynamically, with error checking,
8295b7b453SJohn Marino    and zero it.  */
8395b7b453SJohn Marino /* extern t *XZALLOC (typename t); */
8495b7b453SJohn Marino #define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
8595b7b453SJohn Marino 
8695b7b453SJohn Marino /* Allocate memory for N elements of type T, with error checking,
8795b7b453SJohn Marino    and zero it.  */
8895b7b453SJohn Marino /* extern t *XCALLOC (size_t n, typename t); */
8995b7b453SJohn Marino #define XCALLOC(n, t) \
9095b7b453SJohn Marino    ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
9195b7b453SJohn Marino 
9295b7b453SJohn Marino 
9395b7b453SJohn Marino /* Allocate an array of N objects, each with S bytes of memory,
9495b7b453SJohn Marino    dynamically, with error checking.  S must be nonzero.  */
9595b7b453SJohn Marino 
96680a9cb8SJohn Marino XALLOC_INLINE void *xnmalloc (size_t n, size_t s)
97200fbe8dSJohn Marino                     _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
98680a9cb8SJohn Marino XALLOC_INLINE void *
xnmalloc(size_t n,size_t s)9995b7b453SJohn Marino xnmalloc (size_t n, size_t s)
10095b7b453SJohn Marino {
10195b7b453SJohn Marino   if (xalloc_oversized (n, s))
10295b7b453SJohn Marino     xalloc_die ();
10395b7b453SJohn Marino   return xmalloc (n * s);
10495b7b453SJohn Marino }
10595b7b453SJohn Marino 
10695b7b453SJohn Marino /* Change the size of an allocated block of memory P to an array of N
10795b7b453SJohn Marino    objects each of S bytes, with error checking.  S must be nonzero.  */
10895b7b453SJohn Marino 
109680a9cb8SJohn Marino XALLOC_INLINE void *xnrealloc (void *p, size_t n, size_t s)
110200fbe8dSJohn Marino                     _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
111680a9cb8SJohn Marino XALLOC_INLINE void *
xnrealloc(void * p,size_t n,size_t s)11295b7b453SJohn Marino xnrealloc (void *p, size_t n, size_t s)
11395b7b453SJohn Marino {
11495b7b453SJohn Marino   if (xalloc_oversized (n, s))
11595b7b453SJohn Marino     xalloc_die ();
11695b7b453SJohn Marino   return xrealloc (p, n * s);
11795b7b453SJohn Marino }
11895b7b453SJohn Marino 
11995b7b453SJohn Marino /* If P is null, allocate a block of at least *PN such objects;
12095b7b453SJohn Marino    otherwise, reallocate P so that it contains more than *PN objects
121680a9cb8SJohn Marino    each of S bytes.  S must be nonzero.  Set *PN to the new number of
122680a9cb8SJohn Marino    objects, and return the pointer to the new block.  *PN is never set
123680a9cb8SJohn Marino    to zero, and the returned pointer is never null.
12495b7b453SJohn Marino 
12595b7b453SJohn Marino    Repeated reallocations are guaranteed to make progress, either by
12695b7b453SJohn Marino    allocating an initial block with a nonzero size, or by allocating a
12795b7b453SJohn Marino    larger block.
12895b7b453SJohn Marino 
12995b7b453SJohn Marino    In the following implementation, nonzero sizes are increased by a
13095b7b453SJohn Marino    factor of approximately 1.5 so that repeated reallocations have
13195b7b453SJohn Marino    O(N) overall cost rather than O(N**2) cost, but the
13295b7b453SJohn Marino    specification for this function does not guarantee that rate.
13395b7b453SJohn Marino 
13495b7b453SJohn Marino    Here is an example of use:
13595b7b453SJohn Marino 
13695b7b453SJohn Marino      int *p = NULL;
13795b7b453SJohn Marino      size_t used = 0;
13895b7b453SJohn Marino      size_t allocated = 0;
13995b7b453SJohn Marino 
14095b7b453SJohn Marino      void
14195b7b453SJohn Marino      append_int (int value)
14295b7b453SJohn Marino        {
14395b7b453SJohn Marino          if (used == allocated)
14495b7b453SJohn Marino            p = x2nrealloc (p, &allocated, sizeof *p);
14595b7b453SJohn Marino          p[used++] = value;
14695b7b453SJohn Marino        }
14795b7b453SJohn Marino 
14895b7b453SJohn Marino    This causes x2nrealloc to allocate a block of some nonzero size the
14995b7b453SJohn Marino    first time it is called.
15095b7b453SJohn Marino 
15195b7b453SJohn Marino    To have finer-grained control over the initial size, set *PN to a
15295b7b453SJohn Marino    nonzero value before calling this function with P == NULL.  For
15395b7b453SJohn Marino    example:
15495b7b453SJohn Marino 
15595b7b453SJohn Marino      int *p = NULL;
15695b7b453SJohn Marino      size_t used = 0;
15795b7b453SJohn Marino      size_t allocated = 0;
15895b7b453SJohn Marino      size_t allocated1 = 1000;
15995b7b453SJohn Marino 
16095b7b453SJohn Marino      void
16195b7b453SJohn Marino      append_int (int value)
16295b7b453SJohn Marino        {
16395b7b453SJohn Marino          if (used == allocated)
16495b7b453SJohn Marino            {
16595b7b453SJohn Marino              p = x2nrealloc (p, &allocated1, sizeof *p);
16695b7b453SJohn Marino              allocated = allocated1;
16795b7b453SJohn Marino            }
16895b7b453SJohn Marino          p[used++] = value;
16995b7b453SJohn Marino        }
17095b7b453SJohn Marino 
17195b7b453SJohn Marino    */
17295b7b453SJohn Marino 
173680a9cb8SJohn Marino XALLOC_INLINE void *
x2nrealloc(void * p,size_t * pn,size_t s)17495b7b453SJohn Marino x2nrealloc (void *p, size_t *pn, size_t s)
17595b7b453SJohn Marino {
17695b7b453SJohn Marino   size_t n = *pn;
17795b7b453SJohn Marino 
17895b7b453SJohn Marino   if (! p)
17995b7b453SJohn Marino     {
18095b7b453SJohn Marino       if (! n)
18195b7b453SJohn Marino         {
18295b7b453SJohn Marino           /* The approximate size to use for initial small allocation
18395b7b453SJohn Marino              requests, when the invoking code specifies an old size of
184cf28ed85SJohn Marino              zero.  This is the largest "small" request for the GNU C
185cf28ed85SJohn Marino              library malloc.  */
186cf28ed85SJohn Marino           enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
18795b7b453SJohn Marino 
18895b7b453SJohn Marino           n = DEFAULT_MXFAST / s;
18995b7b453SJohn Marino           n += !n;
19095b7b453SJohn Marino         }
191*09d4459fSDaniel Fojt       if (xalloc_oversized (n, s))
192*09d4459fSDaniel Fojt         xalloc_die ();
19395b7b453SJohn Marino     }
19495b7b453SJohn Marino   else
19595b7b453SJohn Marino     {
196680a9cb8SJohn Marino       /* Set N = floor (1.5 * N) + 1 so that progress is made even if N == 0.
197*09d4459fSDaniel Fojt          Check for overflow, so that N * S stays in both ptrdiff_t and
198*09d4459fSDaniel Fojt          size_t range.  The check may be slightly conservative, but an
199*09d4459fSDaniel Fojt          exact check isn't worth the trouble.  */
200*09d4459fSDaniel Fojt       if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s
201*09d4459fSDaniel Fojt           <= n)
20295b7b453SJohn Marino         xalloc_die ();
203680a9cb8SJohn Marino       n += n / 2 + 1;
20495b7b453SJohn Marino     }
20595b7b453SJohn Marino 
20695b7b453SJohn Marino   *pn = n;
20795b7b453SJohn Marino   return xrealloc (p, n * s);
20895b7b453SJohn Marino }
20995b7b453SJohn Marino 
21095b7b453SJohn Marino /* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
21195b7b453SJohn Marino    except it returns char *.  */
21295b7b453SJohn Marino 
213680a9cb8SJohn Marino XALLOC_INLINE char *xcharalloc (size_t n)
214200fbe8dSJohn Marino                     _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
215680a9cb8SJohn Marino XALLOC_INLINE char *
xcharalloc(size_t n)21695b7b453SJohn Marino xcharalloc (size_t n)
21795b7b453SJohn Marino {
21895b7b453SJohn Marino   return XNMALLOC (n, char);
21995b7b453SJohn Marino }
22095b7b453SJohn Marino 
22195b7b453SJohn Marino #ifdef __cplusplus
22295b7b453SJohn Marino }
22395b7b453SJohn Marino 
22495b7b453SJohn Marino /* C++ does not allow conversions from void * to other pointer types
22595b7b453SJohn Marino    without a cast.  Use templates to work around the problem when
22695b7b453SJohn Marino    possible.  */
22795b7b453SJohn Marino 
22895b7b453SJohn Marino template <typename T> inline T *
xrealloc(T * p,size_t s)22995b7b453SJohn Marino xrealloc (T *p, size_t s)
23095b7b453SJohn Marino {
23195b7b453SJohn Marino   return (T *) xrealloc ((void *) p, s);
23295b7b453SJohn Marino }
23395b7b453SJohn Marino 
23495b7b453SJohn Marino template <typename T> inline T *
xnrealloc(T * p,size_t n,size_t s)23595b7b453SJohn Marino xnrealloc (T *p, size_t n, size_t s)
23695b7b453SJohn Marino {
23795b7b453SJohn Marino   return (T *) xnrealloc ((void *) p, n, s);
23895b7b453SJohn Marino }
23995b7b453SJohn Marino 
24095b7b453SJohn Marino template <typename T> inline T *
x2realloc(T * p,size_t * pn)24195b7b453SJohn Marino x2realloc (T *p, size_t *pn)
24295b7b453SJohn Marino {
24395b7b453SJohn Marino   return (T *) x2realloc ((void *) p, pn);
24495b7b453SJohn Marino }
24595b7b453SJohn Marino 
24695b7b453SJohn Marino template <typename T> inline T *
x2nrealloc(T * p,size_t * pn,size_t s)24795b7b453SJohn Marino x2nrealloc (T *p, size_t *pn, size_t s)
24895b7b453SJohn Marino {
24995b7b453SJohn Marino   return (T *) x2nrealloc ((void *) p, pn, s);
25095b7b453SJohn Marino }
25195b7b453SJohn Marino 
25295b7b453SJohn Marino template <typename T> inline T *
xmemdup(T const * p,size_t s)25395b7b453SJohn Marino xmemdup (T const *p, size_t s)
25495b7b453SJohn Marino {
25595b7b453SJohn Marino   return (T *) xmemdup ((void const *) p, s);
25695b7b453SJohn Marino }
25795b7b453SJohn Marino 
25895b7b453SJohn Marino #endif
25995b7b453SJohn Marino 
260dc7c36e4SJohn Marino _GL_INLINE_HEADER_END
26195b7b453SJohn Marino 
26295b7b453SJohn Marino #endif /* !XALLOC_H_ */
263