diff options
| author | Mark Pulford <mark@kyne.com.au> | 2011-04-15 20:58:53 +0930 |
|---|---|---|
| committer | Mark Pulford <mark@kyne.com.au> | 2011-04-15 20:58:53 +0930 |
| commit | bbf1f5d35e8312fb7373a997664309adf9527af4 (patch) | |
| tree | 39dbd1d56cd730e07a27854adda504b8a120ce2f /strbuf.c | |
| parent | a336401403ed55ca1956c627a5413e456b1f87e8 (diff) | |
| download | lua-cjson-bbf1f5d35e8312fb7373a997664309adf9527af4.tar.gz lua-cjson-bbf1f5d35e8312fb7373a997664309adf9527af4.tar.bz2 lua-cjson-bbf1f5d35e8312fb7373a997664309adf9527af4.zip | |
Initial commit
Split Lua JSON from parent project to create standalone module.
Remove unnecesssary files from new repo.
Diffstat (limited to '')
| -rw-r--r-- | strbuf.c | 130 |
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 @@ | |||
| 1 | #include <stdio.h> | ||
| 2 | #include <stdlib.h> | ||
| 3 | #include <stdarg.h> | ||
| 4 | #include <string.h> | ||
| 5 | |||
| 6 | #include "strbuf.h" | ||
| 7 | |||
| 8 | static void die(const char *format, ...) | ||
| 9 | { | ||
| 10 | va_list arg; | ||
| 11 | |||
| 12 | va_start(arg, format); | ||
| 13 | vfprintf(stderr, format, arg); | ||
| 14 | va_end(arg); | ||
| 15 | |||
| 16 | exit(-1); | ||
| 17 | } | ||
| 18 | |||
| 19 | void strbuf_init(strbuf_t *s) | ||
| 20 | { | ||
| 21 | s->data = NULL; | ||
| 22 | s->size = 0; | ||
| 23 | s->length = 0; | ||
| 24 | s->increment = STRBUF_DEFAULT_INCREMENT; | ||
| 25 | } | ||
| 26 | |||
| 27 | strbuf_t *strbuf_new() | ||
| 28 | { | ||
| 29 | strbuf_t *s; | ||
| 30 | |||
| 31 | s = malloc(sizeof(strbuf_t)); | ||
| 32 | if (!s) | ||
| 33 | die("Out of memory"); | ||
| 34 | |||
| 35 | strbuf_init(s); | ||
| 36 | |||
| 37 | return s; | ||
| 38 | } | ||
| 39 | |||
| 40 | void strbuf_set_increment(strbuf_t *s, int increment) | ||
| 41 | { | ||
| 42 | if (increment <= 0) | ||
| 43 | die("BUG: Invalid string increment"); | ||
| 44 | |||
| 45 | s->increment = increment; | ||
| 46 | } | ||
| 47 | |||
| 48 | void strbuf_free(strbuf_t *s) | ||
| 49 | { | ||
| 50 | if (s->data) | ||
| 51 | free(s->data); | ||
| 52 | free(s); | ||
| 53 | } | ||
| 54 | |||
| 55 | char *strbuf_to_char(strbuf_t *s, int *len) | ||
| 56 | { | ||
| 57 | char *data; | ||
| 58 | |||
| 59 | data = s->data; | ||
| 60 | if (len) | ||
| 61 | *len = s->length; | ||
| 62 | |||
| 63 | free(s); | ||
| 64 | |||
| 65 | return data; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* Ensure strbuf can handle a string length bytes long (ignoring NULL | ||
| 69 | * optional termination). */ | ||
| 70 | void strbuf_resize(strbuf_t *s, int len) | ||
| 71 | { | ||
| 72 | int newsize; | ||
| 73 | |||
| 74 | /* Esnure there is room for optional NULL termination */ | ||
| 75 | newsize = len + 1; | ||
| 76 | /* Round up to the next increment */ | ||
| 77 | newsize = ((newsize + s->increment - 1) / s->increment) * s->increment; | ||
| 78 | s->size = newsize; | ||
| 79 | s->data = realloc(s->data, s->size); | ||
| 80 | if (!s->data) | ||
| 81 | die("Out of memory"); | ||
| 82 | } | ||
| 83 | |||
| 84 | void strbuf_append_mem(strbuf_t *s, const char *c, int len) | ||
| 85 | { | ||
| 86 | if (len > strbuf_emptylen(s)) | ||
| 87 | strbuf_resize(s, s->length + len); | ||
| 88 | |||
| 89 | memcpy(s->data + s->length, c, len); | ||
| 90 | s->length += len; | ||
| 91 | } | ||
| 92 | |||
| 93 | void strbuf_ensure_null(strbuf_t *s) | ||
| 94 | { | ||
| 95 | s->data[s->length] = 0; | ||
| 96 | } | ||
| 97 | |||
| 98 | void strbuf_append_fmt(strbuf_t *s, const char *fmt, ...) | ||
| 99 | { | ||
| 100 | va_list arg; | ||
| 101 | int fmt_len, try; | ||
| 102 | int empty_len; | ||
| 103 | |||
| 104 | /* If the first attempt to append fails, resize the buffer appropriately | ||
| 105 | * and try again */ | ||
| 106 | for (try = 0; ; try++) { | ||
| 107 | va_start(arg, fmt); | ||
| 108 | /* Append the new formatted string */ | ||
| 109 | /* fmt_len is the length of the string required, excluding the | ||
| 110 | * trailing NULL */ | ||
| 111 | empty_len = strbuf_emptylen(s); | ||
| 112 | /* Add 1 since there is also space for the terminating NULL. | ||
| 113 | * If the string hasn't been allocated then empty_len == -1, | ||
| 114 | * and vsprintf() won't store anything on the first pass */ | ||
| 115 | fmt_len = vsnprintf(s->data + s->length, empty_len + 1, fmt, arg); | ||
| 116 | va_end(arg); | ||
| 117 | |||
| 118 | if (fmt_len <= empty_len) | ||
| 119 | break; /* SUCCESS */ | ||
| 120 | if (try > 0) | ||
| 121 | die("BUG: length of formatted string changed"); | ||
| 122 | |||
| 123 | strbuf_resize(s, s->length + fmt_len); | ||
| 124 | } | ||
| 125 | |||
| 126 | s->length += fmt_len; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* vi:ai et sw=4 ts=4: | ||
| 130 | */ | ||
