| 243 | return Result(true); |
| 244 | } |
| 245 | |
| 246 | static Result appendCookiePiece(Span<char> storage, size_t& offset, StringSpan piece) |
| 247 | { |
| 248 | if (not appendTo(storage, offset, piece)) |
| 249 | return Result::Error(HttpResultCategory, HttpError::SetCookieOutputTooSmall); |
| 250 | return Result(true); |
| 251 | } |
| 252 | }; |
| 253 | |
| 254 | HttpCookieIterator::HttpCookieIterator(StringSpan cookieHeader) : header(cookieHeader) {} |
| 255 | |
| 256 | bool HttpCookieIterator::next(HttpHeaderKeyValue& pair) |
| 257 | { |
| 258 | pair = {}; |
| 259 | |
| 260 | const char* data = header.bytesWithoutTerminator(); |
| 261 | const size_t length = header.sizeInBytes(); |
| 262 | |
| 263 | while (cursor < length) |
| 264 | { |
| 265 | const size_t itemStart = cursor; |
| 266 | while (cursor < length and data[cursor] != ';') |
| 267 | { |
| 268 | cursor++; |
| 269 | } |
| 270 | const size_t itemEnd = cursor; |
| 271 | if (cursor < length and data[cursor] == ';') |
| 272 | { |
| 273 | cursor++; |
| 274 | } |
| 275 | |
| 276 | StringSpan item = {{data + itemStart, itemEnd - itemStart}, false, header.getEncoding()}; |
| 277 | item = HttpHeaderInternal::trimOptionalWhitespace(item); |
| 278 | if (item.isEmpty()) |
| 279 | { |
| 280 | continue; |
| 281 | } |
| 282 | |
| 283 | size_t equals = static_cast<size_t>(-1); |
| 284 | for (size_t idx = 0; idx < item.sizeInBytes(); ++idx) |
| 285 | { |
| 286 | if (item.bytesWithoutTerminator()[idx] == '=') |
| 287 | { |
| 288 | equals = idx; |
| 289 | break; |
| 290 | } |
| 291 | } |
| 292 | |
| 293 | if (equals == static_cast<size_t>(-1)) |
| 294 | { |
| 295 | pair.name = HttpHeaderInternal::trimOptionalWhitespace(item); |
| 296 | pair.value = {}; |
| 297 | pair.hasValue = false; |
| 298 | return true; |
| 299 | } |
| 300 | |
| 301 | pair.name = {{item.bytesWithoutTerminator(), equals}, false, item.getEncoding()}; |
| 302 | pair.value = { |