Blame lib/xalloc.h

Packit Service fdd496
/* xalloc.h -- malloc with out-of-memory checking
Packit Service fdd496
Packit Service fdd496
   Copyright (C) 1990-2000, 2003-2004, 2006-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
#ifndef XALLOC_H_
Packit Service fdd496
#define XALLOC_H_
Packit Service fdd496
Packit Service fdd496
#include <stddef.h>
Packit Service fdd496
#include <stdint.h>
Packit Service fdd496
Packit Service fdd496
#include "xalloc-oversized.h"
Packit Service fdd496
Packit Service fdd496
#ifndef _GL_INLINE_HEADER_BEGIN
Packit Service fdd496
 #error "Please include config.h first."
Packit Service fdd496
#endif
Packit Service fdd496
_GL_INLINE_HEADER_BEGIN
Packit Service fdd496
#ifndef XALLOC_INLINE
Packit Service fdd496
# define XALLOC_INLINE _GL_INLINE
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#ifdef __cplusplus
Packit Service fdd496
extern "C" {
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
#if __GNUC__ >= 3
Packit Service fdd496
# define _GL_ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
Packit Service fdd496
#else
Packit Service fdd496
# define _GL_ATTRIBUTE_MALLOC
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if ! defined __clang__ && \
Packit Service fdd496
    (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
Packit Service fdd496
# define _GL_ATTRIBUTE_ALLOC_SIZE(args) __attribute__ ((__alloc_size__ args))
Packit Service fdd496
#else
Packit Service fdd496
# define _GL_ATTRIBUTE_ALLOC_SIZE(args)
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* This function is always triggered when memory is exhausted.
Packit Service fdd496
   It must be defined by the application, either explicitly
Packit Service fdd496
   or by using gnulib's xalloc-die module.  This is the
Packit Service fdd496
   function to call when one wants the program to die because of a
Packit Service fdd496
   memory allocation failure.  */
Packit Service fdd496
extern _Noreturn void xalloc_die (void);
Packit Service fdd496
Packit Service fdd496
void *xmalloc (size_t s)
Packit Service fdd496
      _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
Packit Service fdd496
void *xzalloc (size_t s)
Packit Service fdd496
      _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
Packit Service fdd496
void *xcalloc (size_t n, size_t s)
Packit Service fdd496
      _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
Packit Service fdd496
void *xrealloc (void *p, size_t s)
Packit Service fdd496
      _GL_ATTRIBUTE_ALLOC_SIZE ((2));
Packit Service fdd496
void *x2realloc (void *p, size_t *pn);
Packit Service fdd496
void *xmemdup (void const *p, size_t s)
Packit Service fdd496
      _GL_ATTRIBUTE_ALLOC_SIZE ((2));
Packit Service fdd496
char *xstrdup (char const *str)
Packit Service fdd496
      _GL_ATTRIBUTE_MALLOC;
Packit Service fdd496
Packit Service fdd496
/* In the following macros, T must be an elementary or structure/union or
Packit Service fdd496
   typedef'ed type, or a pointer to such a type.  To apply one of the
Packit Service fdd496
   following macros to a function pointer or array type, you need to typedef
Packit Service fdd496
   it first and use the typedef name.  */
Packit Service fdd496
Packit Service fdd496
/* Allocate an object of type T dynamically, with error checking.  */
Packit Service fdd496
/* extern t *XMALLOC (typename t); */
Packit Service fdd496
#define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
Packit Service fdd496
Packit Service fdd496
/* Allocate memory for N elements of type T, with error checking.  */
Packit Service fdd496
/* extern t *XNMALLOC (size_t n, typename t); */
Packit Service fdd496
#define XNMALLOC(n, t) \
Packit Service fdd496
   ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
Packit Service fdd496
Packit Service fdd496
/* Allocate an object of type T dynamically, with error checking,
Packit Service fdd496
   and zero it.  */
Packit Service fdd496
/* extern t *XZALLOC (typename t); */
Packit Service fdd496
#define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
Packit Service fdd496
Packit Service fdd496
/* Allocate memory for N elements of type T, with error checking,
Packit Service fdd496
   and zero it.  */
Packit Service fdd496
/* extern t *XCALLOC (size_t n, typename t); */
Packit Service fdd496
#define XCALLOC(n, t) \
Packit Service fdd496
   ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
/* Allocate an array of N objects, each with S bytes of memory,
Packit Service fdd496
   dynamically, with error checking.  S must be nonzero.  */
Packit Service fdd496
Packit Service fdd496
XALLOC_INLINE void *xnmalloc (size_t n, size_t s)
Packit Service fdd496
                    _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1, 2));
Packit Service fdd496
XALLOC_INLINE void *
Packit Service fdd496
xnmalloc (size_t n, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  if (xalloc_oversized (n, s))
Packit Service fdd496
    xalloc_die ();
Packit Service fdd496
  return xmalloc (n * s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Change the size of an allocated block of memory P to an array of N
Packit Service fdd496
   objects each of S bytes, with error checking.  S must be nonzero.  */
Packit Service fdd496
Packit Service fdd496
XALLOC_INLINE void *xnrealloc (void *p, size_t n, size_t s)
Packit Service fdd496
                    _GL_ATTRIBUTE_ALLOC_SIZE ((2, 3));
Packit Service fdd496
XALLOC_INLINE void *
Packit Service fdd496
xnrealloc (void *p, size_t n, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  if (xalloc_oversized (n, s))
Packit Service fdd496
    xalloc_die ();
Packit Service fdd496
  return xrealloc (p, n * s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* If P is null, allocate a block of at least *PN such objects;
Packit Service fdd496
   otherwise, reallocate P so that it contains more than *PN objects
Packit Service fdd496
   each of S bytes.  S must be nonzero.  Set *PN to the new number of
Packit Service fdd496
   objects, and return the pointer to the new block.  *PN is never set
Packit Service fdd496
   to zero, and the returned pointer is never null.
Packit Service fdd496
Packit Service fdd496
   Repeated reallocations are guaranteed to make progress, either by
Packit Service fdd496
   allocating an initial block with a nonzero size, or by allocating a
Packit Service fdd496
   larger block.
Packit Service fdd496
Packit Service fdd496
   In the following implementation, nonzero sizes are increased by a
Packit Service fdd496
   factor of approximately 1.5 so that repeated reallocations have
Packit Service fdd496
   O(N) overall cost rather than O(N**2) cost, but the
Packit Service fdd496
   specification for this function does not guarantee that rate.
Packit Service fdd496
Packit Service fdd496
   Here is an example of use:
Packit Service fdd496
Packit Service fdd496
     int *p = NULL;
Packit Service fdd496
     size_t used = 0;
Packit Service fdd496
     size_t allocated = 0;
Packit Service fdd496
Packit Service fdd496
     void
Packit Service fdd496
     append_int (int value)
Packit Service fdd496
       {
Packit Service fdd496
         if (used == allocated)
Packit Service fdd496
           p = x2nrealloc (p, &allocated, sizeof *p);
Packit Service fdd496
         p[used++] = value;
Packit Service fdd496
       }
Packit Service fdd496
Packit Service fdd496
   This causes x2nrealloc to allocate a block of some nonzero size the
Packit Service fdd496
   first time it is called.
Packit Service fdd496
Packit Service fdd496
   To have finer-grained control over the initial size, set *PN to a
Packit Service fdd496
   nonzero value before calling this function with P == NULL.  For
Packit Service fdd496
   example:
Packit Service fdd496
Packit Service fdd496
     int *p = NULL;
Packit Service fdd496
     size_t used = 0;
Packit Service fdd496
     size_t allocated = 0;
Packit Service fdd496
     size_t allocated1 = 1000;
Packit Service fdd496
Packit Service fdd496
     void
Packit Service fdd496
     append_int (int value)
Packit Service fdd496
       {
Packit Service fdd496
         if (used == allocated)
Packit Service fdd496
           {
Packit Service fdd496
             p = x2nrealloc (p, &allocated1, sizeof *p);
Packit Service fdd496
             allocated = allocated1;
Packit Service fdd496
           }
Packit Service fdd496
         p[used++] = value;
Packit Service fdd496
       }
Packit Service fdd496
Packit Service fdd496
   */
Packit Service fdd496
Packit Service fdd496
XALLOC_INLINE void *
Packit Service fdd496
x2nrealloc (void *p, size_t *pn, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  size_t n = *pn;
Packit Service fdd496
Packit Service fdd496
  if (! p)
Packit Service fdd496
    {
Packit Service fdd496
      if (! n)
Packit Service fdd496
        {
Packit Service fdd496
          /* The approximate size to use for initial small allocation
Packit Service fdd496
             requests, when the invoking code specifies an old size of
Packit Service fdd496
             zero.  This is the largest "small" request for the GNU C
Packit Service fdd496
             library malloc.  */
Packit Service fdd496
          enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
Packit Service fdd496
Packit Service fdd496
          n = DEFAULT_MXFAST / s;
Packit Service fdd496
          n += !n;
Packit Service fdd496
        }
Packit Service fdd496
      if (xalloc_oversized (n, s))
Packit Service fdd496
        xalloc_die ();
Packit Service fdd496
    }
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      /* Set N = floor (1.5 * N) + 1 so that progress is made even if N == 0.
Packit Service fdd496
         Check for overflow, so that N * S stays in both ptrdiff_t and
Packit Service fdd496
         size_t range.  The check may be slightly conservative, but an
Packit Service fdd496
         exact check isn't worth the trouble.  */
Packit Service fdd496
      if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s
Packit Service fdd496
          <= n)
Packit Service fdd496
        xalloc_die ();
Packit Service fdd496
      n += n / 2 + 1;
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
  *pn = n;
Packit Service fdd496
  return xrealloc (p, n * s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* Return a pointer to a new buffer of N bytes.  This is like xmalloc,
Packit Service fdd496
   except it returns char *.  */
Packit Service fdd496
Packit Service fdd496
XALLOC_INLINE char *xcharalloc (size_t n)
Packit Service fdd496
                    _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_ALLOC_SIZE ((1));
Packit Service fdd496
XALLOC_INLINE char *
Packit Service fdd496
xcharalloc (size_t n)
Packit Service fdd496
{
Packit Service fdd496
  return XNMALLOC (n, char);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#ifdef __cplusplus
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
/* C++ does not allow conversions from void * to other pointer types
Packit Service fdd496
   without a cast.  Use templates to work around the problem when
Packit Service fdd496
   possible.  */
Packit Service fdd496
Packit Service fdd496
template <typename T> inline T *
Packit Service fdd496
xrealloc (T *p, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  return (T *) xrealloc ((void *) p, s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
template <typename T> inline T *
Packit Service fdd496
xnrealloc (T *p, size_t n, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  return (T *) xnrealloc ((void *) p, n, s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
template <typename T> inline T *
Packit Service fdd496
x2realloc (T *p, size_t *pn)
Packit Service fdd496
{
Packit Service fdd496
  return (T *) x2realloc ((void *) p, pn);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
template <typename T> inline T *
Packit Service fdd496
x2nrealloc (T *p, size_t *pn, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  return (T *) x2nrealloc ((void *) p, pn, s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
template <typename T> inline T *
Packit Service fdd496
xmemdup (T const *p, size_t s)
Packit Service fdd496
{
Packit Service fdd496
  return (T *) xmemdup ((void const *) p, s);
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
_GL_INLINE_HEADER_END
Packit Service fdd496
Packit Service fdd496
#endif /* !XALLOC_H_ */