#include #include #include #include #define DEFAULT_CAPACITY 256 void sb_init(struct sb *ctx) { (void)sb_init_capacity(ctx, DEFAULT_CAPACITY); } int sb_init_capacity(struct sb *ctx, size_t starting_capacity) { ctx->to_ignore = 0; ctx->length = 0; ctx->prebuffer = 0; ctx->string = malloc(starting_capacity); if (NULL == ctx->string) { ctx->capacity = 0; return 0; } ctx->capacity = starting_capacity; return 1; } void sb_init_buffer(struct sb *ctx, char *buffer, size_t size) { ctx->string = buffer; ctx->capacity = size; ctx->length = 0; ctx->prebuffer = 1; ctx->to_ignore = 0; } void sb_free(struct sb *ctx) { if (ctx->prebuffer) { ctx->length = 0; return; } ctx->length = 0; ctx->capacity = 0; free(ctx->string); ctx->string = NULL; } void sb_set_ignore(struct sb *ctx, size_t n) { ctx->to_ignore = n; } void sb_reset(struct sb *ctx) { ctx->length = 0; ctx->to_ignore = 0; } int sb_isempty(const struct sb *ctx) { return (0 == ctx->length); } int sb_increase_buffer(struct sb *ctx, size_t min) { if (ctx->prebuffer) { return 0; } size_t new_capacity = ctx->capacity + max(32, min); char *new_allocation = realloc(ctx->string, new_capacity); if (!new_allocation) { return 0; } ctx->string = new_allocation; ctx->capacity = new_capacity; return 1; } int sb_append_char(struct sb *ctx, char c) { if (ctx->to_ignore > 0) { ctx->to_ignore--; return 1; } if (1 > ctx->capacity - ctx->length) { if (!sb_increase_buffer(ctx, 1)) { return 0; } } memcpy(ctx->string + ctx->length, &c, 1); ctx->length++; return 1; } int sb_delete_right(struct sb *ctx, size_t n) { n = min(n, ctx->length); ctx->length -= n; return n; } int sb_append(struct sb *ctx, const char *s) { size_t l = strlen(s); if (ctx->to_ignore >= l) { ctx->to_ignore -= l; return 1; } l -= ctx->to_ignore; s += ctx->to_ignore; ctx->to_ignore = 0; if (l > ctx->capacity - ctx->length) { if (!sb_increase_buffer(ctx, l)) { return 0; } } memcpy(ctx->string + ctx->length, s, l); ctx->length += l; return 1; } int sb_prepend_sv(struct sb *ctx, struct sv sv) { return sb_prepend_buffer(ctx, sv.s, sv.length); } int sb_prepend_buffer(struct sb *ctx, const void *buffer, size_t length) { if (ctx->to_ignore >= length) { ctx->to_ignore -= length; return 1; } length -= ctx->to_ignore; buffer = (void *)((uintptr_t)buffer + ctx->to_ignore); ctx->to_ignore = 0; if (length > ctx->capacity - ctx->length) { if (!sb_increase_buffer(ctx, length)) { return 0; } } memmove(ctx->string + length, ctx->string, ctx->length); memcpy(ctx->string, buffer, length); ctx->length += length; return 1; } int sb_append_buffer(struct sb *ctx, const void *buffer, size_t length) { if (ctx->to_ignore >= length) { ctx->to_ignore -= length; return 1; } length -= ctx->to_ignore; buffer = (void *)((uintptr_t)buffer + ctx->to_ignore); ctx->to_ignore = 0; if (length > ctx->capacity - ctx->length) { if (!sb_increase_buffer(ctx, length)) { return 0; } } memcpy(ctx->string + ctx->length, buffer, length); ctx->length += length; return 1; } int sb_modify_location(struct sb *ctx, void *buffer, size_t length, size_t offset) { if (offset + length > ctx->length) { return 0; } memcpy(ctx->string + offset, buffer, length); return 1; } int sb_reserve_buffer(struct sb *ctx, size_t *offset, size_t length) { if (ctx->to_ignore > 0) { return 0; } if (length > ctx->capacity - ctx->length) { if (!sb_increase_buffer(ctx, length)) { return 0; } } if (offset) { *offset = ctx->length; } ctx->length += length; return 1; } int sb_append_sv(struct sb *ctx, struct sv sv) { return sb_append_buffer(ctx, sv.s, sv.length); }