A utility for dealing with strings in C
git clone git://soophie.de/buf
blob: 13f152493856d6c651cda290ca410af271572553 (3947 bytes)[raw]
1
/*2
* Copyright (C) 2026 Sophie Sitzler3
*4
* This program is free software: you can redistribute it and/or modify5
* it under the terms of the GNU General Public License as published by6
* the Free Software Foundation, either version 3 of the License, or7
* (at your option) any later version.8
*9
* This program is distributed in the hope that it will be useful,10
* but WITHOUT ANY WARRANTY; without even the implied warranty of11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12
* GNU General Public License for more details.13
*14
* You should have received a copy of the GNU General Public License15
* along with this program. If not, see <https://www.gnu.org/licenses/>.16
*/18
// @file buf.h19
#pragma once21
#include <stdio.h>22
#include <stdint.h>23
#include <stdlib.h>24
#include <stdarg.h>25
#include <stdbool.h>27
#ifndef BUF_CAP_BASE28
#define BUF_CAP_BASE 6429
#endif31
#define BUF_NULL (buf_t) { NULL, 0, 0, 0 }33
typedef struct {34
uint8_t *bytes;35
size_t len;36
size_t cap;37
size_t pos;38
} buf_t;40
void buf_init(buf_t *self, void *bytes, size_t len);41
void buf_free(buf_t *self);42
bool buf_write_len(buf_t *self, const void *bytes, size_t len);43
bool buf_write(buf_t *self, const void *bytes);44
void buf_writef(buf_t *self, const char *fmt, ...);45
bool buf_read(buf_t *self, void *bytes, size_t len);46
void buf_concat(buf_t *self, buf_t buf);47
void buf_repall_len(buf_t *self, const char *pat, const char *rep, size_t len);48
void buf_repall(buf_t *self, const char *pat, const char *rep);50
#ifdef BUF_IMPL52
#include <string.h>54
void buf_init(buf_t *self, void *bytes, size_t len) {55
self->bytes = (uint8_t *)bytes;56
self->len = len;57
self->cap = len;58
self->pos = 0;59
}61
void buf_free(buf_t *self) {62
if (!self || !self->bytes) return;63
free(self->bytes);64
*self = BUF_NULL;65
}67
bool buf_write_len(buf_t *self, const void *bytes, size_t len) {68
if (!self || !bytes) return false;69
size_t needed = self->len + len;70
if (needed > self->cap) {71
size_t new_cap = self->cap ? self->cap * 2 : BUF_CAP_BASE;72
while (needed > new_cap) new_cap *= 2;73
uint8_t *tmp = (uint8_t *) realloc(self->bytes, new_cap);74
if (!tmp) return false;75
self->bytes = tmp;76
self->cap = new_cap;77
}78
memcpy(self->bytes + self->len, bytes, len);79
self->len += len;80
return true;81
}83
bool buf_write(buf_t *self, const void *bytes) {84
if (!bytes) return false;85
return buf_write_len(self, bytes, strlen(bytes));86
}88
void buf_writef(buf_t *self, const char *fmt, ...) {89
if (!self || !fmt) return;90
va_list args;91
va_start(args, fmt);92
ssize_t data_len = vsnprintf(NULL, 0, fmt, args);93
va_end(args);94
if (data_len < 0) return;95
char *data = malloc(data_len + 1);96
if (!data) return;97
va_start(args, fmt);98
vsnprintf(data, data_len + 1, fmt, args);99
va_end(args);100
buf_write(self, data);101
free(data);102
}104
bool buf_read(buf_t *self, void *bytes, size_t len) {105
if (!self || !bytes || self->pos + len > self->len) return false;106
memcpy(bytes, self->bytes + self->pos, len);107
self->pos += len;108
return true;109
}111
void buf_concat(buf_t *self, buf_t buf) {112
buf_write_len(self, buf.bytes, buf.len);113
}115
void buf_repall_len(buf_t *self, const char *pat, const char *rep, size_t len) {116
if (!self || !self->bytes || !pat || !rep) return;117
const char *bytes = (const char *) self->bytes;118
size_t pat_len = strlen(pat);119
size_t rep_len = strlen(rep);120
if (pat_len == 0) return;121
buf_t out = BUF_NULL;122
size_t idx = 0;123
while (idx < len && *bytes) {124
size_t rem = len - idx;125
if (rem >= pat_len && strncmp(bytes, pat, pat_len) == 0) {126
buf_write_len(&out, rep, rep_len);127
bytes += pat_len;128
idx += pat_len;129
}130
else {131
buf_write_len(&out, bytes, 1);132
bytes++;133
idx++;134
}135
}136
buf_free(self);137
buf_write_len(self, out.bytes, out.len);138
buf_free(&out);139
}141
void buf_repall(buf_t *self, const char *pat, const char *rep) {142
buf_repall_len(self, pat, rep, self->len);143
}145
#endif /* BUF_IMPL */