From 1a78688d0d4869de7aff20a41170844156e2860c Mon Sep 17 00:00:00 2001 From: Jessica Date: Sat, 30 Oct 2021 22:21:14 -0500 Subject: [PATCH] Committing various work which was apparently never committed; should break out of that habit --- CMakeLists.txt | 2 +- build/GNU/CMakeLists.txt | 2 +- src/bot/CMakeLists.txt | 3 +- src/bot/base_commands.cpp | 60 +++++++++++++++++++++ src/bot/console/console.cpp | 48 +++++++++++++++++ src/bot/console/console.hpp | 30 +++++++++++ src/bot/console/console_command_context.cpp | 53 ++++++++++++++++++ src/bot/console/console_command_context.hpp | 41 ++++++++++++++ src/bot/main.cpp | 5 +- src/bot/shutdown.cpp | 38 +++++++++++++ src/bot/shutdown.hpp | 29 ++++++++++ src/common/CMakeLists.txt | 2 +- src/common/app_parameters.cpp | 2 +- src/common/io/command_manager.cpp | 52 ++++++++++++++++++ src/common/parsers/json.cpp | 3 +- src/common/unicode.cpp | 44 +++++++++------ src/include/io/ansi/ansi_text.hpp | 2 +- src/include/io/command_context.hpp | 4 +- src/include/io/command_manager.hpp | 14 ++--- src/include/io/irc/irc_text.hpp | 2 +- src/include/unicode.hpp | 13 +++-- src/test/CMakeLists.txt | 2 +- 22 files changed, 409 insertions(+), 42 deletions(-) create mode 100644 src/bot/base_commands.cpp create mode 100644 src/bot/console/console.cpp create mode 100644 src/bot/console/console.hpp create mode 100644 src/bot/console/console_command_context.cpp create mode 100644 src/bot/console/console_command_context.hpp create mode 100644 src/bot/shutdown.cpp create mode 100644 src/bot/shutdown.hpp create mode 100644 src/common/io/command_manager.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a5ac526..789ae93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.8) project(jessilib) # Set common constants -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(JESSILIB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) # Include compiler-specific build configuration diff --git a/build/GNU/CMakeLists.txt b/build/GNU/CMakeLists.txt index e5b6b42..3359be5 100644 --- a/build/GNU/CMakeLists.txt +++ b/build/GNU/CMakeLists.txt @@ -10,4 +10,4 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-omit-frame-pointer -fsanitize=address") # Enable std::filesystem -set(JESSILIB_ADDITOINAL_LIBS "stdc++fs") +set(JESSILIB_ADDITOINAL_LIBS "stdc++fs" pthread) diff --git a/src/bot/CMakeLists.txt b/src/bot/CMakeLists.txt index 90e75aa..7f9454d 100644 --- a/src/bot/CMakeLists.txt +++ b/src/bot/CMakeLists.txt @@ -1,6 +1,7 @@ # Setup source files set(SOURCE_FILES - main.cpp) + main.cpp + console/console_command_context.cpp console/console.cpp shutdown.cpp base_commands.cpp) # Setup executable build target add_executable(jessibot ${SOURCE_FILES}) diff --git a/src/bot/base_commands.cpp b/src/bot/base_commands.cpp new file mode 100644 index 0000000..3dae801 --- /dev/null +++ b/src/bot/base_commands.cpp @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2020 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 + */ + +#include "io/command.hpp" +#include "io/command_manager.hpp" +#include "shutdown.hpp" + +namespace jessibot { +namespace io { + +using namespace jessilib::io; + +command quit_command{ [](command_context& context) { + using namespace jessilib::io; + text quit_text{ "Closing jessibot", text::property::bold, color{ 0xFF0000 } }; // TODO: localize + context.publicReply(formatted_message{ "{}", quit_text }); + notify_shutdown(); +}, "quit" }; + +// ISSUE: help command has no way to know what commands exist for the given context +command help_command{ [](command_context& context) { + auto details = context.details(); + auto table_name = details["table"].get(); + + if (table_name.empty()) { + text error_text{ "ERROR", text::property::bold, color{ 0xFF0000 } }; // TODO: localize + context.publicReply(formatted_message{ "{} command context is missing permission table name", error_text }); + return; + } + + // table examples: "console", "irc", "irc+", "irc%", "irc@"; should table instead be 'tables'? + + text table_text{ table_name, text::property::bold, color{ 0x0000FF } }; + context.publicReply(formatted_message{ "Commands for table '{}':", table_text }); + + // TODO: read some permission table and filter commands based upon permission and context information + const command_manager& manager = command_manager::instance(); + manager.foreach([&context](basic_command* in_command) { + context.publicReply(formatted_message{ "{}", in_command->label() }); + return true; + }); +}, "help" }; + +} // namespace io +} // namespace jessibot diff --git a/src/bot/console/console.cpp b/src/bot/console/console.cpp new file mode 100644 index 0000000..94b31ce --- /dev/null +++ b/src/bot/console/console.cpp @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2020 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 + */ + +#include "console.hpp" + +#include +#include "io/command_manager.hpp" +#include "io/ansi/ansi_text.hpp" +#include "shutdown.hpp" +#include "console/console_command_context.hpp" + +namespace jessibot { +namespace io { + +void console_input_loop() { + using namespace jessilib::io; + + std::string input; + auto shutdown_future = get_shutdown_future(); + while (shutdown_future.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready) { + std::getline(std::cin, input); // TODO: use a non-bloicking call and poll running periodically + jessibot::io::console_command_context context{ input }; + if (!command_manager::instance().execute_command(context)) { + text error_text{ "ERROR", text::property::bold, color{ 0xFF0000 }}; + text keyword_text{ context.keyword(), text::property::bold, color{ 0x0000FF }}; + auto result = process_message(formatted_message{"{} Command \"{}\" not found", error_text, keyword_text}); + std::cout << result << std::endl; + } + } +} + +} // namespace io +} // namespace jessibot diff --git a/src/bot/console/console.hpp b/src/bot/console/console.hpp new file mode 100644 index 0000000..fb74589 --- /dev/null +++ b/src/bot/console/console.hpp @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2020 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 + */ + +#pragma once + +#include + +namespace jessibot { +namespace io { + +void console_input_loop(); + +} // namespace io +} // namespace jessibot + diff --git a/src/bot/console/console_command_context.cpp b/src/bot/console/console_command_context.cpp new file mode 100644 index 0000000..8eedd58 --- /dev/null +++ b/src/bot/console/console_command_context.cpp @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2020 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 + */ + +#include "console_command_context.hpp" + +#include +#include "io/ansi/ansi_text.hpp" + +namespace jessibot { +namespace io { + +/** Reply */ +bool console_command_context::privateReply(const jessilib::io::formatted_message& in_message) { + auto result = jessilib::io::process_message(in_message); + std::cout << result << std::endl; + return true; +} + +bool console_command_context::publicReply(const jessilib::io::formatted_message& in_message) { + // Consoles only have 1 output mechanism + return privateReply(in_message); +} + +/** Additional contextual details */ +jessilib::object console_command_context::details() const { + static jessilib::object s_details { + jessilib::object::map_t{ { "table", "console" } } + }; + + return s_details; +} + +std::string console_command_context::getText(std::string_view tag) const { + return { tag.begin(), tag.end() }; // TODO: implement properly +} + +} // namespace io +} // namespace jessilib diff --git a/src/bot/console/console_command_context.hpp b/src/bot/console/console_command_context.hpp new file mode 100644 index 0000000..b4678dd --- /dev/null +++ b/src/bot/console/console_command_context.hpp @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2020 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 + */ + +#pragma once + +#include "io/command_context.hpp" + +namespace jessibot { +namespace io { + +class console_command_context : public jessilib::io::command_context { +public: + using jessilib::io::command_context::command_context; + + /** Reply */ + bool privateReply(const jessilib::io::formatted_message& in_message) override; + bool publicReply(const jessilib::io::formatted_message& in_message) override; + + /** Additional contextual details */ + jessilib::object details() const override; + std::string getText(std::string_view tag) const override; +}; // class console_command_context + +} // namespace io +} // namespace jessibot + diff --git a/src/bot/main.cpp b/src/bot/main.cpp index 11fd8a7..ea0467e 100644 --- a/src/bot/main.cpp +++ b/src/bot/main.cpp @@ -16,12 +16,10 @@ * Written by Jessica James */ -#include #include #include "app_parameters.hpp" #include "parsers/json.hpp" - -// TODO: input loop +#include "console/console.hpp" int main(int argc, char** argv) { jessilib::app_parameters parameters{ argc, argv }; @@ -31,5 +29,6 @@ int main(int argc, char** argv) { std::cout << std::endl << jessilib::json_parser{}.serialize(parameters) << std::endl; } + jessibot::io::console_input_loop(); return 0; } diff --git a/src/bot/shutdown.cpp b/src/bot/shutdown.cpp new file mode 100644 index 0000000..c3f06ea --- /dev/null +++ b/src/bot/shutdown.cpp @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2020 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 + */ + +#include "shutdown.hpp" + +namespace jessibot { + +std::promise& shutdown_promise() { + static std::promise s_shutdown_promise; + return s_shutdown_promise; +} + +std::shared_future get_shutdown_future() { + static std::shared_future s_shutdown_future{ shutdown_promise().get_future().share() }; + return s_shutdown_future; +} + +void notify_shutdown() { + shutdown_promise().set_value(); +} + +} // namespace jessibot + diff --git a/src/bot/shutdown.hpp b/src/bot/shutdown.hpp new file mode 100644 index 0000000..b95c0e5 --- /dev/null +++ b/src/bot/shutdown.hpp @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2020 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 + */ + +#pragma once + +#include + +namespace jessibot { + +std::shared_future get_shutdown_future(); +void notify_shutdown(); + +} // namespace jessibot + diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e0b3c74..11ae70b 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,6 +1,6 @@ # Setup source files set(SOURCE_FILES - timer/timer.cpp timer/timer_manager.cpp thread_pool.cpp timer/timer_context.cpp timer/cancel_token.cpp timer/synchronized_timer.cpp object.cpp parser/parser.cpp parser/parser_manager.cpp config.cpp serialize.cpp parsers/json.cpp unicode.cpp io/command.cpp io/command_context.cpp io/message.cpp app_parameters.cpp) + timer/timer.cpp timer/timer_manager.cpp thread_pool.cpp timer/timer_context.cpp timer/cancel_token.cpp timer/synchronized_timer.cpp object.cpp parser/parser.cpp parser/parser_manager.cpp config.cpp serialize.cpp parsers/json.cpp unicode.cpp io/command.cpp io/command_context.cpp io/message.cpp app_parameters.cpp io/command_manager.cpp) # Setup library build target add_library(jessilib ${SOURCE_FILES}) diff --git a/src/common/app_parameters.cpp b/src/common/app_parameters.cpp index 95a729f..321d970 100644 --- a/src/common/app_parameters.cpp +++ b/src/common/app_parameters.cpp @@ -35,7 +35,7 @@ app_parameters::app_parameters(int in_argc, const char** in_argv) { m_path = in_argv[0]; // Process args - std::string_view key{ nullptr }; + std::string_view key; std::string value; auto flush_value = [&key, &value, this]() { // This is the start of a key; flush what we were previously processing diff --git a/src/common/io/command_manager.cpp b/src/common/io/command_manager.cpp new file mode 100644 index 0000000..4cf8381 --- /dev/null +++ b/src/common/io/command_manager.cpp @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2020 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 + */ + +#include "io/command_manager.hpp" + +namespace jessilib { +namespace io { + +void command_manager::register_command(basic_command& in_command) { + std::lock_guard guard{ m_commands_mutex }; + m_commands.push_back(&in_command); +} + +void command_manager::unregister_command(basic_command& in_command) { + std::lock_guard guard{ m_commands_mutex }; + std::remove(m_commands.begin(), m_commands.end(), &in_command); +} + +bool command_manager::execute_command(command_context& in_context) { + std::shared_lock lock{ m_commands_mutex }; + for (auto& command : m_commands) { + if (in_context.keyword() == command->label()) { + command->execute(in_context); + return true; + } + } + + return false; +} + +command_manager& command_manager::instance() { + static command_manager s_command_manager; + return s_command_manager; +} + +} // namespace io +} // namespace jessilib diff --git a/src/common/parsers/json.cpp b/src/common/parsers/json.cpp index a6419d1..5bbf36e 100644 --- a/src/common/parsers/json.cpp +++ b/src/common/parsers/json.cpp @@ -259,6 +259,7 @@ std::string read_json_string(std::string_view& in_data) { // Valid unicode sequence result += in_data.substr(0, codepoint.units); + //result.append(reinterpret_cast(in_data.data()), codepoint.units); in_data.remove_prefix(codepoint.units); break; } @@ -539,4 +540,4 @@ std::string json_parser::serialize(const object& in_object) { } } -} // namespace jessilib \ No newline at end of file +} // namespace jessilib diff --git a/src/common/unicode.cpp b/src/common/unicode.cpp index 9211f71..636c1ee 100644 --- a/src/common/unicode.cpp +++ b/src/common/unicode.cpp @@ -32,7 +32,7 @@ void append_helper(std::basic_ostream& out_string, T in_value) { out_string << in_value; } -template +template size_t encode_codepoint_utf8(T& out_destination, char32_t in_codepoint) { if (in_codepoint > 0x10FFFF) { return 0; @@ -40,30 +40,30 @@ size_t encode_codepoint_utf8(T& out_destination, char32_t in_codepoint) { if (in_codepoint <= 0x007F) { // 1-byte sequence (7 bits) - append_helper(out_destination, static_cast(in_codepoint)); + append_helper(out_destination, static_cast(in_codepoint)); return 1; } if (in_codepoint <= 0x07FF) { // 2-byte sequence (11 bits; 5 + 6) - append_helper(out_destination, static_cast(0xC0 | ((in_codepoint >> 6) & 0x1F))); - append_helper(out_destination, static_cast(0x80 | (in_codepoint & 0x3F))); + append_helper(out_destination, static_cast(0xC0 | ((in_codepoint >> 6) & 0x1F))); + append_helper(out_destination, static_cast(0x80 | (in_codepoint & 0x3F))); return 2; } if (in_codepoint <= 0xFFFF) { // 3-byte sequence (16 bits; 4 + 6 + 6) - append_helper(out_destination, static_cast(0xE0 | ((in_codepoint >> 12) & 0x0F))); - append_helper(out_destination, static_cast(0x80 | ((in_codepoint >> 6) & 0x3F))); - append_helper(out_destination, static_cast(0x80 | (in_codepoint & 0x3F))); + append_helper(out_destination, static_cast(0xE0 | ((in_codepoint >> 12) & 0x0F))); + append_helper(out_destination, static_cast(0x80 | ((in_codepoint >> 6) & 0x3F))); + append_helper(out_destination, static_cast(0x80 | (in_codepoint & 0x3F))); return 3; } // 4-byte sequence (21 bits; 3 + 6 + 6 + 6) - append_helper(out_destination, static_cast(0xF0 | ((in_codepoint >> 18) & 0x07))); - append_helper(out_destination, static_cast(0x80 | ((in_codepoint >> 12) & 0x3F))); - append_helper(out_destination, static_cast(0x80 | ((in_codepoint >> 6) & 0x3F))); - append_helper(out_destination, static_cast(0x80 | (in_codepoint & 0x3F))); + append_helper(out_destination, static_cast(0xF0 | ((in_codepoint >> 18) & 0x07))); + append_helper(out_destination, static_cast(0x80 | ((in_codepoint >> 12) & 0x3F))); + append_helper(out_destination, static_cast(0x80 | ((in_codepoint >> 6) & 0x3F))); + append_helper(out_destination, static_cast(0x80 | (in_codepoint & 0x3F))); return 4; } @@ -97,7 +97,11 @@ size_t encode_codepoint_utf32(T& out_destination, char32_t in_codepoint) { } size_t encode_codepoint(std::string& out_string, char32_t in_codepoint) { - return encode_codepoint_utf8(out_string, in_codepoint); + return encode_codepoint_utf8(out_string, in_codepoint); +} + +size_t encode_codepoint(std::u8string& out_string, char32_t in_codepoint) { + return encode_codepoint_utf8(out_string, in_codepoint); } size_t encode_codepoint(std::u16string& out_string, char32_t in_codepoint) { @@ -109,7 +113,11 @@ size_t encode_codepoint(std::u32string& out_string, char32_t in_codepoint) { } size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint) { - return encode_codepoint_utf8(out_stream, in_codepoint); + return encode_codepoint_utf8, char>(out_stream, in_codepoint); +} + +size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint) { + return encode_codepoint_utf8, char8_t>(out_stream, in_codepoint); } size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint) { @@ -120,8 +128,8 @@ size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_co return encode_codepoint_utf32(out_stream, in_codepoint); } -std::string encode_codepoint_u8(char32_t in_codepoint) { - std::string result; +std::u8string encode_codepoint_u8(char32_t in_codepoint) { + std::u8string result; encode_codepoint(result, in_codepoint); return result; } @@ -141,6 +149,10 @@ std::u32string encode_codepoint_u32(char32_t in_codepoint) { /** decode_codepoint */ get_endpoint_result decode_codepoint(const std::string_view& in_string) { + return decode_codepoint(std::u8string_view{ reinterpret_cast(in_string.data()), in_string.size() }); +} + +get_endpoint_result decode_codepoint(const std::u8string_view& in_string) { get_endpoint_result result{ 0, 0 }; if (in_string.empty()) { @@ -254,4 +266,4 @@ get_endpoint_result decode_surrogate_pair(char16_t in_high_surrogate, char16_t i return { 0, 0 }; } -} // namespace jessilib \ No newline at end of file +} // namespace jessilib diff --git a/src/include/io/ansi/ansi_text.hpp b/src/include/io/ansi/ansi_text.hpp index 489735a..85723fe 100644 --- a/src/include/io/ansi/ansi_text.hpp +++ b/src/include/io/ansi/ansi_text.hpp @@ -50,7 +50,7 @@ static constexpr std::string_view COLOR_BG_DEFAULT{ "49" }; } // namespace ansi template<> -std::string text_to_string(const ansi::text_wrapper& in_text) { +inline std::string text_to_string(const ansi::text_wrapper& in_text) { std::string result; result.reserve(in_text.string().size() + 8); diff --git a/src/include/io/command_context.hpp b/src/include/io/command_context.hpp index 5bdfe35..98953f3 100644 --- a/src/include/io/command_context.hpp +++ b/src/include/io/command_context.hpp @@ -37,8 +37,8 @@ public: std::vector paramaters() const; /** Reply */ - virtual bool privateReply(const formatted_message& in_message); // Reply to invoker privately (i.e: PM) - virtual bool publicReply(const formatted_message& in_message); // Reply to invoker publicly (i.e: channel) + virtual bool privateReply(const formatted_message& in_message) = 0; // Reply to invoker privately (i.e: PM) + virtual bool publicReply(const formatted_message& in_message) = 0; // Reply to invoker publicly (i.e: channel) /** Additional contextual details */ virtual object details() const = 0; // Additional details diff --git a/src/include/io/command_manager.hpp b/src/include/io/command_manager.hpp index df03fb6..b6c35fc 100644 --- a/src/include/io/command_manager.hpp +++ b/src/include/io/command_manager.hpp @@ -26,13 +26,9 @@ namespace io { class command_manager { public: - struct entry { - basic_command* m_command; - }; - void register_command(basic_command& in_command); void unregister_command(basic_command& in_command); - bool execute_command(const command_context& in_context); + bool execute_command(command_context& in_context); // executes a predicate for each command, until the predicate returns false or no commands remain template // TODO: add check for non-const @@ -61,9 +57,13 @@ public: static command_manager& instance(); private: - std::vector m_commands; + //struct entry { + // basic_command* m_command; + //}; + + std::vector m_commands; mutable std::shared_mutex m_commands_mutex; }; } // namespace io -} // namespace jessilib \ No newline at end of file +} // namespace jessilib diff --git a/src/include/io/irc/irc_text.hpp b/src/include/io/irc/irc_text.hpp index 0036320..2a77719 100644 --- a/src/include/io/irc/irc_text.hpp +++ b/src/include/io/irc/irc_text.hpp @@ -138,7 +138,7 @@ text::property properties_to_toggle(text::property in_active_properties, text::p } // namespace irc template<> -std::string text_to_string(const irc::text_wrapper& in_text) { +inline std::string text_to_string(const irc::text_wrapper& in_text) { std::string result; result.reserve(in_text.string().size() + 8); diff --git a/src/include/unicode.hpp b/src/include/unicode.hpp index 7c80bc3..f457d6f 100644 --- a/src/include/unicode.hpp +++ b/src/include/unicode.hpp @@ -26,13 +26,15 @@ namespace jessilib { /** encode_codepoint */ -size_t encode_codepoint(std::string& out_string, char32_t in_codepoint); +size_t encode_codepoint(std::string& out_string, char32_t in_codepoint); // ASSUMES UTF-8 +size_t encode_codepoint(std::u8string& out_string, char32_t in_codepoint); size_t encode_codepoint(std::u16string& out_string, char32_t in_codepoint); size_t encode_codepoint(std::u32string& out_string, char32_t in_codepoint); -size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint); +size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint); // ASSUMES UTF-8 +size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint); size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint); size_t encode_codepoint(std::basic_ostream& out_stream, char32_t in_codepoint); -std::string encode_codepoint_u8(char32_t in_codepoint); +std::u8string encode_codepoint_u8(char32_t in_codepoint); std::u16string encode_codepoint_u16(char32_t in_codepoint); std::u32string encode_codepoint_u32(char32_t in_codepoint); @@ -43,7 +45,8 @@ struct get_endpoint_result { size_t units{}; }; -get_endpoint_result decode_codepoint(const std::string_view& in_string); // UTF-8 +get_endpoint_result decode_codepoint(const std::string_view& in_string); // ASSUMES UTF-8 +get_endpoint_result decode_codepoint(const std::u8string_view& in_string); // UTF-8 get_endpoint_result decode_codepoint(const std::u16string_view& in_string); // UTF-16 get_endpoint_result decode_codepoint(const std::u32string_view& in_string); // UTF-32 @@ -59,7 +62,7 @@ char32_t advance_codepoint(std::basic_string_view& in_string) { /** next_codepoint */ template -std::string_view next_codepoint(const std::basic_string_view& in_string) { +std::basic_string_view next_codepoint(const std::basic_string_view& in_string) { return in_string.substr(decode_codepoint(in_string).units); } diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index aa31688..e19ee1e 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -1,6 +1,6 @@ # Setup source files set(SOURCE_FILES - timer.cpp thread_pool.cpp util.cpp object.cpp parser.cpp config.cpp parsers/json.cpp unicode.cpp app_parameters.cpp io/color.cpp) + timer.cpp thread_pool.cpp util.cpp object.cpp parser.cpp config.cpp parsers/json.cpp unicode.cpp app_parameters.cpp io/color.cpp duration.cpp) # Setup gtest add_subdirectory(googletest/googletest)