aboutsummaryrefslogtreecommitdiff
path: root/shared/common/grow.c
blob: c67ab503c86eb49112add21894ace6f795951fc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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 "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);
}