Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpx/lua-cjson.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2011-04-15 15:28:53 +0400
committerMark Pulford <mark@kyne.com.au>2011-04-15 15:28:53 +0400
commitbbf1f5d35e8312fb7373a997664309adf9527af4 (patch)
tree39dbd1d56cd730e07a27854adda504b8a120ce2f /strbuf.c
parenta336401403ed55ca1956c627a5413e456b1f87e8 (diff)
Initial commit
Split Lua JSON from parent project to create standalone module. Remove unnecesssary files from new repo.
Diffstat (limited to 'strbuf.c')
-rw-r--r--strbuf.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/strbuf.c b/strbuf.c
new file mode 100644
index 0000000..f823884
--- /dev/null
+++ b/strbuf.c
@@ -0,0 +1,130 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "strbuf.h"
+
+static void die(const char *format, ...)
+{
+ va_list arg;
+
+ va_start(arg, format);
+ vfprintf(stderr, format, arg);
+ va_end(arg);
+
+ exit(-1);
+}
+
+void strbuf_init(strbuf_t *s)
+{
+ s->data = NULL;
+ s->size = 0;
+ s->length = 0;
+ s->increment = STRBUF_DEFAULT_INCREMENT;
+}
+
+strbuf_t *strbuf_new()
+{
+ strbuf_t *s;
+
+ s = malloc(sizeof(strbuf_t));
+ if (!s)
+ die("Out of memory");
+
+ strbuf_init(s);
+
+ return s;
+}
+
+void strbuf_set_increment(strbuf_t *s, int increment)
+{
+ if (increment <= 0)
+ die("BUG: Invalid string increment");
+
+ s->increment = increment;
+}
+
+void strbuf_free(strbuf_t *s)
+{
+ if (s->data)
+ free(s->data);
+ free(s);
+}
+
+char *strbuf_to_char(strbuf_t *s, int *len)
+{
+ char *data;
+
+ data = s->data;
+ if (len)
+ *len = s->length;
+
+ free(s);
+
+ return data;
+}
+
+/* Ensure strbuf can handle a string length bytes long (ignoring NULL
+ * optional termination). */
+void strbuf_resize(strbuf_t *s, int len)
+{
+ int newsize;
+
+ /* Esnure there is room for optional NULL termination */
+ newsize = len + 1;
+ /* Round up to the next increment */
+ newsize = ((newsize + s->increment - 1) / s->increment) * s->increment;
+ s->size = newsize;
+ s->data = realloc(s->data, s->size);
+ if (!s->data)
+ die("Out of memory");
+}
+
+void strbuf_append_mem(strbuf_t *s, const char *c, int len)
+{
+ if (len > strbuf_emptylen(s))
+ strbuf_resize(s, s->length + len);
+
+ memcpy(s->data + s->length, c, len);
+ s->length += len;
+}
+
+void strbuf_ensure_null(strbuf_t *s)
+{
+ s->data[s->length] = 0;
+}
+
+void strbuf_append_fmt(strbuf_t *s, const char *fmt, ...)
+{
+ va_list arg;
+ int fmt_len, try;
+ int empty_len;
+
+ /* If the first attempt to append fails, resize the buffer appropriately
+ * and try again */
+ for (try = 0; ; try++) {
+ va_start(arg, fmt);
+ /* Append the new formatted string */
+ /* fmt_len is the length of the string required, excluding the
+ * trailing NULL */
+ empty_len = strbuf_emptylen(s);
+ /* Add 1 since there is also space for the terminating NULL.
+ * If the string hasn't been allocated then empty_len == -1,
+ * and vsprintf() won't store anything on the first pass */
+ fmt_len = vsnprintf(s->data + s->length, empty_len + 1, fmt, arg);
+ va_end(arg);
+
+ if (fmt_len <= empty_len)
+ break; /* SUCCESS */
+ if (try > 0)
+ die("BUG: length of formatted string changed");
+
+ strbuf_resize(s, s->length + fmt_len);
+ }
+
+ s->length += fmt_len;
+}
+
+/* vi:ai et sw=4 ts=4:
+ */