From 714d660508381bc2ff3c775f95b5be11e9eabc68 Mon Sep 17 00:00:00 2001 From: Jessica James Date: Sun, 28 Nov 2021 16:19:03 -0600 Subject: [PATCH] Remove tokenize() and adjust code as necessary; various cleanup --- CMakeLists.txt | 2 +- src/common/HTTP_Server.cpp | 337 +++++++++++---------- src/common/IRC_Client.cpp | 39 ++- src/common/Socket.cpp | 264 ++++++---------- src/include/Jupiter/HTTP_QueryString.h | 66 +++- src/include/Jupiter/HTTP_Server.h | 56 ++-- src/include/Jupiter/IRC_Client.h | 4 +- src/include/Jupiter/Readable_String.h | 99 ------ src/include/Jupiter/Readable_String_Imp.h | 286 ----------------- src/include/Jupiter/Reference_String.h | 21 -- src/include/Jupiter/Reference_String_Imp.h | 26 -- src/include/Jupiter/Socket.h | 2 +- src/include/Jupiter/String.hpp | 42 --- src/include/Jupiter/String_Imp.h | 64 ---- 14 files changed, 374 insertions(+), 934 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19bf481..c809d7d 100644 --- a/CMakeLists.txt +++ b/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) diff --git a/src/common/HTTP_Server.cpp b/src/common/HTTP_Server.cpp index fc62db7..3dda14c 100644 --- a/src/common/HTTP_Server.cpp +++ b/src/common/HTTP_Server.cpp @@ -18,6 +18,9 @@ #include #include +#include +#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 +ResultT calc_checksum(const InT& in_container) { + ResultT result{}; + result = std::accumulate(in_container.begin(), in_container.end(), result); + return result; +} + +template +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 in_content) { +void Jupiter::HTTP::Server::Directory::hook(std::string_view in_name, std::unique_ptr 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(dir_name)).get(); + Directory* directory = directories.emplace_back(std::make_unique(static_cast(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(in_name_ref.substring(size_t{ 0 }, index))); + directory->directories.push_back(std::make_unique(static_cast(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(in_name_ref)); + directory->directories.push_back(std::make_unique(static_cast(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 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 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(Jupiter::HTTP::Server::global_namespace)); + m_hosts.push_back(std::make_unique(static_cast(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 in_content) { +void Jupiter::HTTP::Server::Data::hook(std::string_view hostname, std::string_view in_path, std::unique_ptr 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(hostname)).get(); + host = m_hosts.emplace_back(std::make_unique(static_cast(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 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) { +void Jupiter::HTTP::Server::hook(std::string_view host, std::string_view name, std::unique_ptr 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(); if (socket->bind(static_cast(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(); if (socket->bind(static_cast(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(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 diff --git a/src/common/IRC_Client.cpp b/src/common/IRC_Client.cpp index 3620031..cbe5bd1 100644 --- a/src/common/IRC_Client.cpp +++ b/src/common/IRC_Client.cpp @@ -19,6 +19,7 @@ #include #include #include +#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 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); + } + } } } diff --git a/src/common/Socket.cpp b/src/common/Socket.cpp index 8d245f0..720c95c 100644 --- a/src/common/Socket.cpp +++ b/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(&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(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(&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(&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; } diff --git a/src/include/Jupiter/HTTP_QueryString.h b/src/include/Jupiter/HTTP_QueryString.h index e46bfd6..be5d1d3 100644 --- a/src/include/Jupiter/HTTP_QueryString.h +++ b/src/include/Jupiter/HTTP_QueryString.h @@ -20,6 +20,7 @@ #define _HTTP_QUERYSTRING_H_HEADER #include +#include #include "String.hpp" /** @@ -29,6 +30,21 @@ namespace Jupiter { + template + 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 in_key) const noexcept { + return std::hash>()(in_key); + } + + auto operator()(const std::basic_string& in_key) const noexcept { + return std::hash>()(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; + using TableType = std::unordered_map, 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 + CastT tableGetCast(std::string_view in_key, const CastT &in_value) const { + return tableGetCast(static_cast(in_key), in_value); + } + + std::string_view tableGet(std::string_view in_key, std::string_view in_value) const { + return tableGet(static_cast(in_key), in_value); + } +#endif // __cpp_lib_generic_unordered_lookup template - 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(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(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; diff --git a/src/include/Jupiter/HTTP_Server.h b/src/include/Jupiter/HTTP_Server.h index ef616de..2255a7a 100644 --- a/src/include/Jupiter/HTTP_Server.h +++ b/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> directories; std::vector> content; - Jupiter::StringS name; + std::string name; unsigned int name_checksum; - virtual void hook(const Jupiter::ReadableString &path, std::unique_ptr 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 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 ¶meters);*/ - - Host(const Jupiter::ReadableString &in_name); + Host(std::string in_name); }; - void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr 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 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); diff --git a/src/include/Jupiter/IRC_Client.h b/src/include/Jupiter/IRC_Client.h index fd08190..0682ce6 100644 --- a/src/include/Jupiter/IRC_Client.h +++ b/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; diff --git a/src/include/Jupiter/Readable_String.h b/src/include/Jupiter/Readable_String.h index 613cc74..2d6b8f0 100644 --- a/src/include/Jupiter/Readable_String.h +++ b/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 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 R calcChecksumi() const; - /** * @brief Outputs the string to a FILE stream. * @@ -319,84 +301,6 @@ namespace Jupiter template class R> static R gotoToken(const Jupiter::Readable_String &in, size_t pos, const T &token); template class R> static R gotoToken(const Jupiter::Readable_String &in, size_t pos, const Jupiter::Readable_String &token); - /** - * @brief Contains the results from a call to tokenize(). - */ - template class R> struct TokenizeResult - { - /** Underlying type used to represent each token */ - typedef R token_type; - - /** Array of tokens, with a length of 'token_count' */ - R *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 &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 *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 &operator=(const TokenizeResult &right); - - /** Move Operator */ - inline TokenizeResult &operator=(TokenizeResult &&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 class R> static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const T &separator); - template class R> static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator); - template class R> static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &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() const { return std::basic_string(this->ptr(), this->size()); } inline operator std::basic_string_view() const { return std::basic_string_view(this->ptr(), this->size()); } - - private: - template R calcChecksumiHelper() const; }; /** Generic Readable String Type */ diff --git a/src/include/Jupiter/Readable_String_Imp.h b/src/include/Jupiter/Readable_String_Imp.h index 0d69038..4ef6cae 100644 --- a/src/include/Jupiter/Readable_String_Imp.h +++ b/src/include/Jupiter/Readable_String_Imp.h @@ -1017,47 +1017,6 @@ template double Jupiter::Readable_String::asDouble() const return 0; } -// calcChecksum - -template template R Jupiter::Readable_String::calcChecksum() const -{ - R sum = 0; - size_t index = this->size(); - while (index != 0) - sum += this->get(--index); - return sum; -} - -// calcChecksumi - -template template R Jupiter::Readable_String::calcChecksumi() const -{ - return this->calcChecksumiHelper(); -} - -template<> template R inline Jupiter::Readable_String::calcChecksumiHelper() const -{ - R sum = 0; - size_t index = this->size(); - while (index != 0) - sum += toupper(this->get(--index)); - return sum; -} - -template<> template R inline Jupiter::Readable_String::calcChecksumiHelper() const -{ - R sum = 0; - size_t index = this->size(); - while (index != 0) - sum += towupper(this->get(--index)); - return sum; -} - -template template R Jupiter::Readable_String::calcChecksumiHelper() const -{ - return this->calcChecksum(); -} - // Stream output template size_t Jupiter::Readable_String::print(FILE *out) const @@ -1312,251 +1271,6 @@ template template class R> R Jupiter::Readable return R(); } -/** tokenization */ - -template template class R> Jupiter::Readable_String::TokenizeResult::TokenizeResult() -{ - Jupiter::Readable_String::TokenizeResult::tokens = nullptr; - Jupiter::Readable_String::TokenizeResult::token_count = 0; -} - -template template class R> Jupiter::Readable_String::TokenizeResult::TokenizeResult(size_t in_token_count) -{ - Jupiter::Readable_String::TokenizeResult::token_count = in_token_count; - Jupiter::Readable_String::TokenizeResult::tokens = new R[Jupiter::Readable_String::TokenizeResult::token_count]; -} - -template template class R> Jupiter::Readable_String::TokenizeResult::TokenizeResult(R *in_tokens, size_t in_token_count) -{ - Jupiter::Readable_String::TokenizeResult::tokens = in_tokens; - Jupiter::Readable_String::TokenizeResult::token_count = in_token_count; -} - -template template class R> Jupiter::Readable_String::TokenizeResult::TokenizeResult(const TokenizeResult &source) -{ - Jupiter::Readable_String::TokenizeResult::tokens = new R[source.token_count]; - Jupiter::Readable_String::TokenizeResult::token_count = 0; - while (Jupiter::Readable_String::TokenizeResult::token_count != source.token_count) - { - Jupiter::Readable_String::TokenizeResult::tokens[Jupiter::Readable_String::TokenizeResult::token_count] = source.tokens[Jupiter::Readable_String::TokenizeResult::token_count]; - ++Jupiter::Readable_String::TokenizeResult::token_count; - } -} - -template template class R> Jupiter::Readable_String::TokenizeResult::TokenizeResult(TokenizeResult &&source) -{ - Jupiter::Readable_String::TokenizeResult::tokens = source.tokens; - Jupiter::Readable_String::TokenizeResult::token_count = source.token_count; - source.tokens = nullptr; - source.token_count = 0; -} - -template template class R> Jupiter::Readable_String::TokenizeResult::~TokenizeResult() -{ - if (Jupiter::Readable_String::TokenizeResult::tokens != nullptr) - delete[] Jupiter::Readable_String::TokenizeResult::tokens; -} - -template template class R> const R &Jupiter::Readable_String::TokenizeResult::getToken(size_t index) const -{ - if (index < Jupiter::Readable_String::TokenizeResult::token_count) - return Jupiter::Readable_String::TokenizeResult::tokens[index]; - return R::empty; -} - -template template class R> void Jupiter::Readable_String::TokenizeResult::erase() -{ - if (Jupiter::Readable_String::TokenizeResult::tokens != nullptr) - { - delete[] Jupiter::Readable_String::TokenizeResult::tokens; - Jupiter::Readable_String::TokenizeResult::tokens = nullptr; - Jupiter::Readable_String::TokenizeResult::token_count = 0; - } -} - -// TokenizeResult Operators - -#ifdef _WIN32 -#define TOKENIZE_RESULT_PREFIX -#else // _WIN32 -#define TOKENIZE_RESULT_PREFIX template -#endif // _WIN32 - -template template class R> inline typename Jupiter::Readable_String::TOKENIZE_RESULT_PREFIX TokenizeResult &Jupiter::Readable_String::TokenizeResult::operator=(const Jupiter::Readable_String::TokenizeResult &source) -{ - if (Jupiter::Readable_String::TokenizeResult::tokens != nullptr) - delete[] Jupiter::Readable_String::TokenizeResult::tokens; - - Jupiter::Readable_String::TokenizeResult::tokens = new R[source.token_count]; - Jupiter::Readable_String::TokenizeResult::token_count = 0; - while (Jupiter::Readable_String::TokenizeResult::token_count != source.token_count) - { - Jupiter::Readable_String::TokenizeResult::tokens[Jupiter::Readable_String::TokenizeResult::token_count] = source.tokens[Jupiter::Readable_String::TokenizeResult::token_count]; - ++Jupiter::Readable_String::TokenizeResult::token_count; - } - return *this; -} - -template template class R> inline typename Jupiter::Readable_String::TOKENIZE_RESULT_PREFIX TokenizeResult &Jupiter::Readable_String::TokenizeResult::operator=(Jupiter::Readable_String::TokenizeResult &&source) -{ - if (Jupiter::Readable_String::TokenizeResult::tokens != nullptr) - delete[] Jupiter::Readable_String::TokenizeResult::tokens; - - Jupiter::Readable_String::TokenizeResult::tokens = source.tokens; - Jupiter::Readable_String::TokenizeResult::token_count = source.token_count; - source.tokens = nullptr; - source.token_count = 0; - return *this; -} - -// tokenize - -template template class R> typename Jupiter::Readable_String::template TokenizeResult Jupiter::Readable_String::tokenize(const Jupiter::Readable_String &in, const T &token) -{ - // special case: no input - if (in.isEmpty()) - return TokenizeResult(); - - size_t length = in.tokenCount(token); - R *tokens = new R[length]; - - // special case: only 1 token - if (length == 1) - { - *tokens = in; - return TokenizeResult(tokens, length); - } - - R *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(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(tokens, length); -} - -template template class R> typename Jupiter::Readable_String::template TokenizeResult Jupiter::Readable_String::tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator) -{ - return Jupiter::Readable_String::tokenize(in, separator.ptr(), separator.size()); -} - -template template class R> typename Jupiter::Readable_String::template TokenizeResult Jupiter::Readable_String::tokenize(const Jupiter::Readable_String &in, const T *separator, size_t separator_size) -{ - // special case: separator is a single element - if (separator_size == 1) - return Jupiter::Readable_String::tokenize(in, *separator); - - // special case: no input - if (in.isEmpty()) - return TokenizeResult(); - - R *tokens; - - // special case: no separator - if (separator_size == 0) - { - tokens = new R[1]; - *tokens = in; - return TokenizeResult(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(2); - - tokens = new R[1]; - *tokens = in; - return TokenizeResult(tokens, 1); - } - - size_t length = in.tokenCount(separator); - tokens = new R[length]; - - // special case: only 1 token - if (length == 1) - { - *tokens = in; - return TokenizeResult(tokens, length); - } - - R *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(tokens, length); - break; - } - - goto loop_start; - } - ++in_itr; - } - - itr->set(token_start, in_end - token_start); - return TokenizeResult(tokens, length); -} - // Jupiter::DataBuffer specialization template<> struct _Jupiter_DataBuffer_partial_specialization_impl diff --git a/src/include/Jupiter/Reference_String.h b/src/include/Jupiter/Reference_String.h index d1bb141..942036e 100644 --- a/src/include/Jupiter/Reference_String.h +++ b/src/include/Jupiter/Reference_String.h @@ -241,27 +241,6 @@ namespace Jupiter static Reference_String gotoToken(const Jupiter::Readable_String &in, size_t pos, const T &token); static Reference_String gotoToken(const Jupiter::Readable_String &in, size_t pos, const Jupiter::Readable_String &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::template TokenizeResult tokenize(const T &separator) const; - typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &separator) const; - typename Jupiter::Readable_String::template TokenizeResult 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::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const T &separator); - static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator); - static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const T *separator, size_t separator_size); - /** Mutative operators */ inline Reference_String& operator-=(size_t right) { this->truncate(right); return *this; }; inline Reference_String& operator=(const Readable_String &right) { std::basic_string_view::operator=({right.ptr(), right.size()}); return *this; }; diff --git a/src/include/Jupiter/Reference_String_Imp.h b/src/include/Jupiter/Reference_String_Imp.h index 179d4f5..c6460fa 100644 --- a/src/include/Jupiter/Reference_String_Imp.h +++ b/src/include/Jupiter/Reference_String_Imp.h @@ -200,32 +200,6 @@ template Jupiter::Reference_String Jupiter::Reference_String:: template const Jupiter::Reference_String Jupiter::Reference_String::empty = Jupiter::Reference_String(); -// tokenize - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::Reference_String::tokenize(const T &separator) const { - return Jupiter::Reference_String::tokenize(*this, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::Reference_String::tokenize(const Jupiter::Readable_String &separator) const { - return Jupiter::Reference_String::tokenize(*this, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::Reference_String::tokenize(const T *separator, size_t separator_size) const { - return Jupiter::Reference_String::tokenize(*this, separator, separator_size); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::Reference_String::tokenize(const Jupiter::Readable_String &in, const T &token) { - return Jupiter::Readable_String::template tokenize(in, token); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::Reference_String::tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator) { - return Jupiter::Readable_String::template tokenize(in, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::Reference_String::tokenize(const Jupiter::Readable_String &in, const T *separator, size_t separator_size) { - return Jupiter::Readable_String::template tokenize(in, separator, separator_size); -} - // Jupiter::DataBuffer specialization template<> struct _Jupiter_DataBuffer_partial_specialization_impl { diff --git a/src/include/Jupiter/Socket.h b/src/include/Jupiter/Socket.h index f81b845..756dc1d 100644 --- a/src/include/Jupiter/Socket.h +++ b/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. diff --git a/src/include/Jupiter/String.hpp b/src/include/Jupiter/String.hpp index 6673c85..d7deb03 100644 --- a/src/include/Jupiter/String.hpp +++ b/src/include/Jupiter/String.hpp @@ -205,27 +205,6 @@ namespace Jupiter static String_Strict gotoToken(const Jupiter::Readable_String &in, size_t pos, const T &token); static String_Strict gotoToken(const Jupiter::Readable_String &in, size_t pos, const Jupiter::Readable_String &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::template TokenizeResult tokenize(const T &separator) const; - typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &separator) const; - typename Jupiter::Readable_String::template TokenizeResult 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::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const T &separator); - static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator); - static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const T *separator, size_t separator_size); - /** Default Constructor */ String_Strict(); @@ -461,27 +440,6 @@ namespace Jupiter static String_Loose gotoToken(const Jupiter::Readable_String &in, size_t pos, const T &token); static String_Loose gotoToken(const Jupiter::Readable_String &in, size_t pos, const Jupiter::Readable_String &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::template TokenizeResult tokenize(const T &separator); - typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &separator); - typename Jupiter::Readable_String::template TokenizeResult 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::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const T &separator); - static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator); - static typename Jupiter::Readable_String::template TokenizeResult tokenize(const Jupiter::Readable_String &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. diff --git a/src/include/Jupiter/String_Imp.h b/src/include/Jupiter/String_Imp.h index 6bf6cdf..dafed15 100644 --- a/src/include/Jupiter/String_Imp.h +++ b/src/include/Jupiter/String_Imp.h @@ -348,38 +348,6 @@ template Jupiter::String_Strict Jupiter::String_Strict::gotoTo return Jupiter::Readable_String::template gotoToken(in, pos, token); } -// tokenize - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Strict::tokenize(const T &separator) const -{ - return Jupiter::String_Strict::tokenize(*this, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Strict::tokenize(const Jupiter::Readable_String &separator) const -{ - return Jupiter::String_Strict::tokenize(*this, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Strict::tokenize(const T *separator, size_t separator_size) const -{ - return Jupiter::String_Strict::tokenize(*this, separator, separator_size); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Strict::tokenize(const Jupiter::Readable_String &in, const T &token) -{ - return Jupiter::Readable_String::template tokenize(in, token); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Strict::tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator) -{ - return Jupiter::Readable_String::template tokenize(in, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Strict::tokenize(const Jupiter::Readable_String &in, const T *separator, size_t separator_size) -{ - return Jupiter::Readable_String::template tokenize(in, separator, separator_size); -} - // Operators template inline Jupiter::String_Strict Jupiter::String_Strict::operator+(const T &rhs) const @@ -861,38 +829,6 @@ template inline Jupiter::String_Loose Jupiter::String_Loose::o return Jupiter::operator+(*this, rhs); } -// tokenize - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Loose::tokenize(const T &separator) -{ - return Jupiter::String_Loose::tokenize(*this, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Loose::tokenize(const Jupiter::Readable_String &separator) -{ - return Jupiter::String_Loose::tokenize(*this, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Loose::tokenize(const T *separator, size_t separator_size) -{ - return Jupiter::String_Loose::tokenize(*this, separator, separator_size); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Loose::tokenize(const Jupiter::Readable_String &in, const T &separator) -{ - return Jupiter::Readable_String::template tokenize(in, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Loose::tokenize(const Jupiter::Readable_String &in, const Jupiter::Readable_String &separator) -{ - return Jupiter::Readable_String::template tokenize(in, separator); -} - -template typename Jupiter::Readable_String::template TokenizeResult Jupiter::String_Loose::tokenize(const Jupiter::Readable_String &in, const T *separator, size_t separator_size) -{ - return Jupiter::Readable_String::template tokenize(in, separator, separator_size); -} - #if !defined JUPITER_STRING_STRICT_OPERATOR_PLUS #if !defined DISABLE_DEFAULT_JUPITER_STRING_OPERATOR_PLUS template static inline Jupiter::String_Loose Jupiter::operator+(const Jupiter::Readable_String &lhs, const T &rhs)