include: deprecate syscalls leftovers
[cavatools.git] / cachesim / container.c
1 //
2 // container.c
3 // teq
4 //
5 // Created by Pete Wilson on 6/6/17.
6 // Copyright © 2017-2020 Kiva Design Groupe LLC. All rights reserved.
7 //
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12
13 #define EXTERN extern
14
15 #include "types.h"
16 #include "container.h"
17
18 extern void allocError(uint64 n, char * thing, char * filename, int32 linenumber);
19
20 static char * name_and_version = "containers 0.1v8 [October 8 2018]";
21
22 /*
23 provides a uniform way of creating an array which can grow in size.
24 generally used for pointers
25
26 Versions
27
28 - containers 0.1v8 [October 8 2018]
29 - added get and add Float64 and Int64 from/to container
30
31 0.1v7 [October 8 2018]
32 - changed ContainerCount() to containerCount()
33 0.1v6 [September 28 2018]
34 - all Containers now hold just pointers. No 'ptrContainers'. Errors remain..
35 0.1v5 [April 16 2018]
36 - changed API for int pullValFromContainer(). returns 1 if there was something in the container, and writes the value removed to a pointer's variable
37 0.1v4 [November 2017]
38 - added pointer only containers (type Container)
39 0.1v3 August 14 2017
40 - added a set of functions to more efficiently push and pull 'word-sized' (64 bit) values to and from a Container
41
42 */
43
44 // ------------------------- contNameAndVersion --------------
45
46 char * contNameAndVersion(void) {
47 return name_and_version;
48 }
49
50 // ------------------ fprintContainer --------------
51
52 void fprintContainer(FILE * f, Container * c) {
53 fprintf(f, "\n\nContainer '%s':", c -> name);
54 fprintf(f, "\n\tcapacity = %d", c -> max);
55 fprintf(f, "\n\tcount = %d", c -> count);
56 // print the pointers
57 for (int i = 0; i < c -> count; i++) {
58 char * p = getPtrFromContainer(c, i);
59 fprintf(f, "\n\t\tptr %d: %p", i, p);
60 }
61 }
62
63 // -------------- printContainer ----------
64
65 void printContainer(Container * c) {
66 fprintContainer(stdout, c);
67 }
68
69 // ----------------- zeroContainer ----------
70
71 void zeroContainer(Container * c) {
72 c -> count = 0;
73 }
74
75 // ------------------ containerCount -----------------
76
77 uint32 containerCount(Container * c) {
78 return c -> count;
79 }
80
81 // ----------- allocateInContainer ------------
82
83 uint32 allocateInContainer(Container * c) {
84 // allocate space for one more pointer in the container, and return the index to it
85 // printf("\nallocate in container '%s':", c -> name);
86 if (c -> count >= c -> max) {
87 // we need to grow the container - we use 50%
88 uint32 newmax = (c -> max + (c -> max/2));
89 //reallocate the data
90 // printf("\n\t-- growing container from %d to %d pointers", c -> max, newmax);
91 void * newdata = realloc(c -> data.ptrs, newmax * sizeof(char *));
92 if (newdata) {
93 // printf("..succeeded.");
94 c -> data.ptrs = newdata;
95 c -> max = newmax;
96 }
97 else {
98 allocError(newmax * sizeof(char *), "reallocation of a container's data", __FILE__, __LINE__);
99 }
100 }
101 // return the index to the current slot
102 uint32 index = c -> count;
103
104 // and increment the slot
105 c -> count++;
106 // printf("\n\tcount incremented to %d", c -> count);
107 return index;
108 }
109
110 // -------------- getPtrFromContainer ---------
111
112 void * getPtrFromContainer(Container * c, uint64 n) {
113 // Read the n'th pointer
114 if (n >= c -> count) {
115 printf("\n=== container error - asking for item %llu in container '%s' when count is %u", n, c -> name, c -> count);
116 return NULL; // safety - a NULL pointer should cause havoc fairly quickly
117 }
118 char * ptr = c -> data.ptrs[n];
119 // printf("\nget ptr[%lld] %p from %s", n, ptr, c -> name);
120 return ptr;
121 }
122
123 // -------------- getFloat64FromContainer ---------
124
125 float64 getFloat64FromContainer(Container * c, uint64 n) {
126 // Read the n'th pointer
127 if (n >= c -> count) {
128 printf("\n=== container error - asking for item %llu in container '%s' when count is %u", n, c -> name, c -> count);
129 return 0.0; // safety - a NULL pointer should cause havoc fairly quickly
130 }
131 float64 v = c -> data.fvals[n];
132 return v;
133 }
134
135 // -------------- getInt64FromContainer ---------
136
137 int64 getInt64FromContainer(Container * c, uint64 n) {
138 // Read the n'th val
139 if (n >= c -> count) {
140 printf("\n=== container error - asking for item %llu in container '%s' when count is %u", n, c -> name, c -> count);
141 return 0.0; // safety - a NULL pointer should cause havoc fairly quickly
142 }
143 int64 v = c -> data.ivals[n];
144 return v;
145 }
146
147 // -------------- addPtrToContainer ---------
148
149 void addPtrToContainer(Container * c, void * p) {
150 // Add the pointer p to the container
151 uint32 n = allocateInContainer(c); // find index at which to store our pointer
152 c -> data.ptrs[n] = p; // and store it
153 }
154
155 // ------------ addFloat64ToContainer -----------
156
157 void addFloat64ToContainer(Container * c, float64 v) {
158 // Add the pointer p to the container
159 uint32 n = allocateInContainer(c); // find index at which to store our float64
160 c -> data.fvals[n] = v; // and store it
161 }
162
163 // ------------ addInt64ToContainer -----------
164
165 void addInt64ToContainer(Container * c, int64 v) {
166 // Add the pointer p to the container
167 uint32 n = allocateInContainer(c); // find index at which to store our int64
168 c -> data.ivals[n] = v; // and store it
169 }
170
171 // ------------ newContainer --------------
172
173 Container * newContainer(uint32 count, char * name) {
174 // create a new pointer container capable of holding up to 'count' pointers
175 uint64 s = sizeof(Container) + 21;
176 Container * c = malloc(s);
177 if (c) {
178 c -> name = strdup(name);
179 c -> data.ptrs = malloc((count + 8) * sizeof(void *));
180 c -> max = count;
181 c -> count = 0;
182 if (c -> data.ptrs == NULL) {
183 allocError(count * sizeof(char *), "pointer container's data array", __FILE__, __LINE__);
184 free(c);
185 c = NULL;
186 }
187 }
188 else {
189 allocError(s, "GP container", __FILE__, __LINE__);
190 }
191 return c;
192 }
193
194 // ------------ pushPtrToContainer --------------
195
196 void pushPtrToContainer(Container * c, void * ptr) {
197 // push a pointer into a container. Same as add.
198 addPtrToContainer(c, ptr);
199 }
200
201 // ------------ pullPtrFromContainer --------------
202
203 void * pullPtrFromContainer(Container * c) {
204 // pull a pointer from a container into ptr; return 1. If none, return 0
205 if (c -> count > 0) {
206 char * p = getPtrFromContainer(c, c -> count - 1);
207 c -> count--;
208 return p;
209 }
210 return NULL;
211 }
212
213 // ------------ getTopPtrInContainer --------------
214
215 void * getTopPtrInContainer(Container * c) {
216 // if there is a pointer, copies top value into ptr and returns 1; else returns 0
217 uint64 n = c -> count;
218 if (n == 0) {
219 return NULL;
220 }
221 char * p = getPtrFromContainer(c, n - 1);
222 return p;
223 }
224
225
226 // -------------- searchInContainer -----------
227
228 int searchInContainer(Container * c, void * p) {
229 // see if we've already got the pointer p in this container; if so, return its index
230 // if not, return -1
231 for (int i = 0; i < containerCount(c); i++) {
232 void * ptr = getPtrFromContainer(c, i);
233 if (ptr == p) return i;
234 }
235 return -1;
236 }
237
238 // -------------- searchStringInContainer -----------
239
240 int searchStringInContainer(Container * c, char * p) {
241 // see if we've already got the string indicated by p in this container; if so, return its index
242 // if not, return -1
243 for (int i = 0; i < containerCount(c); i++) {
244 void * ptr = getPtrFromContainer(c, i);
245 if (strcmp(p, ptr) == 0) return i;
246 }
247 return -1;
248 }
249
250 // ================== character containers =====================
251
252 // ------------------ fprintCharContainer --------------
253
254 void fprintCharContainer(FILE * f, charContainer * c) {
255 fprintf(f, "\n\nContainer '%s':", c -> name);
256 fprintf(f, "\n\tcapacity = %d", c -> max);
257 fprintf(f, "\n\tcount = %d", c -> count);
258 fprintf(f, "\n\ttext = '");
259 // print the characters
260 for (int i = 0; i < c -> count; i++) {
261 char ch = getCharFromContainer(c, i);
262 fprintf(f, "%c", ch);
263 fprintf(f, "'");
264 }
265 }
266
267 // -------------- printCharContainer ----------
268
269 void printCharContainer(charContainer * c) {
270 fprintCharContainer(stdout, c);
271 }
272
273 // ----------------- zeroCharContainer ----------
274
275 void zeroCharContainer(Container * c) {
276 c -> count = 0;
277 }
278
279 // ------------------ charContainerCount -----------------
280
281 uint32 charContainerCount(charContainer * c) {
282 return c -> count;
283 }
284
285 // ----------- allocateInCharContainer ------------
286
287 uint32 allocateInCharContainer(charContainer * c) {
288 // allocate space for one more character in the container, and return the index to it
289 if (c -> count >= c -> max) {
290 // we need to grow the container - we use 50%
291 uint32 newmax = (c -> max + (c -> max/2));
292 //reallocate the data
293 //printf("\n-- growing container %p from %lld to %lld pointers", c, c -> max, newmax);
294 void * newtext = realloc(c -> text, newmax * sizeof(char));
295 if (newtext) {
296 c -> text = newtext;
297 c -> max = newmax;
298 }
299 else {
300 allocError(newmax * sizeof(char *), "reallocation of a character container's text", __FILE__, __LINE__);
301 }
302 }
303 // return the index to the current slot
304 uint32 index = c -> count;
305
306 // and increment the slot
307 c -> count++;
308 return index;
309 }
310
311 // -------------- getCharFromContainer ---------
312
313 char getCharFromContainer(charContainer * c, uint64 n) {
314 // Read the n'th character
315 if (n >= c -> count) {
316 printf("\n=== char container error - asking for item %llu in container '%s' when count is %u", n, c -> name, c -> count);
317 return '\0';
318 }
319 char ch = c -> text[n];
320 // printf("\nget ptr[%lld] %p from %s", n, ptr, c -> name);
321 return ch;
322 }
323
324 // -------------- addCharToContainer ---------
325
326 void addCharToContainer(charContainer * c, char ch) {
327 // Add the character ch to the container
328 uint32 n = allocateInCharContainer(c); // find index at which to store our character
329 // printf("\nadd '%c'' to %s[%lld]", ch, c -> name, n);
330 c -> text[n] = ch; // and store it
331 }
332
333 // ------------ addStringToContainer ----------
334
335 void addStringToContainer(charContainer * c, char * string) {
336 // initially, we'll do this the easy way
337 while (*string) {
338 addCharToContainer(c, *string++);
339 }
340 }
341
342 // ----------- getContainerAsString -----------
343
344 char * getContainerAsString(charContainer * c) {
345 uint32 len = c -> count;
346 char * string = malloc(len + 1);
347 if (string) {
348 for (int i = 0; i < len; i++) {
349 string[i] = getCharFromContainer(c, i);
350 }
351 }
352 return string;
353 }
354
355 // ------------ newCharContainer --------------
356
357 charContainer * newCharContainer(uint32 count, char * name) {
358 // create a new character container capable of holding up to 'count' characters
359 uint64 s = sizeof(charContainer);
360 charContainer * c = malloc(s);
361 if (c) {
362 c -> name = strdup(name);
363 c -> text = malloc((count + 1) * sizeof(char));
364 c -> max = count;
365 c -> count = 0;
366 if (c -> text == NULL) {
367 allocError(count * sizeof(char), "char container's data array", __FILE__, __LINE__);
368 free(c);
369 c = NULL;
370 }
371 }
372 else {
373 allocError(s, "char container", __FILE__, __LINE__);
374 }
375 return c;
376 }
377