// Copyright (c) Vitaliy Filippov, 2019+ // License: VNPL-1.1 (see README.md for details) // // Efficient XDR implementation almost compatible with rpcgen (see run-rpcgen.sh) #include "xdr_impl_inline.h" XDR* xdr_create() { return new XDR; } void xdr_destroy(XDR* xdrs) { xdr_reset(xdrs); delete xdrs; } void xdr_reset(XDR *xdrs) { for (auto buf: xdrs->allocs) { free(buf); } xdrs->buf = NULL; xdrs->avail = 0; xdrs->allocs.resize(0); xdrs->in_linked_list.resize(0); xdrs->cur_out.resize(0); xdrs->last_end = 0; xdrs->buf_list.resize(0); } int xdr_decode(XDR *xdrs, void *buf, unsigned size, xdrproc_t fn, void *data) { xdrs->x_op = XDR_DECODE; xdrs->buf = (uint8_t*)buf; xdrs->avail = size; return fn(xdrs, data); } int xdr_encode(XDR *xdrs, xdrproc_t fn, void *data) { xdrs->x_op = XDR_ENCODE; return fn(xdrs, data); } void xdr_encode_finish(XDR *xdrs, iovec **iov_list, unsigned *iov_count) { if (xdrs->last_end < xdrs->cur_out.size()) { xdrs->buf_list.push_back((iovec){ .iov_base = 0, .iov_len = xdrs->cur_out.size() - xdrs->last_end, }); xdrs->last_end = xdrs->cur_out.size(); } uint8_t *cur_buf = xdrs->cur_out.data(); for (auto & buf: xdrs->buf_list) { if (!buf.iov_base) { buf.iov_base = cur_buf; cur_buf += buf.iov_len; } } *iov_list = xdrs->buf_list.data(); *iov_count = xdrs->buf_list.size(); } void xdr_dump_encoded(XDR *xdrs) { for (auto & buf: xdrs->buf_list) { for (int i = 0; i < buf.iov_len; i++) printf("%02x", ((uint8_t*)buf.iov_base)[i]); } printf("\n"); } void xdr_add_malloc(XDR *xdrs, void *buf) { xdrs->allocs.push_back(buf); } xdr_string_t xdr_copy_string(XDR *xdrs, const std::string & str) { char *cp = (char*)malloc_or_die(str.size()+1); memcpy(cp, str.data(), str.size()); cp[str.size()] = 0; xdr_add_malloc(xdrs, cp); return (xdr_string_t){ str.size(), cp }; } xdr_string_t xdr_copy_string(XDR *xdrs, const char *str) { return xdr_copy_string(xdrs, str, strlen(str)); } xdr_string_t xdr_copy_string(XDR *xdrs, const char *str, size_t len) { char *cp = (char*)malloc_or_die(len+1); memcpy(cp, str, len); cp[len] = 0; xdr_add_malloc(xdrs, cp); return (xdr_string_t){ len, cp }; }