108 lines
2.4 KiB
C++
108 lines
2.4 KiB
C++
|
// 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 };
|
||
|
}
|