134 lines
3.2 KiB
C
134 lines
3.2 KiB
C
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <px_common.h>
|
|
#include <px_msg_buf.h>
|
|
#include <px_log.h>
|
|
|
|
px_msg_buf_t* px_msg_buf_new(size_t sz) {
|
|
px_msg_buf_t* rbuf = PX_NEW_UNINITIALIZED(px_msg_buf_t);
|
|
if (!rbuf) {
|
|
int e = errno;
|
|
px_log_error("could not allocate response buffer: %s", strerror(e));
|
|
errno = e;
|
|
return NULL;
|
|
}
|
|
px_msg_buf_init(rbuf);
|
|
if (px_msg_buf_resize(rbuf, sz) != 0) {
|
|
free(rbuf);
|
|
return NULL;
|
|
}
|
|
memset((char*)rbuf->buf, 0, sz);
|
|
|
|
return rbuf;
|
|
}
|
|
|
|
void px_msg_buf_init(px_msg_buf_t* mbuf) {
|
|
if (!mbuf)
|
|
return;
|
|
memset(mbuf, 0, sizeof(*mbuf));
|
|
}
|
|
|
|
void px_msg_buf_use_external_buf(px_msg_buf_t* mbuf, char const* buf, size_t bufsz) {
|
|
if (mbuf->buf && !(mbuf->flags & PX_MSG_BUF_EXTERNAL))
|
|
free((void*)mbuf->buf);
|
|
mbuf->flags |= PX_MSG_BUF_EXTERNAL;
|
|
mbuf->buf = buf;
|
|
mbuf->buf_sz = bufsz;
|
|
}
|
|
|
|
int px_msg_buf_has_external_buf(px_msg_buf_t* mbuf) {
|
|
return mbuf->flags & PX_MSG_BUF_EXTERNAL;
|
|
}
|
|
|
|
void px_msg_buf_release_external_buf(px_msg_buf_t* mbuf) {
|
|
if (mbuf->flags & PX_MSG_BUF_EXTERNAL) {
|
|
mbuf->buf = NULL;
|
|
mbuf->buf_sz = 0;
|
|
mbuf->flags &= ~PX_MSG_BUF_EXTERNAL;
|
|
}
|
|
}
|
|
|
|
size_t px_msg_buf_resize(px_msg_buf_t* mbuf, size_t newsz) {
|
|
if (mbuf->flags & PX_MSG_BUF_EXTERNAL)
|
|
return mbuf->buf_sz;
|
|
char const* newbuf = (char const*)realloc((void*)mbuf->buf, newsz);
|
|
if (!newbuf)
|
|
return mbuf->buf_sz;
|
|
mbuf->buf = newbuf;
|
|
mbuf->buf_sz = newsz;
|
|
return newsz;
|
|
}
|
|
|
|
size_t px_msg_buf_grow(px_msg_buf_t* mbuf, size_t add) {
|
|
if (mbuf->flags & PX_MSG_BUF_EXTERNAL)
|
|
return mbuf->buf_sz;
|
|
size_t total = add + mbuf->buf_sz;
|
|
if (total < add) // overflow
|
|
return mbuf->buf_sz;
|
|
return px_msg_buf_resize(mbuf, total);
|
|
}
|
|
|
|
char const* px_msg_buf_get_buffer(px_msg_buf_t* mbuf) {
|
|
return mbuf->buf;
|
|
}
|
|
|
|
int px_msg_buf_is_writable(px_msg_buf_t* mbuf) {
|
|
return !(mbuf->flags & PX_MSG_BUF_EXTERNAL);
|
|
}
|
|
|
|
char* px_msg_buf_get_buffer_writable(px_msg_buf_t* mbuf) {
|
|
if (mbuf->flags & PX_MSG_BUF_EXTERNAL)
|
|
return NULL;
|
|
return (char*)mbuf->buf;
|
|
}
|
|
|
|
char const* px_msg_buf_pend_buffer(px_msg_buf_t* msg) {
|
|
msg->pending = msg->buf;
|
|
msg->pending_sz = msg->buf_sz;
|
|
return msg->pending;
|
|
}
|
|
|
|
char const* px_msg_buf_advance_pending(px_msg_buf_t* msg, size_t count) {
|
|
if (count > msg->pending_sz)
|
|
count = msg->pending_sz;
|
|
|
|
msg->pending += count;
|
|
msg->pending_sz -= count;
|
|
return msg->pending;
|
|
}
|
|
|
|
char const* px_msg_buf_update_pending(px_msg_buf_t* msg, size_t buf_offt, size_t pend_sz) {
|
|
// allow size_t(-1) to get whole remainder of buffer
|
|
if (pend_sz > msg->buf_sz)
|
|
pend_sz = msg->buf_sz;
|
|
|
|
if (buf_offt > msg->buf_sz
|
|
|| buf_offt + pend_sz < buf_offt) // overflow
|
|
return NULL;
|
|
|
|
if (buf_offt + pend_sz > msg->buf_sz) // don't go past the end of the buffer
|
|
pend_sz = msg->buf_sz - buf_offt;
|
|
|
|
msg->pending = msg->buf + buf_offt;
|
|
msg->pending_sz = pend_sz;
|
|
return msg->pending;
|
|
}
|
|
|
|
void px_msg_buf_destroy(px_msg_buf_t* mbuf) {
|
|
if (!mbuf)
|
|
return;
|
|
if (mbuf->flags & PX_MSG_BUF_EXTERNAL)
|
|
px_msg_buf_release_external_buf(mbuf);
|
|
else
|
|
free((void*)mbuf->buf);
|
|
px_msg_buf_init(mbuf);
|
|
}
|
|
|
|
void px_msg_buf_delete(px_msg_buf_t* mbuf) {
|
|
px_msg_buf_destroy(mbuf);
|
|
free(mbuf);
|
|
}
|
|
|