diff --git a/packages/bun-uws/src/App.h b/packages/bun-uws/src/App.h index a13c888c1c..4a959f5426 100644 --- a/packages/bun-uws/src/App.h +++ b/packages/bun-uws/src/App.h @@ -68,11 +68,11 @@ namespace uWS { int ssl_prefer_low_memory_usage = 0; const char **key = nullptr; - unsigned int key_count = 0; + unsigned int key_count = 0; const char **cert = nullptr; - unsigned int cert_count = 0; + unsigned int cert_count = 0; const char **ca = nullptr; - unsigned int ca_count = 0; + unsigned int ca_count = 0; unsigned int secure_options = 0; int reject_unauthorized = 0; int request_cert = 0; @@ -105,7 +105,7 @@ public: /* Server name */ - TemplatedApp &&addServerName(std::string hostname_pattern, SocketContextOptions options = {}, bool *success = nullptr) { + TemplatedApp &&addServerName(const std::string &hostname_pattern, SocketContextOptions options = {}, bool *success = nullptr) { /* Do nothing if not even on SSL */ if constexpr (SSL) { @@ -121,8 +121,8 @@ public: return std::move(*this); } - TemplatedApp &&removeServerName(std::string hostname_pattern) { - + TemplatedApp &&removeServerName(const std::string &hostname_pattern) { + /* This will do for now, would be better if us_socket_context_remove_server_name returned the user data */ auto *domainRouter = us_socket_context_find_server_name_userdata(SSL, (struct us_socket_context_t *) httpContext, hostname_pattern.c_str()); if (domainRouter) { @@ -133,7 +133,7 @@ public: return std::move(*this); } - TemplatedApp &&missingServerName(MoveOnlyFunction handler) { + TemplatedApp &&missingServerName(MoveOnlyFunction &&handler) { if (!constructorFailed()) { httpContext->getSocketContextData()->missingServerNameHandler = std::move(handler); @@ -294,7 +294,7 @@ public: } template - TemplatedApp &&ws(std::string pattern, WebSocketBehavior &&behavior) { + TemplatedApp &&ws(std::string_view pattern, WebSocketBehavior &&behavior) { /* Don't compile if alignment rules cannot be satisfied */ static_assert(alignof(UserData) <= LIBUS_EXT_ALIGNMENT, "µWebSockets cannot satisfy UserData alignment requirements. You need to recompile µSockets with LIBUS_EXT_ALIGNMENT adjusted accordingly."); @@ -473,7 +473,7 @@ public: } /* Browse to a server name, changing the router to this domain */ - TemplatedApp &&domain(std::string serverName) { + TemplatedApp &&domain(const std::string &serverName) { HttpContextData *httpContextData = httpContext->getSocketContextData(); void *domainRouter = us_socket_context_find_server_name_userdata(SSL, (struct us_socket_context_t *) httpContext, serverName.c_str()); @@ -482,46 +482,46 @@ public: } else { httpContextData->currentRouter = &httpContextData->router; } - + return std::move(*this); } - TemplatedApp &&get(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&get(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("GET", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&post(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&post(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("POST", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&options(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&options(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("OPTIONS", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&del(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&del(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("DELETE", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&patch(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&patch(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("PATCH", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&put(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&put(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("PUT", pattern, std::move(handler)); } @@ -535,21 +535,21 @@ public: } - TemplatedApp &&head(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&head(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("HEAD", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&connect(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&connect(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("CONNECT", pattern, std::move(handler)); } return std::move(*this); } - TemplatedApp &&trace(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&trace(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("TRACE", pattern, std::move(handler)); } @@ -557,7 +557,7 @@ public: } /* This one catches any method */ - TemplatedApp &&any(std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { + TemplatedApp &&any(std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler) { if (httpContext) { httpContext->onHttp("*", pattern, std::move(handler)); } @@ -565,8 +565,8 @@ public: } /* Host, port, callback */ - TemplatedApp &&listen(std::string host, int port, MoveOnlyFunction &&handler) { - if (!host.length()) { + TemplatedApp &&listen(const std::string &host, int port, MoveOnlyFunction &&handler) { + if (host.empty()) { return listen(port, std::move(handler)); } handler(httpContext ? httpContext->listen(host.c_str(), port, 0) : nullptr); @@ -574,8 +574,8 @@ public: } /* Host, port, options, callback */ - TemplatedApp &&listen(std::string host, int port, int options, MoveOnlyFunction &&handler) { - if (!host.length()) { + TemplatedApp &&listen(const std::string &host, int port, int options, MoveOnlyFunction &&handler) { + if (host.empty()) { return listen(port, options, std::move(handler)); } handler(httpContext ? httpContext->listen(host.c_str(), port, options) : nullptr); @@ -595,13 +595,13 @@ public: } /* options, callback, path to unix domain socket */ - TemplatedApp &&listen(int options, MoveOnlyFunction &&handler, std::string path) { + TemplatedApp &&listen(int options, MoveOnlyFunction &&handler, std::string_view path) { handler(httpContext ? httpContext->listen_unix(path.data(), path.length(), options) : nullptr); return std::move(*this); } /* callback, path to unix domain socket */ - TemplatedApp &&listen(MoveOnlyFunction &&handler, std::string path, int options) { + TemplatedApp &&listen(MoveOnlyFunction &&handler, std::string_view path, int options) { handler(httpContext ? httpContext->listen_unix(path.data(), path.length(), options) : nullptr); return std::move(*this); } diff --git a/packages/bun-uws/src/AsyncSocketData.h b/packages/bun-uws/src/AsyncSocketData.h index d6f65e6387..2dd4ed88b0 100644 --- a/packages/bun-uws/src/AsyncSocketData.h +++ b/packages/bun-uws/src/AsyncSocketData.h @@ -39,6 +39,7 @@ struct BackPressure { /* Always erase a minimum of 1/32th the current backpressure */ if (pendingRemoval > (buffer.length() >> 5)) { buffer.erase(0, pendingRemoval); + buffer.shrink_to_fit(); pendingRemoval = 0; } } diff --git a/packages/bun-uws/src/ChunkedEncoding.h b/packages/bun-uws/src/ChunkedEncoding.h index e27c9b1d2a..e423806db2 100644 --- a/packages/bun-uws/src/ChunkedEncoding.h +++ b/packages/bun-uws/src/ChunkedEncoding.h @@ -42,9 +42,9 @@ namespace uWS { /* Reads hex number until CR or out of data to consume. Updates state. Returns bytes consumed. */ inline void consumeHexNumber(std::string_view &data, uint64_t &state) { /* Consume everything higher than 32 */ - while (data.length() && data.data()[0] > 32) { + while (data.length() && data[0] > 32) { - unsigned char digit = (unsigned char)data.data()[0]; + unsigned char digit = (unsigned char)data[0]; if (digit >= 'a') { digit = (unsigned char) (digit - ('a' - ':')); } else if (digit >= 'A') { @@ -67,7 +67,7 @@ namespace uWS { data.remove_prefix(1); } /* Consume everything not /n */ - while (data.length() && data.data()[0] != '\n') { + while (data.length() && data[0] != '\n') { data.remove_prefix(1); } /* Now we stand on \n so consume it and enable size */ diff --git a/packages/bun-uws/src/ClientApp.h b/packages/bun-uws/src/ClientApp.h index d8696373e1..073fd65004 100644 --- a/packages/bun-uws/src/ClientApp.h +++ b/packages/bun-uws/src/ClientApp.h @@ -22,7 +22,7 @@ namespace uWS { //webSocketContext = WebSocketContext<0, false, int>::create(); } - ClientApp &&connect(std::string url, std::string protocol = "") { + ClientApp &&connect(std::string_view url, std::string_view protocol = "") { return std::move(*this); } diff --git a/packages/bun-uws/src/Http3App.h b/packages/bun-uws/src/Http3App.h index 4c54b29553..d3a8883ab4 100644 --- a/packages/bun-uws/src/Http3App.h +++ b/packages/bun-uws/src/Http3App.h @@ -33,8 +33,8 @@ namespace uWS { } /* Host, port, callback */ - H3App &&listen(std::string host, int port, MoveOnlyFunction &&handler) { - if (!host.length()) { + H3App &&listen(const std::string &host, int port, MoveOnlyFunction &&handler) { + if (host.empty()) { return listen(port, std::move(handler)); } handler(http3Context ? (us_listen_socket_t *) http3Context->listen(host.c_str(), port) : nullptr); @@ -42,8 +42,8 @@ namespace uWS { } /* Host, port, options, callback */ - H3App &&listen(std::string host, int port, int options, MoveOnlyFunction &&handler) { - if (!host.length()) { + H3App &&listen(const std::string &host, int port, int options, MoveOnlyFunction &&handler) { + if (host.empty()) { return listen(port, options, std::move(handler)); } handler(http3Context ? (us_listen_socket_t *) http3Context->listen(host.c_str(), port) : nullptr); @@ -62,63 +62,63 @@ namespace uWS { return std::move(*this); } - H3App &&get(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&get(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("GET", pattern, std::move(handler)); } return std::move(*this); } - H3App &&post(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&post(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("POST", pattern, std::move(handler)); } return std::move(*this); } - H3App &&options(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&options(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("OPTIONS", pattern, std::move(handler)); } return std::move(*this); } - H3App &&del(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&del(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("DELETE", pattern, std::move(handler)); } return std::move(*this); } - H3App &&patch(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&patch(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("PATCH", pattern, std::move(handler)); } return std::move(*this); } - H3App &&put(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&put(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("PUT", pattern, std::move(handler)); } return std::move(*this); } - H3App &&head(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&head(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("HEAD", pattern, std::move(handler)); } return std::move(*this); } - H3App &&connect(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&connect(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("CONNECT", pattern, std::move(handler)); } return std::move(*this); } - H3App &&trace(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&trace(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("TRACE", pattern, std::move(handler)); } @@ -126,7 +126,7 @@ namespace uWS { } /* This one catches any method */ - H3App &&any(std::string pattern, MoveOnlyFunction &&handler) { + H3App &&any(std::string_view pattern, MoveOnlyFunction &&handler) { if (http3Context) { http3Context->onHttp("*", pattern, std::move(handler)); } diff --git a/packages/bun-uws/src/Http3Context.h b/packages/bun-uws/src/Http3Context.h index 7cb18a8b7c..bdfc480f28 100644 --- a/packages/bun-uws/src/Http3Context.h +++ b/packages/bun-uws/src/Http3Context.h @@ -17,7 +17,7 @@ namespace uWS { us_quic_socket_context_on_stream_data(context, [](us_quic_stream_t *s, char *data, int length) { Http3ResponseData *responseData = (Http3ResponseData *) us_quic_stream_ext(s); - + /* We never emit FIN here */ if (responseData->onData) { responseData->onData({data, (size_t) length}, false); @@ -26,7 +26,7 @@ namespace uWS { us_quic_socket_context_on_stream_end(context, [](us_quic_stream_t *s) { Http3ResponseData *responseData = (Http3ResponseData *) us_quic_stream_ext(s); - + /* Emit FIN to app */ if (responseData->onData) { responseData->onData({nullptr, 0}, true); @@ -77,7 +77,7 @@ namespace uWS { std::string_view upperCasedMethod = req->getHeader(":method"); std::string_view path = req->getHeader(":path"); - + contextData->router.getUserData() = {(Http3Response *) s, (Http3Request *) nullptr}; contextData->router.route(upperCasedMethod, path); @@ -92,7 +92,7 @@ namespace uWS { //lsquic_stream_has_unacked_data Http3ResponseData *responseData = (Http3ResponseData *) us_quic_stream_ext(s); - + if (responseData->onAborted) { responseData->onAborted(); } @@ -130,9 +130,9 @@ namespace uWS { } // generic for get, post, any, etc - void onHttp(std::string method, std::string path, MoveOnlyFunction &&cb) { + void onHttp(std::string_view method, std::string_view path, MoveOnlyFunction &&cb) { // modifies the router we own as part of Http3ContextData, used in callbacks set in init - + Http3ContextData *contextData = (Http3ContextData *) us_quic_socket_context_ext((us_quic_socket_context_t *) this); /* Todo: This is ugly, fix */ @@ -141,7 +141,7 @@ namespace uWS { methods = contextData->router.upperCasedMethods; //bug! needs to be upper cased! // router.upperCasedMethods; } else { - methods = {method}; + methods = {std::string(method)}; } contextData->router.add(methods, path, [handler = std::move(cb)](HttpRouter *router) mutable { diff --git a/packages/bun-uws/src/HttpContext.h b/packages/bun-uws/src/HttpContext.h index 439b8cdf87..39ee70f06d 100644 --- a/packages/bun-uws/src/HttpContext.h +++ b/packages/bun-uws/src/HttpContext.h @@ -66,14 +66,14 @@ private: /* Init the HttpContext by registering libusockets event handlers */ HttpContext *init() { - + if(SSL) { // if we are SSL we need to handle the handshake properly us_socket_context_on_handshake(SSL, getSocketContext(), [](us_socket_t *s, int success, struct us_bun_verify_error_t verify_error, void* custom_data) { // if we are closing or already closed, we don't need to do anything - if (!us_socket_is_closed(SSL, s) && !us_socket_is_shut_down(SSL, s)) { + if (!us_socket_is_closed(SSL, s) && !us_socket_is_shut_down(SSL, s)) { HttpContextData *httpContextData = getSocketContextDataS(s); - + if(httpContextData->rejectUnauthorized) { if(!success || verify_error.error != 0) { // we failed to handshake, close the socket @@ -92,7 +92,7 @@ private: } }, nullptr); } - + /* Handle socket connections */ us_socket_context_on_open(SSL, getSocketContext(), [](us_socket_t *s, int /*is_client*/, char */*ip*/, int /*ip_length*/) { /* Init socket ext */ @@ -115,7 +115,7 @@ private: us_socket_context_on_close(SSL, getSocketContext(), [](us_socket_t *s, int /*code*/, void */*reason*/) { ((AsyncSocket *)s)->uncorkWithoutSending(); - + /* Get socket ext */ HttpResponseData *httpResponseData = (HttpResponseData *) us_socket_ext(SSL, s); @@ -129,7 +129,7 @@ private: if (httpResponseData->onAborted) { httpResponseData->onAborted((HttpResponse *)s, httpResponseData->userData); } - + /* Destruct socket ext */ httpResponseData->~HttpResponseData(); @@ -221,7 +221,7 @@ private: } /* Was the socket closed? */ - if (us_socket_is_closed(SSL, (struct us_socket_t *) s)) { + if (us_socket_is_closed(SSL, (us_socket_t *) s)) { return nullptr; } @@ -377,7 +377,7 @@ private: return s; } - /* We need to drain any remaining buffered data if success == true*/ + /* We need to drain any remaining buffered data if success == true*/ } /* Drain any socket buffer, this might empty our backpressure and thus finish the request */ @@ -441,7 +441,7 @@ public: return nullptr; } // for servers this is only valid when request cert is enabled - + /* Init socket context data */ auto* httpContextData = new ((HttpContextData *) us_socket_context_ext(SSL, (us_socket_context_t *) httpContext)) HttpContextData(); if(options.request_cert && options.reject_unauthorized) { @@ -465,16 +465,10 @@ public: } /* Register an HTTP route handler acording to URL pattern */ - void onHttp(std::string method, std::string pattern, MoveOnlyFunction *, HttpRequest *)> &&handler, bool upgrade = false) { - HttpContextData *httpContextData = getSocketContextData(); + void onHttp(std::string_view method, std::string_view pattern, MoveOnlyFunction *, HttpRequest *)> &&handler, bool upgrade = false) { + HttpContextData *httpContextData = getSocketContextData(); - /* Todo: This is ugly, fix */ - std::vector methods; - if (method == "*") { - methods = {"*"}; - } else { - methods = {method}; - } + std::vector methods{std::string(method)}; uint32_t priority = method == "*" ? httpContextData->currentRouter->LOW_PRIORITY : (upgrade ? httpContextData->currentRouter->HIGH_PRIORITY : httpContextData->currentRouter->MEDIUM_PRIORITY); @@ -495,7 +489,6 @@ public: i++; } parameterOffsets[std::string(pattern.data() + start, i - start)] = offset; - //std::cout << "<" << std::string(pattern.data() + start, i - start) << "> is offset " << offset; offset++; } } @@ -529,7 +522,7 @@ public: // we dont depend on libuv ref for keeping it alive if (socket) { us_socket_unref(&socket->s); - } + } return socket; } diff --git a/packages/bun-uws/src/HttpParser.h b/packages/bun-uws/src/HttpParser.h index 3eb88e353e..c337b8e97b 100644 --- a/packages/bun-uws/src/HttpParser.h +++ b/packages/bun-uws/src/HttpParser.h @@ -141,13 +141,13 @@ namespace uWS std::string_view getFullUrl() { - return std::string_view(headers->value.data(), headers->value.length()); + return headers->value; } /* Hack: this should be getMethod */ std::string_view getCaseSensitiveMethod() { - return std::string_view(headers->key.data(), headers->key.length()); + return headers->key; } std::string_view getMethod() @@ -158,7 +158,7 @@ namespace uWS ((char *)headers->key.data())[i] |= 32; } - return std::string_view(headers->key.data(), headers->key.length()); + return headers->key; } /* Returns the raw querystring as a whole, still encoded */ @@ -167,7 +167,7 @@ namespace uWS if (querySeparator < headers->value.length()) { /* Strip the initial ? */ - return std::string_view(headers->value.data() + querySeparator + 1, headers->value.length() - querySeparator - 1); + return headers->value.substr(querySeparator + 1); } else { @@ -179,9 +179,7 @@ namespace uWS std::string_view getQuery(std::string_view key) { /* Raw querystring including initial '?' sign */ - std::string_view queryString = std::string_view(headers->value.data() + querySeparator, headers->value.length() - querySeparator); - - return getDecodedQueryValue(key, queryString); + return getDecodedQueryValue(key, headers->value.substr(querySeparator)); } void setParameters(std::pair parameters) @@ -569,7 +567,7 @@ namespace uWS * From here we return either [consumed, user] for "keep going", * or [consumed, nullptr] for "break; I am closed or upgraded to websocket" * or [whatever, fullptr] for "break and close me, I am a parser error!" */ - template + template std::pair fenceAndConsumePostPadded(char *data, unsigned int length, void *user, void *reserved, HttpRequest *req, MoveOnlyFunction &requestHandler, MoveOnlyFunction &dataHandler) { /* How much data we CONSUMED (to throw away) */ @@ -669,7 +667,7 @@ namespace uWS remainingStreamingBytes = STATE_IS_CHUNKED; /* If consume minimally, we do not want to consume anything but we want to mark this as being chunked */ - if (!CONSUME_MINIMALLY) { + if constexpr (!ConsumeMinimally) { /* Go ahead and parse it (todo: better heuristics for emitting FIN to the app level) */ std::string_view dataToConsume(data, length); for (auto chunk : uWS::ChunkIterator(&dataToConsume, &remainingStreamingBytes)) { @@ -686,7 +684,7 @@ namespace uWS } } else if (contentLengthStringLen) { - if (!CONSUME_MINIMALLY) { + if constexpr (!ConsumeMinimally) { unsigned int emittable = (unsigned int) std::min(remainingStreamingBytes, length); dataHandler(user, std::string_view(data, emittable), emittable == remainingStreamingBytes); remainingStreamingBytes -= emittable; @@ -701,7 +699,7 @@ namespace uWS } /* Consume minimally should break as easrly as possible */ - if (CONSUME_MINIMALLY) { + if constexpr (ConsumeMinimally) { break; } } diff --git a/packages/bun-uws/src/HttpResponse.h b/packages/bun-uws/src/HttpResponse.h index e2201f01fb..ec8f7c52bb 100644 --- a/packages/bun-uws/src/HttpResponse.h +++ b/packages/bun-uws/src/HttpResponse.h @@ -460,7 +460,7 @@ public: writeStatus(HTTP_200_OK); /* Do not allow sending 0 chunks, they mark end of response */ - if (!data.length()) { + if (data.empty()) { /* If you called us, then according to you it was fine to call us so it's fine to still call us */ return true; } diff --git a/packages/bun-uws/src/HttpRouter.h b/packages/bun-uws/src/HttpRouter.h index 80bf4cc094..ad9679ab74 100644 --- a/packages/bun-uws/src/HttpRouter.h +++ b/packages/bun-uws/src/HttpRouter.h @@ -36,7 +36,7 @@ namespace uWS { template struct HttpRouter { static constexpr std::string_view ANY_METHOD_TOKEN = "*"; - static const uint32_t HIGH_PRIORITY = 0xd0000000, MEDIUM_PRIORITY = 0xe0000000, LOW_PRIORITY = 0xf0000000; + static constexpr uint32_t HIGH_PRIORITY = 0xd0000000, MEDIUM_PRIORITY = 0xe0000000, LOW_PRIORITY = 0xf0000000; private: USERDATA userData; @@ -60,12 +60,12 @@ private: std::vector handlers = {}; bool isHighPriority = false; - Node(std::string name) : name(name) {} + Node(std::string name) : name(std::move(name)) {} } root = {"rootNode"}; /* Sort wildcards after alphanum */ - int lexicalOrder(std::string &name) { - if (!name.length()) { + int lexicalOrder(std::string_view name) { + if (name.empty()) { return 2; } if (name[0] == ':') { @@ -79,7 +79,7 @@ private: /* Advance from parent to child, adding child if necessary */ Node *getNode(Node *parent, std::string child, bool isHighPriority) { - for (std::unique_ptr &node : parent->children) { + for (const std::unique_ptr &node : parent->children) { if (node->name == child && node->isHighPriority == isHighPriority) { return node.get(); } @@ -88,14 +88,13 @@ private: /* Insert sorted, but keep order if parent is root (we sort methods by priority elsewhere) */ std::unique_ptr newNode(new Node(child)); newNode->isHighPriority = isHighPriority; - return parent->children.emplace(std::upper_bound(parent->children.begin(), parent->children.end(), newNode, [parent, this](auto &a, auto &b) { - + auto iter = std::upper_bound(parent->children.begin(), parent->children.end(), newNode, [parent, this](auto &a, auto &b) { if (a->isHighPriority != b->isHighPriority) { return a->isHighPriority; } - - return b->name.length() && (parent != &root) && (lexicalOrder(b->name) < lexicalOrder(a->name)); - }), std::move(newNode))->get(); + return !b->name.empty() && (parent != &root) && (lexicalOrder(b->name) < lexicalOrder(a->name)); + }); + return parent->children.emplace(iter, std::move(newNode))->get(); } /* Basically a pre-allocated stack */ @@ -182,14 +181,14 @@ private: } for (auto &p : parent->children) { - if (p->name.length() && p->name[0] == '*') { + if (p->name.starts_with('*')) { /* Wildcard match (can be seen as a shortcut) */ for (uint32_t handler : p->handlers) { if (handlers[handler & HANDLER_MASK](this)) { return true; } } - } else if (p->name.length() && p->name[0] == ':' && segment.length()) { + } else if (p->name.starts_with(':') && !segment.empty()) { /* Parameter match */ routeParameters.push(segment); if (executeHandlers(p.get(), urlSegment + 1, userData)) { @@ -207,17 +206,17 @@ private: } /* Scans for one matching handler, returning the handler and its priority or UINT32_MAX for not found */ - uint32_t findHandler(std::string method, std::string pattern, uint32_t priority) { - for (std::unique_ptr &node : root.children) { + uint32_t findHandler(std::string_view method, std::string_view pattern, uint32_t priority) { + for (const std::unique_ptr &node : root.children) { if (method == node->name) { setUrl(pattern); Node *n = node.get(); for (int i = 0; !getUrlSegment(i).second; i++) { /* Go to next segment or quit */ - std::string segment = std::string(getUrlSegment(i).first); + std::string segment(getUrlSegment(i).first); Node *next = nullptr; - for (std::unique_ptr &child : n->children) { - if (((segment.length() && child->name.length() && segment[0] == ':' && child->name[0] == ':') || child->name == segment) && child->isHighPriority == (priority == HIGH_PRIORITY)) { + for (const std::unique_ptr &child : n->children) { + if (((segment.starts_with(':') && child->name.starts_with(':')) || child->name == segment) && child->isHighPriority == (priority == HIGH_PRIORITY)) { next = child.get(); break; } @@ -242,7 +241,7 @@ private: public: HttpRouter() { /* Always have ANY route */ - getNode(&root, std::string(ANY_METHOD_TOKEN.data(), ANY_METHOD_TOKEN.length()), false); + getNode(&root, std::string(ANY_METHOD_TOKEN), false); } std::pair getParameters() { @@ -279,25 +278,26 @@ public: } /* Adds the corresponding entires in matching tree and handler list */ - void add(std::vector methods, std::string pattern, MoveOnlyFunction &&handler, uint32_t priority = MEDIUM_PRIORITY) { + void add(const std::vector &methods, std::string_view pattern, MoveOnlyFunction &&handler, uint32_t priority = MEDIUM_PRIORITY) { /* First remove existing handler */ remove(methods[0], pattern, priority); - - for (std::string method : methods) { + + for (const std::string &method : methods) { /* Lookup method */ Node *node = getNode(&root, method, false); /* Iterate over all segments */ setUrl(pattern); for (int i = 0; !getUrlSegment(i).second; i++) { std::string strippedSegment(getUrlSegment(i).first); - if (strippedSegment.length() && strippedSegment[0] == ':') { + if (strippedSegment.length() > 1 && strippedSegment[0] == ':') { /* Parameter routes must be named only : */ - strippedSegment = ":"; + strippedSegment.resize(1); } node = getNode(node, strippedSegment, priority == HIGH_PRIORITY); } /* Insert handler in order sorted by priority (most significant 1 byte) */ - node->handlers.insert(std::upper_bound(node->handlers.begin(), node->handlers.end(), (uint32_t) (priority | handlers.size())), (uint32_t) (priority | handlers.size())); + uint32_t new_priority(priority | handlers.size()); + node->handlers.insert(std::upper_bound(node->handlers.begin(), node->handlers.end(), new_priority), new_priority); } /* Alloate this handler */ @@ -359,7 +359,7 @@ public: /* Removes ALL routes with the same handler as can be found with the given parameters. * Removing a wildcard is done by removing ONE OF the methods the wildcard would match with. * Example: If wildcard includes POST, GET, PUT, you can remove ALL THREE by removing GET. */ - bool remove(std::string method, std::string pattern, uint32_t priority) { + bool remove(std::string_view method, std::string_view pattern, uint32_t priority) { uint32_t handler = findHandler(method, pattern, priority); if (handler == UINT32_MAX) { /* Not found or already removed, do nothing */