diff options
Diffstat (limited to 'zenhttp/httpserver.cpp')
| -rw-r--r-- | zenhttp/httpserver.cpp | 99 |
1 files changed, 65 insertions, 34 deletions
diff --git a/zenhttp/httpserver.cpp b/zenhttp/httpserver.cpp index f97ac0067..5b5738fc4 100644 --- a/zenhttp/httpserver.cpp +++ b/zenhttp/httpserver.cpp @@ -19,6 +19,7 @@ #include <conio.h> #include <new.h> #include <charconv> +#include <mutex> #include <span> #include <string_view> @@ -53,59 +54,81 @@ MapContentTypeToString(HttpContentType ContentType) case HttpContentType::kCbPackageOffer: return "application/x-ue-offer"sv; + case HttpContentType::kCompressedBinary: + return "application/x-ue-comp"sv; + case HttpContentType::kYAML: return "text/yaml"sv; } } -static const uint32_t HashBinary = HashStringDjb2("application/octet-stream"sv); -static const uint32_t HashJson = HashStringDjb2("application/json"sv); -static const uint32_t HashYaml = HashStringDjb2("text/yaml"sv); -static const uint32_t HashText = HashStringDjb2("text/plain"sv); -static const uint32_t HashCompactBinary = HashStringDjb2("application/x-ue-cb"sv); -static const uint32_t HashCompactBinaryPackage = HashStringDjb2("application/x-ue-cbpkg"sv); -static const uint32_t HashCompactBinaryPackageOffer = HashStringDjb2("application/x-ue-offer"sv); +////////////////////////////////////////////////////////////////////////// + +static constinit uint32_t HashBinary = HashStringDjb2("application/octet-stream"sv); +static constinit uint32_t HashJson = HashStringDjb2("application/json"sv); +static constinit uint32_t HashYaml = HashStringDjb2("text/yaml"sv); +static constinit uint32_t HashText = HashStringDjb2("text/plain"sv); +static constinit uint32_t HashCompactBinary = HashStringDjb2("application/x-ue-cb"sv); +static constinit uint32_t HashCompactBinaryPackage = HashStringDjb2("application/x-ue-cbpkg"sv); +static constinit uint32_t HashCompactBinaryPackageOffer = HashStringDjb2("application/x-ue-offer"sv); +static constinit uint32_t HashCompressedBinary = HashStringDjb2("application/x-ue-comp"sv); + +std::once_flag InitContentTypeLookup; + +struct HashedTypeEntry +{ + uint32_t Hash; + HttpContentType Type; +} TypeHashTable[] = {{HashBinary, HttpContentType::kBinary}, + {HashCompactBinary, HttpContentType::kCbObject}, + {HashCompactBinaryPackage, HttpContentType::kCbPackage}, + {HashCompactBinaryPackageOffer, HttpContentType::kCbPackageOffer}, + {HashJson, HttpContentType::kJSON}, + {HashYaml, HttpContentType::kYAML}, + {HashText, HttpContentType::kText}, + {HashCompressedBinary, HttpContentType::kCompressedBinary}}; HttpContentType -ParseContentType(const std::string_view& ContentTypeString) +ParseContentTypeImpl(const std::string_view& ContentTypeString) { if (!ContentTypeString.empty()) { const uint32_t CtHash = HashStringDjb2(ContentTypeString); - if (CtHash == HashBinary) - { - return HttpContentType::kBinary; - } - else if (CtHash == HashCompactBinary) - { - return HttpContentType::kCbObject; - } - else if (CtHash == HashCompactBinaryPackage) - { - return HttpContentType::kCbPackage; - } - else if (CtHash == HashCompactBinaryPackageOffer) - { - return HttpContentType::kCbPackageOffer; - } - else if (CtHash == HashJson) - { - return HttpContentType::kJSON; - } - else if (CtHash == HashYaml) - { - return HttpContentType::kYAML; - } - else if (CtHash == HashText) + if (auto It = std::lower_bound(std::begin(TypeHashTable), + std::end(TypeHashTable), + CtHash, + [](const HashedTypeEntry& Lhs, const uint32_t Rhs) { return Lhs.Hash < Rhs; }); + It != std::end(TypeHashTable)) { - return HttpContentType::kText; + if (It->Hash == CtHash) + { + return It->Type; + } } } return HttpContentType::kUnknownContentType; } +HttpContentType +ParseContentTypeInit(const std::string_view& ContentTypeString) +{ + std::call_once(InitContentTypeLookup, [] { + std::sort(std::begin(TypeHashTable), std::end(TypeHashTable), [](const HashedTypeEntry& Lhs, const HashedTypeEntry& Rhs) { + return Lhs.Hash < Rhs.Hash; + }); + }); + + ParseContentType = ParseContentTypeImpl; + + return ParseContentTypeImpl(ContentTypeString); +} + +HttpContentType (*ParseContentType)(const std::string_view& ContentTypeString) = &ParseContentTypeInit; + +////////////////////////////////////////////////////////////////////////// + const char* ReasonStringForHttpResultCode(int HttpCode) { @@ -523,6 +546,14 @@ TEST_CASE("http") // TestHttpServerRequest req{}; // r.HandleRequest(req); } + + SUBCASE("content-type") + { + for (uint8_t i = 0; i < uint8_t(HttpContentType::kCOUNT); ++i) + { + CHECK_EQ(HttpContentType(i), ParseContentType(MapContentTypeToString(HttpContentType(i)))); + } + } } void |