Defining Enum custom types for Qt D-Bus introspection - dbus

I am working with QDBUS which has the custom type as Enum. After googling I found below link which explains marshalling of QDBUS custom types.
http://techbase.kde.org/Development/Tutorials/D-Bus/CustomTypes#Adventurous_serialization_of_enumerations
This doesnot explain the annotation to be specified in the QTDBUS interospection xml to generate proxy using qdbusxml2cpp.
How to add Enum annotations in QTDBUS interospection xml?
Please if possible explain with some sample code.

I found a solution for my problem:
First create a new header file called enums.h which looks like:
#ifndef ENUMS_H
#define ENUMS_H
#include <QtDBus>
#include "enumDBus.h"
enum Color {
RED = 0,
BLUE,
GREEN
};
Q_DECLARE_METATYPE(Color)
#endif /* ENUMS_H */
Note following line #include "enumDBus.h", you can find this header file here!
So after you declared the enum you can declare a method which takes the enum as argument, in this example I declared following method in calculator.h:
void setColor(Color color);
The implementation for this method:
void Calculator::setColor(Color c)
{
switch (c) {
case BLUE: std::cout << "Color: blue" << std::endl;
break;
case GREEN: std::cout << "Color: green" << std::endl;
break;
case RED: std::cout << "Color: reed" << std::endl;
break;
default:
std::cout << "Color: FAIL!" << std::endl;
}
}
Now let's generate the Interface description (xml), use following command
qdbuscpp2xml -M -s calculator.h -o com.meJ.system.CalculatorInterface.xml
The generation of method which contains custom types doesn't work properply, so we need to do some adjustments:
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="com.meJ.system.CalculatorInterface">
<method name="setColor">
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="Color"/>
<arg type="(i)" direction="in" name="c"/>
</method>
</interface>
</node>
With this xml file we can simply create our adaptors and interfaces classes.
In our main.cpp (on client and server!) we have to register our custom type:
int main(int argc, char** argv)
{
qRegisterMetaType<Color>("Color");
qDBusRegisterMetaType<Color>();
}
Client Side
Include generated calculatorInterface.h and enums.h in your main.cpp.
Now you can simply call your method:
int main(int argc, char** argv)
{
qRegisterMetaType<Color>("Color");
qDBusRegisterMetaType<Color>();
QDBusConnection dbus = QDBusConnection::sessionBus();
com::meJ::system::CalculatorInterface *calculator = new com::meJ::system::CalculatorInterface("com.meJ.system", "/Calc", dbus);
if (calculator->isValid() == false) {
cerr << "ERROR: " << qPrintable(calculator->lastError().message()) << endl;
exit(1);
}
Color c = GREEN;
calculator->setColor(c);
std::cout << qPrintable(calculator->lastError().message()) << std::endl;
exit(0);
}
If everything worked you should see following output at your server programm:
~# Color: green

Related

C program to receive TCP data stream [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have to write a program in the C language to receive TCP data streams. I would like to know
What is effort required considering I am new to networking and C programming?
Also, I came across the Boost C++ libraries. I want to understand, do those libraries provide a ready made TCP client and Server creation programs or do they provide the basics on which we can further work on?
Here is TCP client C++ code with boost library as you asked in comment
#include <iostream>
#include <boost/asio.hpp>
using namespace boost::asio;
using ip::tcp;
using std::string;
using std::cout;
using std::endl;
int main() {
boost::asio::io_service io_service;
//socket creation
tcp::socket socket(io_service);
//connection
socket.connect( tcp::endpoint( boost::asio::ip::address::from_string("127.0.0.1"), 1234 ));
// request/message from client
const string msg = "Hello from Client!\n";
boost::system::error_code error;
boost::asio::write( socket, boost::asio::buffer(msg), error );
if( !error ) {
cout << "Client sent hello message!" << endl;
}
else {
cout << "send failed: " << error.message() << endl;
}
// getting response from server
boost::asio::streambuf receive_buffer;
boost::asio::read(socket, receive_buffer, boost::asio::transfer_all(), error);
if( error && error != boost::asio::error::eof ) {
cout << "receive failed: " << error.message() << endl;
}
else {
const char* data = boost::asio::buffer_cast<const char*>(receive_buffer.data());
cout << data << endl;
}
return 0;
}
Compile and run.
$ g++ client.cpp -o client –lboost_system
$ ./client
TCP server:
#include <iostream>
#include <boost/asio.hpp>
using namespace boost::asio;
using ip::tcp;
using std::string;
using std::cout;
using std::endl;
string read_(tcp::socket & socket) {
boost::asio::streambuf buf;
boost::asio::read_until( socket, buf, "\n" );
string data = boost::asio::buffer_cast<const char*>(buf.data());
return data;
}
void send_(tcp::socket & socket, const string& message) {
const string msg = message + "\n";
boost::asio::write( socket, boost::asio::buffer(message) );
}
int main() {
boost::asio::io_service io_service;
//listen for new connection
tcp::acceptor acceptor_(io_service, tcp::endpoint(tcp::v4(), 1234 ));
//socket creation
tcp::socket socket_(io_service);
//waiting for connection
acceptor_.accept(socket_);
//read operation
string message = read_(socket_);
cout << message << endl;
//write operation
send_(socket_, "Hello From Server!");
cout << "Servent sent Hello message to Client!" << endl;
return 0;
}
compile and run in another window
$ g++ server.cpp -o server –lboost_system
$ ./server

Simple search program using arrays help me

When the user types in a word the program is searching for a match in an array, if there is a match the program prints out the string from the array.The code below does just that. My goal is to make it so when a word matches with a a word in the array the program should print an info not only the word. I thought I can fill the array with functions, but its not working. Is it even possible ?
I am using league of legend hero names because they are a lot and I know them and it doesent take me a lot of time to think of names that way :D
The idea is if the user types in voly, the program finds voly in the array and prints out(for example) his starting life, armor, mr and so on.
I tryed a lot of thing with functions but I cant make it work.
#include <iostream>
#include <string>
using namespace std;
string voly(string holder,string heroName);
int main(){
const int numH = 10;
string holder;
string heroName;
string heroList[numH] = {"voly", "teemo", "vladimir", "morgana", "jax", "ekko", "anivia", "nunu", "ashe", "tresh" };
cout << "Enter hero name.\n" << endl;
cin >> heroName;
for (int i = 0; i < numH; i++){
holder = heroList[i];
if (heroName == holder){
cout << holder << endl;
}
}
system("PAUSE");
return 0;
}
string voly(string holder, string heroName) {
cout << "Voly is the best" << endl;
}
Try to learn about structs. You can utilize them to encapsulate all hero information in a hero struct, as follows. This serves as kind of a prototype for each hero:
struct hero {
string name;
int hp;
int mana;
float mreg;
...
void printMe() { cout << 'hp: ' << hp << endl << 'mana: ' << mana << endl << ...; }
}
Using the printMe() function of that specific hero object, you can print its values.
Then, for each hero, create a struct object and add them to the array.
hero* pointer = new hero[numH];
pointer[0] = new hero {
name: "voly",
hp: 150
};
pointer[1] = new hero {
...
};
(Try considering some import function via a .CSV file or so.)
By using your for loop, compare the name:
for (int i = 0; i < numH; i++){
if (heroName == pointer[i].name){
pointer[i]->printMe();
}
}
Try using Google to find tutorials on that. Unfortunately, I'm not quite sure about the syntax in C++, maybe someone can help me out.
Good Luck!

Design pattern for managing shared libraries loaded into memory

gcc (GCC) 4.7.2
Hello,
I am developing a large project that will contain 2 modules (shared libraries) that I will develop.
The modules are shared libraries created by me in C, that will have to sync and exchange messages between each other.
The manager module will control and load both these modules (.so) into memory. If one was to fail. The manager could try and re-load it.
I am wondering as this is my first time I have done something like this. Is there any design patterns that could be followed?
All this will be written in C and using the APR (Apache Portable Runtime) for memory pool management and maybe some threading pool if needed.
Start manager that will load both modules.
Manager then calls some functions on both of them maybe to start and stop them, and possible cleanup.
Once both modules have been loaded and started. They should be able to exchange some messages between each other.
The modules will all run on the same machine running Redhat.
Many thanks for any suggestions.
The manager module will control and load both these modules (.so) into memory. If one was to fail. The manager could try and re-load it.
This is usually a bad idea if it's in a single C process - if one of these modules fail, you're unlikely to be able to safely unload it, much less load it again. If you need to be able to recover from module failure, you must use independent processes. The code can still be in an .so file though - just fork() the manager once for each module to load; this is the model used by the chrome plugins API, for example.
Moreover, dealing with component failure can be very, very tricky in itself. Just because A restarts doesn't mean B is ready to talk to a newly restarted A. You may want to try to glean some ideas off erlang, which handles component failure exceptionally well by encouraging the decomposition of applications into message-passing subcomponents with a hierarchy of supervisor modules to restart failing components. This may be a bit overkill if you only have two modules, but it's something to think about at least.
As for how to communicate, there are a number of paradigms. If these modules are in the same process, you could just pass a vtable around. That is, for example:
// moduleA.h
struct vtable_A {
void (*do_something)();
};
void set_vtable_B(struct vtable_B *);
struct vtable_A *get_vtable_A();
void start_A();
// moduleB.h
struct vtable_B {
void (*do_something)();
};
void set_vtable_A(struct vtable_A *);
struct vtable_B *get_vtable_B();
void start_B();
Your manager would load both, pass the vtable from A to B and vice versa, and thereafter call the start routines. Be careful with ordering - either A must be started before B is ready, or vice versa, and they need to be okay with this.
If they're in independent processes, message passing is usually the way to go. It's essentially a network protocol at that point - your subprocesses will send serialized messages to the manager, and the manager routes them to other subprocesses. The conversation might look a bit like this:
MGR->A START
MGR->B START
A->MGR REGISTER_ENDPOINT 'ProcessA'
A->MGR WATCH_ENDPOINT 'ProcessB'
MGR->A OK_REGISTER 'ProcessA'
MGR->A OK_WATCH 'ProcessB'
B->MGR REGISTER_ENDPOINT 'ProcessB'
B->MGR WATCH_ENDPOINT 'ProcessA'
MGR->B OK_REGISTER 'ProcessB'
MGR->A NEW_ENDPOINT 'ProcessB'
A->MGR APPLICATION_DATA TO:'ProcessB', PAYLOAD:"Hello, world!"
MGR->B OK_WATCH 'ProcessA'
MGR->B NEW_ENDPOINT 'ProcessA'
MGR->B APPLICATION_DATA FROM:'ProcessA', PAYLOAD:"Hello, world!"
Keep in mind, there are many other ways to structure this kind of protocol than the example above, and to build RPC on top of a message-passing protocol. You may be interested in looking at things such as DBUS (which you may be able to use directly!) or DCOM, which have done this sort of thing before. Other optimizations on top of this sort of protocol include using the manager to establish a direct channel of some sort between A and B, and getting it involved again only if A or B need to be restarted.
That said, don't get too deep into the details of how the manager works before you figure out what it needs to do. Design the plugin<->manager high level interface, and plugin<->plugin protocol; only then design the details of the plugin<->manager interface. It's far too easy to get sidetracked and end up with something way too complex like CORBA or SOAP.
Here after a simple example of project based in your request:
the architecture of your source code could be like this:
src
|__handler1.c //containing the main function
|__handler2.c //containing other functions
|__lib1.c //containing lib1 source
|__lib2_file1.c //containing lib2 source
|__lib2_file2.c //containing lib2 source
|__Makefile // file which contains commands to build the project
|__inc
|__lib1.h
|__lib2.h
|__handler2.h
handler1.c
#include <stdio.h>
#include "lib1.h"
#include "lib2.h"
#include "handler2.h"
int main()
{
char *s1, *s2;
print_hello_from_handler2();
s1 = get_message_from_lib1_method1();
get_message_from_lib1_method2(&s2);
printf("s1 = %s\n",s1);
printf("s2 = %s\n",s2);
printf("extern string_from_lib1 = %s\n",string_from_lib1);
printf("extern string_from_lib2 = %s\n",string_from_lib2);
}
handler2.c
#include <stdio.h>
void print_hello_from_handler2()
{
printf("hello world from handler2\n");
}
lib1.c
#include "lib2.h"
char *string_from_lib1="message from lib1 variable";
char *get_message_from_lib1_method1()
{
return get_message_from_lib2_method1();
}
void get_message_from_lib1_method2(char **s)
{
get_message_from_lib2_method2(s);
}
lib2_file1.c
char *string_from_lib2="message from lib2 variable";
char *str="message from lib2 method1";
char *get_message_from_lib2_method1()
{
return str;
}
lib2_file2.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void get_message_from_lib2_method2(char **s)
{
*s = malloc(30);
strcpy(*s,"message from lib2 method2");
}
lib1.h
extern char *string_from_lib1;
char *get_message_from_lib1_method1();
void get_message_from_lib1_method2(char **s);
lib2.h
extern char *string_from_lib2;
char *get_message_from_lib2_method1();
void get_message_from_lib2_method2(char **s);
handler2.h
void print_hello_from_handler2();
Makefile
SHLIB_EXT=so
LINK=$(CC)
SHLIB1_FILE=libmodule1.$(SHLIB_EXT).1
SHLIB2_FILE=libmodule2.$(SHLIB_EXT).1
SHLIB1_FLAGS=-shared -Wl,-soname,$(SHLIB1_FILE)
SHLIB2_FLAGS=-shared -Wl,-soname,$(SHLIB2_FILE)
FPIC=-fPIC
all: libmodule2.$(SHLIB_EXT) libmodule1.$(SHLIB_EXT) handler
%.o: %.c
$(CC) -Iinc -c -o $# $^
handler: handler1.o handler2.o
$(CC) -o $# $^ -L. -lmodule2 -lmodule1
lib2_file1.o: lib2_file1.c
$(CC) $(FPIC) -Iinc -c -o $# $<
lib2_file2.o: lib2_file2.c
$(CC) $(FPIC) -Iinc -c -o $# $<
libmodule2.$(SHLIB_EXT): lib2_file1.o lib2_file2.o
$(LINK) $(SHLIB2_FLAGS) -o $(SHLIB2_FILE) $^
ln -sf $(SHLIB2_FILE) $#
libmodule1.o: lib1.c
$(CC) $(FPIC) -Iinc -c -o $# $<
libmodule1.$(SHLIB_EXT): libmodule1.o
$(LINK) $(SHLIB1_FLAGS) -o $(SHLIB1_FILE) $< -L. -lmodule2
ln -sf $(SHLIB1_FILE) $#
clean:
rm -f *.o *.so* handler
rm -f /usr/lib/$(SHLIB1_FILE)
rm -f /usr/lib/$(SHLIB2_FILE)
rm -f /usr/lib/libmodule1.$(SHLIB_EXT)
rm -f /usr/lib/libmodule2.$(SHLIB_EXT)
install:
cp $(SHLIB1_FILE) /usr/lib/
cp $(SHLIB2_FILE) /usr/lib/
cp handler /usr/bin/
ln -sf /usr/lib/$(SHLIB1_FILE) /usr/lib/libmodule1.$(SHLIB_EXT)
ln -sf /usr/lib/$(SHLIB2_FILE) /usr/lib/libmodule2.$(SHLIB_EXT)
the command to compile your project
linux$ cd src
linux$ make
and then install the binary and the libraries
linux$ sudo make install
to clean installed libraries and the binary and to clean build binary libraries and objects:
linux$ sudo make clean
To run the application:
linux$ handler
hello world from handler2
s1 = message from lib2 method1
s2 = message from lib2 method2
extern string_from_lib1 = message from lib1 variable
extern string_from_lib2 = message from lib2 variable
linux$
I'm a bit allergic to "pattern talk" but this is how I would approach this:
Decide on threading model.
Will your modules exchange information using memory they control, or the manager?
Should the modules wait on condition variables shared between them or owned by the manager?
Decide on how generic a manager you need.
Should it be able to poll a directory for modules or read a configuration or both?
If the manager manages messages, what is needed for signalling between modules?
When you know this, the rest should be mostly business logic that will live in the modules.
As I get it, you need to decouple point 1 and 2.
For that you should have a separate class called BootstrapManager, which will be
responsible to loading the modules and reloading if they fail.
Next you need is an abstract class called Module which would have 3
methods,
start() - starts a module,
stop() - stops a module,
cleanUp() - cleanup activities,
communicate() - communicates with another module.
Now both Module1 and Module 2 will extend this class and implement
their own business logic accordingly.
If you have already decided to use APR, you should probably use
the dynamic library loading it provides. You can find a tutorial
here.
The architecture here is relatively simple so you do not need a complex design pattern.
The main problem is data integrity. If the system crashes partially, how do you ensure that both have the same copy of the data?
Since you are using messaging you have half solved the problem already. You only need to do two things:
(1) store the list of recent messages and create a rollback/update mechanism to restore a module given a checkpoint backup and the list of messages since the checkpoint
(2) make sure the messages are atomic; ie you never want a partial message or transaction to be accepted because if the sender crashes in the middle of sending a message the receiver could be corrupted by accepting incomplete information.
To solve problem 2 add a checksum or hash to the end of a transaction. The receiver does not finalize its acceptance of a message set unless the hash is received and matches the data.
One critical question: why do you want to implement this in this fashion? You are 'tightly' coupling what are essentially 'loosely' coupled components (because shared libraries have all sorts of crash-related issues: they'll take the manager down). Why not have a Manager program that (can) launch and relaunch if necessary 2 or more child processes.
Have the child processes communicate with the Manager, or with each other, using some sort of protocol. I would recommend ZeroMQ both because it is awesome and because it totally hides the interprocess communication, so it could be sockets (between different machines), or inter-process between threads, or named pipes on a single machine, which is very fast. This means that after implementing your clients, you can decide how you want to deploy them: as shared libraries loaded into the manager, as separate processes running on the same box, or as distributed processes running on separate machines, and you'll hardly need to change anything. Which means very scalable.
However, if you are dedicated to the shared library approach, there is one 'design pattern' that I would absolutely recommend for this, although it can be a bit tricky to implement. But it'll be worth its weight.
Your manager, before passing messages between modules, should check their timestamps and, if anything has changed, recompile and reload them. This will mean that your code changes are 'hot': you won't have to stop the manager, recompile, and restart the manager to see the changes. So you can program in C more like one develops in js! It will save you hours and hours.
I did something similar a while ago (not the inter-library comms) using C++ and APR. The code is a bit 'hacky', but here it is anyway ;-)
Note that it depends on having a Makefile for each submodule in its own directory, and because of dependencies, I don't check timestamps, I just recompile on each request. This might not be ideal for you, so you might need to rethink that part.
The hardest part of getting it to work was getting the right permissions on directories, but come to think of it, that was because I was running this as an fcgi process, so when it actually ran it did so as the webserver. You will most likely not encounter those issues.
#ifndef _CMJ_RUN_HPP
#define _CMJ_RUN_HPP
#include <fcgio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <apr.h>
#include <apr_dso.h>
#include <apr_pools.h>
#include <apr_thread_proc.h>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
#include <stdexcept>
#include <cstdarg>
class Line {
protected:
std::stringstream line_;
bool isError_;
public:
Line(const char* line, bool isError) : line_(line), isError_(isError) {}
Line(const Line& rhs) : line_(rhs.line()), isError_(rhs.error()) {}
bool error() const { return isError_; }
const char* line() const { return line_.str().c_str(); }
const Line& operator = (const Line& rhs) {
line_.str() = rhs.line();
isError_ = rhs.error();
return rhs;
}
};
class Run {
protected:
int exitCode_;
std::vector<Line> out_;
bool errors_;
protected:
void run(const char* dir, const char* cmd, std::vector<const char*> &args, apr_pool_t* parentPool) ;
public:
Run(const char* dir, const char* cmd, std::vector<const char*> &args, apr_pool_t* parentPool);
Run(const char* dir, const char* cmd, apr_pool_t* parentPool);
int exitCode() { return exitCode_; }
bool errors() { return errors_; }
bool errors(std::ostream& out);
int size() { return out_.size(); }
Line& line(int i) { return out_[i]; }
};
class dso_error: public std::runtime_error {
public:
dso_error(const char* c) : std::runtime_error(c) {};
dso_error(std::string err) : std::runtime_error(err) {};
static dso_error instance(const char* format, ...) {
char errbuf[8192];
va_list va;
va_start(va, format);
vsnprintf(errbuf, 8192, format, va);
va_end(va);
return dso_error(errbuf);
}
};
/**
* Provides a building and loading framework for Dynamic libraries, with the full power
* of make behind it.
* Usage:
* <code>
* DsoLib so("/var/www/frontier/echo","/var/www/frontier/echo/libecho.so",pool);
* if (!so.errors(outStream)) {
* void (*pFn)(void) = sym("initialize");
* (*pFn)();
* }
* </code>
*/
class DsoLib : public Run {
protected:
apr_pool_t* pool_;
apr_dso_handle_t* dso_;
std::string dirname_;
std::string libname_;
public:
/** dir is the directory where make should be executed, libname is full path to the library
* from current working directory.
*/
DsoLib(const char* dir, const char* libname, apr_pool_t* parentPool) throw(dso_error);
~DsoLib();
void* sym(const char* symbol) throw (dso_error);
void* sym(std::string symbol) throw (dso_error) { return sym(symbol.c_str()); }
};
#endif
And Run.cpp
#include "Run.hpp"
#include <string>
#include <sstream>
#include <boost/filesystem.hpp>
#include <cassert>
#define DBGENDL " (" << __FILE__ << ":" << __LINE__ << ")" << endl
using namespace std;
Run::Run(const char* dir, const char* cmd, apr_pool_t* pool) : errors_(false) {
vector<const char *> args;
run(dir, cmd, args, pool);
}
Run::Run(const char* dir, const char* cmd, vector<const char*> &args, apr_pool_t* pool) : errors_(false) {
run(dir, cmd, args, pool);
}
void
Run::run(const char* dir, const char* cmd, vector<const char*> &args, apr_pool_t* parentPool) {
cout << "Run::run(dir=" << ", cmd=" << cmd << ", args...)" << endl;
apr_status_t status;
char aprError[1024];
struct aprPool_s {
apr_pool_t* pool_;
aprPool_s(apr_pool_t* parent) {
apr_pool_create(&pool_, parent);
}
~aprPool_s() {
apr_pool_destroy(pool_);
}
operator apr_pool_t* () { return pool_; }
} pool (parentPool);
apr_procattr_t* attr;
if (APR_SUCCESS != (status = apr_procattr_create(&attr, pool))) {
cerr << "apr_procattr_create error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
if (APR_SUCCESS != (status = apr_procattr_dir_set(attr, dir))) {
cerr << "apr_procattr_dir_set error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
if (APR_SUCCESS != (status = apr_procattr_cmdtype_set(attr, APR_PROGRAM_ENV))) {
cerr << "apr_procattr_cmdtype_set error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
if (APR_SUCCESS != (status = apr_procattr_io_set(attr, APR_NO_PIPE, APR_FULL_NONBLOCK, APR_FULL_NONBLOCK))) {
cerr << "apr_procattr_io_set error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
if (APR_SUCCESS != (status = apr_procattr_user_set(attr, "craig", "lateral"))) {
cerr << "apr_procattr_user_set error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
if (APR_SUCCESS != (status = apr_procattr_group_set(attr, "craig"))) {
cerr << "apr_procattr_group_set error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
apr_proc_t proc;
const char **argv = (const char**) new char*[ 2 + args.size() ];
argv[0] = cmd;
size_t i=0;
size_t argc=args.size();
for (i=0; i<argc; i++) {
argv[i+1] = args[i];
cerr << "arg " << i << " = " << args[i];
}
argv[i+1] = NULL;
argc++;
cerr << "About to execute " << cmd << " in dir " << dir << endl;
cerr << "ARGS:" << endl;
for (i=0; i<argc; i++) {
cerr << "[" << i << "]: " << argv[i] << endl;
}
if (APR_SUCCESS != (status = apr_proc_create(&proc, cmd, argv, NULL, attr, pool))) {
cerr << "apr_proc_create error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
apr_exit_why_e exitWhy;
cerr << "--- " << cmd << " ---" << endl;
while (APR_CHILD_NOTDONE == (status = apr_proc_wait(&proc, &exitCode_, &exitWhy, APR_NOWAIT))) {
char line[1024];
status = apr_file_gets(line, sizeof(line), proc.out);
if (APR_SUCCESS==status) {
out_.push_back(Line(line, false));
cerr << line << endl;
}
status = apr_file_gets(line, sizeof(line), proc.err);
if (APR_SUCCESS==status) {
out_.push_back(Line(line, true));
errors_ = true;
cerr << "E:" << line ;
}
}
cerr << " -----" << endl;
delete[] argv;
if ( (APR_CHILD_DONE != status) && (APR_PROC_EXIT != status) ) {
cerr << "apr_proc_wait error: " << apr_strerror(status, aprError, sizeof(aprError)) << endl;
}
cerr << cmd << " exited " << ((APR_PROC_EXIT==exitWhy) ? "PROC_EXIT" :
((APR_PROC_SIGNAL==exitWhy) ? "PROC_SIGNAL" :
((APR_PROC_SIGNAL_CORE==exitWhy) ? "PROC_SIGNAL_CORE" : "Unknown"))) << endl;
}
bool
Run::errors(std::ostream& os) {
cerr << "Run::errors(ostream) : errors()=" << errors() << endl;
if (errors()) {
cerr << "Writing errors to ostream" << endl;
os << "Content-type: text/html\r\n\r\n";
os << "<html><head><title>Errors</title>"
<< "<link rel=\"stylesheet\" type=\"text/css\" href=\"css/frontier.css\"></link>"
<< "</head>"
<< "<body>";
for (int i=0; i<size(); i++) {
Line& errline = line(i);
os << "<div class=\"" << ( (errline.error() ? "error" : "out" ) ) << "\">"
<< errline.line()
<< "</div>";
}
os
<< "</body>"
<< "</html>";
}
return errors();
}
DsoLib::DsoLib(const char* dir, const char* libname, apr_pool_t* parentPool) throw (dso_error) :
Run(dir, "/usr/bin/make", parentPool), pool_(NULL), dso_(NULL), dirname_(dir), libname_(libname)
{
if (errors()) {
cerr << "Run encountered errors, quitting DsoLib::DsoLib()" << DBGENDL;
//throw dso_error::instance("Build failed for dir %s, library %s", dir, libname);
return;
} else {
cerr << "No errors encountered with Run in DsoLib::DsoLib" << DBGENDL;
}
apr_status_t status;
if (APR_SUCCESS != apr_pool_create(&pool_, parentPool)) {
cerr << "Failed to allocate pool" << DBGENDL;
throw dso_error("Failed to allocate apr_pool");
}
cerr << "Created pool ok" << DBGENDL; //(" << __FILE__ << ":" << __LINE__ << ")" << endl;
if (APR_SUCCESS != (status = apr_dso_load(&dso_, libname, pool_))) {
cerr << "apr_dso_load(" << libname << ") failed" << DBGENDL;
char aprError[1024];
throw dso_error::instance("dso_load failed, path=%s, error=%s",
libname, apr_strerror(status, aprError, sizeof(aprError)));
}
cerr << "Loaded dso ok" << DBGENDL;
#if 0
void (*initialize)(apr_pool_t*) = reinterpret_cast< void(*)(apr_pool_t*) > (sym("initialize"));
if (initialize) {
cerr << "found initialize sym: about to call initialize" << DBGENDL;
initialize(pool_);
cerr << "initialize(pool) returned ok" << DBGENDL;
} else {
cerr << "initialize sym not found" << DBGENDL;
}
#endif
cerr << "Exiting DsoLib::DsoLib(" << dir << ", " << libname << ") with success." << endl;
}
DsoLib::~DsoLib() {
cerr << "Entering DsoLib::~DsoLib(dir=" << dirname_ <<", " << "lib=" << libname_ << ")" << endl;
if (NULL!=dso_) {
void (*terminate)(void) = reinterpret_cast<void(*)()>(sym("terminate"));
if (terminate) terminate();
apr_status_t status = apr_dso_unload(dso_);
if (APR_SUCCESS != status) {
char err[8192];
cerr << "ERR apr_dso_unload failed: " << apr_dso_error(dso_, err, sizeof(err)) << endl;
} else {
cerr << "Unloaded " << libname_ << endl;
}
} else {
cerr << "ERR dso_ handle is NULL" << endl;
}
if (NULL!=pool_) apr_pool_destroy(pool_);
}
void *
DsoLib::sym(const char* symbol) throw (dso_error) {
cerr << "sym('" << symbol << "')" << DBGENDL;
cerr << "dso_ == NULL ? " << ((NULL==dso_)?"true":"false") << DBGENDL;
cerr << "dso_ = " << dso_ << DBGENDL;
assert(NULL!=symbol);
assert(NULL!=dso_);
apr_status_t status;
void* p = NULL;
if (APR_SUCCESS != (status = apr_dso_sym((apr_dso_handle_sym_t*)&p, dso_, symbol))) {
cerr << "apr_dso_sym() DID NOT RETURN APR_SUCCESS" << DBGENDL;
char aprError[1024];
stringstream err;
err << "dso_sym failed, symbol=" << symbol << ": " << apr_strerror(status, aprError, sizeof(aprError));
cerr << err.str() << DBGENDL;
} else {
cerr << "sym succeeded for " << symbol << " in " << libname_ << DBGENDL;
}
return p;
}

Skip fingerprint reader PAM module to authenticate with PAM from C application

I would like to authenticate users of my C network application with PAM and I have a found a nice PAM example here on Stack, which I attach at the bottom. The problem is that in my development machine I have a fingerprint reader which PAM is set up to use, as in /etc/pam.d/common-auth:
#%PAM-1.0
#
# This file is autogenerated by pam-config. All changes
# will be overwritten.
#
# Authentication-related modules common to all services
#
# This file is included from other service-specific PAM config files,
# and should contain a list of the authentication modules that define
# the central authentication scheme for use on the system
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the
# traditional Unix authentication mechanisms.
#
auth required pam_env.so
auth sufficient pam_fprint.so
auth optional pam_gnome_keyring.so
auth required pam_unix2.so
pam_fprint.so is the fingerprint reader plugin. When you normally log in, the scan can fail and you are prompted for a password. However, sshd daemon does not initiate the fingerprint at all and I would like to understand how it skips it, because for example /etc/pam.d/sshd references the common-auth module so it must pull it ..
#%PAM-1.0
auth requisite pam_nologin.so
auth include common-auth
account requisite pam_nologin.so
account include common-account
password include common-password
session required pam_loginuid.so
session include common-session
session optional pam_lastlog.so silent noupdate showfailed
I have tried to reference the 'sshd' scheme from the C program but it still initiates the fingerprint reader. I want to skip the fingerprint reader somehow in C and retain my fingerprint reader default config.
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <security/pam_appl.h>
#include <unistd.h>
// To build this:
// g++ test.cpp -lpam -o test
struct pam_response *reply;
//function used to get user input
int function_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
{
*resp = reply;
return PAM_SUCCESS;
}
int main(int argc, char** argv)
{
if(argc != 2) {
fprintf(stderr, "Usage: check_user <username>\n");
exit(1);
}
const char *username;
username = argv[1];
const struct pam_conv local_conversation = { function_conversation, NULL };
pam_handle_t *local_auth_handle = NULL; // this gets set by pam_start
int retval;
// local_auth_handle gets set based on the service
retval = pam_start("common-auth", username, &local_conversation, &local_auth_handle);
if (retval != PAM_SUCCESS)
{
std::cout << "pam_start returned " << retval << std::endl;
exit(retval);
}
reply = (struct pam_response *)malloc(sizeof(struct pam_response));
// *** Get the password by any method, or maybe it was passed into this function.
reply[0].resp = getpass("Password: ");
reply[0].resp_retcode = 0;
retval = pam_authenticate(local_auth_handle, 0);
if (retval != PAM_SUCCESS)
{
if (retval == PAM_AUTH_ERR)
{
std::cout << "Authentication failure." << std::endl;
}
else
{
std::cout << "pam_authenticate returned " << retval << std::endl;
}
exit(retval);
}
std::cout << "Authenticated." << std::endl;
retval = pam_end(local_auth_handle, retval);
if (retval != PAM_SUCCESS)
{
std::cout << "pam_end returned " << retval << std::endl;
exit(retval);
}
return retval;
}
I doubt that sshd is actually skipping that module. Rather, I suspect that the fingerprint reader authentication module (sensibly) is checking whether the authenticating user appears to be on the local system or is coming over the network (which it can figure out from PAM data like rhost) and just silently does nothing if this is a network authentication. You could try looking at the source code to see if it has such a test, or try setting PAM_RHOST via pam_set_item and see if that changes the behavior.
To answer your actual question, I don't believe there is a way to tell PAM to run a particular PAM group except for one module. The expected way to do what you want to do is to create a new configuration file in /etc/pam.d that matches the application name you pass to pam_start that does not include common-auth but instead contains just the modules that you want to run.

Easy way to use variables of enum types as string in C?

Here's what I am trying to do:
typedef enum { ONE, TWO, THREE } Numbers;
I am trying to write a function that would do a switch case similar to the following:
char num_str[10];
int process_numbers_str(Numbers num) {
switch(num) {
case ONE:
case TWO:
case THREE:
{
strcpy(num_str, num); //some way to get the symbolic constant name in here?
} break;
default:
return 0; //no match
return 1;
}
Instead of defining at every case, is there a way to set it using the enum variable like I am trying to do above?
The technique from Making something both a C identifier and a string? can be used here.
As usual with such preprocessor stuff, writing and understanding the preprocessor part can be hard, and includes passing macros to other macros and involves using # and ## operators, but using it is real easy. I find this style very useful for long enums, where maintaining the same list twice can be really troublesome.
Factory code - typed only once, usually hidden in the header:
enumFactory.h:
// expansion macro for enum value definition
#define ENUM_VALUE(name,assign) name assign,
// expansion macro for enum to string conversion
#define ENUM_CASE(name,assign) case name: return #name;
// expansion macro for string to enum conversion
#define ENUM_STRCMP(name,assign) if (!strcmp(str,#name)) return name;
/// declare the access function and define enum values
#define DECLARE_ENUM(EnumType,ENUM_DEF) \
enum EnumType { \
ENUM_DEF(ENUM_VALUE) \
}; \
const char *GetString(EnumType dummy); \
EnumType Get##EnumType##Value(const char *string); \
/// define the access function names
#define DEFINE_ENUM(EnumType,ENUM_DEF) \
const char *GetString(EnumType value) \
{ \
switch(value) \
{ \
ENUM_DEF(ENUM_CASE) \
default: return ""; /* handle input error */ \
} \
} \
EnumType Get##EnumType##Value(const char *str) \
{ \
ENUM_DEF(ENUM_STRCMP) \
return (EnumType)0; /* handle input error */ \
} \
Factory used
someEnum.h:
#include "enumFactory.h"
#define SOME_ENUM(XX) \
XX(FirstValue,) \
XX(SecondValue,) \
XX(SomeOtherValue,=50) \
XX(OneMoreValue,=100) \
DECLARE_ENUM(SomeEnum,SOME_ENUM)
someEnum.cpp:
#include "someEnum.h"
DEFINE_ENUM(SomeEnum,SOME_ENUM)
The technique can be easily extended so that XX macros accepts more arguments, and you can also have prepared more macros to substitute for XX for different needs, similar to the three I have provided in this sample.
Comparison to X-Macros using #include / #define / #undef
While this is similar to X-Macros others have mentioned, I think this solution is more elegant in that it does not require #undefing anything, which allows you to hide more of the complicated stuff is in the factory the header file - the header file is something you are not touching at all when you need to define a new enum, therefore new enum definition is a lot shorter and cleaner.
// Define your enumeration like this (in say numbers.h);
ENUM_BEGIN( Numbers )
ENUM(ONE),
ENUM(TWO),
ENUM(FOUR)
ENUM_END( Numbers )
// The macros are defined in a more fundamental .h file (say defs.h);
#define ENUM_BEGIN(typ) enum typ {
#define ENUM(nam) nam
#define ENUM_END(typ) };
// Now in one and only one .c file, redefine the ENUM macros and reinclude
// the numbers.h file to build a string table
#undef ENUM_BEGIN
#undef ENUM
#undef ENUM_END
#define ENUM_BEGIN(typ) const char * typ ## _name_table [] = {
#define ENUM(nam) #nam
#define ENUM_END(typ) };
#undef NUMBERS_H_INCLUDED // whatever you need to do to enable reinclusion
#include "numbers.h"
// Now you can do exactly what you want to do, with no retyping, and for any
// number of enumerated types defined with the ENUM macro family
// Your code follows;
char num_str[10];
int process_numbers_str(Numbers num) {
switch(num) {
case ONE:
case TWO:
case THREE:
{
strcpy(num_str, Numbers_name_table[num]); // eg TWO -> "TWO"
} break;
default:
return 0; //no match
return 1;
}
// Sweet no ? After being frustrated by this for years, I finally came up
// with this solution for my most recent project and plan to reuse the idea
// forever
There's no built-in solution. The easiest way is with an array of char* where the enum's int value indexes to a string containing the descriptive name of that enum. If you have a sparse enum (one that doesn't start at 0 or has gaps in the numbering) where some of the int mappings are high enough to make an array-based mapping impractical then you could use a hash table instead.
There is definitely a way to do this -- use X() macros. These macros use the C preprocessor to construct enums, arrays and code blocks from a list of source data. You only need to add new items to the #define containing the X() macro. The switch statement would expand automatically.
Your example can be written as follows:
// Source data -- Enum, String
#define X_NUMBERS \
X(ONE, "one") \
X(TWO, "two") \
X(THREE, "three")
...
// Use preprocessor to create the Enum
typedef enum {
#define X(Enum, String) Enum,
X_NUMBERS
#undef X
} Numbers;
...
// Use Preprocessor to expand data into switch statement cases
switch(num)
{
#define X(Enum, String) \
case Enum: strcpy(num_str, String); break;
X_NUMBERS
#undef X
default: return 0; break;
}
return 1;
There are more efficient ways (i.e. using X Macros to create an string array and enum index), but this is the simplest demo.
I know you have a couple good solid answers, but do you know about the # operator in the C preprocessor?
It lets you do this:
#define MACROSTR(k) #k
typedef enum {
kZero,
kOne,
kTwo,
kThree
} kConst;
static char *kConstStr[] = {
MACROSTR(kZero),
MACROSTR(kOne),
MACROSTR(kTwo),
MACROSTR(kThree)
};
static void kConstPrinter(kConst k)
{
printf("%s", kConstStr[k]);
}
C or C++ does not provide this functionality, although I've needed it often.
The following code works, although it's best suited for non-sparse enums.
typedef enum { ONE, TWO, THREE } Numbers;
char *strNumbers[] = {"one","two","three"};
printf ("Value for TWO is %s\n",strNumbers[TWO]);
By non-sparse, I mean not of the form
typedef enum { ONE, FOUR_THOUSAND = 4000 } Numbers;
since that has huge gaps in it.
The advantage of this method is that it put the definitions of the enums and strings near each other; having a switch statement in a function spearates them. This means you're less likely to change one without the other.
KISS. You will be doing all sorts of other switch/case things with your enums so why should printing be different? Forgetting a case in your print routine isn't a huge deal when you consider there are about 100 other places you can forget a case. Just compile -Wall, which will warn of non-exhaustive case matches. Don't use "default" because that will make the switch exhaustive and you wont get warnings. Instead, let the switch exit and deal with the default case like so...
const char *myenum_str(myenum e)
{
switch(e) {
case ONE: return "one";
case TWO: return "two";
}
return "invalid";
}
Try Converting C++ enums to strings. The comments have improvements that solve the problem when enum items have arbitrary values.
The use of boost::preprocessor makes possible an elegant solution like the following:
Step 1: include the header file:
#include "EnumUtilities.h"
Step 2: declare the enumeration object with the following syntax:
MakeEnum( TestData,
(x)
(y)
(z)
);
Step 3: use your data:
Getting the number of elements:
td::cout << "Number of Elements: " << TestDataCount << std::endl;
Getting the associated string:
std::cout << "Value of " << TestData2String(x) << " is " << x << std::endl;
std::cout << "Value of " << TestData2String(y) << " is " << y << std::endl;
std::cout << "Value of " << TestData2String(z) << " is " << z << std::endl;
Getting the enum value from the associated string:
std::cout << "Value of x is " << TestData2Enum("x") << std::endl;
std::cout << "Value of y is " << TestData2Enum("y") << std::endl;
std::cout << "Value of z is " << TestData2Enum("z") << std::endl;
This looks clean and compact, with no extra files to include.
The code I wrote within EnumUtilities.h is the following:
#include <boost/preprocessor/seq/for_each.hpp>
#include <string>
#define REALLY_MAKE_STRING(x) #x
#define MAKE_STRING(x) REALLY_MAKE_STRING(x)
#define MACRO1(r, data, elem) elem,
#define MACRO1_STRING(r, data, elem) case elem: return REALLY_MAKE_STRING(elem);
#define MACRO1_ENUM(r, data, elem) if (REALLY_MAKE_STRING(elem) == eStrEl) return elem;
#define MakeEnum(eName, SEQ) \
enum eName { BOOST_PP_SEQ_FOR_EACH(MACRO1, , SEQ) \
last_##eName##_enum}; \
const int eName##Count = BOOST_PP_SEQ_SIZE(SEQ); \
static std::string eName##2String(const enum eName eel) \
{ \
switch (eel) \
{ \
BOOST_PP_SEQ_FOR_EACH(MACRO1_STRING, , SEQ) \
default: return "Unknown enumerator value."; \
}; \
}; \
static enum eName eName##2Enum(const std::string eStrEl) \
{ \
BOOST_PP_SEQ_FOR_EACH(MACRO1_ENUM, , SEQ) \
return (enum eName)0; \
};
There are some limitation, i.e. the ones of boost::preprocessor. In this case, the list of constants cannot be larger than 64 elements.
Following the same logic, you could also think to create sparse enum:
#define EnumName(Tuple) BOOST_PP_TUPLE_ELEM(2, 0, Tuple)
#define EnumValue(Tuple) BOOST_PP_TUPLE_ELEM(2, 1, Tuple)
#define MACRO2(r, data, elem) EnumName(elem) EnumValue(elem),
#define MACRO2_STRING(r, data, elem) case EnumName(elem): return BOOST_PP_STRINGIZE(EnumName(elem));
#define MakeEnumEx(eName, SEQ) \
enum eName { \
BOOST_PP_SEQ_FOR_EACH(MACRO2, _, SEQ) \
last_##eName##_enum }; \
const int eName##Count = BOOST_PP_SEQ_SIZE(SEQ); \
static std::string eName##2String(const enum eName eel) \
{ \
switch (eel) \
{ \
BOOST_PP_SEQ_FOR_EACH(MACRO2_STRING, _, SEQ) \
default: return "Unknown enumerator value."; \
}; \
};
In this case, the syntax is:
MakeEnumEx(TestEnum,
((x,))
((y,=1000))
((z,))
);
Usage is similar as above (minus the eName##2Enum function, that you could try to extrapolate from the previous syntax).
I tested it on mac and linux, but be aware that boost::preprocessor may not be fully portable.
By merging some of the techniques over here I came up with the simplest form:
#define MACROSTR(k) #k
#define X_NUMBERS \
X(kZero ) \
X(kOne ) \
X(kTwo ) \
X(kThree ) \
X(kFour ) \
X(kMax )
enum {
#define X(Enum) Enum,
X_NUMBERS
#undef X
} kConst;
static char *kConstStr[] = {
#define X(String) MACROSTR(String),
X_NUMBERS
#undef X
};
int main(void)
{
int k;
printf("Hello World!\n\n");
for (k = 0; k < kMax; k++)
{
printf("%s\n", kConstStr[k]);
}
return 0;
}
If you are using gcc, it's possible to use:
const char * enum_to_string_map[]={ [enum1]='string1', [enum2]='string2'};
Then just call for instance
enum_to_string_map[enum1]
Check out the ideas at Mu Dynamics Research Labs - Blog Archive. I found this earlier this year - I forget the exact context where I came across it - and have adapted it into this code. We can debate the merits of adding an E at the front; it is applicable to the specific problem addressed, but not part of a general solution. I stashed this away in my 'vignettes' folder - where I keep interesting scraps of code in case I want them later. I'm embarrassed to say that I didn't keep a note of where this idea came from at the time.
Header: paste1.h
/*
#(#)File: $RCSfile: paste1.h,v $
#(#)Version: $Revision: 1.1 $
#(#)Last changed: $Date: 2008/05/17 21:38:05 $
#(#)Purpose: Automated Token Pasting
*/
#ifndef JLSS_ID_PASTE_H
#define JLSS_ID_PASTE_H
/*
* Common case when someone just includes this file. In this case,
* they just get the various E* tokens as good old enums.
*/
#if !defined(ETYPE)
#define ETYPE(val, desc) E##val,
#define ETYPE_ENUM
enum {
#endif /* ETYPE */
ETYPE(PERM, "Operation not permitted")
ETYPE(NOENT, "No such file or directory")
ETYPE(SRCH, "No such process")
ETYPE(INTR, "Interrupted system call")
ETYPE(IO, "I/O error")
ETYPE(NXIO, "No such device or address")
ETYPE(2BIG, "Arg list too long")
/*
* Close up the enum block in the common case of someone including
* this file.
*/
#if defined(ETYPE_ENUM)
#undef ETYPE_ENUM
#undef ETYPE
ETYPE_MAX
};
#endif /* ETYPE_ENUM */
#endif /* JLSS_ID_PASTE_H */
Example source:
/*
#(#)File: $RCSfile: paste1.c,v $
#(#)Version: $Revision: 1.2 $
#(#)Last changed: $Date: 2008/06/24 01:03:38 $
#(#)Purpose: Automated Token Pasting
*/
#include "paste1.h"
static const char *sys_errlist_internal[] = {
#undef JLSS_ID_PASTE_H
#define ETYPE(val, desc) desc,
#include "paste1.h"
0
#undef ETYPE
};
static const char *xerror(int err)
{
if (err >= ETYPE_MAX || err <= 0)
return "Unknown error";
return sys_errlist_internal[err];
}
static const char*errlist_mnemonics[] = {
#undef JLSS_ID_PASTE_H
#define ETYPE(val, desc) [E ## val] = "E" #val,
#include "paste1.h"
#undef ETYPE
};
#include <stdio.h>
int main(void)
{
int i;
for (i = 0; i < ETYPE_MAX; i++)
{
printf("%d: %-6s: %s\n", i, errlist_mnemonics[i], xerror(i));
}
return(0);
}
Not necessarily the world's cleanest use of the C pre-processor - but it does prevent writing the material out multiple times.
Making something both a C identifier and a string
#define stringify( name ) # name
enum MyEnum {
ENUMVAL1
};
...stuff...
stringify(EnumName::ENUMVAL1); // Returns MyEnum::ENUMVAL1
Further discussion on this method
Preprocessor directive tricks for newcomers
If the enum index is 0-based, you can put the names in an array of char*, and index them with the enum value.
I have created a simple templated class streamable_enum that uses stream operators << and >> and is based on the std::map<Enum, std::string>:
#ifndef STREAMABLE_ENUM_HPP
#define STREAMABLE_ENUM_HPP
#include <iostream>
#include <string>
#include <map>
template <typename E>
class streamable_enum
{
public:
typedef typename std::map<E, std::string> tostr_map_t;
typedef typename std::map<std::string, E> fromstr_map_t;
streamable_enum()
{}
streamable_enum(E val) :
Val_(val)
{}
operator E() {
return Val_;
}
bool operator==(const streamable_enum<E>& e) {
return this->Val_ == e.Val_;
}
bool operator==(const E& e) {
return this->Val_ == e;
}
static const tostr_map_t& to_string_map() {
static tostr_map_t to_str_(get_enum_strings<E>());
return to_str_;
}
static const fromstr_map_t& from_string_map() {
static fromstr_map_t from_str_(reverse_map(to_string_map()));
return from_str_;
}
private:
E Val_;
static fromstr_map_t reverse_map(const tostr_map_t& eToS) {
fromstr_map_t sToE;
for (auto pr : eToS) {
sToE.emplace(pr.second, pr.first);
}
return sToE;
}
};
template <typename E>
streamable_enum<E> stream_enum(E e) {
return streamable_enum<E>(e);
}
template <typename E>
typename streamable_enum<E>::tostr_map_t get_enum_strings() {
// \todo throw an appropriate exception or display compile error/warning
return {};
}
template <typename E>
std::ostream& operator<<(std::ostream& os, streamable_enum<E> e) {
auto& mp = streamable_enum<E>::to_string_map();
auto res = mp.find(e);
if (res != mp.end()) {
os << res->second;
} else {
os.setstate(std::ios_base::failbit);
}
return os;
}
template <typename E>
std::istream& operator>>(std::istream& is, streamable_enum<E>& e) {
std::string str;
is >> str;
if (str.empty()) {
is.setstate(std::ios_base::failbit);
}
auto& mp = streamable_enum<E>::from_string_map();
auto res = mp.find(str);
if (res != mp.end()) {
e = res->second;
} else {
is.setstate(std::ios_base::failbit);
}
return is;
}
#endif
Usage:
#include "streamable_enum.hpp"
using std::cout;
using std::cin;
using std::endl;
enum Animal {
CAT,
DOG,
TIGER,
RABBIT
};
template <>
streamable_enum<Animal>::tostr_map_t get_enum_strings<Animal>() {
return {
{ CAT, "Cat"},
{ DOG, "Dog" },
{ TIGER, "Tiger" },
{ RABBIT, "Rabbit" }
};
}
int main(int argc, char* argv []) {
cout << "What animal do you want to buy? Our offering:" << endl;
for (auto pr : streamable_enum<Animal>::to_string_map()) { // Use from_string_map() and pr.first instead
cout << " " << pr.second << endl; // to have them sorted in alphabetical order
}
streamable_enum<Animal> anim;
cin >> anim;
if (!cin) {
cout << "We don't have such animal here." << endl;
} else if (anim == Animal::TIGER) {
cout << stream_enum(Animal::TIGER) << " was a joke..." << endl;
} else {
cout << "Here you are!" << endl;
}
return 0;
}
Here is a solution using macros with the following features:
only write each value of the enum once, so there are no double lists to maintain
don't keep the enum values in a separate file that is later #included, so I can write it wherever I want
don't replace the enum itself, I still want to have the enum type defined, but in addition to it I want to be able to map every enum name to the corresponding string (to not affect legacy code)
the searching should be fast, so preferably no switch-case, for those huge enums
https://stackoverflow.com/a/20134475/1812866
I thought that a solution like Boost.Fusion one for adapting structs and classes would be nice, they even had it at some point, to use enums as a fusion sequence.
So I made just some small macros to generate the code to print the enums. This is not perfect and has nothing to see with Boost.Fusion generated boilerplate code, but can be used like the Boost Fusion macros. I want to really do generate the types needed by Boost.Fusion to integrate in this infrastructure which allows to print names of struct members, but this will happen later, for now this is just macros :
#ifndef SWISSARMYKNIFE_ENUMS_ADAPT_ENUM_HPP
#define SWISSARMYKNIFE_ENUMS_ADAPT_ENUM_HPP
#include <swissarmyknife/detail/config.hpp>
#include <string>
#include <ostream>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define SWISSARMYKNIFE_ADAPT_ENUM_EACH_ENUMERATION_ENTRY_C( \
R, unused, ENUMERATION_ENTRY) \
case ENUMERATION_ENTRY: \
return BOOST_PP_STRINGIZE(ENUMERATION_ENTRY); \
break;
/**
* \brief Adapts ENUM to reflectable types.
*
* \param ENUM_TYPE To be adapted
* \param ENUMERATION_SEQ Sequence of enum states
*/
#define SWISSARMYKNIFE_ADAPT_ENUM(ENUM_TYPE, ENUMERATION_SEQ) \
inline std::string to_string(const ENUM_TYPE& enum_value) { \
switch (enum_value) { \
BOOST_PP_SEQ_FOR_EACH( \
SWISSARMYKNIFE_ADAPT_ENUM_EACH_ENUMERATION_ENTRY_C, \
unused, ENUMERATION_SEQ) \
default: \
return BOOST_PP_STRINGIZE(ENUM_TYPE); \
} \
} \
\
inline std::ostream& operator<<(std::ostream& os, const ENUM_TYPE& value) { \
os << to_string(value); \
return os; \
}
#endif
The old answer below is pretty bad, please don't use that. :)
Old answer:
I've been searching a way which solves this problem without changing too much the enums declaration syntax. I came to a solution which uses the preprocessor to retrieve a string from a stringified enum declaration.
I'm able to define non-sparse enums like this :
SMART_ENUM(State,
enum State {
RUNNING,
SLEEPING,
FAULT,
UNKNOWN
})
And I can interact with them in different ways:
// With a stringstream
std::stringstream ss;
ss << State::FAULT;
std::string myEnumStr = ss.str();
//Directly to stdout
std::cout << State::FAULT << std::endl;
//to a string
std::string myStr = State::to_string(State::FAULT);
//from a string
State::State myEnumVal = State::from_string(State::FAULT);
Based on the following definitions :
#define SMART_ENUM(enumTypeArg, ...) \
namespace enumTypeArg { \
__VA_ARGS__; \
std::ostream& operator<<(std::ostream& os, const enumTypeArg& val) { \
os << swissarmyknife::enums::to_string(#__VA_ARGS__, val); \
return os; \
} \
\
std::string to_string(const enumTypeArg& val) { \
return swissarmyknife::enums::to_string(#__VA_ARGS__, val); \
} \
\
enumTypeArg from_string(const std::string &str) { \
return swissarmyknife::enums::from_string<enumTypeArg>(#__VA_ARGS__, str); \
} \
} \
namespace swissarmyknife { namespace enums {
static inline std::string to_string(const std::string completeEnumDeclaration, size_t enumVal) throw (std::runtime_error) {
size_t begin = completeEnumDeclaration.find_first_of('{');
size_t end = completeEnumDeclaration.find_last_of('}');
const std::string identifiers = completeEnumDeclaration.substr(begin + 1, end );
size_t count = 0;
size_t found = 0;
do {
found = identifiers.find_first_of(",}", found+1);
if (enumVal == count) {
std::string identifiersSubset = identifiers.substr(0, found);
size_t beginId = identifiersSubset.find_last_of("{,");
identifiersSubset = identifiersSubset.substr(beginId+1);
boost::algorithm::trim(identifiersSubset);
return identifiersSubset;
}
++count;
} while (found != std::string::npos);
throw std::runtime_error("The enum declaration provided doesn't contains this state.");
}
template <typename EnumType>
static inline EnumType from_string(const std::string completeEnumDeclaration, const std::string &enumStr) throw (std::runtime_error) {
size_t begin = completeEnumDeclaration.find_first_of('{');
size_t end = completeEnumDeclaration.find_last_of('}');
const std::string identifiers = completeEnumDeclaration.substr(begin + 1, end );
size_t count = 0;
size_t found = 0;
do {
found = identifiers.find_first_of(",}", found+1);
std::string identifiersSubset = identifiers.substr(0, found);
size_t beginId = identifiersSubset.find_last_of("{,");
identifiersSubset = identifiersSubset.substr(beginId+1);
boost::algorithm::trim(identifiersSubset);
if (identifiersSubset == enumStr) {
return static_cast<EnumType>(count);
}
++count;
} while (found != std::string::npos);
throw std::runtime_error("No valid enum value for the provided string");
}
}}
When I'll need support for sparse enum and when I'll have more time I'll improve the to_string and from_string implementations with boost::xpressive, but this will costs in compilation time because of the important templating performed and the executable generated is likely to be really bigger. But this has the advantage that it will be more readable and maintanable than this ugly manual string manipulation code. :D
Otherwise I always used boost::bimap to perform such mappings between enums value and string, but it has to be maintained manually.
Because I prefer not to use macros for all the usual reasons, I used a more limited macro solution that has the advantage of keeping the enum declaration macro free. Disadvantages include having to copy paste the macro defintion for each enum, and having to explicitly add a macro invocation when adding values to the enum.
std::ostream& operator<<(std::ostream& os, provenance_wrapper::CaptureState cs)
{
#define HANDLE(x) case x: os << #x; break;
switch (cs) {
HANDLE(CaptureState::UNUSED)
HANDLE(CaptureState::ACTIVE)
HANDLE(CaptureState::CLOSED)
}
return os;
#undef HANDLE
}
There's a way simpler and imo sorta clearer approach
that was missing on this thread:
#define ENUM_PUSH(ENUM) ENUM,
#define STRING_PUSH(STR) #STR,
#define FETCH_MSG(X) \
X(string1) \
X(string2) \
static const char * msgStr[] = {
FETCH_MSG(STRING_PUSH)
};
enum msg {
FETCH_MSG(ENUM_PUSH)
};
static enum msg message;
void iterate(void) {
switch (message) {
case string1:
// do your thing here
break;
case string2:
break;
}
}
The only downside is that the last cell will be postceded by a comma,
though it appears to be acceptable by C/C++ compilers.

Resources