diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-16 09:03:11 +0700 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2014-01-16 12:51:23 +0700 |
commit | 96a4fd1bb223d646bb3f3c8b9d4d0800ebe49e13 (patch) | |
tree | ccab6808c0f791790ad3662a836f451c90dad2c7 /membuffer.c | |
parent | 2e08f75618e6ff86e37de5e1ee0100a31cc8efb7 (diff) | |
download | subsurface-96a4fd1bb223d646bb3f3c8b9d4d0800ebe49e13.tar.gz |
Save XML files into a memory buffer rather than directly into a file
This introduces a "struct membuffer" abstraction that you can write
things into, and makes the XML saving code write to the memory buffer
rather than a file.
The UDDF export already really wanted this: it used to write to a file,
only to then read that file back into memory, delete the file, and then
*rewrite* the file after doing the magic xslt transform.
But the longer-term reason for this is that I want to try to write other
formats, and I want to try to share most helpers. And those other
formats will need this memory buffer model.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'membuffer.c')
-rw-r--r-- | membuffer.c | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/membuffer.c b/membuffer.c new file mode 100644 index 000000000..30ba05fdb --- /dev/null +++ b/membuffer.c @@ -0,0 +1,160 @@ +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "dive.h" +#include "membuffer.h" + +void free_buffer(struct membuffer *b) +{ + free(b->buffer); + b->buffer = NULL; + b->used = 0; + b->size = 0; +} + +void flush_buffer(struct membuffer *b, FILE *f) +{ + if (b->used) { + fwrite(b->buffer, 1, b->used, f); + free_buffer(b); + } +} + +/* + * Running out of memory isn't really an issue these days. + * So rather than do insane error handling and making the + * interface very complex, we'll just die. It won't happen + * unless you're running on a potato. + */ +static void oom(void) +{ + fprintf(stderr, "Out of memory\n"); + exit(1); +} + +static void make_room(struct membuffer *b, unsigned int size) +{ + unsigned int needed = b->used + size; + if (needed > b->size) { + char *n; + /* round it up to not reallocate all the time.. */ + needed = needed * 9 / 8 + 1024; + n = realloc(b->buffer, needed); + if (!n) + oom(); + b->buffer = n; + b->size = needed; + } +} + +void put_bytes(struct membuffer *b, const char *str, int len) +{ + make_room(b, len); + memcpy(b->buffer + b->used, str, len); + b->used += len; +} + +void put_string(struct membuffer *b, const char *str) +{ + put_bytes(b, str, strlen(str)); +} + +void put_vformat(struct membuffer *b, const char *fmt, va_list args) +{ + /* Handle the common case on the stack */ + char buffer[128], *p; + int len; + + len = vsnprintf(buffer, sizeof(buffer), fmt, args); + if (len <= sizeof(buffer)) { + put_bytes(b, buffer, len); + return; + } + + p = malloc(len); + len = vsnprintf(p, len, fmt, args); + put_bytes(b, p, len); + free(p); +} + +void put_format(struct membuffer *b, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + put_vformat(b, fmt, args); + va_end(args); +} + +void put_milli(struct membuffer *b, const char *pre, int value, const char *post) +{ + int i; + char buf[4]; + const char *sign = ""; + unsigned v; + + v = value; + if (value < 0) { + sign = "-"; + v = -value; + } + for (i = 2; i >= 0; i--) { + buf[i] = (v % 10) + '0'; + v /= 10; + } + buf[3] = 0; + if (buf[2] == '0') { + buf[2] = 0; + if (buf[1] == '0') + buf[1] = 0; + } + + put_format(b, "%s%s%u.%s%s", pre, sign, v, buf, post); +} + +int put_temperature(struct membuffer *b, temperature_t temp, const char *pre, const char *post) +{ + if (!temp.mkelvin) + return 0; + + put_milli(b, pre, temp.mkelvin - ZERO_C_IN_MKELVIN, post); + return 1; +} + +int put_depth(struct membuffer *b, depth_t depth, const char *pre, const char *post) +{ + if (!depth.mm) + return 0; + + put_milli(b, pre, depth.mm, post); + return 1; +} + +int put_duration(struct membuffer *b, duration_t duration, const char *pre, const char *post) +{ + if (!duration.seconds) + return 0; + + put_format(b, "%s%u:%02u%s", pre, FRACTION(duration.seconds, 60), post); + return 1; +} + +int put_pressure(struct membuffer *b, pressure_t pressure, const char *pre, const char *post) +{ + if (!pressure.mbar) + return 0; + + put_milli(b, pre, pressure.mbar, post); + return 1; +} + +int put_salinity(struct membuffer *b, int salinity, const char *pre, const char *post) +{ + if (!salinity) + return 0; + + put_format(b, "%s%d%s", pre, salinity / 10, post); + return 1; +} |