Browse Source

Remove tokenize() and adjust code as necessary; various cleanup

task/remove_strings
Jessica James 3 years ago
parent
commit
714d660508
  1. 2
      CMakeLists.txt
  2. 333
      src/common/HTTP_Server.cpp
  3. 39
      src/common/IRC_Client.cpp
  4. 264
      src/common/Socket.cpp
  5. 66
      src/include/Jupiter/HTTP_QueryString.h
  6. 56
      src/include/Jupiter/HTTP_Server.h
  7. 4
      src/include/Jupiter/IRC_Client.h
  8. 99
      src/include/Jupiter/Readable_String.h
  9. 286
      src/include/Jupiter/Readable_String_Imp.h
  10. 21
      src/include/Jupiter/Reference_String.h
  11. 26
      src/include/Jupiter/Reference_String_Imp.h
  12. 2
      src/include/Jupiter/Socket.h
  13. 42
      src/include/Jupiter/String.hpp
  14. 64
      src/include/Jupiter/String_Imp.h

2
CMakeLists.txt

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.0)
project(jupiter)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 20)
include(build/CMakeLists.txt)

333
src/common/HTTP_Server.cpp

@ -18,6 +18,9 @@
#include <ctime>
#include <chrono>
#include <numeric>
#include "jessilib/split.hpp"
#include "jessilib/unicode.hpp"
#include "String.hpp"
#include "Reference_String.h"
#include "TCPSocket.h"
@ -25,8 +28,25 @@
#include "HTTP_Server.h"
using namespace Jupiter::literals;
using namespace std::literals;
static const Jupiter::ReferenceString HTTP_REQUEST_ENDING = "\r\n\r\n"_jrs;
static const std::string_view HTTP_REQUEST_ENDING = "\r\n\r\n"sv;
template<typename ResultT = unsigned int, typename InT>
ResultT calc_checksum(const InT& in_container) {
ResultT result{};
result = std::accumulate(in_container.begin(), in_container.end(), result);
return result;
}
template<typename ResultT = unsigned int, typename InT>
ResultT calc_checksumi(const InT& in_container) {
ResultT result{};
result = std::accumulate(in_container.begin(), in_container.end(), result, [](ResultT current_sum, typename InT::value_type current_element) {
return current_sum + jessilib::fold(current_element);
});
return result;
}
// HTTPCommand
@ -49,19 +69,21 @@ enum HTTPVersion
// HTTP::Server::Content
Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name) {
Jupiter::HTTP::Server::Content::Content(std::string in_name, Jupiter::HTTP::Server::HTTPFunction in_function)
: name(std::move(in_name)) {
Jupiter::HTTP::Server::Content::function = in_function;
Jupiter::HTTP::Server::Content::name_checksum = Jupiter::HTTP::Server::Content::name.calcChecksum(); // switch to calcChecksumi to make case-insensitive
Jupiter::HTTP::Server::Content::name_checksum = calc_checksum(name); // switch to calcChecksumi to make case-insensitive
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string) {
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(std::string_view query_string) {
return Jupiter::HTTP::Server::Content::function(query_string);
}
// HTTP::Server::Directory
Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name) {
name_checksum = Jupiter::HTTP::Server::Directory::name.calcChecksum();
Jupiter::HTTP::Server::Directory::Directory(std::string in_name)
: name(std::move(in_name)) {
name_checksum = calc_checksum(name);
}
Jupiter::HTTP::Server::Directory::~Directory() {
@ -70,7 +92,7 @@ Jupiter::HTTP::Server::Directory::~Directory() {
// host/dir/content
// .hook("dir/subdir/", content)
void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, std::unique_ptr<Content> in_content) {
void Jupiter::HTTP::Server::Directory::hook(std::string_view in_name, std::unique_ptr<Content> in_content) {
Jupiter::ReferenceString in_name_ref = in_name;
in_name_ref.shiftRight(in_name_ref.span('/'));
@ -80,7 +102,7 @@ void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_na
}
size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
std::string_view dir_name;
if (index == Jupiter::INVALID_INDEX) {
dir_name = in_name_ref;
}
@ -89,17 +111,17 @@ void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_na
}
in_name_ref.shiftRight(dir_name.size());
unsigned int dir_name_checksum = dir_name.calcChecksum();
unsigned int dir_name_checksum = calc_checksum(dir_name);
index = directories.size();
for (auto& directory : directories) {
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) {
if (directory->name_checksum == dir_name_checksum && directory->name == dir_name) {
directory->hook(in_name_ref, std::move(in_content));
return;
}
}
// create directories
Directory* directory = directories.emplace_back(std::make_unique<Directory>(dir_name)).get();
Directory* directory = directories.emplace_back(std::make_unique<Directory>(static_cast<std::string>(dir_name))).get();
directory_add_loop: // TODO: for the love of god, why why why
in_name_ref.shiftRight(in_name_ref.span('/'));
@ -107,12 +129,12 @@ directory_add_loop: // TODO: for the love of god, why why why
// add directory
index = in_name_ref.find('/');
if (index != Jupiter::INVALID_INDEX) {
directory->directories.push_back(std::make_unique<Directory>(in_name_ref.substring(size_t{ 0 }, index)));
directory->directories.push_back(std::make_unique<Directory>(static_cast<std::string>(in_name_ref.substring(size_t{ 0 }, index))));
directory = directory->directories[directories.size() - 1].get();
in_name_ref.shiftRight(index + 1);
goto directory_add_loop;
}
directory->directories.push_back(std::make_unique<Directory>(in_name_ref));
directory->directories.push_back(std::make_unique<Directory>(static_cast<std::string>(in_name_ref)));
directory = directory->directories[directories.size() - 1].get();
}
@ -120,16 +142,16 @@ directory_add_loop: // TODO: for the love of god, why why why
directory->content.push_back(std::move(in_content));
}
bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name) {
bool Jupiter::HTTP::Server::Directory::remove(std::string_view path, std::string_view content_name) {
Jupiter::ReferenceString in_name_ref = path;
in_name_ref.shiftRight(in_name_ref.span('/'));
unsigned int checksum;
if (in_name_ref.isEmpty()) { // Remove content
checksum = content_name.calcChecksum();
checksum = calc_checksum(content_name);
for (auto itr = content.begin(); itr != content.end(); ++itr) {
auto& content_node = *itr;
if (content_node->name_checksum == checksum && content_node->name.equals(content_name)) {
if (content_node->name_checksum == checksum && content_node->name == content_name) {
content.erase(itr);
return true;
}
@ -140,50 +162,51 @@ bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &pat
// Call remove() on next directory in path
size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
std::string_view dir_name;
if (index == Jupiter::INVALID_INDEX)
dir_name = in_name_ref;
else
dir_name = in_name_ref.substring(size_t{ 0 }, index);
in_name_ref.shiftRight(dir_name.size());
checksum = dir_name.calcChecksum();
checksum = calc_checksum(dir_name);
for (auto& directory : directories) {
if (directory->name_checksum == checksum && directory->name.equals(dir_name)) {
if (directory->name_checksum == checksum && directory->name == dir_name) {
return directory->remove(in_name_ref, content_name);
}
}
return false;
}
bool Jupiter::HTTP::Server::Directory::has(const Jupiter::ReadableString &in_name)
{
bool Jupiter::HTTP::Server::Directory::has(std::string_view in_name) {
return find(in_name) != nullptr;
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jupiter::ReadableString &in_name)
{
Jupiter::ReferenceString in_name_ref = in_name;
in_name_ref.shiftRight(in_name_ref.span("/"_jrs));
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(std::string_view in_name) {
std::string_view in_name_ref = in_name;
while (!in_name_ref.empty() && in_name_ref.front() == '/') {
in_name.remove_prefix(1);
}
size_t index = in_name_ref.find('/');
if (index == Jupiter::INVALID_INDEX) { // Search content
unsigned int content_name_checksum = in_name_ref.calcChecksum();
unsigned int content_name_checksum = calc_checksum(in_name_ref);
index = content.size();
for (auto& content_item : content) {
if (content_item->name_checksum == content_name_checksum && content_item->name.equals(in_name_ref)) {
if (content_item->name_checksum == content_name_checksum && content_item->name == in_name_ref) {
return content_item.get();
}
}
return nullptr; // No such content
}
Jupiter::ReferenceString dir_name(in_name_ref.ptr(), index);
in_name_ref.shiftRight(dir_name.size() + 1);
unsigned int dir_name_checksum = dir_name.calcChecksum();
// Just use split_once?
std::string_view dir_name(in_name_ref.data(), index);
in_name_ref.remove_prefix(dir_name.size() + 1);
unsigned int dir_name_checksum = calc_checksum(dir_name);
for (auto& directory : directories) {
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) {
if (directory->name_checksum == dir_name_checksum && directory->name == dir_name) {
return directory->find(in_name_ref);
}
}
@ -191,7 +214,7 @@ Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jup
return nullptr; // No such directory
}
Jupiter::ReadableString* Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string) {
Jupiter::ReadableString* Jupiter::HTTP::Server::Directory::execute(std::string_view in_name, std::string_view query_string) {
Jupiter::HTTP::Server::Content *content_ptr = find(in_name);
if (content_ptr == nullptr)
return nullptr;
@ -201,15 +224,16 @@ Jupiter::ReadableString* Jupiter::HTTP::Server::Directory::execute(const Jupiter
// HTTP::Server::Host
Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name) {
name_checksum = Jupiter::HTTP::Server::Host::name.calcChecksumi();
Jupiter::HTTP::Server::Host::Host(std::string in_name)
: Directory(std::move(in_name)) {
name_checksum = calc_checksumi(name);
}
// HTTPSession struct
struct HTTPSession {
Jupiter::Socket sock;
Jupiter::String request;
std::string request;
bool keep_alive = false;
Jupiter::HTTP::Server::Host* host = nullptr;
HTTPVersion version = HTTPVersion::HTTP_1_0;
@ -238,17 +262,17 @@ struct Jupiter::HTTP::Server::Data {
bool permit_keept_alive = true; // TODO: Config variable
/** Foward functions */
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
bool remove(const Jupiter::ReadableString &hostname);
//bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path);
bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
bool has(const Jupiter::ReadableString &hostname);
bool has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Jupiter::HTTP::Server::Host *find_host(const Jupiter::ReadableString &name);
Content* find(const Jupiter::ReadableString &name);
Content* find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
void hook(std::string_view host, std::string_view path, std::unique_ptr<Content> in_content);
bool remove(std::string_view hostname);
//bool remove(std::string_view hostname, std::string_view path);
bool remove(std::string_view hostname, std::string_view path, std::string_view name);
bool has(std::string_view hostname);
bool has(std::string_view hostname, std::string_view name);
Jupiter::HTTP::Server::Host *find_host(std::string_view name);
Content* find(std::string_view name);
Content* find(std::string_view hostname, std::string_view name);
Jupiter::ReadableString *execute(std::string_view name, std::string_view query_string);
Jupiter::ReadableString *execute(std::string_view hostname, std::string_view name, std::string_view query_string);
int process_request(HTTPSession &session);
@ -265,7 +289,7 @@ struct Jupiter::HTTP::Server::Data {
Jupiter::HTTP::Server::Data::Data() {
// hosts[0] is always the "global" namespace.
m_hosts.push_back(std::make_unique<Host>(Jupiter::HTTP::Server::global_namespace));
m_hosts.push_back(std::make_unique<Host>(static_cast<std::string>(Jupiter::HTTP::Server::global_namespace)));
}
// Data destructor
@ -275,14 +299,14 @@ Jupiter::HTTP::Server::Data::~Data() {
// Data functions
void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, std::unique_ptr<Content> in_content) {
void Jupiter::HTTP::Server::Data::hook(std::string_view hostname, std::string_view in_path, std::unique_ptr<Content> in_content) {
Jupiter::ReferenceString path = in_path;
Jupiter::ReferenceString dir_name;
Jupiter::HTTP::Server::Host* host = find_host(hostname);
if (host == nullptr) {
//host = new Jupiter::HTTP::Server::Host(hostname);
host = m_hosts.emplace_back(std::make_unique<Host>(hostname)).get();
host = m_hosts.emplace_back(std::make_unique<Host>(static_cast<std::string>(hostname))).get();
// OPTIMIZE: create directory tree and return.
}
@ -295,10 +319,10 @@ void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname,
}
}
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname) {
unsigned int name_checksum = hostname.calcChecksumi();
bool Jupiter::HTTP::Server::Data::remove(std::string_view hostname) {
unsigned int name_checksum = calc_checksumi(hostname);
for (auto host_itr = m_hosts.begin(); host_itr != m_hosts.end(); ++host_itr) {
if (name_checksum == (*host_itr)->name_checksum && (*host_itr)->name.equalsi(hostname)) {
if (name_checksum == (*host_itr)->name_checksum && jessilib::equalsi((*host_itr)->name, hostname)) {
m_hosts.erase(host_itr);
return true;
}
@ -307,7 +331,7 @@ bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname
}
// name: path/to/resource OR path/
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) {
bool Jupiter::HTTP::Server::Data::remove(std::string_view hostname, std::string_view path, std::string_view name) {
Jupiter::HTTP::Server::Host *host = find_host(hostname);
if (host == nullptr) {
return false;
@ -315,10 +339,10 @@ bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname
return host->remove(path, name);
}
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) {
unsigned int name_checksum = hostname.calcChecksumi();
bool Jupiter::HTTP::Server::Data::has(std::string_view hostname) {
unsigned int name_checksum = calc_checksumi(hostname);
for (const auto& host : m_hosts) {
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) {
if (name_checksum == host->name_checksum && jessilib::equalsi(host->name, hostname)) {
return true;
}
}
@ -326,13 +350,13 @@ bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) {
return false;
}
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) {
unsigned int name_checksum = hostname.calcChecksumi();
bool Jupiter::HTTP::Server::Data::has(std::string_view hostname, std::string_view name) {
unsigned int name_checksum = calc_checksumi(hostname);
for (const auto& host : m_hosts) {
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) {
name_checksum = name.calcChecksum(); // switch to equalsi to make case-insensitive
if (name_checksum == host->name_checksum && jessilib::equalsi(host->name, hostname)) {
name_checksum = calc_checksum(name); // switch to equalsi to make case-insensitive
for (const auto& content : host->content) {
if (name_checksum == content->name_checksum && content->name.equals(name)) { // switch to equalsi to make case-insensitive
if (name_checksum == content->name_checksum && content->name == name) { // switch to equalsi to make case-insensitive
return true;
}
}
@ -342,10 +366,10 @@ bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, c
return false;
}
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name) {
unsigned int name_checksum = name.calcChecksumi();
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(std::string_view name) {
unsigned int name_checksum = calc_checksumi(name);
for (const auto& host : m_hosts) {
if (name_checksum == host->name_checksum && host->name.equalsi(name)) {
if (name_checksum == host->name_checksum && host->name == name) {
return host.get();
}
}
@ -353,11 +377,11 @@ Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupite
return nullptr;
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name) {
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(std::string_view name) {
return m_hosts[0]->find(name);
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) {
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(std::string_view hostname, std::string_view name) {
Jupiter::HTTP::Server::Host *host = find_host(hostname);
if (host == nullptr)
return nullptr;
@ -365,7 +389,7 @@ Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter:
return host->find(name);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(std::string_view name, std::string_view query_string) {
Jupiter::HTTP::Server::Content *content = find(name);
if (content == nullptr)
return nullptr;
@ -373,7 +397,7 @@ Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::Rea
return content->execute(query_string);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(std::string_view hostname, std::string_view name, std::string_view query_string) {
Jupiter::HTTP::Server::Content *content = find(hostname, name);
if (content == nullptr)
return nullptr;
@ -389,11 +413,11 @@ char* html_time() {
}
int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> lines = Jupiter::ReferenceString::tokenize(session.request, STRING_LITERAL_AS_REFERENCE(ENDL));
auto lines = jessilib::split_view(session.request, "\r\n"sv);
HTTPCommand command = HTTPCommand::NONE_SPECIFIED;
Content *content = nullptr;
Jupiter::ReferenceString query_string;
Jupiter::ReferenceString first_token;
std::string_view query_string;
std::string_view first_token;
size_t index = 0;
size_t span;
@ -401,20 +425,20 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
{
size_t offset = 0;
while (index != 0)
offset += lines.tokens[--index].size() + 2;
offset += lines[--index].size() + 2;
return offset;
};
while (index != lines.token_count)
while (index != lines.size())
{
Jupiter::ReferenceString &line = lines.tokens[index++];
std::string_view line = lines[index++];
// trim front-end spaces.
span = line.span(" "_jrs);
if (span != 0)
line.shiftRight(span);
while (!line.empty() && line.front() == ' ') {
line.remove_prefix(1);
}
if (line.isEmpty()) // end of http request
if (!line.empty()) // end of http request
{
Jupiter::String result(256);
switch (command)
@ -424,7 +448,8 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
if (content != nullptr)
{
// 200 (success)
Jupiter::ReadableString *content_result = content->execute(query_string);
// TODO: remove referencestring warpper
Jupiter::ReadableString *content_result = content->execute(Jupiter::ReferenceString{query_string});
switch (session.version)
{
@ -517,97 +542,107 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
break;
}
if (session.keep_alive == false) // not keep-alive -- will be destroyed on return
if (session.keep_alive == false) {// not keep-alive -- will be destroyed on return
break;
if (index == lines.token_count) // end of packet
}
if (index == lines.size()) { // end of packet
session.request.erase();
else // end of request -- another request is following
session.request.shiftRight(get_line_offset(index));
}
else { // end of request -- another request is following
// Maybe there's still some value in a shifty string, to avoid substr calls & heap allocations...
session.request = session.request.substr(get_line_offset(index));
}
if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // there's another full request already received
if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // there's another full request already received
return process_request(session);
}
break;
}
// Not empty
first_token = line.getToken(0, ' ');
auto first_split = jessilib::split_once_view(line, ' ');
first_token = first_split.first;
if (first_token.get(first_token.size() - 1) == ':') // header field
{
first_token.truncate(1); // trim trailing ':'
if (first_token.equalsi("HOST"_jrs))
session.host = find_host(line.getWord(1, " "));
else if (first_token.equalsi("CONNECTION"_jrs))
{
Jupiter::ReferenceString connection_type = line.getWord(1, " ");
if (connection_type.equalsi("keep-alive"_jrs))
if (first_token.back() == ':') { // header field
first_token.remove_suffix(1); // trim trailing ':'
if (jessilib::equalsi(first_token, "HOST"sv)) {
session.host = find_host(first_split.second);
}
else if (jessilib::equalsi(first_token, "CONNECTION"sv)) {
std::string_view connection_type = first_split.second;
if (jessilib::equalsi(connection_type, "keep-alive"sv)) {
session.keep_alive = permit_keept_alive;
}
}
}
else // command
{
if (first_token.equals("GET"_jrs))
{
else { // command
if (first_token == "GET"sv) {
command = HTTPCommand::GET;
query_string = line.getWord(1, " ");
auto second_split = jessilib::split_once_view(first_split.second, ' ');
query_string = second_split.first;
span = query_string.find('?'); // repurposing 'span'
if (span == Jupiter::INVALID_INDEX)
{
if (session.host == nullptr)
if (span == Jupiter::INVALID_INDEX) {
if (session.host == nullptr) {
content = find(query_string);
else
}
else {
content = session.host->find(query_string);
query_string.erase();
}
query_string = std::string_view{};
}
else
{
if (session.host == nullptr)
content = find(query_string.substring(size_t{ 0 }, span));
else
content = session.host->find(query_string.substring(size_t{ 0 }, span));
query_string.shiftRight(span + 1);
else {
if (session.host == nullptr) {
content = find(query_string.substr(size_t{ 0 }, span));
}
else {
content = session.host->find(query_string.substr(size_t{ 0 }, span));
}
query_string.remove_prefix(span + 1);
// decode query_string here
}
Jupiter::ReferenceString protocol_str = line.getWord(2, " ");
if (protocol_str.equalsi("http/1.0"_jrs))
std::string_view protocol_str = second_split.second;
if (jessilib::equalsi(protocol_str, "http/1.0"sv)) {
session.version = HTTPVersion::HTTP_1_0;
else if (protocol_str.equalsi("http/1.1"_jrs))
{
}
else if (jessilib::equalsi(protocol_str, "http/1.1"sv)) {
session.version = HTTPVersion::HTTP_1_1;
session.keep_alive = permit_keept_alive;
}
}
else if (first_token.equals("HEAD"_jrs))
{
else if (first_token == "HEAD"sv) {
command = HTTPCommand::HEAD;
query_string = line.getWord(1, " ");
auto second_split = jessilib::split_once_view(first_split.second, ' ');
query_string = second_split.first;
span = query_string.find('?'); // repurposing 'span'
if (span == Jupiter::INVALID_INDEX)
{
if (session.host == nullptr)
if (span == Jupiter::INVALID_INDEX) {
if (session.host == nullptr) {
content = find(query_string);
else
}
else {
content = session.host->find(query_string);
query_string.erase();
}
query_string = std::string_view{};
}
else
{
if (session.host == nullptr)
content = find(query_string.substring(size_t{ 0 }, span));
else
content = session.host->find(query_string.substring(size_t{ 0 }, span));
query_string.shiftRight(span + 1);
else {
if (session.host == nullptr) {
content = find(query_string.substr(size_t{ 0 }, span));
}
else {
content = session.host->find(query_string.substr(size_t{ 0 }, span));
}
query_string.remove_prefix(span + 1);
// decode query_string here
}
Jupiter::ReferenceString protocol_str = line.getWord(2, " ");
if (protocol_str.equalsi("http/1.0"_jrs))
std::string_view protocol_str = second_split.second;
if (jessilib::equalsi(protocol_str, "http/1.0"sv)) {
session.version = HTTPVersion::HTTP_1_0;
else if (protocol_str.equalsi("http/1.1"_jrs))
{
}
else if (jessilib::equalsi(protocol_str, "http/1.1"sv)) {
session.version = HTTPVersion::HTTP_1_1;
session.keep_alive = permit_keept_alive;
}
@ -638,47 +673,43 @@ Jupiter::HTTP::Server::~Server() {
// Server functions
void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, std::unique_ptr<Content> content) {
void Jupiter::HTTP::Server::hook(std::string_view host, std::string_view name, std::unique_ptr<Content> content) {
return m_data->hook(host, name, std::move(content));
}
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host) {
bool Jupiter::HTTP::Server::remove(std::string_view host) {
return m_data->remove(host);
}
/*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path) {
return m_data->remove(host, path);
}*/
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) {
bool Jupiter::HTTP::Server::remove(std::string_view host, std::string_view path, std::string_view name) {
return m_data->remove(host, path, name);
}
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host) {
bool Jupiter::HTTP::Server::has(std::string_view host) {
return m_data->has(host);
}
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) {
bool Jupiter::HTTP::Server::has(std::string_view host, std::string_view name) {
return m_data->has(host, name);
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name) {
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(std::string_view name) {
return m_data->find(name);
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) {
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(std::string_view host, std::string_view name) {
return m_data->find(host, name);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(std::string_view name, std::string_view query_string) {
return m_data->execute(name, query_string);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(std::string_view host, std::string_view name, std::string_view query_string) {
return m_data->execute(host, name, query_string);
}
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port) {
bool Jupiter::HTTP::Server::bind(std::string_view hostname, uint16_t port) {
auto socket = std::make_unique<Jupiter::TCPSocket>();
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) {
socket->setBlocking(false);
@ -689,7 +720,7 @@ bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16
return false;
}
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port) {
bool Jupiter::HTTP::Server::tls_bind(std::string_view hostname, uint16_t port) {
auto socket = std::make_unique<Jupiter::SecureTCPSocket>();
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) {
m_data->m_ports.push_back(std::move(socket));
@ -715,7 +746,7 @@ int Jupiter::HTTP::Server::think() {
continue;
}
else if (session->sock.recv() > 0) {
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer();
std::string_view sock_buffer = session->sock.getBuffer();
if (session->request.size() + sock_buffer.size() <= m_data->max_request_size) { // accept
session->request += sock_buffer;
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
@ -756,7 +787,7 @@ int Jupiter::HTTP::Server::think() {
socket->setBlocking(false);
auto session = std::make_unique<HTTPSession>(std::move(*socket));
if (session->sock.recv() > 0) { // data received
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer();
std::string_view sock_buffer = session->sock.getBuffer();
if (sock_buffer.size() < m_data->max_request_size) { // accept
session->request = session->sock.getBuffer();
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request

39
src/common/IRC_Client.cpp

@ -19,6 +19,7 @@
#include <cstring>
#include <cstdio>
#include <ctime>
#include "jessilib/split.hpp"
#include "Jupiter.h"
#include "Functions.h"
#include "IRC_Client.h"
@ -449,8 +450,8 @@ size_t Jupiter::IRC::Client::messageChannels(const Jupiter::ReadableString &mess
return m_channels.size();
}
int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{
int Jupiter::IRC::Client::process_line(std::string_view in_line) {
Jupiter::ReferenceString line{in_line}; // TODO: remove this
if (line.isNotEmpty())
{
Jupiter::IRC::Client::writeToLogs(line);
@ -1317,36 +1318,34 @@ int Jupiter::IRC::Client::think()
if (tmp > 0)
{
// Process incoming data
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> result = Jupiter::ReferenceString::tokenize(m_socket->getBuffer(), "\r\n"_jrs);
if (result.token_count != 0)
{
if (result.tokens[0].size() > 0)
{
using namespace std::literals;
auto tokens = jessilib::split_view(m_socket->getBuffer(), "\r\n"sv);
if (tokens.size() != 0) {
if (tokens[0].size() > 0) {
// Ensure there's not a token getting split over separate buffers
if (m_last_line.size() > 0)
{
if (result.tokens[0][0] == '\n' && m_last_line[m_last_line.size() - 1] == '\r')
{
m_last_line.truncate(1); // Remove \r
std::string_view token_0 = tokens[0];
if (m_last_line.size() > 0) {
if (tokens[0][0] == '\n' && m_last_line[m_last_line.size() - 1] == '\r') {
m_last_line.pop_back();
Jupiter::IRC::Client::process_line(m_last_line);
m_last_line.erase();
result.tokens[0].shiftRight(1); // Remove \n
token_0.remove_prefix(1);
}
}
m_last_line += result.tokens[0];
m_last_line += token_0;
}
if (result.token_count != 1)
{
if (tokens.size() != 1) {
Jupiter::IRC::Client::process_line(m_last_line);
m_last_line = result.tokens[result.token_count - 1];
m_last_line = tokens[tokens.size() - 1];
for (size_t index = 1; index != result.token_count - 1; ++index)
if (Jupiter::IRC::Client::process_line(result.tokens[index]) != 0)
for (size_t index = 1; index != tokens.size() - 1; ++index) {
if (Jupiter::IRC::Client::process_line(tokens[index]) != 0) {
return handle_error(1);
}
}
}
}

264
src/common/Socket.cpp

@ -45,18 +45,15 @@ bool socketInit = false;
#pragma warning(disable: 4267)
#endif
void Jupiter::Socket::Buffer::set_length(size_t in_length)
{
void Jupiter::Socket::Buffer::set_length(size_t in_length) {
this->length = in_length;
}
char *Jupiter::Socket::Buffer::get_str() const
{
char *Jupiter::Socket::Buffer::get_str() const {
return this->str;
}
struct Jupiter::Socket::Data
{
struct Jupiter::Socket::Data {
Jupiter::Socket::Buffer buffer;
SocketType rawSock = INVALID_SOCKET;
unsigned short remote_port = 0;
@ -73,13 +70,11 @@ struct Jupiter::Socket::Data
Data(const Data &);
};
Jupiter::Socket::Data::Data(size_t buffer_size)
{
Jupiter::Socket::Data::Data(size_t buffer_size) {
Jupiter::Socket::Data::buffer.setBufferSizeNoCopy(buffer_size);
}
Jupiter::Socket::Data::Data(const Data &source)
{
Jupiter::Socket::Data::Data(const Data &source) {
Jupiter::Socket::Data::buffer = source.buffer;
Jupiter::Socket::Data::remote_port = source.remote_port;
Jupiter::Socket::Data::bound_port = source.bound_port;
@ -93,60 +88,49 @@ Jupiter::Socket::Data::Data(const Data &source)
#endif
}
Jupiter::Socket &Jupiter::Socket::operator=(Jupiter::Socket &&source)
{
Jupiter::Socket &Jupiter::Socket::operator=(Jupiter::Socket &&source) {
Jupiter::Socket::data_ = source.data_;
source.data_ = nullptr;
return *this;
}
Jupiter::Socket::Socket() : Jupiter::Socket::Socket(512)
{
Jupiter::Socket::Socket() : Jupiter::Socket::Socket(512) {
}
Jupiter::Socket::Socket(size_t bufferSize)
{
Jupiter::Socket::Socket(size_t bufferSize) {
Jupiter::Socket::data_ = new Jupiter::Socket::Data(bufferSize);
}
Jupiter::Socket::Socket(Jupiter::Socket &&source)
{
Jupiter::Socket::Socket(Jupiter::Socket &&source) {
Jupiter::Socket::data_ = source.data_;
source.data_ = nullptr;
}
Jupiter::Socket::~Socket()
{
if (Jupiter::Socket::data_ != nullptr)
{
Jupiter::Socket::~Socket() {
if (Jupiter::Socket::data_ != nullptr) {
if (Jupiter::Socket::data_->rawSock > 0)
Jupiter::Socket::close();
delete Jupiter::Socket::data_;
}
}
void Jupiter::Socket::setType(int type)
{
void Jupiter::Socket::setType(int type) {
Jupiter::Socket::data_->sockType = type;
}
void Jupiter::Socket::setProtocol(int proto)
{
void Jupiter::Socket::setProtocol(int proto) {
Jupiter::Socket::data_->sockProto = proto;
}
int Jupiter::Socket::getType() const
{
int Jupiter::Socket::getType() const {
return Jupiter::Socket::data_->sockType;
}
int Jupiter::Socket::getProtocol() const
{
int Jupiter::Socket::getProtocol() const {
return Jupiter::Socket::data_->sockProto;
}
bool Jupiter::Socket::connect(addrinfo *info)
{
bool Jupiter::Socket::connect(addrinfo *info) {
#if defined _WIN32
if (!socketInit && !Jupiter::Socket::init())
return false;
@ -170,22 +154,17 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const
Jupiter::Socket::data_->remote_host = hostname;
Jupiter::Socket::data_->remote_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->remote_host.c_str(), std::to_string(Jupiter::Socket::data_->remote_port).c_str());
if (info_head != nullptr)
{
if (info_head != nullptr) {
addrinfo *info = info_head;
do
{
if (clientAddress != nullptr)
{
do {
if (clientAddress != nullptr) {
// bind will initialize our socket
if (Jupiter::Socket::bind(clientAddress, clientPort, false) == false)
break;
}
else
{
else {
Jupiter::Socket::data_->rawSock = socket(info->ai_family, Jupiter::Socket::data_->sockType, Jupiter::Socket::data_->sockProto);
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET)
{
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET) {
info = info->ai_next;
continue;
}
@ -220,20 +199,16 @@ bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andL
Jupiter::Socket::data_->bound_host = hostname;
Jupiter::Socket::data_->bound_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->bound_host.c_str(), std::to_string(Jupiter::Socket::data_->bound_port).c_str());
if (info_head != nullptr)
{
if (info_head != nullptr) {
addrinfo *info = info_head;
do
{
do {
Jupiter::Socket::data_->rawSock = socket(info->ai_family, Jupiter::Socket::data_->sockType, Jupiter::Socket::data_->sockProto);
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET)
{
if (Jupiter::Socket::data_->rawSock == INVALID_SOCKET) {
info = info->ai_next;
continue;
}
if (::bind(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR)
{
if (::bind(Jupiter::Socket::data_->rawSock, info->ai_addr, info->ai_addrlen) == SOCKET_ERROR) {
#if defined _WIN32
::closesocket(Jupiter::Socket::data_->rawSock);
#else // _WIN32
@ -254,19 +229,15 @@ bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andL
return false;
}
void Jupiter::Socket::shutdown()
{
if (Jupiter::Socket::data_ != nullptr)
{
void Jupiter::Socket::shutdown() {
if (Jupiter::Socket::data_ != nullptr) {
::shutdown(Jupiter::Socket::data_->rawSock, 2);
Jupiter::Socket::data_->is_shutdown = true;
}
}
void Jupiter::Socket::close()
{
if (Jupiter::Socket::data_ != nullptr)
{
void Jupiter::Socket::close() {
if (Jupiter::Socket::data_ != nullptr) {
if (Jupiter::Socket::data_->is_shutdown == false)
this->shutdown();
#if defined _WIN32
@ -278,137 +249,117 @@ void Jupiter::Socket::close()
}
}
bool Jupiter::Socket::isShutdown() const
{
bool Jupiter::Socket::isShutdown() const {
return Jupiter::Socket::data_->is_shutdown;
}
addrinfo *Jupiter::Socket::getAddrInfo(const char *hostname, const char *port) // static
{
addrinfo *Jupiter::Socket::getAddrInfo(const char *hostname, const char *port) { // static
addrinfo *ptr;
if (getaddrinfo(hostname, port, nullptr, &ptr)) return nullptr;
return ptr;
}
addrinfo *Jupiter::Socket::getStaticAddrInfo(const char *hostname, const char *port) // static
{
addrinfo *Jupiter::Socket::getStaticAddrInfo(const char *hostname, const char *port) { // static
static addrinfo *ptr = nullptr;
if (ptr != nullptr) freeaddrinfo(ptr);
ptr = Jupiter::Socket::getAddrInfo(hostname, port);
return ptr;
}
void Jupiter::Socket::freeAddrInfo(addrinfo *info) // static
{
void Jupiter::Socket::freeAddrInfo(addrinfo *info) { // static
freeaddrinfo(info);
}
addrinfo *Jupiter::Socket::getAddrInfo(addrinfo *addr, unsigned int result) // static
{
addrinfo *Jupiter::Socket::getAddrInfo(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = addr;
for (unsigned int i = 0; i != result && ptr != nullptr; i++) ptr = ptr->ai_next;
return ptr;
}
char *Jupiter::Socket::resolveAddress(const addrinfo *addr) // static
{
char *Jupiter::Socket::resolveAddress(const addrinfo *addr) { // static
static char resolved[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, NI_MAXHOST, 0, 0, NI_NUMERICHOST);
return resolved;
}
char *Jupiter::Socket::resolveAddress(addrinfo *addr, unsigned int result) // static
{
char *Jupiter::Socket::resolveAddress(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
return Jupiter::Socket::resolveAddress(ptr);
}
char *Jupiter::Socket::resolveAddress(const char *hostname, unsigned int result) // static
{
char *Jupiter::Socket::resolveAddress(const char *hostname, unsigned int result) { // static
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
return Jupiter::Socket::resolveAddress(info, result);
}
char *Jupiter::Socket::resolveHostname(addrinfo *addr) // static
{
char *Jupiter::Socket::resolveHostname(addrinfo *addr) { // static
static char resolved[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, sizeof(resolved), 0, 0, 0);
return resolved;
}
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr) // static
{
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr) { // static
char *resolved = new char[NI_MAXHOST];
getnameinfo(addr->ai_addr, addr->ai_addrlen, resolved, NI_MAXHOST, 0, 0, 0);
return resolved;
}
char *Jupiter::Socket::resolveHostname(addrinfo *addr, unsigned int result) // static
{
char *Jupiter::Socket::resolveHostname(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname(ptr);
}
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr, unsigned int result) // static
{
char *Jupiter::Socket::resolveHostname_alloc(addrinfo *addr, unsigned int result) { // static
addrinfo *ptr = Jupiter::Socket::getAddrInfo(addr, result);
if (ptr == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname_alloc(ptr);
}
char *Jupiter::Socket::resolveHostname(const char *hostname, unsigned int result) // static
{
char *Jupiter::Socket::resolveHostname(const char *hostname, unsigned int result) { // static
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname(info, result);
}
char *Jupiter::Socket::resolveHostname_alloc(const char *hostname, unsigned int result) // static
{
char *Jupiter::Socket::resolveHostname_alloc(const char *hostname, unsigned int result) { // static
addrinfo *info = Jupiter::Socket::getAddrInfo(hostname, 0);
if (info == nullptr) return nullptr;
return Jupiter::Socket::resolveHostname_alloc(info, result);
}
uint32_t Jupiter::Socket::pton4(const char *str)
{
uint32_t Jupiter::Socket::pton4(const char *str) {
in_addr r;
if (inet_pton(AF_INET, str, &r) <= 0)
return 0;
return *reinterpret_cast<uint32_t *>(&r);
}
in_addr6 Jupiter::Socket::pton6(const char *str)
{
in_addr6 Jupiter::Socket::pton6(const char *str) {
in_addr6 r;
if (inet_pton(AF_INET6, str, &r) <= 0)
memset(&r, 0, sizeof(in_addr6));
return r;
}
Jupiter::StringS Jupiter::Socket::ntop4(uint32_t ip)
{
Jupiter::StringS Jupiter::Socket::ntop4(uint32_t ip) {
static char buf[16];
if (inet_ntop(AF_INET, &ip, buf, sizeof(buf)) == nullptr)
return Jupiter::StringS::empty;
return Jupiter::String(buf);
}
Jupiter::StringS Jupiter::Socket::ntop6(in_addr6 ip)
{
Jupiter::StringS Jupiter::Socket::ntop6(in_addr6 ip) {
static char buf[46];
if (inet_ntop(AF_INET6, &ip, buf, sizeof(buf)) == nullptr)
return Jupiter::StringS::empty;
return Jupiter::String(buf);
}
Jupiter::StringS Jupiter::Socket::ntop(void *ip, size_t size)
{
switch (size)
{
Jupiter::StringS Jupiter::Socket::ntop(void *ip, size_t size) {
switch (size) {
case 4:
return ntop4(*reinterpret_cast<uint32_t *>(ip));
case 16:
@ -418,13 +369,11 @@ Jupiter::StringS Jupiter::Socket::ntop(void *ip, size_t size)
}
}
Jupiter::Socket *Jupiter::Socket::accept()
{
Jupiter::Socket *Jupiter::Socket::accept() {
sockaddr addr;
socklen_t size = sizeof(addr);
SocketType tSock = ::accept(Socket::data_->rawSock, &addr, &size);
if (tSock != INVALID_SOCKET)
{
if (tSock != INVALID_SOCKET) {
char resolved[NI_MAXHOST];
char resolved_port[NI_MAXSERV];
getnameinfo(&addr, size, resolved, sizeof(resolved), resolved_port, sizeof(resolved_port), NI_NUMERICHOST | NI_NUMERICSERV);
@ -439,8 +388,7 @@ Jupiter::Socket *Jupiter::Socket::accept()
return nullptr;
}
bool Jupiter::Socket::setReadTimeout(unsigned long milliseconds)
{
bool Jupiter::Socket::setReadTimeout(unsigned long milliseconds) {
#if defined _WIN32
return setsockopt(Jupiter::Socket::data_->rawSock, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<const char *>(&milliseconds), sizeof(milliseconds)) == 0;
#else // _WIN32
@ -451,8 +399,7 @@ bool Jupiter::Socket::setReadTimeout(unsigned long milliseconds)
#endif // _WIN32
}
bool Jupiter::Socket::setSendTimeout(unsigned long milliseconds)
{
bool Jupiter::Socket::setSendTimeout(unsigned long milliseconds) {
#if defined _WIN32
return setsockopt(Jupiter::Socket::data_->rawSock, SOL_SOCKET, SO_SNDTIMEO, reinterpret_cast<const char *>(&milliseconds), sizeof(milliseconds)) == 0;
#else // _WIN32
@ -463,14 +410,12 @@ bool Jupiter::Socket::setSendTimeout(unsigned long milliseconds)
#endif // _WIN32
}
bool Jupiter::Socket::setTimeout(unsigned long milliseconds)
{
bool Jupiter::Socket::setTimeout(unsigned long milliseconds) {
if (Jupiter::Socket::setReadTimeout(milliseconds) && Jupiter::Socket::setSendTimeout(milliseconds)) return true;
return false;
}
bool Jupiter::Socket::setBlocking(bool mode)
{
bool Jupiter::Socket::setBlocking(bool mode) {
#if defined _WIN32
Jupiter::Socket::data_->blockMode = !mode;
return ioctlsocket(Jupiter::Socket::data_->rawSock, FIONBIO, &Jupiter::Socket::data_->blockMode) == 0;
@ -487,8 +432,7 @@ bool Jupiter::Socket::setBlocking(bool mode)
#endif // _WIN32
}
bool Jupiter::Socket::getBlockingMode() const
{
bool Jupiter::Socket::getBlockingMode() const {
#if defined _WIN32
return !Jupiter::Socket::data_->blockMode;
#else // _WIN32
@ -498,98 +442,80 @@ bool Jupiter::Socket::getBlockingMode() const
#endif
}
const std::string &Jupiter::Socket::getRemoteHostname() const
{
const std::string &Jupiter::Socket::getRemoteHostname() const {
return Jupiter::Socket::data_->remote_host;
}
const char *Jupiter::Socket::getRemoteHostnameC() const
{
const char *Jupiter::Socket::getRemoteHostnameC() const {
return Jupiter::Socket::data_->remote_host.c_str();
}
const std::string &Jupiter::Socket::getBoundHostname() const
{
const std::string &Jupiter::Socket::getBoundHostname() const {
return Jupiter::Socket::data_->bound_host;
}
const char *Jupiter::Socket::getBoundHostnameC() const
{
const char *Jupiter::Socket::getBoundHostnameC() const {
return Jupiter::Socket::data_->bound_host.c_str();
}
unsigned short Jupiter::Socket::getRemotePort() const
{
unsigned short Jupiter::Socket::getRemotePort() const {
return Jupiter::Socket::data_->remote_port;
}
unsigned short Jupiter::Socket::getBoundPort() const
{
unsigned short Jupiter::Socket::getBoundPort() const {
return Jupiter::Socket::data_->bound_port;
}
const Jupiter::ReadableString &Jupiter::Socket::getBuffer() const
{
std::string_view Jupiter::Socket::getBuffer() const {
return Jupiter::Socket::data_->buffer;
}
size_t Jupiter::Socket::getBufferSize() const
{
size_t Jupiter::Socket::getBufferSize() const {
return Jupiter::Socket::data_->buffer.capacity();
}
const Jupiter::ReadableString &Jupiter::Socket::setBufferSize(size_t size)
{
const Jupiter::ReadableString &Jupiter::Socket::setBufferSize(size_t size) {
Jupiter::Socket::data_->buffer.setBufferSize(size);
return Jupiter::Socket::data_->buffer;
}
const Jupiter::ReadableString &Jupiter::Socket::getData()
{
const Jupiter::ReadableString &Jupiter::Socket::getData() {
if (this->recv() <= 0)
Jupiter::Socket::data_->buffer.erase();
return Jupiter::Socket::data_->buffer;
}
const char *Jupiter::Socket::getLocalHostname() // static
{
const char *Jupiter::Socket::getLocalHostname() { // static
static char localHostname[NI_MAXHOST];
gethostname(localHostname, NI_MAXHOST);
return localHostname;
}
void Jupiter::Socket::clearBuffer()
{
void Jupiter::Socket::clearBuffer() {
Jupiter::Socket::data_->buffer.erase();
}
int Jupiter::Socket::send(const char *data, size_t datalen)
{
int Jupiter::Socket::send(const char *data, size_t datalen) {
return ::send(Jupiter::Socket::data_->rawSock, data, datalen, 0);
}
int Jupiter::Socket::send(const Jupiter::ReadableString &str)
{
int Jupiter::Socket::send(const Jupiter::ReadableString &str) {
return this->send(str.ptr(), str.size());
}
int Jupiter::Socket::send(const char *msg)
{
int Jupiter::Socket::send(const char *msg) {
return this->send(msg, strlen(msg));
}
int Jupiter::Socket::sendTo(const addrinfo *info, const char *data, size_t datalen)
{
int Jupiter::Socket::sendTo(const addrinfo *info, const char *data, size_t datalen) {
return sendto(Jupiter::Socket::data_->rawSock, data, datalen, 0, info->ai_addr, info->ai_addrlen);
}
int Jupiter::Socket::sendTo(const addrinfo *info, const char *msg)
{
int Jupiter::Socket::sendTo(const addrinfo *info, const char *msg) {
return sendto(Jupiter::Socket::data_->rawSock, msg, strlen(msg), 0, info->ai_addr, info->ai_addrlen);
}
int Jupiter::Socket::peek()
{
int Jupiter::Socket::peek() {
Jupiter::Socket::data_->buffer.erase();
int r = ::recv(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK);
if (r > 0)
@ -597,21 +523,18 @@ int Jupiter::Socket::peek()
return r;
}
int Jupiter::Socket::peekFrom(addrinfo *info)
{
int Jupiter::Socket::peekFrom(addrinfo *info) {
Jupiter::Socket::data_->buffer.erase();
if (info == nullptr)
return recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK, nullptr, nullptr);
socklen_t len = info->ai_addrlen;
if (len <= 0)
{
if (len <= 0) {
info->ai_addr = new sockaddr();
len = sizeof(sockaddr);
}
int r = recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), MSG_PEEK, info->ai_addr, &len);
if (r >= 0)
{
if (r >= 0) {
info->ai_addrlen = len;
info->ai_family = info->ai_addr->sa_family;
info->ai_protocol = Jupiter::Socket::getProtocol();
@ -620,8 +543,7 @@ int Jupiter::Socket::peekFrom(addrinfo *info)
return r;
}
int Jupiter::Socket::recv()
{
int Jupiter::Socket::recv() {
Jupiter::Socket::data_->buffer.erase();
int r = ::recv(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0);
if (r > 0)
@ -629,21 +551,18 @@ int Jupiter::Socket::recv()
return r;
}
int Jupiter::Socket::recvFrom(addrinfo *info)
{
int Jupiter::Socket::recvFrom(addrinfo *info) {
Jupiter::Socket::data_->buffer.erase();
if (info == nullptr)
return recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0, nullptr, nullptr);
socklen_t len = info->ai_addrlen;
if (len <= 0)
{
if (len <= 0) {
info->ai_addr = new sockaddr();
len = sizeof(sockaddr);
}
int r = recvfrom(Jupiter::Socket::data_->rawSock, Jupiter::Socket::data_->buffer.get_str(), Jupiter::Socket::data_->buffer.capacity(), 0, info->ai_addr, &len);
if (r >= 0)
{
if (r >= 0) {
info->ai_addrlen = len;
info->ai_family = info->ai_addr->sa_family;
info->ai_protocol = Jupiter::Socket::getProtocol();
@ -652,13 +571,11 @@ int Jupiter::Socket::recvFrom(addrinfo *info)
return r;
}
int Jupiter::Socket::receive()
{
int Jupiter::Socket::receive() {
return this->recv();
}
int Jupiter::Socket::getLastError() // static
{
int Jupiter::Socket::getLastError() { // static
#if defined _WIN32
int lastError = WSAGetLastError();
#else // _WIN32
@ -667,8 +584,7 @@ int Jupiter::Socket::getLastError() // static
return lastError;
}
bool Jupiter::Socket::init() // static
{
bool Jupiter::Socket::init() { // static
#if defined _WIN32 // _WIN32
WSADATA wsadata;
if (WSAStartup(0x0202, &wsadata)) return false;
@ -682,26 +598,22 @@ bool Jupiter::Socket::init() // static
return true;
}
bool Jupiter::Socket::cleanup() // static
{
bool Jupiter::Socket::cleanup() { // static
#if defined _WIN32 // _WIN32
WSACleanup();
#endif // _WIN32
return true;
}
Jupiter::Socket::SocketType Jupiter::Socket::getDescriptor() const
{
Jupiter::Socket::SocketType Jupiter::Socket::getDescriptor() const {
return Jupiter::Socket::data_->rawSock;
}
void Jupiter::Socket::setDescriptor(SocketType descriptor)
{
void Jupiter::Socket::setDescriptor(SocketType descriptor) {
Jupiter::Socket::data_->rawSock = descriptor;
}
Jupiter::Socket::Buffer &Jupiter::Socket::getInternalBuffer() const
{
Jupiter::Socket::Buffer &Jupiter::Socket::getInternalBuffer() const {
return Jupiter::Socket::data_->buffer;
}

66
src/include/Jupiter/HTTP_QueryString.h

@ -20,6 +20,7 @@
#define _HTTP_QUERYSTRING_H_HEADER
#include <unordered_map>
#include <charconv>
#include "String.hpp"
/**
@ -29,6 +30,21 @@
namespace Jupiter
{
template<typename CharT>
struct str_hash {
using is_transparent = std::true_type;
// C++17 introduces a requirement that these two operators return the same values for same CharT type, but not
// any requirement that std::hash<> be able to accept both key types. This just ties them for convenience
auto operator()(std::basic_string_view<CharT> in_key) const noexcept {
return std::hash<std::basic_string_view<CharT>>()(in_key);
}
auto operator()(const std::basic_string<CharT>& in_key) const noexcept {
return std::hash<std::basic_string<CharT>>()(in_key);
}
};
namespace HTTP
{
/**
@ -50,21 +66,48 @@ namespace Jupiter
{
public:
HTMLFormResponse() = delete;
inline HTMLFormResponse(std::string_view query_string) : HTMLFormResponse(query_string.data(), query_string.size()) {}
inline HTMLFormResponse(const Jupiter::ReadableString &query_string) : HTMLFormResponse(query_string.ptr(), query_string.size()) {}
inline HTMLFormResponse(const char *ptr, size_t str_size);
using TableType = std::unordered_map<Jupiter::StringS, Jupiter::StringS, Jupiter::default_hash_function>;
using TableType = std::unordered_map<std::string, std::string, Jupiter::str_hash<char>, std::equal_to<>>;
#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(const Jupiter::StringS &in_key, const CastT &in_value) const {
CastT tableGetCast(InKeyType in_key, const CastT &in_value) const {
CastT result = in_value;
auto item = table.find(in_key);
if (item != table.end()) {
return static_cast<CastT>(item->second);
std::from_chars(item->second.data(), item->second.data() + item->second.size(), result);
return result;
}
return in_value;
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
const Jupiter::ReadableString& tableGet(const Jupiter::StringS& in_key, const Jupiter::ReadableString& in_value) {
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;
@ -157,7 +200,7 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
char *buf = str;
const char *token_start = buf;
int val;
Jupiter::ReferenceString key;
std::string key;
while (ptr != end)
{
@ -184,16 +227,17 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
}
else if (*ptr == '&') // End of key/value, start of key
{
if (key.isNotEmpty()) // A key was already set; end of value
if (!key.empty()) { // A key was already set; end of value
Jupiter::HTTP::HTMLFormResponse::table[key] = Jupiter::ReferenceString(token_start, buf - token_start);
}
key.erase();
key = std::string_view{};
++buf, ++ptr;
token_start = buf;
}
else if (*ptr == '=') // End of key, start of value
{
key.set(token_start, buf - token_start);
key = std::string_view(token_start, buf - token_start);
++buf, ++ptr;
token_start = buf;
}
@ -209,14 +253,14 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
if (*buf == '=') // End of key, start of value
{
key.set(token_start, ++buf - token_start);
key = std::string_view(token_start, ++buf - token_start);
*buf = *++ptr;
Jupiter::HTTP::HTMLFormResponse::table[key] = Jupiter::ReferenceString(ptr, 1);
}
else
*++buf = *++ptr;
if (key.isNotEmpty()) // A key was already set; end of value
if (!key.empty()) // A key was already set; end of value
Jupiter::HTTP::HTMLFormResponse::table[key] = Jupiter::ReferenceString(token_start, buf - token_start + 1);
Jupiter::StringType::length = buf + 1 - str;

56
src/include/Jupiter/HTTP_Server.h

@ -45,7 +45,7 @@ namespace Jupiter
virtual int think();
public: // Server
typedef Jupiter::ReadableString *HTTPFunction(const Jupiter::ReadableString &query_string);
typedef Jupiter::ReadableString *HTTPFunction(std::string_view query_string);
static const Jupiter::ReadableString &global_namespace;
static const Jupiter::ReadableString &server_string;
@ -53,15 +53,15 @@ namespace Jupiter
{
bool free_result = true;
Jupiter::HTTP::Server::HTTPFunction *function; // function to generate content data
Jupiter::StringS name; // name of the content
std::string name; // name of the content
unsigned int name_checksum; // name.calcChecksum()
const Jupiter::ReadableString *language = nullptr; // Pointer to a constant (or otherwise managed) string
const Jupiter::ReadableString *type = nullptr; // Pointer to a constant (or otherwise managed) string
const Jupiter::ReadableString *charset = nullptr; // Pointer to a constant (or otherwise managed) string
virtual Jupiter::ReadableString *execute(const Jupiter::ReadableString &query_string);
virtual Jupiter::ReadableString *execute(std::string_view query_string);
Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function);
Content(std::string in_name, Jupiter::HTTP::Server::HTTPFunction in_function);
};
class JUPITER_API Directory
@ -69,47 +69,39 @@ namespace Jupiter
public:
std::vector<std::unique_ptr<Server::Directory>> directories;
std::vector<std::unique_ptr<Server::Content>> content;
Jupiter::StringS name;
std::string name;
unsigned int name_checksum;
virtual void hook(const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
//virtual bool remove(const Jupiter::ReadableString &path);
virtual bool remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
virtual bool has(const Jupiter::ReadableString &name);
virtual Jupiter::HTTP::Server::Content* find(const Jupiter::ReadableString &name);
virtual Jupiter::ReadableString* execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
virtual void hook(std::string_view path, std::unique_ptr<Content> in_content);
virtual bool remove(std::string_view path, std::string_view name);
virtual bool has(std::string_view name);
virtual Jupiter::HTTP::Server::Content* find(std::string_view name);
virtual Jupiter::ReadableString* execute(std::string_view name, std::string_view query_string);
Directory(const Directory&) = delete;
Directory& operator=(const Directory&) = delete;
Directory(const Jupiter::ReadableString &in_name);
Directory(std::string in_name);
virtual ~Directory();
};
class JUPITER_API Host : public Directory
{
public:
/*virtual bool remove(const Jupiter::ReadableString &name);
virtual bool has(const Jupiter::ReadableString &name);
virtual Jupiter::HTTP::Server::Content *find(const Jupiter::ReadableString &name);
//virtual Jupiter::HTTP::Server::Directory *find_directory(const Jupiter::ReadableString &name);
virtual Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &parameters);*/
Host(const Jupiter::ReadableString &in_name);
Host(std::string in_name);
};
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
bool remove(const Jupiter::ReadableString &host);
//bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path);
bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
bool has(const Jupiter::ReadableString &host);
bool has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name);
Content *find(const Jupiter::ReadableString &name);
Content *find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
bool bind(const Jupiter::ReadableString &hostname, uint16_t port = 80);
bool tls_bind(const Jupiter::ReadableString &hostname, uint16_t port = 443);
void hook(std::string_view host, std::string_view path, std::unique_ptr<Content> in_content);
bool remove(std::string_view host);
bool remove(std::string_view host, std::string_view path, std::string_view name);
bool has(std::string_view host);
bool has(std::string_view host, std::string_view name);
Content *find(std::string_view name);
Content *find(std::string_view host, std::string_view name);
Jupiter::ReadableString *execute(std::string_view name, std::string_view query_string);
Jupiter::ReadableString *execute(std::string_view host, std::string_view name, std::string_view query_string);
bool bind(std::string_view hostname, uint16_t port = 80);
bool tls_bind(std::string_view hostname, uint16_t port = 443);
Server();
Server(Jupiter::HTTP::Server &&source);

4
src/include/Jupiter/IRC_Client.h

@ -722,7 +722,7 @@ namespace Jupiter
*
* @return 0 upon success, an error code otherwise.
*/
int process_line(const Jupiter::ReadableString &in_line);
int process_line(std::string_view in_line);
/**
* @brief Returns a key's value.
@ -844,7 +844,7 @@ namespace Jupiter
Jupiter::Config *m_primary_section;
Jupiter::Config *m_secondary_section;
std::string m_log_file_name;
Jupiter::StringS m_last_line;
std::string m_last_line;
Jupiter::StringS m_server_name;
Jupiter::StringS m_nickname;
Jupiter::StringS m_realname;

99
src/include/Jupiter/Readable_String.h

@ -231,24 +231,6 @@ namespace Jupiter
*/
double asDouble() const;
/**
* @brief Sums together all of the elements in the string.
*
* @param T Integral type to return
*
* @return Sum of all the elements in the string
*/
template<typename R = unsigned int> R calcChecksum() const;
/**
* @brief Sums together the uppercase version of all of the elements in the string.
*
* @param T Integral type to return
*
* @return Sum of all the elements in the string
*/
template<typename R = unsigned int> R calcChecksumi() const;
/**
* @brief Outputs the string to a FILE stream.
*
@ -319,84 +301,6 @@ namespace Jupiter
template<template<typename> class R> static R<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
template<template<typename> class R> static R<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Contains the results from a call to tokenize().
*/
template<template<typename> class R> struct TokenizeResult
{
/** Underlying type used to represent each token */
typedef R<T> token_type;
/** Array of tokens, with a length of 'token_count' */
R<T> *tokens;
/** Length of 'tokens' array */
size_t token_count;
/**
* @brief A safe accessor method, for fetching tokens.
*
* @param index Index of token to fetch
* @return The token at the specified index if it exists, an empty string otherwise.
*/
const R<T> &getToken(size_t index) const;
/**
* @brief Restores the TokenizeResult to a default state, by deleting the stored tokens.
*/
void erase();
/**
* @brief Default constructor for the TokenizeResult class.
* Note: 'tokens' assigned nullptr, and 'token_count' is assigned 0.
*/
TokenizeResult();
/**
* @brief Allocation constructor for the TokenizeResult class.
*/
TokenizeResult(size_t in_token_count);
/**
* @brief Capture constructor for the TokenizeResult class.
*/
TokenizeResult(R<T> *in_tokens, size_t in_token_count);
/**
* @brief Copy constructor for the TokenizeResult class.
*/
TokenizeResult(const TokenizeResult &source);
/**
* @brief Move constructor for the TokenizeResult class.
*/
TokenizeResult(TokenizeResult &&source);
/**
* @brief Destructor for the TokenizeResult class.
*/
~TokenizeResult();
/** Assignment Operator */
inline TokenizeResult<R> &operator=(const TokenizeResult<R> &right);
/** Move Operator */
inline TokenizeResult<R> &operator=(TokenizeResult<R> &&right);
};
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param R String type to use when constructing results
*
* @param in String to split into tokens
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
template<template<typename> class R> static typename Jupiter::Readable_String<T>::template TokenizeResult<R> tokenize(const Jupiter::Readable_String<T> &in, const T &separator);
template<template<typename> class R> static typename Jupiter::Readable_String<T>::template TokenizeResult<R> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator);
template<template<typename> class R> static typename Jupiter::Readable_String<T>::template TokenizeResult<R> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size);
/**
* @brief Destructor for the Readable_String class.
*/
@ -448,9 +352,6 @@ namespace Jupiter
explicit inline operator long double() const { return this->asDouble(); } // NEEDS TO NOT CAST FROM DOUBLE
explicit inline operator std::basic_string<T>() const { return std::basic_string<T>(this->ptr(), this->size()); }
inline operator std::basic_string_view<T>() const { return std::basic_string_view<T>(this->ptr(), this->size()); }
private:
template<typename R> R calcChecksumiHelper() const;
};
/** Generic Readable String Type */

286
src/include/Jupiter/Readable_String_Imp.h

@ -1017,47 +1017,6 @@ template<typename T> double Jupiter::Readable_String<T>::asDouble() const
return 0;
}
// calcChecksum
template<typename T> template<typename R> R Jupiter::Readable_String<T>::calcChecksum() const
{
R sum = 0;
size_t index = this->size();
while (index != 0)
sum += this->get(--index);
return sum;
}
// calcChecksumi
template<typename T> template<typename R> R Jupiter::Readable_String<T>::calcChecksumi() const
{
return this->calcChecksumiHelper<R>();
}
template<> template<typename R> R inline Jupiter::Readable_String<char>::calcChecksumiHelper() const
{
R sum = 0;
size_t index = this->size();
while (index != 0)
sum += toupper(this->get(--index));
return sum;
}
template<> template<typename R> R inline Jupiter::Readable_String<wchar_t>::calcChecksumiHelper() const
{
R sum = 0;
size_t index = this->size();
while (index != 0)
sum += towupper(this->get(--index));
return sum;
}
template<typename T> template<typename R> R Jupiter::Readable_String<T>::calcChecksumiHelper() const
{
return this->calcChecksum<R>();
}
// Stream output
template<typename T> size_t Jupiter::Readable_String<T>::print(FILE *out) const
@ -1312,251 +1271,6 @@ template<typename T> template<template<typename> class R> R<T> Jupiter::Readable
return R<T>();
}
/** tokenization */
template<typename T> template<template<typename> class R> Jupiter::Readable_String<T>::TokenizeResult<R>::TokenizeResult()
{
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = nullptr;
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = 0;
}
template<typename T> template<template<typename> class R> Jupiter::Readable_String<T>::TokenizeResult<R>::TokenizeResult(size_t in_token_count)
{
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = in_token_count;
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = new R<T>[Jupiter::Readable_String<T>::TokenizeResult<R>::token_count];
}
template<typename T> template<template<typename> class R> Jupiter::Readable_String<T>::TokenizeResult<R>::TokenizeResult(R<T> *in_tokens, size_t in_token_count)
{
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = in_tokens;
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = in_token_count;
}
template<typename T> template<template<typename> class R> Jupiter::Readable_String<T>::TokenizeResult<R>::TokenizeResult(const TokenizeResult &source)
{
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = new R<T>[source.token_count];
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = 0;
while (Jupiter::Readable_String<T>::TokenizeResult<R>::token_count != source.token_count)
{
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens[Jupiter::Readable_String<T>::TokenizeResult<R>::token_count] = source.tokens[Jupiter::Readable_String<T>::TokenizeResult<R>::token_count];
++Jupiter::Readable_String<T>::TokenizeResult<R>::token_count;
}
}
template<typename T> template<template<typename> class R> Jupiter::Readable_String<T>::TokenizeResult<R>::TokenizeResult(TokenizeResult &&source)
{
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = source.tokens;
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = source.token_count;
source.tokens = nullptr;
source.token_count = 0;
}
template<typename T> template<template<typename> class R> Jupiter::Readable_String<T>::TokenizeResult<R>::~TokenizeResult()
{
if (Jupiter::Readable_String<T>::TokenizeResult<R>::tokens != nullptr)
delete[] Jupiter::Readable_String<T>::TokenizeResult<R>::tokens;
}
template<typename T> template<template<typename> class R> const R<T> &Jupiter::Readable_String<T>::TokenizeResult<R>::getToken(size_t index) const
{
if (index < Jupiter::Readable_String<T>::TokenizeResult<R>::token_count)
return Jupiter::Readable_String<T>::TokenizeResult<R>::tokens[index];
return R<T>::empty;
}
template<typename T> template<template<typename> class R> void Jupiter::Readable_String<T>::TokenizeResult<R>::erase()
{
if (Jupiter::Readable_String<T>::TokenizeResult<R>::tokens != nullptr)
{
delete[] Jupiter::Readable_String<T>::TokenizeResult<R>::tokens;
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = nullptr;
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = 0;
}
}
// TokenizeResult Operators
#ifdef _WIN32
#define TOKENIZE_RESULT_PREFIX
#else // _WIN32
#define TOKENIZE_RESULT_PREFIX template
#endif // _WIN32
template<typename T> template<template<typename> class R> inline typename Jupiter::Readable_String<T>::TOKENIZE_RESULT_PREFIX TokenizeResult<R> &Jupiter::Readable_String<T>::TokenizeResult<R>::operator=(const Jupiter::Readable_String<T>::TokenizeResult<R> &source)
{
if (Jupiter::Readable_String<T>::TokenizeResult<R>::tokens != nullptr)
delete[] Jupiter::Readable_String<T>::TokenizeResult<R>::tokens;
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = new R<T>[source.token_count];
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = 0;
while (Jupiter::Readable_String<T>::TokenizeResult<R>::token_count != source.token_count)
{
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens[Jupiter::Readable_String<T>::TokenizeResult<R>::token_count] = source.tokens[Jupiter::Readable_String<T>::TokenizeResult<R>::token_count];
++Jupiter::Readable_String<T>::TokenizeResult<R>::token_count;
}
return *this;
}
template<typename T> template<template<typename> class R> inline typename Jupiter::Readable_String<T>::TOKENIZE_RESULT_PREFIX TokenizeResult<R> &Jupiter::Readable_String<T>::TokenizeResult<R>::operator=(Jupiter::Readable_String<T>::TokenizeResult<R> &&source)
{
if (Jupiter::Readable_String<T>::TokenizeResult<R>::tokens != nullptr)
delete[] Jupiter::Readable_String<T>::TokenizeResult<R>::tokens;
Jupiter::Readable_String<T>::TokenizeResult<R>::tokens = source.tokens;
Jupiter::Readable_String<T>::TokenizeResult<R>::token_count = source.token_count;
source.tokens = nullptr;
source.token_count = 0;
return *this;
}
// tokenize
template<typename T> template<template<typename> class R> typename Jupiter::Readable_String<T>::template TokenizeResult<R> Jupiter::Readable_String<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token)
{
// special case: no input
if (in.isEmpty())
return TokenizeResult<R>();
size_t length = in.tokenCount(token);
R<T> *tokens = new R<T>[length];
// special case: only 1 token
if (length == 1)
{
*tokens = in;
return TokenizeResult<R>(tokens, length);
}
R<T> *itr = tokens;
const T *in_itr = in.ptr();
const T *in_end = in.ptr() + in.size();
const T *token_start = in_itr;
while (in_itr != in_end)
{
loop_start:
if (*in_itr == token)
{
// push token to output
itr->set(token_start, in_itr - token_start);
++itr;
// increment over separator
++in_itr;
// iterator is at end of string
if (in_itr == in_end)
return TokenizeResult<R>(tokens, length);
// start reading new token
token_start = in_itr;
goto loop_start;
}
++in_itr;
}
itr->set(token_start, in_end - token_start);
return TokenizeResult<R>(tokens, length);
}
template<typename T> template<template<typename> class R> typename Jupiter::Readable_String<T>::template TokenizeResult<R> Jupiter::Readable_String<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator)
{
return Jupiter::Readable_String<T>::tokenize<R>(in, separator.ptr(), separator.size());
}
template<typename T> template<template<typename> class R> typename Jupiter::Readable_String<T>::template TokenizeResult<R> Jupiter::Readable_String<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size)
{
// special case: separator is a single element
if (separator_size == 1)
return Jupiter::Readable_String<T>::tokenize<R>(in, *separator);
// special case: no input
if (in.isEmpty())
return TokenizeResult<R>();
R<T> *tokens;
// special case: no separator
if (separator_size == 0)
{
tokens = new R<T>[1];
*tokens = in;
return TokenizeResult<R>(tokens, 1);
}
// special case: only enough space for 1 token, or 2 empty tokens
if (separator_size >= in.size())
{
if (in.equals(separator, separator_size))
return TokenizeResult<R>(2);
tokens = new R<T>[1];
*tokens = in;
return TokenizeResult<R>(tokens, 1);
}
size_t length = in.tokenCount(separator);
tokens = new R<T>[length];
// special case: only 1 token
if (length == 1)
{
*tokens = in;
return TokenizeResult<R>(tokens, length);
}
R<T> *itr = tokens;
const T *in_itr = in.ptr();
const T *in_end = in.ptr() + in.size();
const T *token_start = in_itr;
auto is_separator = [](const T *sep, size_t sep_size, const T *ptr)
{
while (*sep == *ptr)
{
if (--sep_size == 0)
return true;
++sep, ++ptr;
}
return false;
};
while (in_itr + separator_size - 1 != in_end)
{
loop_start:
if (is_separator(separator, separator_size, in_itr))
{
// push token to output
itr->set(token_start, in_itr - token_start);
++itr;
in_itr += separator_size;
token_start = in_itr;
// not enough room for another separator
if (in_itr + separator_size > in_end)
break;
// only enough room for 1 separator (empty token), or 1 token
if (in_itr + separator_size == in_end)
{
if (is_separator(separator, separator_size, in_itr))
return TokenizeResult<R>(tokens, length);
break;
}
goto loop_start;
}
++in_itr;
}
itr->set(token_start, in_end - token_start);
return TokenizeResult<R>(tokens, length);
}
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Readable_String>

21
src/include/Jupiter/Reference_String.h

@ -241,27 +241,6 @@ namespace Jupiter
static Reference_String<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static Reference_String<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> tokenize(const T &separator) const;
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> tokenize(const Jupiter::Readable_String<T> &separator) const;
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> tokenize(const T *separator, size_t separator_size) const;
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param in String to split into tokens
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> tokenize(const Jupiter::Readable_String<T> &in, const T &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size);
/** Mutative operators */
inline Reference_String<T>& operator-=(size_t right) { this->truncate(right); return *this; };
inline Reference_String<T>& operator=(const Readable_String<T> &right) { std::basic_string_view<T>::operator=({right.ptr(), right.size()}); return *this; };

26
src/include/Jupiter/Reference_String_Imp.h

@ -200,32 +200,6 @@ template<typename T> Jupiter::Reference_String<T> Jupiter::Reference_String<T>::
template<typename T> const Jupiter::Reference_String<T> Jupiter::Reference_String<T>::empty = Jupiter::Reference_String<T>();
// tokenize
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> Jupiter::Reference_String<T>::tokenize(const T &separator) const {
return Jupiter::Reference_String<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> Jupiter::Reference_String<T>::tokenize(const Jupiter::Readable_String<T> &separator) const {
return Jupiter::Reference_String<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> Jupiter::Reference_String<T>::tokenize(const T *separator, size_t separator_size) const {
return Jupiter::Reference_String<T>::tokenize(*this, separator, separator_size);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> Jupiter::Reference_String<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token) {
return Jupiter::Readable_String<T>::template tokenize<Jupiter::Reference_String>(in, token);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> Jupiter::Reference_String<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator) {
return Jupiter::Readable_String<T>::template tokenize<Jupiter::Reference_String>(in, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::Reference_String> Jupiter::Reference_String<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size) {
return Jupiter::Readable_String<T>::template tokenize<Jupiter::Reference_String>(in, separator, separator_size);
}
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Reference_String> {

2
src/include/Jupiter/Socket.h

@ -340,7 +340,7 @@ namespace Jupiter
*
* @return Buffer.
*/
const Jupiter::ReadableString &getBuffer() const;
std::string_view getBuffer() const;
/**
* @brief Returns the size of the socket buffer.

42
src/include/Jupiter/String.hpp

@ -205,27 +205,6 @@ namespace Jupiter
static String_Strict<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static String_Strict<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> tokenize(const T &separator) const;
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> tokenize(const Jupiter::Readable_String<T> &separator) const;
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> tokenize(const T *separator, size_t separator_size) const;
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param in String to split into tokens
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> tokenize(const Jupiter::Readable_String<T> &in, const T &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size);
/** Default Constructor */
String_Strict();
@ -461,27 +440,6 @@ namespace Jupiter
static String_Loose<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const T &token);
static String_Loose<T> gotoToken(const Jupiter::Readable_String<T> &in, size_t pos, const Jupiter::Readable_String<T> &token);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> tokenize(const T &separator);
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> tokenize(const Jupiter::Readable_String<T> &separator);
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> tokenize(const T *separator, size_t separator_size);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param in String to split into tokens
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> tokenize(const Jupiter::Readable_String<T> &in, const T &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size);
/**
* @brief Sets the internal buffer to be at least large enough to old a specified number of elements.
* Note: This does nothing if len is less than the string's current length.

64
src/include/Jupiter/String_Imp.h

@ -348,38 +348,6 @@ template<typename T> Jupiter::String_Strict<T> Jupiter::String_Strict<T>::gotoTo
return Jupiter::Readable_String<T>::template gotoToken<Jupiter::template String_Strict>(in, pos, token);
}
// tokenize
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> Jupiter::String_Strict<T>::tokenize(const T &separator) const
{
return Jupiter::String_Strict<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> Jupiter::String_Strict<T>::tokenize(const Jupiter::Readable_String<T> &separator) const
{
return Jupiter::String_Strict<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> Jupiter::String_Strict<T>::tokenize(const T *separator, size_t separator_size) const
{
return Jupiter::String_Strict<T>::tokenize(*this, separator, separator_size);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> Jupiter::String_Strict<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token)
{
return Jupiter::Readable_String<T>::template tokenize<Jupiter::template String_Strict>(in, token);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> Jupiter::String_Strict<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator)
{
return Jupiter::Readable_String<T>::template tokenize<Jupiter::template String_Strict>(in, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Strict> Jupiter::String_Strict<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size)
{
return Jupiter::Readable_String<T>::template tokenize<Jupiter::template String_Strict>(in, separator, separator_size);
}
// Operators
template<typename T> inline Jupiter::String_Strict<T> Jupiter::String_Strict<T>::operator+(const T &rhs) const
@ -861,38 +829,6 @@ template<typename T> inline Jupiter::String_Loose<T> Jupiter::String_Loose<T>::o
return Jupiter::operator+(*this, rhs);
}
// tokenize
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> Jupiter::String_Loose<T>::tokenize(const T &separator)
{
return Jupiter::String_Loose<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> Jupiter::String_Loose<T>::tokenize(const Jupiter::Readable_String<T> &separator)
{
return Jupiter::String_Loose<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> Jupiter::String_Loose<T>::tokenize(const T *separator, size_t separator_size)
{
return Jupiter::String_Loose<T>::tokenize(*this, separator, separator_size);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> Jupiter::String_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &separator)
{
return Jupiter::Readable_String<T>::template tokenize<Jupiter::template String_Loose>(in, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> Jupiter::String_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator)
{
return Jupiter::Readable_String<T>::template tokenize<Jupiter::template String_Loose>(in, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::String_Loose> Jupiter::String_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size)
{
return Jupiter::Readable_String<T>::template tokenize<Jupiter::template String_Loose>(in, separator, separator_size);
}
#if !defined JUPITER_STRING_STRICT_OPERATOR_PLUS
#if !defined DISABLE_DEFAULT_JUPITER_STRING_OPERATOR_PLUS
template<typename T> static inline Jupiter::String_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T &rhs)

Loading…
Cancel
Save