* @ingroup pbuf * Shrink a pbuf chain to a desired length. * * @param p pbuf to shrink. * @param new_len desired new length of pbuf chain * * Depending on the desired length, the first few pbufs in a chain might * be skipped and left unchanged. The new last pbuf in the chain will be * resized, and any remaining pbufs will be freed. * * @note If the pbuf is ROM/REF, only the ->tot_len and
| 399 | * @note Despite its name, pbuf_realloc cannot grow the size of a pbuf (chain). |
| 400 | */ |
| 401 | void |
| 402 | pbuf_realloc(struct pbuf *p, u16_t new_len) |
| 403 | { |
| 404 | struct pbuf *q; |
| 405 | u16_t rem_len; /* remaining length */ |
| 406 | u16_t shrink; |
| 407 | |
| 408 | LWIP_ASSERT("pbuf_realloc: p != NULL", p != NULL); |
| 409 | |
| 410 | /* desired length larger than current length? */ |
| 411 | if (new_len >= p->tot_len) { |
| 412 | /* enlarging not yet supported */ |
| 413 | return; |
| 414 | } |
| 415 | |
| 416 | /* the pbuf chain grows by (new_len - p->tot_len) bytes |
| 417 | * (which may be negative in case of shrinking) */ |
| 418 | shrink = (u16_t)(p->tot_len - new_len); |
| 419 | |
| 420 | /* first, step over any pbufs that should remain in the chain */ |
| 421 | rem_len = new_len; |
| 422 | q = p; |
| 423 | /* should this pbuf be kept? */ |
| 424 | while (rem_len > q->len) { |
| 425 | /* decrease remaining length by pbuf length */ |
| 426 | rem_len = (u16_t)(rem_len - q->len); |
| 427 | /* decrease total length indicator */ |
| 428 | q->tot_len = (u16_t)(q->tot_len - shrink); |
| 429 | /* proceed to next pbuf in chain */ |
| 430 | q = q->next; |
| 431 | LWIP_ASSERT("pbuf_realloc: q != NULL", q != NULL); |
| 432 | } |
| 433 | /* we have now reached the new last pbuf (in q) */ |
| 434 | /* rem_len == desired length for pbuf q */ |
| 435 | |
| 436 | /* shrink allocated memory for PBUF_RAM */ |
| 437 | /* (other types merely adjust their length fields */ |
| 438 | if (pbuf_match_allocsrc(q, PBUF_TYPE_ALLOC_SRC_MASK_STD_HEAP) && (rem_len != q->len) |
| 439 | #if LWIP_SUPPORT_CUSTOM_PBUF |
| 440 | && ((q->flags & PBUF_FLAG_IS_CUSTOM) == 0) |
| 441 | #endif /* LWIP_SUPPORT_CUSTOM_PBUF */ |
| 442 | ) { |
| 443 | /* reallocate and adjust the length of the pbuf that will be split */ |
| 444 | q = (struct pbuf *)mem_trim(q, (mem_size_t)(((u8_t *)q->payload - (u8_t *)q) + rem_len)); |
| 445 | LWIP_ASSERT("mem_trim returned q == NULL", q != NULL); |
| 446 | } |
| 447 | /* adjust length fields for new last pbuf */ |
| 448 | q->len = rem_len; |
| 449 | q->tot_len = q->len; |
| 450 | |
| 451 | /* any remaining pbufs in chain? */ |
| 452 | if (q->next != NULL) { |
| 453 | /* free remaining pbufs in chain */ |
| 454 | pbuf_free(q->next); |
| 455 | } |
| 456 | /* q is last packet in chain */ |
| 457 | q->next = NULL; |
| 458 |
no test coverage detected