custom strdup
===
Mark and sweep garbage collection is suitable for C/C++ where the programmer has access to object pointers (as opposed to more high level lamguages) because this algorithm does not move objects from their addresses in memory, so all pointers can be retained. The algorithm performs a DFS to mark all accessible objects. The objects left unmarked have no references and therefore can not be reasonably accessed aND so their memory can be safely rewritten by new objects.
This is my `tests/string-separate.c` with a strdup implementation:
```
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "gc.h"
#define IS_DEL(c, d) (c == d)
static inline char *strdup(const char *s, int size) {
char *p = gc_alloc(size);
if (p)
memcpy(p, s, size);
return p;
}
static int count_words(char *s, char delimiter)
{
int i = -1, words = 0;
while (s[++i])
if (((i != 0 && IS_DEL(s[i], delimiter) &&
!IS_DEL(s[i - 1], delimiter)) ||
(s[i + 1] == '\0' && !IS_DEL(s[i], delimiter))))
words++;
return words;
}
static char *get_word(char *s, char delimiter)
{
int i = -1, size = 0;
while (s[++i] && !IS_DEL(s[i], delimiter))
size++;
return strdup(s, size);
}
char **my_strsep(char *s, char delimiter)
{
if (!s)
return NULL;
char **tab;
int size = count_words(s, delimiter);
if (!(tab = gc_alloc((size + 1) * sizeof(char *))))
return NULL;
tab[size] = 0; // set to 0? i don't know why. terminated by zero?
char *str = s; // pointer to beginning of s
while (*str) {
if (!IS_DEL(*str, delimiter)) {
*tab++ = get_word(str, delimiter);
str += strlen(get_word(str, delimiter)) - 1;
}
str++;
}
return tab - size; // returns pointer to first word
}
int main(int argc, char *argv[])
{
gc_init(&argc, 1);
char glued[] = "hello,world,world2,world3,hello2,world4,hello3";
char delimiter = ',';
char **sep = my_strsep(glued, delimiter);
assert(sep);
/* print all words */
int cnt = count_words(glued, delimiter);
for (int i = 0 ; i < cnt ; i++)
printf("%s\n", sep[i]);
gc_run();
gc_dump_internals();
gc_destroy();
return 0;
}
```