-
Notifications
You must be signed in to change notification settings - Fork 0
/
multi_malloc.h
144 lines (121 loc) · 4 KB
/
multi_malloc.h
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
* @file multi_malloc.h
* @author Jens Munk Hansen <jens.munk.hansen@gmail.com>
* @date Fri May 5 19:00:21 2007
*
* @brief Allocation of multi-dimensional C arrays using row pointers
*
*
*/
#pragma once
#include <sps/cenv.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) STATIC_INLINE_END;
STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) STATIC_INLINE_END;
/**
* Allocate multi-dimensional array and establish row pointers
*
* @param s size of each element
* @param d number of dimension
*
* @return
*/
STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) {
char* tree;
va_list ap; /* varargs list traverser */
size_t max, /* size of array to be declared */
*q; /* pointer to dimension list */
char **r, /* pointer to beginning of the array of the
* pointers for a dimension */
**s1, *t; /* base pointer to beginning of first array */
size_t i, j; /* loop counters */
size_t *d1; /* dimension list */
va_start(ap,d);
d1 = (size_t *) malloc(d*sizeof(size_t));
if (d1 == NULL)
return NULL;
for(i=0; i<d; i++)
d1[i] = va_arg(ap,size_t);
r = &tree;
q = d1; /* first dimension */
if (d==1) {
max = s * (*q);
va_end(ap);
free(d1);
return malloc(max);
}
max = 1;
for (i = 0; i < d - 1; i++, q++) {
/* for each of the dimensions
* but the last */
max *= (*q);
r[0]=(char *)malloc(max * sizeof(char **));
r = (char **) r[0]; /* step through to beginning of next
* dimension array */
}
max *= s * (size_t) (*q); /* grab actual array memory */
r[0] = (char *)malloc(max * sizeof(char));
/*
* r is now set to point to the beginning of each array so that we can
* use it to scan down each array rather than having to go across and
* then down
*/
r = (char **) tree; /* back to the beginning of list of arrays */
q = d1; /* back to the first dimension */
max = 1;
for (i = 0; i < d - 2; i++, q++) {
/* we deal with the last
* array of pointers later on */
max *= (*q); /* number of elements in this dimension */
for (j=1, s1=r+1, t=r[0]; j<max; j++) {
/* scans down array for
* first and subsequent
* elements */
/* modify each of the pointers so that it points to
* the correct position (sub-array) of the next
* dimension array. s1 is the current position in the
* current array. t is the current position in the
* next array. t is incremented before s1 is, but it
* starts off one behind. *(q+1) is the dimension of
* the next array. */
*s1 = (t += sizeof (char **) **(q + 1));
s1++;
}
r = (char **) r[0]; /* step through to begining of next
* dimension array */
}
max *= (*q); /* max is total number of elements in the
* last pointer array */
/* same as previous loop, but different size factor */
for (j = 1, s1 = r + 1, t = r[0]; j < max; j++)
*s1++ = (t += s **(q + 1));
va_end(ap);
free(d1);
return((void *)tree); /* return base pointer */
}
/**
* Free multi-dimensional array and corresponding row pointers
*
* @param r data
* @param d number of dimensions
*/
STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) {
void **p;
void *next=NULL;
size_t i;
for (p = (void **)r, i = 0; i < d; p = (void **) next,i++)
if (p != NULL) {
next = *p;
free(p);
p = NULL;
}
}
/* Local variables: */
/* indent-tab-mode: nil */
/* tab-width: 2 */
/* c-basic-offset: 2 */
/* indent-tabs-mode: nil */
/* End: */