1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2025-02-20 10:54:14 +01:00

LP-599 Make cloned fields as typedef's of parent types in flight & ground (c, c++) uavobjgenerators.

This commit is contained in:
Vladimir Zidar 2018-02-15 21:50:02 +01:00
parent 9e9c9c8975
commit 8dbf25edc2
4 changed files with 198 additions and 113 deletions

View File

@ -40,6 +40,7 @@
#ifndef $(NAMEUC)_H
#define $(NAMEUC)_H
#include <stdbool.h>
$(INCLUDE)
/* Object constants */
#define $(NAMEUC)_OBJID $(OBJIDHEX)
#define $(NAMEUC)_ISSINGLEINST $(ISSINGLEINST)

View File

@ -35,6 +35,7 @@
#define $(NAMEUC)_H
#include "uavdataobject.h"
$(INCLUDE)
class UAVObjectManager;

View File

@ -24,6 +24,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <QSet>
#include "uavobjectgeneratorflight.h"
using namespace std;
@ -169,52 +170,91 @@ bool UAVObjectGeneratorFlight::process_object(ObjectInfo *info)
enums.append(QString("/* Field %1 information */\n").arg(info->fields[n]->name));
// Only for enum types
if (info->fields[n]->type == FIELDTYPE_ENUM) {
enums.append(QString("\n// Enumeration options for field %1\n").arg(info->fields[n]->name));
enums.append("typedef enum __attribute__ ((__packed__)) {\n");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString s = (m == (options.length() - 1)) ? " %1_%2_%3=%4\n" : " %1_%2_%3=%4,\n";
enums.append(s
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""))
.arg(m));
if (info->fields[n]->parentObjectName.length() > 0) {
enums.append(QString("typedef %1%2Options %3%4Options;\n")
.arg(info->fields[n]->parentObjectName)
.arg(info->fields[n]->parentFieldName)
.arg(info->name)
.arg(info->fields[n]->name));
} else {
enums.append(QString("\n// Enumeration options for field %1\n").arg(info->fields[n]->name));
enums.append("typedef enum __attribute__ ((__packed__)) {\n");
// Go through each option
QStringList options = info->fields[n]->options;
for (int m = 0; m < options.length(); ++m) {
QString s = (m == (options.length() - 1)) ? " %1_%2_%3=%4\n" : " %1_%2_%3=%4,\n";
enums.append(s
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""))
.arg(m));
}
enums.append(QString("} %1%2Options;\n")
.arg(info->name)
.arg(info->fields[n]->name));
}
enums.append(QString("} %1%2Options;\n")
.arg(info->name)
.arg(info->fields[n]->name));
}
// Generate element names (only if field has more than one element)
if (info->fields[n]->numElements > 1 && !info->fields[n]->defaultElementNames) {
enums.append(QString("\n// Array element names for field %1\n").arg(info->fields[n]->name));
enums.append("typedef enum {\n");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m) {
QString s = (m != (elemNames.length() - 1)) ? " %1_%2_%3=%4,\n" : " %1_%2_%3=%4\n";
enums.append(s
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(elemNames[m].toUpper())
.arg(m));
if (info->fields[n]->parentObjectName.length() > 0) {
enums.append(QString("typedef %1%2Elem %3%4Elem;\n")
.arg(info->fields[n]->parentObjectName)
.arg(info->fields[n]->parentFieldName)
.arg(info->name)
.arg(info->fields[n]->name));
} else {
enums.append(QString("\n// Array element names for field %1\n").arg(info->fields[n]->name));
enums.append("typedef enum {\n");
// Go through the element names
QStringList elemNames = info->fields[n]->elementNames;
for (int m = 0; m < elemNames.length(); ++m) {
QString s = (m != (elemNames.length() - 1)) ? " %1_%2_%3=%4,\n" : " %1_%2_%3=%4\n";
enums.append(s
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(elemNames[m].toUpper())
.arg(m));
}
enums.append(QString("} %1%2Elem;\n")
.arg(info->name)
.arg(info->fields[n]->name));
}
enums.append(QString("} %1%2Elem;\n")
.arg(info->name)
.arg(info->fields[n]->name));
}
// Generate array information
if (info->fields[n]->numElements > 1) {
enums.append(QString("\n// Number of elements for field %1\n").arg(info->fields[n]->name));
enums.append(QString("#define %1_%2_NUMELEM %3\n")
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(info->fields[n]->numElements));
if (info->fields[n]->parentObjectName.length() > 0) {
enums.append(QString("#define %1_%2_NUMELEM %3_%4_NUMELEM\n")
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(info->fields[n]->parentObjectName.toUpper())
.arg(info->fields[n]->parentFieldName.toUpper()));
} else {
enums.append(QString("#define %1_%2_NUMELEM %3\n")
.arg(info->name.toUpper())
.arg(info->fields[n]->name.toUpper())
.arg(info->fields[n]->numElements));
}
}
enums.append(QString("\n"));
}
QString includes;
QSet<QString> parentObjects;
for (int n = 0; n < info->fields.length(); ++n) {
if (info->fields[n]->parentObjectName.length() > 0) {
parentObjects.insert(info->fields[n]->parentObjectName);
}
}
foreach(const QString &objectName, parentObjects) {
includes.append("#include \"" + objectName.toLower() + ".h\"\n");
}
outInclude.replace(QString("$(DATAFIELDINFO)"), enums);
outInclude.replace(QString("$(INCLUDE)"), includes);
// Replace the $(INITFIELDS) tag
QString initfields;

View File

@ -24,7 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <QSet>
#include "uavobjectgeneratorgcs.h"
#define VERBOSE false
@ -52,27 +52,32 @@ void info(ObjectInfo *object, QString msg)
}
struct Context {
ObjectInfo *object;
ObjectInfo *object;
// parent objects
QSet<QString> parentObjects;
// enums
QString enums;
QString enumsCount;
QString registerImpl;
QString enums;
QString enumsCount;
QString registerImpl;
// interface
QString fields;
QString fieldsInfo;
QString properties;
QString deprecatedProperties;
QString getters;
QString setters;
QString notifications;
QString fields;
QString fieldsInfo;
QString properties;
QString deprecatedProperties;
QString getters;
QString setters;
QString notifications;
// implementation
QString fieldsInit;
QString fieldsDefault;
QString propertiesImpl;
QString notificationsImpl;
QString fieldsInit;
QString fieldsDefault;
QString propertiesImpl;
QString notificationsImpl;
};
struct FieldContext {
FieldContext(FieldInfo *fieldInfo, ObjectInfo *object);
FieldContext(const FieldContext &fieldContext);
FieldInfo *field;
// field
QString fieldName;
@ -82,6 +87,10 @@ struct FieldContext {
QString ucPropName;
QString propType;
QString propRefType;
//
QString parentClassName;
QString parentFieldName;
QString ucParentPropName;
// deprecation
bool hasDeprecatedProperty;
bool hasDeprecatedGetter;
@ -226,6 +235,10 @@ QString generate(Context &ctxt, FieldContext &fieldCtxt, const QString &fragment
str.replace(":elementCount", QString::number(fieldCtxt.field->numElements));
str.replace(":enumCount", QString::number(fieldCtxt.field->numOptions));
str.replace(":parentFieldName", fieldCtxt.parentFieldName);
str.replace(":parentClassName", fieldCtxt.parentClassName);
str.replace(":ParentPropName", fieldCtxt.ucParentPropName);
return str;
}
@ -234,34 +247,42 @@ void generateFieldInfo(Context &ctxt, FieldContext &fieldCtxt)
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " // :fieldName\n");
if (fieldCtxt.field->type == FIELDTYPE_ENUM) {
QStringList options = fieldCtxt.field->options;
ctxt.fieldsInfo += " typedef enum { ";
for (int m = 0; m < options.length(); ++m) {
if (m > 0) {
ctxt.fieldsInfo.append(", ");
if (fieldCtxt.field->parentObjectName.length() > 0) {
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " typedef :parentClassName:::parentFieldNameOptions :fieldNameOptions;\n");
} else {
QStringList options = fieldCtxt.field->options;
ctxt.fieldsInfo += " typedef enum { ";
for (int m = 0; m < options.length(); ++m) {
if (m > 0) {
ctxt.fieldsInfo.append(", ");
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, "%1_%2=%3")
.arg(fieldCtxt.field->name.toUpper())
.arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""))
.arg(m);
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, "%1_%2=%3")
.arg(fieldCtxt.field->name.toUpper())
.arg(options[m].toUpper().replace(QRegExp(ENUM_SPECIAL_CHARS), ""))
.arg(m);
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameOptions;\n");
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameOptions;\n");
}
// Generate element names (only if field has more than one element)
if (fieldCtxt.field->numElements > 1 && !fieldCtxt.field->defaultElementNames) {
QStringList elemNames = fieldCtxt.field->elementNames;
ctxt.fieldsInfo += " typedef enum { ";
for (int m = 0; m < elemNames.length(); ++m) {
if (m > 0) {
ctxt.fieldsInfo.append(", ");
if (fieldCtxt.field->parentObjectName.length() > 0) {
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " typedef :parentClassName:::parentFieldNameElem :fieldNameElem;\n");
} else {
QStringList elemNames = fieldCtxt.field->elementNames;
ctxt.fieldsInfo += " typedef enum { ";
for (int m = 0; m < elemNames.length(); ++m) {
if (m > 0) {
ctxt.fieldsInfo.append(", ");
}
ctxt.fieldsInfo += QString("%1_%2=%3")
.arg(fieldCtxt.field->name.toUpper())
.arg(elemNames[m].toUpper())
.arg(m);
}
ctxt.fieldsInfo += QString("%1_%2=%3")
.arg(fieldCtxt.field->name.toUpper())
.arg(elemNames[m].toUpper())
.arg(m);
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameElem;\n");
}
ctxt.fieldsInfo += generate(ctxt, fieldCtxt, " } :fieldNameElem;\n");
}
// Generate array information
@ -341,6 +362,9 @@ void generateFieldDefault(Context &ctxt, FieldContext &fieldCtxt)
void generateField(Context &ctxt, FieldContext &fieldCtxt)
{
if (fieldCtxt.parentClassName.length() > 0) {
ctxt.parentObjects.insert(fieldCtxt.parentClassName);
}
if (fieldCtxt.field->numElements > 1) {
ctxt.fields += generate(ctxt, fieldCtxt, " :fieldType :fieldName[:elementCount];\n");
} else {
@ -355,20 +379,24 @@ void generateEnum(Context &ctxt, FieldContext &fieldCtxt)
{
Q_ASSERT(fieldCtxt.field->type == FIELDTYPE_ENUM);
QString enumStringList = toEnumStringList(ctxt.object, fieldCtxt.field);
if (fieldCtxt.field->parentObjectName.length() > 0) {
ctxt.enums += generate(ctxt, fieldCtxt, "typedef :parentClassName_:ParentPropName :ClassName_:PropName;\n\n");
} else {
QString enumStringList = toEnumStringList(ctxt.object, fieldCtxt.field);
ctxt.enums += generate(ctxt, fieldCtxt,
"class :ClassName_:PropName : public QObject {\n"
" Q_OBJECT\n"
"public:\n"
" enum Enum { %1 };\n"
" Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5\n"
"};\n\n").arg(enumStringList);
ctxt.enums += generate(ctxt, fieldCtxt,
"class :ClassName_:PropName : public QObject {\n"
" Q_OBJECT\n"
"public:\n"
" enum Enum { %1 };\n"
" Q_ENUMS(Enum) // TODO switch to Q_ENUM once on Qt 5.5\n"
"};\n\n").arg(enumStringList);
ctxt.enumsCount += generate(ctxt, fieldCtxt, ":PropNameCount = :enumCount, ");
ctxt.enumsCount += generate(ctxt, fieldCtxt, ":PropNameCount = :enumCount, ");
ctxt.registerImpl += generate(ctxt, fieldCtxt,
" qmlRegisterType<:ClassName_:PropName>(\"%1.:ClassName\", 1, 0, \":PropName\");\n").arg("UAVTalk");
ctxt.registerImpl += generate(ctxt, fieldCtxt,
" qmlRegisterType<:ClassName_:PropName>(\"%1.:ClassName\", 1, 0, \":PropName\");\n").arg("UAVTalk");
}
}
void generateBaseProperty(Context &ctxt, FieldContext &fieldCtxt)
@ -507,14 +535,10 @@ void generateIndexedProperty(Context &ctxt, FieldContext &fieldCtxt)
sep = "_";
}
FieldContext elementCtxt;
elementCtxt.field = fieldCtxt.field;
elementCtxt.fieldName = fieldCtxt.fieldName + "_" + elementName;
elementCtxt.fieldType = fieldCtxt.fieldType;
elementCtxt.propName = fieldCtxt.propName + sep + elementName;
elementCtxt.ucPropName = fieldCtxt.ucPropName + sep + elementName;
elementCtxt.propType = fieldCtxt.propType;
elementCtxt.propRefType = fieldCtxt.propRefType;
FieldContext elementCtxt(fieldCtxt);
elementCtxt.fieldName = fieldCtxt.fieldName + "_" + elementName;
elementCtxt.propName = fieldCtxt.propName + sep + elementName;
elementCtxt.ucPropName = fieldCtxt.ucPropName + sep + elementName;
// deprecation
elementCtxt.hasDeprecatedProperty = (elementCtxt.fieldName != elementCtxt.propName) && DEPRECATED;
elementCtxt.hasDeprecatedGetter = DEPRECATED;
@ -593,6 +617,44 @@ bool UAVObjectGeneratorGCS::generate(UAVObjectParser *parser, QString templatepa
return true;
}
FieldContext::FieldContext(const FieldContext &fieldContext)
{
*this = fieldContext;
}
FieldContext::FieldContext(FieldInfo *fieldInfo, ObjectInfo *object)
{
field = fieldInfo;
// field properties
fieldName = field->name;
fieldType = fieldTypeStrCPP(field->type);
parentClassName = field->parentObjectName;
parentFieldName = field->parentFieldName;
ucParentPropName = toPropertyName(field->parentFieldName);
ucPropName = toPropertyName(field->name);
propName = toLowerCamelCase(ucPropName);
propType = fieldType;
if (field->type == FIELDTYPE_INT8) {
propType = fieldTypeStrCPP(FIELDTYPE_INT16);
} else if (field->type == FIELDTYPE_UINT8) {
propType = fieldTypeStrCPP(FIELDTYPE_UINT16);
} else if (field->type == FIELDTYPE_ENUM) {
QString enumClassName = object->name + "_" + ucPropName;
propType = enumClassName + "::Enum";
}
// reference type
propRefType = propType;
// deprecation
hasDeprecatedProperty = (fieldName != propName) && DEPRECATED;
hasDeprecatedGetter = DEPRECATED;
hasDeprecatedSetter = ((fieldName != ucPropName) || (fieldType != propType)) && DEPRECATED;
hasDeprecatedNotification = ((fieldName != propName) || (fieldType != propType)) && DEPRECATED;
}
/**
* Generate the GCS object files
*
@ -634,32 +696,7 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *object)
FieldInfo *field = object->fields[n];
// field context
FieldContext fieldCtxt;
fieldCtxt.field = field;
// field properties
fieldCtxt.fieldName = field->name;
fieldCtxt.fieldType = fieldTypeStrCPP(field->type);
fieldCtxt.ucPropName = toPropertyName(field->name);
fieldCtxt.propName = toLowerCamelCase(fieldCtxt.ucPropName);
fieldCtxt.propType = fieldCtxt.fieldType;
if (field->type == FIELDTYPE_INT8) {
fieldCtxt.propType = fieldTypeStrCPP(FIELDTYPE_INT16);
} else if (field->type == FIELDTYPE_UINT8) {
fieldCtxt.propType = fieldTypeStrCPP(FIELDTYPE_UINT16);
} else if (field->type == FIELDTYPE_ENUM) {
QString enumClassName = object->name + "_" + fieldCtxt.ucPropName;
fieldCtxt.propType = enumClassName + "::Enum";
}
// reference type
fieldCtxt.propRefType = fieldCtxt.propType;
// deprecation
fieldCtxt.hasDeprecatedProperty = (fieldCtxt.fieldName != fieldCtxt.propName) && DEPRECATED;
fieldCtxt.hasDeprecatedGetter = DEPRECATED;
fieldCtxt.hasDeprecatedSetter = ((fieldCtxt.fieldName != fieldCtxt.ucPropName) || (fieldCtxt.fieldType != fieldCtxt.propType)) && DEPRECATED;
fieldCtxt.hasDeprecatedNotification = ((fieldCtxt.fieldName != fieldCtxt.propName) || (fieldCtxt.fieldType != fieldCtxt.propType)) && DEPRECATED;
FieldContext fieldCtxt(field, object);
generateField(ctxt, fieldCtxt);
@ -671,6 +708,12 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *object)
generateProperty(ctxt, fieldCtxt);
}
QString includes;
foreach(const QString &objectName, ctxt.parentObjects) {
includes.append("#include \"" + objectName.toLower() + ".h\"\n");
}
outInclude.replace("$(INCLUDE)", includes);
outInclude.replace("$(ENUMS)", ctxt.enums);
outInclude.replace("$(ENUMS_COUNT)", ctxt.enumsCount);
outInclude.replace("$(DATAFIELDS)", ctxt.fields);