Skip to content

Commit

Permalink
Changes + add missing cmds (unimplemted)
Browse files Browse the repository at this point in the history
  • Loading branch information
alicealys committed Jun 28, 2024
1 parent cd5f768 commit 2a65c3e
Show file tree
Hide file tree
Showing 161 changed files with 3,021 additions and 35 deletions.
274 changes: 274 additions & 0 deletions src/server/component/command.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
#include <std_include.hpp>
#include "loader/component_loader.hpp"

#include "command.hpp"
#include "../server.hpp"

#include "database/database.hpp"

#include <utils/io.hpp>
#include <utils/string.hpp>

namespace command
{
namespace
{
std::unordered_map<std::string, callback> commands;

std::mutex queue_mutex;
std::vector<std::string> command_queue;
}

params::params(const std::vector<std::string>& tokens)
: tokens_(tokens)
{
}

std::string params::get(const size_t index) const
{
if (this->tokens_.size() <= index)
{
return {};
}

return this->tokens_[index];
}

std::string params::operator[](const size_t index) const
{
return this->get(index);
}

size_t params::size() const
{
return this->tokens_.size();
}

std::string params::join(const size_t index) const
{
std::string buffer;

for (auto i = index; i < this->size(); i++)
{
buffer.append(this->tokens_[i]);
buffer.append(" ");
}

return buffer;
}

void execute_single(const std::string& cmd)
{
const auto args = utils::string::split(cmd, ' ');
if (args.size() == 0)
{
return;
}

const auto name = utils::string::to_lower(args[0]);
const auto command = commands.find(name);
if (command == commands.end())
{
console::warning("Command \"%s\" not found\n", name.data());
return;
}

try
{
command->second(args);
}
catch (const std::exception& e)
{
console::error("Error executing command: %s\n", e.what());
}
}

void run_frame()
{
std::vector<std::string> queue_copy;

{
std::lock_guard _0(queue_mutex);
queue_copy = command_queue;
command_queue.clear();
}

for (const auto& cmd : queue_copy)
{
execute_single(cmd);
}
}

void execute(const std::string& cmd)
{
std::lock_guard _0(queue_mutex);
command_queue.emplace_back(cmd);
}

void add(const std::string& name, const callback& cb)
{
console::log("Registering command \"%s\"\n", name.data());
commands.insert(std::make_pair(name, cb));
}

class component final : public component_interface
{
public:
void post_start() override
{
add("quit", [](const params& params)
{
tpp::stop_server();
});

add("query", [](const params& params)
{
const auto query = params.join(1);
const auto start = std::chrono::high_resolution_clock::now();
database::access([&](const database::database_t& db)
{
const auto handle = db->get_handle();

console::print("> %s\n", query.data());

if (mysql_query(handle, query.data()) != 0)
{
console::error("ERROR %i: %s\n", mysql_errno(handle), mysql_error(handle));
return;
}

const auto end = std::chrono::high_resolution_clock::now();
const auto secs = static_cast<float>(std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count()) / 1000.f;

const auto result = mysql_store_result(handle);
const auto _0 = gsl::finally([&]
{
mysql_free_result(result);
});

const auto affected_rows = mysql_affected_rows(handle);

if (result != nullptr)
{
const auto num_rows = mysql_num_rows(result);
const auto num_fields = mysql_num_fields(result);
const auto fields = mysql_fetch_fields(result);

std::vector<std::size_t> max_field_lengths;
std::vector<std::string> fields_str;
std::vector<std::vector<std::string>> rows;

rows.resize(num_rows);
max_field_lengths.resize(num_fields);
fields_str.resize(num_fields);

for (auto f = 0u; f < num_fields; f++)
{
const auto field = &fields[f];
const std::string field_str = {field->name, field->name_length};
fields_str[f] = field_str;
max_field_lengths[f] = std::max(max_field_lengths[f], field_str.size());
}

for (auto i = 0u; i < num_rows; i++)
{
const auto row = mysql_fetch_row(result);
const auto lengths = mysql_fetch_lengths(result);
rows[i].resize(num_fields);

for (auto f = 0u; f < num_fields; f++)
{
const auto field = &fields[f];

const std::string field_str = {field->name, field->name_length};
const std::string row_str = {row[f], lengths[f]};

rows[i][f] = row_str;
max_field_lengths[f] = std::max(max_field_lengths[f], row_str.size());
}
}

auto line_length = static_cast<std::size_t>(num_fields) * 3 + 1;
for (const auto& max_length : max_field_lengths)
{
line_length += max_length;
}

std::string separator;
separator.reserve(line_length);

for (auto f = 0u; f < num_fields; f++)
{
separator.push_back('+');
for (auto i = 0; i < max_field_lengths[f] + 2; i++)
{
separator.push_back('-');
}

if (f == num_fields - 1)
{
separator.push_back('-');
}
}

const auto print_separator = [&]()
{
console::print("%s\n", separator.data());
};

const auto print_values = [&](const std::vector<std::string> values)
{
std::string row_buffer;
row_buffer.reserve(line_length);

for (auto f = 0u; f < num_fields; f++)
{
row_buffer.append("| ");
const auto& field_value = values[f];
const auto diff = max_field_lengths[f] - field_value.size();

row_buffer.append(field_value);

for (auto i = 0; i < diff; i++)
{
row_buffer.push_back(' ');
}

row_buffer.push_back(' ');

if (f == num_fields - 1)
{
row_buffer.push_back('|');
}
}

console::print("%s\n", row_buffer.data());
};

if (result->row_count > 0)
{
print_separator();
print_values(fields_str);
print_separator();

for (auto i = 0; i < result->row_count; i++)
{
print_values(rows[i]);
}

print_separator();

console::print("%i rows in set (%.04f sec)", result->row_count, secs);
}
}
else if (affected_rows > 0)
{
console::print("Query OK, %i row affected (%.04f sec)", affected_rows, secs);
}
});
});
}
};
}

REGISTER_COMPONENT(command::component)
28 changes: 28 additions & 0 deletions src/server/component/command.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

namespace command
{
class params
{
public:
params(const std::vector<std::string>& tokens);

std::string get(const size_t index) const;
std::string operator[](const size_t index) const;

size_t size() const;

std::string join(const size_t index) const;

private:
std::vector<std::string> tokens_;

};

using callback = std::function<void(const params& args)>;

void run_frame();

void execute(const std::string& cmd);
void add(const std::string& name, const callback& cb);
}
Loading

0 comments on commit 2a65c3e

Please sign in to comment.