Browse Source

Removed HashTable, CString. Added JUPITER_SOCK_EWOULDBLOCK

release/0.19
Jessica James 5 years ago
parent
commit
cf77a1b6a7
  1. 68
      src/common/Config.cpp
  2. 12
      src/common/Database.cpp
  3. 25
      src/common/File.cpp
  4. 9
      src/common/HTTP_Server.cpp
  5. 43
      src/common/INIConfig.cpp
  6. 159
      src/common/IRC_Client.cpp
  7. 11
      src/common/Plugin.cpp
  8. 11
      src/common/SecureSocket.cpp
  9. 26
      src/common/Socket.cpp
  10. 570
      src/include/Jupiter/CString.h
  11. 932
      src/include/Jupiter/CString_Imp.h
  12. 41
      src/include/Jupiter/Config.h
  13. 10
      src/include/Jupiter/Database.h
  14. 2
      src/include/Jupiter/File.h
  15. 31
      src/include/Jupiter/HTTP_QueryString.h
  16. 285
      src/include/Jupiter/Hash_Table.h
  17. 503
      src/include/Jupiter/Hash_Table_Imp.h
  18. 14
      src/include/Jupiter/IRC_Client.h
  19. 2
      src/include/Jupiter/Shift_String.h
  20. 6
      src/include/Jupiter/Socket.h
  21. 19
      src/include/Jupiter/String.hpp
  22. 2
      src/include/Jupiter/String_Imp.h
  23. 4
      src/include/Jupiter/String_Type.h
  24. 5
      src/include/Jupiter/String_Type_Imp.h

68
src/common/Config.cpp

@ -20,60 +20,70 @@
const Jupiter::Config o_null_section;
const Jupiter::ReadableString &Jupiter::Config::get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value) const
{
const Jupiter::ReadableString *result = m_table.get(in_key);
if (result == nullptr)
return in_default_value;
Jupiter::Config::Config(const Config& in_config)
: m_sections{ std::make_unique<SectionHashTable>(*in_config.m_sections) } {
}
return *result;
Jupiter::Config& Jupiter::Config::operator=(const Config& in_config) {
m_sections = std::make_unique<SectionHashTable>(*in_config.m_sections);
}
const Jupiter::ReadableString *Jupiter::Config::getValue(const Jupiter::ReadableString &in_key) const
const Jupiter::ReadableString &Jupiter::Config::get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value) const
{
return m_table.get(in_key);
auto value = m_table.find(in_key);
if (value != m_table.end()) {
return value->second;
}
return in_default_value;
}
Jupiter::Config *Jupiter::Config::getSection(const Jupiter::ReadableString &in_key) const
{
return m_sections.get(in_key);
if (m_sections != nullptr) {
auto section = m_sections->find(in_key);
if (section != m_sections->end()) {
return &section->second;
}
}
return nullptr;
}
Jupiter::Config &Jupiter::Config::getSectionReference(const Jupiter::ReadableString &in_key)
{
Config *section = m_sections.get(in_key);
if (m_sections == nullptr) {
m_sections = std::make_unique<SectionHashTable>();
}
if (section == nullptr)
{
m_sections.set(in_key);
section = m_sections.get(in_key);
section->m_name = in_key;
return *section;
Config& section = (*m_sections)[in_key];
if (section.m_name.empty()) {
section.m_name = static_cast<std::string>(in_key);
}
return *section;
return section;
}
bool Jupiter::Config::set(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_value)
{
return m_table.set(in_key, in_value);
return m_table.insert_or_assign(in_key, in_value).second;
}
bool Jupiter::Config::remove(const Jupiter::ReadableString &in_key)
{
return m_table.remove(in_key);
return m_table.erase(in_key) > 0;
}
const Jupiter::ReadableString &Jupiter::Config::getName() const
const std::string &Jupiter::Config::getName() const
{
return m_name;
}
void Jupiter::Config::erase()
{
m_table.erase();
m_sections.erase();
m_table.clear();
m_sections = nullptr;
}
bool Jupiter::Config::read(const char *in_filename)
@ -84,7 +94,7 @@ bool Jupiter::Config::read(const char *in_filename)
bool Jupiter::Config::read(const Jupiter::ReadableString &in_filename)
{
m_name = in_filename;
m_name = static_cast<std::string>(in_filename);
return this->read_internal(m_name.c_str());
}
@ -100,7 +110,7 @@ bool Jupiter::Config::write(const char *in_filename)
bool Jupiter::Config::write(const Jupiter::ReadableString &in_filename)
{
return this->write(Jupiter::CStringS(in_filename).c_str());
return this->write(static_cast<std::string>(in_filename).c_str());
}
bool Jupiter::Config::reload()
@ -121,6 +131,14 @@ bool Jupiter::Config::reload(const Jupiter::ReadableString &in_filename)
return this->read(in_filename);
}
const Jupiter::Config::SectionHashTable &Jupiter::Config::getSections() const {
if (m_sections == nullptr) {
const_cast<Config*>(this)->m_sections = std::make_unique<SectionHashTable>();
}
return *m_sections;
}
/** Operators */
Jupiter::Config &Jupiter::Config::operator[](const Jupiter::ReadableString &in_key)
{

12
src/common/Database.cpp

@ -25,7 +25,7 @@ struct Jupiter::Database::Data
static bool create_database(FILE *file, const Jupiter::DataBuffer *header);
bool auto_create = true;
Jupiter::CStringS file_name;
std::string file_name;
};
void Jupiter::Database::process_header(FILE *)
@ -38,11 +38,11 @@ void Jupiter::Database::create_header(FILE *)
bool Jupiter::Database::process_file(const Jupiter::ReadableString &file)
{
Jupiter::Database::data_->file_name = file;
Jupiter::Database::data_->file_name = static_cast<std::string>(file);
return Jupiter::Database::Data::process_file(this);
}
bool Jupiter::Database::process_file(const Jupiter::CStringType &file)
bool Jupiter::Database::process_file(const std::string &file)
{
Jupiter::Database::data_->file_name = file;
return Jupiter::Database::Data::process_file(this);
@ -115,7 +115,7 @@ void Jupiter::Database::process_file_finish(FILE *)
{
}
const Jupiter::CStringType &Jupiter::Database::getFilename() const
const std::string &Jupiter::Database::getFilename() const
{
return Jupiter::Database::data_->file_name;
}
@ -135,7 +135,7 @@ bool Jupiter::Database::append(Jupiter::ReadableString &file, Jupiter::DataBuffe
return r;
}
bool Jupiter::Database::append(Jupiter::CStringType &file, Jupiter::DataBuffer &data)
bool Jupiter::Database::append(std::string &file, Jupiter::DataBuffer &data)
{
return Jupiter::Database::append(file.c_str(), data);
}
@ -168,7 +168,7 @@ bool Jupiter::Database::create_database(const Jupiter::ReadableString &file, con
return r;
}
bool Jupiter::Database::create_database(const Jupiter::CStringType &file, const Jupiter::DataBuffer *header)
bool Jupiter::Database::create_database(const std::string &file, const Jupiter::DataBuffer *header)
{
return Jupiter::Database::create_database(file.c_str(), header);
}

25
src/common/File.cpp

@ -17,10 +17,9 @@
*/
#include <sys/stat.h>
#include <string>
#include "File.h"
#include "CString.h"
#include "String.hpp"
#include "Reference_String.h"
#include "ArrayList.h"
/**
@ -49,7 +48,7 @@ const size_t defaultBufferSize = 8192;
struct JUPITER_API Jupiter::File::Data
{
Jupiter::CStringS fileName;
std::string fileName;
Jupiter::ArrayList<Jupiter::StringS> lines;
Data();
@ -110,7 +109,7 @@ const Jupiter::ReadableString &Jupiter::File::getLine(size_t line) const
return *Jupiter::File::data_->lines.get(line);
}
const Jupiter::ReadableString &Jupiter::File::getFileName() const
const std::string &Jupiter::File::getFileName() const
{
return Jupiter::File::data_->fileName;
}
@ -128,7 +127,7 @@ bool Jupiter::File::load(const char *file)
{
FILE *filePtr = fopen(file, "rb");
if (filePtr == nullptr) return false;
if (Jupiter::File::data_->fileName.isEmpty())
if (Jupiter::File::data_->fileName.empty())
Jupiter::File::data_->fileName = file;
bool r = Jupiter::File::load(filePtr);
fclose(filePtr);
@ -137,11 +136,11 @@ bool Jupiter::File::load(const char *file)
bool Jupiter::File::load(const Jupiter::ReadableString &file)
{
Jupiter::CStringS fileName = file;
std::string fileName = static_cast<std::string>(file);
FILE *filePtr = fopen(fileName.c_str(), "rb");
if (filePtr == nullptr) return false;
if (Jupiter::File::data_->fileName.isEmpty())
Jupiter::File::data_->fileName = file;
if (Jupiter::File::data_->fileName.empty())
Jupiter::File::data_->fileName = fileName;
bool r = Jupiter::File::load(filePtr);
fclose(filePtr);
return r;
@ -232,15 +231,15 @@ bool Jupiter::File::load(FILE *file)
void Jupiter::File::unload()
{
Jupiter::File::data_->fileName.set("");
Jupiter::File::data_->fileName.clear();
Jupiter::File::data_->lines.emptyAndDelete();
}
bool Jupiter::File::reload()
{
if (Jupiter::File::data_->fileName.isEmpty())
if (Jupiter::File::data_->fileName.empty())
return false;
Jupiter::CStringS fileName(std::move(Jupiter::File::data_->fileName));
std::string fileName(std::move(Jupiter::File::data_->fileName));
Jupiter::File::unload();
return Jupiter::File::load(fileName.c_str());
}
@ -265,7 +264,7 @@ bool Jupiter::File::reload(FILE *file)
bool Jupiter::File::sync()
{
if (Jupiter::File::data_->fileName.isEmpty())
if (Jupiter::File::data_->fileName.empty())
return false;
return Jupiter::File::sync(Jupiter::File::data_->fileName.c_str());
}
@ -281,7 +280,7 @@ bool Jupiter::File::sync(const char *file)
bool Jupiter::File::sync(const Jupiter::ReadableString &file)
{
return Jupiter::File::sync(Jupiter::CStringS(file).c_str());
return Jupiter::File::sync(static_cast<std::string>(file).c_str());
}
bool Jupiter::File::sync(FILE *file)

9
src/common/HTTP_Server.cpp

@ -19,7 +19,6 @@
#include <ctime>
#include <chrono>
#include "String.hpp"
#include "CString.h"
#include "Reference_String.h"
#include "TCPSocket.h"
#include "ArrayList.h"
@ -759,7 +758,7 @@ Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableS
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port)
{
Jupiter::TCPSocket *socket = new Jupiter::TCPSocket();
if (socket->bind(Jupiter::CStringS(hostname).c_str(), port, true))
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true))
{
socket->setBlocking(false);
Jupiter::HTTP::Server::data_->ports.add(socket);
@ -772,7 +771,7 @@ bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port)
{
Jupiter::SecureTCPSocket *socket = new Jupiter::SecureTCPSocket();
if (socket->bind(Jupiter::CStringS(hostname).c_str(), port, true))
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true))
{
Jupiter::HTTP::Server::data_->ports.add(socket);
return true;
@ -821,7 +820,7 @@ int Jupiter::HTTP::Server::think()
else // reject
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
}
else if (session->sock.getLastError() != 10035)
else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK)
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
}
@ -869,7 +868,7 @@ int Jupiter::HTTP::Server::think()
else // reject (too large)
delete session;
}
else if (session->sock.getLastError() == 10035) // store for more processing
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) // store for more processing
Jupiter::HTTP::Server::data_->sessions.add(session);
}
}

43
src/common/INIConfig.cpp

@ -37,7 +37,7 @@ void Jupiter::INIConfig::write_helper(FILE *in_file, const Jupiter::Config *in_s
for (index = 0; index != in_depth; ++index)
fputc('[', in_file);
in_section->getName().print(in_file);
fputs(in_section->getName().c_str(), in_file);
for (index = 0; index != in_depth; ++index)
fputc(']', in_file);
@ -46,42 +46,21 @@ void Jupiter::INIConfig::write_helper(FILE *in_file, const Jupiter::Config *in_s
}
// Write table entries
for (auto& table_entry : in_section->getTable())
{
auto bucket_itr = in_section->getTable().begin();
auto bucket_end = in_section->getTable().end();
std::forward_list<HashTable::Bucket::Entry>::iterator entry_itr;
while (bucket_itr != bucket_end)
{
for (entry_itr = bucket_itr->m_entries.begin(); entry_itr != bucket_itr->m_entries.end(); ++entry_itr)
{
// Tabs
for (index = 1; index < in_depth; ++index)
fputc('\t', in_file);
// Write entry
entry_itr->key.print(in_file);
fputs(" = ", in_file);
entry_itr->value.println(in_file);
}
// Tabs
for (index = 1; index < in_depth; ++index)
fputc('\t', in_file);
++bucket_itr;
}
// Write entry
table_entry.first.print(in_file);
fputs(" = ", in_file);
table_entry.second.println(in_file);
}
// Write subsections
{
auto bucket_itr = in_section->getSections().begin();
auto bucket_end = in_section->getSections().end();
std::forward_list<SectionHashTable::Bucket::Entry>::iterator entry_itr;
while (bucket_itr != bucket_end)
{
for (entry_itr = bucket_itr->m_entries.begin(); entry_itr != bucket_itr->m_entries.end(); ++entry_itr)
write_helper(in_file, &entry_itr->value, in_depth + 1);
++bucket_itr;
}
for (auto& subsection : in_section->getSections()) {
write_helper(in_file, &subsection.second, in_depth + 1);
}
}

159
src/common/IRC_Client.cpp

@ -23,7 +23,6 @@
#include "Functions.h"
#include "IRC_Client.h"
#include "TCPSocket.h"
#include "CString.h"
#include "String.hpp"
#include "Plugin.h"
#include "Base64.h"
@ -47,9 +46,9 @@ Jupiter::IRC::Client::Client(Jupiter::Config *in_primary_section, Jupiter::Confi
if (m_primary_section != nullptr)
m_primary_section_name = m_primary_section->getName();
m_server_hostname = Jupiter::IRC::Client::readConfigValue("Hostname"_jrs, "irc.cncirc.net"_jrs);
m_server_hostname = static_cast<std::string>(Jupiter::IRC::Client::readConfigValue("Hostname"_jrs, "irc.cncirc.net"_jrs));
m_log_file_name = Jupiter::IRC::Client::readConfigValue("LogFile"_jrs);
m_log_file_name = static_cast<std::string>(Jupiter::IRC::Client::readConfigValue("LogFile"_jrs));
m_nickname = Jupiter::IRC::Client::readConfigValue("Nick"_jrs, "Jupiter"_jrs);
m_realname = Jupiter::IRC::Client::readConfigValue("RealName"_jrs, "Jupiter IRC Client"_jrs);
@ -86,7 +85,7 @@ Jupiter::IRC::Client::Client(Jupiter::Config *in_primary_section, Jupiter::Confi
m_output = stdout;
else
m_output = nullptr;
if (m_log_file_name.isNotEmpty())
if (!m_log_file_name.empty())
m_log_file = fopen(m_log_file_name.c_str(), "a+b");
else m_log_file = nullptr;
@ -236,7 +235,7 @@ void Jupiter::IRC::Client::setSecondaryConfigSection(Jupiter::Config *in_seconda
m_secondary_section = in_secondary_section;
}
const Jupiter::ReadableString &Jupiter::IRC::Client::getLogFile() const
const std::string &Jupiter::IRC::Client::getLogFile() const
{
return m_log_file_name;
}
@ -266,7 +265,7 @@ const Jupiter::ReadableString &Jupiter::IRC::Client::getServerName() const
return m_server_name;
}
const Jupiter::ReadableString &Jupiter::IRC::Client::getServerHostname() const
const std::string &Jupiter::IRC::Client::getServerHostname() const
{
return m_server_hostname;
}
@ -328,10 +327,10 @@ int Jupiter::IRC::Client::getAccessLevel(const Channel &in_channel, const Jupite
int Jupiter::IRC::Client::getAccessLevel(const Jupiter::ReadableString &in_channel, const Jupiter::ReadableString &in_nickname) const
{
Jupiter::IRC::Client::Channel *channel = m_channels.get(in_channel);
auto channel = m_channels.find(in_channel);
if (channel != nullptr)
return this->getAccessLevel(*channel, in_nickname);
if (channel != m_channels.end())
return this->getAccessLevel(channel->second, in_nickname);
return 0;
}
@ -356,7 +355,12 @@ size_t Jupiter::IRC::Client::getUserCount() const
Jupiter::IRC::Client::User *Jupiter::IRC::Client::getUser(const Jupiter::ReadableString &in_nickname) const
{
return m_users.get(in_nickname);
auto user = m_users.find(in_nickname);
if (user != m_users.end()) {
return const_cast<User*>(&user->second);
}
return nullptr;
}
const Jupiter::IRC::Client::ChannelTableType &Jupiter::IRC::Client::getChannels() const
@ -371,7 +375,12 @@ size_t Jupiter::IRC::Client::getChannelCount() const
Jupiter::IRC::Client::Channel *Jupiter::IRC::Client::getChannel(const Jupiter::ReadableString &in_channel) const
{
return m_channels.get(in_channel);
auto channel = m_channels.find(in_channel);
if (channel != m_channels.end()) {
return const_cast<Channel*>(&channel->second);
}
return nullptr;
}
bool Jupiter::IRC::Client::isAutoReconnect() const
@ -398,14 +407,14 @@ void Jupiter::IRC::Client::partChannel(const Jupiter::ReadableString &in_channel
{
m_socket->send(Jupiter::StringS::Format("PART %.*s" ENDL, in_channel.size(), in_channel.ptr()));
m_channels.get(in_channel)->setType(-2);
m_channels[in_channel].setType(-2);
}
void Jupiter::IRC::Client::partChannel(const Jupiter::ReadableString &in_channel, const Jupiter::ReadableString &in_message)
{
m_socket->send(Jupiter::StringS::Format("PART %.*s :%.*s" ENDL, in_channel.size(), in_channel.ptr(), in_message.size(), in_message.ptr()));
m_channels.get(in_channel)->setType(-2);
m_channels[in_channel].setType(-2);
}
void Jupiter::IRC::Client::sendMessage(const Jupiter::ReadableString &dest, const Jupiter::ReadableString &message)
@ -420,25 +429,20 @@ void Jupiter::IRC::Client::sendNotice(const Jupiter::ReadableString &dest, const
size_t Jupiter::IRC::Client::messageChannels(int type, const Jupiter::ReadableString &message)
{
auto message_channel_callback = [this, type, &message](ChannelTableType::Bucket::Entry &in_entry)
{
if (in_entry.value.getType() == type)
this->sendMessage(in_entry.value.getName(), message);
};
m_channels.callback(message_channel_callback);
for (auto& channel : m_channels) {
if (channel.second.getType() == type) {
sendMessage(channel.second.getName(), message);
}
}
return m_channels.size();
}
size_t Jupiter::IRC::Client::messageChannels(const Jupiter::ReadableString &message)
{
auto message_channel_callback = [this, &message](ChannelTableType::Bucket::Entry &in_entry)
{
this->sendMessage(in_entry.value.getName(), message);
};
m_channels.callback(message_channel_callback);
for (auto& channel : m_channels) {
sendMessage(channel.second.getName(), message);
}
return m_channels.size();
}
@ -488,7 +492,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
}
if (port != 0) // Don't default -- could be non-compliant input.
{
m_server_hostname = Jupiter::ReferenceString::getWord(line, 3, WHITESPACE);
m_server_hostname = static_cast<std::string>(Jupiter::ReferenceString::getWord(line, 3, WHITESPACE));
m_server_port = port;
puts("Reconnecting due to old bounce.");
this->reconnect();
@ -530,8 +534,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
}
if (bouncePort != 0)
{
m_server_hostname = Jupiter::ReferenceString::getWord(line, 4, " ");
m_server_hostname.truncate(1); // trailing comma
auto server_hostname = Jupiter::ReferenceString::getWord(line, 4, " ");
server_hostname.truncate(1); // trailing comma
m_server_hostname = static_cast<std::string>(server_hostname);
m_server_port = bouncePort;
puts("Reconnecting due to old bounce.");
this->reconnect();
@ -786,21 +791,19 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
i++;
}
auto auto_join_channels_callback = [this](Jupiter::Config::SectionHashTable::Bucket::Entry &in_entry)
auto join_channels_for_config = [this](Jupiter::Config *config)
{
if (in_entry.value.get<bool>("AutoJoin"_jrs, false))
this->joinChannel(in_entry.value.getName());
if (config != nullptr) {
for (auto& section : config->getSections()) {
if (section.second.get<bool>("AutoJoin"_jrs, false)) {
this->joinChannel(section.first);
}
}
}
};
Jupiter::Config *config = m_primary_section->getSection("Channels"_jrs);
if (config != nullptr)
config->getSections().callback(auto_join_channels_callback);
config = m_secondary_section->getSection("Channels"_jrs);
if (config != nullptr)
config->getSections().callback(auto_join_channels_callback);
join_channels_for_config(m_primary_section->getSection("Channels"_jrs));
join_channels_for_config(m_secondary_section->getSection("Channels"_jrs));
m_connection_status = 5;
m_reconnect_attempts = 0;
@ -927,7 +930,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (chan[0] == ':')
chan.shiftRight(1);
Channel *channel = m_channels.get(chan);
auto channel = getChannel(chan);
if (m_nickname.equalsi(nick))
{
@ -936,7 +939,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Client::delChannel(channel->getName());
Client::addChannel(chan);
channel = m_channels.get(chan);
channel = getChannel(chan);
channel->m_adding_names = true;
if (channel->getType() < 0)
@ -963,10 +966,10 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
if (chan.isNotEmpty())
{
Channel *channel = m_channels.get(chan);
Channel *channel = getChannel(chan);
if (channel != nullptr)
{
Jupiter::IRC::Client::User *user = m_users.get(nick);
Jupiter::IRC::Client::User *user = getUser(nick);
if (user != nullptr)
{
channel->delUser(nick);
@ -985,7 +988,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Client::delChannel(chan);
if (user->getChannelCount() == 0)
m_users.remove(nick);
m_users.erase(nick);
}
}
}
@ -1002,10 +1005,10 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Jupiter::ReferenceString kicked = Jupiter::ReferenceString::getWord(line, 3, WHITESPACE);
if (kicked.isNotEmpty())
{
Channel *channel = m_channels.get(chan);
Channel *channel = getChannel(chan);
if (channel != nullptr)
{
Jupiter::IRC::Client::User *user = m_users.get(kicked);
Jupiter::IRC::Client::User *user = getUser(kicked);
if (user != nullptr)
{
channel->delUser(kicked);
@ -1028,7 +1031,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
}
if (user->getChannelCount() == 0)
m_users.remove(kicked);
m_users.erase(kicked);
}
}
}
@ -1039,22 +1042,19 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{
Jupiter::ReferenceString nick = getSender(line);
Jupiter::ReferenceString message = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
Jupiter::IRC::Client::User *user = m_users.get(nick);
Jupiter::IRC::Client::User *user = getUser(nick);
if (user != nullptr)
{
auto remove_user_callback = [&nick](ChannelTableType::Bucket::Entry &in_entry)
{
in_entry.value.delUser(nick);
};
m_channels.callback(remove_user_callback);
for (auto& channel : m_channels) {
channel.second.delUser(nick);
}
this->OnQuit(nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnQuit(this, nick, message);
m_users.remove(nick);
m_users.erase(nick);
}
}
else if (w2.equalsi("INVITE"))
@ -1096,7 +1096,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
tword = modestring.getWord(g, " ");
if (tword.isNotEmpty())
{
Jupiter::IRC::Client::Channel *channel = m_channels.get(chan);
Jupiter::IRC::Client::Channel *channel = getChannel(chan);
if (channel != nullptr)
{
if (symb == '+')
@ -1131,7 +1131,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 4, " ");
Jupiter::ReferenceString names = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
Channel *channel = m_channels.get(chan);
Channel *channel = getChannel(chan);
if (channel != nullptr)
{
if (channel->m_adding_names == false)
@ -1149,7 +1149,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
else if (numeric == Reply::ENDOFNAMES) // We're done here.
{
Jupiter::ReferenceString chan = Jupiter::ReferenceString::getWord(line, 3, " ");
Channel *channel = m_channels.get(chan);
Channel *channel = getChannel(chan);
if (channel != nullptr)
channel->m_adding_names = false;
@ -1209,7 +1209,7 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
bool Jupiter::IRC::Client::connect()
{
const Jupiter::ReadableString &clientAddress = Jupiter::IRC::Client::readConfigValue("ClientAddress"_jrs);
if (m_socket->connect(m_server_hostname.c_str(), m_server_port, clientAddress.isEmpty() ? nullptr : Jupiter::CStringS(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.isEmpty() ? nullptr : static_cast<std::string>(clientAddress).c_str(), (unsigned short)Jupiter::IRC::Client::readConfigLong("ClientPort"_jrs)) == false)
return false;
m_socket->setBlocking(false);
@ -1335,7 +1335,7 @@ int Jupiter::IRC::Client::think()
// No incoming data; check for errors
tmp = m_socket->getLastError();
if (tmp == 10035) // Operation would block
if (tmp == JUPITER_SOCK_EWOULDBLOCK) // Operation would block
return 0;
// Serious error; disconnect if necessary
@ -1440,12 +1440,12 @@ void Jupiter::IRC::Client::writeToLogs(const Jupiter::ReadableString &message)
void Jupiter::IRC::Client::delChannel(const Jupiter::ReadableString &in_channel)
{
m_channels.remove(in_channel);
m_channels.erase(in_channel);
}
Jupiter::IRC::Client::User *Jupiter::IRC::Client::findUser(const Jupiter::ReadableString &in_nickname) const
{
return m_users.get(in_nickname);
return getUser(in_nickname);
}
Jupiter::IRC::Client::User *Jupiter::IRC::Client::findUserOrAdd(const Jupiter::ReadableString &name)
@ -1460,9 +1460,7 @@ Jupiter::IRC::Client::User *Jupiter::IRC::Client::findUserOrAdd(const Jupiter::R
user.m_nickname = nick;
user.m_username = Jupiter::ReferenceString::getWord(name, 1, "!@");
user.m_hostname = Jupiter::ReferenceString::getWord(name, 2, "!@");
m_users.set(nick, user);
return m_users.get(nick);
return &m_users.emplace(nick, user).first->second;
}
void Jupiter::IRC::Client::addNamesToChannel(Channel &in_channel, Jupiter::ReadableString &in_names)
@ -1497,7 +1495,7 @@ void Jupiter::IRC::Client::addNamesToChannel(Channel &in_channel, Jupiter::Reada
void Jupiter::IRC::Client::addChannel(const Jupiter::ReadableString &in_channel)
{
m_channels.set(in_channel, Channel(in_channel, this));
m_channels.emplace(in_channel, Channel(in_channel, this));
}
bool Jupiter::IRC::Client::startCAP()
@ -1512,7 +1510,7 @@ bool Jupiter::IRC::Client::registerClient()
const char *localHostname = Jupiter::Socket::getLocalHostname();
Jupiter::StringS messageToSend;
messageToSend.format("USER %.*s %s %.*s :%.*s" ENDL, m_nickname.size(), m_nickname.ptr(), localHostname, m_server_hostname.size(), m_server_hostname.ptr(), m_realname.size(), m_realname.ptr());
messageToSend.format("USER %.*s %s %.*s :%.*s" ENDL, m_nickname.size(), m_nickname.ptr(), localHostname, m_server_hostname.size(), m_server_hostname.c_str(), m_realname.size(), m_realname.ptr());
if (m_socket->send(messageToSend) <= 0)
result = false;
@ -1596,8 +1594,8 @@ Jupiter::IRC::Client::Channel::User *Jupiter::IRC::Client::Channel::addUser(Jupi
++user->m_channel_count;
m_users.set(channel_user.getNickname(), channel_user);
return m_users.get(channel_user.getNickname());
m_users[channel_user.getNickname()] = channel_user;
return &m_users[channel_user.getNickname()];
}
Jupiter::IRC::Client::Channel::User *Jupiter::IRC::Client::Channel::addUser(Jupiter::IRC::Client::User *user, const char prefix)
@ -1608,18 +1606,18 @@ Jupiter::IRC::Client::Channel::User *Jupiter::IRC::Client::Channel::addUser(Jupi
++user->m_channel_count;
m_users.set(channel_user.getNickname(), channel_user);
return m_users.get(channel_user.getNickname());
m_users[channel_user.getNickname()] = channel_user;
return &m_users[channel_user.getNickname()];
}
void Jupiter::IRC::Client::Channel::delUser(const Jupiter::ReadableString &in_nickname)
{
m_users.remove(in_nickname);
m_users.erase(in_nickname);
}
void Jupiter::IRC::Client::Channel::addUserPrefix(const Jupiter::ReadableString &in_nickname, char prefix)
{
Channel::User *user = m_users.get(in_nickname);
Channel::User *user = getUser(in_nickname);
if (user != nullptr && user->m_prefixes.contains(prefix) == false)
user->m_prefixes += prefix;
@ -1627,7 +1625,7 @@ void Jupiter::IRC::Client::Channel::addUserPrefix(const Jupiter::ReadableString
void Jupiter::IRC::Client::Channel::delUserPrefix(const Jupiter::ReadableString &in_nickname, char prefix)
{
Channel::User *user = m_users.get(in_nickname);
Channel::User *user = getUser(in_nickname);
if (user != nullptr)
user->m_prefixes.remove(prefix);
@ -1640,7 +1638,12 @@ const Jupiter::ReadableString &Jupiter::IRC::Client::Channel::getName() const
Jupiter::IRC::Client::Channel::User *Jupiter::IRC::Client::Channel::getUser(const Jupiter::ReadableString &in_nickname) const
{
return m_users.get(in_nickname);
auto user = m_users.find(in_nickname);
if (user != m_users.end()) {
return const_cast<Channel::User*>(&user->second);
}
return nullptr;
}
char Jupiter::IRC::Client::Channel::getUserPrefix(const Channel::User &in_user) const
@ -1656,7 +1659,7 @@ char Jupiter::IRC::Client::Channel::getUserPrefix(const Channel::User &in_user)
char Jupiter::IRC::Client::Channel::getUserPrefix(const Jupiter::ReadableString &in_nickname) const
{
Channel::User *user = m_users.get(in_nickname);
Channel::User *user = getUser(in_nickname);
if (user != nullptr)
return this->getUserPrefix(*user);

11
src/common/Plugin.cpp

@ -18,6 +18,7 @@
#include <cstring>
#include <cstdio>
#include <string_view>
#if defined _WIN32
#include <Windows.h>
@ -28,10 +29,10 @@
#include "Plugin.h"
#include "Functions.h"
#include "ArrayList.h"
#include "CString.h"
#include "String.hpp"
using namespace Jupiter::literals;
using namespace std::literals;
#if defined _WIN32
constexpr char directory_character = '\\';
@ -63,9 +64,9 @@ dlib::~dlib()
}
#if defined _WIN32
const Jupiter::ReferenceString module_file_extension = ".dll"_jrs;
const char module_file_extension[]{ ".dll" };
#else // _WIN32
const Jupiter::ReferenceString module_file_extension = ".so"_jrs;
const char module_file_extension[]{ ".so" };
#endif // _WIN32
const Jupiter::ReferenceString config_file_extension = ".ini"_jrs;
@ -147,14 +148,14 @@ const Jupiter::ReadableString &Jupiter::Plugin::getConfigDirectory()
Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName)
{
Jupiter::CStringS file = plugins_directory + pluginName + module_file_extension;
std::string file = static_cast<std::string>(plugins_directory) + static_cast<std::string>(pluginName) + module_file_extension;
dlib *dPlug = new dlib();
// Load the library
#if defined _WIN32
dPlug->lib = LoadLibraryA(file.c_str());
#else // _WIN32
dPlug->lib = dlopen(file.c_str(), RTLD_LAZY);
dPlug->lib = dlopen(file.c_str(), RTLD_NOW);
#endif // _WIN32
if (dPlug->lib == nullptr)
{

11
src/common/SecureSocket.cpp

@ -20,7 +20,6 @@
#include <openssl/ssl.h> // OpenSSL SSL functions
#include <openssl/err.h> // OpenSSL SSL errors
#include "SecureSocket.h"
#include "CString.h"
struct Jupiter::SecureSocket::SSLData
{
@ -28,8 +27,8 @@ struct Jupiter::SecureSocket::SSLData
SSL_CTX *context = nullptr;
const SSL_METHOD *method = nullptr;
Jupiter::SecureSocket::EncryptionMethod eMethod = ANY;
Jupiter::CStringS cert;
Jupiter::CStringS key;
std::string cert;
std::string key;
~SSLData();
};
@ -178,8 +177,8 @@ bool loadCertificate(SSL_CTX *context, const char *cert, const char *key)
void Jupiter::SecureSocket::setCertificate(const Jupiter::ReadableString &cert, const Jupiter::ReadableString &key)
{
Jupiter::SecureSocket::SSLdata_->cert = cert;
Jupiter::SecureSocket::SSLdata_->key = key;
Jupiter::SecureSocket::SSLdata_->cert = static_cast<std::string>(cert);
Jupiter::SecureSocket::SSLdata_->key = static_cast<std::string>(key);
}
void Jupiter::SecureSocket::setCertificate(const Jupiter::ReadableString &pem)
@ -241,7 +240,7 @@ bool Jupiter::SecureSocket::initSSL()
ERR_print_errors_fp(stderr);
return false;
}
if (Jupiter::SecureSocket::SSLdata_->cert.isNotEmpty())
if (!Jupiter::SecureSocket::SSLdata_->cert.empty())
loadCertificate(Jupiter::SecureSocket::SSLdata_->context, Jupiter::SecureSocket::SSLdata_->cert.c_str(), Jupiter::SecureSocket::SSLdata_->key.c_str());
}

26
src/common/Socket.cpp

@ -38,7 +38,6 @@ bool socketInit = false;
#include "Socket.h"
#include "Functions.h"
#include "CString.h"
void Jupiter::Socket::Buffer::set_length(size_t in_length)
{
@ -56,8 +55,8 @@ struct Jupiter::Socket::Data
SocketType rawSock = INVALID_SOCKET;
unsigned short remote_port = 0;
unsigned short bound_port = 0;
Jupiter::CStringS remote_host;
Jupiter::CStringS bound_host;
std::string remote_host;
std::string bound_host;
int sockType = SOCK_RAW;
int sockProto = IPPROTO_RAW;
bool is_shutdown = false;
@ -162,9 +161,9 @@ bool Jupiter::Socket::connect(const char *hostname, unsigned short iPort, const
if (!socketInit && !Jupiter::Socket::init())
return false;
#endif // _WIN32
Jupiter::Socket::data_->remote_host.set(hostname);
Jupiter::Socket::data_->remote_host = hostname;
Jupiter::Socket::data_->remote_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->remote_host.c_str(), Jupiter::CStringS::Format("%hu", Jupiter::Socket::data_->remote_port).c_str());
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->remote_host.c_str(), std::to_string(Jupiter::Socket::data_->remote_port).c_str());
if (info_head != nullptr)
{
addrinfo *info = info_head;
@ -212,9 +211,9 @@ bool Jupiter::Socket::bind(const char *hostname, unsigned short iPort, bool andL
if (!socketInit && !Jupiter::Socket::init())
return false;
#endif // _WIN32
Jupiter::Socket::data_->bound_host.set(hostname);
Jupiter::Socket::data_->bound_host = hostname;
Jupiter::Socket::data_->bound_port = iPort;
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->bound_host.c_str(), Jupiter::CStringS::Format("%hu", Jupiter::Socket::data_->bound_port).c_str());
addrinfo *info_head = Jupiter::Socket::getAddrInfo(Jupiter::Socket::data_->bound_host.c_str(), std::to_string(Jupiter::Socket::data_->bound_port).c_str());
if (info_head != nullptr)
{
addrinfo *info = info_head;
@ -427,7 +426,7 @@ Jupiter::Socket *Jupiter::Socket::accept()
r->data_->rawSock = tSock;
r->data_->sockType = Jupiter::Socket::data_->sockType;
r->data_->sockProto = Jupiter::Socket::data_->sockProto;
r->data_->remote_host.set(resolved);
r->data_->remote_host = resolved;
r->data_->remote_port = static_cast<unsigned short>(Jupiter_strtoi(resolved_port, 10));
return r;
}
@ -472,7 +471,12 @@ bool Jupiter::Socket::setBlocking(bool mode)
#else // _WIN32
int flags = fcntl(Jupiter::Socket::data_->rawSock, F_GETFL, 0);
if (flags < 0) return 0;
flags = mode ? (flags|O_NONBLOCK) : (flags&~O_NONBLOCK);
if (mode) {
flags &= ~O_NONBLOCK;
}
else {
flags |= O_NONBLOCK;
}
return fcntl(Jupiter::Socket::data_->rawSock, F_SETFL, flags) == 0;
#endif // _WIN32
}
@ -488,7 +492,7 @@ bool Jupiter::Socket::getBlockingMode() const
#endif
}
const Jupiter::ReadableString &Jupiter::Socket::getRemoteHostname() const
const std::string &Jupiter::Socket::getRemoteHostname() const
{
return Jupiter::Socket::data_->remote_host;
}
@ -498,7 +502,7 @@ const char *Jupiter::Socket::getRemoteHostnameC() const
return Jupiter::Socket::data_->remote_host.c_str();
}
const Jupiter::ReadableString &Jupiter::Socket::getBoundHostname() const
const std::string &Jupiter::Socket::getBoundHostname() const
{
return Jupiter::Socket::data_->bound_host;
}

570
src/include/Jupiter/CString.h

@ -1,570 +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 _CSTRING_H_HEADER
#define _CSTRING_H_HEADER
/**
* @file CString.h
* @brief Defines the base CString_Type, as well as a series of CString 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"
/** 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 CString classes by providing a minimalist implementation (i.e: no extra variables).
*
* @param T Element type which the CString will store. Defaults to char.
*/
template<typename T = char> class CString_Type : public Shift_String_Type<T>
{
public:
/**
* @brief Returns the C-Style string behind the CString.
*
* @return C-Style string that the CString represents.
*/
const T *c_str() 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 CString.
*/
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.
*/
bool remove(const T &value);
/**
* @brief Sets the CString's contents based on the format string and input variables.
* Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t.
*
* @param format Format that the string is compared against.
* @param args Inputs to match the format specifiers.
* @return Number of characters written.
*/
size_t vformat(const T *format, va_list args);
/**
* @brief Appends to a CString's contents based on the format string and input variables.
* Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t.
*
* @param format Format that the string is compared against.
* @param args Inputs to match the format specifiers.
* @return Number of characters written.
*/
size_t avformat(const T *format, va_list args);
/**
* @brief Sets the CString's contents based on the format string and input variables.
* Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t.
*
* @param format Format that the string is compared against.
* @param ... Inputs to match the format specifiers.
* @return String containing the new format.
*/
static CString_Type Format(const T *format, ...);
/**
* @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.
*/
CString_Type<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.
*/
CString_Type<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 CString_Type<T> substring(const Jupiter::Readable_String<T> &in, size_t pos);
static CString_Type<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 CString_Type<T> substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t length);
static CString_Type<T> substring(const T *in, size_t pos, size_t length);
/**
* @brief Creates a partial copy of the string, based on a set of tokens.
*
* @param pos Position of word in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
CString_Type<T> getWord(size_t pos, const T *whitespace) const;
/**
* @brief Creates a partial copy of an input string, based on a set of tokens.
*
* @param in String to get a partial copy of.
* @param pos Position of word in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
static CString_Type<T> getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of an input string, based on a set of tokens.
*
* @param in C-Style string to get a partial copy of.
* @param pos Position of word in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
static CString_Type<T> getWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a set of tokens.
*
* @param pos Position in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
CString_Type<T> gotoWord(size_t pos, const T *whitespace) const;
/**
* @brief Creates a partial copy of the string, based on a set of tokens.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
static CString_Type<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const T &separator) const;
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &separator) const;
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const T *separator, size_t separator_size) const;
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param in String to split into tokens
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &in, const T &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size);
/**
* @brief Copies the data from the input string to the CString.
*
* @param in String containing the data to be copied.
* @return New size of the CString.
*/
size_t set(const T *in, size_t inSize) override;
size_t set(const Jupiter::Readable_String<T> &in) override;
size_t set(const std::basic_string<T> &in) override;
size_t set(const T *in) override;
size_t set(const T &in) override;
/**
* @brief Copies the data from the input string and concatenates it to the end of CString.
*
* @param in String containing the data to be concatenated.
* @return New size of the CString.
*/
size_t concat(const T *in, size_t inSize) override;
size_t concat(const Readable_String<T> &in) override;
size_t concat(const std::basic_string<T> &in) override;
size_t concat(const T *in) override;
size_t concat(const T &in) 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 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) override;
/** Default Constructor */
CString_Type();
/**
* @brief Size hint constructor.
* Note: For the CString_Type base class, this is only truly useful internally.
*
* @param size Minimum number of elements the string must be able to hold.
*/
CString_Type(size_t size);
/** Move Constructor */
CString_Type(CString_Type<T> &&source);
/** Copy Constructors */
CString_Type(const CString_Type<T> &in) : CString_Type((Readable_String<T> &)in) {}
CString_Type(const Readable_String<T> &in);
CString_Type(const std::basic_string<T> &in);
CString_Type(const T *in, size_t len);
CString_Type(const T *in);
/** Concatenation Constructors */
CString_Type(const Readable_String<T> &lhs, const T &rhs);
CString_Type(const Readable_String<T> &lhs, const Readable_String<T> &rhs);
CString_Type(const Readable_String<T> &lhs, const std::basic_string<T> &rhs);
CString_Type(const Readable_String<T> &lhs, const T *rhs);
CString_Type(const Readable_String<T> &lhs, const T *rhs, size_t rhs_size);
/** Addition Operators */
inline CString_Type<T> operator+(const T &rhs) const;
inline CString_Type<T> operator+(const CString_Type<T> &rhs) const;
inline CString_Type<T> operator+(const Readable_String<T> &rhs) const;
inline CString_Type<T> operator+(const std::basic_string<T> &rhs) const;
inline CString_Type<T> operator+(const T *rhs) const;
/** Assignment Operators */
inline CString_Type<T> &operator=(const CString_Type<T> &right) { this->set(right); return *this; };
inline CString_Type<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; };
inline CString_Type<T> &operator=(const std::basic_string<T> &right) { this->set(right); return *this; };
inline CString_Type<T> &operator=(const T *right) { this->set(right); return *this; };
inline CString_Type<T> &operator=(const T right) { this->set(right); return *this; };
static const Jupiter::CString_Type<T> empty; /** Empty instantiation of CString_Type */
protected:
/** Dummy constructor to prevent string initialization */
CString_Type(Jupiter::String_Constructor_Base &) {};
};
template<typename T = char> using CString_Strict = CString_Type<T>;
#if defined JUPITER_CSTRING_TYPE_OPERATOR_PLUS
/** String_Loose<T> Addition Operator */
template<typename T> static inline Jupiter::CString_Type<T> operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs);
#endif // JUPITER_CSTRING_TYPE_OPERATOR_PLUS
/**
* @brief Provides a "loose" CString implementation that's more optimized for repeated concatenations.
* Note: The underlying C-style string will always have a size which is a power of 2, but no fewer than 8 elements.
*
* @param T Element type which the CString will store. Defaults to char.
*/
template<typename T = char> class CString_Loose : public CString_Type<T>
{
public:
/**
* @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 Sets the CString's contents based on the format string and input variables.
* Note: Format specifiers similar to printf. Returns 0 for any type other than char and wchar_t.
*
* @param format Format that the string is compared against.
* @param ... Inputs to match the format specifiers.
* @return String containing the new format.
*/
static CString_Loose<T> Format(const T *format, ...);
/**
* @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.
*/
CString_Loose<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.
*/
CString_Loose<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 CString_Loose<T> substring(const Jupiter::Readable_String<T> &in, size_t pos);
static CString_Loose<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 CString_Loose<T> substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t length);
static CString_Loose<T> substring(const T *in, size_t pos, size_t length);
/**
* @brief Creates a partial copy of the string, based on a set of tokens.
*
* @param pos Position in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
CString_Loose<T> getWord(size_t pos, const T *whitespace) const;
/**
* @brief Creates a partial copy of an input string, based on a set of tokens.
* Useful when the input string's type isn't known.
*
* @param in String to get a partial copy of.
* @param pos Position of word in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
static CString_Loose<T> getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of an input string, based on a set of tokens.
* Useful when the input string's type isn't known.
*
* @param in C-Style string to get a partial copy of.
* @param pos Position of word in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
static CString_Loose<T> getWord(const T *in, size_t pos, const T *whitespace);
/**
* @brief Creates a partial copy of the string, based on a set of tokens.
*
* @param pos Position in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
CString_Loose<T> gotoWord(size_t pos, const T *whitespace) const;
/**
* @brief Creates a partial copy of the string, based on a set of tokens.
*
* @param in String to get a partial copy of.
* @param pos Position in the string to start copying from.
* @param whitespace A string of tokens used to deliminate words.
* @return String containing a partial copy of the original string.
*/
static CString_Loose<T> gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const T &separator);
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &separator);
typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const T *separator, size_t separator_size);
/**
* @brief Tokenizes a string, based on an input token separator
*
* @param in String to split into tokens
* @param separator Separator to split tokens by
* @return TokenizeResult containing the results of the tokenization process.
*/
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &in, const T &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator);
static typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size);
/**
* @brief Sets the internal buffer to be at least large enough to old a specified number of elements.
* Note: This does nothing if len is less than the string's current length.
*
* @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 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) override;
/** Default constructor */
CString_Loose();
/**
* @brief Size hint constructor.
*
* @param size Minimum number of elements the string must be able to hold.
*/
CString_Loose(size_t size);
/** Move Constructor */
CString_Loose(CString_Loose<T> &&source);
/** Copy Constructors */
CString_Loose(const CString_Loose<T> &in);
CString_Loose(const Readable_String<T> &in);
CString_Loose(const std::basic_string<T> &in);
CString_Loose(const T *in, size_t len);
CString_Loose(const T *in);
/** Concatenation Constructors */
CString_Loose(const Readable_String<T> &lhs, const T &rhs);
CString_Loose(const Readable_String<T> &lhs, const Readable_String<T> &rhs);
CString_Loose(const Readable_String<T> &lhs, const std::basic_string<T> &rhs);
CString_Loose(const Readable_String<T> &lhs, const T *rhs);
CString_Loose(const Readable_String<T> &lhs, const T *rhs, size_t rhs_size);
/** Addition Operators */
inline CString_Loose<T> operator+(const T &rhs) const;
inline CString_Loose<T> operator+(const CString_Loose<T> &rhs) const;
inline CString_Loose<T> operator+(const Readable_String<T> &rhs) const;
inline CString_Loose<T> operator+(const std::basic_string<T> &rhs) const;
inline CString_Loose<T> operator+(const T *rhs) const;
/** Assignment Operators */
inline CString_Loose<T> &operator=(const CString_Loose<T> &right) { this->set(right); return *this; };
inline CString_Loose<T> &operator=(const CString_Type<T> &right) { this->set(right); return *this; };
inline CString_Loose<T> &operator=(const Readable_String<T> &right) { this->set(right); return *this; };
inline CString_Loose<T> &operator=(const std::basic_string<T> &right) { this->set(right); return *this; };
inline CString_Loose<T> &operator=(const T *right) { this->set(right); return *this; };
inline CString_Loose<T> &operator=(const T right) { this->set(right); return *this; };
static const Jupiter::CString_Loose<T> empty; /** Empty instantiation of CString_Loose */
static const size_t start_size = 8; /** Starting size for loose CStrings. */
protected:
/** Dummy constructor to prevent string initialization */
CString_Loose(Jupiter::String_Constructor_Base &) {};
size_t strSize; /** Size of underlying C-string buffer */
};
#if defined JUPITER_CSTRING_LOOSE_OPERATOR_PLUS
/** String_Loose<T> Addition Operator */
template<typename T> static inline Jupiter::CString_LOOSE<T> operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs);
#endif // JUPITER_CSTRING_LOOSE_OPERATOR_PLUS
/** Definition of a Loose CString. */
typedef CString_Loose<char> CStringL;
/** Definition of a Loose Wide CString */
typedef CString_Loose<wchar_t> WCStringL;
/** Definition of a CString. */
typedef CStringL CString;
/** Definition of a Wide CString */
typedef WCStringL WCString;
/** Generic CString Type */
typedef CString_Type<char> CStringType;
/** Generic Wide CString Type */
typedef CString_Type<wchar_t> WCStringType;
/** Definition of a Strict CString. */
typedef CStringType CStringS;
/** Definition of a Strict Wide CString */
typedef WCStringType WCStringS;
namespace literals
{
/** CString_Strict literals */
inline Jupiter::CStringType operator"" _jcst(const char *str, size_t len) { return Jupiter::CStringType(str, len); }
inline Jupiter::WCStringType operator"" _jwcst(const wchar_t *str, size_t len) { return Jupiter::WCStringType(str, len); }
/** CString_Strict literals */
inline Jupiter::CStringS operator"" _jcss(const char *str, size_t len) { return Jupiter::CStringS(str, len); }
inline Jupiter::WCStringS operator"" _jwcss(const wchar_t *str, size_t len) { return Jupiter::WCStringS(str, len); }
/** CString_Loose literals */
inline Jupiter::CStringL operator"" _jcsl(const char *str, size_t len) { return Jupiter::CStringL(str, len); }
inline Jupiter::WCStringL operator"" _jwcsl(const wchar_t *str, size_t len) { return Jupiter::WCStringL(str, len); }
/** CString literals */
inline Jupiter::CStringS operator"" _jcs(const char *str, size_t len) { return Jupiter::CString(str, len); }
inline Jupiter::WCStringS operator"" _jwcs(const wchar_t *str, size_t len) { return Jupiter::WCString(str, len); }
}
}
/** Re-enable warning */
#if defined _MSC_VER
#pragma warning(pop)
#endif
/** Implementation for CString_Type and CString_Loose. Very scary. */
#include "CString_Imp.h"
#endif // _CSTRING_H_HEADER

932
src/include/Jupiter/CString_Imp.h

@ -1,932 +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 _CSTRING_IMP_H_HEADER
#define _CSTRING_IMP_H_HEADER
/**
* @file CString_Imp.h
* @brief Provides the implementations for CString_Type functions, as well as extending classes.
* Note: Modification of this file is not supported in any way.
*/
#include "Functions.h"
#include "CString.h"
#include "String.hpp"
#if !defined va_copy
#if defined __INTEL_COMPILER
#pragma message("Warning: va_copy not properly defined. Assuming common implementation.")
#define va_copy(dst, src) ((void)((dst) = (src)))
#else
#error "va_copy not defined."
#endif // __INTEL_COMPILER
#endif // va_copy
#if !defined JUPITER_VSCPRINTF
#if defined _WIN32
#define JUPITER_VSCPRINTF(format, format_args) _vscprintf(format, format_args)
#define JUPITER_VSCWPRINTF(format, format_args) _vscwprintf(format, format_args)
#else // _WIN32
#define JUPITER_VSCPRINTF(format, format_args) vsnprintf(nullptr, 0, format, format_args)
#define JUPITER_VSCWPRINTF(format, format_args) vswprintf(nullptr, 0, format, format_args)
#endif // _WIN32
#endif // JUPITER_VSCPRINTF
/**
* IMPLEMENTATION:
* CString_Type
*/
template<typename T> Jupiter::CString_Type<T>::CString_Type() : Jupiter::CString_Type<T>::CString_Type(size_t(0))
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(size_t len)
{
Jupiter::Shift_String_Type<T>::base = new T[len + 1];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
*Jupiter::String_Type<T>::str = 0;
Jupiter::String_Type<T>::length = 0;
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(Jupiter::CString_Type<T> &&source) : Jupiter::Shift_String_Type<T>(std::move(source))
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &in) : Jupiter::CString_Type<T>::CString_Type(in.ptr(), in.size())
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const std::basic_string<T> &in) : Jupiter::CString_Type<T>::CString_Type(in.data(), in.size())
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const T *in, size_t len) : Jupiter::CString_Type<T>::CString_Type(len)
{
while (Jupiter::String_Type<T>::length != len)
{
if ((Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = *in) == 0) return;
Jupiter::String_Type<T>::length++;
in++;
}
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0;
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const T *in)
{
if (in == nullptr)
{
Jupiter::String_Type<T>::length = 0;
Jupiter::Shift_String_Type<T>::base = new T[1];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
*Jupiter::String_Type<T>::str = 0;
}
else
{
Jupiter::String_Type<T>::length = Jupiter::strlen<T>(in);
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::String_Type<T>::length + 1];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str, in);
}
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const T &rhs) : CString_Type<T>(lhs.size() + 1)
{
const T *itr;
const T *end;
if (lhs.isNotEmpty())
{
itr = lhs.ptr();
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>::str = 0;
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> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) : CString_Type<T>(lhs, rhs.ptr(), rhs.size())
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) : CString_Type<T>(lhs, rhs.data(), rhs.size())
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const T *rhs) : CString_Type<T>(lhs, rhs, Jupiter::strlen<T>(rhs))
{
}
template<typename T> Jupiter::CString_Type<T>::CString_Type(const Jupiter::Readable_String<T> &lhs, const T *rhs, size_t rhs_size) : CString_Type<T>(lhs.size() + rhs_size)
{
const T *itr;
const T *end;
if (lhs.isNotEmpty())
{
itr = lhs.ptr();
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>::str = 0;
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> bool Jupiter::CString_Type<T>::setBufferSize(size_t len)
{
if (Jupiter::Shift_String_Type<T>::setBufferSize(len + 1))
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0;
return true;
}
return false;
}
template<typename T> bool Jupiter::CString_Type<T>::setBufferSizeNoCopy(size_t len)
{
bool r = Jupiter::Shift_String_Type<T>::setBufferSizeNoCopy(len + 1);
*Jupiter::String_Type<T>::str = 0;
return r;
}
template<typename T> const T *Jupiter::CString_Type<T>::c_str() const
{
return Jupiter::String_Type<T>::str;
}
template<typename T> size_t Jupiter::CString_Type<T>::truncate(size_t n)
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::truncate(n)] = 0;
return Jupiter::String_Type<T>::length;
}
template<typename T> bool Jupiter::CString_Type<T>::remove(const T &value)
{
if (Jupiter::Shift_String_Type<T>::remove(value))
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0;
return true;
}
return false;
}
// vformat()
template<> size_t inline Jupiter::CString_Type<char>::vformat(const char *format, va_list args)
{
int minLen;
va_list sargs;
va_copy(sargs, args);
minLen = JUPITER_VSCPRINTF(format, sargs);
va_end(sargs);
if (minLen < 0) return 0; // We simply can not work with this.
this->setBufferSizeNoCopy(minLen);
Jupiter::String_Type<char>::length = minLen;
vsnprintf(Jupiter::String_Type<char>::str, Jupiter::String_Type<char>::length + 1, format, args);
Jupiter::String_Type<char>::str[Jupiter::String_Type<char>::length] = 0;
return Jupiter::String_Type<char>::length;
}
template<> size_t inline Jupiter::CString_Type<wchar_t>::vformat(const wchar_t *format, va_list args)
{
int minLen;
va_list sargs;
va_copy(sargs, args);
minLen = JUPITER_VSCWPRINTF(format, sargs);
va_end(sargs);
if (minLen < 0) return 0; // We simply can not work with this.
this->setBufferSizeNoCopy(minLen);
Jupiter::String_Type<wchar_t>::length = minLen;
vswprintf(Jupiter::String_Type<wchar_t>::str, Jupiter::String_Type<wchar_t>::length, format, args);
Jupiter::String_Type<wchar_t>::str[Jupiter::String_Type<wchar_t>::length] = 0;
return Jupiter::String_Type<wchar_t>::length;
}
template<typename T> size_t Jupiter::CString_Type<T>::vformat(const T *format, va_list args)
{
return 0;
}
// avformat()
template<> size_t inline Jupiter::CString_Type<char>::avformat(const char *format, va_list args)
{
int minLen;
va_list sargs;
va_copy(sargs, args);
minLen = JUPITER_VSCPRINTF(format, sargs);
va_end(sargs);
if (minLen < 0) return 0; // We simply can not work with this.
this->setBufferSize(Jupiter::String_Type<char>::length + minLen);
minLen = vsnprintf(Jupiter::String_Type<char>::str + Jupiter::String_Type<char>::length, minLen + 1, format, args);
if (minLen <= 0) return 0;
Jupiter::String_Type<char>::length += minLen;
Jupiter::String_Type<char>::str[Jupiter::String_Type<char>::length] = 0;
return minLen;
}
template<> size_t inline Jupiter::CString_Type<wchar_t>::avformat(const wchar_t *format, va_list args)
{
int minLen;
va_list sargs;
va_copy(sargs, args);
minLen = JUPITER_VSCWPRINTF(format, sargs);
va_end(sargs);
if (minLen < 0) return 0; // We simply can not work with this.
this->setBufferSize(minLen + Jupiter::String_Type<wchar_t>::length);
minLen = vswprintf(Jupiter::String_Type<wchar_t>::str + Jupiter::String_Type<wchar_t>::length, minLen, format, args);
if (minLen <= 0) return 0;
Jupiter::String_Type<wchar_t>::length += minLen;
Jupiter::String_Type<wchar_t>::str[Jupiter::String_Type<wchar_t>::length] = 0;
return minLen;
}
template<typename T> size_t Jupiter::CString_Type<T>::avformat(const T *format, va_list args)
{
return 0;
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::Format(const T *format, ...)
{
CString_Type<T> r;
va_list args;
va_start(args, format);
r.vformat(format, args);
va_end(args);
return r;
}
// substring
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(size_t pos) const
{
return Jupiter::CString_Type<T>::substring(*this, pos);
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(size_t pos, size_t len) const
{
return Jupiter::CString_Type<T>::substring(*this, pos, len);
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos)
{
if (pos >= in.size()) return Jupiter::CString_Type<T>();
Jupiter::CString_Type<T> r = Jupiter::CString_Type<T>(in.size() - pos);
for (r.length = 0; pos + r.length != in.size() && in.get(pos + r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const T *in, size_t pos)
{
Jupiter::CString_Type<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Type>(in, pos);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len)
{
if (pos + len >= in.size()) return Jupiter::CString_Type<T>::substring(in, pos);
Jupiter::CString_Type<T> r = Jupiter::CString_Type<T>(len);
for (r.length = 0; r.length != len && in.get(pos + r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::substring(const T *in, size_t pos, size_t len)
{
Jupiter::CString_Type<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Type>(in, pos, len);
r.str[r.length] = 0;
return r;
}
// getWord
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::getWord(size_t pos, const T *whitespace) const
{
return Jupiter::CString_Type<T>::getWord(*this, pos, whitespace);
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace)
{
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Type>(in, pos, whitespace);
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::getWord(const T *in, size_t pos, const T *whitespace)
{
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Type>(in, pos, whitespace);
}
// gotoWord
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::gotoWord(size_t pos, const T *whitespace) const
{
return Jupiter::CString_Type<T>::gotoWord(*this, pos, whitespace);
}
template<typename T> Jupiter::CString_Type<T> Jupiter::CString_Type<T>::gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace)
{
return Jupiter::Readable_String<T>::template gotoWord<Jupiter::CString_Type>(in, pos, whitespace);
}
// tokenize
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const T &separator) const
{
return Jupiter::CString_Type<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &separator) const
{
return Jupiter::CString_Type<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const T *separator, size_t separator_size) const
{
return Jupiter::CString_Type<T>::tokenize(*this, separator, separator_size);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token)
{
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Type<T>>(in, token);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator)
{
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Type<T>>(in, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Type> Jupiter::CString_Type<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size)
{
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Type<T>>(in, separator, separator_size);
}
// set
template<typename T> size_t Jupiter::CString_Type<T>::set(const T *in, size_t in_size)
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::set(in, in_size)] = 0;
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::CString_Type<T>::set(const Jupiter::Readable_String<T> &in)
{
return this->set(in.ptr(), in.size());
}
template<typename T> size_t Jupiter::CString_Type<T>::set(const std::basic_string<T> &in)
{
return this->set(in.data(), in.size());
}
template<typename T> size_t Jupiter::CString_Type<T>::set(const T *in)
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::set(in)] = 0;
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::CString_Type<T>::set(const T &in)
{
if (in == 0)
{
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
*Jupiter::String_Type<T>::str = 0;
return Jupiter::String_Type<T>::length = 0;
}
this->setBufferSizeNoCopy(1);
*Jupiter::String_Type<T>::str = in;
Jupiter::String_Type<T>::str[1] = 0;
return Jupiter::String_Type<T>::length = 1;
}
// concat
template<typename T> size_t Jupiter::CString_Type<T>::concat(const T *in, size_t in_size)
{
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::concat(in, in_size)] = 0;
return Jupiter::String_Type<T>::length;
}
template<typename T> size_t Jupiter::CString_Type<T>::concat(const Jupiter::Readable_String<T> &in)
{
return this->concat(in.ptr(), in.size());
}
template<typename T> size_t Jupiter::CString_Type<T>::concat(const std::basic_string<T> &in)
{
return this->concat(in.data(), in.size());
}
template<typename T> size_t Jupiter::CString_Type<T>::concat(const T *in)
{
size_t nSize = Jupiter::String_Type<T>::length + Jupiter::strlen<T>(in);
this->setBufferSize(nSize);
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str + Jupiter::String_Type<T>::length, in);
return Jupiter::String_Type<T>::length = nSize;
}
template<typename T> size_t Jupiter::CString_Type<T>::concat(const T &in)
{
this->setBufferSize(Jupiter::String_Type<T>::length + 1);
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = in;
Jupiter::String_Type<T>::str[++Jupiter::String_Type<T>::length] = 0;
return Jupiter::String_Type<T>::length;
}
// Operators
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const T &rhs) const
{
return Jupiter::template operator+<T>(*this, rhs);
}
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const Jupiter::CString_Type<T> &rhs) const
{
return Jupiter::CString_Type<T>::operator+(reinterpret_cast<const Jupiter::Readable_String<T> &>(rhs));
}
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const Jupiter::Readable_String<T> &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const std::basic_string<T> &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::CString_Type<T> Jupiter::CString_Type<T>::operator+(const T *rhs) const
{
return Jupiter::operator+(*this, rhs);
}
#if defined JUPITER_CSTRING_TYPE_OPERATOR_PLUS
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T &rhs)
{
return Jupiter::CString_Type<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs)
{
return Jupiter::CString_Type<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs)
{
return Jupiter::CString_Type<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::CString_Type<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T *rhs)
{
return Jupiter::CString_Type<T>(lhs, rhs);
}
#endif // JUPITER_CSTRING_TYPE_OPERATOR_PLUS
template<typename T> const Jupiter::CString_Type<T> Jupiter::CString_Type<T>::empty = Jupiter::CString_Type<T>();
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::CString_Type>
{
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::CString_Type<Y> *data)
{
_Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Readable_String>::push<Y>(buffer, data);
};
template<typename Y> static Jupiter::CString_Type<Y> interpret(uint8_t *&head)
{
size_t size_ = *reinterpret_cast<size_t *>(head);
head += sizeof(size_t);
Jupiter::CString_Type<Y> r = Jupiter::CString_Type<Y>(reinterpret_cast<Y *>(head), size_);
head += size_;
return r;
}
};
/**
* IMPLEMENTATION:
* CString_Loose
*/
template<typename T> Jupiter::CString_Loose<T>::CString_Loose() : Jupiter::CString_Loose<T>::CString_Loose(Jupiter::CString_Loose<T>::start_size)
{
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(Jupiter::CString_Loose<T> &&source) : Jupiter::CString_Type<T>(std::move(source))
{
Jupiter::CString_Loose<T>::strSize = source.strSize;
source.strSize = 0;
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(size_t len) : Jupiter::CString_Type<T>::CString_Type(Jupiter::stringConstructorBase)
{
if (len < Jupiter::CString_Loose<T>::start_size) Jupiter::CString_Loose<T>::strSize = Jupiter::CString_Loose<T>::start_size;
else Jupiter::CString_Loose<T>::strSize = getPowerTwo(len + 1);
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
*Jupiter::String_Type<T>::str = 0;
Jupiter::String_Type<T>::length = 0;
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::CString_Loose<T> &in) : Jupiter::CString_Type<T>::CString_Type(Jupiter::stringConstructorBase)
{
Jupiter::CString_Loose<T>::strSize = in.strSize;
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str, in.str);
Jupiter::String_Type<T>::length = in.length;
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &in) : Jupiter::CString_Loose<T>::CString_Loose(in.ptr(), in.size())
{
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const std::basic_string<T> &in) : Jupiter::CString_Loose<T>::CString_Loose(in.data(), in.size())
{
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const T *in, size_t len) : Jupiter::CString_Loose<T>::CString_Loose(len)
{
while (Jupiter::String_Type<T>::length != len)
{
if ((Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = *in) == 0) return;
Jupiter::String_Type<T>::length++;
}
Jupiter::String_Type<T>::str[Jupiter::String_Type<T>::length] = 0;
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const T *in) : Jupiter::CString_Type<T>::CString_Type(Jupiter::stringConstructorBase)
{
if (in == nullptr)
{
Jupiter::CString_Loose<T>::strSize = Jupiter::CString_Loose<T>::start_size;
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
*Jupiter::String_Type<T>::str = 0;
Jupiter::String_Type<T>::length = 0;
}
else
{
Jupiter::String_Type<T>::length = Jupiter::strlen<T>(in);
Jupiter::CString_Loose<T>::strSize = getPowerTwo(Jupiter::String_Type<T>::length + 1);
if (Jupiter::CString_Loose<T>::strSize < Jupiter::CString_Loose<T>::start_size) Jupiter::CString_Loose<T>::strSize = Jupiter::CString_Loose<T>::start_size;
Jupiter::Shift_String_Type<T>::base = new T[Jupiter::CString_Loose<T>::strSize];
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
Jupiter::strcpy<T>(Jupiter::String_Type<T>::str, in);
}
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const T &rhs) : CString_Loose<T>(lhs.size() + 1)
{
const T *itr;
const T *end;
if (lhs.isNotEmpty())
{
itr = lhs.ptr();
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>::str = 0;
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> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs) : CString_Loose<T>(lhs, rhs.ptr(), rhs.size())
{
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs) : CString_Loose<T>(lhs, rhs.data(), rhs.size())
{
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const T *rhs) : CString_Loose<T>(lhs, rhs, Jupiter::strlen<T>(rhs))
{
}
template<typename T> Jupiter::CString_Loose<T>::CString_Loose(const Jupiter::Readable_String<T> &lhs, const T *rhs, size_t rhs_size) : CString_Loose<T>(lhs.size() + rhs_size)
{
const T *itr;
const T *end;
if (lhs.isNotEmpty())
{
itr = lhs.ptr();
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>::str = 0;
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> bool Jupiter::CString_Loose<T>::setBufferSize(size_t len)
{
size_t offset = Jupiter::String_Type<T>::str - Jupiter::Shift_String_Type<T>::base;
++len; // null term
if (len + offset > Jupiter::CString_Loose<T>::strSize)
{
if (len > Jupiter::CString_Loose<T>::strSize)
{
// Buffer is not large enough; reallocate
Jupiter::CString_Loose<T>::strSize = getPowerTwo(len);
T *ptr = new T[Jupiter::CString_Loose<T>::strSize];
for (size_t i = 0; i < Jupiter::String_Type<T>::length; i++)
ptr[i] = Jupiter::String_Type<T>::str[i];
ptr[Jupiter::String_Type<T>::length] = 0;
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;
}
// Buffer has enough space to accomodate; shift data to the left
T *read_itr = Jupiter::String_Type<T>::str;
T *read_end = read_itr + Jupiter::String_Type<T>::length;
T *write_itr = Jupiter::Shift_String_Type<T>::base;
while (read_itr != read_end)
{
*write_itr = *read_itr;
++read_itr;
++write_itr;
}
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
}
return false;
}
template<typename T> bool Jupiter::CString_Loose<T>::setBufferSizeNoCopy(size_t len)
{
len = getPowerTwo(len + 1);
if (len > Jupiter::CString_Loose<T>::strSize)
{
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;
*Jupiter::String_Type<T>::str = 0;
return true;
}
Jupiter::String_Type<T>::length = 0;
Jupiter::String_Type<T>::str = Jupiter::Shift_String_Type<T>::base;
*Jupiter::String_Type<T>::str = 0;
return false;
}
template<typename T> size_t Jupiter::CString_Loose<T>::capacity() const
{
return Jupiter::CString_Loose<T>::strSize - 1;
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::Format(const T *format, ...)
{
CString_Loose<T> r;
va_list args;
va_start(args, format);
r.vformat(format, args);
va_end(args);
return r;
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(size_t pos) const
{
return Jupiter::CString_Loose<T>::substring(*this, pos);
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(size_t pos, size_t length) const
{
return Jupiter::CString_Loose<T>::substring(*this, pos, length);
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos)
{
if (pos > in.size()) return Jupiter::CString_Loose<T>();
Jupiter::CString_Loose<T> r = Jupiter::CString_Loose<T>(in.size() - pos);
for (r.length = 0; pos + r.length != in.size() && in.get(r.length) != 0; r.length++) r.str[r.length] = in.get(pos + r.length);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const T *in, size_t pos)
{
Jupiter::CString_Loose<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Loose>(in, pos);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const Jupiter::Readable_String<T> &in, size_t pos, size_t len)
{
if (pos + len >= in.size()) return Jupiter::CString_Loose<T>::substring(in, pos);
Jupiter::CString_Loose<T> r = Jupiter::CString_Loose<T>(len);
for (r.length = 0; r.length != len && in.get(r.length + pos) != 0; r.length++) r.str[r.length] = in.get(r.length + pos);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::substring(const T *in, size_t pos, size_t len)
{
Jupiter::CString_Loose<T> r = Jupiter::String_Type<T>::template substring<Jupiter::CString_Loose>(in, pos, len);
r.str[r.length] = 0;
return r;
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::getWord(size_t pos, const T *whitespace) const
{
return Jupiter::CString_Loose<T>::getWord(*this, pos, whitespace);
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::getWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace)
{
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Loose>(in, pos, whitespace);
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::getWord(const T *in, size_t pos, const T *whitespace)
{
return Jupiter::Readable_String<T>::template getWord<Jupiter::CString_Loose>(in, pos, whitespace);
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::gotoWord(size_t pos, const T *whitespace) const
{
return Jupiter::CString_Loose<T>::gotoWord(*this, pos, whitespace);
}
template<typename T> Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::gotoWord(const Jupiter::Readable_String<T> &in, size_t pos, const T *whitespace)
{
return Jupiter::Readable_String<T>::template gotoWord<Jupiter::CString_Loose>(in, pos, whitespace);
}
// tokenize
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const T &token)
{
return Jupiter::CString_Loose<T>::tokenize(*this, token);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &separator)
{
return Jupiter::CString_Loose<T>::tokenize(*this, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const T *separator, size_t separator_size)
{
return Jupiter::CString_Loose<T>::tokenize(*this, separator, separator_size);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const T &token)
{
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Loose<T>>(in, token);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const Jupiter::Readable_String<T> &separator)
{
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Loose<T>>(in, separator);
}
template<typename T> typename Jupiter::Readable_String<T>::template TokenizeResult<Jupiter::CString_Loose> Jupiter::CString_Loose<T>::tokenize(const Jupiter::Readable_String<T> &in, const T *separator, size_t separator_size)
{
return typename Jupiter::template Readable_String<T>::template tokenize<typename Jupiter::template CString_Loose<T>>(in, separator, separator_size);
}
// Operators
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const T &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const Jupiter::CString_Loose<T> &rhs) const
{
return Jupiter::CString_Loose<T>::operator+(reinterpret_cast<const Jupiter::Readable_String<T> &>(rhs));
}
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const Jupiter::Readable_String<T> &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const std::basic_string<T> &rhs) const
{
return Jupiter::operator+(*this, rhs);
}
template<typename T> inline Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::operator+(const T *rhs) const
{
return Jupiter::operator+(*this, rhs);
}
#if defined JUPITER_CSTRING_LOOSE_OPERATOR_PLUS
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T &rhs)
{
return Jupiter::CString_Loose<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const Jupiter::Readable_String<T> &rhs)
{
return Jupiter::CString_Loose<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const std::basic_string<T> &rhs)
{
return Jupiter::CString_Loose<T>(lhs, rhs);
}
template<typename T> static inline Jupiter::CString_Loose<T> Jupiter::operator+(const Jupiter::Readable_String<T> &lhs, const T *rhs)
{
return Jupiter::CString_Loose<T>(lhs, rhs);
}
#endif // JUPITER_CSTRING_LOOSE_OPERATOR_PLUS
template<typename T> const Jupiter::CString_Loose<T> Jupiter::CString_Loose<T>::empty = Jupiter::CString_Loose<T>();
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::CString_Loose>
{
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::CString_Loose<Y> *data)
{
_Jupiter_DataBuffer_partial_specialization_impl<Jupiter::Readable_String>::push<Y>(buffer, data);
};
template<typename Y> static Jupiter::CString_Loose<Y> interpret(uint8_t *&head)
{
size_t size_ = *reinterpret_cast<size_t *>(head);
head += sizeof(size_t);
Jupiter::CString_Loose<Y> r = Jupiter::CString_Loose<Y>(reinterpret_cast<Y *>(head), size_);
head += size_;
return r;
}
};
#endif // _CSTRING_IMP_H_HEADER

41
src/include/Jupiter/Config.h

@ -24,10 +24,12 @@
* @brief Defines the Config class, which provides common functionality for Config files in differing formats.
*/
#include <unordered_map>
#include <memory>
#include "Jupiter.h"
#include "Hash_Table.h"
#include "Hash.h"
#include "Reference_String.h"
#include "CString.h"
#include "String.hpp"
/** DLL Linkage Nagging */
#if defined _MSC_VER
@ -44,7 +46,14 @@ namespace Jupiter
{
public:
/** Hash_Table type for sections */
typedef Hash_Table<StringS, Config, ReadableString> SectionHashTable;
using SectionHashTable = std::unordered_map<StringS, Config, default_hash_function>;
using ValuesHashTable = std::unordered_map<StringS, StringS, default_hash_function>;
Config() = default;
Config(const Config& in_config);
Config(Config&& in_config) = default;
Config& operator=(const Config& in_config);
Config& operator=(Config&& in_config) = default;
/**
* @brief Fetches the value of an entry.
@ -55,14 +64,6 @@ namespace Jupiter
*/
const Jupiter::ReadableString &get(const Jupiter::ReadableString &in_key, const Jupiter::ReadableString &in_default_value = Jupiter::ReferenceString::empty) const;
/**
* @brief Fetches the value of an entry
*
* @param in_key Key of the entry to fetch
* @return Pointer to the value of the entry on success, nullptr otherwise
*/
const Jupiter::ReadableString *getValue(const Jupiter::ReadableString &in_key) const;
/**
* @brief Fetches the value of an entry and interprets it as another type.
*
@ -114,7 +115,7 @@ namespace Jupiter
*
* @return Name of this section
*/
const Jupiter::ReadableString &getName() const;
const std::string &getName() const;
/**
* @brief Erases all data from this section
@ -188,14 +189,14 @@ namespace Jupiter
*
* @return Reference to m_table
*/
inline const HashTable &getTable() const { return m_table; }
inline const ValuesHashTable &getTable() const { return m_table; }
/**
* @brief Fetches a reference to this config's subsections
*
* @return Reference to m_sections
*/
inline const SectionHashTable &getSections() const { return m_sections; }
const SectionHashTable &getSections() const;
/** Subscript operator */
Config &operator[](const Jupiter::ReadableString &in_key);
@ -224,13 +225,13 @@ namespace Jupiter
virtual bool write_internal(const char *in_filename);
/** Name of this Config section. This is empty or the filename at the root level. */
Jupiter::CStringS m_name;
std::string m_name;
/** Table of entries within this section */
HashTable m_table;
ValuesHashTable m_table;
/** Table of sections within this section */
SectionHashTable m_sections;
std::unique_ptr<SectionHashTable> m_sections;
};
}
@ -238,12 +239,12 @@ namespace Jupiter
template<typename T> inline T Jupiter::Config::get(const Jupiter::ReadableString &in_key, T in_default_value) const
{
const Jupiter::ReadableString *result = m_table.get(in_key);
auto result = m_table.find(in_key);
if (result == nullptr)
if (result == m_table.end())
return in_default_value;
return static_cast<T>(*result);
return static_cast<T>(result->second);
}
/** Re-enable warnings */

10
src/include/Jupiter/Database.h

@ -24,7 +24,7 @@
* @brief Defines a database file structure.
*/
#include "CString.h"
#include "String.hpp"
namespace Jupiter
{
@ -67,7 +67,7 @@ namespace Jupiter
* @return True on success, false otherwise
*/
bool process_file(const Jupiter::ReadableString &file);
bool process_file(const Jupiter::CStringType &file);
bool process_file(const std::string &file);
bool process_file(const char *file);
bool process_file(FILE *file);
@ -83,7 +83,7 @@ namespace Jupiter
*
* @return Name of the file on the file system.
*/
const Jupiter::CStringType &getFilename() const;
const std::string &getFilename() const;
/**
* @brief Appends a DataBuffer to the end of the Database.
@ -100,7 +100,7 @@ namespace Jupiter
* @return True on success, false otherwise.
*/
static bool append(Jupiter::ReadableString &file, Jupiter::DataBuffer &data);
static bool append(Jupiter::CStringType &file, Jupiter::DataBuffer &data);
static bool append(std::string &file, Jupiter::DataBuffer &data);
static bool append(const char *file, Jupiter::DataBuffer &data);
static bool append(FILE *file, Jupiter::DataBuffer &data);
@ -112,7 +112,7 @@ namespace Jupiter
* @param header DataBuffer containing the header to write to the file
*/
static bool create_database(const Jupiter::ReadableString &file, const Jupiter::DataBuffer *header = nullptr);
static bool create_database(const Jupiter::CStringType &file, const Jupiter::DataBuffer *header = nullptr);
static bool create_database(const std::string &file, const Jupiter::DataBuffer *header = nullptr);
static bool create_database(const char *file, const Jupiter::DataBuffer *header = nullptr);
/**

2
src/include/Jupiter/File.h

@ -55,7 +55,7 @@ namespace Jupiter
*
* @return String containing the name of the first file loaded into this file.
*/
const Jupiter::ReadableString &getFileName() const;
const std::string &getFileName() const;
/**
* @brief Adds data to a file, which may consist of one or more lines.

31
src/include/Jupiter/HTTP_QueryString.h

@ -19,8 +19,8 @@
#if !defined _HTTP_QUERYSTRING_H_HEADER
#define _HTTP_QUERYSTRING_H_HEADER
#include <unordered_map>
#include "String.hpp"
#include "Hash_Table.h"
/**
* @file HTTP_QueryString.h
@ -52,7 +52,28 @@ namespace Jupiter
HTMLFormResponse() = delete;
inline HTMLFormResponse(const Jupiter::ReadableString &query_string) : HTMLFormResponse(query_string.ptr(), query_string.size()) {}
inline HTMLFormResponse(const char *ptr, size_t str_size);
Jupiter::HashTable table;
using TableType = std::unordered_map<Jupiter::StringS, Jupiter::StringS, Jupiter::default_hash_function>;
template<typename CastT>
CastT tableGetCast(const Jupiter::StringS &in_key, const CastT &in_value) const {
auto item = table.find(in_key);
if (item != table.end()) {
return static_cast<CastT>(item->second);
}
return in_value;
}
const Jupiter::ReadableString& tableGet(const Jupiter::StringS& in_key, const Jupiter::ReadableString& in_value) {
auto item = table.find(in_key);
if (item != table.end()) {
return item->second;
}
return in_value;
}
TableType table;
};
}
}
@ -164,7 +185,7 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
else if (*ptr == '&') // End of key/value, start of key
{
if (key.isNotEmpty()) // A key was already set; end of value
Jupiter::HTTP::HTMLFormResponse::table.set(key, Jupiter::ReferenceString(token_start, buf - token_start));
Jupiter::HTTP::HTMLFormResponse::table[key] = Jupiter::ReferenceString(token_start, buf - token_start);
key.erase();
++buf, ++ptr;
@ -190,13 +211,13 @@ inline Jupiter::HTTP::HTMLFormResponse::HTMLFormResponse(const char *ptr, size_t
{
key.set(token_start, ++buf - token_start);
*buf = *++ptr;
Jupiter::HTTP::HTMLFormResponse::table.set(key, Jupiter::ReferenceString(ptr, 1));
Jupiter::HTTP::HTMLFormResponse::table[key] = Jupiter::ReferenceString(ptr, 1);
}
else
*++buf = *++ptr;
if (key.isNotEmpty()) // A key was already set; end of value
Jupiter::HTTP::HTMLFormResponse::table.set(key, Jupiter::ReferenceString(token_start, buf - token_start + 1));
Jupiter::HTTP::HTMLFormResponse::table[key] = Jupiter::ReferenceString(token_start, buf - token_start + 1);
Jupiter::StringType::length = buf + 1 - str;
}

285
src/include/Jupiter/Hash_Table.h

@ -1,285 +0,0 @@
/**
* Copyright (C) 2016-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 _HASH_TABLE_H_HEADER
#define _HASH_TABLE_H_HEADER
/**
* @file Hash_Table.h
* @brief Defines a generic hash table structure
*/
#include <forward_list>
#include "String.hpp"
namespace Jupiter
{
template<typename T> inline size_t default_hash_function(const T &in);
/**
* @brief Provides a generic hash table structure
*
* @param KeyT Type the table will use for keys; must implement following: operator==, move constructor
* @param ValueT Type the table will use for values
* @param InKeyT Type the table will accept for keys (Default: KeyT)
* @param InValueT Type the table will accept for values (Default: ValueT)
* @param HashF Function to be used for generating hashes (Default: Fowler-Noll-Vo 1a)
*/
template<typename KeyT, typename ValueT, typename InKeyT = KeyT, typename InValueT = ValueT, size_t(*HashF)(const InKeyT &) = Jupiter::default_hash_function<InKeyT>> class Hash_Table
{
public:
/** Initial number of buckets to allocate; m_buckets_size is never less than INIT_SIZE. */
static constexpr const size_t INIT_SIZE = 8;
/**
* @brief Container for table entries
*/
struct Bucket
{
/**
* @brief An individual entry within the table, including its normal key and value.
*/
struct Entry
{
KeyT key;
ValueT value;
Entry(const InKeyT &in_key);
Entry(const InKeyT &in_key, const InValueT &in_value);
};
/**
* @brief Searches for an entry in the bucket and returns its value if it exists.
*
* @param in_key Key of the entry to search for
* @return Pointer to the value of the entry if it exists, nullptr otherwise
*/
const ValueT *get(const InKeyT &in_key) const;
ValueT *get(const InKeyT &in_key);
const InValueT &get(const InKeyT &in_key, const InValueT &in_value) const;
template<typename CastT> CastT getCast(const InKeyT &in_key, const CastT &in_value) const;
/**
* @brief Sets the value for an entry in the bucket
*
* @param in_key Key of the entry to set
* @param in_value Value to set in the entry
* @return True if a new entry was added, false if an entry was overwritten
*/
bool set(const InKeyT &in_key, const InValueT &in_value);
bool set(const InKeyT &in_key);
/**
* @brief Removes an entry from the table
*
* @param in_key Key of the entry to remove
* @return True if an entry was removed, false otherwise
*/
bool remove(const InKeyT &in_key);
/**
* @brief Calls a function for each Entry in the table, passing each Entry as a parameter
*
* @param CallT Function type to call
*
* @param in_callback Function to callback
*/
template<typename CallT> void callback(CallT &in_callback) const;
template<typename CallT> void callback(CallT &in_callback);
/**
* @brief Copy assignment operator
*
* @param in_bucket Bucket to copy entries from
* @return Reference to this bucket
*/
Bucket &operator=(const Bucket &in_bucket);
/**
* @brief Move assignment operator
*
* @param in_bucket Bucket to move entries from
* @return Reference to this bucket
*/
Bucket &operator=(Bucket &&in_bucket);
/**
* @brief Default constructor for the Bucket class
*/
Bucket() = default;
/**
* @brief Copy constructor for the Bucket class
*/
Bucket(const Bucket &in_bucket);
/**
* @brief Move constructor for the Bucket class
*/
Bucket(Bucket &&in_bucket);
/**
* @brief Destructor for the Bucket class
*/
~Bucket();
/** List of entries in the bucket */
std::forward_list<Entry> m_entries;
};
/**
* @brief Returns an iterator positioned at the beginning of the table
*
* @brief Iterator at beginning of m_buckets
*/
Bucket *begin() const;
/**
* @brief Returns an iterator positioned at the end of the table
*
* @return Iterator at end of m_buckets
*/
Bucket *end() const;
/**
* @brief Fetches the value of an entry based on its key
*
* @param in_key Key of the entry to search for
* @return Value of the entry if it exists, nullptr otherwise
*/
ValueT *get(const InKeyT &in_key) const;
const InValueT &get(const InKeyT &in_key, const InValueT &in_value) const;
template<typename CastT> CastT getCast(const InKeyT &in_key, const CastT &in_value) const;
/**
* @brief Sets the value for an entry in the table
*
* @param in_key Key of the entry to set
* @param in_value Value of the entry to set
* @return True if a new entry was added, false if an entry was overwritten
*/
bool set(const InKeyT &in_key, const InValueT &in_value);
bool set(const InKeyT &in_key);
/**
* @brief Removes an entry from the table
*
* @param in_key Key of the entry to remove
* @return True if an entry was removed, false otherwise
*/
bool remove(const InKeyT &in_key);
/**
* @brief Calls a function for each Entry in the table, passing each Entry as a parameter
*
* @param CallT Function type to call
*
* @param in_callback Function to callback
*/
template<typename CallT> void callback(CallT &in_callback) const;
template<typename CallT> void callback(CallT &in_callback);
/**
* @brief Returns the number of entries in the table
*
* @return Number of entries in the table
*/
size_t size() const;
/**
* @brief Erases the table's contents
*/
void erase();
/**
* @brief Shrinks the table's internal bucket pool to the current number of entries, not to be less than INIT_SIZE.
*/
void shrink();
/**
* @brief Copy assignment operator
*
* @param in_table Table to copy entries from
* @return Reference to this table
*/
Hash_Table &operator=(const Hash_Table &in_table);
/**
* @brief Move assignment operator
*
* @param in_table Table to move entries from
* @return Reference to this table
*/
Hash_Table &operator=(Hash_Table &&in_table);
/**
* @brief Default constructor for the Hash_Table class
*/
Hash_Table();
/**
* @brief Allocation constructor for the Hash_Table class
*
* @param in_buckets_size Number of buckets to initialize to
*/
Hash_Table(size_t in_buckets_size);
/**
* @brief Copy constructor for the Hash_Table class
*
* @param in_table Table to copy entries from
*/
Hash_Table(const Hash_Table &in_table);
/**
* @brief Move constructor for the Hash_Table class
*
* @param in_table Table to move entries from
*/
Hash_Table(Hash_Table &&in_table);
/**
* @brief Destructor for the Hash_Table class
*/
~Hash_Table();
private:
/**
* @brief Doubles the size of m_buckets
*/
void expand();
/**
* @brief Copies entries from m_buckets to in_buckets; used when expanding or shrinking m_buckets.
*
* @param in_buckets Array of buckets to copy entries into
* @param in_buckets_size Number of buckets in in_buckets
*/
void copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) const;
Bucket *m_buckets; /** Array of Buckets */
size_t m_buckets_size; /** Number of buckets */
size_t m_length = 0; /** Number of entries */
};
typedef Hash_Table<Jupiter::StringS, Jupiter::StringS, Jupiter::ReadableString, Jupiter::ReadableString, Jupiter::default_hash_function<Jupiter::ReadableString>> HashTable;
}
#include "Hash_Table_Imp.h"
#endif // _HASH_TABLE_H_HEADER

503
src/include/Jupiter/Hash_Table_Imp.h

@ -1,503 +0,0 @@
/**
* Copyright (C) 2016-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 _HASH_TABLE_IMP_H_HEADER
#define _HASH_TABLE_IMP_H_HEADER
/**
* @file Hash_Table_Imp.h
* @brief Provides the implementation for Hash_Table.
*/
#include "Hash_Table.h"
#include "Hash.h"
/**
* IMPLEMENTATION:
* Hash_Table
*/
/** Conditional is constant; can probably be removed when 'if constexpr' support is added to MSVC */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127)
#endif
template<typename T> inline size_t Jupiter::default_hash_function(const T &in)
{
if (sizeof(size_t) >= sizeof(uint64_t))
return static_cast<size_t>(Jupiter::fnv1a(in));
return static_cast<size_t>(Jupiter::fnv1a_32(in));
}
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif
/** Hash_Table::Bucket::Entry */
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key)
: key{ in_key }
{
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Entry::Entry(const InKeyT &in_key, const InValueT &in_value)
: key{ in_key }, value{ in_value }
{
}
/** Hash_Table::Bucket */
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
const ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key) const
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
if (node->key == in_key)
return &node->value;
return nullptr;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key)
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
if (node->key == in_key)
return &node->value;
return nullptr;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
const InValueT &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::get(const InKeyT &in_key, const InValueT &in_value) const
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
if (node->key == in_key)
return node->value;
return in_value;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
template<typename CastT>
CastT Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::getCast(const InKeyT &in_key, const CastT &in_value) const
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
if (node->key == in_key)
return static_cast<CastT>(node->value);
return in_value;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(const InKeyT &in_key, const InValueT &in_value)
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
if (node->key == in_key)
{
node->value = in_value;
return false;
}
m_entries.emplace_front(in_key, in_value);
return true;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::set(const InKeyT &in_key)
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
if (node->key == in_key)
return false;
m_entries.emplace_front(in_key);
return true;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::remove(const InKeyT &in_key)
{
auto node = m_entries.begin();
auto end = m_entries.end();
// No nodes in the bucket
if (node == end)
return false;
// Check if the head is the desired node
if (node->key == in_key)
{
m_entries.pop_front();
return true;
}
auto next_node = node;
++next_node;
// iterate through list
while (next_node != end)
{
if (next_node->key == in_key)
{
// The next node is the desired node
m_entries.erase_after(node);
return true;
}
node = next_node;
++next_node;
}
return false;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
template<typename CallT>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::callback(CallT &in_callback) const
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
in_callback(*node);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
template<typename CallT>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::callback(CallT &in_callback)
{
for (auto node = m_entries.begin(); node != m_entries.end(); ++node)
in_callback(*node);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(const Bucket &in_bucket)
{
m_entries.clear();
for (auto node = in_bucket.m_entries.begin(); node != m_entries.end(); ++node)
m_entries.emplace_front(node->key, node->value);
return *this;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::operator=(Bucket &&in_bucket)
{
m_entries = std::move(in_bucket.m_entries);
return *this;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Bucket(const Bucket &in_bucket)
{
for (auto node = in_bucket.m_entries.getHead(); node != in_bucket.m_entries.end(); ++node)
m_entries.emplace_front(node->key, node->value);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::Bucket(Bucket &&in_bucket)
{
m_entries = std::move(in_bucket.m_entries);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket::~Bucket()
{
m_entries.clear();
}
/** Hash_Table */
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::begin() const
{
return m_buckets;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Bucket *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::end() const
{
return m_buckets + m_buckets_size;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
ValueT *Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::get(const InKeyT &in_key) const
{
return m_buckets[HashF(in_key) % m_buckets_size].get(in_key);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
const InValueT &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::get(const InKeyT &in_key, const InValueT &in_value) const
{
return m_buckets[HashF(in_key) % m_buckets_size].get(in_key, in_value);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
template<typename CastT>
CastT Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::getCast(const InKeyT &in_key, const CastT &in_value) const
{
return m_buckets[HashF(in_key) % m_buckets_size].getCast(in_key, in_value);
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKeyT &in_key, const InValueT &in_value)
{
if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key, in_value))
{
if (++m_length == m_buckets_size)
expand();
return true;
}
return false;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::set(const InKeyT &in_key)
{
if (m_buckets[HashF(in_key) % m_buckets_size].set(in_key))
{
if (++m_length == m_buckets_size)
expand();
return true;
}
return false;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
bool Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::remove(const InKeyT &in_key)
{
if (m_buckets[HashF(in_key) % m_buckets_size].remove(in_key))
{
--m_length;
return true;
}
return false;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
template<typename CallT>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::callback(CallT &in_callback) const
{
Bucket *itr = m_buckets;
Bucket *end = m_buckets + m_buckets_size;
while (itr != end)
{
itr->template callback<CallT>(in_callback);
++itr;
}
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
template<typename CallT>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::callback(CallT &in_callback)
{
Bucket *itr = m_buckets;
Bucket *end = m_buckets + m_buckets_size;
while (itr != end)
{
itr->template callback<CallT>(in_callback);
++itr;
}
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
size_t Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::size() const
{
return m_length;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::erase()
{
m_length = 0;
delete[] m_buckets;
m_buckets_size = INIT_SIZE;
m_buckets = new Bucket[m_buckets_size];
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::shrink()
{
size_t buckets_size = m_length < INIT_SIZE ? INIT_SIZE : m_length;
Bucket *buckets = new Bucket[buckets_size];
copy_to_buckets(buckets, buckets_size);
delete[] m_buckets;
m_buckets = buckets;
m_buckets_size = buckets_size;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(const Hash_Table &in_table)
{
if (m_buckets_size >= in_table.m_buckets_size && m_buckets_size <= in_table.m_buckets_size * 2)
{
// We're larger than what we're copying, but not drastically (2x) larger. Just erase our current data and copy their entries.
if (m_length == 0) // we don't need to erase any data
in_table.copy_to_buckets(m_buckets, m_buckets_size);
else
{
// we need to erase data; slightly modified version of copy_to_buckets()
size_t index = 0;
while (index != in_table.m_buckets_size)
{
in_table.m_buckets[index].m_entries.clear();
for (auto node = in_table.m_buckets[index].m_entries.begin(); node != in_table.m_buckets[index].m_entries.end(); ++node)
m_buckets[HashF(node->key) % m_buckets_size].set(node->key, node->value);
++index;
}
while (index != m_buckets_size)
{
in_table.m_buckets[index].m_entries.clear();
++index;
}
}
}
else
{
// m_buckets is either too small to copy the data, or it'd be too wasteful
delete[] m_buckets;
m_buckets_size = in_table.m_buckets_size;
m_buckets = new Bucket[m_buckets_size];
for (size_t index = 0; index != m_buckets_size; ++index)
m_buckets[index] = in_table.m_buckets[index];
}
m_length = in_table.m_length;
return *this;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
typename Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF> &Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::operator=(Hash_Table &&in_table)
{
if (m_length == 0)
{
Bucket *old_buckets = m_buckets;
size_t old_buckets_size = m_buckets_size;
m_buckets = in_table.m_buckets;
m_buckets_size = in_table.m_buckets_size;
m_length = in_table.m_length;
in_table.m_buckets = old_buckets;
in_table.m_buckets_size = old_buckets_size;
}
else
{
delete[] m_buckets;
m_buckets = in_table.m_buckets;
m_buckets_size = in_table.m_buckets_size;
m_length = in_table.m_length;
in_table.m_buckets = new Bucket[1];
in_table.m_buckets_size = 1;
}
in_table.m_length = 0;
return *this;
}
/** Constructors */
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table()
{
m_buckets_size = INIT_SIZE;
m_buckets = new Bucket[m_buckets_size];
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(size_t in_buckets_size)
{
m_buckets_size = in_buckets_size;
m_buckets = new Bucket[m_buckets_size];
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(const Hash_Table &in_table)
{
m_length = in_table.m_length;
m_buckets_size = in_table.m_buckets_size;
m_buckets = new Bucket[m_buckets_size];
for (size_t index = 0; index != m_buckets_size; ++index)
m_buckets[index] = in_table.m_buckets[index];
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::Hash_Table(Hash_Table &&in_table)
{
m_buckets = in_table.m_buckets;
m_buckets_size = in_table.m_buckets_size;
m_length = in_table.m_length;
in_table.m_buckets = new Bucket[1];
in_table.m_buckets_size = 1;
in_table.m_length = 0;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::~Hash_Table()
{
delete[] m_buckets;
}
/** Hash_Table/private */
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::expand()
{
size_t buckets_size = m_buckets_size * 2;
Bucket *buckets = new Bucket[buckets_size];
copy_to_buckets(buckets, buckets_size);
delete[] m_buckets;
m_buckets = buckets;
m_buckets_size = buckets_size;
}
template<typename KeyT, typename ValueT, typename InKeyT, typename InValueT, size_t(*HashF)(const InKeyT &)>
void Jupiter::Hash_Table<KeyT, ValueT, InKeyT, InValueT, HashF>::copy_to_buckets(Bucket *in_buckets, size_t in_buckets_size) const
{
for (size_t index = 0; index != m_buckets_size; ++index)
for (auto node = m_buckets[index].m_entries.begin(); node != m_buckets[index].m_entries.end(); ++node)
in_buckets[HashF(node->key) % in_buckets_size].set(node->key, node->value);
}
#endif // _HASH_TABLE_IMP_H_HEADER

14
src/include/Jupiter/IRC_Client.h

@ -314,7 +314,7 @@ namespace Jupiter
Jupiter::StringS m_prefixes;
};
typedef Jupiter::Hash_Table<Jupiter::StringS, Channel::User, Jupiter::ReadableString> UserTableType;
using UserTableType = std::unordered_map<Jupiter::StringS, Channel::User, default_hash_function>;
/**
* @brief Returns the name of the channel.
@ -428,8 +428,8 @@ namespace Jupiter
bool m_adding_names;
}; // Jupiter::IRC::Client::Channel class
typedef Jupiter::Hash_Table<Jupiter::StringS, Client::Channel, Jupiter::ReadableString> ChannelTableType;
typedef Jupiter::Hash_Table<Jupiter::StringS, Client::User, Jupiter::ReadableString> UserTableType;
using ChannelTableType = std::unordered_map<Jupiter::StringS, Client::Channel, default_hash_function>;
using UserTableType = std::unordered_map<Jupiter::StringS, Client::User, default_hash_function>;
/**
* @brief Returns the name of the primary config section this client reads from.
@ -473,7 +473,7 @@ namespace Jupiter
*
* @return String containing a log file's name.
*/
const Jupiter::ReadableString &getLogFile() const;
const std::string &getLogFile() const;
/**
* @brief Returns the nickname prefixes supported by the connected server.
@ -516,7 +516,7 @@ namespace Jupiter
*
* @return String containing a hostname.
*/
const Jupiter::ReadableString &getServerHostname() const;
const std::string &getServerHostname() const;
/**
* @brief Returns the server's port.
@ -829,7 +829,7 @@ namespace Jupiter
private:
Jupiter::Socket *m_socket;
uint16_t m_server_port;
Jupiter::CStringS m_server_hostname;
std::string m_server_hostname;
bool m_ssl;
Jupiter::StringS m_ssl_certificate;
@ -842,7 +842,7 @@ namespace Jupiter
Jupiter::StringS m_primary_section_name;
Jupiter::Config *m_primary_section;
Jupiter::Config *m_secondary_section;
Jupiter::CStringS m_log_file_name;
std::string m_log_file_name;
Jupiter::StringS m_last_line;
Jupiter::StringS m_server_name;
Jupiter::StringS m_nickname;

2
src/include/Jupiter/Shift_String.h

@ -125,7 +125,7 @@ namespace Jupiter
virtual ~Shift_String_Type();
protected:
T *base; /** Base pointer for the underlying String's memory allocation */
T *base{ nullptr }; /** Base pointer for the underlying String's memory allocation */
};
}

6
src/include/Jupiter/Socket.h

@ -32,8 +32,10 @@
struct addrinfo;
#ifdef _WIN32
#define JUPITER_SOCK_EWOULDBLOCK 10035
struct in_addr6;
#else
#define JUPITER_SOCK_EWOULDBLOCK EWOULDBLOCK
#define in_addr6 in6_addr
struct in6_addr;
#endif
@ -294,7 +296,7 @@ namespace Jupiter
*
* @return String containing the hostname.
*/
const Jupiter::ReadableString &getRemoteHostname() const;
const std::string &getRemoteHostname() const;
const char *getRemoteHostnameC() const;
/**
@ -302,7 +304,7 @@ namespace Jupiter
*
* @return String containing the hostname.
*/
const Jupiter::ReadableString &getBoundHostname() const;
const std::string &getBoundHostname() const;
const char *getBoundHostnameC() const;
/**

19
src/include/Jupiter/String.hpp

@ -27,6 +27,7 @@
*/
#include "Shift_String.h"
#include "Hash.h"
/** Disable warning 4458 */
#if defined _MSC_VER
@ -269,11 +270,6 @@ namespace Jupiter
inline String_Strict<T> &operator=(const T right) { this->set(right); return *this; };
static const Jupiter::String_Strict<T> empty; /** Empty instantiation of String_Strict */
protected:
/** Dummy constructor to prevent string initialization */
String_Strict(Jupiter::String_Constructor_Base &) {};
};
#if defined JUPITER_STRING_STRICT_OPERATOR_PLUS
@ -549,9 +545,6 @@ namespace Jupiter
static const size_t start_size = 8; /** Starting size for loose Strings. */
protected:
/** Dummy constructor to prevent string initialization */
String_Loose(Jupiter::String_Constructor_Base &) {};
size_t strSize; /** Size of underlying string buffer */
};
@ -597,6 +590,16 @@ namespace Jupiter
inline Jupiter::StringS operator""_js(const char *str, size_t len) { return Jupiter::String(str, len); }
inline Jupiter::WStringS operator""_jws(const wchar_t *str, size_t len) { return Jupiter::WString(str, len); }
}
// Carried over from Hash_Table.h for compatibility
struct default_hash_function {
size_t operator()(const Jupiter::ReadableString& in) const {
if constexpr (sizeof(size_t) >= sizeof(uint64_t))
return static_cast<size_t>(Jupiter::fnv1a<char>(in));
return static_cast<size_t>(Jupiter::fnv1a_32<char>(in));
}
};
}
/** Re-enable warning */

2
src/include/Jupiter/String_Imp.h

@ -54,7 +54,7 @@
* String_Strict
*/
template<typename T> Jupiter::String_Strict<T>::String_Strict() : Jupiter::String_Strict<T>::String_Strict(size_t(0))
template<typename T> Jupiter::String_Strict<T>::String_Strict()
{
}

4
src/include/Jupiter/String_Type.h

@ -307,8 +307,8 @@ namespace Jupiter
virtual ~String_Type() = default;
protected:
T *str; /** Pointer for the underlying string of elements */
size_t length; /** Number of representable elements in the string */
T *str{}; /** Pointer for the underlying string of elements */
size_t length{}; /** Number of representable elements in the string */
};
/** Generic String Type */

5
src/include/Jupiter/String_Type_Imp.h

@ -796,11 +796,6 @@ template<typename T> template<template<typename> class R> R<T> Jupiter::String_T
return r;
}
namespace Jupiter
{
static struct String_Constructor_Base {} stringConstructorBase;
}
// Jupiter::DataBuffer specialization
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::String_Type>

Loading…
Cancel
Save