Add 3d table support to the java config file parser. (#3464)

This removes the need to use custom for 3d tables.  Syntax (to avoid changing the ANTLR parser) is
to use 'x' instead of separate [], i.e.:
        uint16_t[HPFP_TARGET_SIZE x HPFP_TARGET_SIZE] hpfpTarget;;"kPa", 1, 0, 0, 65000, 0
This commit is contained in:
Scott Smith 2021-11-05 11:27:32 -07:00 committed by GitHub
parent 8c96be4482
commit 8e5d65978a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 89 additions and 48 deletions

View File

@ -1991,6 +1991,3 @@ end_struct
! we need to improve this further - at the moment we need too many boards to prepend 'false' ! we need to improve this further - at the moment we need too many boards to prepend 'false'
#define show_test_presets true #define show_test_presets true
#define show_Frankenso_presets true #define show_Frankenso_presets true
! poke

Binary file not shown.

View File

@ -14,9 +14,10 @@ import java.util.regex.Pattern;
* 1/15/15 * 1/15/15
*/ */
public class ConfigField { public class ConfigField {
public static final ConfigField VOID = new ConfigField(null, "", null, null, null, 1, null, false, false, null,null, -1, null, null); public static final ConfigField VOID = new ConfigField(null, "", null, null, null, new int[0], null, false, false, null,null, -1, null, null);
private static final String typePattern = "([\\w\\d_]+)(\\[([\\w\\d]+)(\\sx\\s([\\w\\d]+))?(\\s([\\w\\d]+))?\\])?";
private static final String typePattern = "([\\w\\d_]+)(\\[([\\w\\d]+)(\\s([\\w\\d]+))?\\])?";
private static final String namePattern = "[[\\w\\d\\s<>_]]+"; private static final String namePattern = "[[\\w\\d\\s<>_]]+";
private static final String commentPattern = ";([^;]*)"; private static final String commentPattern = ";([^;]*)";
@ -35,7 +36,7 @@ public class ConfigField {
private final String comment; private final String comment;
public final String arraySizeVariableName; public final String arraySizeVariableName;
private final String type; private final String type;
private final int arraySize; private final int[] arraySizes;
private final String tsInfo; private final String tsInfo;
private final boolean isIterate; private final boolean isIterate;
@ -55,7 +56,7 @@ public class ConfigField {
String comment, String comment,
String arraySizeAsText, String arraySizeAsText,
String type, String type,
int arraySize, int[] arraySizes,
String tsInfo, String tsInfo,
boolean isIterate, boolean isIterate,
boolean fsioVisible, boolean fsioVisible,
@ -81,13 +82,13 @@ public class ConfigField {
Objects.requireNonNull(type); Objects.requireNonNull(type);
this.type = type; this.type = type;
this.arraySizeVariableName = arraySizeAsText; this.arraySizeVariableName = arraySizeAsText;
this.arraySize = arraySize; this.arraySizes = arraySizes;
this.tsInfo = tsInfo == null ? null : state.variableRegistry.applyVariables(tsInfo); this.tsInfo = tsInfo == null ? null : state.variableRegistry.applyVariables(tsInfo);
this.isIterate = isIterate; this.isIterate = isIterate;
} }
public boolean isArray() { public boolean isArray() {
return arraySizeVariableName != null || arraySize != 1; return arraySizeVariableName != null || arraySizes.length != 0;
} }
public String getTrueName() { public String getTrueName() {
@ -136,7 +137,7 @@ public class ConfigField {
if (!matcher.matches()) if (!matcher.matches())
return null; return null;
String nameString = matcher.group(6).trim(); String nameString = matcher.group(8).trim();
String[] nameTokens = nameString.split("\\s"); String[] nameTokens = nameString.split("\\s");
String name = nameTokens[nameTokens.length - 1]; String name = nameTokens[nameTokens.length - 1];
@ -152,23 +153,29 @@ public class ConfigField {
break; break;
} }
String comment = matcher.group(8); String comment = matcher.group(10);
String type = matcher.group(1); String type = matcher.group(1);
int arraySize; int[] arraySizes;
String arraySizeAsText; String arraySizeAsText;
if (matcher.group(3) != null) { if (matcher.group(5) != null) {
arraySizeAsText = matcher.group(3) + "][" + matcher.group(5);
arraySizes = new int[2];
arraySizes[0] = ConfigDefinition.getSize(state.variableRegistry, matcher.group(3));
arraySizes[1] = ConfigDefinition.getSize(state.variableRegistry, matcher.group(5));
} else if (matcher.group(3) != null) {
arraySizeAsText = matcher.group(3); arraySizeAsText = matcher.group(3);
arraySize = ConfigDefinition.getSize(state.variableRegistry, arraySizeAsText); arraySizes = new int[1];
arraySizes[0] = ConfigDefinition.getSize(state.variableRegistry, arraySizeAsText);
} else { } else {
arraySize = 1; arraySizes = new int[0];
arraySizeAsText = null; arraySizeAsText = null;
} }
String tsInfo = matcher.group(10); String tsInfo = matcher.group(12);
boolean isIterate = "iterate".equalsIgnoreCase(matcher.group(5)); boolean isIterate = "iterate".equalsIgnoreCase(matcher.group(7));
ConfigField field = new ConfigField(state, name, comment, arraySizeAsText, type, arraySize, ConfigField field = new ConfigField(state, name, comment, arraySizeAsText, type, arraySizes,
tsInfo, isIterate, isFsioVisible, autoscaleSpec, null, -1, null, null); tsInfo, isIterate, isFsioVisible, autoscaleSpec, null, -1, null, null);
SystemOut.println("type " + type); SystemOut.println("type " + type);
SystemOut.println("name " + name); SystemOut.println("name " + name);
@ -187,7 +194,11 @@ public class ConfigField {
return 0; return 0;
if (isBit()) if (isBit())
return 4; return 4;
return getElementSize() * arraySize; int size = getElementSize();
for (int s : arraySizes) {
size *= s;
}
return size;
} }
@Override @Override
@ -195,7 +206,7 @@ public class ConfigField {
return "ConfigField{" + return "ConfigField{" +
"name='" + name + '\'' + "name='" + name + '\'' +
", type='" + type + '\'' + ", type='" + type + '\'' +
", arraySize=" + arraySize + ", arraySizes=" + arraySizes +
'}'; '}';
} }
@ -206,8 +217,8 @@ public class ConfigField {
return comment.charAt(0) == TS_COMMENT_TAG ? comment.substring(1) : comment; return comment.charAt(0) == TS_COMMENT_TAG ? comment.substring(1) : comment;
} }
public int getArraySize() { public int[] getArraySizes() {
return arraySize; return arraySizes;
} }
public String getComment() { public String getComment() {

View File

@ -73,9 +73,16 @@ public class ConfigStructure {
int fillSize = totalSize % 4 == 0 ? 0 : 4 - (totalSize % 4); int fillSize = totalSize % 4 == 0 ? 0 : 4 - (totalSize % 4);
if (fillSize != 0) { if (fillSize != 0) {
int[] fillSizeArray;
if (fillSize != 1) {
fillSizeArray = new int[1];
fillSizeArray[0] = fillSize;
} else {
fillSizeArray = new int[0];
}
ConfigField fill = new ConfigField(state, ALIGNMENT_FILL_AT + totalSize, "need 4 byte alignment", ConfigField fill = new ConfigField(state, ALIGNMENT_FILL_AT + totalSize, "need 4 byte alignment",
"" + fillSize, "" + fillSize,
TypesHelper.UINT8_T, fillSize, "\"units\", 1, 0, -20, 100, 0", false, false, null, null, -1, null, null); TypesHelper.UINT8_T, fillSizeArray, "\"units\", 1, 0, -20, 100, 0", false, false, null, null, -1, null, null);
addBoth(fill); addBoth(fill);
} }
totalSize += fillSize; totalSize += fillSize;
@ -109,7 +116,7 @@ public class ConfigStructure {
return; return;
int sizeAtStartOfPadding = cFields.size(); int sizeAtStartOfPadding = cFields.size();
while (readingBitState.get() < 32) { while (readingBitState.get() < 32) {
ConfigField bitField = new ConfigField(readerState, "unusedBit_" + sizeAtStartOfPadding + "_" + readingBitState.get(), "", null, BOOLEAN_T, 0, null, false, false, null, null, -1, null, null); ConfigField bitField = new ConfigField(readerState, "unusedBit_" + sizeAtStartOfPadding + "_" + readingBitState.get(), "", null, BOOLEAN_T, new int[0], null, false, false, null, null, -1, null, null);
addBitField(bitField); addBitField(bitField);
} }
readingBitState.reset(); readingBitState.reset();

View File

@ -52,7 +52,7 @@ public class ReaderState {
String trueName = bitNameParts.length > 1 ? bitNameParts[1].replaceAll("\"", "") : null; String trueName = bitNameParts.length > 1 ? bitNameParts[1].replaceAll("\"", "") : null;
String falseName = bitNameParts.length > 2 ? bitNameParts[2].replaceAll("\"", "") : null; String falseName = bitNameParts.length > 2 ? bitNameParts[2].replaceAll("\"", "") : null;
ConfigField bitField = new ConfigField(state, bitNameParts[0], comment, null, BOOLEAN_T, 0, null, false, false, null, null, -1, trueName, falseName); ConfigField bitField = new ConfigField(state, bitNameParts[0], comment, null, BOOLEAN_T, new int[0], null, false, false, null, null, -1, trueName, falseName);
if (state.stack.isEmpty()) if (state.stack.isEmpty())
throw new IllegalStateException("Parent structure expected"); throw new IllegalStateException("Parent structure expected");
ConfigStructure structure = state.stack.peek(); ConfigStructure structure = state.stack.peek();
@ -246,7 +246,8 @@ public class ReaderState {
if (cf == null) { if (cf == null) {
if (ConfigField.isPreprocessorDirective(state, line)) { if (ConfigField.isPreprocessorDirective(state, line)) {
cf = new ConfigField(state, "", line, null, cf = new ConfigField(state, "", line, null,
ConfigField.DIRECTIVE_T, 0, null, false, false, null, null, 0, null, null); ConfigField.DIRECTIVE_T, new int[0], null, false, false, null, null, 0,
null, null);
} else { } else {
throw new IllegalStateException("Cannot parse line [" + line + "]"); throw new IllegalStateException("Cannot parse line [" + line + "]");
} }
@ -267,9 +268,9 @@ public class ReaderState {
if (cf.isIterate()) { if (cf.isIterate()) {
structure.addC(cf); structure.addC(cf);
for (int i = 1; i <= cf.getArraySize(); i++) { for (int i = 1; i <= cf.getArraySizes()[0]; i++) {
ConfigField element = new ConfigField(state, cf.getName() + i, cf.getComment(), null, ConfigField element = new ConfigField(state, cf.getName() + i, cf.getComment(), null,
cf.getType(), 1, cf.getTsInfo(), false, false, null, cf.getName(), i, null, null); cf.getType(), new int[0], cf.getTsInfo(), false, false, null, cf.getName(), i, null, null);
structure.addTs(element); structure.addTs(element);
} }
} else if (cf.isDirective()) { } else if (cf.isDirective()) {

View File

@ -68,7 +68,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
return tsPosition; return tsPosition;
} }
if (configField.getArraySize() != 1) { if (configField.getArraySizes().length != 0) {
// todo: array support // todo: array support
} else if (TypesHelper.isFloat(configField.getType())) { } else if (TypesHelper.isFloat(configField.getType())) {
writeJavaFieldName(nameWithPrefix, tsPosition); writeJavaFieldName(nameWithPrefix, tsPosition);
@ -101,7 +101,7 @@ public abstract class JavaFieldsConsumer implements ConfigurationConsumer {
javaFieldsWriter.write(");" + EOL); javaFieldsWriter.write(");" + EOL);
} }
tsPosition += configField.getArraySize() * configField.getElementSize(); tsPosition += configField.getSize(next);
return tsPosition; return tsPosition;
} }

View File

@ -80,23 +80,32 @@ public class TSProjectConsumer implements ConfigurationConsumer {
tsPosition += configField.getState().tsCustomSize.get(configField.getType()); tsPosition += configField.getState().tsCustomSize.get(configField.getType());
} else if (configField.getTsInfo() == null) { } else if (configField.getTsInfo() == null) {
throw new IllegalArgumentException("Need TS info for " + configField.getName() + " at "+ prefix); throw new IllegalArgumentException("Need TS info for " + configField.getName() + " at "+ prefix);
} else if (configField.getArraySize() == 0) { } else if (configField.getArraySizes().length == 0) {
// write nothing for empty array
// TS does not like those
} else if (configField.getArraySize() != 1) {
tsHeader.write(nameWithPrefix + " = array, ");
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
tsHeader.write(" " + tsPosition + ",");
tsHeader.write(" [" + configField.getArraySize() + "],");
tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1));
tsPosition += configField.getArraySize() * configField.getElementSize();
} else {
tsHeader.write(nameWithPrefix + " = scalar, "); tsHeader.write(nameWithPrefix + " = scalar, ");
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ","); tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
tsHeader.write(" " + tsPosition + ","); tsHeader.write(" " + tsPosition + ",");
tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1)); tsHeader.write(" " + handleTsInfo(configField.getTsInfo(), 1));
tsPosition += configField.getArraySize() * configField.getElementSize(); tsPosition += configField.getSize(next);
} else if (configField.getSize(next) == 0) {
// write nothing for empty array
// TS does not like those
} else {
tsHeader.write(nameWithPrefix + " = array, ");
tsHeader.write(TypesHelper.convertToTs(configField.getType()) + ",");
tsHeader.write(" " + tsPosition + ",");
tsHeader.write(" [");
boolean first = true;
for (int size : configField.getArraySizes()) {
if (first) {
first = false;
} else {
tsHeader.write("x");
}
tsHeader.write(Integer.toString(size));
}
tsHeader.write("], " + handleTsInfo(configField.getTsInfo(), 1));
tsPosition += configField.getSize(next);
} }
tsHeader.write(EOL); tsHeader.write(EOL);
return tsPosition; return tsPosition;

View File

@ -25,12 +25,27 @@ public class ConfigFieldParserTest {
{ {
ConfigField cf = ConfigField.parse(state, "uint8_t[8] field"); ConfigField cf = ConfigField.parse(state, "uint8_t[8] field");
assertEquals(cf.getType(), "uint8_t"); assertEquals(cf.getType(), "uint8_t");
assertEquals(cf.getArraySize(), 8); assertEquals(cf.getArraySizes().length, 1);
assertEquals(cf.getArraySizes()[0], 8);
assertEquals(cf.getSize(null), 8); assertEquals(cf.getSize(null), 8);
assertFalse("isIterate", cf.isIterate()); assertFalse("isIterate", cf.isIterate());
} }
} }
@Test
public void testByte3dArray() {
ReaderState state = new ReaderState();
{
ConfigField cf = ConfigField.parse(state, "uint8_t[8 x 16] field");
assertEquals(cf.getType(), "uint8_t");
assertEquals(cf.getArraySizes().length, 2);
assertEquals(cf.getArraySizes()[0], 8);
assertEquals(cf.getArraySizes()[1], 16);
assertEquals(cf.getSize(null), 128);
assertFalse("isIterate", cf.isIterate());
}
}
@Test @Test
public void testFloatMsAlias() throws IOException { public void testFloatMsAlias() throws IOException {
String test = "struct pid_s\n" + String test = "struct pid_s\n" +
@ -382,25 +397,26 @@ public class ConfigFieldParserTest {
{ {
ConfigField cf = ConfigField.parse(state, "int[3 iterate] field"); ConfigField cf = ConfigField.parse(state, "int[3 iterate] field");
assertEquals(cf.getType(), "int"); assertEquals(cf.getType(), "int");
assertEquals(cf.getArraySize(), 3); assertEquals(cf.getArraySizes().length, 1);
assertEquals(cf.getArraySizes()[0], 3);
assertTrue("isIterate", cf.isIterate()); assertTrue("isIterate", cf.isIterate());
} }
{ {
ConfigField cf = ConfigField.parse(state, "int16_t crankingRpm;This,. value controls what RPM values we consider 'cranking' (any RPM below 'crankingRpm')\\nAnything above 'crankingRpm' would be 'running'"); ConfigField cf = ConfigField.parse(state, "int16_t crankingRpm;This,. value controls what RPM values we consider 'cranking' (any RPM below 'crankingRpm')\\nAnything above 'crankingRpm' would be 'running'");
assertEquals(cf.getName(), "crankingRpm"); assertEquals(cf.getName(), "crankingRpm");
assertEquals(cf.getArraySize(), 1); assertEquals(cf.getArraySizes().length, 0);
assertEquals(cf.getType(), "int16_t"); assertEquals(cf.getType(), "int16_t");
} }
{ {
ConfigField cf = ConfigField.parse(state, "MAP_sensor_config_s map"); ConfigField cf = ConfigField.parse(state, "MAP_sensor_config_s map");
assertEquals(cf.getName(), "map"); assertEquals(cf.getName(), "map");
assertEquals(cf.getArraySize(), 1); assertEquals(cf.getArraySizes().length, 0);
assertEquals(cf.getType(), "MAP_sensor_config_s"); assertEquals(cf.getType(), "MAP_sensor_config_s");
} }
{ {
ConfigField cf = ConfigField.parse(state, "MAP_sensor_config_s map;@see hasMapSensor\\n@see isMapAveragingEnabled"); ConfigField cf = ConfigField.parse(state, "MAP_sensor_config_s map;@see hasMapSensor\\n@see isMapAveragingEnabled");
assertEquals(cf.getName(), "map"); assertEquals(cf.getName(), "map");
assertEquals(cf.getArraySize(), 1); assertEquals(cf.getArraySizes().length, 0);
assertEquals(cf.getType(), "MAP_sensor_config_s"); assertEquals(cf.getType(), "MAP_sensor_config_s");
assertEquals(cf.getComment(), "@see hasMapSensor\\n@see isMapAveragingEnabled"); assertEquals(cf.getComment(), "@see hasMapSensor\\n@see isMapAveragingEnabled");
} }