Browse Source

Remove all Jupiter string types & aliases; left some string utilities in Readable_String.h for legacy usage

master
Jessica James 3 years ago
parent
commit
77762980cc
  1. 4
      README.md
  2. 10
      src/common/Config.cpp
  3. 1
      src/common/DataBuffer.cpp
  4. 2
      src/common/Database.cpp
  5. 4
      src/common/File.cpp
  6. 13
      src/common/GenericCommand.cpp
  7. 73
      src/common/HTTP_Server.cpp
  8. 4
      src/common/INIConfig.cpp
  9. 181
      src/common/IRC_Client.cpp
  10. 4
      src/common/Plugin.cpp
  11. 10
      src/common/Socket.cpp
  12. 1
      src/include/Jupiter/Base64.h
  13. 14
      src/include/Jupiter/Config.h
  14. 54
      src/include/Jupiter/DataBuffer_Imp.h
  15. 6
      src/include/Jupiter/Database.h
  16. 1
      src/include/Jupiter/File.h
  17. 3
      src/include/Jupiter/GenericCommand.h
  18. 27
      src/include/Jupiter/HTTP.h
  19. 98
      src/include/Jupiter/HTTP_QueryString.h
  20. 4
      src/include/Jupiter/HTTP_Server.h
  21. 48
      src/include/Jupiter/Hash.h
  22. 2
      src/include/Jupiter/IRC.h
  23. 29
      src/include/Jupiter/IRC_Client.h
  24. 61
      src/include/Jupiter/InvalidIndex.h
  25. 2
      src/include/Jupiter/Jupiter.h
  26. 6
      src/include/Jupiter/Plugin.h
  27. 41
      src/include/Jupiter/Readable_String.h
  28. 45
      src/include/Jupiter/Reference_String.h
  29. 114
      src/include/Jupiter/Shift_String.h
  30. 102
      src/include/Jupiter/Shift_String_Imp.h
  31. 10
      src/include/Jupiter/Socket.h
  32. 185
      src/include/Jupiter/String.hpp
  33. 250
      src/include/Jupiter/String_Imp.h
  34. 326
      src/include/Jupiter/String_Type.h
  35. 593
      src/include/Jupiter/String_Type_Imp.h
  36. 2
      src/jessilib

4
README.md

@ -2,10 +2,6 @@
Primarily developed in C++, Jupiter is an open-source multi-purpose library initially intended for the purpose of creating IRC bots, but is by no means restricted to IRC bots. Primarily developed in C++, Jupiter is an open-source multi-purpose library initially intended for the purpose of creating IRC bots, but is by no means restricted to IRC bots.
Jupiter has been used to expedite the production of numerous projects ranging from ZIP code verifiers, to game administration systems, to game leaderboards and web APIs. Jupiter has been used to expedite the production of numerous projects ranging from ZIP code verifiers, to game administration systems, to game leaderboards and web APIs.
## Strings
Jupiter contains a number of deprecated string classes, which are deprecated in favor of std::string_view and std::string.
These will be removed in the future, with any useful string utilities being replaced by equivalents in jessilib.
## Sockets ## Sockets
Jupiter includes a Socket wrapper, allowing for simple interaction with sockets, while eliminating all of the platform-dependant code. Jupiter includes a Socket wrapper, allowing for simple interaction with sockets, while eliminating all of the platform-dependant code.
Jupiter sockets are also IP agnostic, allowing for compatibility with IPv4, IPv6, and whatever the future may hold. Jupiter sockets are also IP agnostic, allowing for compatibility with IPv4, IPv6, and whatever the future may hold.

10
src/common/Config.cpp

@ -30,7 +30,7 @@ Jupiter::Config& Jupiter::Config::operator=(const Config& in_config) {
} }
std::string_view Jupiter::Config::get(std::string_view in_key, std::string_view in_default_value) const { std::string_view Jupiter::Config::get(std::string_view in_key, std::string_view in_default_value) const {
auto value = m_table.find(JUPITER_WRAP_CONFIG_KEY(in_key)); auto value = m_table.find(JUPITER_WRAP_MAP_KEY(in_key));
if (value != m_table.end()) { if (value != m_table.end()) {
return value->second; return value->second;
} }
@ -40,7 +40,7 @@ std::string_view Jupiter::Config::get(std::string_view in_key, std::string_view
Jupiter::Config *Jupiter::Config::getSection(std::string_view in_key) const { Jupiter::Config *Jupiter::Config::getSection(std::string_view in_key) const {
if (m_sections != nullptr) { if (m_sections != nullptr) {
auto section = m_sections->find(JUPITER_WRAP_CONFIG_KEY(in_key)); auto section = m_sections->find(JUPITER_WRAP_MAP_KEY(in_key));
if (section != m_sections->end()) { if (section != m_sections->end()) {
return &section->second; return &section->second;
} }
@ -54,7 +54,7 @@ Jupiter::Config &Jupiter::Config::getSectionReference(std::string_view in_key) {
m_sections = std::make_unique<SectionHashTable>(); m_sections = std::make_unique<SectionHashTable>();
} }
auto section = m_sections->find(JUPITER_WRAP_CONFIG_KEY(in_key)); auto section = m_sections->find(JUPITER_WRAP_MAP_KEY(in_key));
if (section == m_sections->end()) { if (section == m_sections->end()) {
// for some reason msvc doesn't like emplace // for some reason msvc doesn't like emplace
section = m_sections->try_emplace(static_cast<std::string>(in_key)).first; section = m_sections->try_emplace(static_cast<std::string>(in_key)).first;
@ -72,7 +72,7 @@ bool Jupiter::Config::set(std::string_view in_key, std::string in_value) {
} }
bool Jupiter::Config::remove(std::string_view in_key) { bool Jupiter::Config::remove(std::string_view in_key) {
auto value = m_table.find(JUPITER_WRAP_CONFIG_KEY(in_key)); auto value = m_table.find(JUPITER_WRAP_MAP_KEY(in_key));
if (value == m_table.end()) { if (value == m_table.end()) {
return false; return false;
} }
@ -86,7 +86,7 @@ bool Jupiter::Config::removeSection(std::string_view in_key) {
return false; return false;
} }
auto section = m_sections->find(JUPITER_WRAP_CONFIG_KEY(in_key)); auto section = m_sections->find(JUPITER_WRAP_MAP_KEY(in_key));
if (section == m_sections->end()) { if (section == m_sections->end()) {
return false; return false;
} }

1
src/common/DataBuffer.cpp

@ -19,7 +19,6 @@
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include "DataBuffer.h" #include "DataBuffer.h"
#include "Reference_String.h"
Jupiter::DataBuffer::DataBuffer() { Jupiter::DataBuffer::DataBuffer() {
Jupiter::DataBuffer::base = nullptr; Jupiter::DataBuffer::base = nullptr;

2
src/common/Database.cpp

@ -17,7 +17,7 @@
*/ */
#include "Database.h" #include "Database.h"
#include <cstring> #include "DataBuffer.h"
struct Jupiter::Database::Data struct Jupiter::Database::Data
{ {

4
src/common/File.cpp

@ -20,7 +20,6 @@
#include <string> #include <string>
#include "jessilib/word_split.hpp" #include "jessilib/word_split.hpp"
#include "File.h" #include "File.h"
#include "String.hpp"
#if defined _WIN32 #if defined _WIN32
#define stat64 _stat64 #define stat64 _stat64
@ -142,10 +141,9 @@ bool Jupiter::File::load(std::string file) {
} }
bool Jupiter::File::load(FILE *file) { bool Jupiter::File::load(FILE *file) {
Jupiter::String buffer(defaultBufferSize); std::string buffer;
int chr; int chr;
while (true) { while (true) {
chr = fgetc(file); chr = fgetc(file);

13
src/common/GenericCommand.cpp

@ -20,7 +20,6 @@
#include "jessilib/word_split.hpp" #include "jessilib/word_split.hpp"
#include "Plugin.h" #include "Plugin.h"
using namespace Jupiter::literals;
using namespace std::literals; using namespace std::literals;
// Is there a reason we're not using WHITESPACE_SV? // Is there a reason we're not using WHITESPACE_SV?
@ -103,8 +102,7 @@ Jupiter::GenericCommandNamespace::~GenericCommandNamespace() {
Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommandNamespace::trigger(std::string_view in_input) { Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommandNamespace::trigger(std::string_view in_input) {
GenericCommand* command; GenericCommand* command;
Jupiter::ReferenceString input(in_input); auto split_input = jessilib::word_split_once_view(in_input, GENERIC_COMMAND_WORD_DELIMITER_SV);
auto split_input = jessilib::word_split_once_view(input, GENERIC_COMMAND_WORD_DELIMITER_SV);
if (split_input.second.empty()) { // No parameters; list commands if (split_input.second.empty()) { // No parameters; list commands
return new Jupiter::GenericCommand::ResponseLine(m_help,Jupiter::GenericCommand::DisplayType::PrivateSuccess); return new Jupiter::GenericCommand::ResponseLine(m_help,Jupiter::GenericCommand::DisplayType::PrivateSuccess);
@ -115,14 +113,11 @@ Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommandNamespace::trigger
return command->trigger(split_input.second); return command->trigger(split_input.second);
} }
return new Jupiter::GenericCommand::ResponseLine(""_jrs, Jupiter::GenericCommand::DisplayType::PrivateError); return new Jupiter::GenericCommand::ResponseLine(""sv, Jupiter::GenericCommand::DisplayType::PrivateError);
} }
std::string_view Jupiter::GenericCommandNamespace::getHelp(std::string_view parameters) { std::string_view Jupiter::GenericCommandNamespace::getHelp(std::string_view parameters) {
static Jupiter::ReferenceString not_found = "Error: Command not found"_jrs; auto input_split = jessilib::word_split_once_view(parameters, GENERIC_COMMAND_WORD_DELIMITER_SV);
Jupiter::ReferenceString input(parameters);
auto input_split = jessilib::word_split_once_view(input, GENERIC_COMMAND_WORD_DELIMITER_SV);
if (input_split.second.empty()) // No parameters; list commands if (input_split.second.empty()) // No parameters; list commands
{ {
if (Jupiter::GenericCommandNamespace::m_should_update_help) if (Jupiter::GenericCommandNamespace::m_should_update_help)
@ -140,7 +135,7 @@ std::string_view Jupiter::GenericCommandNamespace::getHelp(std::string_view para
} }
// Command not found // Command not found
return not_found; return "Error: Command not found"sv;
} }
bool Jupiter::GenericCommandNamespace::isNamespace() const { bool Jupiter::GenericCommandNamespace::isNamespace() const {

73
src/common/HTTP_Server.cpp

@ -21,16 +21,14 @@
#include <numeric> #include <numeric>
#include "jessilib/split.hpp" #include "jessilib/split.hpp"
#include "jessilib/unicode.hpp" #include "jessilib/unicode.hpp"
#include "String.hpp"
#include "Reference_String.h"
#include "TCPSocket.h" #include "TCPSocket.h"
#include "HTTP.h" #include "HTTP.h"
#include "HTTP_Server.h" #include "HTTP_Server.h"
using namespace Jupiter::literals;
using namespace std::literals; using namespace std::literals;
static const std::string_view HTTP_REQUEST_ENDING = "\r\n\r\n"sv; static const std::string_view HTTP_REQUEST_ENDING = "\r\n\r\n"sv;
#define HTTP_ENDL "\r\n"
template<typename ResultT = unsigned int, typename InT> template<typename ResultT = unsigned int, typename InT>
ResultT calc_checksum(const InT& in_container) { ResultT calc_checksum(const InT& in_container) {
@ -130,7 +128,7 @@ directory_add_loop: // TODO: for the love of god, why why why
// add directory // add directory
size_t index = in_name_ref.find('/'); size_t index = in_name_ref.find('/');
if (index != Jupiter::INVALID_INDEX) { if (index != std::string_view::npos) {
directory->directories.push_back(std::make_unique<Directory>(static_cast<std::string>(in_name_ref.substr(size_t{ 0 }, index)))); directory->directories.push_back(std::make_unique<Directory>(static_cast<std::string>(in_name_ref.substr(size_t{ 0 }, index))));
directory = directory->directories[directories.size() - 1].get(); directory = directory->directories[directories.size() - 1].get();
in_name_ref.remove_prefix(index + 1); in_name_ref.remove_prefix(index + 1);
@ -191,7 +189,7 @@ Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(std::stri
} }
size_t index = in_name_ref.find('/'); size_t index = in_name_ref.find('/');
if (index == Jupiter::INVALID_INDEX) { // Search content if (index == std::string_view::npos) { // Search content
unsigned int content_name_checksum = calc_checksum(in_name_ref); unsigned int content_name_checksum = calc_checksum(in_name_ref);
index = content.size(); index = content.size();
for (auto& content_item : content) { for (auto& content_item : content) {
@ -291,7 +289,7 @@ struct Jupiter::HTTP::Server::Data {
Jupiter::HTTP::Server::Data::Data() { Jupiter::HTTP::Server::Data::Data() {
// hosts[0] is always the "global" namespace. // hosts[0] is always the "global" namespace.
m_hosts.push_back(std::make_unique<Host>(static_cast<std::string>(Jupiter::HTTP::Server::global_namespace))); m_hosts.push_back(std::make_unique<Host>(""s));
} }
// Data destructor // Data destructor
@ -302,7 +300,6 @@ Jupiter::HTTP::Server::Data::~Data() {
// Data functions // Data functions
void Jupiter::HTTP::Server::Data::hook(std::string_view hostname, std::string_view 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 dir_name;
Jupiter::HTTP::Server::Host* host = find_host(hostname); Jupiter::HTTP::Server::Host* host = find_host(hostname);
if (host == nullptr) { if (host == nullptr) {
@ -458,29 +455,30 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
{ {
default: default:
case HTTPVersion::HTTP_1_0: case HTTPVersion::HTTP_1_0:
result = "HTTP/1.0 200 OK"_jrs ENDL; result = "HTTP/1.0 200 OK"sv HTTP_ENDL;
break; break;
case HTTPVersion::HTTP_1_1: case HTTPVersion::HTTP_1_1:
result = "HTTP/1.1 200 OK"_jrs ENDL; result = "HTTP/1.1 200 OK"sv HTTP_ENDL;
break; break;
} }
result += "Date: "_jrs; result += "Date: "sv;
char *time_header = html_time(); char *time_header = html_time();
result += time_header; result += time_header;
delete[] time_header; delete[] time_header;
result += ENDL; result += HTTP_ENDL;
result += "Server: "_jrs JUPITER_VERSION ENDL; result += "Server: "sv JUPITER_VERSION HTTP_ENDL;
result += "Content-Length: "sv;
result += string_printf("Content-Length: %u" ENDL, content_result->size()); result += std::to_string(content_result->size()); // TODO: to_chars?
result += HTTP_ENDL;
if (session.keep_alive) if (session.keep_alive)
result += "Connection: keep-alive"_jrs ENDL; result += "Connection: keep-alive"sv HTTP_ENDL;
else else
result += "Connection: close"_jrs ENDL; result += "Connection: close"sv HTTP_ENDL;
result += "Content-Type: "_jrs; result += "Content-Type: "sv;
if (content->type.empty()) { if (content->type.empty()) {
result += Jupiter::HTTP::Content::Type::Text::PLAIN; result += Jupiter::HTTP::Content::Type::Text::PLAIN;
} }
@ -489,18 +487,18 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
} }
if (!content->charset.empty()) { if (!content->charset.empty()) {
result += "; charset="_jrs; result += "; charset="sv;
result += content->charset; result += content->charset;
} }
result += ENDL; result += HTTP_ENDL;
if (!content->language.empty()) { if (!content->language.empty()) {
result += "Content-Language: "_jrs; result += "Content-Language: "sv;
result += content->language; result += content->language;
result += ENDL; result += HTTP_ENDL;
} }
result += ENDL; result += HTTP_ENDL;
if (command == HTTPCommand::GET) if (command == HTTPCommand::GET)
result += *content_result; result += *content_result;
@ -517,28 +515,28 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
{ {
default: default:
case HTTPVersion::HTTP_1_0: case HTTPVersion::HTTP_1_0:
result = "HTTP/1.0 404 Not Found"_jrs ENDL; result = "HTTP/1.0 404 Not Found"sv HTTP_ENDL;
break; break;
case HTTPVersion::HTTP_1_1: case HTTPVersion::HTTP_1_1:
result = "HTTP/1.1 404 Not Found"_jrs ENDL; result = "HTTP/1.1 404 Not Found"sv HTTP_ENDL;
break; break;
} }
char *time_header = html_time(); char *time_header = html_time();
result += "Date: "_jrs ENDL; result += "Date: "sv HTTP_ENDL;
result += time_header; result += time_header;
delete[] time_header; delete[] time_header;
result += "Server: "_jrs JUPITER_VERSION ENDL; result += "Server: "sv JUPITER_VERSION HTTP_ENDL;
result += "Content-Length: 0"_jrs ENDL; result += "Content-Length: 0"sv HTTP_ENDL;
if (session.keep_alive) if (session.keep_alive)
result += "Connection: keep-alive"_jrs ENDL; result += "Connection: keep-alive"sv HTTP_ENDL;
else else
result += "Connection: close"_jrs ENDL; result += "Connection: close"sv HTTP_ENDL;
result += ENDL ENDL; result += HTTP_ENDL HTTP_ENDL;
session.sock.send(result); session.sock.send(result);
} }
break; break;
@ -558,7 +556,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
session.request = session.request.substr(get_line_offset(index)); 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) != std::string::npos) { // there's another full request already received
return process_request(session); return process_request(session);
} }
break; break;
@ -587,7 +585,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
auto second_split = jessilib::split_once_view(first_split.second, ' '); auto second_split = jessilib::split_once_view(first_split.second, ' ');
query_string = second_split.first; query_string = second_split.first;
span = query_string.find('?'); // repurposing 'span' span = query_string.find('?'); // repurposing 'span'
if (span == Jupiter::INVALID_INDEX) { if (span == std::string_view::npos) {
if (session.host == nullptr) { if (session.host == nullptr) {
content = find(query_string); content = find(query_string);
} }
@ -622,7 +620,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
auto second_split = jessilib::split_once_view(first_split.second, ' '); auto second_split = jessilib::split_once_view(first_split.second, ' ');
query_string = second_split.first; query_string = second_split.first;
span = query_string.find('?'); // repurposing 'span' span = query_string.find('?'); // repurposing 'span'
if (span == Jupiter::INVALID_INDEX) { if (span == std::string_view::npos) {
if (session.host == nullptr) { if (session.host == nullptr) {
content = find(query_string); content = find(query_string);
} }
@ -753,7 +751,7 @@ int Jupiter::HTTP::Server::think() {
std::string_view 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 if (session->request.size() + sock_buffer.size() <= m_data->max_request_size) { // accept
session->request += sock_buffer; session->request += sock_buffer;
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request if (session->request.find(HTTP_REQUEST_ENDING) != std::string::npos) { // completed request
session->last_active = std::chrono::steady_clock::now(); session->last_active = std::chrono::steady_clock::now();
m_data->process_request(*session); m_data->process_request(*session);
if (session->keep_alive == false) { // remove completed session if (session->keep_alive == false) { // remove completed session
@ -794,7 +792,7 @@ int Jupiter::HTTP::Server::think() {
std::string_view sock_buffer = session->sock.getBuffer(); std::string_view sock_buffer = session->sock.getBuffer();
if (sock_buffer.size() < m_data->max_request_size) { // accept if (sock_buffer.size() < m_data->max_request_size) { // accept
session->request = session->sock.getBuffer(); session->request = session->sock.getBuffer();
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request if (sock_buffer.find(HTTP_REQUEST_ENDING) != std::string_view::npos) { // completed request
m_data->process_request(*session); m_data->process_request(*session);
if (session->keep_alive) { // session will live for 30 seconds. if (session->keep_alive) { // session will live for 30 seconds.
m_data->m_sessions.push_back(std::move(session)); m_data->m_sessions.push_back(std::move(session));
@ -806,7 +804,7 @@ int Jupiter::HTTP::Server::think() {
} }
} }
else if (sock_buffer.size() == m_data->max_request_size) { else if (sock_buffer.size() == m_data->max_request_size) {
if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) { // reject (too large) if (sock_buffer.find(HTTP_REQUEST_ENDING) == std::string_view::npos) { // reject (too large)
continue; continue;
} }
@ -827,6 +825,3 @@ int Jupiter::HTTP::Server::think() {
} }
return 0; return 0;
} }
std::string_view Jupiter::HTTP::Server::global_namespace = ""_jrs;
std::string_view Jupiter::HTTP::Server::server_string = "Jupiter"_jrs;

4
src/common/INIConfig.cpp

@ -131,7 +131,7 @@ bool Jupiter::INIConfig::read_internal(const char *in_filename) {
while (depth > section_stack.size()) while (depth > section_stack.size())
section_stack.push(std::addressof(section_stack.top()->getSectionReference({}))); section_stack.push(std::addressof(section_stack.top()->getSectionReference({})));
section_stack.push(&section_stack.top()->getSectionReference(static_cast<KeyType>(line))); section_stack.push(&section_stack.top()->getSectionReference(line));
} }
else else
{ {
@ -180,7 +180,7 @@ bool Jupiter::INIConfig::read_internal(const char *in_filename) {
line = std::string_view{}; line = std::string_view{};
// Add entry to current table on stack // Add entry to current table on stack
section_stack.top()->set(KeyType{key}, static_cast<std::string>(line)); section_stack.top()->set(std::string{key}, static_cast<std::string>(line));
} }
}; };

181
src/common/IRC_Client.cpp

@ -27,14 +27,13 @@
#include "Jupiter.h" #include "Jupiter.h"
#include "Functions.h" #include "Functions.h"
#include "TCPSocket.h" #include "TCPSocket.h"
#include "String.hpp"
#include "Plugin.h" #include "Plugin.h"
#include "Base64.h" #include "Base64.h"
#include "Readable_String.h"
//#define SHORT_IRC_MACROS //#define SHORT_IRC_MACROS
#include "IRC_Numerics.h" #include "IRC_Numerics.h"
using namespace Jupiter::literals;
using namespace std::literals; using namespace std::literals;
Jupiter::IRC::Client::Client(Jupiter::Config *in_primary_section, Jupiter::Config *in_secondary_section) { Jupiter::IRC::Client::Client(Jupiter::Config *in_primary_section, Jupiter::Config *in_secondary_section) {
@ -44,42 +43,42 @@ Jupiter::IRC::Client::Client(Jupiter::Config *in_primary_section, Jupiter::Confi
if (m_primary_section != nullptr) if (m_primary_section != nullptr)
m_primary_section_name = m_primary_section->getName(); m_primary_section_name = m_primary_section->getName();
m_server_hostname = static_cast<std::string>(Jupiter::IRC::Client::readConfigValue("Hostname"_jrs, ""_jrs)); m_server_hostname = static_cast<std::string>(Jupiter::IRC::Client::readConfigValue("Hostname"sv, ""sv));
m_log_file_name = static_cast<std::string>(Jupiter::IRC::Client::readConfigValue("LogFile"_jrs)); m_log_file_name = static_cast<std::string>(Jupiter::IRC::Client::readConfigValue("LogFile"sv));
m_nickname = Jupiter::IRC::Client::readConfigValue("Nick"_jrs, "Jupiter"_jrs); m_nickname = Jupiter::IRC::Client::readConfigValue("Nick"sv, "Jupiter"sv);
m_realname = Jupiter::IRC::Client::readConfigValue("RealName"_jrs, "Jupiter IRC Client"_jrs); m_realname = Jupiter::IRC::Client::readConfigValue("RealName"sv, "Jupiter IRC Client"sv);
m_sasl_password = Jupiter::IRC::Client::readConfigValue("SASL.Password"_jrs); m_sasl_password = Jupiter::IRC::Client::readConfigValue("SASL.Password"sv);
if (m_sasl_password.empty()) if (m_sasl_password.empty())
m_sasl_password = Jupiter::IRC::Client::readConfigValue("SASL.Pass"_jrs); m_sasl_password = Jupiter::IRC::Client::readConfigValue("SASL.Pass"sv);
m_sasl_account = Jupiter::IRC::Client::readConfigValue("SASL.Account"_jrs); m_sasl_account = Jupiter::IRC::Client::readConfigValue("SASL.Account"sv);
if (m_sasl_account.empty()) if (m_sasl_account.empty())
m_sasl_account = m_nickname; m_sasl_account = m_nickname;
m_auto_part_message = Jupiter::IRC::Client::readConfigValue("AutoPartMessage"_jrs); m_auto_part_message = Jupiter::IRC::Client::readConfigValue("AutoPartMessage"sv);
m_ssl = Jupiter::IRC::Client::readConfigBool("SSL"_jrs); m_ssl = Jupiter::IRC::Client::readConfigBool("SSL"sv);
m_ssl_certificate = Jupiter::IRC::Client::readConfigValue("Certificate"_jrs); m_ssl_certificate = Jupiter::IRC::Client::readConfigValue("Certificate"sv);
m_ssl_key = Jupiter::IRC::Client::readConfigValue("Key"_jrs); m_ssl_key = Jupiter::IRC::Client::readConfigValue("Key"sv);
if (m_ssl_certificate.empty()) if (m_ssl_certificate.empty())
{ {
m_ssl_certificate = Jupiter::IRC::Client::readConfigValue("Cert"_jrs); m_ssl_certificate = Jupiter::IRC::Client::readConfigValue("Cert"sv);
if (m_ssl_certificate.empty()) if (m_ssl_certificate.empty())
m_ssl_certificate = m_ssl_key; m_ssl_certificate = m_ssl_key;
} }
if (m_ssl_key.empty()) if (m_ssl_key.empty())
m_ssl_key = m_ssl_certificate; m_ssl_key = m_ssl_certificate;
m_join_on_kick = Jupiter::IRC::Client::readConfigBool("AutoJoinOnKick"_jrs); m_join_on_kick = Jupiter::IRC::Client::readConfigBool("AutoJoinOnKick"sv);
m_reconnect_delay = Jupiter::IRC::Client::readConfigInt("AutoReconnectDelay"_jrs); m_reconnect_delay = Jupiter::IRC::Client::readConfigInt("AutoReconnectDelay"sv);
m_max_reconnect_attempts = Jupiter::IRC::Client::readConfigInt("MaxReconnectAttempts"_jrs); m_max_reconnect_attempts = Jupiter::IRC::Client::readConfigInt("MaxReconnectAttempts"sv);
m_server_port = (unsigned short)Jupiter::IRC::Client::readConfigInt("Port"_jrs, m_ssl ? 994 : 194); m_server_port = (unsigned short)Jupiter::IRC::Client::readConfigInt("Port"sv, m_ssl ? 994 : 194);
m_default_chan_type = Jupiter::IRC::Client::readConfigInt("Channel.Type"_jrs); m_default_chan_type = Jupiter::IRC::Client::readConfigInt("Channel.Type"sv);
if (Jupiter::IRC::Client::readConfigBool("PrintOutput"_jrs, true)) if (Jupiter::IRC::Client::readConfigBool("PrintOutput"sv, true))
m_output = stdout; m_output = stdout;
else else
m_output = nullptr; m_output = nullptr;
@ -171,7 +170,7 @@ std::string_view Jupiter::IRC::Client::getConfigSection() const {
return m_primary_section_name; return m_primary_section_name;
} }
return ""_jrs; return ""sv;
} }
Jupiter::Config *Jupiter::IRC::Client::getPrimaryConfigSection() const { Jupiter::Config *Jupiter::IRC::Client::getPrimaryConfigSection() const {
@ -255,7 +254,7 @@ void Jupiter::IRC::Client::setPrintOutput(FILE *f) {
m_output = f; m_output = f;
} }
Jupiter::ReferenceString getSender(std::string_view line) { std::string_view getSender(std::string_view line) {
return jessilib::word_split_once_view(line, ":! "sv).first; return jessilib::word_split_once_view(line, ":! "sv).first;
} }
@ -270,7 +269,7 @@ int Jupiter::IRC::Client::getAccessLevel(const Channel &in_channel, std::string_
} }
int Jupiter::IRC::Client::getAccessLevel(std::string_view in_channel, std::string_view in_nickname) const { int Jupiter::IRC::Client::getAccessLevel(std::string_view in_channel, std::string_view in_nickname) const {
auto channel = m_channels.find(in_channel); auto channel = m_channels.find(JUPITER_WRAP_MAP_KEY(in_channel));
if (channel != m_channels.end()) if (channel != m_channels.end())
return this->getAccessLevel(channel->second, in_nickname); return this->getAccessLevel(channel->second, in_nickname);
@ -279,10 +278,7 @@ int Jupiter::IRC::Client::getAccessLevel(std::string_view in_channel, std::strin
} }
void Jupiter::IRC::Client::send(std::string_view rawMessage) { void Jupiter::IRC::Client::send(std::string_view rawMessage) {
Jupiter::StringS out = rawMessage; m_socket->send(static_cast<std::string>(rawMessage) + "\r\n");
out += ENDL;
m_socket->send(out);
} }
const Jupiter::IRC::Client::UserTableType &Jupiter::IRC::Client::getUsers() const { const Jupiter::IRC::Client::UserTableType &Jupiter::IRC::Client::getUsers() const {
@ -294,7 +290,7 @@ size_t Jupiter::IRC::Client::getUserCount() const {
} }
std::shared_ptr<Jupiter::IRC::Client::User> Jupiter::IRC::Client::getUser(std::string_view in_nickname) const { std::shared_ptr<Jupiter::IRC::Client::User> Jupiter::IRC::Client::getUser(std::string_view in_nickname) const {
auto user = m_users.find(in_nickname); auto user = m_users.find(JUPITER_WRAP_MAP_KEY(in_nickname));
if (user != m_users.end()) { if (user != m_users.end()) {
return user->second; return user->second;
} }
@ -311,8 +307,7 @@ size_t Jupiter::IRC::Client::getChannelCount() const {
} }
Jupiter::IRC::Client::Channel *Jupiter::IRC::Client::getChannel(std::string_view in_channel) const { Jupiter::IRC::Client::Channel *Jupiter::IRC::Client::getChannel(std::string_view in_channel) const {
Jupiter::ReferenceString channel_name = in_channel; // TODO: remove this auto channel = m_channels.find(JUPITER_WRAP_MAP_KEY(in_channel));
auto channel = m_channels.find(channel_name);
if (channel != m_channels.end()) { if (channel != m_channels.end()) {
return const_cast<Channel*>(&channel->second); return const_cast<Channel*>(&channel->second);
} }
@ -339,15 +334,19 @@ void Jupiter::IRC::Client::joinChannel(std::string_view in_channel, std::string_
void Jupiter::IRC::Client::partChannel(std::string_view in_channel) { void Jupiter::IRC::Client::partChannel(std::string_view in_channel) {
m_socket->send(string_printf("PART %.*s" ENDL, in_channel.size(), in_channel.data())); m_socket->send(string_printf("PART %.*s" ENDL, in_channel.size(), in_channel.data()));
Jupiter::ReferenceString channel_name = in_channel; auto channel = m_channels.find(JUPITER_WRAP_MAP_KEY(in_channel));
m_channels[channel_name].setType(-2); if (channel != m_channels.end()) {
channel->second.setType(-2);
}
} }
void Jupiter::IRC::Client::partChannel(std::string_view in_channel, std::string_view in_message) { void Jupiter::IRC::Client::partChannel(std::string_view in_channel, std::string_view in_message) {
m_socket->send(string_printf("PART %.*s :%.*s" ENDL, in_channel.size(), in_channel.data(), in_message.size(), in_message.data())); m_socket->send(string_printf("PART %.*s :%.*s" ENDL, in_channel.size(), in_channel.data(), in_message.size(), in_message.data()));
Jupiter::ReferenceString channel_name = in_channel; auto channel = m_channels.find(JUPITER_WRAP_MAP_KEY(in_channel));
m_channels[channel_name].setType(-2); if (channel != m_channels.end()) {
channel->second.setType(-2);
}
} }
void Jupiter::IRC::Client::sendMessage(std::string_view dest, std::string_view message) { void Jupiter::IRC::Client::sendMessage(std::string_view dest, std::string_view message) {
@ -387,7 +386,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
auto first_split = jessilib::split_once_view(line, " "sv); auto first_split = jessilib::split_once_view(line, " "sv);
Jupiter::ReferenceString w1 = first_split.first; std::string_view w1 = first_split.first;
if (!w1.empty()) if (!w1.empty())
{ {
int numeric = asInt(first_split.second); int numeric = asInt(first_split.second);
@ -395,7 +394,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
if (!first_split.second.empty()) { if (!first_split.second.empty()) {
// TODO: This entire method should basically just be a state machine instead of this massive mess // TODO: This entire method should basically just be a state machine instead of this massive mess
auto line_split = jessilib::split_view(line, " "sv); auto line_split = jessilib::split_view(line, " "sv);
auto getLineToken = [&line_split](size_t index) -> Jupiter::ReferenceString { auto getLineToken = [&line_split](size_t index) -> std::string_view {
if (index < line_split.size()) { if (index < line_split.size()) {
return line_split[index]; return line_split[index];
} }
@ -442,7 +441,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
{ {
case Error::UNKNOWNCOMMAND: // 421 case Error::UNKNOWNCOMMAND: // 421
{ {
Jupiter::ReferenceString command = getLineToken(2); std::string_view command = getLineToken(2);
if (jessilib::equalsi(command, "STARTTLS"sv)) { // Server doesn't support STARTTLS if (jessilib::equalsi(command, "STARTTLS"sv)) { // Server doesn't support STARTTLS
Client::startCAP(); Client::startCAP();
} }
@ -492,7 +491,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
case 0: case 0:
if (jessilib::equalsi(getLineToken(1), "CAP"sv)) if (jessilib::equalsi(getLineToken(1), "CAP"sv))
{ {
Jupiter::ReferenceString w4 = getLineToken(3); std::string_view w4 = getLineToken(3);
if (w4 == "LS"sv) if (w4 == "LS"sv)
{ {
std::vector<std::string_view> cap_list{ line_split.begin() + 4, line_split.end() }; std::vector<std::string_view> cap_list{ line_split.begin() + 4, line_split.end() };
@ -567,8 +566,8 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
case Error::NICKNAMEINUSE: // 433 case Error::NICKNAMEINUSE: // 433
case Error::NICKCOLLISION: // 436 case Error::NICKCOLLISION: // 436
case Error::BANNICKCHANGE: // 437 -- Note: This conflicts with another token. case Error::BANNICKCHANGE: // 437 -- Note: This conflicts with another token.
std::string_view altNick = Jupiter::IRC::Client::readConfigValue("AltNick"_jrs); std::string_view altNick = Jupiter::IRC::Client::readConfigValue("AltNick"sv);
std::string_view configNick = Jupiter::IRC::Client::readConfigValue("Nick"_jrs, "Jupiter"_jrs); std::string_view configNick = Jupiter::IRC::Client::readConfigValue("Nick"sv, "Jupiter"sv);
if (!altNick.empty() && jessilib::equalsi(m_nickname, altNick)) // The alternate nick failed. if (!altNick.empty() && jessilib::equalsi(m_nickname, altNick)) // The alternate nick failed.
{ {
@ -630,9 +629,8 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
case Reply::ISUPPORT: // 005 case Reply::ISUPPORT: // 005
{ {
// Parse supported user prefixes // Parse supported user prefixes
size_t pos = line.find("PREFIX=("_jrs); size_t pos = line.find("PREFIX=("sv);
if (pos != Jupiter::INVALID_INDEX) if (pos != std::string_view::npos) {
{
std::string_view prefix_line_start = line.substr(pos + 8); std::string_view prefix_line_start = line.substr(pos + 8);
size_t prefix_modes_end = prefix_line_start.find(')'); size_t prefix_modes_end = prefix_line_start.find(')');
if (prefix_modes_end != std::string_view::npos) { if (prefix_modes_end != std::string_view::npos) {
@ -643,8 +641,8 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
// Parse supported channel modes // Parse supported channel modes
pos = line.find("CHANMODES="_jrs); pos = line.find("CHANMODES="sv);
if (pos != Jupiter::INVALID_INDEX) { if (pos != std::string_view::npos) {
std::string_view chan_modes_view = line.substr(pos + 10, line.find(' ')); std::string_view chan_modes_view = line.substr(pos + 10, line.find(' '));
std::vector<std::string_view> chan_modes = jessilib::split_n_view(chan_modes_view, ","sv, 3); // only split 3 times to cover A-D, but server _can_ send more std::vector<std::string_view> chan_modes = jessilib::split_n_view(chan_modes_view, ","sv, 3); // only split 3 times to cover A-D, but server _can_ send more
if (chan_modes.size() > 0) { if (chan_modes.size() > 0) {
@ -662,8 +660,8 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
// Parse supported channel types // Parse supported channel types
pos = line.find("CHANTYPES="_jrs); pos = line.find("CHANTYPES="sv);
if (pos != Jupiter::INVALID_INDEX) { if (pos != std::string_view::npos) {
m_chan_types = line.substr(pos + 10, line.find(' ')); m_chan_types = line.substr(pos + 10, line.find(' '));
} }
} }
@ -674,7 +672,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
size_t offset = key.size(); size_t offset = key.size();
unsigned int i = 1; unsigned int i = 1;
Jupiter::ReferenceString value; std::string_view value;
auto config_loop_condition = [&] auto config_loop_condition = [&]
{ {
key += std::to_string(i); key += std::to_string(i);
@ -692,15 +690,15 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
{ {
if (config != nullptr) { if (config != nullptr) {
for (auto& section : config->getSections()) { for (auto& section : config->getSections()) {
if (section.second.get<bool>("AutoJoin"_jrs, false)) { if (section.second.get<bool>("AutoJoin"sv, false)) {
this->joinChannel(section.first); this->joinChannel(section.first);
} }
} }
} }
}; };
join_channels_for_config(m_primary_section->getSection("Channels"_jrs)); join_channels_for_config(m_primary_section->getSection("Channels"sv));
join_channels_for_config(m_secondary_section->getSection("Channels"_jrs)); join_channels_for_config(m_secondary_section->getSection("Channels"sv));
m_connection_status = 5; m_connection_status = 5;
m_reconnect_attempts = 0; m_reconnect_attempts = 0;
@ -777,10 +775,9 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
} }
else { else {
Jupiter::ReferenceString message = message_view; this->OnChat(channel_name, nick, message_view);
this->OnChat(channel_name, nick, message);
for (auto& plugin: Jupiter::plugins) { for (auto& plugin: Jupiter::plugins) {
plugin->OnChat(this, channel_name, nick, message); plugin->OnChat(this, channel_name, nick, message_view);
} }
} }
} }
@ -870,7 +867,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
auto user = getUser(nick); auto user = getUser(nick);
if (user != nullptr) { if (user != nullptr) {
channel->delUser(nick); channel->delUser(nick);
Jupiter::ReferenceString reason; std::string_view reason;
size_t pos = line.find(':', 1); size_t pos = line.find(':', 1);
if (pos != std::string_view::npos) if (pos != std::string_view::npos)
@ -885,8 +882,12 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
if (jessilib::equalsi(nick, m_nickname)) if (jessilib::equalsi(nick, m_nickname))
Client::delChannel(channel_name); Client::delChannel(channel_name);
if (user->getChannelCount() == 0) if (user->getChannelCount() == 0) {
m_users.erase(nick); auto user_itr = m_users.find(JUPITER_WRAP_MAP_KEY(nick));
if (user_itr != m_users.end()) {
m_users.erase(user_itr);
}
}
} }
} }
} }
@ -895,7 +896,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
else if (jessilib::equalsi(command_token, "KICK"sv)) { else if (jessilib::equalsi(command_token, "KICK"sv)) {
std::string_view channel_name = getLineToken(2); std::string_view channel_name = getLineToken(2);
if (!channel_name.empty()) { if (!channel_name.empty()) {
Jupiter::ReferenceString kicker = getSender(line); std::string_view kicker = getSender(line);
if (!kicker.empty()) { if (!kicker.empty()) {
std::string_view kicked_nickname = getLineToken(3); std::string_view kicked_nickname = getLineToken(3);
if (!kicked_nickname.empty()) { if (!kicked_nickname.empty()) {
@ -905,7 +906,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
if (user != nullptr) { if (user != nullptr) {
channel->delUser(kicked_nickname); channel->delUser(kicked_nickname);
size_t pos = line.find(':', 1); size_t pos = line.find(':', 1);
Jupiter::ReferenceString reason; std::string_view reason;
if (pos != std::string_view::npos) if (pos != std::string_view::npos)
reason = line.substr(pos + 1); reason = line.substr(pos + 1);
@ -924,7 +925,10 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
if (user->getChannelCount() == 0) { if (user->getChannelCount() == 0) {
m_users.erase(kicked_nickname); auto user_itr = m_users.find(JUPITER_WRAP_MAP_KEY(kicked_nickname));
if (user_itr != m_users.end()) {
m_users.erase(user_itr);
}
} }
} }
} }
@ -933,7 +937,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
} }
else if (jessilib::equalsi(command_token, "QUIT"sv)) { else if (jessilib::equalsi(command_token, "QUIT"sv)) {
Jupiter::ReferenceString nick = getSender(line); std::string_view nick = getSender(line);
std::string_view message = jessilib::split_once_view(line.substr(1), ':').second; std::string_view message = jessilib::split_once_view(line.substr(1), ':').second;
auto user = getUser(nick); auto user = getUser(nick);
if (user != nullptr) { if (user != nullptr) {
@ -947,11 +951,14 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
plugin->OnQuit(this, nick, message); plugin->OnQuit(this, nick, message);
} }
m_users.erase(nick); auto user_itr = m_users.find(JUPITER_WRAP_MAP_KEY(nick));
if (user_itr != m_users.end()) {
m_users.erase(user_itr);
}
} }
} }
else if (jessilib::equalsi(command_token, "INVITE"sv)) { else if (jessilib::equalsi(command_token, "INVITE"sv)) {
Jupiter::ReferenceString inviter = getSender(line); std::string_view inviter = getSender(line);
std::string_view invited_nickname = getLineToken(2); std::string_view invited_nickname = getLineToken(2);
std::string_view channel_name = jessilib::split_once_view(line.substr(1), ':').second; std::string_view channel_name = jessilib::split_once_view(line.substr(1), ':').second;
this->OnInvite(channel_name, inviter, invited_nickname); this->OnInvite(channel_name, inviter, invited_nickname);
@ -1084,7 +1091,7 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
{ {
if (!m_sasl_password.empty()) if (!m_sasl_password.empty())
{ {
Jupiter::StringS auth_str = m_nickname + '\0' + m_sasl_account + '\0' + m_sasl_password; std::string auth_str = m_nickname + '\0' + m_sasl_account + '\0' + m_sasl_password;
char *enc = Jupiter::base64encode(auth_str.data(), auth_str.size()); char *enc = Jupiter::base64encode(auth_str.data(), auth_str.size());
m_socket->send("AUTHENTICATE "s + enc + ENDL); m_socket->send("AUTHENTICATE "s + enc + ENDL);
@ -1112,12 +1119,12 @@ int Jupiter::IRC::Client::process_line(std::string_view line) {
} }
bool Jupiter::IRC::Client::connect() { bool Jupiter::IRC::Client::connect() {
std::string_view clientAddress = Jupiter::IRC::Client::readConfigValue("ClientAddress"_jrs); std::string_view clientAddress = Jupiter::IRC::Client::readConfigValue("ClientAddress"sv);
if (m_socket->connect(m_server_hostname.c_str(), m_server_port, clientAddress.empty() ? nullptr : static_cast<std::string>(clientAddress).c_str(), (unsigned short)Jupiter::IRC::Client::readConfigLong("ClientPort"_jrs)) == false) if (m_socket->connect(m_server_hostname.c_str(), m_server_port, clientAddress.empty() ? nullptr : static_cast<std::string>(clientAddress).c_str(), (unsigned short)Jupiter::IRC::Client::readConfigLong("ClientPort"sv)) == false)
return false; return false;
m_socket->setBlocking(false); m_socket->setBlocking(false);
if (m_ssl == false && Jupiter::IRC::Client::readConfigBool("STARTTLS"_jrs, true)) if (m_ssl == false && Jupiter::IRC::Client::readConfigBool("STARTTLS"sv, true))
{ {
m_socket->send("STARTTLS" ENDL); m_socket->send("STARTTLS" ENDL);
m_connection_status = 1; m_connection_status = 1;
@ -1135,7 +1142,7 @@ void Jupiter::IRC::Client::disconnect(bool stayDead)
m_reconnect_time = time(0) + m_reconnect_delay; m_reconnect_time = time(0) + m_reconnect_delay;
m_dead = stayDead; m_dead = stayDead;
this->OnDisconnect(); this->OnDisconnect();
bool ssl = Jupiter::IRC::Client::readConfigBool("SSL"_jrs); bool ssl = Jupiter::IRC::Client::readConfigBool("SSL"sv);
if (ssl != m_ssl) if (ssl != m_ssl)
{ {
m_ssl = ssl; m_ssl = ssl;
@ -1334,7 +1341,10 @@ void Jupiter::IRC::Client::writeToLogs(std::string_view message) {
*/ */
void Jupiter::IRC::Client::delChannel(std::string_view in_channel) { void Jupiter::IRC::Client::delChannel(std::string_view in_channel) {
m_channels.erase(in_channel); auto channel_itr = m_channels.find(JUPITER_WRAP_MAP_KEY(in_channel));
if (channel_itr != m_channels.end()) {
m_channels.erase(channel_itr);
}
} }
std::shared_ptr<Jupiter::IRC::Client::User> Jupiter::IRC::Client::findUser(std::string_view in_nickname) const { std::shared_ptr<Jupiter::IRC::Client::User> Jupiter::IRC::Client::findUser(std::string_view in_nickname) const {
@ -1390,8 +1400,7 @@ void Jupiter::IRC::Client::addNamesToChannel(Channel &in_channel, std::string_vi
} }
void Jupiter::IRC::Client::addChannel(std::string_view in_channel) { void Jupiter::IRC::Client::addChannel(std::string_view in_channel) {
Jupiter::ReferenceString channel_name = in_channel; m_channels.emplace(in_channel, Channel(in_channel, this));
m_channels.emplace(channel_name, Channel(channel_name, this));
} }
bool Jupiter::IRC::Client::startCAP() { bool Jupiter::IRC::Client::startCAP() {
@ -1420,15 +1429,15 @@ bool Jupiter::IRC::Client::registerClient() {
* User Implementation * User Implementation
*/ */
std::string_view Jupiter::IRC::Client::User::getNickname() const { const std::string& Jupiter::IRC::Client::User::getNickname() const {
return m_nickname; return m_nickname;
} }
std::string_view Jupiter::IRC::Client::User::getUsername() const { const std::string& Jupiter::IRC::Client::User::getUsername() const {
return m_username; return m_username;
} }
std::string_view Jupiter::IRC::Client::User::getHostname() const { const std::string& Jupiter::IRC::Client::User::getHostname() const {
return m_hostname; return m_hostname;
} }
@ -1441,8 +1450,9 @@ size_t Jupiter::IRC::Client::User::getChannelCount() const {
*/ */
Jupiter::IRC::Client::Channel::Channel(std::string_view in_name, Jupiter::IRC::Client *in_parent) { Jupiter::IRC::Client::Channel::Channel(std::string_view in_name, Jupiter::IRC::Client *in_parent) {
// TODO: remove this
auto to_lower = [&in_name]() { auto to_lower = [&in_name]() {
Jupiter::String result(in_name.size()); std::string result;
const char *itr = in_name.data(); const char *itr = in_name.data();
const char *end = itr + in_name.size(); const char *end = itr + in_name.size();
@ -1459,10 +1469,10 @@ Jupiter::IRC::Client::Channel::Channel(std::string_view in_name, Jupiter::IRC::C
m_parent = in_parent; m_parent = in_parent;
m_type = m_parent->getDefaultChanType(); m_type = m_parent->getDefaultChanType();
Jupiter::String name = to_lower(); std::string name = to_lower();
auto read_type = [&name](Jupiter::Config &in_config, int default_type) { auto read_type = [&name](Jupiter::Config &in_config, int default_type) {
return in_config["Channels"_jrs][name].get<int>("Type"_jrs, default_type); return in_config["Channels"sv][name].get<int>("Type"sv, default_type);
}; };
if (m_parent->getSecondaryConfigSection() != nullptr) if (m_parent->getSecondaryConfigSection() != nullptr)
@ -1494,7 +1504,10 @@ std::shared_ptr<Jupiter::IRC::Client::Channel::User> Jupiter::IRC::Client::Chann
} }
void Jupiter::IRC::Client::Channel::delUser(std::string_view in_nickname) { void Jupiter::IRC::Client::Channel::delUser(std::string_view in_nickname) {
m_users.erase(in_nickname); auto user_itr = m_users.find(JUPITER_WRAP_MAP_KEY(in_nickname));
if (user_itr != m_users.end()) {
m_users.erase(user_itr);
}
} }
void Jupiter::IRC::Client::Channel::addUserPrefix(std::string_view in_nickname, char prefix) { void Jupiter::IRC::Client::Channel::addUserPrefix(std::string_view in_nickname, char prefix) {
@ -1520,7 +1533,7 @@ std::string_view Jupiter::IRC::Client::Channel::getName() const {
} }
std::shared_ptr<Jupiter::IRC::Client::Channel::User> Jupiter::IRC::Client::Channel::getUser(std::string_view in_nickname) const { std::shared_ptr<Jupiter::IRC::Client::Channel::User> Jupiter::IRC::Client::Channel::getUser(std::string_view in_nickname) const {
auto user = m_users.find(in_nickname); auto user = m_users.find(JUPITER_WRAP_MAP_KEY(in_nickname));
if (user != m_users.end()) { if (user != m_users.end()) {
return user->second; return user->second;
} }
@ -1528,8 +1541,6 @@ std::shared_ptr<Jupiter::IRC::Client::Channel::User> Jupiter::IRC::Client::Chann
return nullptr; return nullptr;
} }
static_assert(Jupiter::INVALID_INDEX == std::string_view::npos);
char Jupiter::IRC::Client::Channel::getUserPrefix(const Channel::User& in_user) const { char Jupiter::IRC::Client::Channel::getUserPrefix(const Channel::User& in_user) const {
std::string_view prefixes = m_parent->getPrefixes(); std::string_view prefixes = m_parent->getPrefixes();
for (auto prefix : prefixes) { for (auto prefix : prefixes) {
@ -1579,19 +1590,19 @@ Jupiter::IRC::Client::User *Jupiter::IRC::Client::Channel::User::getUser() const
return m_user.get(); return m_user.get();
} }
std::string_view Jupiter::IRC::Client::Channel::User::getPrefixes() const { const std::string& Jupiter::IRC::Client::Channel::User::getPrefixes() const {
return m_prefixes; return m_prefixes;
} }
std::string_view Jupiter::IRC::Client::Channel::User::getNickname() const { const std::string& Jupiter::IRC::Client::Channel::User::getNickname() const {
return m_user->getNickname(); return m_user->getNickname();
} }
std::string_view Jupiter::IRC::Client::Channel::User::getUsername() const { const std::string& Jupiter::IRC::Client::Channel::User::getUsername() const {
return m_user->getUsername(); return m_user->getUsername();
} }
std::string_view Jupiter::IRC::Client::Channel::User::getHostname() const { const std::string& Jupiter::IRC::Client::Channel::User::getHostname() const {
return m_user->getHostname(); return m_user->getHostname();
} }

4
src/common/Plugin.cpp

@ -29,9 +29,7 @@
#include "Plugin.h" #include "Plugin.h"
#include <memory> #include <memory>
#include "Functions.h" #include "Functions.h"
#include "String.hpp"
using namespace Jupiter::literals;
using namespace std::literals; using namespace std::literals;
#if defined _WIN32 #if defined _WIN32
@ -102,7 +100,7 @@ bool Jupiter::Plugin::shouldRemove() const {
return _shouldRemove; return _shouldRemove;
} }
std::string_view Jupiter::Plugin::getName() const { const std::string& Jupiter::Plugin::getName() const {
return name; return name;
} }

10
src/common/Socket.cpp

@ -396,23 +396,23 @@ in_addr6 Jupiter::Socket::pton6(const char *str) {
return r; return r;
} }
Jupiter::StringS Jupiter::Socket::ntop4(uint32_t ip) { std::string Jupiter::Socket::ntop4(uint32_t ip) {
static char buf[16]; static char buf[16];
if (inet_ntop(AF_INET, &ip, buf, sizeof(buf)) == nullptr) { if (inet_ntop(AF_INET, &ip, buf, sizeof(buf)) == nullptr) {
return {}; return {};
} }
return Jupiter::String(buf); return std::string(buf);
} }
Jupiter::StringS Jupiter::Socket::ntop6(in_addr6 ip) { std::string Jupiter::Socket::ntop6(in_addr6 ip) {
static char buf[46]; static char buf[46];
if (inet_ntop(AF_INET6, &ip, buf, sizeof(buf)) == nullptr) { if (inet_ntop(AF_INET6, &ip, buf, sizeof(buf)) == nullptr) {
return {}; return {};
} }
return Jupiter::String(buf); return std::string(buf);
} }
Jupiter::StringS Jupiter::Socket::ntop(void *ip, size_t size) { std::string Jupiter::Socket::ntop(void *ip, size_t size) {
switch (size) { switch (size) {
case 4: case 4:
return ntop4(*reinterpret_cast<uint32_t *>(ip)); return ntop4(*reinterpret_cast<uint32_t *>(ip));

1
src/include/Jupiter/Base64.h

@ -27,7 +27,6 @@
#include <cstdint> #include <cstdint>
#include <cstddef> #include <cstddef>
#include "Jupiter.h" #include "Jupiter.h"
#include "String.hpp"
namespace Jupiter namespace Jupiter
{ {

14
src/include/Jupiter/Config.h

@ -28,8 +28,7 @@
#include <memory> #include <memory>
#include "Jupiter.h" #include "Jupiter.h"
#include "Hash.h" #include "Hash.h"
#include "Reference_String.h" #include "Readable_String.h" // from_string
#include "String.hpp"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
#if defined _MSC_VER #if defined _MSC_VER
@ -48,14 +47,7 @@ namespace Jupiter
/** Hash_Table type for sections */ /** Hash_Table type for sections */
using SectionHashTable = std::unordered_map<std::string, Config, str_hash<char>, std::equal_to<>>; using SectionHashTable = std::unordered_map<std::string, Config, str_hash<char>, std::equal_to<>>;
using ValuesHashTable = std::unordered_map<std::string, std::string, str_hash<char>, std::equal_to<>>; using ValuesHashTable = std::unordered_map<std::string, std::string, str_hash<char>, std::equal_to<>>;
using InKeyType = InMapKeyType;
#ifdef __cpp_lib_generic_unordered_lookup
using KeyType = std::string_view;
#define JUPITER_WRAP_CONFIG_KEY(in_key) in_key
#else // We can't use std::string_view for InKeyType until GCC 11 & clang 12, and I still want to support GCC 9
using KeyType = std::string;
#define JUPITER_WRAP_CONFIG_KEY(in_key) static_cast<KeyType>(in_key)
#endif // __cpp_lib_generic_unordered_lookup
Config() = default; Config() = default;
Config(const Config& in_config); Config(const Config& in_config);
@ -236,7 +228,7 @@ namespace Jupiter
template<typename T> template<typename T>
inline T Jupiter::Config::get(std::string_view in_key, T in_default_value) const { inline T Jupiter::Config::get(std::string_view in_key, T in_default_value) const {
auto result = m_table.find(JUPITER_WRAP_CONFIG_KEY(in_key)); auto result = m_table.find(JUPITER_WRAP_MAP_KEY(in_key));
if (result == m_table.end()) { if (result == m_table.end()) {
return in_default_value; return in_default_value;

54
src/include/Jupiter/DataBuffer_Imp.h

@ -25,6 +25,7 @@
* Note: Modification of this file is not supported in any way. * Note: Modification of this file is not supported in any way.
*/ */
#include <cstring>
#include <vector> #include <vector>
#include <array> #include <array>
#include <string> #include <string>
@ -41,9 +42,6 @@ template<typename T> T Jupiter::DataBuffer::interpret_data(uint8_t *&head)
return r; return r;
} }
template<template<typename, typename> class T, typename X, typename Y> static T<X, Y> interpret_data(uint8_t *&head);
template<template<typename, typename, typename> class T, typename X, typename Y, typename Z> static T<X, Y, Z> interpret_data(uint8_t *&head);
// Basic peek // Basic peek
template<typename T> T Jupiter::DataBuffer::peek() const template<typename T> T Jupiter::DataBuffer::peek() const
@ -201,11 +199,6 @@ template<template<typename> class T, typename Y> void Jupiter::DataBuffer::push(
Jupiter::DataBuffer::push<T, Y>(&data); Jupiter::DataBuffer::push<T, Y>(&data);
} }
template<template<typename> class T, typename Y> T<Y> Jupiter::DataBuffer::interpret_data(uint8_t *&head)
{
return _Jupiter_DataBuffer_partial_specialization_impl<T>::template interpret<Y>(head);
}
// PUSH SPECIALIZATION: std::array // PUSH SPECIALIZATION: std::array
template<template<typename, size_t> class T> struct _Jupiter_DataBuffer_partial_specialization_impl_std_array template<template<typename, size_t> class T> struct _Jupiter_DataBuffer_partial_specialization_impl_std_array
@ -288,42 +281,27 @@ template<template<typename, typename> class T, typename X, typename Y> T<X, Y> J
return _Jupiter_DataBuffer_partial_specialization_impl_std_vector<T>::template interpret<X, Y>(head); return _Jupiter_DataBuffer_partial_specialization_impl_std_vector<T>::template interpret<X, Y>(head);
} }
template<template<typename, typename> class T, typename X, typename Y> static T<X, Y> interpret_data(uint8_t *&head)
{
return _Jupiter_DataBuffer_partial_specialization_impl_std_vector<T>::template interpret<X, Y>(head);
}
// SPECIALIZATION: std::string // SPECIALIZATION: std::string
template<template<typename, typename, typename> class T> struct _Jupiter_DataBuffer_partial_specialization_impl_std_string template<template<typename, typename, typename> class T> struct _Jupiter_DataBuffer_partial_specialization_impl_std_string
{ {
}; };
template<> struct _Jupiter_DataBuffer_partial_specialization_impl_std_string<std::basic_string> template<> struct _Jupiter_DataBuffer_partial_specialization_impl_std_string<std::basic_string> {
{ template<typename X, typename Y, typename Z> static void push(Jupiter::DataBuffer *buffer, const std::basic_string<X, Y, Z> *data) {
template<typename X, typename Y, typename Z> static void push(Jupiter::DataBuffer *buffer, const std::basic_string<X, Y, Z> *data) buffer->secure(sizeof(size_t) + data->size() * sizeof(Y));
{ buffer->push<size_t>(data->size());
buffer->push(data->size()); buffer->push(reinterpret_cast<const uint8_t*>(data->data()), data->size() * sizeof(X));
if (std::is_fundamental<typename std::basic_string<X, Y, Z>::value_type>::value)
buffer->push(reinterpret_cast<const uint8_t *>(data->data()), data->size() * sizeof(X));
else
{
auto itr = data->begin();
auto end = data->end();
while (itr != end)
buffer->push<typename std::basic_string<X, Y, Z>::value_type>(*itr++);
}
}; };
template<typename X, typename Y, typename Z> static std::basic_string<X, Y, Z> interpret(uint8_t *&head) template<typename X, typename Y, typename Z> static std::basic_string<X, Y, Z> interpret(uint8_t*& head) {
{ size_t read_length = *reinterpret_cast<size_t *>(head);
size_t size_ = *reinterpret_cast<size_t *>(head);
head += sizeof(size_t); head += sizeof(size_t);
std::basic_string<X, Y, Z> r; std::basic_string<X, Y, Z> result;
r.reserve(size_); result.resize(read_length);
while (size_-- != 0) std::memcpy(result.data(), head, read_length);
r.push_back(Jupiter::DataBuffer::interpret_data<typename std::basic_string<X, Y, Z>::value_type>(head)); head += read_length;
return r; return result;
} }
}; };
@ -342,9 +320,9 @@ template<template<typename, typename, typename> class T, typename X, typename Y,
return _Jupiter_DataBuffer_partial_specialization_impl_std_string<T>::template interpret<X, Y, Z>(head); return _Jupiter_DataBuffer_partial_specialization_impl_std_string<T>::template interpret<X, Y, Z>(head);
} }
template<template<typename, typename, typename> class T, typename X, typename Y, typename Z> static T<X, Y, Z> interpret_data(uint8_t *&head) template<>
{ inline std::string Jupiter::DataBuffer::interpret_data<std::string>(uint8_t *&head) {
return _Jupiter_DataBuffer_partial_specialization_impl_std_string<T>::template interpret<X, Y, Z>(head); return _Jupiter_DataBuffer_partial_specialization_impl_std_string<std::basic_string>::template interpret<char, std::string::traits_type, std::string::allocator_type>(head);
} }
#endif // _DATABUFFER_IMP_H_HEADER #endif // _DATABUFFER_IMP_H_HEADER

6
src/include/Jupiter/Database.h

@ -24,10 +24,14 @@
* @brief Defines a database file structure. * @brief Defines a database file structure.
*/ */
#include "String.hpp" #include <cstdio>
#include <string>
#include <string_view>
#include "Jupiter.h"
namespace Jupiter namespace Jupiter
{ {
class DataBuffer;
/** /**
* @brief Provides an implementation for database files. * @brief Provides an implementation for database files.

1
src/include/Jupiter/File.h

@ -25,7 +25,6 @@
*/ */
#include "Jupiter.h" #include "Jupiter.h"
#include "Readable_String.h"
#include <cstdio> #include <cstdio>
namespace Jupiter namespace Jupiter

3
src/include/Jupiter/GenericCommand.h

@ -26,7 +26,6 @@
#include <memory> #include <memory>
#include "Command.h" #include "Command.h"
#include "String.hpp"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
#if defined _MSC_VER #if defined _MSC_VER
@ -157,7 +156,7 @@ namespace Jupiter
private: private:
bool m_should_update_help = true; bool m_should_update_help = true;
Jupiter::StringS m_help; std::string m_help;
}; };
/** Generic command list */ /** Generic command list */

27
src/include/Jupiter/HTTP.h

@ -24,8 +24,6 @@
* @brief Defines constants related to HTTP * @brief Defines constants related to HTTP
*/ */
#include "Reference_String.h"
namespace Jupiter namespace Jupiter
{ {
namespace HTTP namespace HTTP
@ -137,14 +135,13 @@ namespace Jupiter
* @brief Content-Language values * @brief Content-Language values
* TODO: Implement all ISO 639-1 translations * TODO: Implement all ISO 639-1 translations
*/ */
namespace Language namespace Language {
{ static constexpr std::string_view ENGLISH = "en";
static STRING_LITERAL_AS_NAMED_REFERENCE(ENGLISH, "en"); static constexpr std::string_view FRENCH = "fr";
static STRING_LITERAL_AS_NAMED_REFERENCE(FRENCH, "fr"); static constexpr std::string_view GERMAN = "gr";
static STRING_LITERAL_AS_NAMED_REFERENCE(GERMAN, "gr"); static constexpr std::string_view RUSSIAN = "ru";
static STRING_LITERAL_AS_NAMED_REFERENCE(RUSSIAN, "ru"); static constexpr std::string_view JAPANESE = "ja";
static STRING_LITERAL_AS_NAMED_REFERENCE(JAPANESE, "ja"); static constexpr std::string_view CHINESE = "zh";
static STRING_LITERAL_AS_NAMED_REFERENCE(CHINESE, "zh");
} }
/** /**
@ -157,16 +154,16 @@ namespace Jupiter
{ {
namespace Charset namespace Charset
{ {
static STRING_LITERAL_AS_NAMED_REFERENCE(ASCII, "ascii"); static constexpr std::string_view ASCII = "ascii";
static STRING_LITERAL_AS_NAMED_REFERENCE(UTF8, "utf-8"); static constexpr std::string_view UTF8 = "utf-8";
} }
static STRING_LITERAL_AS_NAMED_REFERENCE(HTML, "text/html"); static constexpr std::string_view HTML = "text/html";
static STRING_LITERAL_AS_NAMED_REFERENCE(PLAIN, "text/plain"); static constexpr std::string_view PLAIN = "text/plain";
} }
namespace Application namespace Application
{ {
static STRING_LITERAL_AS_NAMED_REFERENCE(OCTET_STREAM, "application/octet-stream"); static constexpr std::string_view OCTET_STREAM = "application/octet-stream";
} }
} }
} }

98
src/include/Jupiter/HTTP_QueryString.h

@ -21,7 +21,6 @@
#include <unordered_map> #include <unordered_map>
#include <charconv> #include <charconv>
#include "String.hpp"
/** /**
* @file HTTP_QueryString.h * @file HTTP_QueryString.h
@ -32,22 +31,11 @@ namespace Jupiter
{ {
namespace HTTP namespace HTTP
{ {
/**
* @brief Provides parsing for HTTP Query Strings.
*/
class QueryString : public Jupiter::StringS
{
public:
QueryString() = delete;
inline QueryString(std::string_view query_string) : QueryString(query_string.data(), query_string.size()) {}
inline QueryString(const char *ptr, size_t str_size);
};
/** /**
* @brief Provides parsing for HTML form responses. * @brief Provides parsing for HTML form responses.
* Note: This is essentially the same thing as QueryString, except key/value pairs are pared into 'table'. * Note: This is essentially the same thing as QueryString, except key/value pairs are pared into 'table'.
*/ */
class HTMLFormResponse : public Jupiter::StringS class HTMLFormResponse
{ {
public: public:
HTMLFormResponse() = delete; HTMLFormResponse() = delete;
@ -101,87 +89,23 @@ namespace Jupiter
} }
TableType table; TableType table;
std::string m_parsed;
}; };
} }
} }
/** Implementation */ /** Implementation */
inline Jupiter::HTTP::QueryString::QueryString(const char *ptr, size_t str_size) : Jupiter::StringS(str_size)
{
if (str_size < 3) // not enough room for "%XX", therefore no escaped characters to parse
{
Jupiter::StringType::length = str_size;
switch (str_size)
{
case 2:
str[1] = ptr[1];
case 1:
*str = *ptr;
case 0:
// nothing to copy
return;
}
}
const char *end = ptr + str_size - 2;
char *buf = str;
int val;
while (ptr != end) inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t str_size) {
{ std::string_view in_view{ ptr, str_size };
if (*ptr == '%') if (str_size < 3) { // not enough room for "%XX", therefore no escaped characters to parse
{ m_parsed = in_view;
if ((val = Jupiter_getHex(*++ptr)) != -1) return;
{
*buf = static_cast<uint8_t>(val) << 4;
if ((val = Jupiter_getHex(*++ptr)) != -1)
*buf |= val;
++buf, ++ptr;
if (ptr > end)
{
if (ptr == end + 1) // copy 1 remaining character
{
*buf = *ptr;
++buf;
}
Jupiter::StringType::length = buf - Jupiter::StringType::str;
return;
}
}
}
else // Copy character
{
*buf = *ptr;
++buf, ++ptr;
}
}
// copy last 2 characters
*buf = *ptr;
*++buf = *++ptr;
Jupiter::StringType::length = buf + 1 - str;
}
inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t str_size) : Jupiter::StringS(str_size)
{
if (str_size < 3) // not enough room for "%XX", therefore no escaped characters to parse
{
Jupiter::StringType::length = str_size;
switch (str_size)
{
case 2:
str[1] = ptr[1];
case 1:
*str = *ptr;
case 0:
// nothing to copy
return;
}
} }
m_parsed.resize(in_view.size());
const char *end = ptr + str_size - 2; const char *end = ptr + str_size - 2;
char *buf = str; char* buf = m_parsed.data();
const char *token_start = buf; const char *token_start = buf;
int val; int val;
std::string key; std::string key;
@ -204,7 +128,7 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
*buf = *ptr; *buf = *ptr;
++buf; ++buf;
} }
Jupiter::StringType::length = buf - Jupiter::StringType::str; m_parsed.erase(buf - m_parsed.data());
return; return;
} }
} }
@ -247,7 +171,7 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
if (!key.empty()) // A key was already set; end of value if (!key.empty()) // A key was already set; end of value
Jupiter::HTTP::HTMLFormResponse::table[key] = std::string_view(token_start, buf - token_start + 1); Jupiter::HTTP::HTMLFormResponse::table[key] = std::string_view(token_start, buf - token_start + 1);
Jupiter::StringType::length = buf + 1 - str; m_parsed.erase(buf + 1 - m_parsed.data()); // TODO: double check where this +1 came from? actually just replace this
} }
#endif // _HTTP_QUERYSTRING_H_HEADER #endif // _HTTP_QUERYSTRING_H_HEADER

4
src/include/Jupiter/HTTP_Server.h

@ -27,7 +27,6 @@
#include <memory> #include <memory>
#include "Jupiter.h" #include "Jupiter.h"
#include "Thinker.h" #include "Thinker.h"
#include "Readable_String.h"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
#if defined _MSC_VER #if defined _MSC_VER
@ -46,8 +45,7 @@ namespace Jupiter
public: // Server public: // Server
typedef std::string* HTTPFunction(std::string_view query_string); typedef std::string* HTTPFunction(std::string_view query_string);
static std::string_view global_namespace; static constexpr std::string_view server_string{ "Jupiter" };
static std::string_view server_string;
struct JUPITER_API Content struct JUPITER_API Content
{ {

48
src/include/Jupiter/Hash.h

@ -25,37 +25,63 @@
*/ */
#include <cstdint> #include <cstdint>
#include <string_view>
#include "Jupiter.h" #include "Jupiter.h"
#include "Readable_String.h"
namespace Jupiter namespace Jupiter
{ {
/** Sums */ /** Sums */
template<typename T = char, typename R = uint64_t> inline R calcsum(const T *in_data, size_t in_length); template<typename T = char, typename R = uint64_t> inline R calcsum(const T *in_data, size_t in_length);
template<typename T = char, typename R = uint64_t> inline R calcsum(const Jupiter::Readable_String<T> &str); template<typename T = char, typename R = uint64_t> inline R calcsum(const std::basic_string_view<T> &str);
/** Fowler-Noll-Vo hash algorithms */ /** Fowler-Noll-Vo hash algorithms */
template<typename T> inline uint64_t fnv1(const T &data); template<typename T> inline uint64_t fnv1(const T &data);
template<typename T = char> inline uint64_t fnv1(const T *str, size_t length); template<typename T = char> inline uint64_t fnv1(const T *str, size_t length);
template<typename T = char> inline uint64_t fnv1(const Jupiter::Readable_String<T> &str); template<typename T = char> inline uint64_t fnv1(const std::basic_string_view<T> &str);
template<typename T> inline uint32_t fnv1_32(const T &data); template<typename T> inline uint32_t fnv1_32(const T &data);
template<typename T = char> inline uint32_t fnv1_32(const T *str, size_t length); template<typename T = char> inline uint32_t fnv1_32(const T *str, size_t length);
template<typename T = char> inline uint32_t fnv1_32(const Jupiter::Readable_String<T> &str); template<typename T = char> inline uint32_t fnv1_32(const std::basic_string_view<T> &str);
template<typename T> inline uint64_t fnv1a(const T &data); template<typename T> inline uint64_t fnv1a(const T &data);
template<typename T = char> inline uint64_t fnv1a(const T *str, size_t length); template<typename T = char> inline uint64_t fnv1a(const T *str, size_t length);
template<typename T = char> inline uint64_t fnv1a(const Jupiter::Readable_String<T> &str); template<typename T = char> inline uint64_t fnv1a(const std::basic_string_view<T> &str);
template<typename T> inline uint32_t fnv1a_32(const T &data); template<typename T> inline uint32_t fnv1a_32(const T &data);
template<typename T = char> inline uint32_t fnv1a_32(const T *str, size_t length); template<typename T = char> inline uint32_t fnv1a_32(const T *str, size_t length);
template<typename T = char> inline uint32_t fnv1a_32(const Jupiter::Readable_String<T> &str); template<typename T = char> inline uint32_t fnv1a_32(const std::basic_string_view<T> &str);
JUPITER_API uint64_t fnv1(const uint8_t *data, const uint8_t *end); JUPITER_API uint64_t fnv1(const uint8_t *data, const uint8_t *end);
JUPITER_API uint64_t fnv1a(const uint8_t *data, const uint8_t *end); JUPITER_API uint64_t fnv1a(const uint8_t *data, const uint8_t *end);
JUPITER_API uint32_t fnv1_32(const uint8_t *data, const uint8_t *end); JUPITER_API uint32_t fnv1_32(const uint8_t *data, const uint8_t *end);
JUPITER_API uint32_t fnv1a_32(const uint8_t *data, const uint8_t *end); JUPITER_API uint32_t fnv1a_32(const uint8_t *data, const uint8_t *end);
/** unordered_map helpers */
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);
}
};
#ifdef __cpp_lib_generic_unordered_lookup
using InMapKeyType = std::string_view;
#define JUPITER_WRAP_MAP_KEY(in_key) in_key
#else // We can't use std::string_view for InKeyType until GCC 11 & clang 12, and I still want to support GCC 9
using InMapKeyType = std::string;
#define JUPITER_WRAP_MAP_KEY(in_key) static_cast<Jupiter::InMapKeyType>(in_key)
#endif // __cpp_lib_generic_unordered_lookup
using default_hash_function = str_hash<char>;
} }
/** Calcsum implementation */ /** Calcsum implementation */
@ -75,7 +101,7 @@ template<typename T, typename R> inline R Jupiter::calcsum(const T *in_data, siz
return sum; return sum;
} }
template<typename T, typename R> inline R Jupiter::calcsum(const Jupiter::Readable_String<T> &str) template<typename T, typename R> inline R Jupiter::calcsum(const std::basic_string_view<T> &str)
{ {
return Jupiter::calcsum<T, R>(str.data(), str.size()); return Jupiter::calcsum<T, R>(str.data(), str.size());
} }
@ -91,7 +117,7 @@ template<typename T> inline uint64_t Jupiter::fnv1(const T *data, size_t length)
return Jupiter::fnv1(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length)); return Jupiter::fnv1(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
} }
template<typename T> inline uint64_t Jupiter::fnv1(const Jupiter::Readable_String<T> &data) template<typename T> inline uint64_t Jupiter::fnv1(const std::basic_string_view<T> &data)
{ {
return Jupiter::fnv1(reinterpret_cast<const uint8_t *>(data.data()), reinterpret_cast<const uint8_t *>(data.data() + data.size())); return Jupiter::fnv1(reinterpret_cast<const uint8_t *>(data.data()), reinterpret_cast<const uint8_t *>(data.data() + data.size()));
} }
@ -106,7 +132,7 @@ template<typename T> inline uint32_t Jupiter::fnv1_32(const T *data, size_t leng
return Jupiter::fnv1_32(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length)); return Jupiter::fnv1_32(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
} }
template<typename T> inline uint32_t Jupiter::fnv1_32(const Jupiter::Readable_String<T> &data) template<typename T> inline uint32_t Jupiter::fnv1_32(const std::basic_string_view<T> &data)
{ {
return Jupiter::fnv1_32(reinterpret_cast<const uint8_t *>(data.data()), reinterpret_cast<const uint8_t *>(data.data() + data.size())); return Jupiter::fnv1_32(reinterpret_cast<const uint8_t *>(data.data()), reinterpret_cast<const uint8_t *>(data.data() + data.size()));
} }
@ -121,7 +147,7 @@ template<typename T> inline uint64_t Jupiter::fnv1a(const T *data, size_t length
return Jupiter::fnv1a(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length)); return Jupiter::fnv1a(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
} }
template<typename T> inline uint64_t Jupiter::fnv1a(const Jupiter::Readable_String<T> &data) template<typename T> inline uint64_t Jupiter::fnv1a(const std::basic_string_view<T> &data)
{ {
return Jupiter::fnv1a(data.data(), data.size()); return Jupiter::fnv1a(data.data(), data.size());
} }
@ -136,7 +162,7 @@ template<typename T> inline uint32_t Jupiter::fnv1a_32(const T *data, size_t len
return Jupiter::fnv1a_32(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length)); return Jupiter::fnv1a_32(reinterpret_cast<const uint8_t *>(data), reinterpret_cast<const uint8_t *>(data + length));
} }
template<typename T> inline uint32_t Jupiter::fnv1a_32(const Jupiter::Readable_String<T> &data) template<typename T> inline uint32_t Jupiter::fnv1a_32(const std::basic_string_view<T> &data)
{ {
return Jupiter::fnv1a_32(data.data(), data.size()); return Jupiter::fnv1a_32(data.data(), data.size());
} }

2
src/include/Jupiter/IRC.h

@ -24,8 +24,6 @@
* @brief Defines IRC protocol constants. * @brief Defines IRC protocol constants.
*/ */
#include "Jupiter.h"
/** Special Character Definitions */ /** Special Character Definitions */
#define IRCCTCP "\001" /** IRC CTCP character contained in a string literal */ #define IRCCTCP "\001" /** IRC CTCP character contained in a string literal */

29
src/include/Jupiter/IRC_Client.h

@ -30,7 +30,6 @@
#include "Jupiter.h" #include "Jupiter.h"
#include "Thinker.h" #include "Thinker.h"
#include "IRC.h" #include "IRC.h"
#include "Reference_String.h"
#include "Config.h" #include "Config.h"
#include "Socket.h" #include "Socket.h"
@ -218,21 +217,21 @@ namespace Jupiter
* *
* @return String containing the user's nickname. * @return String containing the user's nickname.
*/ */
std::string_view getNickname() const; const std::string& getNickname() const;
/** /**
* @brief Fetches the user's username. * @brief Fetches the user's username.
* *
* @return String containing the user's username. * @return String containing the user's username.
*/ */
std::string_view getUsername() const; const std::string& getUsername() const;
/** /**
* @brief Fetches the user's hostname. * @brief Fetches the user's hostname.
* *
* @return String containing the user's hostname. * @return String containing the user's hostname.
*/ */
std::string_view getHostname() const; const std::string& getHostname() const;
/** /**
* @brief Returns the number of channels the user shares with the local client. * @brief Returns the number of channels the user shares with the local client.
@ -245,8 +244,8 @@ namespace Jupiter
private: private:
unsigned int m_channel_count = 0; unsigned int m_channel_count = 0;
std::string m_nickname; std::string m_nickname;
Jupiter::StringS m_username; std::string m_username;
Jupiter::StringS m_hostname; std::string m_hostname;
}; };
/** /**
@ -277,28 +276,28 @@ namespace Jupiter
* *
* @return String containing the user's channel prefixes. * @return String containing the user's channel prefixes.
*/ */
std::string_view getPrefixes() const; const std::string& getPrefixes() const;
/** /**
* @brief Fetches the user's nickname. * @brief Fetches the user's nickname.
* *
* @return String containing the user's nickname. * @return String containing the user's nickname.
*/ */
std::string_view getNickname() const; const std::string& getNickname() const;
/** /**
* @brief Fetches the user's username. * @brief Fetches the user's username.
* *
* @return String containing the user's username. * @return String containing the user's username.
*/ */
std::string_view getUsername() const; const std::string& getUsername() const;
/** /**
* @brief Fetches the user's hostname. * @brief Fetches the user's hostname.
* *
* @return String containing the user's hostname. * @return String containing the user's hostname.
*/ */
std::string_view getHostname() const; const std::string& getHostname() const;
/** /**
* @brief Returns the number of channels the user shares with the local client. * @brief Returns the number of channels the user shares with the local client.
@ -315,7 +314,7 @@ namespace Jupiter
std::string m_prefixes; std::string m_prefixes;
}; };
using UserTableType = std::unordered_map<Jupiter::StringS, std::shared_ptr<Channel::User>, default_hash_function>; using UserTableType = std::unordered_map<std::string, std::shared_ptr<Channel::User>, default_hash_function, std::equal_to<>>;
/** /**
* @brief Returns the name of the channel. * @brief Returns the name of the channel.
@ -421,7 +420,7 @@ namespace Jupiter
/** Private members */ /** Private members */
private: private:
Jupiter::StringS m_name; std::string m_name;
Client *m_parent; Client *m_parent;
int m_type; int m_type;
UserTableType m_users; UserTableType m_users;
@ -429,8 +428,8 @@ namespace Jupiter
bool m_adding_names; bool m_adding_names;
}; // Jupiter::IRC::Client::Channel class }; // Jupiter::IRC::Client::Channel class
using ChannelTableType = std::unordered_map<Jupiter::StringS, Client::Channel, default_hash_function>; using ChannelTableType = std::unordered_map<std::string, Client::Channel, default_hash_function, std::equal_to<>>;
using UserTableType = std::unordered_map<Jupiter::StringS, std::shared_ptr<Client::User>, default_hash_function>; using UserTableType = std::unordered_map<std::string, std::shared_ptr<Client::User>, default_hash_function, std::equal_to<>>;
/** /**
* @brief Returns the name of the primary config section this client reads from. * @brief Returns the name of the primary config section this client reads from.
@ -840,7 +839,7 @@ namespace Jupiter
std::string m_sasl_password; std::string m_sasl_password;
int m_connection_status; int m_connection_status;
Jupiter::StringS m_primary_section_name; std::string m_primary_section_name;
Jupiter::Config *m_primary_section; Jupiter::Config *m_primary_section;
Jupiter::Config *m_secondary_section; Jupiter::Config *m_secondary_section;
std::string m_log_file_name; std::string m_log_file_name;

61
src/include/Jupiter/InvalidIndex.h

@ -1,61 +0,0 @@
/**
* Copyright (C) 2014-2015 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _INVALIDINDEX_H_HEADER
#define _INVALIDINDEX_H_HEADER
/**
* @file InvalidIndex.h
* @brief Defines some constants for invalid indexes for unsigned types.
*/
#if defined __cplusplus
#include <cstdint>
#include <climits>
namespace Jupiter
{
static const size_t INVALID_INDEX = SIZE_MAX;
static const uint32_t INVALID_INDEX32 = UINT32_MAX;
static const uint64_t INVALID_INDEX64 = UINT64_MAX;
static const unsigned int ERROR_INDICATOR = UINT_MAX;
static const uint32_t ERROR_INDICATOR32 = INVALID_INDEX32;
static const uint64_t ERROR_INDICATOR64 = INVALID_INDEX32;
}
extern "C"
{
#else
#include <stdint.h>
#include <limits.h>
#endif // __cplusplus
static const size_t JUPITER_INVALID_INDEX = SIZE_MAX;
static const uint32_t JUPITER_INVALID_INDEX32 = UINT32_MAX;
static const uint64_t JUPITER_INVALID_INDEX64 = UINT64_MAX;
static const unsigned int JUPITER_ERROR_INDICATOR = UINT_MAX;
static const uint32_t JUPITER_ERROR_INDICATOR32 = JUPITER_INVALID_INDEX32;
static const uint64_t JUPITER_ERROR_INDICATOR64 = JUPITER_INVALID_INDEX32;
#if defined __cplusplus
}
#endif // __cplusplus
#endif // _INVALIDINDEX_H_HEADER

2
src/include/Jupiter/Jupiter.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2013-2016 Jessica James. * Copyright (C) 2013-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above

6
src/include/Jupiter/Plugin.h

@ -24,10 +24,10 @@
* @brief Provides a hot-swapable plugin system. * @brief Provides a hot-swapable plugin system.
*/ */
#include <vector>
#include "Thinker.h" #include "Thinker.h"
#include "Rehash.h" #include "Rehash.h"
#include "INIConfig.h" #include "INIConfig.h"
#include "String.hpp"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
#if defined _MSC_VER #if defined _MSC_VER
@ -88,7 +88,7 @@ namespace Jupiter
* *
* @return String containing the name of the plugin. * @return String containing the name of the plugin.
*/ */
std::string_view getName() const; const std::string& getName() const;
/** /**
* @brief Returns the plugin's configuration file. * @brief Returns the plugin's configuration file.
@ -353,7 +353,7 @@ namespace Jupiter
protected: protected:
bool _shouldRemove = false; bool _shouldRemove = false;
Jupiter::StringS name; std::string name;
Jupiter::INIConfig config; Jupiter::INIConfig config;
}; };

41
src/include/Jupiter/Readable_String.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2017 Jessica James. * Copyright (C) 2014-2021 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -21,27 +21,17 @@
/** /**
* @file Readable_String.h * @file Readable_String.h
* @brief Defines several basic accessive and comparative virtual functions for strings. * @brief Defines various legacy string utilities which should be removed
*/ */
#include <cwchar> // wchar_t
#include <cwctype> // towupper
#include <cstdio> // FILE
#include <string> // std::basic_string<T> type #include <string> // std::basic_string<T> type
#include <iostream> // std::endl #include <string_view> // std::basic_string_view<T> type
#include <cstdarg> #include <cstdarg> // arg helpers needed by string_printf
#include "InvalidIndex.h" #include "Functions.h" // string -> bool/number converters
#include "DataBuffer.h"
#include "Functions.h"
namespace Jupiter { namespace Jupiter {
/** DEPRECATED: Generic Readable String Type */
template<typename CharT>
using Readable_String = std::basic_string_view<CharT>;
using ReadableString = std::string_view;
// these methods will be written in a similar fashion in jessilib, to retain behavior / ease of use // these methods will be written in a similar fashion in jessilib, to retain behavior / ease of use
template<typename CharT> template<typename CharT> /** DEPRECATED */
bool asBool(std::basic_string_view<CharT> in_string) { bool asBool(std::basic_string_view<CharT> in_string) {
using namespace std::literals; using namespace std::literals;
@ -59,31 +49,32 @@ namespace Jupiter {
return true; return true;
} }
template<typename CharT> template<typename CharT> /** DEPRECATED */
int asInt(std::basic_string_view<CharT> in_string, int base = 0) { int asInt(std::basic_string_view<CharT> in_string, int base = 0) {
return Jupiter_strtoi_s(in_string.data(), in_string.size(), base); return Jupiter_strtoi_s(in_string.data(), in_string.size(), base);
} }
template<typename CharT> template<typename CharT> /** DEPRECATED */
long long asLongLong(std::basic_string_view<CharT> in_string, int base = 0) { long long asLongLong(std::basic_string_view<CharT> in_string, int base = 0) {
return Jupiter_strtoll_s(in_string.data(), in_string.size(), base); return Jupiter_strtoll_s(in_string.data(), in_string.size(), base);
} }
template<typename CharT> template<typename CharT> /** DEPRECATED */
unsigned int asUnsignedInt(std::basic_string_view<CharT> in_string, int base = 0) { unsigned int asUnsignedInt(std::basic_string_view<CharT> in_string, int base = 0) {
return Jupiter_strtoui_s(in_string.data(), in_string.size(), base); return Jupiter_strtoui_s(in_string.data(), in_string.size(), base);
} }
template<typename CharT> template<typename CharT> /** DEPRECATED */
unsigned long long asUnsignedLongLong(std::basic_string_view<CharT> in_string, int base = 0) { unsigned long long asUnsignedLongLong(std::basic_string_view<CharT> in_string, int base = 0) {
return Jupiter_strtoull_s(in_string.data(), in_string.size(), base); return Jupiter_strtoull_s(in_string.data(), in_string.size(), base);
} }
template<typename CharT> template<typename CharT> /** DEPRECATED */
double asDouble(std::basic_string_view<CharT> in_string) { double asDouble(std::basic_string_view<CharT> in_string) {
return Jupiter_strtod_s(in_string.data(), in_string.size()); return Jupiter_strtod_s(in_string.data(), in_string.size());
} }
/** DEPRECATED (similar function w/ identical semantics to be implemented) */
template<typename OutT> template<typename OutT>
OutT from_string(std::string_view in_string) { OutT from_string(std::string_view in_string) {
return static_cast<OutT>(in_string); return static_cast<OutT>(in_string);
@ -158,8 +149,10 @@ namespace Jupiter {
inline long double from_string<long double>(std::string_view in_string) { inline long double from_string<long double>(std::string_view in_string) {
return asDouble(in_string); return asDouble(in_string);
} }
}
} // namespace Jupiter
/** DEPRECATED */
inline std::string vstring_printf(const char* format, va_list args) { inline std::string vstring_printf(const char* format, va_list args) {
std::string result; std::string result;
@ -177,13 +170,15 @@ inline std::string vstring_printf(const char* format, va_list args) {
} }
if (result.size() != min_length) { if (result.size() != min_length) {
throw std::runtime_error("result.size() != min_length"); // This should never happen; if it does, it's probably indicative of a race condition
result.erase(min_length);
} }
} }
return result; return result;
} }
/** DEPRECATED */
inline std::string string_printf(const char* format, ...) { inline std::string string_printf(const char* format, ...) {
va_list args; va_list args;
va_start(args, format); va_start(args, format);

45
src/include/Jupiter/Reference_String.h

@ -1,45 +0,0 @@
/**
* Copyright (C) 2014-2017 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _REFERENCE_STRING_H_HEADER
#define _REFERENCE_STRING_H_HEADER
/**
* @file Reference_String.h
* @brief Provides the basis for String types, of any implementation.
* Note: DEPRECATED
*/
#include <string_view>
#include "Readable_String.h"
namespace Jupiter {
/** DEPRECATED: Generic Reference String Type */
using ReferenceString = std::string_view;
namespace literals {
/** DEPRECATED: Reference_String literals */
inline constexpr std::string_view operator"" _jrs(const char *str, size_t len) { return { str, len }; }
}
}
/** DEPRECATED */
#define STRING_LITERAL_AS_REFERENCE(str) Jupiter::literals::operator"" _jrs(str, sizeof(str) - 1)
#define STRING_LITERAL_AS_NAMED_REFERENCE(name, str) Jupiter::ReferenceString name = STRING_LITERAL_AS_REFERENCE(str)
#endif // _REFERENCE_STRING_H_HEADER

114
src/include/Jupiter/Shift_String.h

@ -1,114 +0,0 @@
/**
* Copyright (C) 2014-2015 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _SHIFT_STRING_H_HEADER
#define _SHIFT_STRING_H_HEADER
/**
* @file Shift_String.h
* @brief Allows for separation of a string's representation from its memory base.
*/
#include "String_Type.h"
/** Disable warning 4458 */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4458) // declaration of 'length' hides class member
#endif
namespace Jupiter
{
/**
* @brief Provides the basis for String classes by providing implementations for operators, comparative operations, and defining abstract functions.
* Note: This is an abstract type.
*
* @param T Element type which the String will store. Defaults to char.
*/
template<typename T = char> class Shift_String_Type : public Jupiter::String_Type<T>
{
public:
/**
* @brief Removes the first instance of an element from the string.
*
* @param value Value of the element to remove.
* @return True if an element was removed, false otherwise.
*/
virtual bool remove(const T &value) override;
/**
* @brief Removes a number of elements starting at an index.
*
* @param index Index to start removing elements at.
* @param length Number of elements to remove.
*/
virtual void remove(size_t index, size_t length) override;
/**
* @brief Removes all elements from the string.
*/
void clear() override;
/**
* @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.
*
* @param len Minimum number of elements the string buffer must be able to hold.
* @return True if a new buffer was allocated, false otherwise.
*/
virtual bool setBufferSize(size_t len) override;
/**
* @brief Empties the string, and sets the internal buffer to be at least large enough to old a specified number of elements.
* Note: This still empties the string if len is less than the string's current length.
*
* @param len Minimum number of elements the string buffer must be able to hold.
* @return True if a new buffer was allocated, false otherwise.
*/
virtual bool setBufferSizeNoCopy(size_t len) override;
/**
* @brief Default constructor for the Shift_String_Type class.
*/
Shift_String_Type() {}
/**
* @brief Move constructor for the Shift_String_Type class.
*/
Shift_String_Type(Jupiter::Shift_String_Type<T> &&source);
/**
* @brief Destructor for the Shift_String_Type class.
*/
virtual ~Shift_String_Type();
protected:
T *base{ nullptr }; /** Base pointer for the underlying String's memory allocation */
};
}
/** Re-enable warning */
#if defined _MSC_VER
#pragma warning(pop)
#endif
#include "Shift_String_Imp.h"
#endif // _SHIFT_STRING_H_HEADER

102
src/include/Jupiter/Shift_String_Imp.h

@ -1,102 +0,0 @@
/**
* Copyright (C) 2014-2015 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _SHIFT_STRING_IMP_H_HEADER
#define _SHIFT_STRING_IMP_H_HEADER
/**
* @file Shift_String_Imp.h
* @brief Provides the implementations for Shift_String_Type functions.
* Note: Modification of this file is not supported in any way.
*/
template<typename T> Jupiter::Shift_String_Type<T>::Shift_String_Type(Jupiter::Shift_String_Type<T> &&source) : Jupiter::String_Type<T>(std::move(source))
{
Jupiter::Shift_String_Type<T>::base = source.base;
source.base = nullptr;
}
template<typename T> Jupiter::Shift_String_Type<T>::~Shift_String_Type()
{
if (Jupiter::Shift_String_Type<T>::base != nullptr) delete[] Jupiter::Shift_String_Type<T>::base;
}
template<typename T> bool Jupiter::Shift_String_Type<T>::remove(const T &value)
{
if (Jupiter::String_Type<T>::length == 0) return false;
if (*Jupiter::String_Type<T>::str == value)
{
if (Jupiter::String_Type<T>::length == 1) this->truncate(1);
else {
++Jupiter::String_Type<T>::str;
--Jupiter::String_Type<T>::length;
}
return true;
}
return Jupiter::String_Type<T>::remove(value);
}
template<typename T> void Jupiter::Shift_String_Type<T>::remove(size_t index, size_t len)
{
Jupiter::String_Type<T>::remove(index, len);
}
template<typename T> void Jupiter::Shift_String_Type<T>::clear()
{
Jupiter::String_Type<T>::clear();
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
}
template<typename T> bool Jupiter::Shift_String_Type<T>::setBufferSize(size_t len)
{
if (len > Jupiter::String_Type<T>::length)
{
T *ptr = new T[len];
for (unsigned int i = 0; i < Jupiter::String_Type<T>::length; i++) ptr[i] = Jupiter::String_Type<T>::str[i];
delete[] Jupiter::Shift_String_Type<T>::base;
Jupiter::Shift_String_Type<T>::base = ptr;
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
return true;
}
return false;
}
template<typename T> bool Jupiter::Shift_String_Type<T>::setBufferSizeNoCopy(size_t len)
{
if (len > Jupiter::String_Type<T>::length)
{
Jupiter::String_Type<T>::length = 0;
delete[] Jupiter::Shift_String_Type<T>::base;
Jupiter::Shift_String_Type<T>::base = new T[len];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
return true;
}
Jupiter::String_Type<T>::length = 0;
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
return false;
}
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Shift_String_Type> {
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::Shift_String_Type<Y> *data) {
_Jupiter_DataBuffer_partial_specialization_impl<Jupiter::String_Type>::push<Y>(buffer, data);
};
};
#endif // _SHIFT_STRING_IMP_H_HEADER

10
src/include/Jupiter/Socket.h

@ -25,9 +25,9 @@
*/ */
#include <cstring> #include <cstring>
#include <string>
#include <string_view>
#include "Jupiter.h" #include "Jupiter.h"
#include "Readable_String.h"
#include "String.hpp"
struct addrinfo; struct addrinfo;
@ -170,7 +170,7 @@ namespace Jupiter
* @param ip IP to format * @param ip IP to format
* @return String containing the address's string presentation. * @return String containing the address's string presentation.
*/ */
static Jupiter::StringS ntop4(uint32_t ip); static std::string ntop4(uint32_t ip);
/** /**
* @brief Formats an IPv6 address in its string presentation format. * @brief Formats an IPv6 address in its string presentation format.
@ -178,7 +178,7 @@ namespace Jupiter
* @param ip IP to format * @param ip IP to format
* @return String containing the address's string presentation. * @return String containing the address's string presentation.
*/ */
static Jupiter::StringS ntop6(in_addr6 ip); static std::string ntop6(in_addr6 ip);
/** /**
* @brief Formats an IPvX address in its string presentation format. * @brief Formats an IPvX address in its string presentation format.
@ -188,7 +188,7 @@ namespace Jupiter
* @param size Size of the input type * @param size Size of the input type
* @return String containing the address's string presentation. * @return String containing the address's string presentation.
*/ */
static Jupiter::StringS ntop(void *ip, size_t size); static std::string ntop(void *ip, size_t size);
/** /**
* @brief Interface to provide simple connection establishing. * @brief Interface to provide simple connection establishing.

185
src/include/Jupiter/String.hpp

@ -1,185 +0,0 @@
/**
* Copyright (C) 2013-2017 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _STRING_H_HEADER
#define _STRING_H_HEADER
/**
* @file String.h
* @brief Defines the base String_Base, as well as a series of String types.
* Note: Functions which take "case" or "wildcards" into consideration will only function
* for types char and wchar_t; inputs with other types will simply return false.
*/
#include "Shift_String.h"
#include "Hash.h"
/** Disable warning 4458 */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4458) // declaration of 'length' hides class member
#endif
namespace Jupiter
{
/**
* @brief Provides a minimal String implementation (i.e: no extra variables).
*
* @param T Element type which the String will store. Defaults to char.
*/
template<typename T = char> class String_Strict : public Shift_String_Type<T>
{
public:
/**
* @brief Creates a partial copy of the string.
*
* @param pos Position in the string to start copying from.
* @return String containing a partial copy of the original string.
*/
typename Jupiter::template String_Strict<T> substring(size_t pos) const;
/**
* @brief Creates a partial copy of the string.
*
* @param pos Position in the string to start copying from.
* @param length Number of characters to copy.
* @return String containing a partial copy of the original string.
*/
typename Jupiter::template String_Strict<T> substring(size_t pos, size_t length) const;
/**
* @brief Creates a partial copy of the string.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @return String containing a partial copy of the original string.
*/
static typename Jupiter::template String_Strict<T> substring(const Jupiter::Readable_String<T> &in, size_t pos);
static typename Jupiter::template String_Strict<T> substring(const T *in, size_t pos);
/**
* @brief Creates a partial copy of the string.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @param length Number of characters to copy.
* @return String containing a partial copy of the original string.
*/
static typename Jupiter::template String_Strict<T> substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t length);
static typename Jupiter::template String_Strict<T> substring(const T *in, size_t pos, size_t length);
/** Default Constructor */
String_Strict();
/**
* @brief Size hint constructor.
* Note: For the String_Strict base class, this is only truly useful internally.
*
* @param size Minimum number of elements the string must be able to hold.
*/
String_Strict(size_t size);
/** Move Constructor */
String_Strict(String_Strict<T> &&source);
/** Copy Constructors */
String_Strict(const String_Strict<T> &in);
String_Strict(const Readable_String<T> &in);
String_Strict(const std::basic_string<T> &in);
String_Strict(const T *in, size_t len);
String_Strict(const T *in);
String_Strict(const Jupiter::DataBuffer &in);
/** Concatenation Constructors */
String_Strict(const Readable_String<T> &lhs, const T &rhs);
String_Strict(const Readable_String<T> &lhs, const Readable_String<T> &rhs);
String_Strict(const Readable_String<T> &lhs, const std::basic_string<T> &rhs);
String_Strict(const Readable_String<T> &lhs, const T *rhs);
String_Strict(const Readable_String<T> &lhs, const T *rhs, size_t rhs_size);
/** Addition Operators */
inline String_Strict<T> operator+(const T &rhs) const;
inline String_Strict<T> operator+(const String_Strict<T> &rhs) const;
inline String_Strict<T> operator+(const Readable_String<T> &rhs) const;
inline String_Strict<T> operator+(const std::basic_string<T> &rhs) const;
inline String_Strict<T> operator+(const T *rhs) const;
/** Assignment Operators */
inline String_Strict<T> &operator=(const String_Strict<T> &right) { this->set(right); return *this; };
inline String_Strict<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; };
inline String_Strict<T> &operator=(const std::basic_string<T> &right) { this->set(right); return *this; };
inline String_Strict<T> &operator=(const T *right) { this->set(right); return *this; };
inline String_Strict<T> &operator=(const T right) { this->set(right); return *this; };
};
/** String_Strict<T> Addition Operators */
template<typename T> static inline Jupiter::String_Strict<T> operator+(const Jupiter::String_Type<T> &lhs, const Jupiter::String_Type<T> &rhs);
template<typename T> static inline Jupiter::String_Strict<T> operator+(const Jupiter::String_Type<T> &lhs, const T &rhs);
template<typename T> static inline Jupiter::String_Strict<T> operator+(const Jupiter::String_Type<T> &lhs, const Jupiter::String_Type<T> &rhs);
template<typename T> static inline Jupiter::String_Strict<T> operator+(const Jupiter::String_Type<T> &lhs, const std::basic_string<T> &rhs);
template<typename T> static inline Jupiter::String_Strict<T> operator+(const Jupiter::String_Type<T> &lhs, const std::basic_string_view<T> &rhs);
template<typename T> static inline Jupiter::String_Strict<T> operator+(const Jupiter::String_Type<T> &lhs, const T *rhs);
/** Definition of a Strict String. */
typedef String_Strict<char> StringS;
/** Definition of a Loose String. */
typedef String_Strict<char> StringL;
/** Definition of a String. */
typedef StringS String;
namespace literals {
/** String_Strict literals */
inline Jupiter::StringS operator""_jss(const char *str, size_t len) { return Jupiter::StringS(str, len); }
}
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);
}
// DEPRECATED:
auto operator()(const String_Type<CharT>& in_key) const noexcept {
return operator()(static_cast<std::basic_string_view<CharT>>(in_key));
}
};
using default_hash_function = str_hash<char>;
}
/** Re-enable warning */
#if defined _MSC_VER
#pragma warning(pop)
#endif
/** Implementation for String_Strict and String_Loose. Very scary. */
#include "String_Imp.h"
#endif // _STRING_H_HEADER

250
src/include/Jupiter/String_Imp.h

@ -1,250 +0,0 @@
/**
* Copyright (C) 2013-2017 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _STRING_IMP_H_HEADER
#define _STRING_IMP_H_HEADER
/**
* @file String_Imp.h
* @brief Provides the implementations for String_Strict and String_Loose.
*/
#include "String.hpp"
/**
* IMPLEMENTATION:
* String_Strict
*/
template<typename T> Jupiter::String_Strict<T>::String_Strict()
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(size_t len)
{
Jupiter::Shift_String_Type<T>::base = new T[len];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
Jupiter::String_Type<T>::length = 0;
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(Jupiter::String_Strict<T> &&source) : Jupiter::Shift_String_Type<T>(std::move(source))
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::String_Strict<T> &in) : Jupiter::String_Strict<T>::String_Strict(
in.data(), in.size())
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::Readable_String<T> &in) : Jupiter::String_Strict<T>::String_Strict(
in.data(), in.size())
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const std::basic_string<T> &in) : Jupiter::String_Strict<T>::String_Strict(in.data(), in.size())
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const T *in, size_t len) : Jupiter::String_Strict<T>::String_Strict(len)
{
while (Jupiter::String_Type<T>::length != len)
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = *in;
Jupiter::String_Type<T>::length++;
in++;
}
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const T *in)
{
if (in == nullptr) Jupiter::String_Type<T>::length = 0;
else Jupiter::String_Type<T>::length = Jupiter::strlen<T>(in);
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::String_Type<T>::length];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
for (size_t index = 0; index != Jupiter::String_Type<T>::length; index++, in++) Jupiter::String_Type<T>::str[index] = *in;
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::DataBuffer &in) : String_Strict(reinterpret_cast<T *>(in.getHead()), in.size() / sizeof(T))
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::Readable_String<T> &lhs, const T &rhs) : String_Strict<T>(lhs.size() + 1)
{
const T *itr;
const T *end;
if (!lhs.empty())
{
itr = lhs.data();
end = itr + lhs.size();
*Jupiter::String_Type<T>::str = *itr;
while (++itr != end)
*++Jupiter::String_Type<T>::str = *itr;
++Jupiter::String_Type<T>::str;
}
*Jupiter::String_Type<T>::str = rhs;
Jupiter::String_Type<T>::length = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base + 1;
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) : String_Strict<T>(lhs,
rhs.data(), rhs.size())
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) : String_Strict<T>(lhs, rhs.data(), rhs.size())
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::Readable_String<T> &lhs, const T *rhs) : String_Strict<T>(lhs, rhs, Jupiter::strlen<T>(rhs))
{
}
template<typename T> Jupiter::String_Strict<T>::String_Strict(const Jupiter::Readable_String<T> &lhs, const T *rhs, size_t rhs_size) : String_Strict<T>(lhs.size() + rhs_size)
{
const T *itr;
const T *end;
if (!lhs.empty())
{
itr = lhs.data();
end = itr + lhs.size();
*Jupiter::String_Type<T>::str = *itr;
while (++itr != end)
*++Jupiter::String_Type<T>::str = *itr;
++Jupiter::String_Type<T>::str;
}
if (rhs_size != 0)
{
itr = rhs;
end = itr + rhs_size;
*Jupiter::String_Type<T>::str = *itr;
while (++itr != end)
*++Jupiter::String_Type<T>::str = *itr;
++Jupiter::String_Type<T>::str;
}
Jupiter::String_Type<T>::length = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base;
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
}
template<typename T> typename Jupiter::String_Strict<T> Jupiter::String_Strict<T>::substring(size_t pos) const
{
return Jupiter::String_Strict<T>::substring(*this, pos);
}
template<typename T> typename Jupiter::String_Strict<T> Jupiter::String_Strict<T>::substring(size_t pos, size_t len) const
{
return Jupiter::String_Strict<T>::substring(*this, pos, len);
}
template<typename T> typename Jupiter::String_Strict<T> Jupiter::String_Strict<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos)
{
return Jupiter::String_Type<T>::template substring<Jupiter::template String_Strict>(in, pos);
}
template<typename T> typename Jupiter::String_Strict<T> Jupiter::String_Strict<T>::substring(const T *in, size_t pos)
{
return Jupiter::String_Type<T>::template substring<Jupiter::template String_Strict>(in, pos);
}
template<typename T> typename Jupiter::String_Strict<T> Jupiter::String_Strict<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len)
{
return Jupiter::String_Type<T>::template substring<Jupiter::template String_Strict>(in, pos, len);
}
template<typename T> typename Jupiter::String_Strict<T> Jupiter::String_Strict<T>::substring(const T *in, size_t pos, size_t len)
{
return Jupiter::String_Type<T>::template substring<Jupiter::template String_Strict>(in, pos, len);
}
// Operators
template<typename T> inline Jupiter::String_Strict<T> Jupiter::String_Strict<T>::operator+(const T &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::String_Strict<T> Jupiter::String_Strict<T>::operator+(const Jupiter::String_Strict<T> &rhs) const
{
return Jupiter::String_Strict<T>::operator+(reinterpret_cast<const Jupiter::Readable_String<T> &>(rhs));
}
template<typename T> inline Jupiter::String_Strict<T> Jupiter::String_Strict<T>::operator+(const Jupiter::Readable_String<T> &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::String_Strict<T> Jupiter::String_Strict<T>::operator+(const std::basic_string<T> &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::String_Strict<T> Jupiter::String_Strict<T>::operator+(const T *rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> static inline Jupiter::String_Strict<T> Jupiter::operator+(const Jupiter::String_Type<T> &lhs, const T &rhs)
{
return Jupiter::String_Strict<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::String_Strict<T> Jupiter::operator+(const Jupiter::String_Type<T> &lhs, const Jupiter::String_Type<T> &rhs)
{
return Jupiter::String_Strict<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::String_Strict<T> Jupiter::operator+(const Jupiter::String_Type<T> &lhs, const std::basic_string<T> &rhs)
{
return Jupiter::String_Strict<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::String_Strict<T> Jupiter::operator+(const Jupiter::String_Type<T> &lhs, const std::basic_string_view<T> &rhs)
{
return Jupiter::String_Strict<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::String_Strict<T> Jupiter::operator+(const Jupiter::String_Type<T> &lhs, const T *rhs)
{
return Jupiter::String_Strict<T>(lhs, rhs);
}
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::String_Strict>
{
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::String_Strict<Y> *data) {
_Jupiter_DataBuffer_partial_specialization_impl<Jupiter::String_Type>::push<Y>(buffer, data);
};
template<typename Y> static Jupiter::String_Strict<Y> interpret(uint8_t *&head)
{
size_t size_ = *reinterpret_cast<size_t *>(head);
head += sizeof(size_t);
Jupiter::String_Strict<Y> r = Jupiter::String_Strict<Y>(reinterpret_cast<Y *>(head), size_);
head += size_;
return r;
}
};
#endif // _STRING_IMP_H_HEADER

326
src/include/Jupiter/String_Type.h

@ -1,326 +0,0 @@
/**
* Copyright (C) 2013-2015 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _STRING_TYPE_H_HEADER
#define _STRING_TYPE_H_HEADER
/**
* @file String_Type.h
* @brief Provides the basis for String types, of any implementation.
* Note: Some methods are commented out. This means that they should be implemented, but could not be put declared in this template (return of abstract type).
*/
#include <cstdarg> // va_list
#include "Readable_String.h"
/** Disable warning 4458 */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4458) // declaration of 'length' hides class member
#endif
namespace Jupiter
{
/**
* @brief Provides the basis for String classes by providing implementations for operators, comparative operations, and defining abstract functions.
* Note: This is an abstract type.
*
* @param T Element type which the String will store. Defaults to char.
*/
template<typename T = char> class String_Type
{
public:
/**
* @brief Returns the number of elements in the String.
*
* @return Number of elements in the string.
*/
size_t size() const;
/**
* @brief Returns the maximum number of elements the String can contain,
* without expanding the socket buffer. This is generally the size of the
* underlying memory buffer.
*
* @return Number of elements the string can contain without reallocation.
*/
virtual size_t capacity() const;
/**
* @brief Returns a pointer to the underlying string of elements.
*
* @return Pointer to the underlying string of elements.
*/
const T *data() const;
/**
* @brief Truncates the string by a specified number of elements.
*
* @param n Number of elements to remove from the tail.
* @return New size of the String.
*/
virtual size_t truncate(size_t n);
/**
* @brief Removes the first instance of an element from the string.
*
* @param value Value of the element to remove.
* @return True if an element was removed, false otherwise.
*/
virtual bool remove(const T &value);
/**
* @brief Removes a number of elements starting at an index.
*
* @param index Index to start removing elements at.
* @param length Number of elements to remove.
*/
virtual void remove(size_t index, size_t length);
/**
* @brief Removes all elements from the string.
*/
virtual void clear();
/**
* @brief Sets the value of an element at the specified index.
* Note: If the index is not in the string, it will be added.
*
* @param index Index of element to replace.
* @param in Value to set element to.
* @return New size of the String.
*/
virtual size_t set(size_t index, const T &in);
virtual size_t set(size_t index, const T *in, size_t inSize);
virtual size_t set(size_t index, const Jupiter::Readable_String<T> &in);
virtual size_t set(size_t index, const std::basic_string<T> &in);
virtual size_t set(size_t index, const T *in);
/**
* @brief Copies the data from the input string to the String.
*
* @param in String containing the data to be copied.
* @return New size of the String.
*/
virtual size_t set(const T *in, size_t inSize);
virtual size_t set(const Jupiter::Readable_String<T> &in);
virtual size_t set(const std::basic_string<T> &in);
virtual size_t set(const T *in);
virtual size_t set(const T &in);
/**
* @brief Inserts data into a position in the string.
*
* @param index Index to insert data to.
* @param value Value to insert.
*/
virtual size_t insert(size_t index, const T &value);
virtual size_t insert(size_t index, const Jupiter::Readable_String<T> &value);
/**
* @brief Replaces data at an index with a specified value.
*
* @param index Index to start replacing at.
* @param length Number of elements to replace.
* @param value Value to write over the elements.
* @return New size of the string.
*/
virtual size_t replace(size_t index, size_t length, const T &value);
virtual size_t replace(size_t index, size_t length, const T *value, size_t valueSize);
virtual size_t replace(size_t index, size_t length, std::basic_string_view<T> value);
/**
* @brief Replaces all instances of one value with another value.
*
* @param target Target to search for and replace.
* @param value Value to replace the target with.
* @return New size of the string.
*/
virtual size_t replace(const T &target, const T &value);
virtual size_t replace(const T *target, size_t targetSize, const T &value);
virtual size_t replace(const Jupiter::Readable_String<T> &target, const T &value);
virtual size_t replace(const T *target, size_t targetSize, const T *value, size_t valueSize);
virtual size_t replace(const T *target, size_t targetSize, const Jupiter::Readable_String<T> &value);
virtual size_t replace(const Jupiter::Readable_String<T> &target, const T *value, size_t valueSize);
virtual size_t replace(std::basic_string_view<T> target, std::basic_string_view<T> value);
/**
* @brief Copies the data from the input string and concatenates it to the end of String.
*
* @param in String containing the data to be concatenated.
* @return New size of the String.
*/
virtual size_t concat(const T *in, size_t inSize);
virtual size_t concat(const Jupiter::Readable_String<T> &in);
virtual size_t concat(const std::basic_string<T> &in);
virtual size_t concat(const T *in);
virtual size_t concat(const T &in);
/**
* @brief Copies a part of an input string and returns it in an output type.
*
* @param R Type to return. Must be a subclass of String_Type.
*
* @param in String to get a partial copy of.
* @param pos Position to start copying from.
* @return Partial copy of the input string.
*/
template<template<typename> class R> static R<T> substring(const Jupiter::Readable_String<T> &in, size_t pos); // REPLACE
template<template<typename> class R> static R<T> substring(const T *in, size_t pos); // REPLACE
/**
* @brief Copies a part of an input string and returns it in an output type.
*
* @param R Type to return. Must be a subclass of String_Type.
*
* @param in String to get a partial copy of.
* @param pos Position to start copying from.
* @param len Number of elements to copy.
* @return Partial copy of the input string.
*/
template<template<typename> class R> static R<T> substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len); // REPLACE
template<template<typename> class R> static R<T> substring(const T *in, size_t pos, size_t len); // REPLACE
/** Mutative operators */
inline String_Type<T> &operator+=(const String_Type<T> &right) { this->concat(right); return *this; };
inline String_Type<T> &operator+=(const std::basic_string<T> &right) { this->concat(right); return *this; };
inline String_Type<T> &operator+=(const std::basic_string_view<T> &right) { this->concat(right); return *this; };
inline String_Type<T> &operator+=(const T *right) { this->concat(right); return *this; };
inline String_Type<T> &operator+=(const T right) { this->concat(right); return *this; };
inline String_Type<T> &operator-=(size_t right) { this->truncate(right); return *this; };
inline String_Type<T> &operator=(const String_Type<T> &right) { this->set(right); return *this; };
inline String_Type<T> &operator=(const std::basic_string<T> &right) { this->set(right); return *this; };
inline String_Type<T> &operator=(const std::basic_string_view<T> &right) { this->set(right.data(), right.size()); return *this; };
inline String_Type<T> &operator=(const T *right) { this->set(right); return *this; };
inline String_Type<T> &operator=(const T right) { this->set(right); return *this; };
/**
* @brief Default constructor for the String_Type class.
*/
String_Type() {}
/**
* @brief Move constructor for the String_Type class.
*/
String_Type(Jupiter::String_Type<T> &&source);
/**
* The following constructors should exist:
* A default constructor
* A copy constructor for the same class.
* A copy constructor for Readable_String.
* A copy constructor for std::basic_string<T>.
* A copy constructor for C-style strings.
* A copy constructor for memory array strings.
* A conversion constructor for Jupiter::DataBuffer
*/
/**
* @brief Destructor for the String_Type class.
*/
virtual ~String_Type() = default;
/**
* Necessities when removing Readable_String & Reference_String
*/
bool empty() const { return size() == 0; }; // KEEP
/** Access operator */
inline const T &operator[](size_t index) const { return this->data()[index]; };
/** Conversion operators */
explicit inline operator std::basic_string<T>() const { return std::basic_string<T>(this->data(), this->size()); }
inline operator std::basic_string_view<T>() const { return std::basic_string_view<T>(this->data(), this->size()); }
/** Comparative operators */
inline bool operator==(const String_Type<T>& right)const{ return operator==(std::basic_string_view<T>{right}); }
inline bool operator==(const std::basic_string<T>& right)const{ return operator==(std::basic_string_view<T>{right}); }
inline bool operator==(const std::basic_string_view<T>& right)const{ return std::basic_string_view<T>(data(), size()) == right; }
inline bool operator==(const T right)const{ return this->size() == 1 && this->get(0) == right; }
inline bool operator==(std::nullptr_t) = delete;
inline bool operator!=(const String_Type<T> &right)const{ return !operator==(right); }
inline bool operator!=(const std::basic_string<T> &right)const{ return !operator==(right); }
inline bool operator!=(const T right)const{ return !operator==(right); }
inline bool operator!=(std::nullptr_t) = delete;
inline bool operator<(const String_Type<T> &right)const{ return this->compare(right) < 0; }
inline bool operator<(const std::basic_string<T> &right)const{ return this->compare(right) < 0; }
inline bool operator<(const T right)const{ return this->compare(right) < 0; }
inline bool operator>(const String_Type<T> &right)const{ return this->compare(right) > 0; }
inline bool operator>(const std::basic_string<T> &right)const{ return this->compare(right) > 0; }
inline bool operator>(const T right)const{ return this->compare(right) > 0; }
inline bool operator<=(const String_Type<T> &right)const{ return !operator>(right); }
inline bool operator<=(const std::basic_string<T> &right)const{ return !operator>(right); }
inline bool operator<=(const T right)const{ return !operator>(right); }
inline bool operator>=(const String_Type<T> &right)const{ return !operator<(right); }
inline bool operator>=(const std::basic_string<T> &right)const{ return !operator<(right); }
inline bool operator>=(const T right)const{ return !operator<(right); }
protected: // Things which cannot be removed right now
T *str{}; /** Pointer for the underlying string of elements */
size_t length{}; /** Number of representable elements in the string */
/**
* @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.
*
* @param len Minimum number of elements the string buffer must be able to hold.
* @return True if a new buffer was allocated, false otherwise.
*/
virtual bool setBufferSize(size_t len) = 0;
/**
* @brief Empties the string, and 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.
*
* @param len Minimum number of elements the string buffer must be able to hold.
* @return True if a new buffer was allocated, false otherwise.
*/
virtual bool setBufferSizeNoCopy(size_t len) = 0;
};
namespace literals {
// Not truly a literal, but I just want this available in places I'm using literals
template<typename T>
static inline std::basic_string<T> operator+(std::basic_string<T> lhs, std::basic_string_view<T> rhs) {
lhs += rhs;
return lhs;
}
template<typename T>
static inline std::basic_string<T> operator+(std::basic_string<T> lhs, const String_Type<T>& rhs) {
lhs += std::basic_string_view<T>{rhs};
return lhs;
}
}
/** Generic String Type */
typedef String_Type<char> StringType;
}
/** Re-enable warning */
#if defined _MSC_VER
#pragma warning(pop)
#endif
/** Implementation for String_Type. */
#include "String_Type_Imp.h"
#endif // _STRING_TYPE_H_HEADER

593
src/include/Jupiter/String_Type_Imp.h

@ -1,593 +0,0 @@
/**
* Copyright (C) 2014-2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _STRING_TYPE_IMP_H_HEADER
#define _STRING_TYPE_IMP_H_HEADER
/**
* @file String_Type_Imp.h
* @brief Provides the implementations for String_Type functions.
* Note: Modification of this file is not supported in any way.
*/
#include "String_Type.h"
#include "Functions.h"
/**
* IMPLEMENTATION:
* String_Type
*/
template<typename T> Jupiter::String_Type<T>::String_Type(Jupiter::String_Type<T> &&source)
{
Jupiter::String_Type<T>::str = source.str;
Jupiter::String_Type<T>::length = source.length;
source.length = 0;
source.str = nullptr;
}
template<typename T> size_t Jupiter::String_Type<T>::size() const
{
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::capacity() const
{
return this->size();
}
template<typename T> const T *Jupiter::String_Type<T>::data() const
{
return Jupiter::String_Type<T>::str;
}
// truncate base
template<typename T> size_t Jupiter::String_Type<T>::truncate(size_t n)
{
if (n >= Jupiter::String_Type<T>::length) return (Jupiter::String_Type<T>::length = 0);
return (Jupiter::String_Type<T>::length -= n);
}
// remove base
template<typename T> bool Jupiter::String_Type<T>::remove(const T &value)
{
for (size_t i = 0; i < Jupiter::String_Type<T>::length - 1; i++)
{
if (Jupiter::String_Type<T>::str[i] == value)
{
while (i < Jupiter::String_Type<T>::length)
{
i++;
Jupiter::String_Type<T>::str[i - 1] = Jupiter::String_Type<T>::str[i];
}
Jupiter::String_Type<T>::length--;
return true;
}
}
if (Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length - 1] == value)
{
this->truncate(1);
return true;
}
return false;
}
template<typename T> void Jupiter::String_Type<T>::remove(size_t index, size_t len)
{
if (index >= Jupiter::String_Type<T>::length)
return;
if (index + len >= Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::length = index;
else
{
Jupiter::String_Type<T>::length -= len;
len += index;
Jupiter::String_Type<T>::str[index] = Jupiter::String_Type<T>::str[len];
while (++index != Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::str[index] = Jupiter::String_Type<T>::str[++len];
}
}
// erase
template<typename T> void Jupiter::String_Type<T>::clear()
{
Jupiter::String_Type<T>::length = 0;
}
// set
template<typename T> size_t Jupiter::String_Type<T>::set(size_t index, const T &in)
{
if (index == Jupiter::String_Type<T>::length)
return this->concat(in);
if (index > Jupiter::String_Type<T>::length)
{
this->setBufferSize(index + 1);
while (Jupiter::String_Type<T>::length != index)
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length++] = 0;
Jupiter::String_Type<T>::length++;
}
Jupiter::String_Type<T>::str[index] = in;
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::set(size_t index, const T *in, size_t inSize)
{
if (index == Jupiter::String_Type<T>::length)
return this->concat(in);
if (index > Jupiter::String_Type<T>::length)
{
this->setBufferSize(index + inSize);
while (Jupiter::String_Type<T>::length != index)
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length++] = 0;
index = 0;
while (index != inSize)
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length++] = in[index];
}
else
{
index += inSize;
if (index > Jupiter::String_Type<T>::length)
{
this->setBufferSize(index);
Jupiter::String_Type<T>::length = index;
}
while (inSize != 0)
Jupiter::String_Type<T>::str[--index] = in[--inSize];
}
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::set(size_t index, const Jupiter::Readable_String<T> &in)
{
return this->set(index, in.data(), in.size());
}
template<typename T> size_t Jupiter::String_Type<T>::set(size_t index, const std::basic_string<T> &in)
{
return this->set(index, in.c_str(), in.size());
}
template<typename T> size_t Jupiter::String_Type<T>::set(size_t index, const T *in)
{
return this->set(index, in, Jupiter::strlen<T>(in));
}
template<typename T> size_t Jupiter::String_Type<T>::set(const T *in, size_t inSize)
{
this->setBufferSizeNoCopy(inSize);
Jupiter::String_Type<T>::length = inSize;
while (inSize-- != 0)
*Jupiter::String_Type<T>::str++ = *in++;
Jupiter::String_Type<T>::str -= Jupiter::String_Type<T>::length;
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::set(const Jupiter::Readable_String<T> &in)
{
return this->set(in.data(), in.size());
}
template<typename T> size_t Jupiter::String_Type<T>::set(const std::basic_string<T> &in)
{
return this->set(in.c_str(), in.size());
}
template<typename T> size_t Jupiter::String_Type<T>::set(const T *in)
{
return this->set(in, Jupiter::strlen<T>(in));
}
template<typename T> size_t Jupiter::String_Type<T>::set(const T &in)
{
this->setBufferSizeNoCopy(1);
*Jupiter::String_Type<T>::str = in;
return Jupiter::String_Type<T>::length = 1;
}
// insert
template<typename T> size_t Jupiter::String_Type<T>::insert(size_t index, const T &value)
{
if (index >= Jupiter::String_Type<T>::length)
return this->concat(value);
this->setBufferSize(Jupiter::String_Type<T>::length + 1);
for (size_t i = Jupiter::String_Type<T>::length; i != index; i--)
Jupiter::String_Type<T>::str[i] = operator[](i-1);
Jupiter::String_Type<T>::str[index] = value;
return ++Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::insert(size_t index, const Jupiter::Readable_String<T> &value)
{
if (index >= Jupiter::String_Type<T>::length)
return this->concat(value);
if (value.empty())
return Jupiter::String_Type<T>::length;
if (value.size() == 1)
return this->insert(index, value[0]);
this->setBufferSize(Jupiter::String_Type<T>::length + value.size());
size_t i;
for (i = Jupiter::String_Type<T>::length + value.size() - 1; i != index + value.size() - 1; i--)
Jupiter::String_Type<T>::str[i] = operator[](i - value.size());
while (i != index)
{
Jupiter::String_Type<T>::str[i] = value[i - index];
i--;
}
Jupiter::String_Type<T>::str[index] = value[0];
return Jupiter::String_Type<T>::length += value.size();
}
// replace
template<typename T> size_t Jupiter::String_Type<T>::replace(size_t index, size_t targetSize, const T &value)
{
if (targetSize != 0)
{
if (index >= Jupiter::String_Type<T>::length)
return this->set(index, value);
if (index + targetSize > Jupiter::String_Type<T>::length)
{
Jupiter::String_Type<T>::str[index] = value;
return Jupiter::String_Type<T>::length = index + 1;
}
if (targetSize == 1)
return this->set(index, value);
Jupiter::String_Type<T>::str[index] = value;
Jupiter::String_Type<T>::length -= targetSize - 1;
while (++index != Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::str[index] = Jupiter::String_Type<T>::str[index + targetSize - 1];
}
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::replace(size_t index, size_t targetSize, const T *value, size_t valueSize)
{
if (valueSize == 1)
return this->replace(index, targetSize, *value);
if (valueSize == 0)
{
this->remove(index, targetSize);
return Jupiter::String_Type<T>::length;
}
if (targetSize != 0)
{
if (index >= Jupiter::String_Type<T>::length)
return this->set(index, value);
if (index + targetSize > Jupiter::String_Type<T>::length)
{
if (index + valueSize > Jupiter::String_Type<T>::length)
this->setBufferSize(index + valueSize);
Jupiter::String_Type<T>::length = index + valueSize;
Jupiter::String_Type<T>::str[index] = *value;
while (++index != Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::str[index] = *++value;
return Jupiter::String_Type<T>::length;
}
if (targetSize == valueSize)
return this->set(index, value, valueSize);
if (valueSize < targetSize)
{
targetSize -= valueSize;
Jupiter::String_Type<T>::length -= targetSize;
Jupiter::String_Type<T>::str[index] = *value;
while (--valueSize != 0)
Jupiter::String_Type<T>::str[++index] = *++value;
while (++index != Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::str[index] = Jupiter::String_Type<T>::str[index + targetSize];
}
else
{
size_t i = Jupiter::String_Type<T>::length;
valueSize -= targetSize;
this->setBufferSize(Jupiter::String_Type<T>::length + valueSize);
Jupiter::String_Type<T>::length += valueSize;
index += targetSize;
while (i-- != index)
Jupiter::String_Type<T>::str[i + valueSize] = Jupiter::String_Type<T>::str[i];
index -= targetSize;
valueSize += targetSize;
Jupiter::String_Type<T>::str[index] = *value;
while (--valueSize != 0)
Jupiter::String_Type<T>::str[++index] = *++value;
}
}
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::replace(size_t index, size_t targetSize, std::basic_string_view<T> value) {
return this->replace(index, targetSize, value.data(), value.size());
}
template<typename T> size_t Jupiter::String_Type<T>::replace(const T &target, const T &value)
{
for (size_t i = 0; i != Jupiter::String_Type<T>::length; i++)
{
if (operator[](i) == target)
Jupiter::String_Type<T>::str[i] = value;
}
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::replace(const T *target, size_t targetSize, const T &value)
{
if (targetSize != 0)
{
if (targetSize == 1)
return this->replace(*target, value);
if (targetSize < Jupiter::String_Type<T>::length)
{
size_t i = 0, j = 0, k;
while (j <= Jupiter::String_Type<T>::length - targetSize)
{
k = 0;
while (operator[](j + k) == target[k])
{
if (++k == targetSize) // match found
{
Jupiter::String_Type<T>::str[i] = value;
i += 1;
j += k;
break;
}
}
if (k != targetSize)
Jupiter::String_Type<T>::str[i++] = Jupiter::String_Type<T>::str[j++];
}
while (j < Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::str[i++] = Jupiter::String_Type<T>::str[j++];
Jupiter::String_Type<T>::length = i;
}
else if (targetSize == Jupiter::String_Type<T>::length && *this == std::basic_string_view<T>(target, targetSize))
return this->set(value);
}
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::replace(const Jupiter::Readable_String<T> &target, const T &value)
{
return this->replace(target.data(), target.size(), value);
}
template<typename T> size_t Jupiter::String_Type<T>::replace(const T *target, size_t targetSize, const T *value, size_t valueSize)
{
if (valueSize == 1)
return this->replace(target, targetSize, *value);
if (targetSize != 0)
{
//if (targetSize == 1)
// return this->replace(*target, value, valueSize);
if (targetSize < Jupiter::String_Type<T>::length)
{
if (valueSize > targetSize)
{
size_t instancesSize = 4;
size_t *instances = new size_t[instancesSize];
// pass 1 (count instances)
size_t instanceCount = 0, i = 0, j;
while (i <= Jupiter::String_Type<T>::length - targetSize)
{
j = 0;
while (operator[](i + j) == target[j])
{
if (++j == targetSize)
{
i += targetSize;
if (instanceCount == instancesSize)
{
size_t *tInstances = new size_t[instancesSize * 2];
for (instanceCount = 0; instanceCount != instancesSize; instanceCount++)
tInstances[instanceCount] = instances[instanceCount];
delete[] instances;
instances = tInstances;
instancesSize *= 2;
}
instances[instanceCount] = i;
instanceCount++;
break;
}
}
if (j != targetSize)
i++;
}
if (instanceCount != 0)
{
// pass 2 (adjust string and replace values)
size_t endSize = Jupiter::String_Type<T>::length + (valueSize - targetSize) * instanceCount;
this->setBufferSize(endSize);
instancesSize = endSize; // Repurposing. Now used as just another index.
j = Jupiter::String_Type<T>::length;
while (instanceCount != 0)
{
i = instances[--instanceCount];
while (j != i)
Jupiter::String_Type<T>::str[--instancesSize] = Jupiter::String_Type<T>::str[--j];
j = valueSize;
while (j != 0)
Jupiter::String_Type<T>::str[--instancesSize] = value[--j];
j = i - targetSize;
}
Jupiter::String_Type<T>::length = endSize;
}
delete[] instances;
}
else
{
size_t i = 0, j = 0, k, l;
while (j <= Jupiter::String_Type<T>::length - targetSize)
{
k = 0;
while (operator[](j + k) == target[k])
{
if (++k == targetSize) // match found
{
for (l = 0; l != valueSize; l++)
Jupiter::String_Type<T>::str[i + l] = value[l];
i += valueSize;
j += k;
break;
}
}
if (k != targetSize)
Jupiter::String_Type<T>::str[i++] = Jupiter::String_Type<T>::str[j++];
}
while (j < Jupiter::String_Type<T>::length)
Jupiter::String_Type<T>::str[i++] = Jupiter::String_Type<T>::str[j++];
Jupiter::String_Type<T>::length = i;
}
}
else if (targetSize == Jupiter::String_Type<T>::length && *this == std::basic_string_view<T>(target, targetSize))
return this->set(value);
}
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::replace(const T *target, size_t targetSize, const Jupiter::Readable_String<T> &value)
{
return this->replace(target, targetSize, value.data(), value.size());
}
template<typename T> size_t Jupiter::String_Type<T>::replace(const Jupiter::Readable_String<T> &target, const T *value, size_t valueSize)
{
return this->replace(target.data(), target.size(), value, valueSize);
}
template<typename T> size_t Jupiter::String_Type<T>::replace(std::basic_string_view<T> target, std::basic_string_view<T> value)
{
return this->replace(target.data(), target.size(), value.data(), value.size());
}
// concat
template<typename T> size_t Jupiter::String_Type<T>::concat(const T *in, size_t inSize)
{
this->setBufferSize(Jupiter::String_Type<T>::length + inSize);
while (inSize-- != 0)
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length++] = *in++;
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::String_Type<T>::concat(const Jupiter::Readable_String<T> &in)
{
return this->concat(in.data(), in.size());
}
template<typename T> size_t Jupiter::String_Type<T>::concat(const std::basic_string<T> &in)
{
return this->concat(in.c_str(), in.size());
}
template<typename T> size_t Jupiter::String_Type<T>::concat(const T *in)
{
return this->concat(in, Jupiter::strlen<T>(in));
}
template<typename T> size_t Jupiter::String_Type<T>::concat(const T &c)
{
this->setBufferSize(Jupiter::String_Type<T>::length + 1);
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = c;
return ++Jupiter::String_Type<T>::length;
}
/**
* IMPLEMENTATION:
* String helper templates
*/
// substring
template<typename T> template<template<typename> class R> R<T> Jupiter::String_Type<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos)
{
if (pos >= in.size()) return R<T>();
R<T> r = R<T>(in.size() - pos);
for (r.length = 0; pos + r.length != in.size(); r.length++) r.str[r.length] = in[pos + r.length];
return r;
}
template<typename T> template<template<typename> class R> R<T> Jupiter::String_Type<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len)
{
if (pos + len >= in.size()) return R<T>::substring(in, pos);
R<T> r = R<T>(len);
for (r.length = 0; r.length != len; r.length++) r.str[r.length] = in[pos + r.length];
return r;
}
template<typename T> template<template<typename> class R> R<T> Jupiter::String_Type<T>::substring(const T *in, size_t pos)
{
size_t strLen = Jupiter::strlen<T>(in);
if (pos >= strLen) return R<T>();
R<T> r = R<T>(strLen - pos);
in += pos;
for (r.length = 0; *in != 0; r.length++, in++) r.str[r.length] = *in;
return r;
}
template<typename T> template<template<typename> class R> R<T> Jupiter::String_Type<T>::substring(const T *in, size_t pos, size_t len)
{
R<T> r = R<T>(len);
in += pos;
for (r.length = 0; r.length != len; r.length++, in++) r.str[r.length] = *in;
return r;
}
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::String_Type> {
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::String_Type<Y> *data) {
buffer->secure(sizeof(size_t) + data->size() * sizeof(Y));
buffer->push<size_t>(data->size());
buffer->push(reinterpret_cast<const uint8_t *>(data->data()), data->size() * sizeof(Y));
};
};
#endif // _STRING_TYPE_IMP_H_HEADER

2
src/jessilib

@ -1 +1 @@
Subproject commit d7e4f337c786184a68b095449176261ce1700295 Subproject commit bce3bfefc6323754656d8153630b80155e4644e2
Loading…
Cancel
Save