summaryrefslogtreecommitdiff
path: root/tools/generate_adaptor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/generate_adaptor.cpp')
-rw-r--r--tools/generate_adaptor.cpp1358
1 files changed, 679 insertions, 679 deletions
diff --git a/tools/generate_adaptor.cpp b/tools/generate_adaptor.cpp
index 940e451..f7972be 100644
--- a/tools/generate_adaptor.cpp
+++ b/tools/generate_adaptor.cpp
@@ -40,683 +40,683 @@ extern const char *dbus_includes;
*/
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 *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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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);
- }
-
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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.empty())
- {
- 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();
+ 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 *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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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);
+ }
+
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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.empty())
+ {
+ 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();
}