From 35a201cc8ef0c3f5b2df88d2e528aabee1048348 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 30 Apr 2021 18:47:09 +0200 Subject: Initial/Final commit --- string_buf.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 string_buf.c (limited to 'string_buf.c') diff --git a/string_buf.c b/string_buf.c new file mode 100644 index 0000000..81051d5 --- /dev/null +++ b/string_buf.c @@ -0,0 +1,282 @@ +#include +#include +#include +#include +#include + +#define MINIMUM_EXTEND_BYTES 63 + +int extend_buf(char **buf, size_t *buf_len, size_t *buf_filled, + size_t extend_len) +{ + ssize_t space_left = *buf_len - *buf_filled - 1; + size_t new_size, size_required, size_more_space; + char *new_buf; + + if (space_left >= 0 && space_left >= extend_len) + return 0; + + size_required = *buf_filled + extend_len + 1; + size_more_space = size_required + MINIMUM_EXTEND_BYTES; + new_size = *buf_len * 2; + if (new_size < size_more_space) + new_size = size_more_space; + + new_buf = realloc(*buf, new_size); + if (!new_buf) + new_buf = realloc(*buf, size_required); + if (!new_buf) + return -1; + + *buf = new_buf; + *buf_len = new_size; + return 0; +} + +int sb_bytes(char **buf, size_t *buf_len, size_t *buf_filled, + const unsigned char *bytes, size_t bytes_len) +{ + if (extend_buf(buf, buf_len, buf_filled, bytes_len)) + return -1; + + memcpy(*buf + *buf_filled, bytes, bytes_len); + *(*buf + *buf_filled + bytes_len) = '\0'; + *buf_filled += bytes_len; + return 0; +} + +int sb_string(char **buf, size_t *buf_len, size_t *buf_filled, + const char *string) +{ + size_t string_len = strlen(string); + + return sb_bytes(buf, buf_len, buf_filled, + (const unsigned char*) string, string_len); +} + +int sb_char(char **buf, size_t *buf_len, size_t *buf_filled, char c) +{ + return sb_bytes(buf, buf_len, buf_filled, + (const unsigned char*) &c, 1); +} + +/* Below is old version */ + +/* inline static size_t process_fmt(MYSQL *mysql, const char *fmt, */ +/* va_list ap, char *dst) */ +/* { */ +/* size_t len = 0; */ +/* const char *in_pos = fmt; */ +/* char *out_pos = dst, c; */ +/* bool percent = false; */ + +/* short digits_count; */ +/* long power_of_10; */ +/* long num_arg; */ + +/* const char *string_arg; */ +/* size_t string_len; */ + +/* #define WRITE_CHAR(ch) \ */ +/* do { \ */ +/* if (dst) \ */ +/* *(out_pos++) = (ch); \ */ +/* else \ */ +/* len++; \ */ +/* } \ */ +/* while (0) \ */ + +/* while (*in_pos) { */ +/* c = *(in_pos++); */ + +/* if (!percent) { */ +/* if (c != '%') */ +/* WRITE_CHAR(c); */ +/* else */ +/* percent = true; */ + +/* continue; */ +/* } */ + +/* percent = false; */ + +/* switch (c) { */ +/* case 'd': */ +/* case 'u': */ +/* if (c == 'd') */ +/* num_arg = va_arg(ap, int); */ +/* else */ +/* num_arg = va_arg(ap, unsigned); */ + +/* if (num_arg < 0) { */ +/* WRITE_CHAR('-'); */ +/* num_arg = -num_arg; */ +/* } */ +/* for (digits_count = 1, power_of_10 = 10; */ +/* power_of_10 <= num_arg; */ +/* digits_count++, power_of_10 *= 10); */ + +/* power_of_10 /= 10; */ +/* while (digits_count--) { */ +/* WRITE_CHAR('0' + num_arg / power_of_10); */ +/* num_arg = (num_arg % power_of_10) * 10; */ +/* } */ +/* break; */ +/* case 's': */ +/* for (string_arg = va_arg(ap, const char*); */ +/* *string_arg; string_arg++) */ +/* WRITE_CHAR(*string_arg); */ +/* break; */ +/* case 'm': */ +/* string_arg = va_arg(ap, const char*); */ +/* string_len = strlen(string_arg); */ +/* if (!dst) { */ +/* len += 2 * string_len; */ +/* break; */ +/* } */ +/* out_pos += mysql_real_escape_string(mysql, out_pos, */ +/* string_arg, */ +/* string_len); */ +/* break; */ +/* case '%': */ +/* WRITE_CHAR('%'); */ +/* } */ +/* } */ + +/* if (dst) { */ +/* *out_pos = '\0'; */ +/* return out_pos - dst; */ +/* } */ +/* return len; */ +/* } */ + +/* int sb_sprintf(char **buf, size_t *buf_len, size_t *buf_filled, */ +/* MYSQL *mysql, const char *fmt, ...) */ +/* { */ +/* size_t extend_len; */ +/* va_list ap; */ + +/* va_start(ap, fmt); */ +/* extend_len = process_fmt(NULL, fmt, ap, NULL); */ +/* va_end(ap); */ + +/* if (extend_buf(buf, buf_len, buf_filled, extend_len)) */ +/* return -1; */ + +/* va_start(ap, fmt); */ +/* *buf_filled += process_fmt(mysql, fmt, ap, *buf + *buf_filled); */ +/* va_end(ap); */ + +/* return 0; */ +/* } */ + +int sb_num(char **buf, size_t *buf_len, size_t *buf_filled, long num) +{ + unsigned char repr[3 * sizeof(long) + 1]; + int i; + bool neg = num < 0; + + for (i = sizeof(repr); num; num /= 10) + repr[--i] = '0' + num % 10; + + if (i == sizeof(repr)) + repr[--i] = '0'; + else if (neg) + repr[--i] = '-'; + + sb_bytes(buf, buf_len, buf_filled, + repr + i, sizeof(repr) - i); + + return 0; +} + +int sb_vsprintf(char **buf, size_t *buf_len, size_t *buf_filled, + const char *fmt, va_list ap) +{ + const unsigned char *in_pos = (const unsigned char*) fmt; + char c; + size_t i = 0; + bool percent = false; + + long num_arg; + int (*sb_cb)(char**, size_t*, size_t*, void*); + + while (in_pos[i]) { + c = in_pos[i++]; + + if (!percent) { + if (c == '%') { + percent = true; + if (sb_bytes(buf, buf_len, buf_filled, + in_pos, i - 1)) + return -1; + } + + continue; + } + + percent = false; + in_pos += i; + i = 0; + + switch (c) { + case 'd': + case 'u': + num_arg = c == 'd' ? + va_arg(ap, int) : va_arg(ap, unsigned); + + if (sb_num(buf, buf_len, buf_filled, num_arg)) + return -1; + break; + case 's': + if (sb_string(buf, buf_len, buf_filled, + va_arg(ap, const char*))) + return -1; + break; + case '_': + sb_cb = va_arg(ap, int (*)(char**, size_t*, + size_t*, void*)); + if (sb_cb(buf, buf_len, buf_filled, + va_arg(ap, void*))) + return -1; + break; + case '%': + in_pos--; + i++; + } + } + + if (!percent && sb_bytes(buf, buf_len, buf_filled, in_pos, i)) + return -1; + + return 0; +} + +int sb_sprintf(char **buf, size_t *buf_len, size_t *buf_filled, + const char *fmt, ...) +{ + va_list ap; + int res; + + va_start(ap, fmt); + res = sb_vsprintf(buf, buf_len, buf_filled, fmt, ap); + va_end(ap); + + return res; +} + +int crop_buf(char **buf, size_t *buf_len, size_t *buf_filled) +{ + char *new_buf; + + if (*buf_len <= *buf_filled + 1) + return 0; + + new_buf = realloc(*buf, *buf_filled + 1); + if (!new_buf) + return -1; + + *buf = new_buf; + *buf_len = *buf_filled + 1; + return 0; +} -- cgit v1.2.3