| 624 | } |
| 625 | |
| 626 | span<char> http_parser::collapse_chunk_headers(span<char> buffer) const |
| 627 | { |
| 628 | if (!chunked_encoding()) return buffer; |
| 629 | |
| 630 | // go through all chunks and compact them |
| 631 | // since we're bottled, and the buffer is our after all |
| 632 | // it's OK to mutate it |
| 633 | char* write_ptr = buffer.data(); |
| 634 | // the offsets in the array are from the start of the |
| 635 | // buffer, not start of the body, so subtract the size |
| 636 | // of the HTTP header from them |
| 637 | int const offset = body_start(); |
| 638 | for (auto const& i : chunks()) |
| 639 | { |
| 640 | auto const chunk_start = i.first; |
| 641 | auto const chunk_end = i.second; |
| 642 | if (chunk_end - offset > buffer.size() |
| 643 | || (i.second - i.first) >= std::numeric_limits<int>::max()) |
| 644 | { |
| 645 | // invalid chunk header. Return the body we've parsed out so far |
| 646 | return buffer.first(write_ptr - buffer.data()); |
| 647 | } |
| 648 | span<char> chunk = buffer.subspan( |
| 649 | aux::numeric_cast<std::ptrdiff_t>(chunk_start - offset) |
| 650 | , aux::numeric_cast<std::ptrdiff_t>(chunk_end - chunk_start)); |
| 651 | #if defined __GNUC__ && __GNUC__ >= 7 |
| 652 | #pragma GCC diagnostic push |
| 653 | #pragma GCC diagnostic ignored "-Wstringop-overflow" |
| 654 | #endif |
| 655 | std::memmove(write_ptr, chunk.data(), std::size_t(chunk.size())); |
| 656 | #if defined __GNUC__ && __GNUC__ >= 7 |
| 657 | #pragma GCC diagnostic pop |
| 658 | #endif |
| 659 | write_ptr += chunk.size(); |
| 660 | } |
| 661 | return buffer.first(write_ptr - buffer.data()); |
| 662 | } |
| 663 | } |