Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • sw/armarx/robot-api
  • uwkce_singer/robot-api
  • untcg_hofmann/robot-api
  • ulqba_korosakov/RobotAPI
4 results
Show changes
Commits on Source (2)
......@@ -177,33 +177,60 @@ int main(int argc, char* argv[])
}
}
auto w = CppWriterPtr(new CppWriter());
// Generate enums at top of generated header file
std::vector<MetaEnumPtr> enums = writer.getTypeEnums();
if (verbose)
{
std::cout << "Now exporting enums..." << std::endl;
}
MetaEnum::Write(enums, w);
std::string enum_file_generation_content = w->getString();
if (verbose)
{
std::cout << "Now exporting enums... done!" << std::endl;
}
if (enums.size() > 0 && enum_file_generation_content == "")
{
std::cerr << "\033[31m" << "Error code 11 - Found error in code generation. Aborting!" << "\033[0m" << std::endl;
exit(1);
}
// Generate all classes
std::vector<MetaClassPtr> classes = writer.getTypeClasses();
if (verbose)
{
std::cout << "Now exporting classes..." << std::endl;
}
auto w = CppWriterPtr(new CppWriter());
CppClass::Write(classes, w);
std::string new_file_content = w->getString();
std::string class_file_generation_content = simox::alg::remove_prefix(w->getString(), enum_file_generation_content);
if (verbose)
{
std::cout << "Now exporting classes... done!" << std::endl;
}
if (new_file_content == "")
if (classes.size() > 0 && class_file_generation_content == "")
{
std::cerr << "Found error in code generation. Aborting!" << std::endl;
std::cerr << "\033[31m" << "Error code 21 - Found error in code generation. Aborting!" << "\033[0m" << std::endl;
exit(1);
}
std::time_t current_time = std::time(0);
std::tm* now = std::localtime(&current_time);
std::string current_year = std::to_string(now->tm_year + 1900);
std::string new_file_header = "\
/* \n\
* This file is part of ArmarX. \n\
* \n\
* Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T), \n\
* Copyright (C) 2012-" + current_year + ", High Performance Humanoid Technologies (H2T), \n\
* Karlsruhe Institute of Technology (KIT), all rights reserved. \n\
* \n\
* ArmarX is free software; you can redistribute it and/or modify \n\
......@@ -228,7 +255,7 @@ int main(int argc, char* argv[])
************************************************************************* \n\
*/\n\n\n";
std::string new_file_full_content = new_file_header + new_file_content;
std::string new_file_full_content = new_file_header + w->getString();
std::string new_name_with_extension = input_file.filename().replace_extension("").string();
new_name_with_extension += ".aron.generated.h";
......@@ -247,7 +274,7 @@ int main(int argc, char* argv[])
{
if (verbose)
{
std::cout << "File content not changed for <" + output_file.string() + ">" << std::endl;
std::cout << "\033[31m" << "Error code 31 - File content not changed for <" + output_file.string() + ">" << "\033[0m" << std::endl;
}
exit(0);
}
......@@ -261,12 +288,12 @@ int main(int argc, char* argv[])
if (verbose)
{
std::cout << "Finished generating <" + output_file.string() + ">. The new file ist called <" << output_file.string() << ">" << std::endl;
std::cout << "\033[32m" << "Finished generating <" + output_file.string() + ">. The new file ist called <" << output_file.string() << ">" << "\033[0m" << std::endl;
}
}
catch (const cxxopts::OptionException& e)
{
std::cerr << "Error in parsing cxxopts options: " << e.what() << std::endl;
std::cerr << "\033[31m" << "Error code 01 - Error in parsing cxxopts options: " << e.what() << "\033[0m" << std::endl;
exit(1);
}
exit(0);
......
......@@ -31,7 +31,8 @@
#include <typeindex>
// ArmarX
#include <ArmarXCore/libraries/cppgen/MetaClass.h>
#include <ArmarXCore/libraries/cppgen/CppEnum.h>
#include <ArmarXCore/libraries/cppgen/CppClass.h>
#include <RobotAPI/libraries/aron/core/type/variant/All.h>
......@@ -61,12 +62,18 @@ namespace armarx::aron::codegenerator
return typeClasses;
}
std::vector<MetaEnumPtr> getTypeEnums() const // TODO: Create Meta Enum class to abstract away cpp details
{
return typeEnums;
}
protected:
virtual void addSpecificReaderMethods() = 0;
virtual void addSpecificWriterMethods() = 0;
protected:
std::vector<MetaClassPtr> typeClasses;
std::vector<MetaEnumPtr> typeEnums;
std::string producerName;
std::vector<codegenerator::WriterInfo> dataWriters;
......
......@@ -32,6 +32,45 @@
namespace armarx::aron::codegenerator::cpp
{
// Function to convert camel case
// string to snake case string
std::string camelToSnake(const std::string& str)
{
// Empty String
std::string result = "";
// Append first character(in lower case)
// to result string
char c = std::tolower(str[0]);
result+=(char(c));
// Traverse the string from
// ist index to last index
for (unsigned int i = 1; i < str.length(); i++) {
char ch = str[i];
// Check if the character is upper case
// then append '_' and such character
// (in lower case) to result string
if (std::isupper(ch)) {
result = result + '_';
result+=char(std::tolower(ch));
}
// If the character is lower case then
// add such character into result string
else {
result = result + ch;
}
}
// return the result
return result;
}
Writer::Writer(const std::string& producerName, const std::vector<std::string>& additionalIncludesFromXMLFile) :
CodeWriter(producerName, additionalIncludesFromXMLFile)
{
......@@ -247,17 +286,19 @@ namespace armarx::aron::codegenerator::cpp
ARMARX_CHECK_NOT_NULL(nav);
generator::IntEnumClass generator(*nav);
// Create enum class and add to enums
CppEnumPtr enumrepresentation = setupEnumPtr(publicGenerateIntEnumType, generator);
typeEnums.push_back(enumrepresentation);
// Generate aron wrapper class and add to classes
CppClassPtr c = setupBasicCppClass(publicGenerateIntEnumType, generator);
setupMemberFields(c, publicGenerateIntEnumType.doc_values, generator);
c->addInherit("public armarx::aron::cpp::AronGeneratedClass");
// ctor
c->addCtor(generator.toInnerEnumCtor(c->getName()));
// Specific methods
CppEnumPtr enumrepresentation = generator.toInnerEnumDefinition();
c->addInnerEnum(enumrepresentation);
c->addCtor(generator.toEnumCtor(c->getName()));
CppMethodPtr toString = generator.toToStringMethod();
c->addMethod(toString);
......@@ -346,6 +387,33 @@ namespace armarx::aron::codegenerator::cpp
}
}
CppEnumPtr Writer::setupEnumPtr(const typereader::GenerateInfo& info, const generator::IntEnumClass& gen) const
{
const auto& type = gen.getType();
if (type.getMaybe() != type::Maybe::NONE)
{
// Should not happen since we check the maybe flag on creation of the generator. However, better to double check
throw error::ValueNotValidException(__PRETTY_FUNCTION__, "Somehow the maybe flag of a top level object declaration is set. This is not valid!", std::to_string((int) type.getMaybe()) + " aka " + type::defaultconversion::string::Maybe2String.at(type.getMaybe()), type.getPath());
}
const std::string classCppTypename = gen.getClassCppTypename();
std::vector<std::string> namespaces = info.getNamespaces();
std::string rawObjectName = info.getNameWithoutNamespace();
namespaces.push_back(simox::alg::to_lower(camelToSnake(rawObjectName)) + "_details");
std::string enumdoc = "The enum definition of the enum of the auogenerated class '" + gen.getFullClassCppTypename() + "'.";
CppEnumPtr e = std::make_shared<CppEnum>(namespaces, "Enum");
auto enumFields = gen.toEnumFields();
for (const auto& field : enumFields)
{
e->addField(field);
}
return e;
}
CppClassPtr Writer::setupBasicCppClass(const typereader::GenerateInfo& info, const Generator& gen) const
{
const auto& type = gen.getType();
......@@ -393,7 +461,7 @@ namespace armarx::aron::codegenerator::cpp
}
}
// add aron includes
// always add aron includes
c->addInclude("<RobotAPI/libraries/aron/core/aron_conversions.h>");
c->addInclude("<RobotAPI/libraries/aron/core/rw.h>");
c->addInclude("<RobotAPI/libraries/aron/core/codegeneration/cpp/AronGeneratedClass.h>");
......@@ -434,7 +502,7 @@ namespace armarx::aron::codegenerator::cpp
void Writer::setupMemberFields(CppClassPtr& c, const std::map<std::string, std::string>& doc_members, const generator::ObjectClass& o) const
{
auto publicFields = o.getPublicVariableDeclarations("");
auto publicFields = o.getPublicVariableDeclarations(c->getName());
for (const auto& f : publicFields)
{
if (auto it = doc_members.find(f->getName()); it != doc_members.end())
......@@ -447,7 +515,7 @@ namespace armarx::aron::codegenerator::cpp
void Writer::setupMemberFields(CppClassPtr& c, const std::map<std::string, std::string>& doc_members, const generator::IntEnumClass& o) const
{
auto publicFields = o.getPublicVariableDeclarations("");
auto publicFields = o.getPublicVariableDeclarations(camelToSnake(c->getName()));
for (const auto& f : publicFields)
{
if (auto it = doc_members.find(f->getName()); it != doc_members.end())
......
......@@ -59,6 +59,8 @@ namespace armarx::aron::codegenerator::cpp
virtual void addSpecificReaderMethods() override;
CppClassPtr setupBasicCppClass(const typereader::GenerateInfo& info, const Generator& gen) const;
CppEnumPtr setupEnumPtr(const typereader::GenerateInfo& info, const generator::IntEnumClass& gen) const;
void setupMemberFields(CppClassPtr&, const std::map<std::string, std::string>& doc_members, const generator::ObjectClass&) const;
void setupMemberFields(CppClassPtr&, const std::map<std::string, std::string>& doc_members, const generator::IntEnumClass&) const;
......
......@@ -44,7 +44,7 @@ namespace armarx::aron::codegenerator::cpp::generator
}
}
std::vector<CppFieldPtr> IntEnumClass::getPublicVariableDeclarations(const std::string&) const
std::vector<CppFieldPtr> IntEnumClass::getPublicVariableDeclarations(const std::string& className) const
{
std::vector<CppFieldPtr> fields;
std::stringstream enum_to_name;
......@@ -52,6 +52,9 @@ namespace armarx::aron::codegenerator::cpp::generator
std::stringstream enum_to_value;
std::stringstream value_to_enum;
// add legacy typedef
fields.push_back(std::make_shared<CppField>("using", std::string(IMPL_ENUM), simox::alg::to_lower(className) + "_details::Enum", "Legacy typedef of enum"));
enum_to_name << "{" << std::endl;
name_to_enum << "{" << std::endl;
enum_to_value << "{" << std::endl;
......@@ -164,7 +167,7 @@ namespace armarx::aron::codegenerator::cpp::generator
return {{{"value", ARON_OTHER_ACCESSOR + ".value"}}, false};
}
CppCtorPtr IntEnumClass::toInnerEnumCtor(const std::string& name) const
CppCtorPtr IntEnumClass::toEnumCtor(const std::string& name) const
{
CppCtorPtr c = std::make_shared<CppCtor>(name + "(const " + std::string(IMPL_ENUM) + " e)");
std::vector<std::pair<std::string, std::string>> initList = {{"value", "e"}};
......@@ -173,12 +176,12 @@ namespace armarx::aron::codegenerator::cpp::generator
return c;
}
CppEnumPtr IntEnumClass::toInnerEnumDefinition() const
std::vector<CppEnumFieldPtr> IntEnumClass::toEnumFields() const
{
CppEnumPtr e = std::make_shared<CppEnum>(std::string(IMPL_ENUM), "The internal enum definition of the enum of this autogenerated class.");
std::vector<CppEnumFieldPtr> e;
for (const auto& [key, value] : type.getAcceptedValueMap())
{
e->addField(std::make_shared<CppEnumField>(key));
e.push_back(std::make_shared<CppEnumField>(key));
}
return e;
}
......
......@@ -54,8 +54,8 @@ namespace armarx::aron::codegenerator::cpp::generator
// TODO: Move some of those methods to upper class for enums (if we want to support multiple enums)
//CppCtorPtr toCopyCtor(const std::string&) const;
CppCtorPtr toInnerEnumCtor(const std::string&) const;
CppEnumPtr toInnerEnumDefinition() const;
std::vector<CppEnumFieldPtr> toEnumFields() const;
CppCtorPtr toEnumCtor(const std::string&) const;
CppMethodPtr toIntMethod() const;
CppMethodPtr toCopyAssignmentMethod() const;
CppMethodPtr toEnumAssignmentMethod() const;
......