1 /**
2 * (C) 2016 - 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
3 * (C) 2016 - 2019 Stanislav Angelovic <angelovic.s@gmail.com>
4 *
5 * @file BaseGenerator.cpp
6 *
7 * Created on: Feb 1, 2017
8 * Project: sdbus-c++
9 * Description: High-level D-Bus IPC C++ library based on sd-bus
10 *
11 * This file is part of sdbus-c++.
12 *
13 * sdbus-c++ is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation, either version 2.1 of the License, or
16 * (at your option) any later version.
17 *
18 * sdbus-c++ is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27 // Own
28 #include "generator_utils.h"
29 #include "BaseGenerator.h"
30
31 // STL
32 #include <algorithm>
33 #include <fstream>
34 #include <iterator>
35 #include <iostream>
36 #include <map>
37 #include <sstream>
38
39
40 using std::endl;
41
42 using sdbuscpp::xml::Document;
43 using sdbuscpp::xml::Node;
44 using sdbuscpp::xml::Nodes;
45
46
transformXmlToFile(const Document & doc,const char * filename) const47 int BaseGenerator::transformXmlToFile(const Document& doc, const char* filename) const
48 {
49 return transformXmlToFileImpl(doc, filename);
50 }
51
52
writeToFile(const char * filename,const std::string & data) const53 int BaseGenerator::writeToFile(const char* filename, const std::string& data) const
54 {
55 std::ofstream file(filename);
56 if (file.bad())
57 {
58 std::cerr << "Unable to write file " << filename << endl;
59 return 1;
60 }
61
62 file << data;
63 file.close();
64 return 0;
65 }
66
createHeader(const char * filename,const StubType & stubType) const67 std::string BaseGenerator::createHeader(const char* filename, const StubType& stubType) const
68 {
69 std::ostringstream head;
70 head << getHeaderComment();
71
72 std::string specialization = stubType == StubType::ADAPTOR ? "adaptor" : "proxy";
73
74 std::string cond_comp{"__sdbuscpp__" + underscorize(filename)
75 + "__" + specialization + "__H__"};
76
77 head << "#ifndef " << cond_comp << endl
78 << "#define " << cond_comp << endl << endl;
79
80 head << "#include <sdbus-c++/sdbus-c++.h>" << endl
81 << "#include <string>" << endl
82 << "#include <tuple>" << endl
83 << endl;
84
85 return head.str();
86 }
87
generateNamespaces(const std::string & ifaceName) const88 std::tuple<unsigned, std::string> BaseGenerator::generateNamespaces(const std::string& ifaceName) const
89 {
90 std::stringstream ss{ifaceName};
91 std::ostringstream body;
92 unsigned count{0};
93
94 // prints the namespaces X and Y defined with <interface name="X.Y.Z">
95 while (ss.str().find('.', ss.tellg()) != std::string::npos)
96 {
97 std::string nspace;
98 getline(ss, nspace, '.');
99 nspace = mangle_name(nspace);
100 body << "namespace " << nspace << " {" << endl;
101 ++count;
102 }
103 body << endl;
104
105 return std::make_tuple(count, body.str());
106 }
107
108
argsToNamesAndTypes(const Nodes & args,bool async) const109 std::tuple<std::string, std::string, std::string, std::string> BaseGenerator::argsToNamesAndTypes(const Nodes& args, bool async) const
110 {
111 std::ostringstream argSS, argTypeSS, typeSS, argStringsSS;
112
113 for (size_t i = 0; i < args.size(); ++i)
114 {
115 auto arg = args.at(i);
116 if (i > 0)
117 {
118 argSS << ", ";
119 argStringsSS << ", ";
120 argTypeSS << ", ";
121 typeSS << ", ";
122 }
123
124 auto argName = arg->get("name");
125 if (argName.empty())
126 {
127 argName = "arg" + std::to_string(i);
128 }
129 auto argNameSafe = mangle_name(argName);
130 auto type = signature_to_type(arg->get("type"));
131 argStringsSS << "\"" << argName << "\"";
132 if (!async)
133 {
134 argSS << argNameSafe;
135 argTypeSS << "const " << type << "& " << argNameSafe;
136 }
137 else
138 {
139 argSS << "std::move(" << argNameSafe << ")";
140 argTypeSS << type << " " << argNameSafe;
141 }
142 typeSS << type;
143 }
144
145 return std::make_tuple(argSS.str(), argTypeSS.str(), typeSS.str(), argStringsSS.str());
146 }
147
148 /**
149 *
150 */
outArgsToType(const Nodes & args,bool bareList) const151 std::string BaseGenerator::outArgsToType(const Nodes& args, bool bareList) const
152 {
153 std::ostringstream retTypeSS;
154
155 if (args.size() == 0)
156 {
157 if (bareList)
158 return "";
159
160 retTypeSS << "void";
161 }
162 else if (args.size() == 1)
163 {
164 const auto& arg = *args.begin();
165 retTypeSS << signature_to_type(arg->get("type"));
166 }
167 else if (args.size() >= 2)
168 {
169 if (!bareList)
170 retTypeSS << "std::tuple<";
171
172 bool firstArg = true;
173 for (const auto& arg : args)
174 {
175 if (firstArg) firstArg = false; else retTypeSS << ", ";
176 retTypeSS << signature_to_type(arg->get("type"));
177 }
178
179 if (!bareList)
180 retTypeSS << ">";
181 }
182
183 return retTypeSS.str();
184 }
185
186