aboutsummaryrefslogtreecommitdiff
path: root/shared/common/grow.c
diff options
context:
space:
mode:
Diffstat (limited to 'shared/common/grow.c')
-rw-r--r--shared/common/grow.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/shared/common/grow.c b/shared/common/grow.c
new file mode 100644
index 0000000..f02509a
--- /dev/null
+++ b/shared/common/grow.c
@@ -0,0 +1,105 @@
+/* Copyright (c) 2002-2003 krzYszcz and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* LATER generic handling of reentrant output request and self-invoked set */
+
+#include <string.h>
+#include "m_pd.h"
+#include "common/grow.h"
+
+/* Prior to this call a caller is supposed to check for *nrequested > *sizep.
+ Returns a reallocated buffer's pointer (success) or a given 'bufini'
+ default value (failure).
+ Upon return *nrequested contains the actual number of elements:
+ requested (success) or a given default value of 'inisize' (failure). */
+void *grow_nodata(int *nrequested, int *sizep, void *bufp,
+ int inisize, void *bufini, size_t typesize)
+{
+ int newsize = *sizep * 2;
+ while (newsize < *nrequested) newsize *= 2;
+ if (bufp == bufini)
+ bufp = getbytes(newsize * typesize);
+ else
+ bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize);
+ if (bufp)
+ {
+ *sizep = newsize;
+ return (bufp);
+ }
+ else
+ {
+ *nrequested = *sizep = inisize;
+ return (bufini);
+ }
+}
+
+/* Like grow_nodata(), but preserving first *nexisting elements. */
+void *grow_withdata(int *nrequested, int *nexisting,
+ int *sizep, void *bufp,
+ int inisize, void *bufini, size_t typesize)
+{
+ int newsize = *sizep * 2;
+ while (newsize < *nrequested) newsize *= 2;
+ if (bufp == bufini)
+ {
+ if (!(bufp = getbytes(newsize * typesize)))
+ {
+ *nrequested = *sizep = inisize;
+ return (bufini);
+ }
+ *sizep = newsize;
+ memcpy(bufp, bufini, *nexisting * typesize);
+ }
+ else
+ {
+ int oldsize = *sizep;
+ if (!(bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize)))
+ {
+ *nrequested = *sizep = inisize;
+ *nexisting = 0;
+ return (bufini);
+ }
+ *sizep = newsize;
+ }
+ return (bufp);
+}
+
+/* Like grow_nodata(), but preserving a 'tail' of *nexisting elements,
+ starting from *startp. */
+/* LATER rethink handling of a start pointer (clumsy now) */
+void *grow_withtail(int *nrequested, int *nexisting, char **startp,
+ int *sizep, void *bufp,
+ int inisize, void *bufini, size_t typesize)
+{
+ int newsize = *sizep * 2;
+ while (newsize < *nrequested) newsize *= 2;
+ if (bufp == bufini)
+ {
+ char *oldstart = *startp;
+ if (!(bufp = getbytes(newsize * typesize)))
+ {
+ *nrequested = *sizep = inisize;
+ return (bufini);
+ }
+ *startp = (char *)bufp + (newsize - *nexisting) * typesize;
+ *sizep = newsize;
+ memcpy(*startp, oldstart, *nexisting * typesize);
+ }
+ else
+ {
+ int oldsize = *sizep;
+ if (!(bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize)))
+ {
+ *startp = (char *)bufini + inisize * typesize;
+ *nrequested = *sizep = inisize;
+ *nexisting = 0;
+ return (bufini);
+ }
+ *startp = (char *)bufp + (newsize - *nexisting) * typesize;
+ *sizep = newsize;
+ memmove(*startp, (char *)bufp + (oldsize - *nexisting) * typesize,
+ *nexisting * typesize);
+ }
+ return (bufp);
+}