Blame src/gl/xalloc.h

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