aboutsummaryrefslogtreecommitdiff
path: root/string_buf.c
diff options
context:
space:
mode:
authorWojtek Kosior <wk@koszkonutek-tmp.pl.eu.org>2021-04-30 18:47:09 +0200
committerWojtek Kosior <wk@koszkonutek-tmp.pl.eu.org>2021-04-30 18:47:09 +0200
commit35a201cc8ef0c3f5b2df88d2e528aabee1048348 (patch)
tree902dae955480e19f4498dbe4964619fc91d09b06 /string_buf.c
downloadxml-backup-restore-master.tar.gz
xml-backup-restore-master.zip
Initial/Final commitHEADmaster
Diffstat (limited to 'string_buf.c')
-rw-r--r--string_buf.c282
1 files changed, 282 insertions, 0 deletions
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 <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#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;
+}