mirror of https://github.com/JAJames/Jupiter.git
Jessica James
3 years ago
4 changed files with 151 additions and 323 deletions
@ -1,177 +0,0 @@ |
|||
/**
|
|||
* Copyright (C) 2016 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#if !defined _HTTP_QUERYSTRING_H_HEADER |
|||
#define _HTTP_QUERYSTRING_H_HEADER |
|||
|
|||
#include <unordered_map> |
|||
#include <charconv> |
|||
|
|||
/**
|
|||
* @file HTTP_QueryString.h |
|||
* @brief Provides parsing for HTTP Query Strings. |
|||
*/ |
|||
|
|||
namespace Jupiter |
|||
{ |
|||
namespace HTTP |
|||
{ |
|||
/**
|
|||
* @brief Provides parsing for HTML form responses. |
|||
* Note: This is essentially the same thing as QueryString, except key/value pairs are pared into 'table'. |
|||
*/ |
|||
class HTMLFormResponse |
|||
{ |
|||
public: |
|||
HTMLFormResponse() = delete; |
|||
inline HTMLFormResponse(std::string_view query_string) : HTMLFormResponse(query_string.data(), query_string.size()) {} |
|||
inline HTMLFormResponse(const char *ptr, size_t str_size); |
|||
using TableType = std::unordered_map<std::string, std::string, jessilib::text_hash, jessilib::text_equal>; |
|||
#ifdef __cpp_lib_generic_unordered_lookup |
|||
using InKeyType = std::string_view; |
|||
#else // We can't use std::string_view for InKeyType until GCC 11 & clang 12, and I still want to support GCC 9
|
|||
using InKeyType = const std::string&; |
|||
|
|||
template<typename CastT> |
|||
CastT tableGetCast(std::string_view in_key, const CastT &in_value) const { |
|||
return tableGetCast<CastT>(static_cast<std::string>(in_key), in_value); |
|||
} |
|||
|
|||
std::string_view tableGet(std::string_view in_key, std::string_view in_value) const { |
|||
return tableGet(static_cast<std::string>(in_key), in_value); |
|||
} |
|||
#endif // __cpp_lib_generic_unordered_lookup
|
|||
|
|||
template<typename CastT> |
|||
CastT tableGetCast(InKeyType in_key, const CastT &in_value) const { |
|||
CastT result = in_value; |
|||
auto item = table.find(in_key); |
|||
if (item != table.end()) { |
|||
std::from_chars(item->second.data(), item->second.data() + item->second.size(), result); |
|||
return result; |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
auto tableFind(InKeyType in_key) const { |
|||
return table.find(in_key); |
|||
} |
|||
|
|||
#ifndef __cpp_lib_generic_unordered_lookup |
|||
auto tableFind(std::string_view in_key) const { |
|||
return tableFind(static_cast<std::string>(in_key)); |
|||
} |
|||
#endif // __cpp_lib_generic_unordered_lookup
|
|||
|
|||
std::string_view tableGet(InKeyType in_key, std::string_view in_value) const { |
|||
auto item = table.find(in_key); |
|||
if (item != table.end()) { |
|||
return item->second; |
|||
} |
|||
|
|||
return in_value; |
|||
} |
|||
|
|||
TableType table; |
|||
std::string m_parsed; |
|||
}; |
|||
} |
|||
} |
|||
|
|||
/** Implementation */ |
|||
|
|||
inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t str_size) { |
|||
std::string_view in_view{ ptr, str_size }; |
|||
if (str_size < 3) { // not enough room for "%XX", therefore no escaped characters to parse
|
|||
m_parsed = in_view; |
|||
return; |
|||
} |
|||
m_parsed.resize(in_view.size()); |
|||
|
|||
const char *end = ptr + str_size - 2; |
|||
char* buf = m_parsed.data(); |
|||
const char *token_start = buf; |
|||
int val; |
|||
std::string key; |
|||
|
|||
while (ptr != end) |
|||
{ |
|||
if (*ptr == '%') |
|||
{ |
|||
if ((val = Jupiter_getHex(*++ptr)) != -1) |
|||
{ |
|||
*buf = static_cast<uint8_t>(val) << 4; |
|||
if ((val = Jupiter_getHex(*++ptr)) != -1) |
|||
*buf |= val; |
|||
|
|||
++buf, ++ptr; |
|||
if (ptr > end) |
|||
{ |
|||
if (ptr == end + 1) // copy 1 remaining character
|
|||
{ |
|||
*buf = *ptr; |
|||
++buf; |
|||
} |
|||
m_parsed.erase(buf - m_parsed.data()); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
else if (*ptr == '&') // End of key/value, start of key
|
|||
{ |
|||
if (!key.empty()) { // A key was already set; end of value
|
|||
Jupiter::HTTP::HTMLFormResponse::table[key] = std::string_view(token_start, buf - token_start); |
|||
} |
|||
|
|||
key = std::string_view{}; |
|||
++buf, ++ptr; |
|||
token_start = buf; |
|||
} |
|||
else if (*ptr == '=') // End of key, start of value
|
|||
{ |
|||
key = std::string_view(token_start, buf - token_start); |
|||
++buf, ++ptr; |
|||
token_start = buf; |
|||
} |
|||
else // Copy character
|
|||
{ |
|||
*buf = *ptr; |
|||
++buf, ++ptr; |
|||
} |
|||
} |
|||
|
|||
// copy last 2 characters
|
|||
*buf = *ptr; |
|||
|
|||
if (*buf == '=') // End of key, start of value
|
|||
{ |
|||
key = std::string_view(token_start, ++buf - token_start); |
|||
*buf = *++ptr; |
|||
Jupiter::HTTP::HTMLFormResponse::table[key] = std::string_view(ptr, 1); |
|||
} |
|||
else |
|||
*++buf = *++ptr; |
|||
|
|||
if (!key.empty()) // A key was already set; end of value
|
|||
Jupiter::HTTP::HTMLFormResponse::table[key] = std::string_view(token_start, buf - token_start + 1); |
|||
|
|||
m_parsed.erase(buf + 1 - m_parsed.data()); // TODO: double check where this +1 came from? actually just replace this
|
|||
} |
|||
|
|||
#endif // _HTTP_QUERYSTRING_H_HEADER
|
@ -1 +1 @@ |
|||
Subproject commit 8d3efe083522c94a0dcfd31f34a07130b824f215 |
|||
Subproject commit ea14492235d22bad37de6612850b2fef322ba119 |
Loading…
Reference in new issue