diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index cdb5e17b3..721728b30 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -75,6 +75,31 @@ lws_buflist_next_segment_len(struct lws_buflist **head, uint8_t **buf); LWS_VISIBLE LWS_EXTERN int lws_buflist_use_segment(struct lws_buflist **head, size_t len); +/** + * lws_buflist_total_len(): Get the total size of the buflist + * + * \param head: list head + * + * Returns the total number of bytes held on all segments of the buflist + */ +LWS_VISIBLE LWS_EXTERN size_t +lws_buflist_total_len(struct lws_buflist **head); + +/** + * lws_buflist_linear_copy(): copy everything out as one without consuming + * + * \param head: list head + * \param ofs: start offset into buflist in bytes + * \param buf: buffer to copy linearly into + * \param len: length of buffer available + * + * Returns -1 if len is too small, or bytes copied. Happy to do partial + * copies, returns 0 when there are no more bytes to copy. + */ +LWS_VISIBLE LWS_EXTERN int +lws_buflist_linear_copy(struct lws_buflist **head, size_t ofs, uint8_t *buf, + size_t len); + /** * lws_buflist_destroy_all_segments(): free all segments on the list * diff --git a/lib/core/buflist.c b/lib/core/buflist.c index bb86b4cc5..393a018b2 100644 --- a/lib/core/buflist.c +++ b/lib/core/buflist.c @@ -158,6 +158,45 @@ lws_buflist_use_segment(struct lws_buflist **head, size_t len) return lws_buflist_next_segment_len(head, NULL); } +size_t +lws_buflist_total_len(struct lws_buflist **head) +{ + struct lws_buflist *p = *head; + size_t size = 0; + + while (p) { + size += p->len; + p = p->next; + } + + return size; +} + +int +lws_buflist_linear_copy(struct lws_buflist **head, size_t ofs, uint8_t *buf, + size_t len) +{ + struct lws_buflist *p = *head; + uint8_t *obuf = buf; + size_t s; + + while (p && len) { + if (ofs < p->len) { + s = p->len - ofs; + if (s > len) + s = len; + memcpy(buf, ((uint8_t *)&p[1]) + ofs, s); + len -= s; + buf += s; + ofs = 0; + } else + ofs -= p->len; + p = p->next; + } + + return lws_ptr_diff(buf, obuf); +} + #if defined(_DEBUG) void lws_buflist_describe(struct lws_buflist **head, void *id, const char *reason)