Polymorphic Command Parser Design - c++

Would love some opinions on this problem I'm trying to workout. I'm trying to improve my OO experience and fully leverage C++'s polymorphic capabilities. I'm trying to write some code for a basic command parser. They command structure goes as so:
[command name] [arguments]
The command name will just be limited to a one word string. The arguments can be a 0 to N list of strings.
Each command and list of arguments could be directed to any variety of software objects in my system. So for example I could have an rtp statistics command map to my rtp module, the user statistics to my user module. Something like that.
Right now the entry point for my CLI provides the entire command string as a standard string. And it provides a standard output stream for displaying results to the user.
I really want to avoid using a parser function and then doing an if then else kind of deal. So I was thinking something like this:
I would have a base class called command. Its constructor would take the string command, the stdout, and an interface for the object it needs to interact with.
I would create a command factory that would match the command name to the object that handles it. This would instantiate the right command object for the right command.
Each separate command object would parse the given arguments and make the right choices for this command.
What I'm struggling with is how to give the right module to the right command. Is this where I should use a template argument? So that each command can take any interface and I'll let the factory decide which module to pass in to the command object?
I'm also open to other opinions as well. I'm just trying to learn and hoping the community can give me some tips :-).

What you're looking for is a common pattern in OOP. Design Patterns (the Gang of Four book) referred to this as a Command Pattern.
There's generally no need for templates. Everything is parsed and dispatched at runtime, so dynamic polymorphism (virtual functions) is probably a better choice.
In another answer, Rafael Baptista suggested a basic design. Here is how I would modify his design to be more complete:
Command objects and CommandDispatcher
Commands are handled by subclasses of the Command class. Commands are dispatched by a CommandDispatcher object that handles the basic parsing of the command string (basically, splitting at spaces, possibly handling quoted strings, etc.).
The system registers an instance of Command with the CommandDispatcher, and associates each instance of Command with a command name (std::string). The association is handled by a std::map object, although that could be replaced by a hash table (or similar structure to associate key-value pairs).
class Command
{
public:
virtual ~Command(void);
virtual void execute(FILE* in, const std::vector<std::string>& args) = 0;
};
class CommandDispatcher
{
public:
typedef std::map<std::string, Command*> CommandMap;
void registerCommand(const std::string& commandName, Command* command)
{
CommandMap::const_iterator cmdPair = registeredCommands.find(commandName);
if (cmdPair != registeredCommands.end())
{
// handle error: command already registered
}
else
{
registeredCommands[commandName] = command;
}
}
// possibly include isRegistered, unregisterCommand, etc.
void run(FILE* in, const std::string& unparsedCommandLine); // parse arguments, call command
void dispatch(FILE* in, const std::vector<std::string>& args)
{
if (! args.empty())
{
CommandMap::const_iterator cmdPair = registeredCommands.find(args[0]);
if (cmdPair == registeredCommands.end())
{
// handle error: command not found
}
else
{
Command* cmd = cmdPair->second;
cmd->execute(in, args);
}
}
}
private:
CommandMap registeredCommands;
};
I've left the parsing, and other details out, but this is a pretty common structure for command patterns. Notice how the std::map handles associating the command name with the command object.
Registering commands
To make use of this design, you need to register commands in the system. You need to instantiate CommandDispatcher, either using a Singleton pattern, in main, or in another central location.
Then, you need to register the command objects. There are several ways to do this. The way I prefer, because you have more control, is to have each module (set of related commands) provide its own registration function. For example, if you have a 'File IO' module, then you might have a function fileio_register_commands:
void fileio_register_commands(CommandDispatcher* dispatcher)
{
dispatcher->registerCommand( "readfile", new ReadFileCommand );
dispatcher->registerCommand( "writefile", new WriteFileCommand );
// etc.
}
Here ReadFileCommand and WriteFileCommand are subclasses of Command that implement the desired behavior.
You have to make sure to call fileio_register_commands before the commands become available.
This approach can be made to work for dynamically loaded libraries (DLLs or shared libraries). Make sure that the function to register commands has a regular pattern, based on the name of the module: XXX_register_commands, where XXX is, for example, the lower cased module name. After you load the shared library or DLL, your code can determine whether such a function exists, and then call it.

Templates is overkill. I imagine you want something where the command interpreter just figures out what commands are possible from the objects that are available.
For each class that wants to support this CLI, I'd give it a function that registers the class, and the command name that triggers that class.
class CLIObject
{
virtual void registerCli( Cli& cli ) = 0;
virtual bool doCommand( FILE* file, char** args ) = 0;
}
class HelloWorld : public ClIObject
{
void registerCli( Cli& cli ) { cli.register( this, "helloworld" ); }
bool doCommand( FILE* file, char** args )
{
if ( !args[0] ) return false;
fprintf( file, "hello world! %s", args[0] );
return true;
}
}
Now your cli can support any class that derives from CLIObject.

Related

OOP for global system/task monitoring class

I'm trying to create a performance monitor of sorts to run on a Particle board (STM32 based). I'm used to programming in c so the OOP approach is a bit new but I think it would fit well here.
For the purpose of this question let's assume I have two types of monitors:
Frequency. The application can call a "tick" method of the monitor to calculate the time since it last ran and store it.
Period- call a "start" and "stop" method of the monitor to calculate how long a process takes to run and store it.
What I would like to do is to create instances of these monitors throughout my application and be able to report on the stats of all monitors of all types from the main module.
I've read about the singleton design pattern which seems like it might be what I need but I'm not sure and I'm also concerned about thread safety with that.
I'm thinking I will create a "StatMonitor" class and a derived class "FrequencyMonitor" and "PeriodMonitor". Monitor would be a singleton and everywhere I wanted to create a new monitor I would request an instance of "Monitor" and use that like so:
freqMonitor * task1FreqMonitor = StatMonitor::GetInstance()->Add_Freq_Monitor("Task1");
The StatMonitor would track all monitors I've added and when I wanted to print the stats I could just call the printAll method which would iterate it's array of monitors and request their results like so:
StatMonitor::GetInstance()->PrintAllStats();
Am I going down the right path?
Your path sounds good, except that FrequencyMonitor and PeriodMonitor should not derive from the class that "manages" all these monitors (let's call it MonitorPrinter).
MonitorPrinter should be a singleton and could look like this:
class MonitorPrinter
{
public:
static MonitorPrinter& getInstance()
{
static MonitorPrinter monitorPrinter;
return monitorPrinter;
}
void printAllStats()
{
for (const auto& [_, frequencyMonitor] : _frequencyMonitors)
frequencyMonitor.print();
for (const auto& [_, periodMonitor] : _periodMonitors)
periodMonitor.print();
}
FrequencyMonitor& getFrequencyMonitor(std::string name)
{ return _frequencyMonitors[name]; }
PeriodMonitor& getPeriodMonitor(std::string name)
{ return _periodMonitors[name]; }
private:
MonitorPrinter() = default;
std::map<std::string, FrequencyMonitor> _frequencyMonitors;
std::map<std::string, PeriodMonitor> _periodMonitors;
};
Demo
(The const auto& [_, frequencyMonitor] is a structured binding).
FrequencyMonitor and PeriodMonitor should not have anything to do with singletons, and from your description, they need not be part of a class hierarchy either (as they have different interfaces). If you want, you can prevent users (other than the MonitorPrinter) from instantiating these classes using other techniques, but I won't elaborate on that here.
In short, there is no need to use OOP here. Use a singleton to provide (and keep track of) the monitors, and implement the monitors to your liking. Be wary of thread safety if this is relevant (the above is not thread-safe!).

c++ best way to realise global switches/flags to control program behaviour without tying the classes to a common point

Let me elaborate on the title:
I want to implement a system that would allow me to enable/disable/modify the general behavior of my program. Here are some examples:
I could switch off and on logging
I could change if my graphing program should use floating or pixel coordinates
I could change if my calculations should be based upon some method or some other method
I could enable/disable certain aspects like maybe a extension api
I could enable/disable some basic integrated profiler (if I had one)
These are some made-up examples.
Now I want to know what the most common solution for this sort of thing is.
I could imagine this working with some sort of singelton class that gets instanced globally or in some other globally available object. Another thing that would be possible would be just constexpr or other variables floating around in a namespace, again globally.
However doing something like that, globally, feels like bad practise.
second part of the question
This might sound like I cant decide what I want, but I want a way to modify all these switches/flags or whatever they are actually called in a single location, without tying any of my classes to it. I don't know if this is possible however.
Why don't I want to do that? Well I like to make my classes somewhat reusable and I don't like tying classes together, unless its required by the DRY principle and or inheritance. I basically couldn't get rid of the flags without modifying the possible hundreds of classes that used them.
What I have tried in the past
Having it all as compiler defines. This worked reasonably well, however I didnt like that I couldnt make it so if the flag file was gone there were some sort of default settings that would make the classes themselves still operational and changeable (through these default values)
Having it as a class and instancing it globally (system class). Worked ok, however I didnt like instancing anything globally. Also same problem as above
Instancing the system class locally and passing it to the classes on construction. This was kinda cool, since I could make multiple instruction sets. However at the same time that kinda ruined the point since it would lead to things that needed to have one flag set the same to have them set differently and therefore failing to properly work together. Also passing it on every construction was a pain.
A static class. This one worked ok for the longest time, however there is still the problem when there are missing dependencies.
Summary
Basically I am looking for a way to have a single "place" where I can mess with some values (bools, floats etc.) and that will change the behaviour of all classes using them for whatever, where said values either overwrite default values or get replaced by default values if said "place" isnt defined.
If a Singleton class does not work for you , maybe using a DI container may fit in your third approach? It may help with the construction and make the code more testable.
There are some DI frameworks for c++, like https://github.com/google/fruit/wiki or https://github.com/boost-experimental/di which you can use.
If you decide to use switch/flags, pay attention for "cyclometric complexity".
If you do not change the skeleton of your algorithm but only his behaviour according to the objets in parameter, have a look at "template design pattern". This method allow you to define a generic algorithm and specify particular step for a particular situation.
Here's an approach I found useful; I don't know if it's what you're looking for, but maybe it will give you some ideas.
First, I created a BehaviorFlags.h file that declares the following function:
// Returns true iff the given feature/behavior flag was specified for us to use
bool IsBehaviorFlagEnabled(const char * flagName);
The idea being that any code in any of your classes could call this function to find out if a particular behavior should be enabled or not. For example, you might put this code at the top of your ExtensionsAPI.cpp file:
#include "BehaviorFlags.h"
static const enableExtensionAPI = IsBehaviorFlagEnabled("enable_extensions_api");
[...]
void DoTheExtensionsAPIStuff()
{
if (enableExtensionsAPI == false) return;
[... otherwise do the extensions API stuff ...]
}
Note that the IsBehaviorFlagEnabled() call is only executed once at program startup, for best run-time efficiency; but you also have the option of calling IsBehaviorFlagEnabled() on every call to DoTheExtensionsAPIStuff(), if run-time efficiency is less important that being able to change your program's behavior without having to restart your program.
As far as how the IsBehaviorFlagEnabled() function itself is implemented, it looks something like this (simplified version for demonstration purposes):
bool IsBehaviorFlagEnabled(const char * fileName)
{
// Note: a real implementation would find the user's home directory
// using the proper API and not just rely on ~ to expand to the home-dir path
std::string filePath = "~/MyProgram_Settings/";
filePath += fileName;
FILE * fpIn = fopen(filePath.c_str(), "r"); // i.e. does the file exist?
bool ret = (fpIn != NULL);
fclose(fpIn);
return ret;
}
The idea being that if you want to change your program's behavior, you can do so by creating a file (or folder) in the ~/MyProgram_Settings directory with the appropriate name. E.g. if you want to enable your Extensions API, you could just do a
touch ~/MyProgram_Settings/enable_extensions_api
... and then re-start your program, and now IsBehaviorFlagEnabled("enable_extensions_api") returns true and so your Extensions API is enabled.
The benefits I see of doing it this way (as opposed to parsing a .ini file at startup or something like that) are:
There's no need to modify any "central header file" or "registry file" every time you add a new behavior-flag.
You don't have to put a ParseINIFile() function at the top of main() in order for your flags-functionality to work correctly.
You don't have to use a text editor or memorize a .ini syntax to change the program's behavior
In a pinch (e.g. no shell access) you can create/remove settings simply using the "New Folder" and "Delete" functionality of the desktop's window manager.
The settings are persistent across runs of the program (i.e. no need to specify the same command line arguments every time)
The settings are persistent across reboots of the computer
The flags can be easily modified by a script (via e.g. touch ~/MyProgram_Settings/blah or rm -f ~/MyProgram_Settings/blah) -- much easier than getting a shell script to correctly modify a .ini file
If you have code in multiple different .cpp files that needs to be controlled by the same flag-file, you can just call IsBehaviorFlagEnabled("that_file") from each of them; no need to have every call site refer to the same global boolean variable if you don't want them to.
Extra credit: If you're using a bug-tracker and therefore have bug/feature ticket numbers assigned to various issues, you can creep the elegance a little bit further by also adding a class like this one:
/** This class encapsulates a feature that can be selectively disabled/enabled by putting an
* "enable_behavior_xxxx" or "disable_behavior_xxxx" file into the ~/MyProgram_Settings folder.
*/
class ConditionalBehavior
{
public:
/** Constructor.
* #param bugNumber Bug-Tracker ID number associated with this bug/feature.
* #param defaultState If true, this beheavior will be enabled by default (i.e. if no corresponding
* file exists in ~/MyProgram_Settings). If false, it will be disabled by default.
* #param switchAtVersion If specified, this feature's default-enabled state will be inverted if
* GetMyProgramVersion() returns any version number greater than this.
*/
ConditionalBehavior(int bugNumber, bool defaultState, int switchAtVersion = -1)
{
if ((switchAtVersion >= 0)&&(GetMyProgramVersion() >= switchAtVersion)) _enabled = !_enabled;
std::string fn = defaultState ? "disable" : "enable";
fn += "_behavior_";
fn += to_string(bugNumber);
if ((IsBehaviorFlagEnabled(fn))
||(IsBehaviorFlagEnabled("enable_everything")))
{
_enabled = !_enabled;
printf("Note: %s Behavior #%i\n", _enabled?"Enabling":"Disabling", bugNumber);
}
}
/** Returns true iff this feature should be enabled. */
bool IsEnabled() const {return _enabled;}
private:
bool _enabled;
};
Then, in your ExtensionsAPI.cpp file, you might have something like this:
// Extensions API feature is tracker #4321; disabled by default for now
// but you can try it out via "touch ~/MyProgram_Settings/enable_feature_4321"
static const ConditionalBehavior _feature4321(4321, false);
// Also tracker #4222 is now enabled-by-default, but you can disable
// it manually via "touch ~/MyProgram_Settings/disable_feature_4222"
static const ConditionalBehavior _feature4222(4222, true);
[...]
void DoTheExtensionsAPIStuff()
{
if (_feature4321.IsEnabled() == false) return;
[... otherwise do the extensions API stuff ...]
}
... or if you know that you are planning to make your Extensions API enabled-by-default starting with version 4500 of your program, you can set it so that Extensions API will be enabled-by-default only if GetMyProgramVersion() returns 4500 or greater:
static ConditionalBehavior _feature4321(4321, false, 4500);
[...]
... also, if you wanted to get more elaborate, the API could be extended so that IsBehaviorFlagEnabled() can optionally return a string to the caller containing the contents of the file it found (if any), so that you could do shell commands like:
echo "opengl" > ~/MyProgram_Settings/graphics_renderer
... to tell your program to use OpenGL for its 3D graphics, or etc:
// In Renderer.cpp
std::string rendererType;
if (IsDebugFlagEnabled("graphics_renderer", &rendererType))
{
printf("The user wants me to use [%s] for rendering 3D graphics!\n", rendererType.c_str());
}
else printf("The user didn't specify what renderer to use.\n");

A neat way to apply many (300) methods to one data

I need to apply a lot of functions to the same piece of data in arbitrary order. Different people add different functions. I have created a system, that, after simplification, looks like that:
abstract_filter.h
class AbstractFilter {
void filter(data) = 0;
}
blue_filter.h
class BlueFilter: public AbstractFilter ...
red_filter.h ...
green_filter.h ...
parser.cpp
#include "blue_filter.h"
#include "red_filter.h" //so on
void Parse(const Data data) {
RedFilter redFilter();
redFilter.filter(data);
BlueFilter blueFilter();
blueFilter.filter(data);
....
}
I have hundreds of filters and people always forget to add them to the list or configure. Is it possible to write something like "take all classes from that group/folder and instantiate and put in array...."? I can't make them static or register filters in their constructors because several filtering stacks can be active in the same time.
All I want is to not have to manually enumerate all filters. Would be great to put them in place by just adding them to the project.
Write a python script which parses the filter directory entries an adds them to a generic factory or processing class. If the script runs on every build process the filters will always be taken care of.

Boost.Python - Passing boost::python::object as argument to python function?

So I'm working on a little project in which I'm using Python as an embedded scripting engine. So far I've not had much trouble with it using boost.python, but there's something I'd like to do with it if it's possible.
Basically, Python can be used to extend my C++ classes by adding functions and even data values to the class. I'd like to be able to have these persist in the C++ side, so one python function can add data members to a class, and then later the same instance passed to a different function will still have them. The goal here being to write a generic core engine in C++, and let users extend it in Python in any way they need without ever having to touch the C++.
So what I thought would work was that I would store a boost::python::object in the C++ class as a value self, and when calling the python from the C++, I'd send that python object through boost::python::ptr(), so that modifications on the python side would persist back to the C++ class. Unfortunately when I try this, I get the following error:
TypeError: No to_python (by-value) converter found for C++ type: boost::python::api::object
Is there any way of passing an object directly to a python function like that, or any other way I can go about this to achieve my desired result?
Thanks in advance for any help. :)
Got this fantastic solution from the c++sig mailing list.
Implement a std::map<std::string, boost::python::object> in the C++ class, then overload __getattr__() and __setattr__() to read from and write to that std::map. Then just send it to the python with boost::python::ptr() as usual, no need to keep an object around on the C++ side or send one to the python. It works perfectly.
Edit: I also found I had to override the __setattr__() function in a special way as it was breaking things I added with add_property(). Those things worked fine when getting them, since python checks a class's attributes before calling __getattr__(), but there's no such check with __setattr__(). It just calls it directly. So I had to make some changes to turn this into a full solution. Here's the full implementation of the solution:
First create a global variable:
boost::python::object PyMyModule_global;
Create a class as follows (with whatever other information you want to add to it):
class MyClass
{
public:
//Python checks the class attributes before it calls __getattr__ so we don't have to do anything special here.
boost::python::object Py_GetAttr(std::string str)
{
if(dict.find(str) == dict.end())
{
PyErr_SetString(PyExc_AttributeError, JFormat::format("MyClass instance has no attribute '{0}'", str).c_str());
throw boost::python::error_already_set();
}
return dict[str];
}
//However, with __setattr__, python doesn't do anything with the class attributes first, it just calls __setattr__.
//Which means anything that's been defined as a class attribute won't be modified here - including things set with
//add_property(), def_readwrite(), etc.
void Py_SetAttr(std::string str, boost::python::object val)
{
try
{
//First we check to see if the class has an attribute by this name.
boost::python::object obj = PyMyModule_global["MyClass"].attr(str.c_str());
//If so, we call the old cached __setattr__ function.
PyMyModule_global["MyClass"].attr("__setattr_old__")(ptr(this), str, val);
}
catch(boost::python::error_already_set &e)
{
//If it threw an exception, that means that there is no such attribute.
//Put it on the persistent dict.
PyErr_Clear();
dict[str] = val;
}
}
private:
std::map<std::string, boost::python::object> dict;
};
Then define the python module as follows, adding whatever other defs and properties you want:
BOOST_PYTHON_MODULE(MyModule)
{
boost::python::class_<MyClass>("MyClass", boost::python::no_init)
.def("__getattr__", &MyClass::Py_GetAttr)
.def("__setattr_new__", &MyClass::Py_SetAttr);
}
Then initialize python:
void PyInit()
{
//Initialize module
PyImport_AppendInittab( "MyModule", &initMyModule );
//Initialize Python
Py_Initialize();
//Grab __main__ and its globals
boost::python::object main = boost::python::import("__main__");
boost::python::object global = main.attr("__dict__");
//Import the module and grab its globals
boost::python::object PyMyModule = boost::python::import("MyModule");
global["MyModule"] = PyMyModule;
PyMyModule_global = PyMyModule.attr("__dict__");
//Overload MyClass's setattr, so that it will work with already defined attributes while persisting new ones
PyMyModule_global["MyClass"].attr("__setattr_old__") = PyMyModule_global["MyClass"].attr("__setattr__");
PyMyModule_global["MyClass"].attr("__setattr__") = PyMyModule_global["MyClass"].attr("__setattr_new__");
}
Once you've done all of this, you'll be able to persist changes to the instance made in python over to the C++. Anything that's defined in C++ as an attribute will be handled properly, and anything that's not will be appended to dict instead of the class's __dict__.

Can you use multiple message domains in boost::locale?

I have a number of applications that share a number of general libraries. I am trying to internationalize my applications using boost::locale. It will be easy for me to create a separate .mo file for each general library and for each specific application. I was wandering if it is possible to simultaneously use multiple message domains like this:
boost::locale::generator gen;
gen.add_messages_path(".");
gen.add_messages_domain("lib1");
gen.add_messages_domain("lib2");
std::locale::global(gen("zh_CN.UTF-8"));
.
.
.
boost::locale::gettext("Show image");
I was expecting boost::locale to search in both lib1.mo and lib2.mo, however this doesn't seem to work. Only messages from the first domain added are found, in this case from lib1.mo. If I add lib2 before lib1, then only messages from lib2 are found.
I know you can use a domain explicitly in the call like this:
boost::locale::dgettext("lib2", "Show image");
This does work, but I would like to avoid specifying the domain for every call. I am also not sure that this will work well with extracting the strings with xgettext.
Is it possible what I am trying to do? Am I missing something?
Please suggest any alternative if you know one.
I use msvc 9.0 (2008) and boost 1.48.
Since there were no answers posted to this question I assume that this is not possible with boost::locale. I will shortly therefore outline what I did to achieve my required functionality:
I created a singleton class with the following interface
class MY_GETTEXT
{
public:
void SetPath(const std::string& i_path);
void AddDomain(const std::string& i_domain);
void ChangeLocale(const std::string& i_locale);
std::string gettext(const std::string i_msg_id);
};
AddDomain is called for each domain you want to use, and adds it to a member set m_language_domains_a. ChangeLocale does some locale manipulation and stores a locale in the member m_locale, I will ignore its implementation here.
To translate you should simply call MY_GETTEXT::gettext. Its implementation looks like this:
std::string MY_GETTEXT::gettext(const std::string i_msg_id)
{
BOOST_FOREACH(const std::string& domain , m_language_domains_a)
{
if (boost::locale::translate(i_msg_id).str(m_locale, domain) != i_msg_id)
{
return boost::locale::translate(i_msg_id).str(m_locale, domain);
}
}
return i_msg_id;
}