YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
generate_cpp_functions.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024-2024 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <vector>
7#include <cstdio>
8
9#include <iostream>
10#include <fstream>
11
12#include <yarp/os/Log.h>
13#include <yarp/os/LogStream.h>
14
15#include "generator.h"
16
18{
19 std::ostringstream s;
21 s << "\n";
22 s << m_classname << "_ParamsParser::" << m_classname << "_ParamsParser()\n";\
23 s << "{\n";
24 for (const auto& param : m_params)
25 {
26 if ( !param.defaultValue.empty() &&
27 (param.type == "vector<int>" ||
28 param.type == "vector<string>" ||
29 param.type == "vector<double>"))
30 {
31 std::string typ="";
32 if (param.type == "vector<int>") { typ = ".asInt64()"; }
33 else if (param.type == "vector<string>") { typ = ".asString()"; }
34 else if (param.type == "vector<double>") { typ = ".asFloat64()"; }
35 s << S_TAB1 << "//Default value of parameter" << param.getFullParamVariable() <<"\n";
36 s << S_TAB1 << "{\n";
37 s << S_TAB1 << " m_" << param.getFullParamVariable() << ".clear();\n";
38 s << S_TAB1 << " yarp::os::Value tempVal;\n";
39 s << S_TAB1 << " tempVal.fromString(m_" << param.getFullParamVariable() << "_defaultValue.c_str()" << ");\n";
40 s << S_TAB1 << " yarp::os::Bottle* tempBot = tempVal.asList();\n";
41 s << S_TAB1 << " if (tempBot && tempBot->size()!=0)\n";
42 s << S_TAB1 << " {\n";
43 s << S_TAB1 << " for (size_t i=0; i<tempBot->size(); i++)\n";
44 s << S_TAB1 << " {\n";
45 s << S_TAB1 << " m_" << param.getFullParamVariable() << ".push_back(tempBot->get(i)" << typ << ");\n";
46 s << S_TAB1 << " }\n";
47 s << S_TAB1 << " }\n";
48 s << S_TAB1 << " else\n";
49 s << S_TAB1 << " {\n";
50 s << S_TAB1 << " yError() <<" << "\"parameter '" << param.getFullParamVariable() << "' is not a properly formatted bottle\";\n";
51 s << S_TAB1 << " }\n";
52 s << S_TAB1 << "}\n\n";
53 }
54 }
55 s << "}\n";
56 s << "\n";
57 return s.str();
58};
59
61{
62 std::ostringstream s;
64s << "\n\
65std::vector<std::string> " << m_classname << "_ParamsParser::getListOfParams() const\n\
66{\n";
67
68s << S_TAB1 << "std::vector<std::string> params;\n";
69
71for (const auto& param : m_params)
72{
73 s << S_TAB1 << "params.push_back(\"" << param.getFullParamName() << "\");\n";
74}
75
77s << S_TAB1 << "return params;\n\
78}\n\
79\n\
80";
81
82 return s.str();
83}
84
86{
87 std::ostringstream s;
89 s << "\n\
90std::string "
91 << m_classname << "_ParamsParser::getConfiguration() const\n\
92{\n";
93 s << S_TAB1 << "//This is a sub-optimal solution.\n";
94 s << S_TAB1 << "//Ideally getConfiguration() should return all parameters but it is currently\n";
95 s << S_TAB1 << "//returning only user provided parameters (excluding default values)\n";
96 s << S_TAB1 << "//This behaviour will be fixed in the near future.\n";
97 s << S_TAB1 << "std::string s_cfg = m_provided_configuration;\n";
98 s << S_TAB1 << "return s_cfg;\n";
99 s << "}\n";
100 return s.str();
101}
102
104{
105 std::ostringstream s;
107 s << "\n\
108bool "
109 << m_classname << "_ParamsParser::getParamValue(const std::string& paramName, std::string& paramValue) const\n\
110{\n";
111
112 if (m_params.size() == 0)
113 {
114 s << S_TAB1 << "return false\n\
115}\n\
116\n\
117";
118 }
119
121 for (const auto& param : m_params)
122 {
123 s << S_TAB1 << "if (paramName ==\"" << param.getFullParamName() << "\")\n";
124 s << S_TAB1 << "{\n";
125 if (param.type == "string") {
126 s << S_TAB1 << " paramValue = m_" << param.getFullParamVariable() << ";\n";
127 s << S_TAB1 << " return true;\n";
128 } else if (param.type == "bool") {
129 s << S_TAB1 << " if (m_" << param.getFullParamVariable() << "==true) paramValue = \"true\";\n";
130 s << S_TAB1 << " else paramValue = \"false\";\n";
131 s << S_TAB1 << " return true;\n";
132 } else if (param.type == "double") {
133 s << S_TAB1 << " paramValue = std::to_string(m_" << param.getFullParamVariable() << ");\n";
134 s << S_TAB1 << " return true;\n";
135 } else if (param.type == "int") {
136 s << S_TAB1 << " paramValue = std::to_string(m_" << param.getFullParamVariable() << ");\n";
137 s << S_TAB1 << " return true;\n";
138 } else if (param.type == "size_t") {
139 s << S_TAB1 << " paramValue = std::to_string(m_" << param.getFullParamVariable() << ");\n";
140 s << S_TAB1 << " return true;\n";
141 } else if (param.type == "float") {
142 s << S_TAB1 << " paramValue = std::to_string(m_" << param.getFullParamVariable() << ");\n";
143 s << S_TAB1 << " return true;\n";
144 } else if (param.type == "char") {
145 s << S_TAB1 << " return false;\n";
146 } else if (param.type == "vector<int>") {
147 s << S_TAB1 << " return false;\n";
148 } else if (param.type == "vector<string>") {
149 s << S_TAB1 << " return false;\n";
150 } else if (param.type == "vector<double>") {
151 s << S_TAB1 << " return false;\n";
152 }
153 s << S_TAB1 << "}\n";
154 }
155 s << "\n";
156 s << S_TAB1 << "yError() <<" << "\"parameter '\" << paramName << \"' was not found\";\n";
157 s << S_TAB1 << "return false;\n";
158 s << "\n\
159}\n\
160\n\
161";
162
163 return s.str();
164}
165
167{
168 std::ostringstream s;
170
171 s << "\n";
172 s << "std::string " << m_classname << "_ParamsParser::getDocumentationOfDeviceParams() const\n";
173 s << "{\n";
174 s << S_TAB1 << "std::string doc;\n";
175
176 s << S_TAB1 << "doc = doc + std::string(\"\\n=============================================\\n\");\n";
177 s << S_TAB1 << "doc = doc + std::string(\"This is the help for device: " << m_classname << "\\n\");\n";
178 s << S_TAB1 << "doc = doc + std::string(\"\\n\");\n";
179 s << S_TAB1 << "doc = doc + std::string(\"This is the list of the parameters accepted by the device:\\n\");\n";
180
181 for (const auto& param : m_params)
182 {
183 s << S_TAB1 << "doc = doc + std::string(\"'" << param.getFullParamName() << "': ";
184 s << param.description;
185 s << "\\n\");\n";
186 }
187
188 s << S_TAB1 << "doc = doc + std::string(\"\\n\");\n";
189 s << S_TAB1 << "doc = doc + std::string(\"Here are some examples of invocation command with yarpdev, with all params:\\n\");\n";
190 s << S_TAB1 << "doc = doc + \"" << generateYarpdevStringAllParams() << "\\n\";\n";
191 s << S_TAB1 << "doc = doc + std::string(\"Using only mandatory params:\\n\");\n";
192 s << S_TAB1 << "doc = doc + \"" << generateYarpdevStringMandatoryParamsOnly() << "\\n\";\n";
193 s << S_TAB1 << "doc = doc + std::string(\"=============================================\\n\\n\");";
194 s << S_TAB1 << "return doc;\n";
195 s << "}\n";
196 return s.str();
197}
198
199void ParamsFilesGenerator::generate_section(std::ostringstream& s, std::deque<std::string> vec, size_t count, size_t siz)
200{
201 if (vec.size()==0) return;
202
203 //The first iteration should take data from config...(1)
204 if (count == 0)
205 {
206 //The last iteration should put data in sectionp...(2)
207 if (count == siz-1)
208 {
209 s << S_TAB2 << "yarp::os::Bottle sectionp" << ";\n";
210 s << S_TAB2 << "sectionp" << " = config.findGroup(\"" << vec.front() << "\");\n";
211 }
212 //(2)...All other iteration should put data in sectionp<count>
213 else
214 {
215 s << S_TAB2 << "yarp::os::Bottle sectionp" << count << ";\n";
216 s << S_TAB2 << "sectionp" << count << " = config.findGroup(\"" << vec.front() << "\");\n";
217 }
218 }
219 //(1)...All other iteration should take data from previous sectionp.
220 else
221 {
222 //The last iteration should put data in sectionp...(2)
223 if (count == siz-1)
224 {
225 s << S_TAB2 << "yarp::os::Bottle sectionp" << ";\n";
226 s << S_TAB2 << "sectionp" << " = " << "sectionp" << count - 1 << ".findGroup(\"" << vec.front() << "\");\n";
227 }
228 //(2)...All other iteration should put data in sectionp<count>
229 else
230 {
231 s << S_TAB2 << "yarp::os::Bottle sectionp" << count << ";\n";
232 s << S_TAB2 << "sectionp" << count << " = " << "sectionp" << count - 1 << ".findGroup(\"" << vec.front() << "\");\n";
233 }
234 }
235
236 vec.pop_front();
237 generate_section(s,vec, count+1, siz);
238}
239
240inline void KK (std::string origin, std::ostringstream& s, const Parameter& param, std::string as, std::string component)
241{
243 s << S_TAB3 << "m_" << param.getFullParamVariable() << " = "<<origin<<".find(\"" << param.getParamOnly() << "\")" << as <<";\n";
244}
245
246inline void AA (std::string origin, std::ostringstream& s, const Parameter& param, std::string typ, std::string component)
247{
249 s << S_TAB3 << "{\n";
250 s << S_TAB3 << " m_" << param.getFullParamVariable() << ".clear();\n";
251 s << S_TAB3 << " yarp::os::Bottle* tempBot = " << origin << ".find(\"" << param.getParamOnly() << "\").asList();\n";
252 s << S_TAB3 << " if (tempBot)\n";
253 s << S_TAB3 << " {\n";
254 s << S_TAB3 << " std::string tempBots = tempBot->toString();\n";
255 s << S_TAB3 << " for (size_t i=0; i<tempBot->size(); i++)\n";
256 s << S_TAB3 << " {\n";
257 s << S_TAB3 << " m_" << param.getFullParamVariable() << ".push_back(tempBot->get(i)" << typ << ");\n";
258 s << S_TAB3 << " }\n";
259 s << S_TAB3 << " }\n";
260 s << S_TAB3 << " else\n";
261 s << S_TAB3 << " {\n";
262 s << S_TAB3 << " yCError(" << component << ") <<" << "\"parameter '" << param.getFullParamVariable() <<"' is not a properly formatted bottle\";\n";
263 s << S_TAB3 << " }\n";
264 s << S_TAB3 << "}\n";
265}
266
267inline void BB (std::string origin, std::ostringstream& s, const Parameter& param, std::string typ, std::string component)
268{
270 s << S_TAB3 << "{\n";
271 s << S_TAB3 << " m_" << param.getFullParamVariable() << ".clear();\n";
272 s << S_TAB3 << " std::string tempString = "<<origin<<".find(\"" << param.getParamOnly() << "\").asString();\n";
273 s << S_TAB3 << " std::istringstream iss(tempString);\n";
274 s << S_TAB3 << " " << typ << " val;\n";
275 s << S_TAB3 << " while (iss >> val)\n";
276 s << S_TAB3 << " {\n";
277 s << S_TAB3 << " m_" << param.getFullParamVariable() << ".push_back(val"<<typ<<"); \n";
278 s << S_TAB3 << " }\n";
279 s << S_TAB3 << "}\n";
280}
281
282inline void CC(std::string origin, std::ostringstream& s, const Parameter& param, std::string typ, std::string component)
283{
285 s << S_TAB3 << "{\n";
286 s << S_TAB3 << " m_" << param.getFullParamVariable() << ".clear();\n";
287 s << S_TAB3 << " yarp::os::Bottle tempBot = " << origin << ".findGroup(\"" << param.getParamOnly() << "\");\n";
288 s << S_TAB3 << " if (tempBot.size()>0)\n";
289 s << S_TAB3 << " {\n";
290 s << S_TAB3 << " int sizes = tempBot.size();\n";
291 s << S_TAB3 << " std::string tempBots = tempBot.toString();\n";
292 s << S_TAB3 << " tempBot = tempBot.tail();\n";
293 s << S_TAB3 << " for (size_t i=0; i<tempBot.size(); i++)\n";
294 s << S_TAB3 << " {\n";
295 s << S_TAB3 << " m_" << param.getFullParamVariable() << ".push_back(tempBot.get(i)" << typ << ");\n";
296 s << S_TAB3 << " }\n";
297 s << S_TAB3 << " }\n";
298 s << S_TAB3 << " else\n";
299 s << S_TAB3 << " {\n";
300 s << S_TAB3 << " yCError("<< component << ") << " << "\"parameter '" << param.getFullParamVariable() << "' is not a properly formatted bottle\";\n";
301 s << S_TAB3 << " }\n";
302 s << S_TAB3 << "}\n";
303}
304
305void ParamsFilesGenerator::generate_param(std::string origin, std::ostringstream& s, const Parameter& param)
306{
308 s << \
309 S_TAB2 << "if ("<<origin<<".check(\"" << param.getParamOnly() << "\"))\n" << \
310 S_TAB2 << "{\n";
311
312
313 if (param.type == "string") { KK(origin, s, param, ".asString()", m_component); }
314 else if (param.type == "bool") { KK(origin, s, param, ".asBool()", m_component); }
315 else if (param.type == "double") { KK(origin, s, param, ".asFloat64()", m_component); }
316 else if (param.type == "int") { KK(origin, s, param, ".asInt64()", m_component); }
317 else if (param.type == "size_t") { KK(origin, s, param, ".asInt64()", m_component); }
318 else if (param.type == "float") { KK(origin, s, param, ".asFloat32()", m_component); }
319 else if (param.type == "char") { KK(origin, s, param, ".asInt8()", m_component); }
320 else if (param.type == "vector<int>") { AA(origin, s, param, ".asInt64()", m_component); }
321 else if (param.type == "vector<string>") { AA(origin, s, param, ".asString()", m_component); }
322 else if (param.type == "vector<double>") { AA(origin, s, param, ".asFloat64()", m_component); }
323// else if (param.type == "vector<int>") { BB(origin, s, param, "int"); }
324// else if (param.type == "vector<string>") { BB(origin, s, param, "std::string"); }
325// else if (param.type == "vector<double>") { BB(origin, s, param, "double"); }
326 else {
327 yFatal("ERROR: Unknown data type for param %s: %s",param.getFullParamName().c_str(), param.type.c_str()); //error
328 }
329
331 s << \
332 S_TAB3 << "yCInfo("<< m_component<< ") << \"Parameter '" << param.getFullParamName() << "' using value:\" << m_" << param.getFullParamVariable() << ";\n";
333
334
336
337 s << \
338 S_TAB2 << "}\n" << \
339 S_TAB2 << "else\n" << \
340 S_TAB2 << "{\n";
341
342 if (param.required)
343 {
345 s << \
346 S_TAB3 << "yCError(" << m_component << ") << \"Mandatory parameter '" << param.getFullParamName() << "' not found!\";\n";
347 if (!param.description.empty())
348 {
349 s << \
350 S_TAB3 << "yCError(" << m_component << ") << \"Description of the parameter: " << param.description << "\";\n";
351 }
352 if (!param.units.empty())
353 {
354 s << \
355 S_TAB3 << "yCError(" << m_component << ") << \"Remember: Units for this parameter are: '" << param.units << "'\";\n";
356 }
357 s << \
358 S_TAB3 << "return false;\n";
359 }
360 else
361 {
363 s << \
364 S_TAB3 << "yCInfo(" << m_component << ") << \"Parameter '" << param.getFullParamName() << "' using DEFAULT value:\" << m_" << param.getFullParamVariable() << ";\n";
365 }
366
367
369 s << \
370 S_TAB2 << "}\n\
371";
372}
373
375{
376 std::ostringstream s;
378s << "\n\
379bool "<< m_classname << "_ParamsParser::parseParams(const yarp::os::Searchable & config)\n\
380{\n";
381
382 s << S_TAB1 << "//Check for --help option\n";
383 s << S_TAB1 << "if (config.check(\"help\"))\n";
384 s << S_TAB1 << "{\n";
385 s << S_TAB1 << " yCInfo(" << m_component << ") << getDocumentationOfDeviceParams();\n";
386 s << S_TAB1 << "}\n";
387 s << "\n";
388
390 s << S_TAB1 << "m_provided_configuration = config.toString();\n";
391 s << S_TAB1 << "yarp::os::Property prop_check(m_provided_configuration.c_str());\n";
392
394 auto copy_of_m_params = m_params;
395 for (const auto& param : copy_of_m_params)
396 {
397 if (param.getListOfGroups().empty())
398 {
399 s << S_TAB1 << "//Parser of parameter " << param.getParamOnly() <<"\n";
400 s << S_TAB1 << "{\n";
401 generate_param("config", s, param);
402 s << S_TAB2 << "prop_check.unput(\"" << param.getParamOnly() << "\");\n";
403 s << S_TAB1 << "}\n";
404 s << "\n";
405 }
406 else
407 {
408 s << S_TAB1 << "//Parser of parameter " << param.getFullParamName() << "\n";
409 s << S_TAB1 << "{\n";
410 auto pg = param.getListOfGroups();
411 generate_section (s,pg,0,pg.size());
412 generate_param("sectionp", s, param);
413 s << S_TAB2 << "prop_check.unput(\"" << param.getFullParamName() << "\");\n";
414 s << S_TAB1 << "}\n";
415 s << "\n";
416 }
417 }
418
420
421 //commented because this code is not ready yet
422 s << S_TAB1 << "/*\n";
423
424 s << S_TAB1 << "//This code check if the user set some parameter which are not check by the parser\n";
425 s << S_TAB1 << "//If the parser is set in strict mode, this will generate an error\n";
426 s << S_TAB1 << "if (prop_check.size() > 0)\n";
427 s << S_TAB1 << "{\n";
428 s << S_TAB1 << " bool extra_params_found = false;\n";
429 s << S_TAB1 << " for (auto it=prop_check.begin(); it!=prop_check.end(); it++)\n";
430 s << S_TAB1 << " {\n";
431 s << S_TAB1 << " if (m_parser_is_strict)\n";
432 s << S_TAB1 << " {\n";
433 s << S_TAB1 << " yCError(" << m_component << ") << \"User asking for parameter: \"<<it->name <<\" which is unknown to this parser!\";\n";
434 s << S_TAB1 << " extra_params_found = true;\n";
435 s << S_TAB1 << " }\n";
436 s << S_TAB1 << " else\n";
437 s << S_TAB1 << " {\n";
438 s << S_TAB1 << " yCWarning(" << m_component << ") << \"User asking for parameter: \"<< it->name <<\" which is unknown to this parser!\";\n";
439 s << S_TAB1 << " }\n";
440 s << S_TAB1 << " }\n";
441 s << "\n";
442 s << S_TAB1 << " if (m_parser_is_strict && extra_params_found)\n";
443 s << S_TAB1 << " {\n";
444 s << S_TAB1 << " return false;\n";
445 s << S_TAB1 << " }\n";
446 s << S_TAB1 << "}\n";
447
448 //commented because this code is not ready yet
449 s << S_TAB1 << "*/\n";
450
451s <<\
452S_TAB1 << "return true;\n\
453}\n\
454\n\
455";
456
457 return s.str();
458}
#define yFatal(...)
Definition Log.h:382
std::string getParamOnly() const
Definition parameter.cpp:89
std::string units
Definition parameter.h:28
std::string getFullParamName() const
Definition parameter.cpp:53
std::string type
Definition parameter.h:27
bool required
Definition parameter.h:30
std::string description
Definition parameter.h:31
std::string getFullParamVariable() const
Definition parameter.cpp:76
std::string m_component
Definition generator.h:40
std::string generateFunction_getDocumentationOfDeviceParams()
std::string m_classname
Definition generator.h:38
std::string generateFunction_getParamValue()
std::string generateYarpdevStringAllParams()
void generate_param(std::string origin, std::ostringstream &s, const Parameter &param)
std::string generateFunction_getListOfParams()
std::string generateFunction_getConfiguration()
std::deque< Parameter > m_params
Definition generator.h:34
void generate_section(std::ostringstream &s, std::deque< std::string > vec, size_t count, size_t siz)
std::string generateYarpdevStringMandatoryParamsOnly()
void CC(std::string origin, std::ostringstream &s, const Parameter &param, std::string typ, std::string component)
void AA(std::string origin, std::ostringstream &s, const Parameter &param, std::string typ, std::string component)
void KK(std::string origin, std::ostringstream &s, const Parameter &param, std::string as, std::string component)
void BB(std::string origin, std::ostringstream &s, const Parameter &param, std::string typ, std::string component)
#define ADD_DEBUG_COMMENT(out)
Definition generator.h:21
#define S_TAB1
Definition generator.h:22
#define S_TAB2
Definition generator.h:23
#define S_TAB3
Definition generator.h:24