I want your suggestion on the following pseudo-code. Please suggest how could I improve it, whether or not I could use some design patterns.
// i'm receiving a string containing : id operation arguments
data = read(socket);
tokens = tokenize(data," "); // tokenize the string based on spaces
if(tokens[0] == "A") {
if(tokens[1] == "some_operation") {
// here goes code for some_operation , will use the remaining tokens as arguments for function calls
}
else if(tokens[1] == "some_other_operation") {
// here goes code for some_other_operation , will use the remaining tokens
}
...
else {
// unknown operation
}
}
else if(tokens[0] == "B") {
if(tokens[1] == "some_operation_for_B") {
// do some operation for B
}
else if(tokens[1] == "yet_another_operation") {
// do yet_another_operation for B
}
...
else {
// unknown operation
}
}
I hope you get the point . The thing is I have a large number of id's and each has it's own operations , and I think it's kinda ugly to have 10 screens of code containing a lot of if's and else if's.
Have a class for each ID which implements a common interface. Basically the Strategy pattern IIRC.
So you'd call (pseudo)code like:
StrategyFactory.GetStrategy(tokens[0]).parse(tokens[1..n])
First write down the syntax of what you support, then write the code to support it.
Using BNF notation is great for that. And using the Spirit library for the code-part is quite straightforward.
Command := ACommand | BCommand
ACommand := 'A' AOperation
AOperation := 'some_operation' | 'some_other_operation'
BCommand := 'B' BOperation
BOperation := 'some_operation_for_B' | 'some_other_operation_for_B'
This easily translates into a Spirit parser. Every production rule would become a one-liner, every end-symbol would be translated into a function.
#include "stdafx.h"
#include <boost/spirit/core.hpp>
#include <iostream>
#include <string>
using namespace std;
using namespace boost::spirit;
namespace {
void AOperation(char const*, char const*) { cout << "AOperation\n"; }
void AOtherOperation(char const*, char const*) { cout << "AOtherOperation\n"; }
void BOperation(char const*, char const*) { cout << "BOperation\n"; }
void BOtherOperation(char const*, char const*) { cout << "BOtherOperation\n"; }
}
struct arguments : public grammar<arguments>
{
template <typename ScannerT>
struct definition
{
definition(arguments const& /*self*/)
{
command
= acommand | bcommand;
acommand = chlit<char>('A')
>> ( a_someoperation | a_someotheroperation );
a_someoperation = str_p( "some_operation" ) [ &AOperation ];
a_someotheroperation = str_p( "some_other_operation" )[ &AOtherOperation ];
bcommand = chlit<char>('B')
>> ( b_someoperation | b_someotheroperation );
b_someoperation = str_p( "some_operation_for_B" ) [ &BOperation ];
b_someotheroperation = str_p( "some_other_operation_for_B" )[ &BOtherOperation ];
}
rule<ScannerT> command;
rule<ScannerT> acommand, bcommand;
rule<ScannerT> a_someoperation, a_someotheroperation;
rule<ScannerT> b_someoperation, b_someotheroperation;
rule<ScannerT> const&
start() const { return command; }
};
};
template<typename parse_info >
bool test( parse_info pi ) {
if( pi.full ) {
cout << "success" << endl;
return true;
} else {
cout << "fail" << endl;
return false;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
arguments args;
test( parse( "A some_operation", args, space_p ) );
test( parse( "A some_other_operation", args, space_p ) );
test( parse( "B some_operation_for_B", args, space_p ) );
test( parse( "B some_other_operation_for_B", args, space_p ) );
test( parse( "A some_other_operation_for_B", args, space_p ) );
return 0;
}
You could have a look into "Table Driven Methods" (as described in "Code Complete", 2nd edition, chapter 18).
I think this is what Cheery describes.
A benefit of that is easy extensibility. You just have to add some entries to the table. This table could be hard coded or even loaded at run-time.
Similar to Epaga's suggestion you coul also try to solve this via polymorphism, having specialized classes perform actions for the different cases. The drawback here is that you have to write new classes in case of changes.
You want to split this up into multiple functions, one for each ID, and one for each operation.
A guideline I normally use is a screen height. If I can't have a function in full fit on my screen I start thinking about splitting things up. That way you don't need to scroll just to see where the function is going. As I said, it's a guideline, not a rule, but I find it more practical to be in control of the structure.
If you then want to take an OO approach and turn this into a bunch of classes, you're welcome to do so if you see an advantage. Be mindful of all the plumbing that goes with it, though. You might want to keep it simple.
Dave
I've seen a solution to this problem that worked well: a hash table of functions.
At compile time a Perfect Hash Function is created for each supported operation and the operation is associated with a function to call (the function pointer is the value in the hash, the command string is the key).
During runtime, the command functionality is called by using the command string to find the function in the hash table. Then the function is called passing the "data" string by reference. Each command function then parses out the remaining string according to its rules... the strategy pattern also applies at this point.
Makes the code work like a state machine, which is (IMHO) the easiest way to approach networking code.
Create a map of functions. Then you'd have code like:
consumed_count = token_mapper[tokens[0]](tokens)
remove amount of consumed tokens according to the return value and repeat.
Though, I don't understand your approach anyway, You are going to write a language that's hard to handle and inflexible. Think about it: A small difference in the amount of arguments causes real havoc in that language. Therefore you are always limited to 1-3 arguments per command.
I'd rather just use some lexer/parser generator combination, but if you want to do what you are going to do, I'd propose you at least split first with newline, then with space, and have therefore clear way to see whether it was meant to give 2 or 3 arguments.
It's important even if your language would be machine-generated, what if your generator ends up having a bug? Fail early, fail often.
you could use the command pattern...... each of your actions would know its id and operation and add itself to to a list at run time...then you'd simply look up the right command, pass it whatever context it needs and it will execute the operation.
The table driven aproach seems to fit this, like mxp said. If you have diffrent number of parameters for your functions you could have a column in the table that specifies the number of parameters for the function on the same row.
Related
I have some error codes that I would like represent as strings:
enum class ErrorCode
{
OK,
InvalidInput,
BadAlloc,
Other
};
I want to create an intuitive and simple way of getting strings that represent these errors. The simple solutions is:
std::string const ErrorCode2Str(ErrorCode errorCode)
{
switch (errorCode)
{
case OK:
return "OK";
case InvalidInput:
return "Invalid Input";
case BadAlloc:
return "Allocation Error";
case Other:
return "Other Error";
default:
throw Something;
}
}
Is there a better way? Can I overload an ErrorCode to string cast somehow? Can I create a ErrorCode::str() function? Is there a standard solution to this problem?
One possibility is a map:
class to_str {
std::unordered_map<ErrorCode, std::string> strings;
public:
to_str() {
strings[ErrorCode::OK] = "Ok";
strings[ErrorCode::InvalidInput] = "Invalid Input";
strings[ErrorCode::BadAlloc] = "Allocation Error";
strings[ErrorCode::Other] = "Other";
}
std::string operator()(ErrorCode e) {
return strings[e];
}
};
// ...
auto e = foo(some_input);
if (e != ErrorCode::OK)
std::cerr << to_str()(e);
It's obviously not a huge difference, but I find it at least marginally more readable, and think it's probably a bit more maintainable in the long term.
There is no prefect solution to this, and a lot of libraries out there do what you are currently doing.
But if you want a different way of doing it, you can turn the error into a class like so:
#include <iostream>
#include <string>
class Error
{
public:
Error(int key, std::string message) : key(key), message(message){}
int key;
std::string message;
operator int(){return key;}
operator std::string(){ return message; }
bool operator==(Error rValue){return this->key == rValue.key; }
};
int main()
{
Error e(0, "OK");
int errorCode = e;
std::string errorMessage = e;
std::cout << errorCode << " " << errorMessage;
}
Although many simple ways to do an enum-to-string or string-to-enum conversion exist, I woud like consider, here, a more generalized way.
Why doesn't C++ allow native contruct for it? There are mainly two reasons:
The first is technical: C++ doesn't have any reflection mechanism: compiled symbols simple cease to exist (and become just numbers). And since they don't exist, you cannot get them back.
The second is more a programming issue: enumerals are "shared" between the compiler and the programmer. String literals are shared between the progam and the end-user. That may be not a programmer and may not speak English (and we don't know what he speaks).
A general way to solve the problem is so to spkit it in two parts: one is at stream level, and the other at localization level.
What does it happen when you write std::cout << 42 ?
The operator<<(ostream&, int) implementation, in fact calls use_facet<num_put<char> >(cout.getloc()).do_put(int) which in turn use eventually the numpunct facet that define how to handle signs, decimal separator and digit group separators.
The standard way to handle enumeral output is so, by implementing an ostrea<<enumeral operator that gets a facet and calls on it a method to actually write that string.
Such a facet can them be implemented a number of times and made available for each supported language.
That's not easy and straightforward, but that's how C++ I/O is conceived.
Once you did all that, the idiomatic way to get a string is using a strngstream imbued with a local that supports all the enums and classes required facets.
Too complex? may be. But if you think this is too complicated, stop to teach std::cout << "Hello wrld" << std::endl; and write a more simple "output library".
For example
bool read(Input &input);
Input input; //error
bool success = read(input);
will be an error because Input has no default constructor.
Is there any trickery I can use to get the Input object out of the function in this case? I imagine there must be some unique_ptr trickery available to me, but I'm not sure exactly how. Feel free to suggest other methods.
Please suggest with example how the read function could look.
I would rather not create a (meaningless) default constructor for Input just for this purpose, and note that this is just a silly example, so don't attach any special meaning to the words "Input", "read", etc. :)
bool read(unique_ptr<Input> &input) // read asume input is disposable/empty
{ ....
input.reset(new Input( a,d,c ) );
....
}
....
unique_ptr<Input> input; //error ?
bool success = read(input);
if (input)
if (succes)
input->X();
else
input->Y();
unique_ptr<Input> input_ptr = read();
where read() is defined as:
unique_ptr<Input> read()
{
.
.
.
return unique_ptr<Input>(new Input(x,y,z));
}
From the comments, it appears that your problem is to design a function that
can fail (and if so should signal that to caller),
but if not, produces a value of a type without a default cconstructor
The first point is easy: use exceptions.
The second point is also easy: use the function return value feature.
I.e.,
Object foo()
{
if( "didna wrok" )
{
throw std::runtime_error( "foo: I failed, miserably" );
}
return Object( arg1, arg2, arg3 );
}
Now there also many other ways to do this, but the above is the most natural, directly using the language features that are intended to support and fully solve these aspects.
If you are in pre-C+11 world, there is a workaround by use of malloc:
bool read(Input &input); // keep the function read intact
Input* input = static_cast<Input*>(malloc(sizeof(Input))); // bypass constructor
bool success = read(*input);
...
free(input); // don't forget to free input later
I have the output of another program that was more intended to be human readable than machine readable, but yet am going to parse it anyway. It's nothing too complex.
Yet, I'm wondering what the best way to do this in C++ is. This is more of a 'general practice' type of question.
I looked into Boost.Spirit, and even got it working a bit. That thing is crazy! If I was designing the language that I was reading, it might be the right tool for the job. But as it is, given its extreme compile-times, the several pages of errors from g++ when I do anything wrong, it's just not what I need. (I don't have much need for run-time performance either.)
Thinking about using C++ operator <<, but that seems worthless. If my file has lines like "John has 5 widgets", and others "Mary works at 459 Ramsy street" how can I even make sure I have a line of the first type in my program, and not the second type? I have to read the whole line and then use things like string::find and string::substr I guess.
And that leaves sscanf. It would handle the above cases beautifully
if( sscanf( str, "%s has %d widgets", chararr, & intvar ) == 2 )
// then I know I matched "foo has bar" type of string,
// and I now have the parameters too
So I'm just wondering if I'm missing something or if C++ really doesn't have much built-in alternative.
sscanf does indeed sound like a pretty good fit for your requirements:
you may do some redundant parsing, but you don't have performance requirements prohibiting that
it localises the requirements on the different input words and allows parsing of non-string values directly into typed variables, making the different input formats easy to understand
A potential problem is that it's error prone, and if you have lots of oft-changing parsing phrases then the testing effort and risk can be worrying. Keeping the spirit of sscanf but using istream for type safety:
#include <iostream>
#include <sstream>
// Str captures a string literal and consumes the same from an istream...
// (for non-literals, better to have `std::string` member to guarantee lifetime)
class Str
{
public:
Str(const char* p) : p_(p) { }
const char* c_str() const { return p_; }
private:
const char* p_;
};
bool operator!=(const Str& lhs, const Str& rhs)
{
return strcmp(lhs.c_str(), rhs.c_str()) != 0;
}
std::istream& operator>>(std::istream& is, const Str& str)
{
std::string s;
if (is >> s)
if (s.c_str() != str)
is.setstate(std::ios_base::failbit);
return is;
}
// sample usage...
int main()
{
std::stringstream is("Mary has 4 cats");
int num_dogs, num_cats;
if (is >> Str("Mary") >> Str("has") >> num_dogs >> Str("dogs"))
{
std::cout << num_dogs << " dogs\n";
}
else if (is.clear(), is.seekg(0), // "reset" the stream...
(is >> Str("Mary") >> Str("has") >> num_cats >> Str("cats")))
{
std::cout << num_cats << " cats\n";
}
}
The GNU tools flex and bison are very powerful tools you could use that are along the lines of Spirit but (according to some people) easier to use, partially because the error reporting is a bit better since the tools have their own compilers. This, or Spirit, or some other parser generator, is the "correct" way to go with this because it affords you the greatest flexibility in your approach.
If you're thinking about using strtok, you might want to instead take a look at stringstream, which splits on whitespace and lets you do some nice formatting conversions between strings, primitives, etc. It can also be plugged into the STL algorithms, and avoids all the messy details of raw C-style string memory management.
I've written extensive parsing code in C++. It works just great for that, but I wrote the code myself and didn't rely on more general code written by someone else. C++ doesn't come with extensive code already written, but it's a great language to write such code in.
I'm not sure what your question is beyond just that you'd like to find code someone has already written that will do what you need. Part of the problem is that you haven't really described what you need, or asked a question for that matter.
If you can make the question more specific, I'd be happy to try and offer a more specific answer.
I've used Boost.Regex (Which I think is also tr1::regex). Easy to use.
there is always strtok() I suppose
Have a look at strtok.
Depending on exactly what you want to parse, you may well want a regular expression library.
See msdn or earlier question.
Personally, again depending the exact format, I'd consider using perl to do an initial conversion into a more machine readable format (E.g. variable record CSV) and then import into C++ much more easily.
If sticking to C++, you need to:
Identify a record - hopefully just a
line
Determine the type of the record - use regex
Parse the record - scanf is fine
A base class on the lines of:
class Handler
{
public:
Handler(const std::string& regexExpr)
: regex_(regexExpr)
{}
bool match(const std::string& s)
{
return std::tr1::regex_match(s,regex_);
}
virtual bool process(const std::string& s) = 0;
private:
std::tr1::basic_regex<char> regex_;
};
Define a derived class for each record type, stick an instance of each in a set and search for matches.
class WidgetOwner : public Handler
{
public:
WidgetOwner()
: Handler(".* has .* widgets")
{}
virtual bool process(const std::string& s)
{
char name[32];
int widgets= 0;
int fieldsRead = sscanf( s.c_str(), "%32s has %d widgets", name, & widgets) ;
if (fieldsRead == 2)
{
std::cout << "Found widgets in " << s << std::endl;
}
return fieldsRead == 2;
}
};
struct Pred
{
Pred(const std::string& record)
: record_(record)
{}
bool operator()(Handler* handler)
{
return handler->match(record_);
}
std::string record_;
};
std::set<Handler*> handlers_;
handlers_.insert(new WidgetOwner);
handlers_.insert(new WorkLocation);
Pred pred(line);
std::set<Handler*>::iterator handlerIt =
std::find_if(handlers_.begin(), handlers_.end(), pred);
if (handlerIt != handlers_.end())
(*handlerIt)->process(line);
I think the problem is pretty common. You have some input string, and have to call a function depending on the content of the string. Something like a switch() for strings.
Think of command line options.
Currently I am using:
using std::string;
void Myclass::dispatch(string cmd, string args) {
if (cmd == "foo")
cmd_foo(args);
else if (cmd == "bar")
cmd_bar(args);
else if ...
...
else
cmd_default(args);
}
void Myclass::cmd_foo(string args) {
...
}
void Myclass::cmd_bar(string args) {
...
}
and in the header
class Myclass {
void cmd_bar(string args);
void cmd_foo(string args);
}
So every foo and bar I have to repeat four (4!) times. I know I can feed the function pointers and strings to an static array before and do the dispatching in a loop, saving some if...else lines. But is there some macro trickery (or preprocessor abuse, depending on the POV), which makes is possible to somehow define the function and at the same time have it update the array automagically?
So I would have to write it only twice, or possibly once if used inline?
I am looking for a solution in C or C++.
It sounds like you're looking for the Command pattern
Something like this:
Create a map like this
std::map<std::string, Command*> myMap;
then just use your key to execute the command like this....
std::map<std::string, Command*>::iterator it = myMap.find(str);
if( it != myMap.end() ) {
it->second->execute()
}
To register your commands you just do this
myMap["foo"] = new CommandFoo("someArgument");
myMap["bar"] = new CommandBar("anotherArgument");
The basic solution, per my link in the question comment, is to map a string to a function call of some sort.
To actually register the string -> function pointer/functor pair:
Firstly, have a singleton (shock! horror!) dispatcher object.
Let's call it TheDispatcher - it's a wrapper for a map<string,Func>, where
Func is your function pointer or functor type.
Then, have a register class:
struct Register {
Register( comst string & s, Func f ) {
TheDispatcher.Add( s, f );
}
};
Now in your individual compilation units you create
static objects (shock! horror!):
Register r1_( "hello", DoSayHello );
These objects will be created (assuming the code is not in a static library) and will automatically register with TheDispatcher.
And at run-time, you look up strings in TheDispatcher and execute the associated function/functor.
as alternative to the Command pattern you can build an hashtable of string -> function pointers:
typedef void (*cmd)(string);
The ugly macro solution, which you kind-of asked for. Note that it doesn't automatically register, but it does keep some things synchronized, and also will cause compile errors if you only add to mappings, and not the function in the source file.
Mappings.h:
// Note: no fileguard
// The first is the text string of the command,
// the second is the function to be called,
// the third is the description.
UGLY_SUCKER( "foo", cmd_foo, "Utilize foo." );
UGLY_SUCKER( "bar", cmd_bar, "Turn on bar." );
Parser.h:
class Myclass {
...
protected:
// The command functions
#define UGLY_SUCKER( a, b, c ) void b( args )
#include Mappings.h
#undef UGLY_SUCKER
};
Parser.cpp:
void Myclass::dispatch(string cmd, string args) {
if (cmd == "")
// handle empty case
#define UGLY_SUCKER( a, b, c ) else if (cmd == a) b( args )
#include Mappings.h
#undef UGLY_SUCKER
else
cmd_default(args);
}
void Myclass::printOptions() {
#define UGLY_SUCKER( a, b, c ) std::cout << a << \t << c << std::endl
#include Mappings.h
#undef UGLY_SUCKER
}
void Myclass::cmd_foo(string args) {
...
}
You'll have to at least define the functions and add them to some registry. (If they are to be non-inline member functions of some class, you'll also have to declare them.) Other than some domain-specific language generating the actual code (like cjhuitt's macro hackery), I see no way around mentioning these functions two (or three) times.
I would like to have an easy to use way to write code like:
#include <iostream>
int main (){
std::cout << "hello, world!\n";
}
but that supports i18n. Here is an example using gettext():
#include <libintl.h>
#include <iostream>
int main (){
std::cout << gettext("hello, world!\n");
}
This can then be processed by xgettext to produce a message catalog file that can be used
by translators to create various versions. These extra files can be handled on target
systems to allow the user to interact in a preferred language.
I would like to write the code something like this instead:
#include <i18n-iostream>
int main (){
i18n::cout << "hello, world!\n";
}
At build time the quoted strings would be examined by a program like xgettext to produce the
base message catalog file. << operator with argument i18n::cout would take a string
literal as the key to lookup the run-time text to use from a message catalog.
Does it exist somewhere?
At build time the quoted strings would be examined by a program like xgettext to produce the base message catalog file. << operator with argument i18n::cout would take a string literal as the key to lookup the run-time text to use from a message catalog.
You try to convert a string like a single instance, but it isn't/
The point, you don't want something like this. Think of:
if(n=1)
i18n::cout << "I need one apple"
else
i18n::cout << "I need " << n << " apples" ;
So why this is would not work, because "n=1" or "n!=1" works only for English, many other languages have more then one plural form, also it requires translation of "I need X apples" as signle instance.
I suggest you just to learn to deal with gettext, it is quite simple and powerful, many people had thought about it.
Another point, you are usually do not call gettext but
#include <libintl.h>
#include <iostream>
#define _(x) gettext(x)
int main (){
std::cout << _("hello, world!\n");
}
This makes the code much cleaner, also it is quite a "standard" feature to use "_" as gettext alias.
Just learn how to use it, before you try to make "nicer" API. Just to mention, gettext API is quite de-facto standard for many languages, not only C.
The short answer is "No" :)
Seriously, which aspects of internationalization are you interested in? ICU provides pretty much everything but does not feel like standard C++. There are other libraries smaller in scope that provide some i18n functionalities, i.e. UTF-CPP for handling UTF-8 encoded strings.
Personally I would go with this answer, but it might be possible to use a bit of streambuf magic to do this as the text is written to the stream. If you're really interested in doing this though, please take a look at Standard C++ IOStreams and Locales by Langer and Kreft, it's the bible of iostreams.
The following assumes that everything written to the buffer is to be translated, and that each full line can be translated completely:
std::string xgettext (std::string const & s)
{
return s;
}
The following transbuf class overrides the "overflow" function and
translates the buffer every time it sees a newline.
class transbuf : public std::streambuf {
public:
transbuf (std::streambuf * realsb) : std::streambuf (), m_realsb (realsb)
, m_buf () {}
~transbuf () {
// ... flush m_buf if necessary
}
virtual std::streambuf::int_type overflow (std::streambuf::int_type c) {
m_buf.push_back (c);
if (c == '\n') {
// We have a complete line, translate it and write it to our stream:
std::string transtext = xgettext (m_buf);
for (std::string::const_iterator i = transtext.begin ()
; i != transtext.end ()
; ++i) {
m_realsb->sputc (*i);
// ... check that overflow returned the correct value...
}
m_buf = "";
}
return c;
}
std::streambuf * get () { return m_realsb; }
// data
private:
std::streambuf * m_realsb;
std::string m_buf;
};
And here's an example of how that might be used:
int main ()
{
transbuf * buf = new transbuf (std::cout.rdbuf ());
std::ostream trans (buf);
trans << "Hello"; // Added to m_buf
trans << " World"; // Added to m_buf
trans << "\n"; // Causes m_buf to be written
trans << "Added to buffer\neach new line causes\n"
"the string to be translated\nand written" << std::endl;
delete buf;
}
You mean you just want another API? You could write a small wrapper, shouldn't be too hard and it would give you the possibility to use the best API you can think of :)