raw
vtools_genesis          1 #ifndef XALLOC_H_
vtools_genesis 2 #define XALLOC_H_
vtools_genesis 3
vtools_genesis 4 #include <stddef.h>
vtools_genesis 5 #include <stdint.h>
vtools_genesis 6 #include "system.h"
vtools_genesis 7
vtools_genesis 8 /* This function is always triggered when memory is exhausted. It
vtools_genesis 9 must be defined by the application, either explicitly or by using
vtools_genesis 10 gnulib's xalloc-die module. This is the function to call when one
vtools_genesis 11 wants the program to die because of a memory allocation
vtools_genesis 12 failure. */
vdiff_fixes_newli... 13 extern void xalloc_die(void) __attribute__((noreturn));
vtools_genesis 14
vtools_genesis 15 void *xmalloc(size_t s);
vtools_genesis 16 void *xzalloc(size_t s);
vtools_genesis 17 void *xcalloc(size_t n, size_t s);
vtools_genesis 18 void *xrealloc(void *p, size_t s);
vtools_genesis 19 void *x2realloc(void *p, size_t *pn);
vtools_genesis 20 void *xmemdup(void const *p, size_t s);
vtools_genesis 21 char *xstrdup(char const *str);
vtools_genesis 22
vtools_genesis 23 /* In the following macros, |t| must be an elementary or
vtools_genesis 24 structure/union or typedef'ed type, or a pointer to such a type.
vtools_genesis 25 To apply one of the following macros to a function pointer or array
vtools_genesis 26 type, you need to typedef it first and use the typedef name. */
vtools_genesis 27
vtools_genesis 28 /* Allocate an object of type |t| dynamically, with error checking. */
vtools_genesis 29 #define XMALLOC(t) ((t *) xmalloc (sizeof (t)))
vtools_genesis 30
vtools_genesis 31 /* Allocate memory for |n| elements of type |t|, with error
vtools_genesis 32 checking. */
vtools_genesis 33 #define XNMALLOC(n, t) \
vtools_genesis 34 ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t))))
vtools_genesis 35
vtools_genesis 36 /* Allocate an object of type |t| dynamically, with error checking,
vtools_genesis 37 and zero it. */
vtools_genesis 38 #define XZALLOC(t) ((t *) xzalloc (sizeof (t)))
vtools_genesis 39
vtools_genesis 40 /* Allocate memory for |n| elements of type |t|, with error checking,
vtools_genesis 41 and zero it. */
vtools_genesis 42 #define XCALLOC(n, t) \
vtools_genesis 43 ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t))))
vtools_genesis 44
vtools_genesis 45
vtools_genesis 46 /* Allocate an array of |n| objects, each with |s| bytes of memory,
vtools_genesis 47 dynamically, with error checking. |s| must be nonzero. */
vtools_genesis 48
vtools_genesis 49 inline void *xnmalloc(size_t n, size_t s);
vtools_genesis 50
vtools_genesis 51 inline void *
vtools_genesis 52 xnmalloc(size_t n, size_t s) {
vtools_genesis 53 if (xalloc_oversized (n, s))
vtools_genesis 54 xalloc_die();
vtools_genesis 55 return xmalloc(n * s);
vtools_genesis 56 }
vtools_genesis 57
vtools_genesis 58 /* Change the size of an allocated block of memory |p| to an array of
vtools_genesis 59 |n| objects each of |s| bytes, with error checking. |s| must be
vtools_genesis 60 nonzero. */
vtools_genesis 61
vtools_genesis 62 inline void *xnrealloc(void *p, size_t n, size_t s);
vtools_genesis 63
vtools_genesis 64 inline void *
vtools_genesis 65 xnrealloc(void *p, size_t n, size_t s) {
vtools_genesis 66 if (xalloc_oversized (n, s))
vtools_genesis 67 xalloc_die();
vtools_genesis 68 return xrealloc(p, n * s);
vtools_genesis 69 }
vtools_genesis 70
vtools_genesis 71 /* If |p| is |NULL|, allocate a block of at least |*pn| such objects;
vtools_genesis 72 otherwise, reallocate |p| so that it contains more than |*pn|
vtools_genesis 73 objects each of |s| bytes. |s| must be nonzero. Set |*pn| to the
vtools_genesis 74 new number of objects, and return the pointer to the new block.
vtools_genesis 75 |*PN| is never set to zero, and the returned pointer is never |NULL|.
vtools_genesis 76
vtools_genesis 77 Repeated reallocations are guaranteed to make progress, either by
vtools_genesis 78 allocating an initial block with a nonzero size, or by allocating a
vtools_genesis 79 larger block.
vtools_genesis 80
vtools_genesis 81 In the following implementation, nonzero sizes are increased by a
vtools_genesis 82 factor of approximately 1.5 so that repeated reallocations have
vtools_genesis 83 $O(N)$ overall cost rather than $O(N^2)$ cost, but the
vtools_genesis 84 specification for this function does not guarantee that rate.
vtools_genesis 85
vtools_genesis 86 Here is an example of use:
vtools_genesis 87
vtools_genesis 88 |int *p = NULL;
vtools_genesis 89 size_t used = 0;
vtools_genesis 90 size_t allocated = 0;
vtools_genesis 91
vtools_genesis 92 void
vtools_genesis 93 append_int (int value)
vtools_genesis 94 {
vtools_genesis 95 if (used == allocated)
vtools_genesis 96 p = x2nrealloc (p, &allocated, sizeof *p);
vtools_genesis 97 p[used++] = value;
vtools_genesis 98 }|
vtools_genesis 99
vtools_genesis 100 This causes |x2nrealloc| to allocate a block of some nonzero size
vtools_genesis 101 the first time it is called.
vtools_genesis 102
vtools_genesis 103 To have finer-grained control over the initial size, set |*pn| to a
vtools_genesis 104 nonzero value before calling this function with |p == NULL|. For
vtools_genesis 105 example:
vtools_genesis 106
vtools_genesis 107 |int *p = NULL;
vtools_genesis 108 size_t used = 0;
vtools_genesis 109 size_t allocated = 0;
vtools_genesis 110 size_t allocated1 = 1000;
vtools_genesis 111
vtools_genesis 112 void
vtools_genesis 113 append_int (int value)
vtools_genesis 114 {
vtools_genesis 115 if (used == allocated)
vtools_genesis 116 {
vtools_genesis 117 p = x2nrealloc (p, &allocated1, sizeof *p);
vtools_genesis 118 allocated = allocated1;
vtools_genesis 119 }
vtools_genesis 120 p[used++] = value;
vtools_genesis 121 }|
vtools_genesis 122
vtools_genesis 123 */
vtools_genesis 124
vtools_genesis 125 static inline void *
vtools_genesis 126 x2nrealloc(void *p, size_t *pn, size_t s) {
vtools_genesis 127 size_t n = *pn;
vtools_genesis 128
vtools_genesis 129 if (!p) {
vtools_genesis 130 if (!n) {
vtools_genesis 131 /* The approximate size to use for initial small
vtools_genesis 132 allocation requests, when the invoking code specifies
vtools_genesis 133 an old size of zero. This is the largest "small"
vtools_genesis 134 request for the GNU C library malloc. */
vtools_genesis 135 enum {
vtools_genesis 136 DEFAULT_MXFAST = 64 * sizeof(size_t) / 4
vtools_genesis 137 };
vtools_genesis 138
vtools_genesis 139 n = DEFAULT_MXFAST / s;
vtools_genesis 140 n += !n;
vtools_genesis 141 }
vtools_genesis 142 if (xalloc_oversized (n, s))
vtools_genesis 143 xalloc_die();
vtools_genesis 144 } else {
vtools_genesis 145 /* Set $n = \lfloor 1.5 * n \rfloor + 1$ so that progress is
vtools_genesis 146 made even if $n = 0$. Check for overflow, so that $n * s$
vtools_genesis 147 stays in both |ptrdiff_t| and |size_t| range. The check
vtools_genesis 148 may be slightly conservative, but an exact check isn't
vtools_genesis 149 worth the trouble. */
vtools_genesis 150 if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s
vtools_genesis 151 <= n)
vtools_genesis 152 xalloc_die();
vtools_genesis 153 n += n / 2 + 1;
vtools_genesis 154 }
vtools_genesis 155
vtools_genesis 156 *pn = n;
vtools_genesis 157 return xrealloc(p, n * s);
vtools_genesis 158 }
vtools_genesis 159
vtools_genesis 160 /* Return a pointer to a new buffer of |n| bytes. This is like
vtools_genesis 161 xmalloc, except it returns |char *|. */
vtools_genesis 162
vtools_genesis 163 static inline char *xcharalloc(size_t n);
vtools_genesis 164
vtools_genesis 165 static inline char *
vtools_genesis 166 xcharalloc(size_t n) {
vtools_genesis 167 return XNMALLOC (n, char);
vtools_genesis 168 }
vtools_genesis 169
vtools_genesis 170 #endif