Blame gnulib/lib/xalloc.h

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