summaryrefslogtreecommitdiff
path: root/src/lib/capnp-c/capn-malloc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/capnp-c/capn-malloc.cc')
-rw-r--r--src/lib/capnp-c/capn-malloc.cc424
1 files changed, 0 insertions, 424 deletions
diff --git a/src/lib/capnp-c/capn-malloc.cc b/src/lib/capnp-c/capn-malloc.cc
deleted file mode 100644
index 79f08c8..0000000
--- a/src/lib/capnp-c/capn-malloc.cc
+++ /dev/null
@@ -1,424 +0,0 @@
-/* vim: set sw=8 ts=8 sts=8 noet: */
-/* capn-malloc.c
- *
- * Copyright (C) 2013 James McKaskill
- * Copyright (C) 2014 Steve Dee
- *
- * This software may be modified and distributed under the terms
- * of the MIT license. See the LICENSE file for details.
- */
-
-#ifdef __GNUC__
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#endif
-
-#include "capnp_c.h"
-#include "capnp_priv.h"
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include <errno.h>
-
-#ifdef MULTIPASS_TRACE_MALLOC
-#include "lib/mpmalloc.h"
-#else
-#define mpcalloc calloc
-#define mpfree free
-#endif
-
-/*
- * 8 byte alignment is required for struct capn_segment.
- * This struct check_segment_alignment verifies this at compile time.
- *
- * Unless capn_segment is defined with 8 byte alignment, check_segment_alignment
- * fails to compile in x86 mode (or on another CPU with 32-bit pointers),
- * as (sizeof(struct capn_segment)&7) -> (44 & 7) evaluates to 4.
- * It compiles in x64 mode (or on another CPU with 64-bit pointers),
- * as (sizeof(struct capn_segment)&7) -> (80 & 7) evaluates to 0.
- */
-struct check_segment_alignment {
- unsigned int foo : (sizeof(struct capn_segment)&7) ? -1 : 1;
-};
-
-static struct capn_segment *create(void *u, uint32_t id, int sz) {
- struct capn_segment *s;
- sz += sizeof(*s);
-#if 0
- if (sz < 1024) {
- sz = 1024;
- } else {
- sz = (sz + 1023) & ~1023;
- }
-#else
- if (sz < 4096) {
- sz = 4096;
- } else {
- sz = (sz + 4095) & ~4095;
- }
-#endif
- s = (struct capn_segment*) mpcalloc(1, sz);
- s->data = (char*) (s+1);
- s->cap = sz - sizeof(*s);
- s->user = s;
- return s;
-}
-
-static struct capn_segment *create_local(void *u, int sz) {
- return create(u, 0, sz);
-}
-
-void capn_init_malloc(struct capn *c) {
- memset(c, 0, sizeof(*c));
- c->create = &create;
- c->create_local = &create_local;
-}
-
-void capn_free(struct capn *c) {
- struct capn_segment *s = c->seglist;
- while (s != NULL) {
- struct capn_segment *n = s->next;
- mpfree(s->user);
- s = n;
- }
- capn_reset_copy(c);
-}
-
-void capn_reset_copy(struct capn *c) {
- struct capn_segment *s = c->copylist;
- while (s != NULL) {
- struct capn_segment *n = s->next;
- mpfree(s->user);
- s = n;
- }
- c->copy = NULL;
- c->copylist = NULL;
-}
-
-#define ZBUF_SZ 4096
-
-static int read_fp(void *p, size_t sz, FILE *f, struct capn_stream *z, uint8_t* zbuf, int packed) {
- if (f && packed) {
- z->next_out = (uint8_t*) p;
- z->avail_out = sz;
-
- while (z->avail_out && capn_inflate(z) == CAPN_NEED_MORE) {
- int r;
- memmove(zbuf, z->next_in, z->avail_in);
- r = fread(zbuf+z->avail_in, 1, ZBUF_SZ - z->avail_in, f);
- if (r <= 0)
- return -1;
- z->avail_in += r;
- }
- return 0;
-
- } else if (f && !packed) {
- return fread(p, sz, 1, f) != 1;
-
- } else if (packed) {
- z->next_out = (uint8_t*) p;
- z->avail_out = sz;
- return capn_inflate(z) != 0;
-
- } else {
- if (z->avail_in < sz)
- return -1;
- memcpy(p, z->next_in, sz);
- z->next_in += sz;
- z->avail_in -= sz;
- return 0;
- }
-}
-
-static int init_fp(struct capn *c, FILE *f, struct capn_stream *z, int packed) {
- /*
- * Initialize 'c' from the contents of 'f', assuming the message has been
- * serialized with the standard framing format. From https://capnproto.org/encoding.html:
- *
- * When transmitting over a stream, the following should be sent. All integers are unsigned and little-endian.
- * (4 bytes) The number of segments, minus one (since there is always at least one segment).
- * (N * 4 bytes) The size of each segment, in words.
- * (0 or 4 bytes) Padding up to the next word boundary.
- * The content of each segment, in order.
- */
-
- struct capn_segment *s = NULL;
- uint32_t i, segnum, total = 0;
- uint32_t hdr[1024];
- uint8_t zbuf[ZBUF_SZ];
- char *data = NULL;
-
- capn_init_malloc(c);
-
- /* Read the first four bytes to know how many headers we have */
- if (read_fp(&segnum, 4, f, z, zbuf, packed))
- goto err;
-
- segnum = capn_flip32(segnum);
- if (segnum > 1023)
- goto err;
- segnum++; /* The wire encoding was zero-based */
-
- /* Read the header list */
- if (read_fp(hdr, 8 * (segnum/2) + 4, f, z, zbuf, packed))
- goto err;
-
- for (i = 0; i < segnum; i++) {
- uint32_t n = capn_flip32(hdr[i]);
- if (n > INT_MAX/8 || n > UINT32_MAX/8 || UINT32_MAX - total < n*8)
- goto err;
- hdr[i] = n*8;
- total += hdr[i];
- }
-
- /* Allocate space for the data and the capn_segment structs */
- s = (struct capn_segment*) mpcalloc(1, total + (sizeof(*s) * segnum));
- if (!s)
- goto err;
-
- /* Now read the data and setup the capn_segment structs */
- data = (char*) (s+segnum);
- if (read_fp(data, total, f, z, zbuf, packed))
- goto err;
-
- for (i = 0; i < segnum; i++) {
- s[i].len = s[i].cap = hdr[i];
- s[i].data = data;
- data += s[i].len;
- capn_append_segment(c, &s[i]);
- }
-
- /* Set the entire region to be freed on the last segment */
- s[segnum-1].user = s;
-
- return 0;
-
-err:
- memset(c, 0, sizeof(*c));
- mpfree(s);
- return -1;
-}
-
-int capn_init_fp(struct capn *c, FILE *f, int packed) {
- struct capn_stream z;
- memset(&z, 0, sizeof(z));
- return init_fp(c, f, &z, packed);
-}
-
-int capn_init_mem(struct capn *c, const uint8_t *p, size_t sz, int packed) {
- struct capn_stream z;
- memset(&z, 0, sizeof(z));
- z.next_in = p;
- z.avail_in = sz;
- return init_fp(c, NULL, &z, packed);
-}
-
-static void header_calc(struct capn *c, uint32_t *headerlen, size_t *headersz)
-{
- /* segnum == 1:
- * [segnum][segsiz]
- * segnum == 2:
- * [segnum][segsiz][segsiz][zeroes]
- * segnum == 3:
- * [segnum][segsiz][segsiz][segsiz]
- * segnum == 4:
- * [segnum][segsiz][segsiz][segsiz][segsiz][zeroes]
- */
- *headerlen = ((2 + c->segnum) / 2) * 2;
- *headersz = 4 * *headerlen;
-}
-
-static int header_render(struct capn *c, struct capn_segment *seg, uint32_t *header, uint32_t headerlen, size_t *datasz)
-{
- size_t i;
-
- header[0] = capn_flip32(c->segnum - 1);
- header[headerlen-1] = 0; /* Zero out the spare position in the header sizes */
- for (i = 0; i < c->segnum; i++, seg = seg->next) {
- if (0 == seg)
- return -1;
- *datasz += seg->len;
- header[1 + i] = capn_flip32(seg->len / 8);
- }
- if (0 != seg)
- return -1;
-
- return 0;
-}
-
-static int capn_write_mem_packed(struct capn *c, uint8_t *p, size_t sz)
-{
- struct capn_segment *seg;
- struct capn_ptr root;
- uint32_t headerlen;
- size_t headersz, datasz = 0;
- uint32_t *header;
- struct capn_stream z;
- int ret;
-
- root = capn_root(c);
- header_calc(c, &headerlen, &headersz);
- header = (uint32_t*) (p + headersz + 2); /* must reserve two bytes for worst case expansion */
-
- if (sz < headersz*2 + 2) /* We must have space for temporary writing of header to deflate */
- return -1;
-
- ret = header_render(c, root.seg, header, headerlen, &datasz);
- if (ret != 0)
- return -1;
-
- memset(&z, 0, sizeof(z));
- z.next_in = (uint8_t *)header;
- z.avail_in = headersz;
- z.next_out = p;
- z.avail_out = sz;
-
- // pack the headers
- ret = capn_deflate(&z);
- if (ret != 0 || z.avail_in != 0)
- return -1;
-
- for (seg = root.seg; seg; seg = seg->next) {
- z.next_in = (uint8_t *)seg->data;
- z.avail_in = seg->len;
- ret = capn_deflate(&z);
- if (ret != 0 || z.avail_in != 0)
- return -1;
- }
-
- return sz - z.avail_out;
-}
-
-int
-capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed)
-{
- struct capn_segment *seg;
- struct capn_ptr root;
- uint32_t headerlen;
- size_t headersz, datasz = 0;
- uint32_t *header;
- int ret;
-
- if (c->segnum == 0)
- return -1;
-
- if (packed)
- return capn_write_mem_packed(c, p, sz);
-
- root = capn_root(c);
- header_calc(c, &headerlen, &headersz);
- header = (uint32_t*) p;
-
- if (sz < headersz)
- return -1;
-
- ret = header_render(c, root.seg, header, headerlen, &datasz);
- if (ret != 0)
- return -1;
-
- if (sz < headersz + datasz)
- return -1;
-
- p += headersz;
-
- for (seg = root.seg; seg; seg = seg->next) {
- memcpy(p, seg->data, seg->len);
- p += seg->len;
- }
-
- return headersz+datasz;
-}
-
-static int _write_fd(ssize_t (*write_fd)(int fd, const void *p, size_t count), int fd, void *p, size_t count)
-{
- ssize_t ret;
- size_t sent = 0;
-
- while (sent < count) {
- ret = write_fd(fd, ((uint8_t*)p)+sent, count-sent);
- if (ret < 0) {
- if (errno == EAGAIN || errno == EINTR)
- continue;
- else
- return -1;
- }
- sent += ret;
- }
-
- return 0;
-}
-
-int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, const void *p, size_t count), int fd, int packed)
-{
- unsigned char buf[4096];
- struct capn_segment *seg;
- struct capn_ptr root;
- uint32_t headerlen;
- size_t headersz, datasz = 0;
- int ret;
- struct capn_stream z;
- unsigned char *p;
-
- if (c->segnum == 0)
- return -1;
-
- root = capn_root(c);
- header_calc(c, &headerlen, &headersz);
-
- if (sizeof(buf) < headersz)
- return -1;
-
- ret = header_render(c, root.seg, (uint32_t*)buf, headerlen, &datasz);
- if (ret != 0)
- return -1;
-
- if (packed) {
- const int headerrem = sizeof(buf) - headersz;
- const int maxpack = headersz + 2;
- if (headerrem < maxpack)
- return -1;
-
- memset(&z, 0, sizeof(z));
- z.next_in = buf;
- z.avail_in = headersz;
- z.next_out = buf + headersz;
- z.avail_out = headerrem;
- ret = capn_deflate(&z);
- if (ret != 0)
- return -1;
-
- p = buf + headersz;
- headersz = headerrem - z.avail_out;
- } else {
- p = buf;
- }
-
- ret = _write_fd(write_fd, fd, p, headersz);
- if (ret < 0)
- return -1;
-
- datasz = headersz;
- for (seg = root.seg; seg; seg = seg->next) {
- size_t bufsz;
- if (packed) {
- memset(&z, 0, sizeof(z));
- z.next_in = (uint8_t*)seg->data;
- z.avail_in = seg->len;
- z.next_out = buf;
- z.avail_out = sizeof(buf);
- ret = capn_deflate(&z);
- if (ret != 0)
- return -1;
- p = buf;
- bufsz = sizeof(buf) - z.avail_out;
- } else {
- p = (uint8_t*)seg->data;
- bufsz = seg->len;
- }
- ret = _write_fd(write_fd, fd, p, bufsz);
- if (ret < 0)
- return -1;
- datasz += bufsz;
- }
-
- return datasz;
-}