5 // Created by Pete Wilson on 6/6/17.
6 // Copyright © 2017-2020 Kiva Design Groupe LLC. All rights reserved.
16 #include "container.h"
18 extern void allocError(uint64 n
, char * thing
, char * filename
, int32 linenumber
);
20 static char * name_and_version
= "containers 0.1v8 [October 8 2018]";
23 provides a uniform way of creating an array which can grow in size.
24 generally used for pointers
28 - containers 0.1v8 [October 8 2018]
29 - added get and add Float64 and Int64 from/to container
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..
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
38 - added pointer only containers (type Container)
40 - added a set of functions to more efficiently push and pull 'word-sized' (64 bit) values to and from a Container
44 // ------------------------- contNameAndVersion --------------
46 char * contNameAndVersion(void) {
47 return name_and_version
;
50 // ------------------ fprintContainer --------------
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
);
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
);
63 // -------------- printContainer ----------
65 void printContainer(Container
* c
) {
66 fprintContainer(stdout
, c
);
69 // ----------------- zeroContainer ----------
71 void zeroContainer(Container
* c
) {
75 // ------------------ containerCount -----------------
77 uint32
containerCount(Container
* c
) {
81 // ----------- allocateInContainer ------------
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));
90 // printf("\n\t-- growing container from %d to %d pointers", c -> max, newmax);
91 void * newdata
= realloc(c
-> data
.ptrs
, newmax
* sizeof(char *));
93 // printf("..succeeded.");
94 c
-> data
.ptrs
= newdata
;
98 allocError(newmax
* sizeof(char *), "reallocation of a container's data", __FILE__
, __LINE__
);
101 // return the index to the current slot
102 uint32 index
= c
-> count
;
104 // and increment the slot
106 // printf("\n\tcount incremented to %d", c -> count);
110 // -------------- getPtrFromContainer ---------
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
118 char * ptr
= c
-> data
.ptrs
[n
];
119 // printf("\nget ptr[%lld] %p from %s", n, ptr, c -> name);
123 // -------------- getFloat64FromContainer ---------
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
131 float64 v
= c
-> data
.fvals
[n
];
135 // -------------- getInt64FromContainer ---------
137 int64
getInt64FromContainer(Container
* c
, uint64 n
) {
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
143 int64 v
= c
-> data
.ivals
[n
];
147 // -------------- addPtrToContainer ---------
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
155 // ------------ addFloat64ToContainer -----------
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
163 // ------------ addInt64ToContainer -----------
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
171 // ------------ newContainer --------------
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
);
178 c
-> name
= strdup(name
);
179 c
-> data
.ptrs
= malloc((count
+ 8) * sizeof(void *));
182 if (c
-> data
.ptrs
== NULL
) {
183 allocError(count
* sizeof(char *), "pointer container's data array", __FILE__
, __LINE__
);
189 allocError(s
, "GP container", __FILE__
, __LINE__
);
194 // ------------ pushPtrToContainer --------------
196 void pushPtrToContainer(Container
* c
, void * ptr
) {
197 // push a pointer into a container. Same as add.
198 addPtrToContainer(c
, ptr
);
201 // ------------ pullPtrFromContainer --------------
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);
213 // ------------ getTopPtrInContainer --------------
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
;
221 char * p
= getPtrFromContainer(c
, n
- 1);
226 // -------------- searchInContainer -----------
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
231 for (int i
= 0; i
< containerCount(c
); i
++) {
232 void * ptr
= getPtrFromContainer(c
, i
);
233 if (ptr
== p
) return i
;
238 // -------------- searchStringInContainer -----------
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
243 for (int i
= 0; i
< containerCount(c
); i
++) {
244 void * ptr
= getPtrFromContainer(c
, i
);
245 if (strcmp(p
, ptr
) == 0) return i
;
250 // ================== character containers =====================
252 // ------------------ fprintCharContainer --------------
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
);
267 // -------------- printCharContainer ----------
269 void printCharContainer(charContainer
* c
) {
270 fprintCharContainer(stdout
, c
);
273 // ----------------- zeroCharContainer ----------
275 void zeroCharContainer(Container
* c
) {
279 // ------------------ charContainerCount -----------------
281 uint32
charContainerCount(charContainer
* c
) {
285 // ----------- allocateInCharContainer ------------
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));
300 allocError(newmax
* sizeof(char *), "reallocation of a character container's text", __FILE__
, __LINE__
);
303 // return the index to the current slot
304 uint32 index
= c
-> count
;
306 // and increment the slot
311 // -------------- getCharFromContainer ---------
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
);
319 char ch
= c
-> text
[n
];
320 // printf("\nget ptr[%lld] %p from %s", n, ptr, c -> name);
324 // -------------- addCharToContainer ---------
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
333 // ------------ addStringToContainer ----------
335 void addStringToContainer(charContainer
* c
, char * string
) {
336 // initially, we'll do this the easy way
338 addCharToContainer(c
, *string
++);
342 // ----------- getContainerAsString -----------
344 char * getContainerAsString(charContainer
* c
) {
345 uint32 len
= c
-> count
;
346 char * string
= malloc(len
+ 1);
348 for (int i
= 0; i
< len
; i
++) {
349 string
[i
] = getCharFromContainer(c
, i
);
355 // ------------ newCharContainer --------------
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
);
362 c
-> name
= strdup(name
);
363 c
-> text
= malloc((count
+ 1) * sizeof(char));
366 if (c
-> text
== NULL
) {
367 allocError(count
* sizeof(char), "char container's data array", __FILE__
, __LINE__
);
373 allocError(s
, "char container", __FILE__
, __LINE__
);