#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include "buffer.h" void zpm_buffer_init(struct zpm_buffer *buffer) { buffer->buffer = 0; buffer->len = 0; buffer->size = 0; buffer->error = 0; } void zpm_buffer_compact(struct zpm_buffer *b) { void *new; if (b->error || b->size == b->len) { return; } errno = 0; new = realloc(b->buffer, b->len); if (new == NULL) { b->error = errno; return; } b->buffer = new; return; } /* makes sure there's at least need bytes free */ void zpm_buffer_expand(struct zpm_buffer *buf, size_t need) { size_t want; if (buf->error) { return; } want = buf->len + need; if (want <= buf->size) { return; } errno = 0; char *new = realloc(buf->buffer, want); if (new) { buf->buffer = new; buf->size = want; memset(buf->buffer + buf->len, 0, buf->size - buf->len); } else { buf->error = errno; } } void zpm_buffer_free(struct zpm_buffer *buffer) { /* TODO only zero out memory if it's "secure" buffer */ if (buffer->buffer && buffer->len) { memset(buffer->buffer, 0, buffer->len); } free(buffer->buffer); zpm_buffer_init(buffer); } void zpm_buffer_set(struct zpm_buffer *buffer, int ch) { /* TODO only zero out memory if it's "secure" buffer */ if (buffer->buffer && buffer->size) { memset(buffer->buffer, ch, buffer->size); } } void zpm_buffer_appendvf(struct zpm_buffer *buf, const char *fmt, va_list ap) { int len; va_list ar; va_copy(ar, ap); len = vsnprintf(0, 0, fmt, ar); va_end(ar); zpm_buffer_expand(buf, len+1); vsprintf(buf->buffer + buf->len, fmt, ap); } void zpm_buffer_appendf(struct zpm_buffer *buf, const char *fmt, ...) { va_list ap; int len; va_start(ap, fmt); len = vsnprintf(0, 0, fmt, ap); va_end(ap); zpm_buffer_expand(buf, len+1); va_start(ap, fmt); vsprintf(buf->buffer + buf->len, fmt, ap); va_end(ap); } void zpm_buffer_append(struct zpm_buffer *buffer, const unsigned char *bytes, size_t n) { zpm_buffer_expand(buffer, n); if (buffer->error || !bytes) { return; } memcpy(buffer->buffer + buffer->len, bytes, n); buffer->len += n; } void zpm_buffer_append_str(struct zpm_buffer *buf, const char *s) { zpm_buffer_append(buf, (const unsigned char *)s, strlen(s)); } void zpm_buffer_append16(struct zpm_buffer *buffer, uint16_t n) { zpm_buffer_expand(buffer, 2); if (buffer->error) { return; } buffer->buffer[buffer->len++] = (n >> 8) & 0xff; buffer->buffer[buffer->len++] = n & 0xff; } void zpm_buffer_append24(struct zpm_buffer *buffer, uint32_t n) { zpm_buffer_expand(buffer, 3); if (buffer->error) { return; } buffer->buffer[buffer->len++] = (n >> 16) & 0xff; buffer->buffer[buffer->len++] = (n >> 8) & 0xff; buffer->buffer[buffer->len++] = n & 0xff; } void zpm_buffer_append_byte(struct zpm_buffer *buffer, uint8_t n) { zpm_buffer_expand(buffer, 1); if (buffer->error) { return; } buffer->buffer[buffer->len++] = n & 0xff; } void zpm_buffer_write16(struct zpm_buffer *buffer, uint16_t n, size_t at) { if (at+2 > buffer->size) { zpm_buffer_expand(buffer, at+2 - buffer->size); } if (buffer->error) { return; } buffer->buffer[at] = (n >> 8) & 0xff; buffer->buffer[at+1] = n & 0xff; if (at+2 > buffer->len) { buffer->len = at + 2; } } uint16_t zpm_buffer_read16(struct zpm_buffer *buffer, size_t at) { uint16_t res = 0; if (buffer->error || at+2 < buffer->len) { return 0; } res = (buffer->buffer[at] << 8) + buffer->buffer[at+1]; return res; } uint64_t zpm_buffer_readbe(struct zpm_buffer *buffer, int bytes, size_t at) { uint16_t res = 0; int i; if (buffer->error || at+bytes < buffer->len) { return 0; } for (i=0; ibuffer[at+i]; } return res; } void zpm_buffer_writebe(struct zpm_buffer *buffer, int bytes, size_t at, uint64_t val) { int i; if (at+bytes > buffer->size) { zpm_buffer_expand(buffer, at+bytes - buffer->size); } if (buffer->error) { return; } for (i=bytes-1; i>=0; i--) { buffer->buffer[at+i] = val & 0xff; val >>= 8; } return; } void zpm_buffer_shift(struct zpm_buffer *buffer, size_t n) { if (buffer->error) { return; } if (buffer->len < n) { n = buffer->len; } if (n) { memmove(buffer->buffer, buffer->buffer + n, buffer->len - n); memset(buffer->buffer + buffer->len - n, 0, n); #if 0 fprintf(stderr, "memmove(%p, %p, %zu)\n", buffer->buffer, buffer->buffer+n, buffer->len - n); fprintf(stderr, "memset(%p, %d, %zu)\n", buffer->buffer+n, 0, n); #endif buffer->len -= n; } } /* make room at the beginning */ void zpm_buffer_unshift(struct zpm_buffer *buffer, size_t n) { zpm_buffer_expand(buffer, n); if (buffer->error) { return; } memmove(buffer->buffer + n, buffer->buffer, n); memset(buffer->buffer, 0, n); } #if 0 uint32_t zpm_buffer_next3(struct zpm_buffer_reader *rb) { uint32_t r; r = zpm_buffer_readbe(rb, 3, rb->cursor); rb->cursor += 3; return r; } uint16_t zpm_buffer_next2(struct zpm_buffer_reader *rb) { uint16_t r; r = zpm_buffer_readbe(rb, 2, rb->cursor); rb->cursor += 2; return r; } uint8_t zpm_buffer_next(struct zpm_buffer_reader *rb) { uint16_t r; r = zpm_buffer_readbe(rb, 2, rb->cursor); rb->cursor += 2; } void zpm_buffer_nextn(struct zpm_buffer_reader *rb, unsigned char *b, size_t n) { zpm_buffer_read(rb, b, n, rb->cursor); rb->cursor += n; } #endif