| 18 | } |
| 19 | |
| 20 | void ChunkedReader::feed(fl::span<const u8> data) { |
| 21 | mBuffer.insert(mBuffer.end(), data.begin(), data.end()); |
| 22 | |
| 23 | // Process buffer based on current state |
| 24 | while (true) { |
| 25 | switch (mState) { |
| 26 | case READ_SIZE: { |
| 27 | // Parse chunk size (hex) until CRLF |
| 28 | if (parseChunkSize(mChunkSize)) { |
| 29 | if (mChunkSize == 0) { |
| 30 | // Final chunk (size 0) |
| 31 | mState = STATE_FINAL; |
| 32 | return; |
| 33 | } else { |
| 34 | // Start reading chunk data |
| 35 | mState = READ_DATA; |
| 36 | mBytesRead = 0; |
| 37 | } |
| 38 | } else { |
| 39 | // Not enough data to parse size |
| 40 | return; |
| 41 | } |
| 42 | break; |
| 43 | } |
| 44 | case READ_DATA: { |
| 45 | // Read chunk data (mChunkSize bytes) |
| 46 | size_t remaining = mChunkSize; |
| 47 | size_t available = mBuffer.size(); |
| 48 | if (available >= remaining) { |
| 49 | // Complete chunk data available, save to mCurrentChunk |
| 50 | mCurrentChunk.clear(); |
| 51 | mCurrentChunk.reserve(remaining); |
| 52 | for (size_t i = 0; i < remaining; i++) { |
| 53 | mCurrentChunk.push_back(mBuffer[i]); |
| 54 | } |
| 55 | consume(remaining); |
| 56 | mState = READ_TRAILER; |
| 57 | } else { |
| 58 | // Not enough data yet |
| 59 | return; |
| 60 | } |
| 61 | break; |
| 62 | } |
| 63 | case READ_TRAILER: { |
| 64 | // Read trailing CRLF |
| 65 | if (hasCRLF()) { |
| 66 | consume(2); // Consume CRLF |
| 67 | // Chunk is now complete, add to mChunks |
| 68 | mChunks.push_back(mCurrentChunk); |
| 69 | mCurrentChunk.clear(); |
| 70 | mState = READ_SIZE; |
| 71 | } else { |
| 72 | // Not enough data for CRLF |
| 73 | return; |
| 74 | } |
| 75 | break; |
| 76 | } |
| 77 | case STATE_FINAL: |