mirror of
https://git.savannah.nongnu.org/git/lwip.git
synced 2025-08-08 23:44:39 +08:00
pbuf: Add pbuf_copy_partial_pbuf library function
Like pbuf_copy, but can copy part of a pbuf to an offset in another. pbuf_copy now uses this function internally. Signed-off-by: Simon Goldschmidt <goldsimon@gmx.de>
This commit is contained in:
parent
1c6202c414
commit
843a116155
@ -960,54 +960,88 @@ pbuf_dechain(struct pbuf *p)
|
|||||||
err_t
|
err_t
|
||||||
pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
|
pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from)
|
||||||
{
|
{
|
||||||
size_t offset_to = 0, offset_from = 0, len;
|
|
||||||
|
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
|
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy(%p, %p)\n",
|
||||||
(const void *)p_to, (const void *)p_from));
|
(const void *)p_to, (const void *)p_from));
|
||||||
|
|
||||||
|
LWIP_ERROR("pbuf_copy: invalid source", p_from != NULL, return ERR_ARG;);
|
||||||
|
return pbuf_copy_partial_pbuf(p_to, p_from, p_from->tot_len, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup pbuf
|
||||||
|
* Copy part or all of one packet buffer into another, to a specified offset.
|
||||||
|
*
|
||||||
|
* @note Only data in one packet is copied, no packet queue!
|
||||||
|
* @note Argument order is shared with pbuf_copy, but different than pbuf_copy_partial.
|
||||||
|
*
|
||||||
|
* @param p_to pbuf destination of the copy
|
||||||
|
* @param p_from pbuf source of the copy
|
||||||
|
* @param copy_len number of bytes to copy
|
||||||
|
* @param offset offset in destination pbuf where to copy to
|
||||||
|
*
|
||||||
|
* @return ERR_OK if copy_len bytes were copied
|
||||||
|
* ERR_ARG if one of the pbufs is NULL or p_from is shorter than copy_len
|
||||||
|
* or p_to is not big enough to hold copy_len at offset
|
||||||
|
* ERR_VAL if any of the pbufs are part of a queue
|
||||||
|
*/
|
||||||
|
err_t
|
||||||
|
pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset)
|
||||||
|
{
|
||||||
|
size_t offset_to = offset, offset_from = 0, len_calc;
|
||||||
|
u16_t len;
|
||||||
|
|
||||||
|
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf(%p, %p, %"U16_F", %"U16_F")\n",
|
||||||
|
(const void *)p_to, (const void *)p_from, copy_len, offset));
|
||||||
|
|
||||||
|
/* is the copy_len in range? */
|
||||||
|
LWIP_ERROR("pbuf_copy_partial_pbuf: copy_len bigger than source", ((p_from != NULL) &&
|
||||||
|
(p_from->tot_len >= copy_len)), return ERR_ARG;);
|
||||||
/* is the target big enough to hold the source? */
|
/* is the target big enough to hold the source? */
|
||||||
LWIP_ERROR("pbuf_copy: target not big enough to hold source", ((p_to != NULL) &&
|
LWIP_ERROR("pbuf_copy_partial_pbuf: target not big enough", ((p_to != NULL) &&
|
||||||
(p_from != NULL) && (p_to->tot_len >= p_from->tot_len)), return ERR_ARG;);
|
(p_to->tot_len >= (offset + copy_len))), return ERR_ARG;);
|
||||||
|
|
||||||
/* iterate through pbuf chain */
|
/* iterate through pbuf chain */
|
||||||
do {
|
do {
|
||||||
/* copy one part of the original chain */
|
/* copy one part of the original chain */
|
||||||
if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
|
if ((p_to->len - offset_to) >= (p_from->len - offset_from)) {
|
||||||
/* complete current p_from fits into current p_to */
|
/* complete current p_from fits into current p_to */
|
||||||
len = p_from->len - offset_from;
|
len_calc = p_from->len - offset_from;
|
||||||
} else {
|
} else {
|
||||||
/* current p_from does not fit into current p_to */
|
/* current p_from does not fit into current p_to */
|
||||||
len = p_to->len - offset_to;
|
len_calc = p_to->len - offset_to;
|
||||||
}
|
}
|
||||||
|
len = (u16_t)LWIP_MIN(copy_len, len_calc);
|
||||||
MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len);
|
MEMCPY((u8_t *)p_to->payload + offset_to, (u8_t *)p_from->payload + offset_from, len);
|
||||||
offset_to += len;
|
offset_to += len;
|
||||||
offset_from += len;
|
offset_from += len;
|
||||||
|
copy_len -= len;
|
||||||
LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
|
LWIP_ASSERT("offset_to <= p_to->len", offset_to <= p_to->len);
|
||||||
LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
|
LWIP_ASSERT("offset_from <= p_from->len", offset_from <= p_from->len);
|
||||||
if (offset_from >= p_from->len) {
|
if (offset_from >= p_from->len) {
|
||||||
/* on to next p_from (if any) */
|
/* on to next p_from (if any) */
|
||||||
offset_from = 0;
|
offset_from = 0;
|
||||||
p_from = p_from->next;
|
p_from = p_from->next;
|
||||||
|
LWIP_ERROR("p_from != NULL", (p_from != NULL) || (copy_len == 0), return ERR_ARG;);
|
||||||
}
|
}
|
||||||
if (offset_to == p_to->len) {
|
if (offset_to == p_to->len) {
|
||||||
/* on to next p_to (if any) */
|
/* on to next p_to (if any) */
|
||||||
offset_to = 0;
|
offset_to = 0;
|
||||||
p_to = p_to->next;
|
p_to = p_to->next;
|
||||||
LWIP_ERROR("p_to != NULL", (p_to != NULL) || (p_from == NULL), return ERR_ARG;);
|
LWIP_ERROR("p_to != NULL", (p_to != NULL) || (copy_len == 0), return ERR_ARG;);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((p_from != NULL) && (p_from->len == p_from->tot_len)) {
|
if ((p_from != NULL) && (p_from->len == p_from->tot_len)) {
|
||||||
/* don't copy more than one packet! */
|
/* don't copy more than one packet! */
|
||||||
LWIP_ERROR("pbuf_copy() does not allow packet queues!",
|
LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
|
||||||
(p_from->next == NULL), return ERR_VAL;);
|
(p_from->next == NULL), return ERR_VAL;);
|
||||||
}
|
}
|
||||||
if ((p_to != NULL) && (p_to->len == p_to->tot_len)) {
|
if ((p_to != NULL) && (p_to->len == p_to->tot_len)) {
|
||||||
/* don't copy more than one packet! */
|
/* don't copy more than one packet! */
|
||||||
LWIP_ERROR("pbuf_copy() does not allow packet queues!",
|
LWIP_ERROR("pbuf_copy_partial_pbuf() does not allow packet queues!",
|
||||||
(p_to->next == NULL), return ERR_VAL;);
|
(p_to->next == NULL), return ERR_VAL;);
|
||||||
}
|
}
|
||||||
} while (p_from);
|
} while (copy_len);
|
||||||
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy: end of chain reached.\n"));
|
LWIP_DEBUGF(PBUF_DEBUG | LWIP_DBG_TRACE, ("pbuf_copy_partial_pbuf: copy complete.\n"));
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,6 +296,7 @@ void pbuf_cat(struct pbuf *head, struct pbuf *tail);
|
|||||||
void pbuf_chain(struct pbuf *head, struct pbuf *tail);
|
void pbuf_chain(struct pbuf *head, struct pbuf *tail);
|
||||||
struct pbuf *pbuf_dechain(struct pbuf *p);
|
struct pbuf *pbuf_dechain(struct pbuf *p);
|
||||||
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from);
|
err_t pbuf_copy(struct pbuf *p_to, const struct pbuf *p_from);
|
||||||
|
err_t pbuf_copy_partial_pbuf(struct pbuf *p_to, const struct pbuf *p_from, u16_t copy_len, u16_t offset);
|
||||||
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
u16_t pbuf_copy_partial(const struct pbuf *p, void *dataptr, u16_t len, u16_t offset);
|
||||||
void *pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset);
|
void *pbuf_get_contiguous(const struct pbuf *p, void *buffer, size_t bufsize, u16_t len, u16_t offset);
|
||||||
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user