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
|
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "common/strbuild.h"
void sfdo_strbuild_init(struct sfdo_strbuild *strbuild) {
strbuild->data = NULL;
strbuild->len = strbuild->cap = 0;
}
void sfdo_strbuild_finish(struct sfdo_strbuild *strbuild) {
free(strbuild->data);
}
void sfdo_strbuild_reset(struct sfdo_strbuild *strbuild) {
strbuild->len = 0;
}
bool sfdo_strbuild_add(
struct sfdo_strbuild *strbuild, const struct sfdo_string *items, size_t n_items) {
size_t total_len = 0;
for (size_t i = 0; i < n_items; i++) {
const struct sfdo_string *item = &items[i];
total_len += item->len;
}
size_t cap = strbuild->cap == 0 ? 4096 : strbuild->cap;
// end must be strictly bigger than cap to have space for a null terminator
size_t end = strbuild->len + total_len;
while (end >= cap) {
if (cap > SIZE_MAX / 2) {
return false;
}
cap *= 2;
}
if (strbuild->cap != cap) {
char *pb_data = realloc(strbuild->data, cap);
if (pb_data == NULL) {
return false;
}
strbuild->data = pb_data;
strbuild->cap = cap;
}
for (size_t i = 0; i < n_items; i++) {
const struct sfdo_string *item = &items[i];
memcpy(&strbuild->data[strbuild->len], item->data, item->len);
strbuild->len += item->len;
}
strbuild->data[strbuild->len] = '\0';
return true;
}
|