Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
HttpConnection.h
1// Copyright (c) Stefano Cristiano
2// SPDX-License-Identifier: MIT
3#pragma once
4#include "HttpExport.h"
5#include "HttpParser.h"
6
7#include "../Async/Async.h"
8#include "../AsyncStreams/AsyncRequestStreams.h"
9#include "../Foundation/StringSpan.h"
10#include "Internal/HttpFixedBufferWriter.h"
11#include "Internal/HttpParsedHeaders.h"
12
13namespace SC
14{
17
18enum class HttpBodyFramingKind : uint8_t
19{
20 None,
21 ContentLength,
22 Chunked,
23 CloseDelimited,
24};
25
26struct HttpAsyncClient;
27
28struct SC_HTTP_EXPORT HttpMultipartWriter
29{
30 struct Part
31 {
32 StringSpan partName;
33 StringSpan fileName;
34 StringSpan contentType;
35
37 };
38
39 static constexpr size_t MaxParts = 8;
40
41 void reset();
42
43 Result setBoundary(StringSpan boundaryValue);
44 Result addField(StringSpan fieldName, StringSpan value);
45 Result addFile(StringSpan fieldName, StringSpan fileName, Span<const char> body,
46 StringSpan contentType = "application/octet-stream");
47
48 [[nodiscard]] StringSpan getBoundary() const { return boundary; }
49 [[nodiscard]] size_t getNumParts() const { return numParts; }
50 [[nodiscard]] const Part& getPart(size_t idx) const { return parts[idx]; }
51 [[nodiscard]] size_t getContentLength() const;
52
53 private:
54 Part parts[MaxParts];
55 size_t numParts = 0;
56 char boundaryStorage[71] = {0};
57 StringSpan boundary;
58};
59
61struct SC_HTTP_EXPORT HttpConnectionBase
62{
65
66 ReadableSocketStream readableSocketStream;
67 WritableSocketStream writableSocketStream;
68 AsyncBuffersPool buffersPool;
69 AsyncPipeline pipeline;
70 SocketDescriptor socket;
71
72 void setHeaderMemory(Span<char> memory) { headerMemory = memory; }
73
74 [[nodiscard]] Span<char> getHeaderMemory() const { return headerMemory; }
75
76 void reset();
77
78 protected:
79 Span<char> headerMemory;
80};
81
83struct SC_HTTP_EXPORT HttpIncomingMessage
84{
85 struct SC_HTTP_EXPORT BodyStream : public AsyncReadableStream
86 {
87 BodyStream();
88
89 Result begin(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
90 bool pushBodyData(AsyncBufferView::ID bufferID, size_t sizeInBytes);
91 void finishBody();
92 void failBody(Result result);
93
94 Function<Result()> onReadRequest;
95 Request queue[4];
96
97 private:
98 virtual Result asyncRead() override;
99 };
100
102 const HttpParser& getParser() const { return parsedHeaders.parser; }
103
105 [[nodiscard]] bool getKeepAlive() const { return parsedHeaders.parser.connectionKeepAlive; }
106
108 [[nodiscard]] HttpBodyFramingKind getBodyFramingKind() const { return bodyFramingKind; }
109
111 [[nodiscard]] uint64_t getBodyBytesRemaining() const { return bodyBytesRemaining; }
112
114 [[nodiscard]] bool isBodyComplete() const { return bodyComplete; }
115
117 [[nodiscard]] bool isMultipart() const;
118
120 [[nodiscard]] StringSpan getBoundary() const;
121
126 [[nodiscard]] bool getHeader(StringSpan headerName, StringSpan& value) const;
127
130
133
136
137 protected:
138 void resetIncoming(HttpParser::Type type, Span<char> memory);
139
140 [[nodiscard]] bool hasReceivedHeaders() const { return parsedHeaders.headersEndReceived; }
141 [[nodiscard]] Span<char> getUnusedHeaderMemory() const { return parsedHeaders.availableHeader; }
142
143 Result initBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest);
144 Result startBodyStream();
145 bool pushBodyData(AsyncBufferView::ID bufferID, size_t sizeInBytes);
146 void finishBodyStream();
147 void failBodyStream(Result result);
148 void abortBodyStream();
149 Result prepareBodyStream(AsyncBuffersPool& buffersPool, Function<Result()>&& onReadRequest,
150 bool allowCloseDelimited);
151 Result processBodyData(AsyncReadableStream& sourceStream, AsyncBufferView::ID bufferID, Span<const char> readData,
152 bool allowTrailingData);
153
154 void setBodyBytesRemaining(uint64_t value) { bodyBytesRemaining = value; }
155 void setBodyFramingKind(HttpBodyFramingKind value) { bodyFramingKind = value; }
156 void setBodyComplete(bool value) { bodyComplete = value; }
157 void attachReadableStream(AsyncReadableStream& stream) { readableStream = &stream; }
158
163 [[nodiscard]] bool findParserToken(HttpParser::Token token, StringSpan& res) const;
164
167 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
168 AsyncBufferView::ID bufferID, const char* outOfSpaceError, const char* sizeExceededError,
169 bool stopAtHeadersEnd, bool unshiftPendingBodyToStream = true);
170
172 [[nodiscard]] size_t getHeadersLength() const;
173
174 enum class ChunkedState : uint8_t
175 {
176 Size,
177 SizeExtension,
178 SizeLF,
179 Data,
180 DataCR,
181 DataLF,
182 TrailerLineStart,
183 TrailerEndLF,
184 Finished,
185 };
186
187 HttpParsedHeaders parsedHeaders;
188 Span<char> headerMemory;
189 AsyncReadableStream* readableStream = nullptr;
190 uint64_t bodyBytesRemaining = 0;
191 HttpBodyFramingKind bodyFramingKind = HttpBodyFramingKind::None;
192 bool bodyComplete = true;
193 bool bodyStreamStarted = false;
194 BodyStream bodyStream;
195 ChunkedState chunkedState = ChunkedState::Size;
196 uint64_t chunkedChunkSize = 0;
197 uint64_t chunkedBytesRemaining = 0;
198 bool chunkedSizeHasDigits = false;
199};
200
202struct SC_HTTP_EXPORT HttpRequest : public HttpIncomingMessage
203{
205 StringSpan getURL() const { return url; }
206
208 void reset();
209
210 private:
211 friend struct HttpConnectionsPool;
212 friend struct HttpResponse;
213 friend struct HttpAsyncServer;
214
215 void setHeaderMemory(Span<char> memory);
216
218 Result writeHeaders(const uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
219 AsyncBufferView::ID bufferID);
220
221 StringSpan url;
222};
223
225struct SC_HTTP_EXPORT HttpAsyncClientResponse : public HttpIncomingMessage
226{
227 private:
228 friend struct HttpAsyncClient;
229
230 void reset(Span<char> memory);
231 Result writeHeaders(uint32_t maxHeaderSize, Span<const char> readData, AsyncReadableStream& stream,
232 AsyncBufferView::ID bufferID);
233};
234
236struct SC_HTTP_EXPORT HttpOutgoingMessage
237{
238 struct SC_HTTP_EXPORT ChunkedWritableStream : public AsyncWritableStream
239 {
241
242 Result init(AsyncBuffersPool& buffersPool, AsyncWritableStream& destination);
243
244 protected:
245 virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function<void(AsyncBufferView::ID)> cb) override;
246 virtual bool canEndWritable() override;
247
248 private:
249 void onChunkHeaderWritten(AsyncBufferView::ID);
250 void onChunkBodyWritten(AsyncBufferView::ID);
251 void onChunkTerminatorWritten(AsyncBufferView::ID);
252 void onFinalChunkWritten(AsyncBufferView::ID);
253
254 AsyncWritableStream* destination = nullptr;
255
256 AsyncBufferView::ID currentBodyBufferID;
257 Function<void(AsyncBufferView::ID)> currentBodyCallback;
258
259 bool finalChunkStarted = false;
260 bool finalChunkWritten = false;
261
262 char headerStorage[20] = {0};
263
264 Request queue[4];
265 };
266
270 Result addHeader(StringSpan headerName, StringSpan headerValue);
271
274
276 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
277
279 void reset();
280
283
285 AsyncWritableStream& getWritableStream() { return *writableStream; }
286
290 void setKeepAlive(bool keepAlive);
291
294 [[nodiscard]] bool getKeepAlive() const { return forceDisableKeepAlive ? false : keepAlive; }
295
296 protected:
297 enum class KnownHeader : uint8_t
298 {
299 Connection,
300 Host,
301 UserAgent,
302 ContentLength,
303 ContentType,
304 TransferEncoding,
305 };
306
307 void setHeaderMemory(Span<char> memory);
308 void setWritableStream(AsyncWritableStream& stream)
309 {
310 destinationStream = &stream;
311 writableStream = &stream;
312 }
313
314 [[nodiscard]] bool hasHeader(KnownHeader header) const;
315 [[nodiscard]] bool hasSentHeaders() const { return headersSent; }
316 [[nodiscard]] bool hasEnded() const { return endCalled; }
317 [[nodiscard]] bool isChunkedTransferEncodingEnabled() const { return chunkedTransferEncodingEnabled; }
318
319 HttpFixedBufferWriter responseHeaders;
320 Span<char> headerMemory;
321
322 bool headersSent = false;
323 bool endCalled = false;
324
325 bool forceDisableKeepAlive = false;
326 bool keepAlive = true;
327 bool connectionHeaderAdded = false;
328 bool hostHeaderAdded = false;
329 bool userAgentHeaderAdded = false;
330 bool contentLengthAdded = false;
331 bool contentTypeAdded = false;
332 bool transferEncodingAdded = false;
333 bool chunkedTransferEncodingEnabled = false;
334
335 AsyncWritableStream* destinationStream = nullptr;
336 AsyncWritableStream* writableStream = nullptr;
337 ChunkedWritableStream chunkedWritableStream;
338};
339
341struct SC_HTTP_EXPORT HttpResponse : public HttpOutgoingMessage
342{
344 Result startResponse(int httpCode);
345
346 private:
347 friend struct HttpConnectionsPool;
348 friend struct HttpAsyncServer;
349
351 void grabUnusedHeaderMemory(HttpRequest& request);
352};
353
355struct SC_HTTP_EXPORT HttpAsyncClientRequest : public HttpOutgoingMessage
356{
357 enum class BodyType : uint8_t
358 {
359 None,
360 Manual,
361 Span,
362 Stream,
363 Multipart,
364 };
365
366 void reset();
367
368 Result startRequest(HttpParser::Method method, StringSpan url);
369 Result setExpectedBodyLength(uint64_t value);
370 Result setBody(Span<const char> value);
371 Result setBody(StringSpan value) { return setBody(value.toCharSpan()); }
372 Result setBody(AsyncReadableStream& stream);
373 void setBody(AsyncReadableStream& stream, uint64_t contentLengthValue);
374 void setMultipart(HttpMultipartWriter& value);
375 Result sendHeaders(Function<void(AsyncBufferView::ID)> callback = {});
376
377 [[nodiscard]] HttpParser::Method getMethod() const { return method; }
378
379 [[nodiscard]] StringSpan getURL() const { return url; }
380 [[nodiscard]] BodyType getBodyType() const { return bodyType; }
381 [[nodiscard]] uint64_t getContentLength() const { return contentLength; }
382 [[nodiscard]] bool usesChunkedTransferEncoding() const { return chunkedTransferEncodingEnabled; }
383
384 private:
385 friend struct HttpAsyncClient;
386
387 void setDefaultHost(StringSpan value) { defaultHost = value; }
388
389 [[nodiscard]] bool hasTransferEncodingHeader() const { return hasHeader(KnownHeader::TransferEncoding); }
390
391 [[nodiscard]] AsyncReadableStream* getBodyStream() const { return bodyStream; }
392 [[nodiscard]] const HttpMultipartWriter* getMultipartWriter() const { return multipartWriter; }
393 [[nodiscard]] Span<const char> getBodySpan() const { return bodySpan; }
394
395 HttpParser::Method method = HttpParser::Method::HttpGET;
396 StringSpan url;
397 AsyncReadableStream* bodyStream = nullptr;
398 BodyType bodyType = BodyType::None;
399 Span<const char> bodySpan;
400 uint64_t contentLength = 0;
401 HttpMultipartWriter* multipartWriter = nullptr;
402 StringSpan defaultHost;
403
404 Function<void(AsyncBufferView::ID)> userHeadersSentCallback;
405 Function<void(AsyncBufferView::ID)> internalHeadersSentCallback;
406};
407
409struct SC_HTTP_EXPORT HttpConnection : public HttpConnectionBase
410{
412
413 struct SC_HTTP_EXPORT ID
414 {
415 size_t getIndex() const { return index; }
416
417 private:
418 friend struct HttpConnectionsPool;
419 size_t index = 0;
420 };
421
423 void reset();
424
426 ID getConnectionID() const { return connectionID; }
427
428 HttpRequest request;
429 HttpResponse response;
430
431 uint32_t requestCount = 0;
432
433 protected:
434 enum class State
435 {
436 Inactive,
437 Active
438 };
439 friend struct HttpConnectionsPool;
440 friend struct HttpAsyncServer;
441
442 State state = State::Inactive;
443 ID connectionID;
444};
445
447template <typename Type>
448struct SC_HTTP_EXPORT SpanWithStride
449{
451 constexpr SpanWithStride() : data(nullptr), sizeElements(0), strideInBytes(0) {}
452
457 constexpr SpanWithStride(void* data, size_t sizeInElements, size_t strideInBytes)
458 : data(data), sizeElements(sizeInElements), strideInBytes(strideInBytes)
459 {}
460
461 template <typename U>
462 constexpr SpanWithStride(Span<U> span)
463 : data(span.data()), sizeElements(span.sizeInElements()), strideInBytes(sizeof(U))
464 {}
465
466 [[nodiscard]] constexpr size_t sizeInElements() const { return sizeElements; }
467 [[nodiscard]] constexpr bool empty() const { return sizeElements == 0; }
468
469 template <typename U>
470 SpanWithStride<U> castTo()
471 {
472 return {static_cast<U*>(reinterpret_cast<Type*>(data)), sizeElements, strideInBytes};
473 }
474
475 [[nodiscard]] Type& operator[](size_t idx)
476 {
477 return *reinterpret_cast<Type*>(reinterpret_cast<char*>(data) + idx * strideInBytes);
478 }
479
480 [[nodiscard]] const Type& operator[](size_t idx) const
481 {
482 return *reinterpret_cast<const Type*>(reinterpret_cast<const char*>(data) + idx * strideInBytes);
483 }
484
485 private:
486 void* data;
487 size_t sizeElements;
488 size_t strideInBytes;
489};
490
492struct SC_HTTP_EXPORT HttpConnectionsPool
493{
495 {
496 size_t readQueueSize = 3;
497 size_t writeQueueSize = 3;
498 size_t buffersQueueSize = 6;
499 size_t headerBytesLength = 8 * 1024;
500 size_t streamBytesLength = 512 * 1024;
501 };
502
503 struct SC_HTTP_EXPORT Memory
504 {
507
508 Span<AsyncBufferView> allBuffers;
509
510 Span<char> allHeaders;
511 Span<char> allStreams;
512
514 };
515
518
521
523 [[nodiscard]] size_t getNumActiveConnections() const { return numConnections; }
524
526 [[nodiscard]] size_t getNumTotalConnections() const { return connections.sizeInElements(); }
527
529 [[nodiscard]] size_t getHighestActiveConnection() const { return highestActiveConnection; }
530
533 {
534 return connections[connectionID.index];
535 }
536
538 [[nodiscard]] HttpConnection& getConnectionAt(size_t idx) { return connections[idx]; }
539
541 [[nodiscard]] bool activateNew(HttpConnection::ID& connectionID);
542
544 [[nodiscard]] bool deactivate(HttpConnection::ID connectionID);
545
546 private:
548
549 size_t numConnections = 0;
550
551 // Optimization for HttpAsyncServer::resize to avoid having to scan all connections
552 size_t highestActiveConnection = 0;
553};
554
556template <int ReadQueue, int WriteQueue, int HeaderBytes, int StreamBytes, int ExtraBuffers, typename BaseClass>
557struct SC_HTTP_EXPORT HttpStaticConnection : public BaseClass
558{
559 AsyncReadableStream::Request readQueue[ReadQueue];
560 AsyncWritableStream::Request writeQueue[WriteQueue];
561
562 AsyncBufferView buffers[ReadQueue + WriteQueue + ExtraBuffers];
563
564 char headerStorage[HeaderBytes];
565 char streamStorage[StreamBytes];
566
567 constexpr HttpStaticConnection()
568 {
569 constexpr const size_t NumSlices = ReadQueue;
570 constexpr const size_t SliceLength = StreamBytes / NumSlices;
571
572 Span<char> memory = streamStorage;
573 for (size_t idx = 0; idx < NumSlices; ++idx)
574 {
575 Span<char> slice;
576 (void)memory.sliceStartLength(idx * SliceLength, SliceLength, slice);
577 buffers[idx] = slice;
578 buffers[idx].setReusable(true);
579 }
580 this->setHeaderMemory(headerStorage);
581 this->buffersPool.setBuffers(buffers);
582 this->readableSocketStream.setReadQueue(readQueue);
583 this->writableSocketStream.setWriteQueue(writeQueue);
584 }
585};
586
588} // namespace SC
struct SC_FOUNDATION_EXPORT Function
Wraps function pointers, member functions and lambdas without ever allocating.
Definition Function.h:19
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:27
unsigned long long uint64_t
Platform independent (8) bytes unsigned int.
Definition PrimitiveTypes.h:33
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:29
Definition AsyncStreams.h:58
A Span of bytes memory to be read or written by async streams.
Definition AsyncStreams.h:56
void setReusable(bool reusable)
Tags this AsyncBufferView as reusable after its refCount goes to zero.
Definition AsyncStreams.h:97
Holds a Span of AsyncBufferView (allocated by user) holding available memory for the streams.
Definition AsyncStreams.h:169
void setBuffers(Span< AsyncBufferView > newBuffers)
Sets memory for the new buffers.
Definition AsyncStreams.h:199
Pipes read data from SC::AsyncReadableStream, forwarding them to SC::AsyncWritableStream.
Definition AsyncStreams.h:544
Definition AsyncStreams.h:225
Async source abstraction emitting data events in caller provided byte buffers.
Definition AsyncStreams.h:220
Definition AsyncStreams.h:357
Async destination abstraction where bytes can be written to.
Definition AsyncStreams.h:350
Outgoing HTTP request sent by the client.
Definition HttpConnection.h:356
Incoming HTTP response received by the client.
Definition HttpConnection.h:226
Asynchronous HTTP/1.1 client using caller-provided fixed storage.
Definition HttpAsyncClient.h:46
Async Http Server.
Definition HttpAsyncServer.h:40
Shared async transport storage for HTTP client and server endpoints.
Definition HttpConnection.h:62
Definition HttpConnection.h:414
Http connection abstraction holding both the incoming and outgoing messages in an HTTP transaction.
Definition HttpConnection.h:410
void reset()
Prepare this client for re-use, marking it as Inactive.
ID getConnectionID() const
The ID used to find this client in HttpConnectionsPool.
Definition HttpConnection.h:426
Definition HttpConnection.h:495
Definition HttpConnection.h:504
A pool of HttpConnection that can be active or inactive.
Definition HttpConnection.h:493
size_t getNumActiveConnections() const
Returns only the number of active connections.
Definition HttpConnection.h:523
size_t getHighestActiveConnection() const
Returns only the number of active connections.
Definition HttpConnection.h:529
HttpConnection & getConnectionAt(size_t idx)
Returns a connection in the [0, getNumTotalConnections] range.
Definition HttpConnection.h:538
Result init(SpanWithStride< HttpConnection > connectionsStorage)
Initializes the server with memory buffers for connections and headers.
bool activateNew(HttpConnection::ID &connectionID)
Finds an available connection (if any), activates it and returns its ID to use with getConnection(id)
HttpConnection & getConnection(HttpConnection::ID connectionID)
Returns a connection by ID.
Definition HttpConnection.h:532
size_t getNumTotalConnections() const
Returns the total number of connections (active + inactive)
Definition HttpConnection.h:526
Result close()
Closes the server, removing references to the memory buffers passed during init.
bool deactivate(HttpConnection::ID connectionID)
De-activates a connection previously returned by activateNew.
Definition HttpConnection.h:86
Incoming message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:84
bool getKeepAlive() const
Gets whether the other party requested the connection to stay alive.
Definition HttpConnection.h:105
const AsyncReadableStream & getReadableStream() const
Obtains the readable stream for the message body.
AsyncReadableStream & getReadableStream()
Obtains the readable stream for the message body.
bool isMultipart() const
Checks if the request is a multipart/form-data request.
const HttpParser & getParser() const
Gets the associated HttpParser.
Definition HttpConnection.h:102
bool getHeader(StringSpan headerName, StringSpan &value) const
Gets the value of a specific header (case-insensitive name matching)
size_t getHeadersLength() const
Gets the length of the headers in bytes.
StringSpan getBoundary() const
Gets the multipart boundary string (if isMultipart() returns true)
bool findParserToken(HttpParser::Token token, StringSpan &res) const
Finds a specific HttpParser::Result in the list of parsed header.
Result consumeBodyBytes(size_t bytes)
Decrements the remaining body bytes after consuming data.
bool isBodyComplete() const
Returns true once the full body has been received according to its framing.
Definition HttpConnection.h:114
uint64_t getBodyBytesRemaining() const
Returns how many body bytes are still expected for this message.
Definition HttpConnection.h:111
HttpBodyFramingKind getBodyFramingKind() const
Returns the effective framing mode for the incoming body.
Definition HttpConnection.h:108
Result writeHeaders(const uint32_t maxHeaderSize, Span< const char > readData, AsyncReadableStream &stream, AsyncBufferView::ID bufferID, const char *outOfSpaceError, const char *sizeExceededError, bool stopAtHeadersEnd, bool unshiftPendingBodyToStream=true)
Parses an incoming slice of data eventually copying it to the availableHeader.
Definition HttpConnection.h:31
Definition HttpConnection.h:29
Definition HttpConnection.h:239
virtual Result asyncWrite(AsyncBufferView::ID bufferID, Function< void(AsyncBufferView::ID)> cb) override
Function that every stream must define to implement its custom write operation.
virtual bool canEndWritable() override
Allows keeping a writable in ENDING state until it has finished flushing all pending data.
Outgoing message from the perspective of the participants of an HTTP transaction.
Definition HttpConnection.h:237
Result setChunkedTransferEncoding()
Enables chunked transfer-encoding for subsequent body writes.
bool getKeepAlive() const
Gets whether the connection should be kept alive after this response.
Definition HttpConnection.h:294
Result end()
Finalizes the writable stream after sending all in progress writes.
void reset()
Resets this object for it to be re-usable.
Result sendHeaders(Function< void(AsyncBufferView::ID)> callback={})
Start sending response headers, before sending any data.
Result addHeader(StringSpan headerName, StringSpan headerValue)
Writes an http header to this response.
void setKeepAlive(bool keepAlive)
Sets whether to keep the connection alive after this response.
AsyncWritableStream & getWritableStream()
Obtain writable stream for sending content back to connected client.
Definition HttpConnection.h:285
Incremental HTTP request or response parser.
Definition HttpParser.h:16
Token
One possible Token reported by the parser.
Definition HttpParser.h:42
Method
Method of the current request / response.
Definition HttpParser.h:19
Type
Type of the stream to be parsed (Request or Response)
Definition HttpParser.h:59
Incoming HTTP request received by the server.
Definition HttpConnection.h:203
StringSpan getURL() const
Gets the request URL.
Definition HttpConnection.h:205
void reset()
Resets this object for it to be re-usable.
Outgoing HTTP response sent by the server.
Definition HttpConnection.h:342
Result startResponse(int httpCode)
Starts the response with a http standard code (200 OK, 404 NOT FOUND etc.)
Adds compile-time configurable read and write queues to any class subclassing HttpConnectionBase.
Definition HttpConnection.h:558
An ascii string used as boolean result. SC_TRY macro forwards errors to caller.
Definition Result.h:13
Low-level OS socket handle.
Definition Socket.h:159
View over a contiguous sequence of items with a custom stride between elements.
Definition HttpConnection.h:449
constexpr SpanWithStride(void *data, size_t sizeInElements, size_t strideInBytes)
Builds a SpanWithStride from data, size, and stride.
Definition HttpConnection.h:457
constexpr SpanWithStride()
Builds an empty SpanWithStride.
Definition HttpConnection.h:451
View over a contiguous sequence of items (pointer + size in elements).
Definition Span.h:29
constexpr bool sliceStartLength(SizeType offsetInElements, SizeType lengthInElements, Span &destination) const
Creates another Span, starting at an offset in elements from current Span of specified length.
Definition Span.h:121
An read-only view over a string (to avoid including Strings library when parsing is not needed).
Definition StringSpan.h:37
Span< const char > toCharSpan() const
Obtain a const char Span from this StringView.
Definition StringSpan.h:82