]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
xalloc: Add x2realloc function, from gnulib.
authorBruno Haible <bruno@clisp.org>
Mon, 12 Aug 2019 01:31:49 +0000 (03:31 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 12 Aug 2019 01:31:49 +0000 (03:31 +0200)
* 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.

gnulib-local/lib/xalloc.h
gnulib-local/lib/xmalloc.c
gnulib-local/modules/xalloc

index e4fb28866af97380c1c69ac31ce041f8731e44b6..b512cc8eb7368025a8f7ed261ecfcc0552b200b5 100644 (file)
@@ -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
index 869cc1804633390866ca061649fa461b24feb56b..a1456c520ecc0627384b3d5009b213dfa09cd39b 100644 (file)
@@ -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);
+}
index 56734b9fa171fd244a8b083bbed51ab388c3210a..dd8151511fd4f1cac47b2443563d4db9494b239b 100644 (file)
@@ -13,6 +13,7 @@ stdlib
 xalloc-oversized
 
 configure.ac:
+AC_REQUIRE([AC_C_INLINE])
 
 Makefile.am:
 lib_SOURCES += xalloc.h xmalloc.c xstrdup.c