/* [ʞ] compose.c
* ~ lexi hale <lexi@hale.su>
* © affero general public license v3
* $ cc -c compose.c
* # include <string.h>
*
* compose.c contains some useful string utilities
* that libc lacks.
TODO add macro to use homebrew strlen instead of
dragging in <string.h> */
#ifdef k_header // only emit the declarations
# define fn(x)
#else
# define fn(x) x
#endif
#include <string.h>
typedef struct pstr { size_t len; union {
const char* ptr;
char* mutptr;
}; } pstr;
#define _p(str) { sizeof str - 1, str }
typedef struct safestr {
union {
const char* ptr;
char* mutptr;
}; // im sorry okay
bool heap;
size_t len;
} safestr;
void delstr(safestr s) fn ({
if (s.heap) { free(s.mutptr); }
});
void clrstr(safestr* s) fn ({
delstr(*s);
s->heap = false;
s->ptr = NULL;
s->len = 0;
})
char* compose(pstr* lst,size_t ct, size_t* strsz) fn({
size_t len = 0;
for (size_t i = 0; i < ct; ++i) {
if (lst[i].len == 0) {
if (lst[i].ptr == NULL) continue;
lst[i].len = strlen(lst[i].ptr);
}
len += lst[i].len;
}
if (strsz != NULL) *strsz = len;
if (len == 0) return NULL;
char* str = malloc(len + 1);
char* ptr = str;
for (size_t i = 0; i < ct; ++i) {
if (lst[i].len == 0) continue;
strncpy(ptr,lst[i].ptr,lst[i].len);
ptr += lst[i].len;
}
*ptr = 0;
return str;
});