FastLED 3.10.8
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#include "fl/stl/noexcept.h"
10
11namespace fl {
12namespace net {
13namespace http {
14
15// ChunkedReader implementation
16
20
22 mBuffer.insert(mBuffer.end(), data.begin(), data.end());
23
24 // Process buffer based on current state
25 while (true) {
26 switch (mState) {
27 case READ_SIZE: {
28 // Parse chunk size (hex) until CRLF
30 if (mChunkSize == 0) {
31 // Final chunk (size 0)
33 return;
34 } else {
35 // Start reading chunk data
37 mBytesRead = 0;
38 }
39 } else {
40 // Not enough data to parse size
41 return;
42 }
43 break;
44 }
45 case READ_DATA: {
46 // Read chunk data (mChunkSize bytes)
47 size_t remaining = mChunkSize;
48 size_t available = mBuffer.size();
49 if (available >= remaining) {
50 // Complete chunk data available, save to mCurrentChunk
51 mCurrentChunk.clear();
52 mCurrentChunk.reserve(remaining);
53 for (size_t i = 0; i < remaining; i++) {
54 mCurrentChunk.push_back(mBuffer[i]);
55 }
56 consume(remaining);
58 } else {
59 // Not enough data yet
60 return;
61 }
62 break;
63 }
64 case READ_TRAILER: {
65 // Read trailing CRLF
66 if (hasCRLF()) {
67 consume(2); // Consume CRLF
68 // Chunk is now complete, add to mChunks
69 mChunks.push_back(mCurrentChunk);
70 mCurrentChunk.clear();
72 } else {
73 // Not enough data for CRLF
74 return;
75 }
76 break;
77 }
78 case STATE_FINAL:
79 // No more processing
80 return;
81 }
82 }
83}
84
86 return !mChunks.empty();
87}
88
90 using Status = ChunkedReadResult::Status;
91 if (mChunks.empty()) {
92 Status s = isFinal() ? Status::CHUNKED_FINAL : Status::CHUNKED_NO_DATA;
94 }
95 const fl::vector<u8>& front = mChunks.front();
96 if (out.size() < front.size()) {
97 // Caller's buffer is too small
98 return ChunkedReadResult(Status::CHUNKED_NO_DATA, fl::span<const u8>());
99 }
100 memcpy(out.data(), front.data(), front.size());
101 fl::span<const u8> written(out.data(), front.size());
102 mChunks.erase(mChunks.begin());
103 return ChunkedReadResult(Status::CHUNKED_DATA, written);
104}
105
107 if (mChunks.empty()) {
108 return 0;
109 }
110 return mChunks.front().size();
111}
112
114 return mState == STATE_FINAL;
115}
116
119 mBuffer.clear();
120 mChunkSize = 0;
121 mBytesRead = 0;
122 mChunks.clear();
123 mCurrentChunk.clear();
124}
125
127 // Find CRLF in buffer
128 for (size_t i = 0; i + 1 < mBuffer.size(); i++) {
129 if (mBuffer[i] == '\r' && mBuffer[i + 1] == '\n') {
130 // Found CRLF, parse hex size
131 fl::string sizeStr(reinterpret_cast<const char*>(mBuffer.data()), i); // ok reinterpret cast
132
133 // Parse hex (ignore chunk extensions after ';')
134 size_t semicolon = sizeStr.find(';');
135 if (semicolon != fl::string::npos) {
136 sizeStr = sizeStr.substr(0, semicolon);
137 }
138
139 // Convert hex to size_t
140 char* end = nullptr;
141 outSize = static_cast<size_t>(strtoul(sizeStr.c_str(), &end, 16));
142 if (end == sizeStr.c_str()) {
143 // Invalid hex
144 return false;
145 }
146
147 // Consume size line + CRLF
148 consume(i + 2);
149 return true;
150 }
151 }
152 // No CRLF found
153 return false;
154}
155
157 return mBuffer.size() >= 2 && mBuffer[0] == '\r' && mBuffer[1] == '\n';
158}
159
161 if (n >= mBuffer.size()) {
162 mBuffer.clear();
163 } else {
164 // fl::vector doesn't have erase(first, last), so create new vector without first n elements
165 fl::vector<u8> newBuffer;
166 newBuffer.reserve(mBuffer.size() - n);
167 for (size_t i = n; i < mBuffer.size(); i++) {
168 newBuffer.push_back(mBuffer[i]);
169 }
170 mBuffer = fl::move(newBuffer);
171 }
172}
173
174// ChunkedWriter implementation
175
178
180 // Overhead: hex-digits + "\r\n" + data + "\r\n"
181 // Count hex digits needed
182 char sizeHex[32];
183 int hexLen = fl::snprintf(sizeHex, sizeof(sizeHex), "%zx", dataLen);
184 return static_cast<size_t>(hexLen) + 2 + dataLen + 2; // hex + \r\n + data + \r\n
185}
186
188 // Format: <size-hex>\r\n<data>\r\n
189 char sizeHex[32];
190 int hexLen = fl::snprintf(sizeHex, sizeof(sizeHex), "%zx\r\n", data.size());
191 size_t totalNeeded = static_cast<size_t>(hexLen) + data.size() + 2;
192 if (out.size() < totalNeeded) {
193 return 0;
194 }
195
196 u8* dst = out.data();
197
198 // Write size hex + CRLF
199 memcpy(dst, sizeHex, static_cast<size_t>(hexLen));
200 dst += hexLen;
201
202 // Write data
203 memcpy(dst, data.data(), data.size());
204 dst += data.size();
205
206 // Write trailing CRLF
207 *dst++ = '\r';
208 *dst++ = '\n';
209
210 return totalNeeded;
211}
212
214 if (out.size() < FINAL_SIZE) {
215 return 0;
216 }
217 // Final chunk: 0\r\n\r\n
218 const char* finalStr = "0\r\n\r\n";
219 memcpy(out.data(), finalStr, FINAL_SIZE);
220 return FINAL_SIZE;
221}
222
223} // namespace http
224} // namespace net
225} // namespace fl
fl::size find(const char &value) const FL_NO_EXCEPT
const char * c_str() const FL_NO_EXCEPT
bool parseChunkSize(size_t &outSize) FL_NO_EXCEPT
ChunkedReadResult readChunk(fl::span< u8 > out) FL_NO_EXCEPT
size_t nextChunkSize() const FL_NO_EXCEPT
void feed(fl::span< const u8 > data) FL_NO_EXCEPT
void consume(size_t n) FL_NO_EXCEPT
bool hasChunk() const FL_NO_EXCEPT
bool isFinal() const FL_NO_EXCEPT
bool hasCRLF() const FL_NO_EXCEPT
fl::vector< fl::vector< u8 > > mChunks
size_t writeChunk(fl::span< const u8 > data, fl::span< u8 > out) FL_NO_EXCEPT
size_t writeFinal(fl::span< u8 > out) FL_NO_EXCEPT
static constexpr size_t FINAL_SIZE
static size_t chunkOverhead(size_t dataLen) FL_NO_EXCEPT
string substr(fl::size start, fl::size length) const FL_NO_EXCEPT
static constexpr fl::size npos
Definition string.h:204
fl::size size() const FL_NO_EXCEPT
void reserve(fl::size n) FL_NO_EXCEPT
Definition vector.h:591
T * data() FL_NO_EXCEPT
Definition vector.h:619
void push_back(const T &value) FL_NO_EXCEPT
Definition vector.h:624
constexpr T * end(T(&array)[N]) FL_NO_EXCEPT
constexpr remove_reference< T >::type && move(T &&t) FL_NO_EXCEPT
Definition move.h:30
unsigned char u8
Definition stdint.h:131
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
int snprintf(char *buffer, fl::size size, const char *format) FL_NO_EXCEPT
FASTLED_FORCE_INLINE void * memcpy(void *dest, const void *src, size_t n) FL_NO_EXCEPT
Definition cstring.h:136
FASTLED_FORCE_INLINE unsigned long strtoul(const char *str, char **endptr, int base) FL_NO_EXCEPT
Definition cstdlib.h:65
int available() FL_NO_EXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179