From 2bdc5c476a19aa5c7ca6a35d262d95da88e1c095 Mon Sep 17 00:00:00 2001 From: Baruch Even Date: Thu, 7 Aug 2014 17:56:51 +0300 Subject: [PATCH] Implement capn_write_fd --- capn-malloc.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ capn.h | 1 + 2 files changed, 97 insertions(+) diff --git a/capn-malloc.c b/capn-malloc.c index 5d6e882..41588db 100644 --- a/capn-malloc.c +++ b/capn-malloc.c @@ -3,6 +3,7 @@ #include #include #include +#include struct check_segment_alignment { unsigned int foo : (sizeof(struct capn_segment)&7) ? -1 : 1; @@ -276,3 +277,98 @@ capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed) return headersz+datasz; } + +static int _write_fd(ssize_t (*write_fd)(int fd, void *p, size_t count), int fd, void *p, size_t count) +{ + int ret; + int 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, 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; +} diff --git a/capn.h b/capn.h index e24aca2..4e5bc57 100644 --- a/capn.h +++ b/capn.h @@ -246,6 +246,7 @@ int capn_init_mem(struct capn *c, const uint8_t *p, size_t sz, int packed); */ /* TODO */ /*int capn_write_fp(struct capn *c, FILE *f, int packed);*/ +int capn_write_fd(struct capn *c, ssize_t (*write_fd)(int fd, void *p, size_t count), int fd, int packed); int capn_write_mem(struct capn *c, uint8_t *p, size_t sz, int packed); void capn_free(struct capn *c);