#include #include #include #include #include "dive.h" #include "membuffer.h" void free_buffer(struct membuffer *b) { free(b->buffer); b->buffer = NULL; b->len = 0; b->alloc = 0; } void flush_buffer(struct membuffer *b, FILE *f) { if (b->len) { fwrite(b->buffer, 1, b->len, f); free_buffer(b); } } void strip_mb(struct membuffer *b) { while (b->len && isspace(b->buffer[b->len - 1])) b->len--; } /* * 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->len + size; if (needed > b->alloc) { 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->alloc = needed; } } const char *mb_cstring(struct membuffer *b) { make_room(b, 1); b->buffer[b->len] = 0; return b->buffer; } void put_bytes(struct membuffer *b, const char *str, int len) { make_room(b, len); memcpy(b->buffer + b->len, str, len); b->len += 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); } void put_temperature(struct membuffer *b, temperature_t temp, const char *pre, const char *post) { if (temp.mkelvin) put_milli(b, pre, temp.mkelvin - ZERO_C_IN_MKELVIN, post); } void put_depth(struct membuffer *b, depth_t depth, const char *pre, const char *post) { if (depth.mm) put_milli(b, pre, depth.mm, post); } void put_duration(struct membuffer *b, duration_t duration, const char *pre, const char *post) { if (duration.seconds) put_format(b, "%s%u:%02u%s", pre, FRACTION(duration.seconds, 60), post); } void put_pressure(struct membuffer *b, pressure_t pressure, const char *pre, const char *post) { if (pressure.mbar) put_milli(b, pre, pressure.mbar, post); } void put_salinity(struct membuffer *b, int salinity, const char *pre, const char *post) { if (salinity) put_format(b, "%s%d%s", pre, salinity / 10, post); }