FastLED 3.9.15
Loading...
Searching...
No Matches
chunked_encoding.cpp.hpp
Go to the documentation of this file.
1#pragma once
2
4#include "fl/stl/stdio.h" // fl::snprintf — avoids _svfprintf_r (#2773 item 1.1)
5#include "fl/stl/string.h"
6// Note: fl/stl/cstdio.h intentionally NOT included — workaround for
7// zackees/zccache#619 (Windows PCH path-spelling drift). Dead include.
8#include "fl/stl/cstdlib.h"
9
10namespace fl {
11namespace net {
12namespace http {
13
14// ChunkedReader implementation
15
19
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
29 if (mChunkSize == 0) {
30 // Final chunk (size 0)
32 return;
33 } else {
34 // Start reading chunk 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);
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();
71 } else {
72 // Not enough data for CRLF
73 return;
74 }
75 break;
76 }
77 case STATE_FINAL:
78 // No more processing
79 return;
80 }
81 }
82}
83
85 return !mChunks.empty();
86}
87
89 using Status = ChunkedReadResult::Status;
90 if (mChunks.empty()) {
91 Status s = isFinal() ? Status::CHUNKED_FINAL : Status::CHUNKED_NO_DATA;
93 }
94 const fl::vector<u8>& front = mChunks.front();
95 if (out.size() < front.size()) {
96 // Caller's buffer is too small
97 return ChunkedReadResult(Status::CHUNKED_NO_DATA, fl::span<const u8>());
98 }
99 memcpy(out.data(), front.data(), front.size());
100 fl::span<const u8> written(out.data(), front.size());
101 mChunks.erase(mChunks.begin());
102 return ChunkedReadResult(Status::CHUNKED_DATA, written);
103}
104
106 if (mChunks.empty()) {
107 return 0;
108 }
109 return mChunks.front().size();
110}
111
113 return mState == STATE_FINAL;
114}
115
118 mBuffer.clear();
119 mChunkSize = 0;
120 mBytesRead = 0;
121 mChunks.clear();
122 mCurrentChunk.clear();
123}
124
125bool ChunkedReader::parseChunkSize(size_t& outSize) {
126 // Find CRLF in buffer
127 for (size_t i = 0; i + 1 < mBuffer.size(); i++) {
128 if (mBuffer[i] == '\r' && mBuffer[i + 1] == '\n') {
129 // Found CRLF, parse hex size
130 fl::string sizeStr(reinterpret_cast<const char*>(mBuffer.data()), i); // ok reinterpret cast
131
132 // Parse hex (ignore chunk extensions after ';')
133 size_t semicolon = sizeStr.find(';');
134 if (semicolon != fl::string::npos) {
135 sizeStr = sizeStr.substr(0, semicolon);
136 }
137
138 // Convert hex to size_t
139 char* end = nullptr;
140 outSize = static_cast<size_t>(strtoul(sizeStr.c_str(), &end, 16));
141 if (end == sizeStr.c_str()) {
142 // Invalid hex
143 return false;
144 }
145
146 // Consume size line + CRLF
147 consume(i + 2);
148 return true;
149 }
150 }
151 // No CRLF found
152 return false;
153}
154
156 return mBuffer.size() >= 2 && mBuffer[0] == '\r' && mBuffer[1] == '\n';
157}
158
160 if (n >= mBuffer.size()) {
161 mBuffer.clear();
162 } else {
163 // fl::vector doesn't have erase(first, last), so create new vector without first n elements
164 fl::vector<u8> newBuffer;
165 newBuffer.reserve(mBuffer.size() - n);
166 for (size_t i = n; i < mBuffer.size(); i++) {
167 newBuffer.push_back(mBuffer[i]);
168 }
169 mBuffer = fl::move(newBuffer);
170 }
171}
172
173// ChunkedWriter implementation
174
177
178size_t ChunkedWriter::chunkOverhead(size_t dataLen) {
179 // Overhead: hex-digits + "\r\n" + data + "\r\n"
180 // Count hex digits needed
181 char sizeHex[32];
182 int hexLen = fl::snprintf(sizeHex, sizeof(sizeHex), "%zx", dataLen);
183 return static_cast<size_t>(hexLen) + 2 + dataLen + 2; // hex + \r\n + data + \r\n
184}
185
187 // Format: <size-hex>\r\n<data>\r\n
188 char sizeHex[32];
189 int hexLen = fl::snprintf(sizeHex, sizeof(sizeHex), "%zx\r\n", data.size());
190 size_t totalNeeded = static_cast<size_t>(hexLen) + data.size() + 2;
191 if (out.size() < totalNeeded) {
192 return 0;
193 }
194
195 u8* dst = out.data();
196
197 // Write size hex + CRLF
198 memcpy(dst, sizeHex, static_cast<size_t>(hexLen));
199 dst += hexLen;
200
201 // Write data
202 memcpy(dst, data.data(), data.size());
203 dst += data.size();
204
205 // Write trailing CRLF
206 *dst++ = '\r';
207 *dst++ = '\n';
208
209 return totalNeeded;
210}
211
213 if (out.size() < FINAL_SIZE) {
214 return 0;
215 }
216 // Final chunk: 0\r\n\r\n
217 const char* finalStr = "0\r\n\r\n";
218 memcpy(out.data(), finalStr, FINAL_SIZE);
219 return FINAL_SIZE;
220}
221
222} // namespace http
223} // namespace net
224} // namespace fl
fl::size find(const char &value) const FL_NOEXCEPT
const char * c_str() const FL_NOEXCEPT
void feed(fl::span< const u8 > data)
ChunkedReadResult readChunk(fl::span< u8 > out)
fl::vector< fl::vector< u8 > > mChunks
size_t writeChunk(fl::span< const u8 > data, fl::span< u8 > out)
static size_t chunkOverhead(size_t dataLen)
static constexpr size_t FINAL_SIZE
size_t writeFinal(fl::span< u8 > out)
iterator begin() FL_NOEXCEPT
Definition span.h:440
const T * data() const FL_NOEXCEPT
Definition span.h:461
iterator end() FL_NOEXCEPT
Definition span.h:444
constexpr fl::size size() const FL_NOEXCEPT
Definition span.h:458
string substr(fl::size start, fl::size length) const FL_NOEXCEPT
static constexpr fl::size npos
Definition string.h:195
fl::size size() const FL_NOEXCEPT
T * data() FL_NOEXCEPT
Definition vector.h:619
void reserve(fl::size n) FL_NOEXCEPT
Definition vector.h:591
void push_back(const T &value) FL_NOEXCEPT
Definition vector.h:624
constexpr remove_reference< T >::type && move(T &&t) FL_NOEXCEPT
Definition s16x16x4.h:28
int available()
void * memcpy(void *dest, const void *src, size_t n) FL_NOEXCEPT
unsigned char u8
Definition stdint.h:131
constexpr T * end(T(&array)[N]) FL_NOEXCEPT
int snprintf(char *buffer, fl::size size, const char *format, const Args &... args) FL_NOEXCEPT
Snprintf-like formatting function that writes to a buffer.
Definition stdio.h:666
unsigned long strtoul(const char *str, char **endptr, int base)
Base definition for an LED controller.
Definition crgb.hpp:179