summaryrefslogtreecommitdiff
path: root/gnulib-local
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-08-12 03:31:49 +0200
committerBruno Haible <bruno@clisp.org>2019-08-12 03:31:49 +0200
commit8e280e2efdcb9fa9a5e93edb89354496a55f228a (patch)
tree43e375bf40eee522f7038c7cea3849ab229652e5 /gnulib-local
parent9a4495f84f0291f66fb230ab7afa1ee7d47e89e0 (diff)
downloadgettext-8e280e2efdcb9fa9a5e93edb89354496a55f228a.tar.gz
xalloc: Add x2realloc function, from gnulib.
* gnulib-local/lib/xalloc.h (x2realloc): New declaration, from gnulib/lib/xalloc.h. * gnulib-local/lib/xmalloc.c (x2nrealloc): New function, from gnulib/lib/xalloc.h. (x2realloc): New function, from gnulib/lib/xmalloc.c. * gnulib-local/modules/xalloc (configure.ac): Require AC_C_INLINE.
Diffstat (limited to 'gnulib-local')
-rw-r--r--gnulib-local/lib/xalloc.h16
-rw-r--r--gnulib-local/lib/xmalloc.c103
-rw-r--r--gnulib-local/modules/xalloc1
3 files changed, 120 insertions, 0 deletions
diff --git a/gnulib-local/lib/xalloc.h b/gnulib-local/lib/xalloc.h
index e4fb28866..b512cc8eb 100644
--- a/gnulib-local/lib/xalloc.h
+++ b/gnulib-local/lib/xalloc.h
@@ -58,6 +58,22 @@ template <typename T>
extern "C" {
#endif
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+ reallocate P so that it contains more than *PN bytes. *PN must be
+ nonzero unless P is null. Set *PN to the new block's size, and
+ return the pointer to the new block. *PN is never set to zero, and
+ the returned pointer is never null. */
+extern void *x2realloc (void *ptr, size_t *pn);
+#ifdef __cplusplus
+}
+template <typename T>
+ inline T * x2realloc (T * ptr, size_t *pn)
+ {
+ return (T *) x2realloc ((void *) ptr, pn);
+ }
+extern "C" {
+#endif
+
/* This function is always triggered when memory is exhausted. It is
in charge of honoring the three previous items. This is the
function to call when one wants the program to die because of a
diff --git a/gnulib-local/lib/xmalloc.c b/gnulib-local/lib/xmalloc.c
index 869cc1804..a1456c520 100644
--- a/gnulib-local/lib/xmalloc.c
+++ b/gnulib-local/lib/xmalloc.c
@@ -127,3 +127,106 @@ xrealloc (void *p, size_t n)
p = fixup_null_alloc (n);
return p;
}
+
+/* If P is null, allocate a block of at least *PN such objects;
+ otherwise, reallocate P so that it contains more than *PN objects
+ each of S bytes. S must be nonzero. Set *PN to the new number of
+ objects, and return the pointer to the new block. *PN is never set
+ to zero, and the returned pointer is never null.
+
+ Repeated reallocations are guaranteed to make progress, either by
+ allocating an initial block with a nonzero size, or by allocating a
+ larger block.
+
+ In the following implementation, nonzero sizes are increased by a
+ factor of approximately 1.5 so that repeated reallocations have
+ O(N) overall cost rather than O(N**2) cost, but the
+ specification for this function does not guarantee that rate.
+
+ Here is an example of use:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ p = x2nrealloc (p, &allocated, sizeof *p);
+ p[used++] = value;
+ }
+
+ This causes x2nrealloc to allocate a block of some nonzero size the
+ first time it is called.
+
+ To have finer-grained control over the initial size, set *PN to a
+ nonzero value before calling this function with P == NULL. For
+ example:
+
+ int *p = NULL;
+ size_t used = 0;
+ size_t allocated = 0;
+ size_t allocated1 = 1000;
+
+ void
+ append_int (int value)
+ {
+ if (used == allocated)
+ {
+ p = x2nrealloc (p, &allocated1, sizeof *p);
+ allocated = allocated1;
+ }
+ p[used++] = value;
+ }
+
+ */
+
+static inline void *
+x2nrealloc (void *p, size_t *pn, size_t s)
+{
+ size_t n = *pn;
+
+ if (! p)
+ {
+ if (! n)
+ {
+ /* The approximate size to use for initial small allocation
+ requests, when the invoking code specifies an old size of
+ zero. This is the largest "small" request for the GNU C
+ library malloc. */
+ enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 };
+
+ n = DEFAULT_MXFAST / s;
+ n += !n;
+ }
+ if (xalloc_oversized (n, s))
+ xalloc_die ();
+ }
+ else
+ {
+ /* Set N = floor (1.5 * N) + 1 so that progress is made even if N == 0.
+ Check for overflow, so that N * S stays in both ptrdiff_t and
+ size_t range. The check may be slightly conservative, but an
+ exact check isn't worth the trouble. */
+ if ((PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX) / 3 * 2 / s
+ <= n)
+ xalloc_die ();
+ n += n / 2 + 1;
+ }
+
+ *pn = n;
+ return xrealloc (p, n * s);
+}
+
+/* If P is null, allocate a block of at least *PN bytes; otherwise,
+ reallocate P so that it contains more than *PN bytes. *PN must be
+ nonzero unless P is null. Set *PN to the new block's size, and
+ return the pointer to the new block. *PN is never set to zero, and
+ the returned pointer is never null. */
+
+void *
+x2realloc (void *p, size_t *pn)
+{
+ return x2nrealloc (p, pn, 1);
+}
diff --git a/gnulib-local/modules/xalloc b/gnulib-local/modules/xalloc
index 56734b9fa..dd8151511 100644
--- a/gnulib-local/modules/xalloc
+++ b/gnulib-local/modules/xalloc
@@ -13,6 +13,7 @@ stdlib
xalloc-oversized
configure.ac:
+AC_REQUIRE([AC_C_INLINE])
Makefile.am:
lib_SOURCES += xalloc.h xmalloc.c xstrdup.c