Skip to content

Commit e9ecdb3

Browse files
authored
Object to read commands from stdin (#46)
* Implement Stdcin Waiter Signed-off-by: jparisu <javierparis@eprosima.com> * add code documentation Signed-off-by: jparisu <javierparis@eprosima.com> * Add deleted functions that fail in ubuntu20 Signed-off-by: jparisu <javierparis@eprosima.com> * uncrustify Signed-off-by: jparisu <javierparis@eprosima.com> --------- Signed-off-by: jparisu <javierparis@eprosima.com>
1 parent b24fb94 commit e9ecdb3

6 files changed

Lines changed: 403 additions & 0 deletions

File tree

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
// Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include <cpp_utils/event/StdinEventHandler.hpp>
18+
#include <cpp_utils/enum/EnumBuilder.hpp>
19+
#include <cpp_utils/wait/DBQueueWaitHandler.hpp>
20+
21+
namespace eprosima {
22+
namespace utils {
23+
24+
/**
25+
* @brief Data struct that contains a command in a way of enumeration, and arguments in a string way.
26+
*
27+
* @tparam CommandEnum enumeration that represent the different commands available.
28+
*/
29+
template <typename CommandEnum>
30+
struct Command
31+
{
32+
//! Command in the way of a enumeration class.
33+
CommandEnum command;
34+
35+
//! Vector with arguments of command in string way
36+
std::vector<std::string> arguments;
37+
};
38+
39+
/**
40+
* Class that allows to easily read commands and their arguments from \c std::cin .
41+
*
42+
* Giving an enumeration \c CommandEnum that represent the different possible values of commands, and a
43+
* \c EnumBuilder that transform strings to CommandEnum values, this class read from stdin when call to
44+
* \c read_next_command and return a command and its arguments, in case the command is parsable to the enum.
45+
*
46+
* This class is similar to \c StdinEventHandler but this reads under request,
47+
* vs the event handler that is asynchronous.
48+
*
49+
* @note This class relies on \c StdinEventHandler to read from stdin and in \c EnumBuilder to interpret command.
50+
*/
51+
template <typename CommandEnum>
52+
class CommandReader
53+
{
54+
public:
55+
56+
/**
57+
* @brief Construct a new Command Reader object giving an \c EnumBuilder and a source from where to read.
58+
*
59+
* @param builder class that allow to convert a string to a enumeration kind.
60+
* @param source : source \c istream to get data from.
61+
*
62+
* @warning using a source different than std::cin is dangerous as the reference is passed forward.
63+
* However this is very useful for testing purpose.
64+
*/
65+
CommandReader(
66+
const EnumBuilder<CommandEnum>& builder,
67+
std::istream& source = std::cin);
68+
69+
//! Default dtor
70+
~CommandReader() = default;
71+
72+
//! Illegal copy of this class due to internal EventHandler. This remove other copy or move operators.
73+
CommandReader(
74+
const CommandReader& other) = delete;
75+
76+
/**
77+
* @brief Read next command written in stdin.
78+
*
79+
* @param [out] command command to fill with the data read.
80+
*
81+
* @return true if the data read is parsable to a enum value of \c EnumBuilder .
82+
* @return false otherwise.
83+
*/
84+
bool read_next_command(
85+
Command<CommandEnum>& command);
86+
87+
protected:
88+
89+
/**
90+
* @brief
91+
*
92+
* @param command_read
93+
*/
94+
void read_command_callback_(
95+
std::string command_read);
96+
97+
//! Builder to transform string into a command enum value.
98+
EnumBuilder<CommandEnum> builder_;
99+
100+
//! Event Handler used to read from stdin.
101+
event::StdinEventHandler stdin_handler_;
102+
103+
/**
104+
* @brief Consumer where \c stdin_handler_ will produce commands read, and method \c read_next_command will
105+
* consume next command.
106+
*
107+
* @note Using a DBQueueWaitHandler is maybe pretty complex for what is required here, as there will be only one
108+
* value available at a time. But it is the only implementation of ConsumerWaitHandler so far.
109+
*/
110+
event::DBQueueWaitHandler<std::string> commands_read_;
111+
};
112+
113+
} /* namespace utils */
114+
} /* namespace eprosima */
115+
116+
// Include implementation template file
117+
#include <cpp_utils/user_interface/impl/CommandReader.ipp>
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
#include <cpp_utils/utils.hpp>
18+
19+
namespace eprosima {
20+
namespace utils {
21+
22+
template <typename CommandEnum>
23+
CommandReader<CommandEnum>::CommandReader(
24+
const EnumBuilder<CommandEnum>& builder,
25+
std::istream& source /* = std::cin */)
26+
: builder_(builder)
27+
, stdin_handler_(
28+
[this](std::string st)
29+
{
30+
this->read_command_callback_(st);
31+
},
32+
true,
33+
0,
34+
source)
35+
, commands_read_(0, true)
36+
{
37+
// Do nothing
38+
}
39+
40+
template <typename CommandEnum>
41+
bool CommandReader<CommandEnum>::read_next_command(
42+
Command<CommandEnum>& command)
43+
{
44+
stdin_handler_.read_one_more_line();
45+
std::string full_command = commands_read_.consume();
46+
47+
// Divide command
48+
command.arguments = utils::split_string(full_command, " ");
49+
50+
// Check if command exists
51+
// The args are already set in command, and the enum value will be set string_to_enumeration
52+
return builder_.string_to_enumeration(command.arguments[0], command.command);
53+
}
54+
55+
template <typename CommandEnum>
56+
void CommandReader<CommandEnum>::read_command_callback_(
57+
std::string command_read)
58+
{
59+
commands_read_.produce(command_read);
60+
}
61+
62+
} /* namespace utils */
63+
} /* namespace eprosima */
64+
65+
// Include implementation template file
66+
#include <cpp_utils/user_interface/impl/CommandReader.ipp>

cpp_utils/test/unittest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,6 @@ add_subdirectory(return_code)
2626
add_subdirectory(testing)
2727
add_subdirectory(thread_pool)
2828
add_subdirectory(time)
29+
add_subdirectory(user_interface)
2930
add_subdirectory(utils)
3031
add_subdirectory(wait)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
set(TEST_NAME CommandReaderTest)
16+
17+
set(TEST_SOURCES
18+
CommandReaderTest.cpp
19+
)
20+
all_library_sources("${TEST_SOURCES}")
21+
22+
set(TEST_LIST
23+
trivial_create
24+
read_lines_enum_1
25+
read_lines_enum_1_negative
26+
read_lines_enum_2_singleton
27+
)
28+
29+
set(TEST_EXTRA_LIBRARIES
30+
fastcdr
31+
fastrtps
32+
cpp_utils
33+
)
34+
35+
add_unittest_executable(
36+
"${TEST_NAME}"
37+
"${TEST_SOURCES}"
38+
"${TEST_LIST}"
39+
"${TEST_EXTRA_LIBRARIES}"
40+
"${TEST_NEEDED_SOURCES}"
41+
)

0 commit comments

Comments
 (0)