diff --git a/include/libwebsockets/lws-misc.h b/include/libwebsockets/lws-misc.h index d8519d297..0b2df96c1 100644 --- a/include/libwebsockets/lws-misc.h +++ b/include/libwebsockets/lws-misc.h @@ -109,6 +109,47 @@ LWS_VISIBLE LWS_EXTERN int lws_buflist_linear_copy(struct lws_buflist **head, size_t ofs, uint8_t *buf, size_t len); +/** + * lws_buflist_linear_use(): copy and consume from buflist head + * + * \param head: list head + * \param buf: buffer to copy linearly into + * \param len: length of buffer available + * + * Copies a possibly fragmented buflist from the head into the linear output + * buffer \p buf for up to length \p len, and consumes the buflist content that + * was copied out. + * + * Since it was consumed, calling again will resume copying out and consuming + * from as far as it got the first time. + * + * Returns the number of bytes written into \p buf. + */ +LWS_VISIBLE LWS_EXTERN int +lws_buflist_linear_use(struct lws_buflist **head, uint8_t *buf, size_t len); + +/** + * lws_buflist_fragment_use(): copy and consume <= 1 frag from buflist head + * + * \param head: list head + * \param buf: buffer to copy linearly into + * \param len: length of buffer available + * \param frag_first: pointer to char written on exit to if this is start of frag + * \param frag_fin: pointer to char written on exit to if this is end of frag + * + * Copies all or part of the fragment at the start of a buflist from the head + * into the output buffer \p buf for up to length \p len, and consumes the + * buflist content that was copied out. + * + * Since it was consumed, calling again will resume copying out and consuming + * from as far as it got the first time. + * + * Returns the number of bytes written into \p buf. + */ +LWS_VISIBLE LWS_EXTERN int +lws_buflist_fragment_use(struct lws_buflist **head, uint8_t *buf, + size_t len, char *frag_first, char *frag_fin); + /** * lws_buflist_destroy_all_segments(): free all segments on the list * diff --git a/lib/core/buflist.c b/lib/core/buflist.c index 0a9d69fc5..8f2f25361 100644 --- a/lib/core/buflist.c +++ b/lib/core/buflist.c @@ -197,6 +197,54 @@ lws_buflist_linear_copy(struct lws_buflist **head, size_t ofs, uint8_t *buf, return lws_ptr_diff(buf, obuf); } +int +lws_buflist_linear_use(struct lws_buflist **head, uint8_t *buf, size_t len) +{ + uint8_t *obuf = buf; + size_t s; + + while (*head && len) { + s = (*head)->len - (*head)->pos; + if (s > len) + s = len; + memcpy(buf, ((uint8_t *)((*head) + 1)) + + LWS_PRE + (*head)->pos, s); + len -= s; + buf += s; + lws_buflist_use_segment(head, s); + } + + return lws_ptr_diff(buf, obuf); +} + +int +lws_buflist_fragment_use(struct lws_buflist **head, uint8_t *buf, + size_t len, char *frag_first, char *frag_fin) +{ + uint8_t *obuf = buf; + size_t s; + + if (!*head) + return 0; + + s = (*head)->len - (*head)->pos; + if (s > len) + s = len; + + if (frag_first) + *frag_first = !(*head)->pos; + + if (frag_fin) + *frag_fin = (*head)->pos + s == (*head)->len; + + memcpy(buf, ((uint8_t *)((*head) + 1)) + LWS_PRE + (*head)->pos, s); + len -= s; + buf += s; + lws_buflist_use_segment(head, s); + + return lws_ptr_diff(buf, obuf); +} + #if defined(_DEBUG) void lws_buflist_describe(struct lws_buflist **head, void *id, const char *reason)