Blame gnulib/lib/xalloc.h

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