Browse Source

Remove ArrayList

task/remove_strings
Jessica James 3 years ago
parent
commit
3a11bda36d
  1. 52
      src/common/Command.cpp
  2. 217
      src/common/File.cpp
  3. 197
      src/common/GenericCommand.cpp
  4. 598
      src/common/HTTP_Server.cpp
  5. 93
      src/common/IRC_Client.cpp
  6. 270
      src/common/Plugin.cpp
  7. 257
      src/include/Jupiter/ArrayList.h
  8. 5
      src/include/Jupiter/Command.h
  9. 4
      src/include/Jupiter/File.h
  10. 17
      src/include/Jupiter/GenericCommand.h
  11. 20
      src/include/Jupiter/HTTP_Server.h
  12. 5
      src/include/Jupiter/Plugin.h

52
src/common/Command.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2013-2015 Jessica James.
* Copyright (C) 2013-2021 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
@ -17,55 +17,43 @@
*/
#include <cstring>
#include "ArrayList.h"
#include "Functions.h"
#include "Command.h"
#include "String.hpp"
struct Jupiter::Command::Data
{
public:
Jupiter::ArrayList<Jupiter::StringS> triggers;
struct Jupiter::Command::Data { // TODO: remove pimpl
std::vector<Jupiter::StringS> triggers;
};
Jupiter::Command::Command()
{
Jupiter::Command::data_ = new Jupiter::Command::Data();
Jupiter::Command::Command() {
m_data = new Data();
}
Jupiter::Command::Command(const Command &command)
{
Jupiter::Command::data_ = new Jupiter::Command::Data();
for (size_t i = 0; i != Jupiter::Command::data_->triggers.size(); i++)
Jupiter::Command::data_->triggers.add(new Jupiter::StringS(*command.data_->triggers.get(i)));
Jupiter::Command::Command(const Command &command) {
m_data = new Data();
//for (size_t i = 0; i != m_data->triggers.size(); i++) // triggers.size() would always be 0? this code does nothing?
// m_data->triggers.add(new Jupiter::StringS(*command.m_data->triggers.get(i)));
}
Jupiter::Command::~Command()
{
Jupiter::Command::data_->triggers.emptyAndDelete();
delete Jupiter::Command::data_;
Jupiter::Command::~Command() {
delete m_data;
}
// Command Functions
void Jupiter::Command::addTrigger(const Jupiter::ReadableString &trigger)
{
Jupiter::Command::data_->triggers.add(new Jupiter::StringS(trigger));
void Jupiter::Command::addTrigger(const Jupiter::ReadableString &trigger) {
m_data->triggers.emplace_back(trigger);
}
const Jupiter::ReadableString &Jupiter::Command::getTrigger(size_t index) const
{
return *Jupiter::Command::data_->triggers.get(index);
const Jupiter::ReadableString &Jupiter::Command::getTrigger(size_t index) const {
return m_data->triggers[index];
}
size_t Jupiter::Command::getTriggerCount() const
{
return Jupiter::Command::data_->triggers.size();
size_t Jupiter::Command::getTriggerCount() const {
return m_data->triggers.size();
}
bool Jupiter::Command::matches(const Jupiter::ReadableString &trigger) const
{
for (size_t i = 0; i != Jupiter::Command::data_->triggers.size(); i++)
if (Jupiter::Command::data_->triggers.get(i)->equalsi(trigger)) return true;
bool Jupiter::Command::matches(const Jupiter::ReadableString &in_trigger) const {
for (const auto& trigger : m_data->triggers)
if (trigger.equalsi(in_trigger)) return true;
return false;
}

217
src/common/File.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2014-2015 Jessica James.
* Copyright (C) 2014-2021 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
@ -20,19 +20,12 @@
#include <string>
#include "File.h"
#include "String.hpp"
#include "ArrayList.h"
/**
* TODO:
* Consider replacing the ArrayList of Strings with a Rope (requires a Rope implementation).
*/
#if defined _WIN32
#define stat64 _stat64
#endif
int64_t getFileSize(const char *file)
{
int64_t getFileSize(const char *file) {
struct stat64 data;
if (stat64(file, &data) == 0) return data.st_size;
return -1;
@ -46,10 +39,9 @@ const size_t defaultBufferSize = 8192;
#pragma warning(disable: 4251)
#endif
struct JUPITER_API Jupiter::File::Data
{
struct JUPITER_API Jupiter::File::Data { // TODO: remove pimpl
std::string fileName;
Jupiter::ArrayList<Jupiter::StringS> lines;
std::vector<Jupiter::StringS> lines;
Data();
Data(const Data &data);
@ -61,125 +53,119 @@ struct JUPITER_API Jupiter::File::Data
#pragma warning(pop)
#endif
Jupiter::File::Data::Data()
{
Jupiter::File::Data::Data() {
}
Jupiter::File::Data::Data(const Jupiter::File::Data &data)
{
Jupiter::File::Data::fileName = data.fileName;
Jupiter::File::Data::Data(const Jupiter::File::Data &data) {
fileName = data.fileName;
for (size_t i = 0; i != Jupiter::File::Data::lines.size(); i++)
Jupiter::File::Data::lines.add(new Jupiter::StringS(*data.lines.get(i)));
// TODO: fix or remove this
//for (size_t i = 0; i != lines.size(); i++) // lines.size() will always be 0 here; this code does nothing?
// lines.emplace_back(data.lines[i]);
}
Jupiter::File::Data::~Data()
{
Jupiter::File::Data::lines.emptyAndDelete();
Jupiter::File::Data::~Data() {
}
Jupiter::File::File()
{
Jupiter::File::data_ = new Jupiter::File::Data();
Jupiter::File::File() {
m_data = new Data();
}
Jupiter::File::File(File &&file)
{
Jupiter::File::data_ = file.data_;
file.data_ = new Jupiter::File::Data();
Jupiter::File::File(File &&file) {
m_data = file.m_data;
file.m_data = new Data();
}
Jupiter::File::File(const File &file)
{
Jupiter::File::data_ = new Jupiter::File::Data(*file.data_);
Jupiter::File::File(const File &file) {
m_data = new Data(*file.m_data);
}
Jupiter::File::~File()
{
delete Jupiter::File::data_;
Jupiter::File::~File() {
delete m_data; // TODO: remove raw delete
}
size_t Jupiter::File::getLineCount() const
{
return Jupiter::File::data_->lines.size();
size_t Jupiter::File::getLineCount() const {
return m_data->lines.size();
}
const Jupiter::ReadableString &Jupiter::File::getLine(size_t line) const
{
return *Jupiter::File::data_->lines.get(line);
const Jupiter::ReadableString &Jupiter::File::getLine(size_t line) const {
return m_data->lines[line];
}
const std::string &Jupiter::File::getFileName() const
{
return Jupiter::File::data_->fileName;
const std::string &Jupiter::File::getFileName() const {
return m_data->fileName;
}
bool Jupiter::File::addData(const Jupiter::ReadableString &data)
{
unsigned int wc = data.wordCount(ENDL);
if (wc == 0) return false;
bool Jupiter::File::addData(const Jupiter::ReadableString &data) {
unsigned int word_count = data.wordCount(ENDL);
if (word_count == 0) return false;
for (unsigned int i = 0; i < wc; i++) Jupiter::File::data_->lines.add(new Jupiter::StringS(std::move(Jupiter::StringS::getWord(data, i, ENDL))));
for (unsigned int i = 0; i < word_count; i++) {
m_data->lines.emplace_back(std::move(Jupiter::StringS::getWord(data, i, ENDL)));
}
return true;
}
bool Jupiter::File::load(const char *file)
{
bool Jupiter::File::load(const char *file) {
FILE *filePtr = fopen(file, "rb");
if (filePtr == nullptr) return false;
if (Jupiter::File::data_->fileName.empty())
Jupiter::File::data_->fileName = file;
bool r = Jupiter::File::load(filePtr);
if (filePtr == nullptr) {
return false;
}
if (m_data->fileName.empty()) {
m_data->fileName = file;
}
bool result = load(filePtr);
fclose(filePtr);
return r;
return result;
}
bool Jupiter::File::load(const Jupiter::ReadableString &file)
{
bool Jupiter::File::load(const Jupiter::ReadableString &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.empty())
Jupiter::File::data_->fileName = fileName;
bool r = Jupiter::File::load(filePtr);
if (filePtr == nullptr) {
return false;
}
if (m_data->fileName.empty()) {
m_data->fileName = fileName;
}
bool r = load(filePtr);
fclose(filePtr);
return r;
}
bool Jupiter::File::load(FILE *file)
{
bool Jupiter::File::load(FILE *file) {
Jupiter::String buffer(defaultBufferSize);
int chr;
while (true)
{
while (true) {
chr = fgetc(file);
if (chr == EOF)
{
if (buffer.isNotEmpty())
{
Jupiter::File::data_->lines.add(new Jupiter::StringS(buffer));
if (chr == EOF) {
if (buffer.isNotEmpty()) {
m_data->lines.emplace_back(buffer);
return true;
}
return Jupiter::File::data_->lines.size() != 0;
return !m_data->lines.empty();
}
if (static_cast<char>(chr) == '\r') // new line
{
// TODO: refactor this nonsense
if (static_cast<char>(chr) == '\r') { // new line
new_line_r:
Jupiter::File::data_->lines.add(new Jupiter::StringS(buffer));
m_data->lines.emplace_back(buffer);
buffer.erase();
// check for optional trailing \n
chr = fgetc(file);
switch (chr)
{
switch (chr) {
case EOF:
return true;
@ -196,19 +182,17 @@ bool Jupiter::File::load(FILE *file)
continue;
}
if (static_cast<char>(chr) == '\n') // new line
{
if (static_cast<char>(chr) == '\n') { // new line
new_line_n:
Jupiter::File::data_->lines.add(new Jupiter::StringS(buffer));
m_data->lines.emplace_back(buffer);
buffer.erase();
// check for optional trailing \r
chr = fgetc(file);
switch (chr)
{
switch (chr) {
case EOF:
return true;
@ -229,63 +213,60 @@ bool Jupiter::File::load(FILE *file)
}
}
void Jupiter::File::unload()
{
Jupiter::File::data_->fileName.clear();
Jupiter::File::data_->lines.emptyAndDelete();
void Jupiter::File::unload() {
m_data->fileName.clear();
m_data->lines.clear();
}
bool Jupiter::File::reload()
{
if (Jupiter::File::data_->fileName.empty())
bool Jupiter::File::reload() {
if (m_data->fileName.empty()) {
return false;
std::string fileName(std::move(Jupiter::File::data_->fileName));
Jupiter::File::unload();
return Jupiter::File::load(fileName.c_str());
}
std::string fileName(std::move(m_data->fileName));
unload();
return load(fileName.c_str());
}
bool Jupiter::File::reload(const char *file)
{
Jupiter::File::unload();
return Jupiter::File::load(file);
bool Jupiter::File::reload(const char *file) {
unload();
return load(file);
}
bool Jupiter::File::reload(const Jupiter::ReadableString &file)
{
Jupiter::File::unload();
return Jupiter::File::load(file);
bool Jupiter::File::reload(const Jupiter::ReadableString &file) {
unload();
return load(file);
}
bool Jupiter::File::reload(FILE *file)
{
Jupiter::File::unload();
return Jupiter::File::load(file);
bool Jupiter::File::reload(FILE *file) {
unload();
return load(file);
}
bool Jupiter::File::sync()
{
if (Jupiter::File::data_->fileName.empty())
bool Jupiter::File::sync() {
if (m_data->fileName.empty()) {
return false;
return Jupiter::File::sync(Jupiter::File::data_->fileName.c_str());
}
return sync(m_data->fileName.c_str());
}
bool Jupiter::File::sync(const char *file)
{
bool Jupiter::File::sync(const char *file) {
FILE *filePtr = fopen(file, "wb");
if (filePtr == nullptr) return false;
Jupiter::File::sync(filePtr); // Always returns true.
sync(filePtr); // Always returns true.
fclose(filePtr);
return true;
}
bool Jupiter::File::sync(const Jupiter::ReadableString &file)
{
return Jupiter::File::sync(static_cast<std::string>(file).c_str());
bool Jupiter::File::sync(const Jupiter::ReadableString &file) {
return sync(static_cast<std::string>(file).c_str());
}
bool Jupiter::File::sync(FILE *file)
{
for (size_t i = 0; i != Jupiter::File::data_->lines.size(); i++)
Jupiter::File::data_->lines.get(i)->println(file);
bool Jupiter::File::sync(FILE *file) {
for (const auto& line : m_data->lines) {
line.println(file);
}
return true;
}

197
src/common/GenericCommand.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015-2016 Jessica James.
* Copyright (C) 2015-2021 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
@ -29,96 +29,91 @@ Jupiter::GenericCommandNamespace &Jupiter::g_generic_commands = o_generic_comman
/** GenericCommand */
Jupiter::GenericCommand::GenericCommand()
{
if (&o_generic_commands != this)
Jupiter::GenericCommand::GenericCommand() {
if (&o_generic_commands != this) {
Jupiter::GenericCommand::setNamespace(o_generic_commands);
}
}
Jupiter::GenericCommand::~GenericCommand()
{
Jupiter::GenericCommand::~GenericCommand() {
// Inform the parent
if (GenericCommand::m_parent != nullptr)
if (GenericCommand::m_parent != nullptr) {
GenericCommand::m_parent->removeCommand(*this);
}
// Notify plugins
for (size_t index = 0; index != Jupiter::plugins->size(); ++index)
Jupiter::plugins->get(index)->OnGenericCommandRemove(*this);
for (auto& plugin : Jupiter::plugins) {
plugin->OnGenericCommandRemove(*this);
}
}
bool Jupiter::GenericCommand::isNamespace() const
{
bool Jupiter::GenericCommand::isNamespace() const {
return false;
}
void Jupiter::GenericCommand::setNamespace(const Jupiter::ReadableString &in_namespace)
{
if (in_namespace.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0)
void Jupiter::GenericCommand::setNamespace(const Jupiter::ReadableString &in_namespace) {
if (in_namespace.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) {
return; // We're already here
}
if (Jupiter::GenericCommand::m_parent == nullptr)
if (Jupiter::GenericCommand::m_parent == nullptr) {
return; // We have no parent to start from
}
Jupiter::GenericCommand *command = Jupiter::GenericCommand::m_parent->getCommand(in_namespace);
if (command != nullptr && command->isNamespace())
Jupiter::GenericCommand::setNamespace(*reinterpret_cast<Jupiter::GenericCommandNamespace *>(command));
Jupiter::GenericCommand::setNamespace(*static_cast<Jupiter::GenericCommandNamespace *>(command));
}
void Jupiter::GenericCommand::setNamespace(Jupiter::GenericCommandNamespace &in_namespace)
{
if (Jupiter::GenericCommand::m_parent != nullptr) // Remove from previous parent
void Jupiter::GenericCommand::setNamespace(Jupiter::GenericCommandNamespace &in_namespace) {
if (Jupiter::GenericCommand::m_parent != nullptr) { // Remove from previous parent
Jupiter::GenericCommand::m_parent->removeCommand(*this);
}
// Add to new parent
Jupiter::GenericCommand::m_parent = &in_namespace;
in_namespace.addCommand(*this);
}
Jupiter::GenericCommandNamespace *Jupiter::GenericCommand::getNamespace() const
{
return Jupiter::GenericCommand::m_parent;
Jupiter::GenericCommandNamespace *Jupiter::GenericCommand::getNamespace() const {
return m_parent;
}
/** GenericCommand::ResponseLine */
Jupiter::GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_)
{
GenericCommand::ResponseLine::response = response_;
GenericCommand::ResponseLine::type = type_;
Jupiter::GenericCommand::ResponseLine::ResponseLine(const Jupiter::ReadableString &in_response, GenericCommand::DisplayType in_type)
: response{ in_response },
type{ in_type } {
}
Jupiter::GenericCommand::ResponseLine *Jupiter::GenericCommand::ResponseLine::set(const Jupiter::ReadableString &response_, GenericCommand::DisplayType type_)
{
GenericCommand::ResponseLine::response = response_;
GenericCommand::ResponseLine::type = type_;
Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommand::ResponseLine::set(const Jupiter::ReadableString &in_response, GenericCommand::DisplayType in_type) {
response = in_response;
type = in_type;
return this;
}
/** GenericCommandNamespace */
Jupiter::GenericCommandNamespace::~GenericCommandNamespace()
{
// Murder the children
Jupiter::GenericCommandNamespace::m_commands.emptyAndDelete();
Jupiter::GenericCommandNamespace::~GenericCommandNamespace() {
}
Jupiter::GenericCommand::ResponseLine *Jupiter::GenericCommandNamespace::trigger(const Jupiter::ReadableString &in_input)
{
GenericCommand *command;
Jupiter::GenericCommand::ResponseLine* Jupiter::GenericCommandNamespace::trigger(const Jupiter::ReadableString &in_input) {
GenericCommand* command;
Jupiter::ReferenceString input(in_input);
if (input.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands
return new Jupiter::GenericCommand::ResponseLine(Jupiter::GenericCommandNamespace::m_help, Jupiter::GenericCommand::DisplayType::PrivateSuccess);
if (input.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) { // No parameters; list commands
return new Jupiter::GenericCommand::ResponseLine(m_help,Jupiter::GenericCommand::DisplayType::PrivateSuccess);
}
command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS));
if (command != nullptr)
if (command != nullptr) {
return command->trigger(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS));
}
return new Jupiter::GenericCommand::ResponseLine(Jupiter::ReferenceString::empty, Jupiter::GenericCommand::DisplayType::PrivateError);
}
const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const Jupiter::ReadableString &parameters)
{
const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const Jupiter::ReadableString &parameters) {
static Jupiter::ReferenceString not_found = "Error: Command not found"_jrs;
if (parameters.wordCount(GENERIC_COMMAND_WORD_DELIMITER_CS) == 0) // No parameters; list commands
@ -134,136 +129,110 @@ const Jupiter::ReadableString &Jupiter::GenericCommandNamespace::getHelp(const J
// Search for command
command = Jupiter::GenericCommandNamespace::getCommand(input.getWord(0, GENERIC_COMMAND_WORD_DELIMITER_CS));
if (command != nullptr)
if (command != nullptr) {
return command->getHelp(input.gotoWord(1, GENERIC_COMMAND_WORD_DELIMITER_CS));
}
// Command not found
return not_found;
}
bool Jupiter::GenericCommandNamespace::isNamespace() const
{
bool Jupiter::GenericCommandNamespace::isNamespace() const {
return true;
}
bool Jupiter::GenericCommandNamespace::isUsing() const
{
bool Jupiter::GenericCommandNamespace::isUsing() const {
return m_using;
}
void Jupiter::GenericCommandNamespace::setUsing(bool in_value)
{
void Jupiter::GenericCommandNamespace::setUsing(bool in_value) {
m_using = in_value;
if (Jupiter::GenericCommand::m_parent != nullptr)
Jupiter::GenericCommand::m_parent->updateHelp();
}
Jupiter::ArrayList<Jupiter::GenericCommand> Jupiter::GenericCommandNamespace::getCommands() const
{
Jupiter::ArrayList<Jupiter::GenericCommand> result(Jupiter::GenericCommandNamespace::m_commands.size());
Jupiter::GenericCommand *command;
size_t tmp_index;
std::vector<Jupiter::GenericCommand*> Jupiter::GenericCommandNamespace::getCommands() const {
std::vector<Jupiter::GenericCommand*> result(m_commands.size());
for (size_t command_index = 0; command_index != Jupiter::GenericCommandNamespace::m_commands.size(); ++command_index)
{
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index);
result.add(command);
for (const auto& command : m_commands) {
result.push_back(command);
if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing())
{
if (command->isNamespace() && static_cast<GenericCommandNamespace*>(command)->isUsing()) {
// Add commands from namespace
Jupiter::ArrayList<Jupiter::GenericCommand> tmp = reinterpret_cast<GenericCommandNamespace *>(command)->getCommands();
for (tmp_index = 0; tmp_index != tmp.size(); ++tmp_index)
result.add(tmp.get(tmp_index));
auto namespace_commands = static_cast<GenericCommandNamespace*>(command)->getCommands();
for (const auto& namespace_command : namespace_commands)
result.push_back(namespace_command);
}
}
return result;
}
Jupiter::GenericCommand *Jupiter::GenericCommandNamespace::getCommand(const Jupiter::ReadableString &in_command) const
{
Jupiter::GenericCommand *command;
size_t command_index, namespaces = 0;
Jupiter::GenericCommand *Jupiter::GenericCommandNamespace::getCommand(const Jupiter::ReadableString &in_command) const {
/** This is broken into 2 loops in order to insure that exact matches are ALWAYS prioritized over inexact matches */
// Search commands
for (command_index = 0; command_index != Jupiter::GenericCommandNamespace::m_commands.size(); ++command_index)
{
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index);
if (command->matches(in_command)) // Command found
for (const auto& command : m_commands) {
if (command->matches(in_command)) {// Command found
return command;
else if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing()) // Search namespace for matches
++namespaces;
}
}
// None found; check namespaces
for (command_index = 0; namespaces != 0; ++command_index)
{
command = Jupiter::GenericCommandNamespace::m_commands.get(command_index);
if (command->isNamespace() && reinterpret_cast<GenericCommandNamespace *>(command)->isUsing())
{
command = reinterpret_cast<GenericCommandNamespace *>(command)->getCommand(in_command);
if (command != nullptr) // match found
return command;
--namespaces;
for (const auto& command : m_commands) {
if (command->isNamespace() && static_cast<GenericCommandNamespace*>(command)->isUsing()) {
auto result_command = static_cast<GenericCommandNamespace*>(command)->getCommand(in_command);
if (result_command != nullptr) { // match found
return result_command;
}
}
}
return nullptr;
}
void Jupiter::GenericCommandNamespace::addCommand(Jupiter::GenericCommand &in_command)
{
if (in_command.getNamespace() != this)
void Jupiter::GenericCommandNamespace::addCommand(Jupiter::GenericCommand &in_command) {
if (in_command.getNamespace() != this) {
in_command.setNamespace(*this);
else
{
Jupiter::GenericCommandNamespace::m_commands.add(&in_command);
Jupiter::GenericCommandNamespace::m_should_update_help = true;
}
else {
m_commands.push_back(&in_command);
m_should_update_help = true;
}
}
void Jupiter::GenericCommandNamespace::removeCommand(Jupiter::GenericCommand &in_command)
{
for (size_t index = 0; index != Jupiter::GenericCommandNamespace::m_commands.size(); ++index)
if (Jupiter::GenericCommandNamespace::m_commands.get(index) == &in_command)
{
Jupiter::GenericCommandNamespace::m_commands.remove(index);
Jupiter::GenericCommandNamespace::m_should_update_help = true;
void Jupiter::GenericCommandNamespace::removeCommand(Jupiter::GenericCommand &in_command) {
for (auto itr = m_commands.begin(); itr != m_commands.end(); ++itr) {
if (*itr == &in_command) {
m_commands.erase(itr);
m_should_update_help = true;
return;
}
}
}
void Jupiter::GenericCommandNamespace::removeCommand(const Jupiter::ReadableString &in_command)
{
for (size_t index = 0; index != Jupiter::GenericCommandNamespace::m_commands.size(); ++index)
if (Jupiter::GenericCommandNamespace::m_commands.get(index)->matches(in_command))
{
Jupiter::GenericCommandNamespace::m_commands.remove(index);
Jupiter::GenericCommandNamespace::m_should_update_help = true;
for (auto itr = m_commands.begin(); itr != m_commands.end(); ++itr) {
if ((*itr)->matches(in_command)) {
m_commands.erase(itr);
m_should_update_help = true;
return;
}
}
}
void Jupiter::GenericCommandNamespace::updateHelp()
{
Jupiter::GenericCommandNamespace::m_should_update_help = false;
void Jupiter::GenericCommandNamespace::updateHelp() {
m_should_update_help = false;
Jupiter::ArrayList<Jupiter::GenericCommand> commands = Jupiter::GenericCommandNamespace::getCommands();
std::vector<Jupiter::GenericCommand*> commands = getCommands();
Jupiter::StringL tmp_help(commands.size() * 8);
for (size_t index = 0; index != commands.size(); ++index)
{
tmp_help += commands.get(index)->getTrigger();
for (const auto& command : commands) {
tmp_help += command->getTrigger();
tmp_help += ' ';
}
Jupiter::GenericCommandNamespace::m_help = tmp_help;
m_help = tmp_help;
}

598
src/common/HTTP_Server.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015-2016 Jessica James.
* Copyright (C) 2015-2021 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
@ -21,7 +21,6 @@
#include "String.hpp"
#include "Reference_String.h"
#include "TCPSocket.h"
#include "ArrayList.h"
#include "HTTP.h"
#include "HTTP_Server.h"
@ -50,131 +49,108 @@ enum HTTPVersion
// HTTP::Server::Content
Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name)
{
Jupiter::HTTP::Server::Content::Content(const Jupiter::ReadableString &in_name, Jupiter::HTTP::Server::HTTPFunction in_function) : name(in_name) {
Jupiter::HTTP::Server::Content::function = in_function;
Jupiter::HTTP::Server::Content::name_checksum = Jupiter::HTTP::Server::Content::name.calcChecksum(); // switch to calcChecksumi to make case-insensitive
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string)
{
Jupiter::ReadableString *Jupiter::HTTP::Server::Content::execute(const Jupiter::ReadableString &query_string) {
return Jupiter::HTTP::Server::Content::function(query_string);
}
// HTTP::Server::Directory
Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name)
{
Jupiter::HTTP::Server::Directory::Directory(const Jupiter::ReadableString &in_name) : name(in_name) {
name_checksum = Jupiter::HTTP::Server::Directory::name.calcChecksum();
}
Jupiter::HTTP::Server::Directory::~Directory()
{
Jupiter::HTTP::Server::Directory::directories.emptyAndDelete();
Jupiter::HTTP::Server::Directory::content.emptyAndDelete();
Jupiter::HTTP::Server::Directory::~Directory() {
}
// host/dir/content
// .hook("dir/subdir/", content)
void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, Content *in_content)
{
void Jupiter::HTTP::Server::Directory::hook(const Jupiter::ReadableString &in_name, std::unique_ptr<Content> in_content) {
Jupiter::ReferenceString in_name_ref = in_name;
in_name_ref.shiftRight(in_name_ref.span('/'));
if (in_name_ref.isEmpty()) // Hook content
Jupiter::HTTP::Server::Directory::content.add(in_content);
else
{
size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
if (index == Jupiter::INVALID_INDEX)
dir_name = in_name_ref;
else
dir_name = in_name_ref.substring(size_t{ 0 }, index);
in_name_ref.shiftRight(dir_name.size());
Jupiter::HTTP::Server::Directory *directory;
unsigned int dir_name_checksum = dir_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::directories.size();
while (index != 0)
{
directory = Jupiter::HTTP::Server::Directory::directories.get(--index);
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name))
{
directory->hook(in_name_ref, in_content);
return;
}
}
if (in_name_ref.isEmpty()) { // Hook content
content.push_back(std::move(in_content));
return;
}
// create directories
directory = new Jupiter::HTTP::Server::Directory(dir_name);
Jupiter::HTTP::Server::Directory::directories.add(directory);
size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
if (index == Jupiter::INVALID_INDEX) {
dir_name = in_name_ref;
}
else {
dir_name = in_name_ref.substring(size_t{ 0 }, index);
}
directory_add_loop:
in_name_ref.shiftRight(in_name_ref.span('/'));
if (in_name_ref.isNotEmpty())
{
// add directory
index = in_name_ref.find('/');
if (index != Jupiter::INVALID_INDEX)
{
directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref.substring(size_t{ 0 }, index)));
directory = directory->directories.get(directories.size() - 1);
in_name_ref.shiftRight(index + 1);
goto directory_add_loop;
}
directory->directories.add(new Jupiter::HTTP::Server::Directory(in_name_ref));
directory = directory->directories.get(directories.size() - 1);
in_name_ref.shiftRight(dir_name.size());
unsigned int dir_name_checksum = dir_name.calcChecksum();
index = directories.size();
for (auto& directory : directories) {
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) {
directory->hook(in_name_ref, std::move(in_content));
return;
}
}
// add content
directory->content.add(in_content);
// create directories
Directory* directory = directories.emplace_back(std::make_unique<Directory>(dir_name)).get();
directory_add_loop: // TODO: for the love of god, why why why
in_name_ref.shiftRight(in_name_ref.span('/'));
if (in_name_ref.isNotEmpty()) {
// add directory
index = in_name_ref.find('/');
if (index != Jupiter::INVALID_INDEX) {
directory->directories.push_back(std::make_unique<Directory>(in_name_ref.substring(size_t{ 0 }, index)));
directory = directory->directories[directories.size() - 1].get();
in_name_ref.shiftRight(index + 1);
goto directory_add_loop;
}
directory->directories.push_back(std::make_unique<Directory>(in_name_ref));
directory = directory->directories[directories.size() - 1].get();
}
// add content
directory->content.push_back(std::move(in_content));
}
bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name)
{
size_t index;
bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &content_name) {
Jupiter::ReferenceString in_name_ref = path;
in_name_ref.shiftRight(in_name_ref.span('/'));
unsigned int checksum;
if (in_name_ref.isEmpty()) // Remove content
{
Jupiter::HTTP::Server::Content *content_node;
if (in_name_ref.isEmpty()) { // Remove content
checksum = content_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::content.size();
while (index != 0)
{
content_node = Jupiter::HTTP::Server::Directory::content.get(--index);
if (content_node->name_checksum == checksum && content_node->name.equals(content_name))
{
delete Jupiter::HTTP::Server::Directory::content.remove(index);
for (auto itr = content.begin(); itr != content.end(); ++itr) {
auto& content_node = *itr;
if (content_node->name_checksum == checksum && content_node->name.equals(content_name)) {
content.erase(itr);
return true;
}
}
return false;
}
else // Call remove() on next directory in path
{
index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
if (index == Jupiter::INVALID_INDEX)
dir_name = in_name_ref;
else
dir_name = in_name_ref.substring(size_t{ 0 }, index);
in_name_ref.shiftRight(dir_name.size());
Jupiter::HTTP::Server::Directory *directory;
checksum = dir_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::directories.size();
while (index != 0)
{
directory = Jupiter::HTTP::Server::Directory::directories.get(--index);
if (directory->name_checksum == checksum && directory->name.equals(dir_name))
return directory->remove(in_name_ref, content_name);
// Call remove() on next directory in path
size_t index = in_name_ref.find('/');
Jupiter::ReferenceString dir_name;
if (index == Jupiter::INVALID_INDEX)
dir_name = in_name_ref;
else
dir_name = in_name_ref.substring(size_t{ 0 }, index);
in_name_ref.shiftRight(dir_name.size());
checksum = dir_name.calcChecksum();
for (auto& directory : directories) {
if (directory->name_checksum == checksum && directory->name.equals(dir_name)) {
return directory->remove(in_name_ref, content_name);
}
}
return false;
@ -182,7 +158,7 @@ bool Jupiter::HTTP::Server::Directory::remove(const Jupiter::ReadableString &pat
bool Jupiter::HTTP::Server::Directory::has(const Jupiter::ReadableString &in_name)
{
return this->find(in_name) != nullptr;
return find(in_name) != nullptr;
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jupiter::ReadableString &in_name)
@ -191,96 +167,86 @@ Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Directory::find(const Jup
in_name_ref.shiftRight(in_name_ref.span("/"_jrs));
size_t index = in_name_ref.find('/');
if (index == Jupiter::INVALID_INDEX) // Search content
{
if (index == Jupiter::INVALID_INDEX) { // Search content
unsigned int content_name_checksum = in_name_ref.calcChecksum();
index = Jupiter::HTTP::Server::Directory::content.size();
Jupiter::HTTP::Server::Content *content_itr;
while (index != 0)
{
content_itr = Jupiter::HTTP::Server::Directory::content.get(--index);
if (content_itr->name_checksum == content_name_checksum && content_itr->name.equals(in_name_ref))
return content_itr;
index = content.size();
for (auto& content_item : content) {
if (content_item->name_checksum == content_name_checksum && content_item->name.equals(in_name_ref)) {
return content_item.get();
}
}
return nullptr; // No such content
}
Jupiter::ReferenceString dir_name(in_name_ref.ptr(), index);
in_name_ref.shiftRight(dir_name.size() + 1);
Jupiter::HTTP::Server::Directory *directory;
unsigned int dir_name_checksum = dir_name.calcChecksum();
index = Jupiter::HTTP::Server::Directory::directories.size();
while (index != 0)
{
directory = Jupiter::HTTP::Server::Directory::directories.get(--index);
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name))
for (auto& directory : directories) {
if (directory->name_checksum == dir_name_checksum && directory->name.equals(dir_name)) {
return directory->find(in_name_ref);
}
}
return nullptr; // No such directory
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string)
{
Jupiter::HTTP::Server::Content *content_ptr = Jupiter::HTTP::Server::Directory::find(in_name);
Jupiter::ReadableString* Jupiter::HTTP::Server::Directory::execute(const Jupiter::ReadableString &in_name, const Jupiter::ReadableString &query_string) {
Jupiter::HTTP::Server::Content *content_ptr = find(in_name);
if (content_ptr == nullptr)
return nullptr;
return content_ptr->execute(query_string);
}
// HTTP::Server::Host
Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name)
{
Jupiter::HTTP::Server::Host::Host(const Jupiter::ReadableString &in_name) : Directory(in_name) {
name_checksum = Jupiter::HTTP::Server::Host::name.calcChecksumi();
}
// HTTPSession struct
struct HTTPSession
{
struct HTTPSession {
Jupiter::Socket sock;
Jupiter::String request;
bool keep_alive = false;
Jupiter::HTTP::Server::Host *host = nullptr;
Jupiter::HTTP::Server::Host* host = nullptr;
HTTPVersion version = HTTPVersion::HTTP_1_0;
std::chrono::steady_clock::time_point last_active = std::chrono::steady_clock::now();
HTTPSession(Jupiter::Socket &&in_sock);
HTTPSession(Jupiter::Socket&& in_sock);
~HTTPSession();
};
HTTPSession::HTTPSession(Jupiter::Socket &&in_sock) : sock(std::move(in_sock))
{
HTTPSession::HTTPSession(Jupiter::Socket&& in_sock)
: sock(std::move(in_sock)) {
}
HTTPSession::~HTTPSession()
{
HTTPSession::~HTTPSession() {
}
// Server::Data struct
struct Jupiter::HTTP::Server::Data
{
struct Jupiter::HTTP::Server::Data {
/** Data */
Jupiter::ArrayList<Jupiter::HTTP::Server::Host> hosts;
Jupiter::ArrayList<Socket> ports;
Jupiter::ArrayList<HTTPSession> sessions;
std::vector<std::unique_ptr<Jupiter::HTTP::Server::Host>> m_hosts;
std::vector<std::unique_ptr<Socket>> m_ports;
std::vector<std::unique_ptr<HTTPSession>> m_sessions;
std::chrono::milliseconds session_timeout = std::chrono::milliseconds(2000); // TODO: Config variable
std::chrono::milliseconds keep_alive_session_timeout = std::chrono::milliseconds(5000); // TODO: Config variable
size_t max_request_size = 8192; // TODO: Config variable
bool permit_keept_alive = true; // TODO: Config variable
/** Foward functions */
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, Content *in_content);
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
bool remove(const Jupiter::ReadableString &hostname);
//bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path);
bool remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
bool has(const Jupiter::ReadableString &hostname);
bool has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Jupiter::HTTP::Server::Host *find_host(const Jupiter::ReadableString &name);
Content *find(const Jupiter::ReadableString &name);
Content *find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Content* find(const Jupiter::ReadableString &name);
Content* find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
Jupiter::ReadableString *execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
@ -297,54 +263,43 @@ struct Jupiter::HTTP::Server::Data
// Data constructor
Jupiter::HTTP::Server::Data::Data()
{
Jupiter::HTTP::Server::Data::Data() {
// hosts[0] is always the "global" namespace.
Jupiter::HTTP::Server::Data::hosts.add(new Jupiter::HTTP::Server::Host(Jupiter::HTTP::Server::global_namespace));
m_hosts.push_back(std::make_unique<Host>(Jupiter::HTTP::Server::global_namespace));
}
// Data destructor
Jupiter::HTTP::Server::Data::~Data()
{
Jupiter::HTTP::Server::Data::hosts.emptyAndDelete();
Jupiter::HTTP::Server::Data::sessions.emptyAndDelete();
Jupiter::HTTP::Server::Data::ports.emptyAndDelete();
Jupiter::HTTP::Server::Data::~Data() {
}
// Data functions
void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, Content *in_content)
{
void Jupiter::HTTP::Server::Data::hook(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &in_path, std::unique_ptr<Content> in_content) {
Jupiter::ReferenceString path = in_path;
Jupiter::ReferenceString dir_name;
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname);
Jupiter::HTTP::Server::Host* host = find_host(hostname);
if (host == nullptr)
{
host = new Jupiter::HTTP::Server::Host(hostname);
Jupiter::HTTP::Server::Data::hosts.add(host);
if (host == nullptr) {
//host = new Jupiter::HTTP::Server::Host(hostname);
host = m_hosts.emplace_back(std::make_unique<Host>(hostname)).get();
// OPTIMIZE: create directory tree and return.
}
path.shiftRight(path.span('/'));
if (path.isEmpty())
host->content.add(in_content);
else
host->hook(path, in_content);
if (path.isEmpty()) {
host->content.push_back(std::move(in_content));
}
else {
host->hook(path, std::move(in_content));
}
}
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname)
{
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname) {
unsigned int name_checksum = hostname.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size();
Jupiter::HTTP::Server::Host *host;
while (index != 0)
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(hostname))
{
delete Jupiter::HTTP::Server::Data::hosts.remove(index);
for (auto host_itr = m_hosts.begin(); host_itr != m_hosts.end(); ++host_itr) {
if (name_checksum == (*host_itr)->name_checksum && (*host_itr)->name.equalsi(hostname)) {
m_hosts.erase(host_itr);
return true;
}
}
@ -352,46 +307,34 @@ bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname
}
// name: path/to/resource OR path/
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name)
{
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname);
if (host == nullptr)
bool Jupiter::HTTP::Server::Data::remove(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) {
Jupiter::HTTP::Server::Host *host = find_host(hostname);
if (host == nullptr) {
return false;
}
return host->remove(path, name);
}
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname)
{
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname) {
unsigned int name_checksum = hostname.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size();
Jupiter::HTTP::Server::Host *host;
while (index != 0)
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(hostname))
for (const auto& host : m_hosts) {
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) {
return true;
}
}
return false;
}
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name)
{
bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) {
unsigned int name_checksum = hostname.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size();
Jupiter::HTTP::Server::Host *host;
while (index != 0)
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(hostname))
{
for (const auto& host : m_hosts) {
if (name_checksum == host->name_checksum && host->name.equalsi(hostname)) {
name_checksum = name.calcChecksum(); // switch to equalsi to make case-insensitive
index = host->content.size();
Jupiter::HTTP::Server::Content *content;
while (index != 0)
{
content = host->content.get(--index);
if (name_checksum == content->name_checksum && content->name.equals(name)) // switch to equalsi to make case-insensitive
for (const auto& content : host->content) {
if (name_checksum == content->name_checksum && content->name.equals(name)) { // switch to equalsi to make case-insensitive
return true;
}
}
return false;
}
@ -399,60 +342,53 @@ bool Jupiter::HTTP::Server::Data::has(const Jupiter::ReadableString &hostname, c
return false;
}
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name)
{
Jupiter::HTTP::Server::Host *Jupiter::HTTP::Server::Data::find_host(const Jupiter::ReadableString &name) {
unsigned int name_checksum = name.calcChecksumi();
size_t index = Jupiter::HTTP::Server::Data::hosts.size();
Jupiter::HTTP::Server::Host *host;
while (index != 0)
{
host = Jupiter::HTTP::Server::Data::hosts.get(--index);
if (name_checksum == host->name_checksum && host->name.equalsi(name))
return host;
for (const auto& host : m_hosts) {
if (name_checksum == host->name_checksum && host->name.equalsi(name)) {
return host.get();
}
}
return nullptr;
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name)
{
return Jupiter::HTTP::Server::Data::hosts.get(0)->find(name);
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &name) {
return m_hosts[0]->find(name);
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name)
{
Jupiter::HTTP::Server::Host *host = Jupiter::HTTP::Server::Data::find_host(hostname);
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::Data::find(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name) {
Jupiter::HTTP::Server::Host *host = find_host(hostname);
if (host == nullptr)
return nullptr;
return host->find(name);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string)
{
Jupiter::HTTP::Server::Content *content = Jupiter::HTTP::Server::Data::find(name);
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
Jupiter::HTTP::Server::Content *content = find(name);
if (content == nullptr)
return nullptr;
return content->execute(query_string);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string)
{
Jupiter::HTTP::Server::Content *content = Jupiter::HTTP::Server::Data::find(hostname, name);
Jupiter::ReadableString *Jupiter::HTTP::Server::Data::execute(const Jupiter::ReadableString &hostname, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
Jupiter::HTTP::Server::Content *content = find(hostname, name);
if (content == nullptr)
return nullptr;
return content->execute(query_string);
}
char *html_time()
{
char* html_time() {
time_t rawtime = time(0);
char *rtime = new char[64];
strftime(rtime, 64, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime));
return rtime;
}
int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
{
int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session) {
Jupiter::ReadableString::TokenizeResult<Jupiter::Reference_String> lines = Jupiter::ReferenceString::tokenize(session.request, STRING_LITERAL_AS_REFERENCE(ENDL));
HTTPCommand command = HTTPCommand::NONE_SPECIFIED;
Content *content = nullptr;
@ -589,7 +525,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
session.request.shiftRight(get_line_offset(index));
if (session.request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // there's another full request already received
return Jupiter::HTTP::Server::Data::process_request(session);
return process_request(session);
break;
}
@ -600,12 +536,12 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
{
first_token.truncate(1); // trim trailing ':'
if (first_token.equalsi("HOST"_jrs))
session.host = Jupiter::HTTP::Server::Data::find_host(line.getWord(1, " "));
session.host = find_host(line.getWord(1, " "));
else if (first_token.equalsi("CONNECTION"_jrs))
{
Jupiter::ReferenceString connection_type = line.getWord(1, " ");
if (connection_type.equalsi("keep-alive"_jrs))
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive;
session.keep_alive = permit_keept_alive;
}
}
else // command
@ -619,7 +555,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
if (span == Jupiter::INVALID_INDEX)
{
if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string);
content = find(query_string);
else
content = session.host->find(query_string);
query_string.erase();
@ -627,7 +563,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else
{
if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span));
content = find(query_string.substring(size_t{ 0 }, span));
else
content = session.host->find(query_string.substring(size_t{ 0 }, span));
query_string.shiftRight(span + 1);
@ -640,7 +576,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else if (protocol_str.equalsi("http/1.1"_jrs))
{
session.version = HTTPVersion::HTTP_1_1;
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive;
session.keep_alive = permit_keept_alive;
}
}
else if (first_token.equals("HEAD"_jrs))
@ -652,7 +588,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
if (span == Jupiter::INVALID_INDEX)
{
if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string);
content = find(query_string);
else
content = session.host->find(query_string);
query_string.erase();
@ -660,7 +596,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else
{
if (session.host == nullptr)
content = Jupiter::HTTP::Server::Data::find(query_string.substring(size_t{ 0 }, span));
content = find(query_string.substring(size_t{ 0 }, span));
else
content = session.host->find(query_string.substring(size_t{ 0 }, span));
query_string.shiftRight(span + 1);
@ -673,7 +609,7 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
else if (protocol_str.equalsi("http/1.1"_jrs))
{
session.version = HTTPVersion::HTTP_1_1;
session.keep_alive = Jupiter::HTTP::Server::Data::permit_keept_alive;
session.keep_alive = permit_keept_alive;
}
}
else
@ -687,188 +623,172 @@ int Jupiter::HTTP::Server::Data::process_request(HTTPSession &session)
// Server constructors
Jupiter::HTTP::Server::Server()
{
Jupiter::HTTP::Server::data_ = new Jupiter::HTTP::Server::Data();
Jupiter::HTTP::Server::Server() {
m_data = new Data();
}
Jupiter::HTTP::Server::Server(Jupiter::HTTP::Server &&source)
{
Jupiter::HTTP::Server::data_ = source.data_;
source.data_ = new Jupiter::HTTP::Server::Data();
Jupiter::HTTP::Server::Server(Jupiter::HTTP::Server &&source) {
m_data = source.m_data;
source.m_data = new Data();
}
Jupiter::HTTP::Server::~Server()
{
delete Jupiter::HTTP::Server::data_;
Jupiter::HTTP::Server::~Server() {
delete m_data;
}
// Server functions
void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, Content *content)
{
return Jupiter::HTTP::Server::data_->hook(host, name, content);
void Jupiter::HTTP::Server::hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, std::unique_ptr<Content> content) {
return m_data->hook(host, name, std::move(content));
}
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host)
{
return Jupiter::HTTP::Server::data_->remove(host);
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host) {
return m_data->remove(host);
}
/*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path)
{
return Jupiter::HTTP::Server::data_->remove(host, path);
/*bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path) {
return m_data->remove(host, path);
}*/
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name)
{
return Jupiter::HTTP::Server::data_->remove(host, path, name);
bool Jupiter::HTTP::Server::remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name) {
return m_data->remove(host, path, name);
}
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host)
{
return Jupiter::HTTP::Server::data_->has(host);
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host) {
return m_data->has(host);
}
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name)
{
return Jupiter::HTTP::Server::data_->has(host, name);
bool Jupiter::HTTP::Server::has(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) {
return m_data->has(host, name);
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name)
{
return Jupiter::HTTP::Server::data_->find(name);
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &name) {
return m_data->find(name);
}
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name)
{
return Jupiter::HTTP::Server::data_->find(host, name);
Jupiter::HTTP::Server::Content *Jupiter::HTTP::Server::find(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name) {
return m_data->find(host, name);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string)
{
return Jupiter::HTTP::Server::data_->execute(name, query_string);
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
return m_data->execute(name, query_string);
}
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string)
{
return Jupiter::HTTP::Server::data_->execute(host, name, query_string);
Jupiter::ReadableString *Jupiter::HTTP::Server::execute(const Jupiter::ReadableString &host, const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string) {
return m_data->execute(host, name, query_string);
}
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port)
{
Jupiter::TCPSocket *socket = new Jupiter::TCPSocket();
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true))
{
bool Jupiter::HTTP::Server::bind(const Jupiter::ReadableString &hostname, uint16_t port) {
auto socket = std::make_unique<Jupiter::TCPSocket>();
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) {
socket->setBlocking(false);
Jupiter::HTTP::Server::data_->ports.add(socket);
m_data->m_ports.push_back(std::move(socket));
return true;
}
delete socket;
return false;
}
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port)
{
Jupiter::SecureTCPSocket *socket = new Jupiter::SecureTCPSocket();
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true))
{
Jupiter::HTTP::Server::data_->ports.add(socket);
bool Jupiter::HTTP::Server::tls_bind(const Jupiter::ReadableString &hostname, uint16_t port) {
auto socket = std::make_unique<Jupiter::SecureTCPSocket>();
if (socket->bind(static_cast<std::string>(hostname).c_str(), port, true)) {
m_data->m_ports.push_back(std::move(socket));
return true;
}
delete socket;
return false;
}
int Jupiter::HTTP::Server::think()
{
Jupiter::Socket *socket;
HTTPSession *session;
int Jupiter::HTTP::Server::think() {
// Process existing clients
size_t index = Jupiter::HTTP::Server::data_->sessions.size();
while (index != 0)
{
session = Jupiter::HTTP::Server::data_->sessions.get(--index);
if (session->sock.isShutdown())
{
if (session->sock.recv() == 0)
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
auto sessions_end = m_data->m_sessions.end();
for (auto itr = m_data->m_sessions.begin(); itr != sessions_end;) {
auto& session = *itr;
if (session->sock.isShutdown()) {
if (session->sock.recv() == 0) {
itr = m_data->m_sessions.erase(itr + 1);
continue;
}
}
else if ((std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->keep_alive_session_timeout)
|| (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + Jupiter::HTTP::Server::data_->session_timeout))
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
//session->sock.shutdown();
else if (session->sock.recv() > 0)
{
else if ((std::chrono::steady_clock::now() > session->last_active + m_data->keep_alive_session_timeout)
|| (session->keep_alive == false && std::chrono::steady_clock::now() > session->last_active + m_data->session_timeout)) {
itr = m_data->m_sessions.erase(itr + 1);
continue;
}
else if (session->sock.recv() > 0) {
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer();
if (session->request.size() + sock_buffer.size() <= Jupiter::HTTP::Server::data_->max_request_size) // accept
{
if (session->request.size() + sock_buffer.size() <= m_data->max_request_size) { // accept
session->request += sock_buffer;
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // completed request
{
if (session->request.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
session->last_active = std::chrono::steady_clock::now();
Jupiter::HTTP::Server::data_->process_request(*session);
if (session->keep_alive == false) // remove completed session
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
m_data->process_request(*session);
if (session->keep_alive == false) { // remove completed session
itr = m_data->m_sessions.erase(itr + 1);
//session->sock.shutdown();
continue;
}
// else // keep_alive: session not deleted
}
else if (session->request.size() == Jupiter::HTTP::Server::data_->max_request_size) // reject (full buffer)
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
else if (session->request.size() == m_data->max_request_size) { // reject (full buffer)
itr = m_data->m_sessions.erase(itr + 1);
continue;
}
// else // request not over: session not deleted
}
else { // reject
itr = m_data->m_sessions.erase(itr + 1);
continue;
}
else // reject
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
}
else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK)
delete Jupiter::HTTP::Server::data_->sessions.remove(index);
else if (session->sock.getLastError() != JUPITER_SOCK_EWOULDBLOCK) {
itr = m_data->m_sessions.erase(itr + 1);
continue;
}
// else // EWOULDBLOCK: session not deleted
++itr;
}
// Process incoming clients
index = Jupiter::HTTP::Server::data_->ports.size();
while (index != 0)
{
socket = Jupiter::HTTP::Server::data_->ports.get(--index);
socket = socket->accept();
if (socket != nullptr)
{
std::unique_ptr<Jupiter::Socket> socket;
for (auto& port : m_data->m_ports) {
socket.reset(socket->accept());
if (socket != nullptr) {
socket->setBlocking(false);
session = new HTTPSession(std::move(*socket));
if (session->sock.recv() > 0) // data received
{
auto session = std::make_unique<HTTPSession>(std::move(*socket));
if (session->sock.recv() > 0) { // data received
const Jupiter::ReadableString &sock_buffer = session->sock.getBuffer();
if (sock_buffer.size() < Jupiter::HTTP::Server::data_->max_request_size) // accept
{
if (sock_buffer.size() < m_data->max_request_size) { // accept
session->request = session->sock.getBuffer();
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) // completed request
{
Jupiter::HTTP::Server::data_->process_request(*session);
if (session->keep_alive) // session will live for 30 seconds.
Jupiter::HTTP::Server::data_->sessions.add(session);
else // session completed
delete session;
if (sock_buffer.find(HTTP_REQUEST_ENDING) != Jupiter::INVALID_INDEX) { // completed request
m_data->process_request(*session);
if (session->keep_alive) { // session will live for 30 seconds.
m_data->m_sessions.push_back(std::move(session));
}
// else // session completed
}
else { // store for more processing
m_data->m_sessions.push_back(std::move(session));
}
else // store for more processing
Jupiter::HTTP::Server::data_->sessions.add(session);
}
else if (sock_buffer.size() == Jupiter::HTTP::Server::data_->max_request_size)
{
if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) // reject (too large)
delete session;
else // accept (max size, completed request)
{
session->request = session->sock.getBuffer();
Jupiter::HTTP::Server::data_->process_request(*session);
if (session->keep_alive) // session will live for 30 seconds.
Jupiter::HTTP::Server::data_->sessions.add(session);
else // session completed
delete session;
else if (sock_buffer.size() == m_data->max_request_size) {
if (sock_buffer.find(HTTP_REQUEST_ENDING) == Jupiter::INVALID_INDEX) { // reject (too large)
continue;
}
// accept (max size, completed request)
session->request = session->sock.getBuffer();
m_data->process_request(*session);
if (session->keep_alive) { // session will live for 30 seconds.
m_data->m_sessions.push_back(std::move(session));
}
// else // session completed
}
else // reject (too large)
delete session;
// else // reject (too large)
}
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) { // store for more processing
m_data->m_sessions.push_back(std::move(session));
}
else if (session->sock.getLastError() == JUPITER_SOCK_EWOULDBLOCK) // store for more processing
Jupiter::HTTP::Server::data_->sessions.add(session);
}
}
return 0;

93
src/common/IRC_Client.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2013-2017 Jessica James.
* Copyright (C) 2013-2021 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
@ -805,7 +805,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
m_connection_status = 5;
m_reconnect_attempts = 0;
this->OnConnect();
for (i = 0; i < Jupiter::plugins->size(); i++) Jupiter::plugins->get(i)->OnConnect(this);
for (auto& plugin : Jupiter::plugins) {
plugin->OnConnect(this);
}
}
break;
}
@ -832,8 +834,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (command.equals("ACTION"))
{
this->OnAction(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnAction(this, chan, nick, message);
for (auto& plugin : Jupiter::plugins) {
plugin->OnAction(this, chan, nick, message);
}
}
else
{
@ -861,16 +864,18 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
response += IRCCTCP ENDL;
m_socket->send(response);
this->OnCTCP(chan, nick, command, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnCTCP(this, chan, nick, message);
for (auto& plugin : Jupiter::plugins) {
plugin->OnCTCP(this, chan, nick, message);
}
}
}
else
{
Jupiter::ReferenceString message = premessage;
this->OnChat(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnChat(this, chan, nick, message);
for (auto& plugin : Jupiter::plugins) {
plugin->OnChat(this, chan, nick, message);
}
}
}
}
@ -886,8 +891,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{
auto nick = Jupiter::ReferenceString::substring(line, 1, pos);
this->OnNotice(chan, nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnNotice(this, chan, nick, message);
for (auto& plugin : Jupiter::plugins) {
plugin->OnNotice(this, chan, nick, message);
}
}
else
{
@ -895,8 +901,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (sender.isNotEmpty())
{
this->OnServerNotice(chan, sender, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnServerNotice(this, chan, sender, message);
for (auto& plugin : Jupiter::plugins) {
plugin->OnServerNotice(this, chan, sender, message);
}
}
}
}
@ -916,8 +923,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
user->m_nickname = newnick;
this->OnNick(nick, newnick);
}
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnNick(this, nick, newnick);
for (auto& plugin : Jupiter::plugins) {
plugin->OnNick(this, nick, newnick);
}
}
else if (w2.equalsi("JOIN"))
{
@ -952,8 +960,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
this->OnJoin(chan, nick);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnJoin(this, chan, nick);
for (auto& plugin : Jupiter::plugins) {
plugin->OnJoin(this, chan, nick);
}
}
else if (w2.equalsi("PART"))
{
@ -977,9 +986,10 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
reason = Jupiter::ReferenceString::substring(line, pos + 1);
this->OnPart(chan, nick, reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnPart(this, chan, nick, reason);
for (auto& plugin : Jupiter::plugins) {
plugin->OnPart(this, chan, nick, reason);
}
if (nick.equalsi(m_nickname))
Client::delChannel(chan);
@ -1017,8 +1027,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
this->OnKick(chan, kicker, kicked, reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnKick(this, chan, kicker, kicked, reason);
for (auto& plugin : Jupiter::plugins) {
plugin->OnKick(this, chan, kicker, kicked, reason);
}
if (kicked.equalsi(m_nickname))
{
@ -1048,8 +1059,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
this->OnQuit(nick, message);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnQuit(this, nick, message);
for (auto& plugin : Jupiter::plugins) {
plugin->OnQuit(this, nick, message);
}
m_users.erase(nick);
}
@ -1060,8 +1072,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
Jupiter::ReferenceString invited = Jupiter::ReferenceString::getWord(line, 2, WHITESPACE);
Jupiter::ReferenceString chan = Jupiter::ReferenceString::substring(line, line.find(':', 1) + 1);
this->OnInvite(chan, inviter, invited);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnInvite(this, chan, inviter, invited);
for (auto& plugin : Jupiter::plugins) {
plugin->OnInvite(this, chan, inviter, invited);
}
}
else if (w2.equalsi("MODE"))
{
@ -1122,8 +1135,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
}
}
this->OnMode(chan, nick, modestring);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnMode(this, chan, nick, modestring);
for (auto& plugin : Jupiter::plugins) {
plugin->OnMode(this, chan, nick, modestring);
}
}
}
}
@ -1177,8 +1191,9 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
{
Jupiter::ReferenceString reason = Jupiter::ReferenceString::substring(line, line.find(':') + 1);
this->OnError(reason);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnError(this, reason);
for (auto& plugin : Jupiter::plugins) {
plugin->OnError(this, reason);
}
Jupiter::IRC::Client::disconnect();
}
else if (w1.equals("AUTHENTICATE"))
@ -1198,13 +1213,15 @@ int Jupiter::IRC::Client::process_line(const Jupiter::ReadableString &line)
if (numeric != 0)
{
this->OnNumeric(numeric, line);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnNumeric(this, numeric, line);
for (auto& plugin : Jupiter::plugins) {
plugin->OnNumeric(this, numeric, line);
}
}
}
this->OnRaw(line);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnRaw(this, line);
for (auto& plugin : Jupiter::plugins) {
plugin->OnRaw(this, line);
}
}
return 0;
@ -1253,8 +1270,9 @@ void Jupiter::IRC::Client::disconnect(bool stayDead)
m_socket.reset(t);
}
}
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnDisconnect(this);
for (auto& plugin : Jupiter::plugins) {
plugin->OnDisconnect(this);
}
}
void Jupiter::IRC::Client::disconnect(const Jupiter::ReadableString &message, bool stayDead)
@ -1269,8 +1287,9 @@ void Jupiter::IRC::Client::reconnect()
m_reconnect_attempts++;
bool successConnect = Jupiter::IRC::Client::connect();
this->OnReconnectAttempt(successConnect);
for (size_t i = 0; i < Jupiter::plugins->size(); i++)
Jupiter::plugins->get(i)->OnReconnectAttempt(this, successConnect);
for (auto& plugin : Jupiter::plugins) {
plugin->OnReconnectAttempt(this, successConnect);
}
}
int Jupiter::IRC::Client::think()

270
src/common/Plugin.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2014-2016 Jessica James.
* Copyright (C) 2014-2021 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
@ -27,8 +27,8 @@
#endif // _WIN32
#include "Plugin.h"
#include <memory>
#include "Functions.h"
#include "ArrayList.h"
#include "String.hpp"
using namespace Jupiter::literals;
@ -40,21 +40,25 @@ constexpr char directory_character = '\\';
constexpr char directory_character = '/';
#endif // _WIN32
struct dlib
{
Jupiter::Plugin *plugin = nullptr;
struct dlib {
dlib() = default;
// Ensure the lib handle doesn't get duplicated / prevent double free
dlib(const dlib&) = delete;
dlib(dlib&&) = delete;
dlib& operator=(const dlib&) = delete;
dlib& operator=(dlib&&) = delete;
#if defined _WIN32
HMODULE lib = nullptr;
#else // _WIN32
void *lib = nullptr;
void* lib = nullptr;
#endif // _WIN32
~dlib();
};
dlib::~dlib()
{
if (dlib::lib != nullptr)
{
dlib::~dlib() {
if (dlib::lib != nullptr) {
#if defined _WIN32
FreeLibrary(dlib::lib);
#else // _WIN32
@ -74,23 +78,19 @@ const Jupiter::ReferenceString config_file_extension = ".ini"_jrs;
Jupiter::StringS plugins_directory = "Plugins"_jrs + directory_character;
Jupiter::StringS plugin_configs_directory = "Configs"_jrs + directory_character;
Jupiter::ArrayList<Jupiter::Plugin> _plugins;
Jupiter::ArrayList<Jupiter::Plugin> *Jupiter::plugins = &_plugins;
Jupiter::ArrayList<dlib> _libList;
std::vector<Jupiter::Plugin*> g_plugins; // Array of weak pointers to plugin instances generally stored in static memory
std::vector<Jupiter::Plugin*>& Jupiter::plugins = g_plugins;
std::vector<std::unique_ptr<dlib>> g_libList;
/** Jupiter::Plugin Implementation */
Jupiter::Plugin::Plugin()
{
Jupiter::Plugin::Plugin() {
}
Jupiter::Plugin::~Plugin()
{
for (size_t index = 0; index != _plugins.size(); ++index)
{
if (_plugins.get(index) == this)
{
_plugins.remove(index);
Jupiter::Plugin::~Plugin() {
for (auto itr = g_plugins.begin(); itr != g_plugins.end(); ++itr) {
if (*itr == this) {
g_plugins.erase(itr);
break;
}
}
@ -98,58 +98,50 @@ Jupiter::Plugin::~Plugin()
// Instance Functions
bool Jupiter::Plugin::shouldRemove() const
{
return Jupiter::Plugin::_shouldRemove;
bool Jupiter::Plugin::shouldRemove() const {
return _shouldRemove;
}
const Jupiter::ReadableString &Jupiter::Plugin::getName() const
{
return Jupiter::Plugin::name;
const Jupiter::ReadableString &Jupiter::Plugin::getName() const {
return name;
}
Jupiter::Config &Jupiter::Plugin::getConfig()
{
return Jupiter::Plugin::config;
Jupiter::Config &Jupiter::Plugin::getConfig() {
return config;
}
bool Jupiter::Plugin::initialize()
{
bool Jupiter::Plugin::initialize() {
return true;
}
void Jupiter::Plugin::OnPostInitialize()
{
void Jupiter::Plugin::OnPostInitialize() {
}
// Static Functions
void Jupiter::Plugin::setDirectory(const Jupiter::ReadableString &dir)
{
if (plugins_directory.set(dir) != 0 && plugins_directory.get(plugins_directory.size() - 1) != directory_character)
void Jupiter::Plugin::setDirectory(const Jupiter::ReadableString &dir) {
if (plugins_directory.set(dir) != 0 && plugins_directory.get(plugins_directory.size() - 1) != directory_character) {
plugins_directory += directory_character;
}
}
const Jupiter::ReadableString &Jupiter::Plugin::getDirectory()
{
const Jupiter::ReadableString &Jupiter::Plugin::getDirectory() {
return plugins_directory;
}
void Jupiter::Plugin::setConfigDirectory(const Jupiter::ReadableString &dir)
{
if (plugin_configs_directory.set(dir) != 0 && plugin_configs_directory.get(plugin_configs_directory.size() - 1) != directory_character)
void Jupiter::Plugin::setConfigDirectory(const Jupiter::ReadableString &dir) {
if (plugin_configs_directory.set(dir) != 0 && plugin_configs_directory.get(plugin_configs_directory.size() - 1) != directory_character) {
plugin_configs_directory += directory_character;
}
}
const Jupiter::ReadableString &Jupiter::Plugin::getConfigDirectory()
{
const Jupiter::ReadableString &Jupiter::Plugin::getConfigDirectory() {
return plugin_configs_directory;
}
Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName)
{
Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName) {
std::string file = static_cast<std::string>(plugins_directory) + static_cast<std::string>(pluginName) + module_file_extension;
dlib *dPlug = new dlib();
std::unique_ptr<dlib> dPlug{ std::make_unique<dlib>() };
// Load the library
#if defined _WIN32
@ -157,12 +149,12 @@ Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName
#else // _WIN32
dPlug->lib = dlopen(file.c_str(), RTLD_NOW);
#endif // _WIN32
if (dPlug->lib == nullptr)
{
if (dPlug->lib == nullptr) {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (File failed to load)" ENDL, file.c_str());
goto fail;
return nullptr;
}
Plugin* weak_plugin;
{
// Get the "getPlugin" function
typedef Jupiter::Plugin *(*func_type)(void);
@ -171,24 +163,22 @@ Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName
#else // _WIN32
func_type func = (func_type)dlsym(dPlug->lib, "getPlugin");
#endif // _WIN32
if (func == nullptr)
{
if (func == nullptr) {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Invalid plugin)" ENDL, file.c_str());
goto fail;
return nullptr;
}
// Get the plugin
dPlug->plugin = func();
if (dPlug->plugin == nullptr)
{
weak_plugin = func();
if (weak_plugin == nullptr) {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to initialize)" ENDL, file.c_str());
goto fail;
return nullptr;
}
// Initialize the plugin
dPlug->plugin->name.set(pluginName);
dPlug->plugin->config.read(plugin_configs_directory + pluginName + config_file_extension);
dPlug->plugin->initialize();
weak_plugin->name.set(pluginName);
weak_plugin->config.read(plugin_configs_directory + pluginName + config_file_extension);
weak_plugin->initialize();
}
{
// Get and execute the "load" function if it exists
@ -198,85 +188,81 @@ Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName
#else // _WIN32
func_type func = (func_type)dlsym(dPlug->lib, "load");
#endif // _WIN32
if (func != nullptr && func() == false)
{
if (func != nullptr && func() == false) {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to load)" ENDL, file.c_str());
goto fail;
return nullptr;
}
}
_libList.add(dPlug);
_plugins.add(dPlug->plugin);
return dPlug->plugin;
g_libList.push_back(std::move(dPlug));
g_plugins.push_back(weak_plugin);
fail:
delete dPlug;
return nullptr;
return weak_plugin;
}
bool Jupiter::Plugin::free(size_t index)
{
if (index < _plugins.size())
{
// Do not free() the plugin; plugin gets free'd by FreeLibrary().
_plugins.remove(index);
dlib *dPlug = _libList.remove(index);
bool Jupiter::Plugin::free(size_t index) {
if (index < g_plugins.size()) {
// Do not free() the plugin; plugin gets free'd either by FreeLibrary() during static memory deallocation or unload.
g_plugins.erase(g_plugins.begin() + index);
auto dPlugItr = g_libList.begin() + index;
std::unique_ptr<dlib> dPlug = std::move(*dPlugItr);
g_libList.erase(dPlugItr);
typedef void(*func_type)(void);
#if defined _WIN32
func_type func = (func_type)GetProcAddress(dPlug->lib, "unload");
func_type unload_func = (func_type)GetProcAddress(dPlug->lib, "unload");
#else // _WIN32
func_type func = (func_type)dlsym(dPlug->lib, "unload");
func_type unload_func = (func_type)dlsym(dPlug->lib, "unload");
#endif // _WIN32
if (func != nullptr) func();
delete dPlug;
if (unload_func != nullptr) {
unload_func();
}
return true;
}
return false;
}
bool Jupiter::Plugin::free(Jupiter::Plugin *plugin)
{
if (plugin == nullptr)
bool Jupiter::Plugin::free(Jupiter::Plugin *plugin) {
if (plugin == nullptr) {
return false;
}
for (size_t index = 0; index != _plugins.size(); ++index)
if (_plugins.get(index) == plugin)
for (size_t index = 0; index != g_plugins.size(); ++index) {
if (g_plugins[index] == plugin) {
return Jupiter::Plugin::free(index);
}
}
return false;
}
bool Jupiter::Plugin::free(const Jupiter::ReadableString &pluginName)
{
if (pluginName == nullptr)
bool Jupiter::Plugin::free(const Jupiter::ReadableString &pluginName) {
if (pluginName == nullptr) {
return false;
}
for (size_t index = 0; index != _plugins.size(); ++index)
if (pluginName.matchi(_plugins.get(index)->getName()))
for (size_t index = 0; index != g_plugins.size(); ++index) {
if (pluginName.matchi(g_plugins[index]->getName())) {
return Jupiter::Plugin::free(index);
}
}
return false;
}
Jupiter::Plugin *Jupiter::Plugin::get(size_t index)
{
if (index < _plugins.size())
return _plugins.get(index);
Jupiter::Plugin *Jupiter::Plugin::get(size_t index) {
if (index < g_plugins.size()) {
return g_plugins[index];
}
return nullptr;
}
Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName)
{
Jupiter::Plugin *plugin;
for (size_t index = 0; index != _plugins.size(); ++index)
{
plugin = _plugins.get(index);
if (pluginName.matchi(plugin->getName()))
Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName) {
for (const auto& plugin : g_plugins) {
if (pluginName.matchi(plugin->getName())) {
return plugin;
}
}
return nullptr;
@ -284,124 +270,100 @@ Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName)
// Event Implementations
int Jupiter::Plugin::think()
{
int Jupiter::Plugin::think() {
return 0;
}
int Jupiter::Plugin::OnRehash()
{
Jupiter::Plugin::config.reload();
int Jupiter::Plugin::OnRehash() {
config.reload();
return 0;
}
bool Jupiter::Plugin::OnBadRehash(bool removed)
{
Jupiter::Plugin::_shouldRemove = removed;
bool Jupiter::Plugin::OnBadRehash(bool removed) {
_shouldRemove = removed;
return false;
}
// Event Placeholders
void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *)
{
void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *) {
return;
}
void Jupiter::Plugin::OnDisconnect(Jupiter::IRC::Client *)
{
void Jupiter::Plugin::OnDisconnect(Jupiter::IRC::Client *) {
return;
}
void Jupiter::Plugin::OnReconnectAttempt(Jupiter::IRC::Client *, bool)
{
void Jupiter::Plugin::OnReconnectAttempt(Jupiter::IRC::Client *, bool) {
return;
}
void Jupiter::Plugin::OnRaw(Jupiter::IRC::Client *, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnRaw(Jupiter::IRC::Client *, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnNumeric(Jupiter::IRC::Client *, long int, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnNumeric(Jupiter::IRC::Client *, long int, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnError(Jupiter::IRC::Client *, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnError(Jupiter::IRC::Client *, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnChat(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnChat(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnServerNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnServerNotice(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnCTCP(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnCTCP(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnAction(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnAction(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnInvite(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnInvite(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnJoin(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnJoin(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnPart(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnPart(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnNick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnNick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnKick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnKick(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnQuit(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnQuit(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnMode(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &)
{
void Jupiter::Plugin::OnMode(Jupiter::IRC::Client *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, const Jupiter::ReadableString &) {
return;
}
void Jupiter::Plugin::OnThink(Jupiter::IRC::Client *)
{
void Jupiter::Plugin::OnThink(Jupiter::IRC::Client *) {
return;
}
void Jupiter::Plugin::OnGenericCommandAdd(Jupiter::GenericCommand &)
{
void Jupiter::Plugin::OnGenericCommandAdd(Jupiter::GenericCommand &) {
}
void Jupiter::Plugin::OnGenericCommandRemove(Jupiter::GenericCommand &)
{
void Jupiter::Plugin::OnGenericCommandRemove(Jupiter::GenericCommand &) {
}

257
src/include/Jupiter/ArrayList.h

@ -1,257 +0,0 @@
/**
* Copyright (C) 2013-2016 Jessica James.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Written by Jessica James <jessica.aj@outlook.com>
*/
#if !defined _ARRAYLIST_H_HEADER
#define _ARRAYLIST_H_HEADER
/**
* @file ArrayList.h
* @brief Provides an array-based list implementation using the List interface.
*/
#include "Jupiter.h"
#include "DataBuffer.h"
namespace Jupiter
{
/**
* @brief Provides an array-based list implementation using the List interface.
*/
template<typename T> class ArrayList
{
public:
/**
* @brief Gets the data at a specified index.
*
* @param index Index of the data to get.
* @return Data stored at the specified index.
*/
T *get(size_t index) const;
/**
* @brief Removes the data at a specified index from the list, and returns the removed data.
*
* @param n Index of the node to remove.
* @return Data removed.
*/
T *remove(size_t index);
/**
* @brief Removes the last element in the list, and returns the data removed.
*
* @return Data removed.
*/
T *pop();
/**
* @brief Adds data to the list at a specified index.
*
* @param data Data to add to the list.
* @param index Position in the list to add the data to.
*/
void add(T *data, size_t index);
/**
* @brief Adds data to the end of the list.
*
* @param data Data to add to the list.
*/
void add(T *data);
/**
* @brief Returns the size of the list.
*
* @return Number of nodes in the list.
*/
size_t size() const { return m_length; };
/**
* @brief Empties the ArrayList of all elements.
*/
void empty();
/**
* @brief Remove and deletes all elements within the ArrayList.
*/
void emptyAndDelete();
/**
* @brief Default constructor for the ArrayList class.
*/
ArrayList();
/**
* @brief Initializes the ArrayList's underlying array to a specified size.
*/
ArrayList(size_t length);
/**
* @brief Copy constructor for the ArrayList class.
*/
ArrayList(const ArrayList<T> &);
/**
* @brief Move constructor for the ArrayList class.
*/
ArrayList(ArrayList<T> &&);
/**
* @brief Destructor for the ArrayList class.
* Note: This does not delete data added to the list.
*/
~ArrayList();
/** Initial size constant */
static const size_t start_size = 8;
/** Access Operator */
inline T *operator[](size_t index) { return this->get(index); };
/** Private members */
private:
T **data;
size_t dataSize;
size_t m_length;
size_t expandArray();
};
}
// Implementation
template<typename T> size_t Jupiter::ArrayList<T>::expandArray()
{
T **tmp = new T *[Jupiter::ArrayList<T>::dataSize * 2];
for (size_t i = 0; i < Jupiter::ArrayList<T>::dataSize; i++)
tmp[i] = data[i];
delete[] Jupiter::ArrayList<T>::data;
Jupiter::ArrayList<T>::data = tmp;
Jupiter::ArrayList<T>::dataSize *= 2;
return Jupiter::ArrayList<T>::dataSize;
}
template<typename T> Jupiter::ArrayList<T>::ArrayList() : ArrayList(Jupiter::ArrayList<T>::start_size)
{
}
template<typename T> Jupiter::ArrayList<T>::ArrayList(size_t length_)
{
Jupiter::ArrayList<T>::dataSize = length_;
Jupiter::ArrayList<T>::data = new T*[Jupiter::ArrayList<T>::dataSize];
m_length = 0;
}
template<typename T> Jupiter::ArrayList<T>::ArrayList(const Jupiter::ArrayList<T> &source)
{
Jupiter::ArrayList<T>::dataSize = source.dataSize;
Jupiter::ArrayList<T>::data = new T*[Jupiter::ArrayList<T>::dataSize];
m_length = 0;
while (m_length != source.m_length)
{
Jupiter::ArrayList<T>::data[m_length] = source.data[m_length];
++m_length;
}
}
template<typename T> Jupiter::ArrayList<T>::ArrayList(ArrayList<T> &&source)
{
Jupiter::ArrayList<T>::dataSize = source.dataSize;
Jupiter::ArrayList<T>::data = source.data;
m_length = source.m_length;
source.dataSize = Jupiter::ArrayList<T>::start_size;
source.data = new T*[source.dataSize];
source.m_length = 0;
}
template<typename T> Jupiter::ArrayList<T>::~ArrayList()
{
delete[] Jupiter::ArrayList<T>::data;
}
template<typename T> T *Jupiter::ArrayList<T>::get(size_t index) const
{
return Jupiter::ArrayList<T>::data[index];
}
template<typename T> T *Jupiter::ArrayList<T>::remove(size_t index)
{
T *r = Jupiter::ArrayList<T>::data[index];
Jupiter::ArrayList<T>::data[index] = nullptr;
for (size_t i = index + 1; i < m_length; i++)
Jupiter::ArrayList<T>::data[i - 1] = Jupiter::ArrayList<T>::data[i];
--m_length;
return r;
}
template<typename T> T *Jupiter::ArrayList<T>::pop()
{
return Jupiter::ArrayList<T>::data[--m_length];
}
template<typename T> void Jupiter::ArrayList<T>::add(T *ndata, size_t index)
{
if (m_length == Jupiter::ArrayList<T>::dataSize) Jupiter::ArrayList<T>::expandArray();
for (size_t i = m_length; i > index; i--)
Jupiter::ArrayList<T>::data[i] = Jupiter::ArrayList<T>::data[i - 1];
Jupiter::ArrayList<T>::data[index] = ndata;
++m_length;
}
template<typename T> void Jupiter::ArrayList<T>::add(T *ndata)
{
Jupiter::ArrayList<T>::add(ndata, m_length);
}
template<typename T> void Jupiter::ArrayList<T>::empty()
{
m_length = 0;
}
template<typename T> void Jupiter::ArrayList<T>::emptyAndDelete()
{
while (m_length != 0)
delete Jupiter::ArrayList<T>::data[--m_length];
}
template<> struct _Jupiter_DataBuffer_partial_specialization_impl<Jupiter::ArrayList>
{
template<typename Y> static void push(Jupiter::DataBuffer *buffer, const Jupiter::ArrayList<Y> *data)
{
buffer->push<size_t>(data->size());
for (size_t index = 0; index != data->size(); index++)
buffer->push<Y>(*data->get(index));
};
template<typename Y> static Jupiter::ArrayList<Y> interpret(uint8_t *&head)
{
size_t size_ = *reinterpret_cast<size_t *>(head);
head += sizeof(size_t);
Jupiter::ArrayList<Y> r = Jupiter::ArrayList<Y>(size_);
while (size_-- != 0)
r.add(Jupiter::DataBuffer::interpret_data<Y>(head));
return r;
}
};
#endif // _ARRAYLIST_H_HEADER

5
src/include/Jupiter/Command.h

@ -1,5 +1,5 @@
/**
* Copyright (C) 2013-2015 Jessica James.
* Copyright (C) 2013-2021 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
@ -25,7 +25,6 @@
*/
#include "Jupiter.h"
#include "ArrayList.h"
#include "Reference_String.h"
namespace Jupiter
@ -94,7 +93,7 @@ namespace Jupiter
/** Private members */
private:
struct Data;
Data *data_;
Data *m_data;
};
}

4
src/include/Jupiter/File.h

@ -1,5 +1,5 @@
/**
* Copyright (C) 2014-2015 Jessica James.
* Copyright (C) 2014-2021 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
@ -158,7 +158,7 @@ namespace Jupiter
/** Private members */
private:
struct Data;
Data *data_;
Data *m_data;
};
}

17
src/include/Jupiter/GenericCommand.h

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015-2016 Jessica James.
* Copyright (C) 2015-2021 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
@ -24,9 +24,9 @@
* @brief Provides an extendable command system.
*/
#include <memory>
#include "Command.h"
#include "String.hpp"
#include "ArrayList.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
@ -41,8 +41,9 @@ namespace Jupiter
/**
* @brief Provides the base for generic commands.
*/
class JUPITER_API GenericCommand : public Jupiter::Command
{
class JUPITER_API GenericCommand : public Jupiter::Command, public std::enable_shared_from_this<GenericCommand> {
// Note: only needs shared_from_this because of the horrendous way this was originally written before shared_ptr
// This isn't worth improving since it should be replaced eventually
public:
/** Enumerated class to guide output in generic command interpreters */
enum class DisplayType
@ -138,7 +139,7 @@ namespace Jupiter
bool isUsing() const;
void setUsing(bool in_value);
Jupiter::ArrayList<GenericCommand> getCommands() const; // differs from m_commands in that it checks if it's using a namespace
std::vector<GenericCommand*> getCommands() const; // differs from m_commands in that it checks if it's using a namespace
GenericCommand *getCommand(const Jupiter::ReadableString &in_command) const;
void addCommand(GenericCommand &in_command);
@ -151,7 +152,7 @@ namespace Jupiter
protected:
bool m_using;
Jupiter::ArrayList<GenericCommand> m_commands;
std::vector<GenericCommand*> m_commands;
private:
bool m_should_update_help = true;
@ -183,8 +184,8 @@ class CLASS : public Jupiter::GenericCommand { \
class CLASS ## _Init : public CLASS { \
public: \
CLASS ## _Init() { \
for (size_t index = 0; index != Jupiter::plugins->size(); ++index) \
Jupiter::plugins->get(index)->OnGenericCommandAdd(*this); \
for (auto& plugin : Jupiter::plugins) \
plugin->OnGenericCommandAdd(*this); \
} }; \
CLASS ## _Init CLASS ## _instance = CLASS ## _Init (); \
CLASS & CLASS :: instance = CLASS ## _instance;

20
src/include/Jupiter/HTTP_Server.h

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015-2016 Jessica James.
* Copyright (C) 2015-2021 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
@ -24,10 +24,10 @@
* @brief Provides an interface to distribute data using HTTP.
*/
#include <memory>
#include "Jupiter.h"
#include "Thinker.h"
#include "Readable_String.h"
#include "ArrayList.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
@ -67,18 +67,20 @@ namespace Jupiter
class JUPITER_API Directory
{
public:
Jupiter::ArrayList<Jupiter::HTTP::Server::Directory> directories;
Jupiter::ArrayList<Jupiter::HTTP::Server::Content> content;
std::vector<std::unique_ptr<Server::Directory>> directories;
std::vector<std::unique_ptr<Server::Content>> content;
Jupiter::StringS name;
unsigned int name_checksum;
virtual void hook(const Jupiter::ReadableString &path, Content *in_content);
virtual void hook(const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
//virtual bool remove(const Jupiter::ReadableString &path);
virtual bool remove(const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
virtual bool has(const Jupiter::ReadableString &name);
virtual Jupiter::HTTP::Server::Content *find(const Jupiter::ReadableString &name);
virtual Jupiter::ReadableString *execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
virtual Jupiter::HTTP::Server::Content* find(const Jupiter::ReadableString &name);
virtual Jupiter::ReadableString* execute(const Jupiter::ReadableString &name, const Jupiter::ReadableString &query_string);
Directory(const Directory&) = delete;
Directory& operator=(const Directory&) = delete;
Directory(const Jupiter::ReadableString &in_name);
virtual ~Directory();
};
@ -95,7 +97,7 @@ namespace Jupiter
Host(const Jupiter::ReadableString &in_name);
};
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, Content *in_content);
void hook(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, std::unique_ptr<Content> in_content);
bool remove(const Jupiter::ReadableString &host);
//bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path);
bool remove(const Jupiter::ReadableString &host, const Jupiter::ReadableString &path, const Jupiter::ReadableString &name);
@ -115,7 +117,7 @@ namespace Jupiter
/** Private members */
private:
struct Data;
Data *data_;
Data *m_data;
}; // Jupiter::HTTP::Server class
} // Jupiter::HTTP namespace
} // Jupiter namespace

5
src/include/Jupiter/Plugin.h

@ -1,5 +1,5 @@
/**
* Copyright (C) 2014-2016 Jessica James.
* Copyright (C) 2014-2021 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
@ -24,7 +24,6 @@
* @brief Provides a hot-swapable plugin system.
*/
#include "ArrayList.h"
#include "Thinker.h"
#include "Rehash.h"
#include "INIConfig.h"
@ -376,7 +375,7 @@ namespace Jupiter
};
/** The list containing pointers to plugins */
JUPITER_API extern Jupiter::ArrayList<Jupiter::Plugin> *plugins;
JUPITER_API extern std::vector<Jupiter::Plugin*>& plugins; // TODO: There are better ways to expose this
}
/** Re-enable warnings */

Loading…
Cancel
Save