diff options
author | Andreas Volz <andreas@optolix.mittelerde> | 2009-03-28 22:27:08 +0100 |
---|---|---|
committer | Andreas Volz <andreas@optolix.mittelerde> | 2009-03-28 22:27:08 +0100 |
commit | 7424df631dc6ce43820df8b52b47b93140bad909 (patch) | |
tree | 130bd1fbb022d0fb0dc7a920d1f4a8a7d83101df | |
parent | 3b3ffe166bb01405e75e1f558ccb76ab668d6711 (diff) | |
download | dbus-c++-7424df631dc6ce43820df8b52b47b93140bad909.tar.gz |
split into multiple files for better organization
-rw-r--r-- | tools/Makefile.am | 4 | ||||
-rw-r--r-- | tools/generate_adaptor.cpp | 708 | ||||
-rw-r--r-- | tools/generate_adaptor.h | 9 | ||||
-rw-r--r-- | tools/generate_proxy.cpp | 654 | ||||
-rw-r--r-- | tools/generate_proxy.h | 8 | ||||
-rw-r--r-- | tools/generator_utils.cpp | 128 | ||||
-rw-r--r-- | tools/generator_utils.h | 23 | ||||
-rw-r--r-- | tools/xml2cpp.cpp | 1467 | ||||
-rw-r--r-- | tools/xml2cpp.h | 11 |
9 files changed, 1540 insertions, 1472 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index 36691d4..b2e595e 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -17,7 +17,9 @@ endif bin_PROGRAMS = dbusxx-xml2cpp dbusxx-introspect -dbusxx_xml2cpp_SOURCES = xml.h xml.cpp xml2cpp.h xml2cpp.cpp +dbusxx_xml2cpp_SOURCES = xml.h xml.cpp xml2cpp.h xml2cpp.cpp \ + generate_adaptor.cpp generate_proxy.cpp generate_adaptor.h\ + generate_proxy.h generator_utils.cpp generator_utils.h dbusxx_xml2cpp_LDADD = $(libdbus_cxx_la) $(xml_LIBS) dbusxx_introspect_SOURCES = introspect.h introspect.cpp diff --git a/tools/generate_adaptor.cpp b/tools/generate_adaptor.cpp new file mode 100644 index 0000000..cac6bfc --- /dev/null +++ b/tools/generate_adaptor.cpp @@ -0,0 +1,708 @@ +#include <iostream> +#include <fstream> + +#include "generator_utils.h" +#include "generate_adaptor.h" + +using namespace std; +using namespace DBus; + +static const char *tab = " "; + +static const char *header = "\n\ +/*\n\ + * This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!\n\ + */\n\ +\n\ +"; + +static const char *dbus_includes = "\n\ +#include <dbus-c++/dbus.h>\n\ +#include <cassert>\n\n\ +\n\ +"; + +/*! Generate adaptor code for a XML introspection + */ +void generate_adaptor(Xml::Document &doc, const char *filename) +{ + ostringstream body; + ostringstream head; + vector <string> include_vector; + + head << header; + string filestring = filename; + underscorize(filestring); + + string cond_comp = "__dbusxx__" + filestring + "__ADAPTOR_MARSHAL_H"; + + head << "#ifndef " << cond_comp << endl + << "#define " << cond_comp << endl; + + head << dbus_includes; + + Xml::Node &root = *(doc.root); + Xml::Nodes interfaces = root["interface"]; + + // iterate over all interface definitions + for (Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i) + { + Xml::Node &iface = **i; + Xml::Nodes methods = iface["method"]; + Xml::Nodes signals = iface["signal"]; + Xml::Nodes properties = iface["property"]; + Xml::Nodes ms; + ms.insert(ms.end(), methods.begin(), methods.end()); + ms.insert(ms.end(), signals.begin(), signals.end()); + + // gets the name of a interface: <interface name="XYZ"> + string ifacename = iface.get("name"); + + // these interface names are skipped. + if (ifacename == "org.freedesktop.DBus.Introspectable" + ||ifacename == "org.freedesktop.DBus.Properties") + { + cerr << "skipping interface " << ifacename << endl; + continue; + } + + istringstream ss(ifacename); + string nspace; + unsigned int nspaces = 0; + + // prints all the namespaces defined with <interface name="X.Y.Z"> + while (ss.str().find('.', ss.tellg()) != string::npos) + { + getline(ss, nspace, '.'); + + body << "namespace " << nspace << " {" << endl; + + ++nspaces; + } + body << endl; + + string ifaceclass; + + getline(ss, ifaceclass); + + // a "_adaptor" is added to class name to distinguish between proxy and adaptor + ifaceclass += "_adaptor"; + + cerr << "generating code for interface " << ifacename << "..." << endl; + + // the code from class definiton up to opening of the constructor is generated... + body << "class " << ifaceclass << endl + << ": public ::DBus::InterfaceAdaptor" << endl + << "{" << endl + << "public:" << endl + << endl + << tab << ifaceclass << "()" << endl + << tab << ": ::DBus::InterfaceAdaptor(\"" << ifacename << "\")" << endl + << tab << "{" << endl; + + // generates code to bind the properties + for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) + { + Xml::Node &property = **pi; + + body << tab << tab << "bind_property(" + << property.get("name") << ", " + << "\"" << property.get("type") << "\", " + << (property.get("access").find("read") != string::npos + ? "true" + : "false") + << ", " + << (property.get("access").find("write") != string::npos + ? "true" + : "false") + << ");" << endl; + } + + // generate code to register all methods + for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) + { + Xml::Node &method = **mi; + + body << tab << tab << "register_method(" + << ifaceclass << ", " << method.get("name") << ", "<< stub_name(method.get("name")) + << ");" << endl; + } + + body << tab << "}" << endl + << endl; + + body << tab << "::DBus::IntrospectedInterface *const introspect() const " << endl + << tab << "{" << endl; + + // generate the introspect arguments + for (Xml::Nodes::iterator mi = ms.begin(); mi != ms.end(); ++mi) + { + Xml::Node &method = **mi; + Xml::Nodes args = method["arg"]; + + body << tab << tab << "static ::DBus::IntrospectedArgument " << method.get("name") << "_args[] = " << endl + << tab << tab << "{" << endl; + + for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai) + { + Xml::Node &arg = **ai; + + body << tab << tab << tab << "{ "; + + if (arg.get("name").length()) + { + body << "\"" << arg.get("name") << "\", "; + } + else + { + body << "0, "; + } + body << "\"" << arg.get("type") << "\", " + << (arg.get("direction") == "in" ? "true" : "false") + << " }," << endl; + } + body << tab << tab << tab << "{ 0, 0, 0 }" << endl + << tab << tab << "};" << endl; + } + + body << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_methods[] = " << endl + << tab << tab << "{" << endl; + + // generate the introspect methods + for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) + { + Xml::Node &method = **mi; + + body << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; + } + + body << tab << tab << tab << "{ 0, 0 }" << endl + << tab << tab << "};" << endl; + + body << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_signals[] = " << endl + << tab << tab << "{" << endl; + + for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) + { + Xml::Node &method = **si; + + body << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; + } + + body << tab << tab << tab << "{ 0, 0 }" << endl + << tab << tab << "};" << endl; + + body << tab << tab << "static ::DBus::IntrospectedProperty " << ifaceclass << "_properties[] = " << endl + << tab << tab << "{" << endl; + + for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) + { + Xml::Node &property = **pi; + + body << tab << tab << tab << "{ " + << "\"" << property.get("name") << "\", " + << "\"" << property.get("type") << "\", " + << (property.get("access").find("read") != string::npos + ? "true" + : "false") + << ", " + << (property.get("access").find("write") != string::npos + ? "true" + : "false") + << " }," << endl; + } + + + body << tab << tab << tab << "{ 0, 0, 0, 0 }" << endl + << tab << tab << "};" << endl; + + // generate the Introspected interface + body << tab << tab << "static ::DBus::IntrospectedInterface " << ifaceclass << "_interface = " << endl + << tab << tab << "{" << endl + << tab << tab << tab << "\"" << ifacename << "\"," << endl + << tab << tab << tab << ifaceclass << "_methods," << endl + << tab << tab << tab << ifaceclass << "_signals," << endl + << tab << tab << tab << ifaceclass << "_properties" << endl + << tab << tab << "};" << endl + << tab << tab << "return &" << ifaceclass << "_interface;" << endl + << tab << "}" << endl + << endl; + + body << "public:" << endl + << endl + << tab << "/* properties exposed by this interface, use" << endl + << tab << " * property() and property(value) to get and set a particular property" << endl + << tab << " */" << endl; + + // generate the properties code + for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) + { + Xml::Node &property = **pi; + string name = property.get("name"); + string type = property.get("type"); + string type_name = signature_to_type(type); + + body << tab << "::DBus::PropertyAdaptor< " << type_name << " > " << name << ";" << endl; + } + + body << endl; + + body << "public:" << endl + << endl + << tab << "/* methods exported by this interface," << endl + << tab << " * you will have to implement them in your ObjectAdaptor" << endl + << tab << " */" << endl; + + // generate the methods code + for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) + { + Xml::Node &method = **mi; + Xml::Nodes args = method["arg"]; + Xml::Nodes args_in = args.select("direction","in"); + Xml::Nodes args_out = args.select("direction","out"); + Xml::Nodes annotations = args["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + body << tab << "virtual "; + + // return type is 'void' if none or multible return values + if (args_out.size() == 0 || args_out.size() > 1) + { + body << "void "; + } + else if (args_out.size() == 1) + { + // generate basic or object return type + if (arg_object.length()) + { + body << arg_object << " "; + } + else + { + body << signature_to_type(args_out.front()->get("type")) << " "; + } + } + + // generate the method name + body << method.get("name") << "("; + + // generate the methods 'in' variables + unsigned int i = 0; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_name = arg.get("name"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate basic signature only if no object name available... + if (!arg_object.length()) + { + body << "const " << signature_to_type(arg.get("type")) << "& "; + } + // ...or generate object style if available + else + { + body << "const " << arg_object << "& "; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + + if (arg_name.length()) + body << arg_name; + + if ((i+1 != args_in.size() || args_out.size() > 1)) + body << ", "; + } + + // generate the method 'out' variables if multibe 'out' values exist + if (args_out.size() > 1) + { + unsigned int i = 0; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) + { + Xml::Node &arg = **ao; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_name = arg.get("name"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate basic signature only if no object name available... + if (!arg_object.length()) + { + body << "const " << signature_to_type(arg.get("type")) << "& "; + } + // ...or generate object style if available + else + { + body << "const " << arg_object << "& "; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + + if (arg_name.length()) + body << " " << arg_name; + + if (i+1 != args_out.size()) + body << ", "; + } + } + body << ") = 0;" << endl; + } + + body << endl + << "public:" << endl + << endl + << tab << "/* signal emitters for this interface" << endl + << tab << " */" << endl; + + // generate the signals code + for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) + { + Xml::Node &signal = **si; + Xml::Nodes args = signal["arg"]; + + body << tab << "void " << signal.get("name") << "("; + + // generate the signal arguments + unsigned int i = 0; + for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i) + { + Xml::Node &arg = **a; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate basic signature only if no object name available... + if (!arg_object.length()) + { + body << "const " << signature_to_type(arg.get("type")) << "& arg" << i+1; + } + // ...or generate object style if available + else + { + body << "const " << arg_object << "& arg" << i+1; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + + if (i+1 != args.size()) + body << ", "; + } + + body << ")" << endl + << tab << "{" << endl + << tab << tab << "::DBus::SignalMessage sig(\"" << signal.get("name") <<"\");" << endl; + + // generate the signal body + if (args.size() > 0) + { + body << tab << tab << "::DBus::MessageIter wi = sig.writer();" << endl; + + unsigned int i = 0; + for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i) + { + Xml::Node &arg = **a; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (arg_object.length()) + { + body << tab << tab << signature_to_type(arg.get("type")) << " _arg" << i+1 << ";" << endl; + body << tab << tab << "_arg" << i+1 << " << " << "arg" << i+1 << ";" << endl; + + body << tab << tab << "wi << _arg" << i+1 << ";" << endl; + } + else + { + body << tab << tab << "wi << arg" << i+1 << ";" << endl; + } + } + } + + // emit the signal in method body + body << tab << tab << "emit_signal(sig);" << endl + << tab << "}" << endl; + } + + body << endl + << "private:" << endl + << endl + << tab << "/* unmarshalers (to unpack the DBus message before calling the actual interface method)" << endl + << tab << " */" << endl; + + // generate the unmarshalers + for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) + { + Xml::Node &method = **mi; + Xml::Nodes args = method["arg"]; + Xml::Nodes args_in = args.select("direction","in"); + Xml::Nodes args_out = args.select("direction","out"); + + body << tab << "::DBus::Message " << stub_name(method.get("name")) << "(const ::DBus::CallMessage &call)" << endl + << tab << "{" << endl + << tab << tab << "::DBus::MessageIter ri = call.reader();" << endl + << endl; + + // generate the 'in' variables + unsigned int i = 1; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + + body << tab << tab << signature_to_type(arg.get("type")) << " argin" << i << ";" << " "; + body << "ri >> argin" << i << ";" << endl; + } + + // generate the 'in' object variables + i = 1; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (arg_object.length()) + { + body << tab << tab << arg_object << " _argin" << i << ";"; + body << " " << "_argin" << i << " << " << "argin" << i << ";" << endl; + } + } + + // generate 'out' variables + if (args_out.size() > 0) + { + unsigned int i = 1; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) + { + Xml::Node &arg = **ao; + + body << tab << tab << signature_to_type(arg.get("type")) << " argout" << i; + + if (args_out.size() == 1) // a single 'out' parameter will be assigned + { + body << " = "; + } + else // multible 'out' parameters will be handled as parameters below + { + body << ";" << endl; + } + } + } + + // generate 'out' object variables + if (args_out.size() > 0) + { + unsigned int i = 1; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) + { + Xml::Node &arg = **ao; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate object types + if (arg_object.length()) + { + body << tab << tab << arg_object << " _argout" << i << ";" << endl; + } + } + } + + // generate in '<<' operation + i = 0; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + } + + // do correct indent + if (args_out.size() != 1 ) + { + body << tab << tab; + } + + body << method.get("name") << "("; + + // generate call stub parameters + i = 0; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (arg_object.length()) + { + body << "_argin" << i+1; + } + else + { + body << "argin" << i+1; + } + + if ((i+1 != args_in.size() || args_out.size() > 1)) + body << ", "; + } + + if (args_out.size() > 1) + { + i = 0; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) + { + Xml::Node &arg = **ao; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (arg_object.length()) + { + body << "_argout" << i+1; + } + else + { + body << "argout" << i+1; + } + + if (i+1 != args_out.size()) + body << ", "; + } + } + + body << ");" << endl; + + body << tab << tab << "::DBus::ReturnMessage reply(call);" << endl; + + if (args_out.size() > 0) + { + body << tab << tab << "::DBus::MessageIter wi = reply.writer();" << endl; + + // generate out '<<' operation + i = 0; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) + { + Xml::Node &arg = **ao; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (arg_object.length()) + { + body << tab << tab << "argout" << i+1 << " << " << "_argout" << i+1 << ";" << endl; + } + } + + for (unsigned int i = 0; i < args_out.size(); ++i) + { + body << tab << tab << "wi << argout" << i+1 << ";" << endl; + } + } + + body << tab << tab << "return reply;" << endl; + + body << tab << "}" << endl; + } + + body << "};" << endl + << endl; + + for (unsigned int i = 0; i < nspaces; ++i) + { + body << "} "; + } + body << endl; + } + + body << "#endif //" << cond_comp << endl; + + // remove all duplicates in the header include vector + vector<string>::const_iterator vec_end_it = unique (include_vector.begin (), include_vector.end ()); + + for (vector<string>::const_iterator vec_it = include_vector.begin (); + vec_it != vec_end_it; + ++vec_it) + { + const string &include = *vec_it; + + head << "#include " << "\"" << include << ".h" << "\"" << endl; + } + head << endl; + + ofstream file(filename); + if (file.bad()) + { + cerr << "unable to write file " << filename << endl; + exit(-1); + } + + file << head.str (); + file << body.str (); + + file.close(); +} diff --git a/tools/generate_adaptor.h b/tools/generate_adaptor.h new file mode 100644 index 0000000..dd7738d --- /dev/null +++ b/tools/generate_adaptor.h @@ -0,0 +1,9 @@ +#ifndef __DBUSXX_TOOLS_GENERATE_ADAPTOR_H +#define __DBUSXX_TOOLS_GENERATE_ADAPTOR_H + +#include <string> +#include "xml.h" + +void generate_adaptor(DBus::Xml::Document &doc, const char *filename); + +#endif//__DBUSXX_TOOLS_GENERATE_ADAPTOR_H diff --git a/tools/generate_proxy.cpp b/tools/generate_proxy.cpp new file mode 100644 index 0000000..64da9fa --- /dev/null +++ b/tools/generate_proxy.cpp @@ -0,0 +1,654 @@ +#include <iostream> +#include <fstream> + +#include "generator_utils.h" +#include "generate_proxy.h" + +using namespace std; +using namespace DBus; + +static const char *tab = " "; + +static const char *header = "\n\ +/*\n\ + * This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!\n\ + */\n\ +\n\ +"; + +static const char *dbus_includes = "\n\ +#include <dbus-c++/dbus.h>\n\ +#include <cassert>\n\n\ +\n\ +"; + +/*! Generate proxy code for a XML introspection + */ +void generate_proxy(Xml::Document &doc, const char *filename) +{ + ostringstream body; + ostringstream head; + vector <string> include_vector; + + head << header; + string filestring = filename; + underscorize(filestring); + + string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H"; + + head << "#ifndef " << cond_comp << endl + << "#define " << cond_comp << endl; + + head << dbus_includes; + + Xml::Node &root = *(doc.root); + Xml::Nodes interfaces = root["interface"]; + + // iterate over all interface definitions + for (Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i) + { + Xml::Node &iface = **i; + Xml::Nodes methods = iface["method"]; + Xml::Nodes signals = iface["signal"]; + Xml::Nodes properties = iface["property"]; + Xml::Nodes ms; + ms.insert(ms.end(), methods.begin(), methods.end()); + ms.insert(ms.end(), signals.begin(), signals.end()); + + // gets the name of a interface: <interface name="XYZ"> + string ifacename = iface.get("name"); + + // these interface names are skipped. + if (ifacename == "org.freedesktop.DBus.Introspectable" + ||ifacename == "org.freedesktop.DBus.Properties") + { + cerr << "skipping interface " << ifacename << endl; + continue; + } + + istringstream ss(ifacename); + string nspace; + unsigned int nspaces = 0; + + // prints all the namespaces defined with <interface name="X.Y.Z"> + while (ss.str().find('.', ss.tellg()) != string::npos) + { + getline(ss, nspace, '.'); + + body << "namespace " << nspace << " {" << endl; + + ++nspaces; + } + body << endl; + + string ifaceclass; + + getline(ss, ifaceclass); + + // a "_proxy" is added to class name to distinguish between proxy and adaptor + ifaceclass += "_proxy"; + + cerr << "generating code for interface " << ifacename << "..." << endl; + + // the code from class definiton up to opening of the constructor is generated... + body << "class " << ifaceclass << endl + << " : public ::DBus::InterfaceProxy" << endl + << "{" << endl + << "public:" << endl + << endl + << tab << ifaceclass << "()" << endl + << tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl + << tab << "{" << endl; + + // generates code to connect all the signal stubs; this is still inside the constructor + for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) + { + Xml::Node &signal = **si; + + string marshname = "_" + signal.get("name") + "_stub"; + + body << tab << tab << "connect_signal(" + << ifaceclass << ", " << signal.get("name") << ", " << stub_name(signal.get("name")) + << ");" << endl; + } + + // the constructor ends here + body << tab << "}" << endl + << endl; + + // write public block header for properties + body << "public:" << endl << endl + << tab << "/* properties exported by this interface */" << endl; + + // this loop generates all properties + for (Xml::Nodes::iterator pi = properties.begin (); + pi != properties.end (); ++pi) + { + Xml::Node & property = **pi; + string prop_name = property.get ("name"); + string property_access = property.get ("access"); + if (property_access == "read" || property_access == "readwrite") + { + body << tab << tab << "const " << signature_to_type (property.get("type")) + << " " << prop_name << "() {" << endl; + body << tab << tab << tab << "::DBus::CallMessage call ;\n "; + body << tab << tab << tab + << "call.member(\"Get\"); call.interface(\"org.freedesktop.DBus.Properties\");" + << endl; + body << tab << tab << tab + << "::DBus::MessageIter wi = call.writer(); " << endl; + body << tab << tab << tab + << "const std::string interface_name = \"" << ifacename << "\";" + << endl; + body << tab << tab << tab + << "const std::string property_name = \"" << prop_name << "\";" + << endl; + body << tab << tab << tab << "wi << interface_name;" << endl; + body << tab << tab << tab << "wi << property_name;" << endl; + body << tab << tab << tab + << "::DBus::Message ret = this->invoke_method (call);" << endl; + // TODO: support invoke_method_NoReply for properties + body << tab << tab << tab + << "::DBus::MessageIter ri = ret.reader ();" << endl; + body << tab << tab << tab << "::DBus::Variant argout; " << endl; + body << tab << tab << tab << "ri >> argout;" << endl; + body << tab << tab << tab << "return argout;" << endl; + body << tab << tab << "};" << endl; + } + + if (property_access == "write" || property_access == "readwrite") + { + body << tab << tab << "void " << prop_name << "( const "<< signature_to_type (property.get("type")) << " & input" << ") {" << endl; + body << tab << tab << tab << "::DBus::CallMessage call ;\n "; + body << tab << tab << tab <<"call.member(\"Set\"); call.interface( \"org.freedesktop.DBus.Properties\");"<< endl; + body << tab << tab << tab <<"::DBus::MessageIter wi = call.writer(); " << endl; + body << tab << tab << tab <<"::DBus::Variant value;" << endl; + body << tab << tab << tab <<"::DBus::MessageIter vi = value.writer ();" << endl; + body << tab << tab << tab <<"vi << input;" << endl; + body << tab << tab << tab <<"const std::string interface_name = \"" << ifacename << "\";" << endl; + body << tab << tab << tab <<"const std::string property_name = \"" << prop_name << "\";"<< endl; + body << tab << tab << tab <<"wi << interface_name;" << endl; + body << tab << tab << tab <<"wi << property_name;" << endl; + body << tab << tab << tab <<"wi << value;" << endl; + body << tab << tab << tab <<"::DBus::Message ret = this->invoke_method (call);" << endl; + // TODO: support invoke_method_noreply for properties + body << tab << tab << "};" << endl; + } + } + + // write public block header for methods + body << "public:" << endl + << endl + << tab << "/* methods exported by this interface," << endl + << tab << " * this functions will invoke the corresponding methods on the remote objects" << endl + << tab << " */" << endl; + + // this loop generates all methods + for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) + { + Xml::Node &method = **mi; + Xml::Nodes args = method["arg"]; + Xml::Nodes args_in = args.select("direction","in"); + Xml::Nodes args_out = args.select("direction","out"); + Xml::Nodes annotations = args["annotation"]; + Xml::Nodes method_annotations = method["annotation"]; + Xml::Nodes annotations_noreply = method_annotations.select("name","org.freedesktop.DBus.Method.NoReply"); + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + bool annotation_noreply_value = false; + + // parse method level noreply annotations + if (annotations_noreply.size() > 0) + { + string annotation_noreply_value_str = annotations_noreply.front()->get("value"); + + if (annotation_noreply_value_str == "true") + { + annotation_noreply_value = true; + } + } + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (args_out.size() == 0 || args_out.size() > 1) + { + body << tab << "void "; + } + else if (args_out.size() == 1) + { + if (arg_object.length()) + { + body << tab << arg_object << " "; + } + else + { + body << tab << signature_to_type(args_out.front()->get("type")) << " "; + } + } + + body << method.get("name") << "("; + + // generate all 'in' arguments for a method signature + unsigned int i = 0; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate basic signature only if no object name available... + if (!arg_object.length()) + { + body << "const " << signature_to_type(arg.get("type")) << "& "; + } + // ...or generate object style if available + else + { + body << "const " << arg_object << "& "; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + + string arg_name = arg.get("name"); + if (arg_name.length()) + body << arg_name; + else + body << "argin" << i; + + if ((i+1 != args_in.size() || args_out.size() > 1)) + body << ", "; + } + + if (args_out.size() > 1) + { + // generate all 'out' arguments for a method signature + unsigned int j = 0; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++j) + { + Xml::Node &arg = **ao; + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate basic signature only if no object name available... + if (!arg_object.length()) + { + body << signature_to_type(arg.get("type")) << "&"; + } + // ...or generate object style if available + else + { + body << arg_object << "& "; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + + string arg_name = arg.get("name"); + if (arg_name.length()) + body << " " << arg_name; + else + body << " argout" << j; + + if (j+1 != args_out.size()) + body << ", "; + } + } + body << ")" << endl; + + body << tab << "{" << endl + << tab << tab << "::DBus::CallMessage call;" << endl; + + if (args_in.size() > 0) + { + body << tab << tab << "::DBus::MessageIter wi = call.writer();" << endl + << endl; + } + + // generate all 'in' arguments for a method body + i = 0; + for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + string arg_name = arg.get("name"); + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (!arg_name.length()) + { + arg_name = "argin"; + arg_name += toString <uint> (i); + } + + // generate extra code to wrap object + if (arg_object.length()) + { + body << tab << tab << signature_to_type(arg.get("type")) << "_" << arg_name << ";" << endl; + body << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl; + + arg_name = string ("_") + arg_name; + } + + body << tab << tab << "wi << " << arg_name << ";" << endl; + } + + body << tab << tab << "call.member(\"" << method.get("name") << "\");" << endl; + + // generate noreply/reply method calls + if (annotation_noreply_value) + { + if (args_out.size ()) + { + cerr << "Function: " << method.get("name") << ":" << endl; + cerr << "Option 'org.freedesktop.DBus.Method.NoReply' not allowed for methods with 'out' variables!" << endl << "-> Option ignored!" << endl; + + body << tab << tab << "::DBus::Message ret = invoke_method (call);" << endl; + } + else + { + body << tab << tab << "assert (invoke_method_noreply (call));" << endl; // will only assert in case of no memory + } + } + else + { + body << tab << tab << "::DBus::Message ret = invoke_method (call);" << endl; + } + + if (args_out.size() > 0) + { + body << tab << tab << "::DBus::MessageIter ri = ret.reader();" << endl + << endl; + } + + // generate 'out' values as return if only one existing + if (args_out.size() == 1) + { + Xml::Nodes annotations = args_out["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (arg_object.length()) + { + body << tab << tab << arg_object << " _argout;" << endl; + } + + body << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout;" << endl; + + body << tab << tab << "ri >> argout;" << endl; + + if (arg_object.length()) + { + body << tab << tab << "_argout << argout;" << endl; + body << tab << tab << "return _argout;" << endl; + } + else + { + body << tab << tab << "return argout;" << endl; + } + } + else if (args_out.size() > 1) + { + // generate multible 'out' value + unsigned int i = 0; + for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) + { + Xml::Node &arg = **ao; + string arg_name = arg.get("name"); + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (!arg_name.length()) + { + arg_name = "argout" + toString <uint> (i); + } + + if (arg_object.length()) + { + body << tab << tab << signature_to_type(arg.get("type")) << "_" << arg_name << ";" << endl; + } + + if (arg_object.length()) + { + body << tab << tab << "ri >> " << "_" << arg_name << ";" << endl; + } + else + { + body << tab << tab << "ri >> " << arg_name << ";" << endl; + } + + if (arg_object.length()) + { + body << tab << tab << arg_name << " << " << "_" << arg_name << ";" << endl; + } + } + } + + body << tab << "}" << endl + << endl; + } + + // write public block header for signals + body << endl + << "public:" << endl + << endl + << tab << "/* signal handlers for this interface" << endl + << tab << " */" << endl; + + // this loop generates all signals + for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) + { + Xml::Node &signal = **si; + Xml::Nodes args = signal["arg"]; + + body << tab << "virtual void " << signal.get("name") << "("; + + // this loop generates all argument for a signal + unsigned int i = 0; + for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + string arg_name = arg.get("name"); + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + // generate basic signature only if no object name available... + if (!arg_object.length()) + { + body << "const " << signature_to_type(arg.get("type")) << "& "; + } + // ...or generate object style if available + else + { + body << "const " << arg_object << "& "; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + + if (arg_name.length()) + body << arg_name; + else + body << "argin" << i; + + if ((ai+1 != args.end())) + body << ", "; + } + body << ") = 0;" << endl; + } + + // write private block header for unmarshalers + body << endl + << "private:" << endl + << endl + << tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl + << tab << " */" << endl; + + // generate all the unmarshalers + for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) + { + Xml::Node &signal = **si; + Xml::Nodes args = signal["arg"]; + + body << tab << "void " << stub_name(signal.get("name")) << "(const ::DBus::SignalMessage &sig)" << endl + << tab << "{" << endl; + + if (args.size() > 0) + { + body << tab << tab << "::DBus::MessageIter ri = sig.reader();" << endl + << endl; + } + + unsigned int i = 0; + for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) + { + Xml::Node &arg = **ai; + string arg_name = arg.get("name"); + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + body << tab << tab << signature_to_type(arg.get("type")) << " " ; + + // use a default if no arg name given + if (!arg_name.length()) + { + arg_name = "arg" + toString <uint> (i); + } + + body << arg_name << ";" << endl; + body << tab << tab << "ri >> " << arg_name << ";" << endl; + + // if a object type is used create a local variable and insert values with '<<' operation + if (arg_object.length()) + { + body << tab << tab << arg_object << " _" << arg_name << ";" << endl; + body << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl; + + // store a object name to later generate header includes + include_vector.push_back (arg_object); + } + } + + body << tab << tab << signal.get("name") << "("; + + // generate all arguments for the call to the virtual function + unsigned int j = 0; + for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j) + { + Xml::Node &arg = **ai; + string arg_name = arg.get("name"); + Xml::Nodes annotations = arg["annotation"]; + Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); + string arg_object; + + if (annotations_object.size() > 0) + { + arg_object = annotations_object.front()->get("value"); + } + + if (!arg_name.length()) + { + arg_name = "arg" + toString <uint> (j); + } + + if (arg_object.length()) + { + body << "_" << arg_name; + } + else + { + body << arg_name; + } + + if (ai+1 != args.end()) + body << ", "; + } + + body << ");" << endl; + + body << tab << "}" << endl; + } + + + body << "};" << endl + << endl; + + for (unsigned int i = 0; i < nspaces; ++i) + { + body << "} "; + } + body << endl; + } + + body << "#endif //" << cond_comp << endl; + + cerr << "writing " << filename << endl; + + // remove all duplicates in the header include vector + vector<string>::const_iterator vec_end_it = unique (include_vector.begin (), include_vector.end ()); + + for (vector<string>::const_iterator vec_it = include_vector.begin (); + vec_it != vec_end_it; + ++vec_it) + { + const string &include = *vec_it; + + head << "#include " << "\"" << include << ".h" << "\"" << endl; + } + head << endl; + + ofstream file(filename); + if (file.bad()) + { + cerr << "unable to write file " << filename << endl; + exit(-1); + } + + file << head.str (); + file << body.str (); + + file.close(); +} diff --git a/tools/generate_proxy.h b/tools/generate_proxy.h new file mode 100644 index 0000000..bdf07d0 --- /dev/null +++ b/tools/generate_proxy.h @@ -0,0 +1,8 @@ +#ifndef __DBUSXX_TOOLS_GENERATE_PROXY_H +#define __DBUSXX_TOOLS_GENERATE_PROXY_H + +#include "xml.h" + +void generate_proxy(DBus::Xml::Document &doc, const char *filename); + +#endif//__DBUSXX_TOOLS_GENERATE_PROXY_H diff --git a/tools/generator_utils.cpp b/tools/generator_utils.cpp new file mode 100644 index 0000000..4ebeb98 --- /dev/null +++ b/tools/generator_utils.cpp @@ -0,0 +1,128 @@ +#include "generator_utils.h" + +#include <iostream> + +using namespace std; + +const char *atomic_type_to_string(char t) +{ + static struct { char type; const char *name; } atos[] = + { + { 'y', "uint8_t" }, + { 'b', "bool" }, + { 'n', "int16_t" }, + { 'q', "uint16_t" }, + { 'i', "int32_t" }, + { 'u', "uint32_t" }, + { 'x', "int64_t" }, + { 't', "uint64_t" }, + { 'd', "double" }, + { 's', "std::string" }, + { 'o', "::DBus::Path" }, + { 'g', "::DBus::Signature" }, + { 'v', "::DBus::Variant" }, + { '\0', "" } + }; + int i; + + for (i = 0; atos[i].type; ++i) + { + if (atos[i].type == t) break; + } + return atos[i].name; +} + +string stub_name(string name) +{ + underscorize(name); + + return "_" + name + "_stub"; +} + +void _parse_signature(const string &signature, string &type, unsigned int &i) +{ + for (; i < signature.length(); ++i) + { + switch (signature[i]) + { + case 'a': + { + switch (signature[++i]) + { + case '{': + { + type += "std::map< "; + + const char *atom = atomic_type_to_string(signature[++i]); + if (!atom) + { + cerr << "invalid signature" << endl; + exit(-1); + } + type += atom; + type += ", "; + ++i; + break; + } + default: + { + type += "std::vector< "; + break; + } + } + _parse_signature(signature, type, i); + type += " >"; + continue; + } + case '(': + { + type += "::DBus::Struct< "; + ++i; + _parse_signature(signature, type, i); + type += " >"; + if (signature[i+1]) + { + type += ", "; + } + continue; + } + case ')': + case '}': + { + return; + } + default: + { + const char *atom = atomic_type_to_string(signature[i]); + if (!atom) + { + cerr << "invalid signature" << endl; + exit(-1); + } + type += atom; + + if (signature[i+1] != ')' && signature[i+1] != '}' && i+1 < signature.length()) + { + type += ", "; + } + break; + } + } + } +} + +string signature_to_type(const string &signature) +{ + string type; + unsigned int i = 0; + _parse_signature(signature, type, i); + return type; +} + +void underscorize(string &str) +{ + for (unsigned int i = 0; i < str.length(); ++i) + { + if (!isalpha(str[i]) && !isdigit(str[i])) str[i] = '_'; + } +} diff --git a/tools/generator_utils.h b/tools/generator_utils.h new file mode 100644 index 0000000..281affa --- /dev/null +++ b/tools/generator_utils.h @@ -0,0 +1,23 @@ +#ifndef __DBUSXX_TOOLS_GENERATOR_UTILS_H +#define __DBUSXX_TOOLS_GENERATOR_UTILS_H + +#include <string> +#include <sstream> +#include <iomanip> + +const char *atomic_type_to_string(char t); +std::string stub_name(std::string name); +std::string signature_to_type(const std::string &signature); +void _parse_signature(const std::string &signature, std::string &type, unsigned int &i); +void underscorize(std::string &str); + +/// create std::string from any number +template <typename T> +std::string toString (const T &thing, int w = 0, int p = 0) +{ + std::ostringstream os; + os << std::setw(w) << std::setprecision(p) << thing; + return os.str(); +} + +#endif//__DBUSXX_TOOLS_GENERATOR_UTILS_H diff --git a/tools/xml2cpp.cpp b/tools/xml2cpp.cpp index 870b2cc..81cd18e 100644 --- a/tools/xml2cpp.cpp +++ b/tools/xml2cpp.cpp @@ -21,9 +21,6 @@ * */ - -#include "xml2cpp.h" - #include <dbus/dbus.h> #include <cstdlib> @@ -35,25 +32,14 @@ #include <sstream> #include <algorithm> +#include "xml2cpp.h" +#include "generate_adaptor.h" +#include "generate_proxy.h" + using namespace std; using namespace DBus; -static const char *tab = " "; - -static const char *header = "\n\ -/*\n\ - * This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!\n\ - */\n\ -\n\ -"; - -static const char *dbus_includes = "\n\ -#include <dbus-c++/dbus.h>\n\ -#include <cassert>\n\n\ -\n\ -"; - -typedef map<string,string> TypeCache; +//typedef map<string,string> TypeCache; void usage(const char *argv0) { @@ -62,22 +48,7 @@ void usage(const char *argv0) exit(-1); } -void underscorize(string &str) -{ - for (unsigned int i = 0; i < str.length(); ++i) - { - if (!isalpha(str[i]) && !isdigit(str[i])) str[i] = '_'; - } -} - -string stub_name(string name) -{ - underscorize(name); - - return "_" + name + "_stub"; -} - -int char_to_atomic_type(char t) +/*int char_to_atomic_type(char t) { if (strchr("ybnqiuxtdsgavre", t)) return t; @@ -85,1434 +56,10 @@ int char_to_atomic_type(char t) return DBUS_TYPE_INVALID; } -const char *atomic_type_to_string(char t) -{ - static struct { char type; const char *name; } atos[] = - { - { 'y', "uint8_t" }, - { 'b', "bool" }, - { 'n', "int16_t" }, - { 'q', "uint16_t" }, - { 'i', "int32_t" }, - { 'u', "uint32_t" }, - { 'x', "int64_t" }, - { 't', "uint64_t" }, - { 'd', "double" }, - { 's', "std::string" }, - { 'o', "::DBus::Path" }, - { 'g', "::DBus::Signature" }, - { 'v', "::DBus::Variant" }, - { '\0', "" } - }; - int i; - - for (i = 0; atos[i].type; ++i) - { - if (atos[i].type == t) break; - } - return atos[i].name; -} - bool is_atomic_type(const string &type) { return type.length() == 1 && char_to_atomic_type(type[0]) != DBUS_TYPE_INVALID; -} - -void _parse_signature(const string &signature, string &type, unsigned int &i) -{ - for (; i < signature.length(); ++i) - { - switch (signature[i]) - { - case 'a': - { - switch (signature[++i]) - { - case '{': - { - type += "std::map< "; - - const char *atom = atomic_type_to_string(signature[++i]); - if (!atom) - { - cerr << "invalid signature" << endl; - exit(-1); - } - type += atom; - type += ", "; - ++i; - break; - } - default: - { - type += "std::vector< "; - break; - } - } - _parse_signature(signature, type, i); - type += " >"; - continue; - } - case '(': - { - type += "::DBus::Struct< "; - ++i; - _parse_signature(signature, type, i); - type += " >"; - if (signature[i+1]) - { - type += ", "; - } - continue; - } - case ')': - case '}': - { - return; - } - default: - { - const char *atom = atomic_type_to_string(signature[i]); - if (!atom) - { - cerr << "invalid signature" << endl; - exit(-1); - } - type += atom; - - if (signature[i+1] != ')' && signature[i+1] != '}' && i+1 < signature.length()) - { - type += ", "; - } - break; - } - } - } -} - -string signature_to_type(const string &signature) -{ - string type; - unsigned int i = 0; - _parse_signature(signature, type, i); - return type; -} - -/*! Generate proxy code for a XML introspection - */ -void generate_proxy(Xml::Document &doc, const char *filename) -{ - ostringstream body; - ostringstream head; - vector <string> include_vector; - - head << header; - string filestring = filename; - underscorize(filestring); - - string cond_comp = "__dbusxx__" + filestring + "__PROXY_MARSHAL_H"; - - head << "#ifndef " << cond_comp << endl; - head << "#define " << cond_comp << endl; - - head << dbus_includes; - - Xml::Node &root = *(doc.root); - Xml::Nodes interfaces = root["interface"]; - - // iterate over all interface definitions - for (Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i) - { - Xml::Node &iface = **i; - Xml::Nodes methods = iface["method"]; - Xml::Nodes signals = iface["signal"]; - Xml::Nodes properties = iface["property"]; - Xml::Nodes ms; - ms.insert(ms.end(), methods.begin(), methods.end()); - ms.insert(ms.end(), signals.begin(), signals.end()); - - // gets the name of a interface: <interface name="XYZ"> - string ifacename = iface.get("name"); - - // these interface names are skipped. - if (ifacename == "org.freedesktop.DBus.Introspectable" - ||ifacename == "org.freedesktop.DBus.Properties") - { - cerr << "skipping interface " << ifacename << endl; - continue; - } - - istringstream ss(ifacename); - string nspace; - unsigned int nspaces = 0; - - // prints all the namespaces defined with <interface name="X.Y.Z"> - while (ss.str().find('.', ss.tellg()) != string::npos) - { - getline(ss, nspace, '.'); - - body << "namespace " << nspace << " {" << endl; - - ++nspaces; - } - body << endl; - - string ifaceclass; - - getline(ss, ifaceclass); - - // a "_proxy" is added to class name to distinguish between proxy and adaptor - ifaceclass += "_proxy"; - - cerr << "generating code for interface " << ifacename << "..." << endl; - - // the code from class definiton up to opening of the constructor is generated... - body << "class " << ifaceclass << endl - << " : public ::DBus::InterfaceProxy" << endl - << "{" << endl - << "public:" << endl - << endl - << tab << ifaceclass << "()" << endl - << tab << ": ::DBus::InterfaceProxy(\"" << ifacename << "\")" << endl - << tab << "{" << endl; - - // generates code to connect all the signal stubs; this is still inside the constructor - for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) - { - Xml::Node &signal = **si; - - string marshname = "_" + signal.get("name") + "_stub"; - - body << tab << tab << "connect_signal(" - << ifaceclass << ", " << signal.get("name") << ", " << stub_name(signal.get("name")) - << ");" << endl; - } - - // the constructor ends here - body << tab << "}" << endl - << endl; - - // write public block header for properties - body << "public:" << endl << endl - << tab << "/* properties exported by this interface */" << endl; - - // this loop generates all properties - for (Xml::Nodes::iterator pi = properties.begin (); - pi != properties.end (); ++pi) - { - Xml::Node & property = **pi; - string prop_name = property.get ("name"); - string property_access = property.get ("access"); - if (property_access == "read" || property_access == "readwrite") - { - body << tab << tab << "const " << signature_to_type (property.get("type")) - << " " << prop_name << "() {" << endl; - body << tab << tab << tab << "::DBus::CallMessage call ;\n "; - body << tab << tab << tab - << "call.member(\"Get\"); call.interface(\"org.freedesktop.DBus.Properties\");" - << endl; - body << tab << tab << tab - << "::DBus::MessageIter wi = call.writer(); " << endl; - body << tab << tab << tab - << "const std::string interface_name = \"" << ifacename << "\";" - << endl; - body << tab << tab << tab - << "const std::string property_name = \"" << prop_name << "\";" - << endl; - body << tab << tab << tab << "wi << interface_name;" << endl; - body << tab << tab << tab << "wi << property_name;" << endl; - body << tab << tab << tab - << "::DBus::Message ret = this->invoke_method (call);" << endl; - // TODO: support invoke_method_NoReply for properties - body << tab << tab << tab - << "::DBus::MessageIter ri = ret.reader ();" << endl; - body << tab << tab << tab << "::DBus::Variant argout; " << endl; - body << tab << tab << tab << "ri >> argout;" << endl; - body << tab << tab << tab << "return argout;" << endl; - body << tab << tab << "};" << endl; - } - - if (property_access == "write" || property_access == "readwrite") - { - body << tab << tab << "void " << prop_name << "( const "<< signature_to_type (property.get("type")) << " & input" << ") {" << endl; - body << tab << tab << tab << "::DBus::CallMessage call ;\n "; - body << tab << tab << tab <<"call.member(\"Set\"); call.interface( \"org.freedesktop.DBus.Properties\");"<< endl; - body << tab << tab << tab <<"::DBus::MessageIter wi = call.writer(); " << endl; - body << tab << tab << tab <<"::DBus::Variant value;" << endl; - body << tab << tab << tab <<"::DBus::MessageIter vi = value.writer ();" << endl; - body << tab << tab << tab <<"vi << input;" << endl; - body << tab << tab << tab <<"const std::string interface_name = \"" << ifacename << "\";" << endl; - body << tab << tab << tab <<"const std::string property_name = \"" << prop_name << "\";"<< endl; - body << tab << tab << tab <<"wi << interface_name;" << endl; - body << tab << tab << tab <<"wi << property_name;" << endl; - body << tab << tab << tab <<"wi << value;" << endl; - body << tab << tab << tab <<"::DBus::Message ret = this->invoke_method (call);" << endl; - // TODO: support invoke_method_noreply for properties - body << tab << tab << "};" << endl; - } - } - - // write public block header for methods - body << "public:" << endl - << endl - << tab << "/* methods exported by this interface," << endl - << tab << " * this functions will invoke the corresponding methods on the remote objects" << endl - << tab << " */" << endl; - - // this loop generates all methods - for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) - { - Xml::Node &method = **mi; - Xml::Nodes args = method["arg"]; - Xml::Nodes args_in = args.select("direction","in"); - Xml::Nodes args_out = args.select("direction","out"); - Xml::Nodes annotations = args["annotation"]; - Xml::Nodes method_annotations = method["annotation"]; - Xml::Nodes annotations_noreply = method_annotations.select("name","org.freedesktop.DBus.Method.NoReply"); - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - bool annotation_noreply_value = false; - - // parse method level noreply annotations - if (annotations_noreply.size() > 0) - { - string annotation_noreply_value_str = annotations_noreply.front()->get("value"); - - if (annotation_noreply_value_str == "true") - { - annotation_noreply_value = true; - } - } - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (args_out.size() == 0 || args_out.size() > 1) - { - body << tab << "void "; - } - else if (args_out.size() == 1) - { - if (arg_object.length()) - { - body << tab << arg_object << " "; - } - else - { - body << tab << signature_to_type(args_out.front()->get("type")) << " "; - } - } - - body << method.get("name") << "("; - - // generate all 'in' arguments for a method signature - unsigned int i = 0; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate basic signature only if no object name available... - if (!arg_object.length()) - { - body << "const " << signature_to_type(arg.get("type")) << "& "; - } - // ...or generate object style if available - else - { - body << "const " << arg_object << "& "; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - - string arg_name = arg.get("name"); - if (arg_name.length()) - body << arg_name; - else - body << "argin" << i; - - if ((i+1 != args_in.size() || args_out.size() > 1)) - body << ", "; - } - - if (args_out.size() > 1) - { - // generate all 'out' arguments for a method signature - unsigned int j = 0; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++j) - { - Xml::Node &arg = **ao; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate basic signature only if no object name available... - if (!arg_object.length()) - { - body << signature_to_type(arg.get("type")) << "&"; - } - // ...or generate object style if available - else - { - body << arg_object << "& "; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - - string arg_name = arg.get("name"); - if (arg_name.length()) - body << " " << arg_name; - else - body << " argout" << j; - - if (j+1 != args_out.size()) - body << ", "; - } - } - body << ")" << endl; - - body << tab << "{" << endl - << tab << tab << "::DBus::CallMessage call;" << endl; - - if (args_in.size() > 0) - { - body << tab << tab << "::DBus::MessageIter wi = call.writer();" << endl - << endl; - } - - // generate all 'in' arguments for a method body - i = 0; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - string arg_name = arg.get("name"); - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (!arg_name.length()) - { - arg_name = "argin"; - arg_name += toString <uint> (i); - } - - // generate extra code to wrap object - if (arg_object.length()) - { - body << tab << tab << signature_to_type(arg.get("type")) << "_" << arg_name << ";" << endl; - body << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl; - - arg_name = string ("_") + arg_name; - } - - body << tab << tab << "wi << " << arg_name << ";" << endl; - } - - body << tab << tab << "call.member(\"" << method.get("name") << "\");" << endl; - - // generate noreply/reply method calls - if (annotation_noreply_value) - { - if (args_out.size ()) - { - cerr << "Function: " << method.get("name") << ":" << endl; - cerr << "Option 'org.freedesktop.DBus.Method.NoReply' not allowed for methods with 'out' variables!" << endl << "-> Option ignored!" << endl; - - body << tab << tab << "::DBus::Message ret = invoke_method (call);" << endl; - } - else - { - body << tab << tab << "assert (invoke_method_noreply (call));" << endl; // will only assert in case of no memory - } - } - else - { - body << tab << tab << "::DBus::Message ret = invoke_method (call);" << endl; - } - - if (args_out.size() > 0) - { - body << tab << tab << "::DBus::MessageIter ri = ret.reader();" << endl - << endl; - } - - // generate 'out' values as return if only one existing - if (args_out.size() == 1) - { - Xml::Nodes annotations = args_out["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (arg_object.length()) - { - body << tab << tab << arg_object << " _argout;" << endl; - } - - body << tab << tab << signature_to_type(args_out.front()->get("type")) << " argout;" << endl; - - body << tab << tab << "ri >> argout;" << endl; - - if (arg_object.length()) - { - body << tab << tab << "_argout << argout;" << endl; - body << tab << tab << "return _argout;" << endl; - } - else - { - body << tab << tab << "return argout;" << endl; - } - } - else if (args_out.size() > 1) - { - // generate multible 'out' value - unsigned int i = 0; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) - { - Xml::Node &arg = **ao; - string arg_name = arg.get("name"); - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (!arg_name.length()) - { - arg_name = "argout" + toString <uint> (i); - } - - if (arg_object.length()) - { - body << tab << tab << signature_to_type(arg.get("type")) << "_" << arg_name << ";" << endl; - } - - if (arg_object.length()) - { - body << tab << tab << "ri >> " << "_" << arg_name << ";" << endl; - } - else - { - body << tab << tab << "ri >> " << arg_name << ";" << endl; - } - - if (arg_object.length()) - { - body << tab << tab << arg_name << " << " << "_" << arg_name << ";" << endl; - } - } - } - - body << tab << "}" << endl - << endl; - } - - // write public block header for signals - body << endl - << "public:" << endl - << endl - << tab << "/* signal handlers for this interface" << endl - << tab << " */" << endl; - - // this loop generates all signals - for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) - { - Xml::Node &signal = **si; - Xml::Nodes args = signal["arg"]; - - body << tab << "virtual void " << signal.get("name") << "("; - - // this loop generates all argument for a signal - unsigned int i = 0; - for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - string arg_name = arg.get("name"); - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate basic signature only if no object name available... - if (!arg_object.length()) - { - body << "const " << signature_to_type(arg.get("type")) << "& "; - } - // ...or generate object style if available - else - { - body << "const " << arg_object << "& "; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - - if (arg_name.length()) - body << arg_name; - else - body << "argin" << i; - - if ((ai+1 != args.end())) - body << ", "; - } - body << ") = 0;" << endl; - } - - // write private block header for unmarshalers - body << endl - << "private:" << endl - << endl - << tab << "/* unmarshalers (to unpack the DBus message before calling the actual signal handler)" << endl - << tab << " */" << endl; - - // generate all the unmarshalers - for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) - { - Xml::Node &signal = **si; - Xml::Nodes args = signal["arg"]; - - body << tab << "void " << stub_name(signal.get("name")) << "(const ::DBus::SignalMessage &sig)" << endl - << tab << "{" << endl; - - if (args.size() > 0) - { - body << tab << tab << "::DBus::MessageIter ri = sig.reader();" << endl - << endl; - } - - unsigned int i = 0; - for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - string arg_name = arg.get("name"); - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - body << tab << tab << signature_to_type(arg.get("type")) << " " ; - - // use a default if no arg name given - if (!arg_name.length()) - { - arg_name = "arg" + toString <uint> (i); - } - - body << arg_name << ";" << endl; - body << tab << tab << "ri >> " << arg_name << ";" << endl; - - // if a object type is used create a local variable and insert values with '<<' operation - if (arg_object.length()) - { - body << tab << tab << arg_object << " _" << arg_name << ";" << endl; - body << tab << tab << "_" << arg_name << " << " << arg_name << ";" << endl; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - } - - body << tab << tab << signal.get("name") << "("; - - // generate all arguments for the call to the virtual function - unsigned int j = 0; - for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai, ++j) - { - Xml::Node &arg = **ai; - string arg_name = arg.get("name"); - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (!arg_name.length()) - { - arg_name = "arg" + toString <uint> (j); - } - - if (arg_object.length()) - { - body << "_" << arg_name; - } - else - { - body << arg_name; - } - - if (ai+1 != args.end()) - body << ", "; - } - - body << ");" << endl; - - body << tab << "}" << endl; - } - - - body << "};" << endl - << endl; - - for (unsigned int i = 0; i < nspaces; ++i) - { - body << "} "; - } - body << endl; - } - - body << "#endif //" << cond_comp << endl; - - cerr << "writing " << filename << endl; - - // remove all duplicates in the header include vector - vector<string>::const_iterator vec_end_it = unique (include_vector.begin (), include_vector.end ()); - - for (vector<string>::const_iterator vec_it = include_vector.begin (); - vec_it != vec_end_it; - ++vec_it) - { - const string &include = *vec_it; - - head << "#include " << "\"" << include << ".h" << "\"" << endl; - } - head << endl; - - ofstream file(filename); - if (file.bad()) - { - cerr << "unable to write file " << filename << endl; - exit(-1); - } - - file << head.str (); - file << body.str (); - - file.close(); -} - -/*! Generate adaptor code for a XML introspection - */ -void generate_adaptor(Xml::Document &doc, const char *filename) -{ - ostringstream body; - ostringstream head; - vector <string> include_vector; - - head << header; - string filestring = filename; - underscorize(filestring); - - string cond_comp = "__dbusxx__" + filestring + "__ADAPTOR_MARSHAL_H"; - - head << "#ifndef " << cond_comp << endl - << "#define " << cond_comp << endl; - - head << dbus_includes; - - Xml::Node &root = *(doc.root); - Xml::Nodes interfaces = root["interface"]; - - // iterate over all interface definitions - for (Xml::Nodes::iterator i = interfaces.begin(); i != interfaces.end(); ++i) - { - Xml::Node &iface = **i; - Xml::Nodes methods = iface["method"]; - Xml::Nodes signals = iface["signal"]; - Xml::Nodes properties = iface["property"]; - Xml::Nodes ms; - ms.insert(ms.end(), methods.begin(), methods.end()); - ms.insert(ms.end(), signals.begin(), signals.end()); - - // gets the name of a interface: <interface name="XYZ"> - string ifacename = iface.get("name"); - - // these interface names are skipped. - if (ifacename == "org.freedesktop.DBus.Introspectable" - ||ifacename == "org.freedesktop.DBus.Properties") - { - cerr << "skipping interface " << ifacename << endl; - continue; - } - - istringstream ss(ifacename); - string nspace; - unsigned int nspaces = 0; - - // prints all the namespaces defined with <interface name="X.Y.Z"> - while (ss.str().find('.', ss.tellg()) != string::npos) - { - getline(ss, nspace, '.'); - - body << "namespace " << nspace << " {" << endl; - - ++nspaces; - } - body << endl; - - string ifaceclass; - - getline(ss, ifaceclass); - - // a "_adaptor" is added to class name to distinguish between proxy and adaptor - ifaceclass += "_adaptor"; - - cerr << "generating code for interface " << ifacename << "..." << endl; - - // the code from class definiton up to opening of the constructor is generated... - body << "class " << ifaceclass << endl - << ": public ::DBus::InterfaceAdaptor" << endl - << "{" << endl - << "public:" << endl - << endl - << tab << ifaceclass << "()" << endl - << tab << ": ::DBus::InterfaceAdaptor(\"" << ifacename << "\")" << endl - << tab << "{" << endl; - - // generates code to bind the properties - for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) - { - Xml::Node &property = **pi; - - body << tab << tab << "bind_property(" - << property.get("name") << ", " - << "\"" << property.get("type") << "\", " - << (property.get("access").find("read") != string::npos - ? "true" - : "false") - << ", " - << (property.get("access").find("write") != string::npos - ? "true" - : "false") - << ");" << endl; - } - - // generate code to register all methods - for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) - { - Xml::Node &method = **mi; - - body << tab << tab << "register_method(" - << ifaceclass << ", " << method.get("name") << ", "<< stub_name(method.get("name")) - << ");" << endl; - } - - body << tab << "}" << endl - << endl; - - body << tab << "::DBus::IntrospectedInterface *const introspect() const " << endl - << tab << "{" << endl; - - // generate the introspect arguments - for (Xml::Nodes::iterator mi = ms.begin(); mi != ms.end(); ++mi) - { - Xml::Node &method = **mi; - Xml::Nodes args = method["arg"]; - - body << tab << tab << "static ::DBus::IntrospectedArgument " << method.get("name") << "_args[] = " << endl - << tab << tab << "{" << endl; - - for (Xml::Nodes::iterator ai = args.begin(); ai != args.end(); ++ai) - { - Xml::Node &arg = **ai; - - body << tab << tab << tab << "{ "; - - if (arg.get("name").length()) - { - body << "\"" << arg.get("name") << "\", "; - } - else - { - body << "0, "; - } - body << "\"" << arg.get("type") << "\", " - << (arg.get("direction") == "in" ? "true" : "false") - << " }," << endl; - } - body << tab << tab << tab << "{ 0, 0, 0 }" << endl - << tab << tab << "};" << endl; - } - - body << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_methods[] = " << endl - << tab << tab << "{" << endl; - - // generate the introspect methods - for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) - { - Xml::Node &method = **mi; - - body << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; - } - - body << tab << tab << tab << "{ 0, 0 }" << endl - << tab << tab << "};" << endl; - - body << tab << tab << "static ::DBus::IntrospectedMethod " << ifaceclass << "_signals[] = " << endl - << tab << tab << "{" << endl; - - for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) - { - Xml::Node &method = **si; - - body << tab << tab << tab << "{ \"" << method.get("name") << "\", " << method.get("name") << "_args }," << endl; - } - - body << tab << tab << tab << "{ 0, 0 }" << endl - << tab << tab << "};" << endl; - - body << tab << tab << "static ::DBus::IntrospectedProperty " << ifaceclass << "_properties[] = " << endl - << tab << tab << "{" << endl; - - for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) - { - Xml::Node &property = **pi; - - body << tab << tab << tab << "{ " - << "\"" << property.get("name") << "\", " - << "\"" << property.get("type") << "\", " - << (property.get("access").find("read") != string::npos - ? "true" - : "false") - << ", " - << (property.get("access").find("write") != string::npos - ? "true" - : "false") - << " }," << endl; - } - - - body << tab << tab << tab << "{ 0, 0, 0, 0 }" << endl - << tab << tab << "};" << endl; - - // generate the Introspected interface - body << tab << tab << "static ::DBus::IntrospectedInterface " << ifaceclass << "_interface = " << endl - << tab << tab << "{" << endl - << tab << tab << tab << "\"" << ifacename << "\"," << endl - << tab << tab << tab << ifaceclass << "_methods," << endl - << tab << tab << tab << ifaceclass << "_signals," << endl - << tab << tab << tab << ifaceclass << "_properties" << endl - << tab << tab << "};" << endl - << tab << tab << "return &" << ifaceclass << "_interface;" << endl - << tab << "}" << endl - << endl; - - body << "public:" << endl - << endl - << tab << "/* properties exposed by this interface, use" << endl - << tab << " * property() and property(value) to get and set a particular property" << endl - << tab << " */" << endl; - - // generate the properties code - for (Xml::Nodes::iterator pi = properties.begin(); pi != properties.end(); ++pi) - { - Xml::Node &property = **pi; - string name = property.get("name"); - string type = property.get("type"); - string type_name = signature_to_type(type); - - body << tab << "::DBus::PropertyAdaptor< " << type_name << " > " << name << ";" << endl; - } - - body << endl; - - body << "public:" << endl - << endl - << tab << "/* methods exported by this interface," << endl - << tab << " * you will have to implement them in your ObjectAdaptor" << endl - << tab << " */" << endl; - - // generate the methods code - for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) - { - Xml::Node &method = **mi; - Xml::Nodes args = method["arg"]; - Xml::Nodes args_in = args.select("direction","in"); - Xml::Nodes args_out = args.select("direction","out"); - Xml::Nodes annotations = args["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - body << tab << "virtual "; - - // return type is 'void' if none or multible return values - if (args_out.size() == 0 || args_out.size() > 1) - { - body << "void "; - } - else if (args_out.size() == 1) - { - // generate basic or object return type - if (arg_object.length()) - { - body << arg_object << " "; - } - else - { - body << signature_to_type(args_out.front()->get("type")) << " "; - } - } - - // generate the method name - body << method.get("name") << "("; - - // generate the methods 'in' variables - unsigned int i = 0; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_name = arg.get("name"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate basic signature only if no object name available... - if (!arg_object.length()) - { - body << "const " << signature_to_type(arg.get("type")) << "& "; - } - // ...or generate object style if available - else - { - body << "const " << arg_object << "& "; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - - if (arg_name.length()) - body << arg_name; - - if ((i+1 != args_in.size() || args_out.size() > 1)) - body << ", "; - } - - // generate the method 'out' variables if multibe 'out' values exist - if (args_out.size() > 1) - { - unsigned int i = 0; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) - { - Xml::Node &arg = **ao; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_name = arg.get("name"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate basic signature only if no object name available... - if (!arg_object.length()) - { - body << "const " << signature_to_type(arg.get("type")) << "& "; - } - // ...or generate object style if available - else - { - body << "const " << arg_object << "& "; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - - if (arg_name.length()) - body << " " << arg_name; - - if (i+1 != args_out.size()) - body << ", "; - } - } - body << ") = 0;" << endl; - } - - body << endl - << "public:" << endl - << endl - << tab << "/* signal emitters for this interface" << endl - << tab << " */" << endl; - - // generate the signals code - for (Xml::Nodes::iterator si = signals.begin(); si != signals.end(); ++si) - { - Xml::Node &signal = **si; - Xml::Nodes args = signal["arg"]; - - body << tab << "void " << signal.get("name") << "("; - - // generate the signal arguments - unsigned int i = 0; - for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i) - { - Xml::Node &arg = **a; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate basic signature only if no object name available... - if (!arg_object.length()) - { - body << "const " << signature_to_type(arg.get("type")) << "& arg" << i+1; - } - // ...or generate object style if available - else - { - body << "const " << arg_object << "& arg" << i+1; - - // store a object name to later generate header includes - include_vector.push_back (arg_object); - } - - if (i+1 != args.size()) - body << ", "; - } - - body << ")" << endl - << tab << "{" << endl - << tab << tab << "::DBus::SignalMessage sig(\"" << signal.get("name") <<"\");" << endl; - - // generate the signal body - if (args.size() > 0) - { - body << tab << tab << "::DBus::MessageIter wi = sig.writer();" << endl; - - unsigned int i = 0; - for (Xml::Nodes::iterator a = args.begin(); a != args.end(); ++a, ++i) - { - Xml::Node &arg = **a; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (arg_object.length()) - { - body << tab << tab << signature_to_type(arg.get("type")) << " _arg" << i+1 << ";" << endl; - body << tab << tab << "_arg" << i+1 << " << " << "arg" << i+1 << ";" << endl; - - body << tab << tab << "wi << _arg" << i+1 << ";" << endl; - } - else - { - body << tab << tab << "wi << arg" << i+1 << ";" << endl; - } - } - } - - // emit the signal in method body - body << tab << tab << "emit_signal(sig);" << endl - << tab << "}" << endl; - } - - body << endl - << "private:" << endl - << endl - << tab << "/* unmarshalers (to unpack the DBus message before calling the actual interface method)" << endl - << tab << " */" << endl; - - // generate the unmarshalers - for (Xml::Nodes::iterator mi = methods.begin(); mi != methods.end(); ++mi) - { - Xml::Node &method = **mi; - Xml::Nodes args = method["arg"]; - Xml::Nodes args_in = args.select("direction","in"); - Xml::Nodes args_out = args.select("direction","out"); - - body << tab << "::DBus::Message " << stub_name(method.get("name")) << "(const ::DBus::CallMessage &call)" << endl - << tab << "{" << endl - << tab << tab << "::DBus::MessageIter ri = call.reader();" << endl - << endl; - - // generate the 'in' variables - unsigned int i = 1; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - - body << tab << tab << signature_to_type(arg.get("type")) << " argin" << i << ";" << " "; - body << "ri >> argin" << i << ";" << endl; - } - - // generate the 'in' object variables - i = 1; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (arg_object.length()) - { - body << tab << tab << arg_object << " _argin" << i << ";"; - body << " " << "_argin" << i << " << " << "argin" << i << ";" << endl; - } - } - - // generate 'out' variables - if (args_out.size() > 0) - { - unsigned int i = 1; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) - { - Xml::Node &arg = **ao; - - body << tab << tab << signature_to_type(arg.get("type")) << " argout" << i; - - if (args_out.size() == 1) // a single 'out' parameter will be assigned - { - body << " = "; - } - else // multible 'out' parameters will be handled as parameters below - { - body << ";" << endl; - } - } - } - - // generate 'out' object variables - if (args_out.size() > 0) - { - unsigned int i = 1; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) - { - Xml::Node &arg = **ao; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - // generate object types - if (arg_object.length()) - { - body << tab << tab << arg_object << " _argout" << i << ";" << endl; - } - } - } - - // generate in '<<' operation - i = 0; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - } - - // do correct indent - if (args_out.size() != 1 ) - { - body << tab << tab; - } - - body << method.get("name") << "("; - - // generate call stub parameters - i = 0; - for (Xml::Nodes::iterator ai = args_in.begin(); ai != args_in.end(); ++ai, ++i) - { - Xml::Node &arg = **ai; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (arg_object.length()) - { - body << "_argin" << i+1; - } - else - { - body << "argin" << i+1; - } - - if ((i+1 != args_in.size() || args_out.size() > 1)) - body << ", "; - } - - if (args_out.size() > 1) - { - i = 0; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) - { - Xml::Node &arg = **ao; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (arg_object.length()) - { - body << "_argout" << i+1; - } - else - { - body << "argout" << i+1; - } - - if (i+1 != args_out.size()) - body << ", "; - } - } - - body << ");" << endl; - - body << tab << tab << "::DBus::ReturnMessage reply(call);" << endl; - - if (args_out.size() > 0) - { - body << tab << tab << "::DBus::MessageIter wi = reply.writer();" << endl; - - // generate out '<<' operation - i = 0; - for (Xml::Nodes::iterator ao = args_out.begin(); ao != args_out.end(); ++ao, ++i) - { - Xml::Node &arg = **ao; - Xml::Nodes annotations = arg["annotation"]; - Xml::Nodes annotations_object = annotations.select("name","org.freedesktop.DBus.Object"); - string arg_object; - - if (annotations_object.size() > 0) - { - arg_object = annotations_object.front()->get("value"); - } - - if (arg_object.length()) - { - body << tab << tab << "argout" << i+1 << " << " << "_argout" << i+1 << ";" << endl; - } - } - - for (unsigned int i = 0; i < args_out.size(); ++i) - { - body << tab << tab << "wi << argout" << i+1 << ";" << endl; - } - } - - body << tab << tab << "return reply;" << endl; - - body << tab << "}" << endl; - } - - body << "};" << endl - << endl; - - for (unsigned int i = 0; i < nspaces; ++i) - { - body << "} "; - } - body << endl; - } - - body << "#endif //" << cond_comp << endl; - - // remove all duplicates in the header include vector - vector<string>::const_iterator vec_end_it = unique (include_vector.begin (), include_vector.end ()); - - for (vector<string>::const_iterator vec_it = include_vector.begin (); - vec_it != vec_end_it; - ++vec_it) - { - const string &include = *vec_it; - - head << "#include " << "\"" << include << ".h" << "\"" << endl; - } - head << endl; - - ofstream file(filename); - if (file.bad()) - { - cerr << "unable to write file " << filename << endl; - exit(-1); - } - - file << head.str (); - file << body.str (); - - file.close(); -} +}*/ int main(int argc, char ** argv) { diff --git a/tools/xml2cpp.h b/tools/xml2cpp.h index 9752426..84f53fe 100644 --- a/tools/xml2cpp.h +++ b/tools/xml2cpp.h @@ -31,17 +31,6 @@ #include <dbus-c++/dbus.h> #include <dbus/dbus.h> -#include <sstream> -#include <iomanip> - -/// create std::string from any number -template <typename T> -std::string toString (const T &thing, int w = 0, int p = 0) -{ - std::ostringstream os; - os << std::setw(w) << std::setprecision(p) << thing; - return os.str(); -} #include "xml.h" |