Browse Source

Committing `command` work that was apparently never committed

master
Jessica James 4 years ago
parent
commit
22f81473ba
  1. 2
      src/common/CMakeLists.txt
  2. 50
      src/common/io/command.cpp
  3. 97
      src/common/io/command_context.cpp
  4. 65
      src/include/io/command.hpp
  5. 54
      src/include/io/command_context.hpp
  6. 69
      src/include/io/command_manager.hpp
  7. 28
      src/test/object.cpp

2
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/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)
# Setup library build target
add_library(jessilib ${SOURCE_FILES})

50
src/common/io/command.cpp

@ -0,0 +1,50 @@
/**
* Copyright (C) 2019 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>
*/
#include "io/command.hpp"
#include "io/command_manager.hpp"
namespace jessilib {
namespace io {
command::command(callback_t in_callback, std::string_view in_label)
: m_callback{ std::move(in_callback) },
m_label{ std::move(in_label) } {
// Register command
command_manager::instance().register_command(*this);
}
command::~command() {
// Unregister command
command_manager::instance().unregister_command(*this);
}
std::string_view command::label() const {
return m_label;
}
void command::execute(command_context& in_context) const {
m_callback(in_context);
}
command test_command{ [](command_context&) {
// do stuff
}, "test" };
} // namespace io
} // namespace jessilib

97
src/common/io/command_context.cpp

@ -0,0 +1,97 @@
/**
* Copyright (C) 2019 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>
*/
#include "io/command_context.hpp"
namespace jessilib {
namespace io {
command_context::command_context(std::string_view in_input)
: m_input{ in_input } {
// Strip leading whitespace
std::size_t pos = in_input.find_first_not_of(' ');
if (pos != std::string_view::npos) {
in_input.remove_prefix(pos);
// Whitespace is stripped; parse keyword from input
pos = in_input.find(' ');
if (pos == std::string_view::npos) {
pos = in_input.size();
}
m_keyword = in_input.substr(0, pos);
in_input.remove_prefix(pos);
// Strip leading whitespace and parse parameter from remaining input
pos = in_input.find_first_not_of(' ');
if (pos != std::string_view::npos) {
in_input.remove_prefix(pos);
m_parameter = in_input;
}
}
}
command_context::command_context(std::string_view in_input, std::string_view in_keyword, std::string_view in_parameter)
: m_input{ std::move(in_input) },
m_keyword{ std::move(in_keyword) },
m_parameter{ std::move(in_parameter) } {
// Empty ctor body
}
std::string_view command_context::input() const {
return m_input;
}
std::string_view command_context::keyword() const {
return m_keyword;
}
std::string_view command_context::parameter() const {
return m_parameter;
}
std::vector<std::string_view> command_context::paramaters() const {
std::vector<std::string_view> result;
std::string_view parameter = m_parameter;
// Strip leading whitespace
std::size_t pos = parameter.find_first_not_of(' ');
if (pos == std::string_view::npos) {
// parameter is empty; return empty vector
return result;
}
parameter.remove_prefix(pos);
// Parse parameter into result
while (!parameter.empty()) {
// Parse word from parameter into result
pos = parameter.find(' ');
if (pos == std::string_view::npos) {
pos = parameter.size();
}
result.push_back(parameter.substr(0, pos));
// Strip word and trailing whitespace
parameter.remove_prefix(pos);
parameter.remove_prefix(std::min(parameter.find_first_not_of(' '), parameter.size()));
}
return result;
};
} // namespace io
} // namespace jessilib

65
src/include/io/command.hpp

@ -0,0 +1,65 @@
/**
* Copyright (C) 2019 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>
*/
#pragma once
#include <string_view>
#include <functional>
#include "command_context.hpp"
namespace jessilib {
namespace io {
class basic_command {
public:
virtual ~basic_command() = default;
virtual std::string_view label() const = 0;
virtual void execute(command_context& in_context) const = 0;
}; // class basic_command
class command : public basic_command {
public:
// Types
using callback_t = std::function<void(command_context&)>;
// Delete all implicit constructors and assignment operators
command() = delete;
command(const command&) = delete;
command(command&&) = delete;
command& operator=(const command&) = delete;
command& operator=(command&&) = delete;
// Instantiates and self-registers a command
command(callback_t in_callback, std::string_view in_label);
// Cleans up and unregisters the command
virtual ~command();
// Unique label associated with command
virtual std::string_view label() const override;
// Executes the command
virtual void execute(command_context& in_context) const override;
private:
callback_t m_callback;
std::string_view m_label;
}; // class command
} // namespace io
} // namespace jessilib

54
src/include/io/command_context.hpp

@ -0,0 +1,54 @@
/**
* Copyright (C) 2019 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>
*/
#pragma once
#include <string_view>
#include "object.hpp"
#include "message.hpp"
namespace jessilib {
namespace io {
class command_context {
public:
command_context(std::string_view in_input);
command_context(std::string_view in_input, std::string_view in_keyword, std::string_view in_parameter);
/** User input */
std::string_view input() const;
std::string_view keyword() const;
std::string_view parameter() const;
std::vector<std::string_view> 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)
/** Additional contextual details */
virtual object details() const = 0; // Additional details
virtual std::string getText(std::string_view tag) const = 0; // Get localized text
private:
std::string_view m_input;
std::string_view m_keyword;
std::string_view m_parameter;
}; // class command_context
} // namespace io
} // namespace jessilib

69
src/include/io/command_manager.hpp

@ -0,0 +1,69 @@
/**
* Copyright (C) 2019 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>
*/
#pragma once
#include <shared_mutex>
#include "command.hpp"
namespace jessilib {
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);
// executes a predicate for each command, until the predicate returns false or no commands remain
template<typename predicate_t> // TODO: add check for non-const
void foreach(predicate_t&& in_predicate) {
std::lock_guard<std::shared_mutex> guard{ m_commands_mutex };
for (auto& command_entry : m_commands) {
if (!in_predicate(command_entry)) {
// Predicate returned false; we're done here
return;
}
}
}
// executes a predicate for each command, until the predicate returns false or no commands remain
template<typename predicate_t> // TODO: add check for const
void foreach(predicate_t&& in_predicate) const {
std::shared_lock<std::shared_mutex> guard{ m_commands_mutex };
for (const auto& command_entry : m_commands) {
if (!in_predicate(command_entry)) {
// Predicate returned false; we're done here
return;
}
}
}
static command_manager& instance();
private:
std::vector<entry> m_commands;
mutable std::shared_mutex m_commands_mutex;
};
} // namespace io
} // namespace jessilib

28
src/test/object.cpp

@ -28,6 +28,20 @@ using unsigned_char_t = unsigned char;
using long_long_t = long long;
using long_double_t = long double;
using map_str_str = std::map<std::string, std::string>;
using map_str_strv = std::map<std::string, std::string_view>;
using map_str_obj = std::map<std::string, object>;
using map_strv_str = std::map<std::string_view, std::string>;
using map_strv_strv = std::map<std::string_view, std::string_view>;
using map_strv_obj = std::map<std::string_view, object>;
using unordered_map_str_str = std::unordered_map<std::string, std::string>;
using unordered_map_str_strv = std::unordered_map<std::string, std::string_view>;
using unordered_map_str_obj = std::unordered_map<std::string, object>;
using unordered_map_strv_str = std::unordered_map<std::string_view, std::string>;
using unordered_map_strv_strv = std::unordered_map<std::string_view, std::string_view>;
using unordered_map_strv_obj = std::unordered_map<std::string_view, object>;
/** basic tests; these test function calls against null objects and heavily test for compilation errors */
TEST(ObjectTest, basic) {
@ -148,20 +162,15 @@ TEST(ObjectTest, basic_has_unordered_set) {
EXPECT_FALSE(obj.has<std::unordered_set<object>>());
}
using map_str_str = std::map<std::string, std::string>;
using map_str_strv = std::map<std::string, std::string_view>;
using map_str_obj = std::map<std::string, object>;
using unordered_map_str_str = std::unordered_map<std::string, std::string>;
using unordered_map_str_strv = std::unordered_map<std::string, std::string_view>;
using unordered_map_str_obj = std::unordered_map<std::string, object>;
TEST(ObjectTest, basic_has_map) {
object obj;
EXPECT_FALSE(obj.has<map_str_str>());
EXPECT_FALSE(obj.has<map_str_strv>());
EXPECT_FALSE(obj.has<map_str_obj>());
EXPECT_FALSE(obj.has<map_strv_str>());
EXPECT_FALSE(obj.has<map_strv_strv>());
EXPECT_FALSE(obj.has<map_strv_obj>());
}
TEST(ObjectTest, basic_has_unordered_map) {
@ -170,6 +179,9 @@ TEST(ObjectTest, basic_has_unordered_map) {
EXPECT_FALSE(obj.has<unordered_map_str_str>());
EXPECT_FALSE(obj.has<unordered_map_str_strv>());
EXPECT_FALSE(obj.has<unordered_map_str_obj>());
EXPECT_FALSE(obj.has<unordered_map_strv_str>());
EXPECT_FALSE(obj.has<unordered_map_strv_strv>());
EXPECT_FALSE(obj.has<unordered_map_strv_obj>());
}
/** basic_get tests */

Loading…
Cancel
Save