This is an automated email from the ASF dual-hosted git repository. sruehl pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit a28fac5a883e7f889172586c9b56f5a1228020df Author: Sebastian Rühl <[email protected]> AuthorDate: Mon Apr 19 23:39:01 2021 +0200 plc4j: converted ReadBuffer and WriteBuffer to interfaces + added logical names to all calls --- .../language/java/JavaLanguageTemplateHelper.java | 72 +++-- .../templates/java/data-io-template.java.ftlh | 8 +- .../resources/templates/java/io-template.java.ftlh | 74 +++-- go.mod | 2 +- go.sum | 2 + .../plc4x/java/ads/protocol/AdsProtocolLogic.java | 18 +- .../protocol/ads/ManualParserSerializerTest.java | 3 +- .../canopen/CANOpenConversationBase.java | 4 +- .../canopen/protocol/CANOpenProtocolLogic.java | 8 +- .../plc4x/java/canopen/ManualParserTest.java | 5 +- .../eip/readwrite/protocol/EipProtocolLogic.java | 9 +- .../java/firmata/readwrite/utils/FirmataUtils.java | 3 +- .../knxnetip/protocol/KnxNetIpProtocolLogic.java | 12 +- .../plc4x/java/knxnetip/utils/KnxHelper.java | 3 +- .../org/apache/plc4x/java/knxnetip/IOTest.java | 10 +- .../java/modbus/protocol/ModbusProtocolLogic.java | 16 +- .../plc4x/java/s7/readwrite/field/S7Field.java | 3 +- .../s7/readwrite/protocol/S7ProtocolLogic.java | 8 +- .../s7/src/test/java/BenchmarkGeneratedS7.java | 6 +- .../java/simulated/connection/SimulatedDevice.java | 3 +- .../spi/GeneratedDriverByteToMessageCodec.java | 9 +- .../plc4x/java/spi/generation/ReadBuffer.java | 339 +++++---------------- .../{ReadBuffer.java => ReadBufferByteBased.java} | 68 +++-- .../plc4x/java/spi/generation/StaticHelper.java | 63 ++-- .../plc4x/java/spi/generation/WriteBuffer.java | 306 +++++-------------- ...{WriteBuffer.java => WriteBufferByteBased.java} | 86 ++++-- .../plc4x/java/spi/generation/ReadBufferTest.java | 6 +- .../plc4x/test/driver/DriverTestsuiteRunner.java | 4 +- .../ParserSerializerTestsuiteRunner.java | 4 +- 29 files changed, 438 insertions(+), 716 deletions(-) diff --git a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java index 19bbedd..fcd6ec2 100644 --- a/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java +++ b/build-utils/language-java/src/main/java/org/apache/plc4x/language/java/JavaLanguageTemplateHelper.java @@ -316,39 +316,43 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe @Override public String getReadBufferReadMethodCall(SimpleTypeReference simpleTypeReference, String valueString, TypedField field) { + return getReadBufferReadMethodCall("", simpleTypeReference, valueString, field); + } + + public String getReadBufferReadMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String valueString, TypedField field) { switch (simpleTypeReference.getBaseType()) { case BIT: { - return "io.readBit()"; + return "io.readBit(\"" + logicalName + "\")"; } case UINT: { IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference; if (integerTypeReference.getSizeInBits() <= 4) { - return "io.readUnsignedByte(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readUnsignedByte(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } if (integerTypeReference.getSizeInBits() <= 8) { - return "io.readUnsignedShort(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readUnsignedShort(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } if (integerTypeReference.getSizeInBits() <= 16) { - return "io.readUnsignedInt(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readUnsignedInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } if (integerTypeReference.getSizeInBits() <= 32) { - return "io.readUnsignedLong(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readUnsignedLong(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } - return "io.readUnsignedBigInteger(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readUnsignedBigInteger(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } case INT: { IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference; if (integerTypeReference.getSizeInBits() <= 8) { - return "io.readByte(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readByte(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } if (integerTypeReference.getSizeInBits() <= 16) { - return "io.readShort(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readShort(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } if (integerTypeReference.getSizeInBits() <= 32) { - return "io.readInt(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readInt(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } if (integerTypeReference.getSizeInBits() <= 64) { - return "io.readLong(" + integerTypeReference.getSizeInBits() + ")"; + return "io.readLong(\"" + logicalName + "\", " + integerTypeReference.getSizeInBits() + ")"; } return "io.readBigInteger(" + integerTypeReference.getSizeInBits() + ")"; } @@ -357,17 +361,17 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe String type = (floatTypeReference.getSizeInBits() <= 32) ? "Float" : "Double"; String typeCast = (floatTypeReference.getSizeInBits() <= 32) ? "float" : "double"; String defaultNull = (floatTypeReference.getSizeInBits() <= 32) ? "0.0f" : "0.0"; - StringBuilder sb = new StringBuilder("((Supplier<").append(type).append(">) (() -> {"); - sb.append("\n return (").append(typeCast).append(") toFloat(io, ").append( - (floatTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.FLOAT) ? "true" : "false") - .append(", ").append(floatTypeReference.getExponent()).append(", ") - .append(floatTypeReference.getMantissa()).append(");"); - sb.append("\n })).get()"); - return sb.toString(); + // TODO: insert logical name + return "((Supplier<" + type + ">) (() -> {" + + "\n return (" + typeCast + ") toFloat(io, \""+logicalName +"\", "+ + ((floatTypeReference.getBaseType() == SimpleTypeReference.SimpleBaseType.FLOAT) ? "true" : "false") + + ", " + floatTypeReference.getExponent() + ", " + + floatTypeReference.getMantissa() + ");" + + "\n })).get()"; } case STRING: { StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference; - return "io.readString(" + toParseExpression(field, stringTypeReference.getLengthExpression(), null) + ", \"" + + return "io.readString(\"" + logicalName + "\", " + toParseExpression(field, stringTypeReference.getLengthExpression(), null) + ", \"" + stringTypeReference.getEncoding() + "\")"; } } @@ -376,56 +380,60 @@ public class JavaLanguageTemplateHelper extends BaseFreemarkerLanguageTemplateHe @Override public String getWriteBufferWriteMethodCall(SimpleTypeReference simpleTypeReference, String fieldName, TypedField field) { + return getWriteBufferWriteMethodCall("", simpleTypeReference,fieldName,field); + } + + public String getWriteBufferWriteMethodCall(String logicalName, SimpleTypeReference simpleTypeReference, String fieldName, TypedField field) { switch (simpleTypeReference.getBaseType()) { case BIT: { - return "io.writeBit((boolean) " + fieldName + ")"; + return "io.writeBit(\""+logicalName+"\", (boolean) " + fieldName + ")"; } case UINT: { IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference; if (integerTypeReference.getSizeInBits() <= 4) { - return "io.writeUnsignedByte(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").byteValue())"; + return "io.writeUnsignedByte(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").byteValue())"; } if (integerTypeReference.getSizeInBits() <= 8) { - return "io.writeUnsignedShort(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").shortValue())"; + return "io.writeUnsignedShort(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").shortValue())"; } if (integerTypeReference.getSizeInBits() <= 16) { - return "io.writeUnsignedInt(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").intValue())"; + return "io.writeUnsignedInt(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").intValue())"; } if (integerTypeReference.getSizeInBits() <= 32) { - return "io.writeUnsignedLong(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").longValue())"; + return "io.writeUnsignedLong(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").longValue())"; } - return "io.writeUnsignedBigInteger(" + integerTypeReference.getSizeInBits() + ", (BigInteger) " + fieldName + ")"; + return "io.writeUnsignedBigInteger(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", (BigInteger) " + fieldName + ")"; } case INT: { IntegerTypeReference integerTypeReference = (IntegerTypeReference) simpleTypeReference; if (integerTypeReference.getSizeInBits() <= 8) { - return "io.writeByte(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").byteValue())"; + return "io.writeByte(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").byteValue())"; } if (integerTypeReference.getSizeInBits() <= 16) { - return "io.writeShort(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").shortValue())"; + return "io.writeShort(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").shortValue())"; } if (integerTypeReference.getSizeInBits() <= 32) { - return "io.writeInt(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").intValue())"; + return "io.writeInt(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").intValue())"; } if (integerTypeReference.getSizeInBits() <= 64) { - return "io.writeLong(" + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").longValue())"; + return "io.writeLong(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", ((Number) " + fieldName + ").longValue())"; } - return "io.writeBigInteger(" + integerTypeReference.getSizeInBits() + ", BigInteger.valueOf( " + fieldName + "))"; + return "io.writeBigInteger(\""+logicalName+"\", " + integerTypeReference.getSizeInBits() + ", BigInteger.valueOf( " + fieldName + "))"; } case FLOAT: case UFLOAT: { FloatTypeReference floatTypeReference = (FloatTypeReference) simpleTypeReference; if (floatTypeReference.getSizeInBits() <= 32) { - return "io.writeFloat(" + fieldName + "," + floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() + ")"; + return "io.writeFloat(\""+logicalName+"\", " + fieldName + "," + floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() + ")"; } else if (floatTypeReference.getSizeInBits() <= 64) { - return "io.writeDouble(" + fieldName + "," + floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() + ")"; + return "io.writeDouble(\""+logicalName+"\", " + fieldName + "," + floatTypeReference.getExponent() + "," + floatTypeReference.getMantissa() + ")"; } else { throw new RuntimeException("Unsupported float type"); } } case STRING: { StringTypeReference stringTypeReference = (StringTypeReference) simpleTypeReference; - return "io.writeString(" + toSerializationExpression(field, stringTypeReference.getLengthExpression(), getThisTypeDefinition().getParserArguments()) + ", \"" + + return "io.writeString(\""+logicalName+"\", " + toSerializationExpression(field, stringTypeReference.getLengthExpression(), getThisTypeDefinition().getParserArguments()) + ", \"" + stringTypeReference.getEncoding() + "\", (String) " + fieldName + ")"; } } diff --git a/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh b/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh index f03f904..2353894 100644 --- a/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh +++ b/build-utils/language-java/src/main/resources/templates/java/data-io-template.java.ftlh @@ -70,7 +70,7 @@ import org.apache.plc4x.java.api.value.*; import org.apache.plc4x.java.spi.generation.EvaluationHelper; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.WriteBufferByteBased; import ${helper.packageName(protocolName, languageName, outputFlavor)}.*; import ${helper.packageName(protocolName, languageName, outputFlavor)}.types.*; import org.apache.plc4x.java.spi.values.*; @@ -315,14 +315,14 @@ public class ${type.name}IO { } <#if outputFlavor != "passive"> - public static WriteBuffer staticSerialize(PlcValue _value<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws ParseException { + public static WriteBufferByteBased staticSerialize(PlcValue _value<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws ParseException { return staticSerialize(_value<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${parserArgument.name}<#sep>, </#sep></#list></#if>, false); } - public static WriteBuffer staticSerialize(PlcValue _value<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>, boolean littleEndian) throws ParseException { + public static WriteBufferByteBased staticSerialize(PlcValue _value<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>, boolean littleEndian) throws ParseException { <#assign defaultCaseOutput=false> <#list type.switchField.cases as case><#if case.discriminatorValues?has_content>if(<#list case.discriminatorValues as discriminatorValue>EvaluationHelper.equals(${helper.toParseExpression(null, type.switchField.discriminatorExpressions[discriminatorValue?index], type.parserArguments)},<#if helper.discriminatorValueNeedsStringEqualityCheck(type.switchField.discriminatorExpressions[discriminatorValue?index])>"${discriminatorValue}"<#elseif helper.isComplexTypeReference(type.parserA [...] - WriteBuffer io = new WriteBuffer((int) Math.ceil(((float) ${helper.getSizeInBits(case, type.parserArguments)}) / 8.0f), littleEndian); + WriteBufferByteBased io = new WriteBufferByteBased((int) Math.ceil(((float) ${helper.getSizeInBits(case, type.parserArguments)}) / 8.0f), littleEndian); <#list case.fields as field> <#switch field.typeName> diff --git a/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh b/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh index 7f62994..68c0865 100644 --- a/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh +++ b/build-utils/language-java/src/main/resources/templates/java/io-template.java.ftlh @@ -146,6 +146,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< </#if> <#-- Here come the actual parse and serialize methods that actually do the parsing and serlaizing --> public static ${type.name}<#if helper.isDiscriminatedChildTypeDefinition()>Builder</#if> staticParse(ReadBuffer io<#if type.parserArguments?has_content>, <#list type.parserArguments as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws ParseException { + io.pullContext("${type.name}"); int startPos = io.getPos(); int curPos; <#list type.fields as field> @@ -154,6 +155,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< <#assign arrayField = field> // Array field (${arrayField.name}) + io.pullContext("${arrayField.name}"); <#-- Only update curPos if the length expression uses it --> <#if arrayField.loopExpression.contains("curPos")> curPos = io.getPos() - startPos; @@ -171,7 +173,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< for(int curItem = 0; curItem < itemCount; curItem++) { <#-- When parsing simple types, there is nothing that could require the "lastItem" --> <#if !helper.isSimpleTypeReference(arrayField.type)>boolean lastItem = curItem == (itemCount - 1);</#if> - ${arrayField.name}[curItem] = <#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, [...] + ${arrayField.name}[curItem] = <#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayFie [...] } } <#-- In all other cases do we have to work with a list, that is later converted to an array --> @@ -183,7 +185,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< List<${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}> _${arrayField.name}List = new LinkedList<>(); int ${arrayField.name}EndPos = io.getPos() + _${arrayField.name}Length; while(io.getPos() < ${arrayField.name}EndPos) { - _${arrayField.name}List.add(<#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parser [...] + _${arrayField.name}List.add(<#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, pa [...] <#-- After parsing, update the current position, but only if it's needed --> <#if arrayField.loopExpression.contains("curPos")> curPos = io.getPos() - startPos; @@ -194,7 +196,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Terminated array List<${helper.getNonPrimitiveLanguageTypeNameForField(arrayField)}> _${arrayField.name}List = new LinkedList<>(); while(!((boolean) (${helper.toParseExpression(arrayField, arrayField.loopExpression, type.parserArguments)}))) { - _${arrayField.name}List.add(<#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, parser [...] + _${arrayField.name}List.add(<#if helper.isSimpleTypeReference(arrayField.type)><#assign simpleTypeReference = arrayField.type>${helper.getReadBufferReadMethodCall("", simpleTypeReference, "", arrayField)}<#else>${arrayField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(arrayField.type, parserArgument?index), true)}) (${helper.toParseExpression(arrayField, pa [...] <#-- After parsing, update the current position, but only if it's needed --> <#if arrayField.loopExpression.contains("curPos")> @@ -217,6 +219,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< </#if> </#if> <#break> + io.closeContext("${arrayField.name}"); <#case "checksum"> <#assign checksumField = field> <#assign simpleTypeReference = checksumField.type> @@ -226,7 +229,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< ${helper.getLanguageTypeNameForField(field)} checksum = ${helper.getNullValueForTypeReference(checksumField.type)}; // Create an array of all the bytes read in this message element so far. byte[] checksumRawData = io.getBytes(startPos, io.getPos()); - ${helper.getLanguageTypeNameForField(field)} checksumRef = ${helper.getReadBufferReadMethodCall(simpleTypeReference, "", checksumField)}; + ${helper.getLanguageTypeNameForField(field)} checksumRef = ${helper.getReadBufferReadMethodCall("checksum", simpleTypeReference, "", checksumField)}; checksum = (${helper.getLanguageTypeNameForField(field)}) (${helper.toParseExpression(checksumField, checksumField.checksumExpression, type.parserArguments)}); if(checksum != checksumRef) { throw new ParseException(String.format("Checksum verification failed. Expected %04X but got %04X", checksumRef & 0xFFFF, checksum & 0xFFFF)); @@ -238,7 +241,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< <#assign simpleTypeReference = constField.type> // Const Field (${constField.name}) - ${helper.getLanguageTypeNameForField(field)} ${constField.name} = ${helper.getReadBufferReadMethodCall(simpleTypeReference, "", constField)}; + ${helper.getLanguageTypeNameForField(field)} ${constField.name} = ${helper.getReadBufferReadMethodCall(constField.name, simpleTypeReference, "", constField)}; if(${constField.name} != ${type.name}.${constField.name?upper_case}) { throw new ParseException("Expected constant value " + ${type.name}.${constField.name?upper_case} + " but got " + ${constField.name}); } @@ -249,9 +252,9 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Discriminator Field (${discriminatorField.name}) (Used as input to a switch field) <#if helper.isEnumField(field)> - ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = ${helper.getLanguageTypeNameForField(discriminatorField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(discriminatorField.type), "", discriminatorField)}); + ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = ${helper.getLanguageTypeNameForField(discriminatorField)}.enumForValue(${helper.getReadBufferReadMethodCall(discriminatorField.name, helper.getEnumBaseTypeReference(discriminatorField.type), "", discriminatorField)}); <#else> - ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = <#if helper.isSimpleTypeReference(discriminatorField.type)>${helper.getReadBufferReadMethodCall(discriminatorField.type, "", discriminatorField)}<#else>${discriminatorField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type, parserArgument?index), true)}) (${helper.toPar [...] + ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = <#if helper.isSimpleTypeReference(discriminatorField.type)>${helper.getReadBufferReadMethodCall(discriminatorField.name, discriminatorField.type, "", discriminatorField)}<#else>${discriminatorField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(discriminatorField.type, parserArgument?index) [...] </#if> <#break> @@ -260,9 +263,9 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Enum field (${enumField.name}) <#if enumField.fieldName?has_content> - ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = ${helper.getLanguageTypeNameForField(field)}.firstEnumForField${enumField.fieldName?cap_first}(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type), "", enumField)}); + ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = ${helper.getLanguageTypeNameForField(field)}.firstEnumForField${enumField.fieldName?cap_first}(${helper.getReadBufferReadMethodCall(enumField.name, helper.getEnumBaseTypeReference(enumField.type), "", enumField)}); <#else> - ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = ${helper.getLanguageTypeNameForField(field)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(enumField.type), "", enumField)}); + ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = ${helper.getLanguageTypeNameForField(field)}.enumForValue(${helper.getReadBufferReadMethodCall(enumField.name, helper.getEnumBaseTypeReference(enumField.type), "", enumField)}); </#if> <#break> <#case "implicit"> @@ -270,11 +273,12 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< <#assign simpleTypeReference = implicitField.type> // Implicit Field (${implicitField.name}) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content) - ${helper.getLanguageTypeNameForField(field)} ${implicitField.name} = ${helper.getReadBufferReadMethodCall(simpleTypeReference, "", implicitField)}; + ${helper.getLanguageTypeNameForField(field)} ${implicitField.name} = ${helper.getReadBufferReadMethodCall(implicitField.name, simpleTypeReference, "", implicitField)}; <#break> <#case "manualArray"> <#assign manualArrayField = field> + io.pullContext("${manualArrayField.name}"); // Manual Array Field (${manualArrayField.name}) <#-- Only update curPos if the length expression uses it --> <#if manualArrayField.loopExpression.contains("curPos")> @@ -330,6 +334,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< ${helper.getLanguageTypeNameForField(field)}[] ${manualArrayField.name} = _${manualArrayField.name}List.toArray(new ${helper.getNonPrimitiveLanguageTypeNameForField(manualArrayField)}[0]); </#if> </#if> + io.closeContext("${manualArrayField.name}"); <#break> <#case "manual"> <#assign manualField = field> @@ -347,9 +352,9 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< ${helper.getLanguageTypeNameForField(field)} ${optionalField.name} = null; if(${helper.toParseExpression(optionalField, optionalField.conditionExpression, type.parserArguments)}) { <#if helper.isEnumField(field)> - ${optionalField.name} = ${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(optionalField.type), "", optionalField)}); + ${optionalField.name} = ${helper.getLanguageTypeNameForField(optionalField)}.enumForValue(${helper.getReadBufferReadMethodCall(optionalField.name, helper.getEnumBaseTypeReference(optionalField.type), "", optionalField)}); <#else> - ${optionalField.name} = <#if helper.isSimpleTypeReference(optionalField.type)>${helper.getReadBufferReadMethodCall(optionalField.type, "", optionalField)}<#else>${optionalField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type, parserArgument?index), true)}) (${helper.toParseExpression(optionalField, parserArgument, type.parserArguments)})<#se [...] + ${optionalField.name} = <#if helper.isSimpleTypeReference(optionalField.type)>${helper.getReadBufferReadMethodCall(optionalField.name, optionalField.type, "", optionalField)}<#else>${optionalField.type.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentType(optionalField.type, parserArgument?index), true)}) (${helper.toParseExpression(optionalField, parserArgument, type.pa [...] </#if> } <#break> @@ -359,11 +364,13 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Padding Field (padding) { + io.pullContext("padding"); int _timesPadding = (int) (${helper.toParseExpression(paddingField, paddingField.paddingCondition, type.parserArguments)}); while ((io.hasMore(${helper.getNumBits(simpleTypeReference)})) && (_timesPadding-- > 0)) { // Just read the padding data and ignore it ${helper.getReadBufferReadMethodCall(simpleTypeReference, "", paddingField)}; } + io.closeContext("padding"); } <#break> <#case "reserved"> @@ -372,7 +379,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Reserved Field (Compartmentalized so the "reserved" variable can't leak) { - ${helper.getLanguageTypeNameForField(field)} reserved = ${helper.getReadBufferReadMethodCall(simpleTypeReference, "", reservedField)}; + ${helper.getLanguageTypeNameForField(field)} reserved = ${helper.getReadBufferReadMethodCall("reserved", simpleTypeReference, "", reservedField)}; if(reserved != ${helper.getReservedValue(reservedField)}) { LOGGER.info("Expected constant value " + ${reservedField.referenceValue} + " but got " + reserved + " for reserved field."); } @@ -383,9 +390,9 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Simple Field (${simpleField.name}) <#if helper.isEnumField(field)> - ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = ${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(${helper.getReadBufferReadMethodCall(helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)}); + ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = ${helper.getLanguageTypeNameForField(simpleField)}.enumForValue(${helper.getReadBufferReadMethodCall(simpleField.name, helper.getEnumBaseTypeReference(simpleField.type), "", simpleField)}); <#else> - ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = <#if helper.isSimpleTypeReference(simpleField.type)><#assign simpleTypeReference = simpleField.type>${helper.getReadBufferReadMethodCall(simpleTypeReference, "", simpleField)}<#else><#assign complexTypeReference = simpleField.type>${complexTypeReference.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(helper.getArgumentT [...] + ${helper.getLanguageTypeNameForField(simpleField)} ${simpleField.name} = <#if helper.isSimpleTypeReference(simpleField.type)><#assign simpleTypeReference = simpleField.type>${helper.getReadBufferReadMethodCall(simpleField.name, simpleTypeReference, "", simpleField)}<#else><#assign complexTypeReference = simpleField.type>${complexTypeReference.name}IO.staticParse(io<#if field.params?has_content>, <#list field.params as parserArgument>(${helper.getLanguageTypeNameForTypeReference(h [...] </#if> <#break> <#case "switch"> @@ -429,7 +436,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< <#if outputFlavor != "passive"> public static void staticSerialize(WriteBuffer io, ${type.name} _value<#if helper.getSerializerArguments(type.parserArguments)?has_content>, <#list helper.getSerializerArguments(type.parserArguments) as parserArgument>${helper.getLanguageTypeNameForTypeReference(parserArgument.type, false)} ${parserArgument.name}<#sep>, </#sep></#list></#if>) throws ParseException { int startPos = io.getPos(); - + io.pushContext("${type.name}"); <#list type.fields as field> <#switch field.typeName> <#case "array"> @@ -438,12 +445,13 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Array Field (${arrayField.name}) if(_value.get${arrayField.name?cap_first}() != null) { + io.pushContext("${arrayField.name}"); int itemCount = (int) _value.get${arrayField.name?cap_first}().length; int curItem = 0; for(${helper.getLanguageTypeNameForField(field)} element : _value.get${arrayField.name?cap_first}()) { <#if helper.isSimpleTypeReference(arrayField.type)> <#assign simpleTypeReference = arrayField.type> - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "element", field)}; + ${helper.getWriteBufferWriteMethodCall("", simpleTypeReference, "element", field)}; <#else> <#assign complexTypeReference = arrayField.type> boolean lastItem = curItem == (itemCount - 1); @@ -451,6 +459,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< </#if> curItem++; } + io.popContext("${arrayField.name}"); } <#break> <#case "checksum"> @@ -463,7 +472,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Create an array of all the bytes written in this message element so far. byte[] checksumRawData = io.getBytes(startPos, io.getPos()); _checksum = (${helper.getLanguageTypeNameForField(field)}) (${helper.toSerializationExpression(checksumField, checksumField.checksumExpression, type.parserArguments)}); - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(_checksum)", field)}; + ${helper.getWriteBufferWriteMethodCall("checksum", simpleTypeReference, "(_checksum)", field)}; } <#break> <#case "const"> @@ -472,7 +481,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Const Field (${constField.name}) <#if helper.getLanguageTypeNameForField(field) = 'float'>${helper.getWriteBufferWriteMethodCall(simpleTypeReference, constField.referenceValue + "f", field)}; - <#else>${helper.getWriteBufferWriteMethodCall(simpleTypeReference, constField.referenceValue, field)}; + <#else>${helper.getWriteBufferWriteMethodCall(constField.name, simpleTypeReference, constField.referenceValue, field)}; </#if> <#break> <#case "discriminator"> @@ -483,11 +492,11 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< ${helper.getLanguageTypeNameForField(field)} ${discriminatorField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${discriminatorField.name?cap_first}(); <#if helper.isSimpleTypeReference(discriminatorField.type)> <#assign simpleTypeReference = discriminatorField.type> - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + discriminatorField.name + ")", field)}; + ${helper.getWriteBufferWriteMethodCall(discriminatorField.name, simpleTypeReference, "(" + discriminatorField.name + ")", field)}; <#else> <#assign complexTypeReference = discriminatorField.type> <#if helper.isEnumField(field)> - ${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(discriminatorField.type), "(" + discriminatorField.name + ".getValue())", field)}; + ${helper.getWriteBufferWriteMethodCall(discriminatorField.name, helper.getEnumBaseTypeReference(discriminatorField.type), "(" + discriminatorField.name + ".getValue())", field)}; <#else> ${complexTypeReference.name}IO.staticSerialize(io, ${discriminatorField.name}); </#if> @@ -499,9 +508,9 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Enum field (${enumField.name}) ${helper.getLanguageTypeNameForField(field)} ${enumField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${enumField.name?cap_first}(); <#if enumField.fieldName?has_content> - ${helper.getWriteBufferWriteMethodCall(helper.getEnumFieldSimpleTypeReference(enumField.type, enumField.fieldName), "(" + enumField.name + ".get" + enumField.fieldName?cap_first + "())", field)}; + ${helper.getWriteBufferWriteMethodCall(enumField.name, helper.getEnumFieldSimpleTypeReference(enumField.type, enumField.fieldName), "(" + enumField.name + ".get" + enumField.fieldName?cap_first + "())", field)}; <#else> - ${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(enumField.type), "(" + enumField.name + ".getValue())", field)}; + ${helper.getWriteBufferWriteMethodCall(enumField.name, helper.getEnumBaseTypeReference(enumField.type), "(" + enumField.name + ".getValue())", field)}; </#if> <#break> <#case "implicit"> @@ -510,16 +519,18 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Implicit Field (${implicitField.name}) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content) ${helper.getLanguageTypeNameForField(field)} ${implicitField.name} = (${helper.getLanguageTypeNameForField(field)}) (${helper.toSerializationExpression(implicitField, implicitField.serializeExpression, type.parserArguments)}); - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + implicitField.name + ")", field)}; + ${helper.getWriteBufferWriteMethodCall(implicitField.name, simpleTypeReference, "(" + implicitField.name + ")", field)}; <#break> <#case "manualArray"> <#assign manualArrayField = field> // Manual Array Field (${manualArrayField.name}) if(_value.get${manualArrayField.name?cap_first}() != null) { + io.pushContext("${manualArrayField.name}"); for(${helper.getLanguageTypeNameForField(field)} element : _value.get${manualArrayField.name?cap_first}()) { ${helper.toSerializationExpression(manualArrayField, manualArrayField.serializeExpression, type.parserArguments)}; } + io.pushContext("${manualArrayField.name}"); } <#break> <#case "manual"> @@ -537,11 +548,11 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< ${optionalField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${optionalField.name?cap_first}(); <#if helper.isSimpleTypeReference(optionalField.type)> <#assign simpleTypeReference = optionalField.type> - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + optionalField.name + ")", field)}; + ${helper.getWriteBufferWriteMethodCall(optionalField.name, simpleTypeReference, "(" + optionalField.name + ")", field)}; <#else> <#assign complexTypeReference = optionalField.type> <#if helper.isEnumField(field)> - ${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(optionalField.type), "(" + optionalField.name + ".getValue())", field)}; + ${helper.getWriteBufferWriteMethodCall(optionalField.name, helper.getEnumBaseTypeReference(optionalField.type), "(" + optionalField.name + ".getValue())", field)}; <#else> ${complexTypeReference.name}IO.staticSerialize(io, ${optionalField.name}); </#if> @@ -554,11 +565,13 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< // Padding Field (padding) { + io.pushContext("padding"); int _timesPadding = (int) (${helper.toSerializationExpression(paddingField, paddingField.paddingCondition, type.parserArguments)}); while (_timesPadding-- > 0) { ${helper.getLanguageTypeNameForField(field)} _paddingValue = (${helper.getLanguageTypeNameForField(field)}) (${helper.toSerializationExpression(paddingField, paddingField.paddingValue, type.parserArguments)}); - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(_paddingValue)", field)}; + ${helper.getWriteBufferWriteMethodCall("", simpleTypeReference, "(_paddingValue)", field)}; } + io.popContext("padding"); } <#break> <#case "reserved"> @@ -566,7 +579,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< <#assign simpleTypeReference = reservedField.type> // Reserved Field (reserved) - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, helper.getReservedValue(field), field)}; + ${helper.getWriteBufferWriteMethodCall("reserved", simpleTypeReference, helper.getReservedValue(field), field)}; <#break> <#case "simple"> <#assign simpleField = field> @@ -575,11 +588,11 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< ${helper.getLanguageTypeNameForField(field)} ${simpleField.name} = (${helper.getLanguageTypeNameForField(field)}) _value.get${simpleField.name?cap_first}(); <#if helper.isSimpleTypeReference(simpleField.type)> <#assign simpleTypeReference = simpleField.type> - ${helper.getWriteBufferWriteMethodCall(simpleTypeReference, "(" + simpleField.name + ")", simpleField)}; + ${helper.getWriteBufferWriteMethodCall(simpleField.name, simpleTypeReference, "(" + simpleField.name + ")", simpleField)}; <#else> <#assign complexTypeReference = simpleField.type> <#if helper.isEnumField(field)> - ${helper.getWriteBufferWriteMethodCall(helper.getEnumBaseTypeReference(simpleField.type), "(" + simpleField.name + ".getValue())", simpleField)}; + ${helper.getWriteBufferWriteMethodCall(simpleField.name, helper.getEnumBaseTypeReference(simpleField.type), "(" + simpleField.name + ".getValue())", simpleField)}; <#else> ${complexTypeReference.name}IO.staticSerialize(io, ${simpleField.name}); </#if> @@ -599,6 +612,7 @@ public class ${type.name}IO implements <#if outputFlavor != "passive">MessageIO< <#break> </#switch> </#list> + io.popContext("${type.name}"); } </#if> diff --git a/go.mod b/go.mod index e2ec48f..cab7d85 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,6 @@ module github.com/apache/plc4x go 1.15 require ( - github.com/apache/plc4x/plc4go v0.0.0-20210419100902-f62f7dd9c377 // indirect + github.com/apache/plc4x/plc4go v0.0.0-20210419161206-de2ecac62cce // indirect github.com/sirupsen/logrus v1.7.0 // indirect ) diff --git a/go.sum b/go.sum index 4e0b305..25fb7d0 100644 --- a/go.sum +++ b/go.sum @@ -90,6 +90,8 @@ github.com/apache/plc4x/plc4go v0.0.0-20210419074057-6deb18d3d472 h1:Z4OnG7I8U3Q github.com/apache/plc4x/plc4go v0.0.0-20210419074057-6deb18d3d472/go.mod h1:d7O6kgWHhwFxXbMbl1DSu55qCYcQz9uwjdsSSJOEA/4= github.com/apache/plc4x/plc4go v0.0.0-20210419100902-f62f7dd9c377 h1:fFZl6lI4JFMC9PCmoob0D/ZLmLo62yDVvINSy41NRtg= github.com/apache/plc4x/plc4go v0.0.0-20210419100902-f62f7dd9c377/go.mod h1:d7O6kgWHhwFxXbMbl1DSu55qCYcQz9uwjdsSSJOEA/4= +github.com/apache/plc4x/plc4go v0.0.0-20210419161206-de2ecac62cce h1:6niN+3NLO6jQxXPhr6R9YBAloipJzajur6GVlGAhvBg= +github.com/apache/plc4x/plc4go v0.0.0-20210419161206-de2ecac62cce/go.mod h1:NqpWaMMhsu3sTm418XwsUWgmY7e2zjgpRMyddBUwmGk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dnephin/pflag v1.0.7/go.mod h1:uxE91IoWURlOiTUIA8Mq5ZZkAv3dPUfZNaT80Zm7OQE= diff --git a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java index eb95ba1..ec1b6ce 100644 --- a/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java +++ b/plc4j/drivers/ads/src/main/java/org/apache/plc4x/java/ads/protocol/AdsProtocolLogic.java @@ -38,9 +38,7 @@ import org.apache.plc4x.java.api.value.PlcValue; import org.apache.plc4x.java.spi.ConversationContext; import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.spi.configuration.HasConfiguration; -import org.apache.plc4x.java.spi.generation.ParseException; -import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.*; import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse; import org.apache.plc4x.java.spi.messages.DefaultPlcWriteResponse; import org.apache.plc4x.java.spi.messages.utils.ResponseItem; @@ -290,12 +288,12 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements Map<String, PlcResponseCode> responseCodes = new HashMap<>(); if (adsData instanceof AdsReadResponse) { AdsReadResponse adsReadResponse = (AdsReadResponse) adsData; - readBuffer = new ReadBuffer(adsReadResponse.getData(), true); + readBuffer = new ReadBufferByteBased(adsReadResponse.getData(), true); responseCodes.put(readRequest.getFieldNames().stream().findFirst().orElse(""), parsePlcResponseCode(adsReadResponse.getResult())); } else if (adsData instanceof AdsReadWriteResponse) { AdsReadWriteResponse adsReadWriteResponse = (AdsReadWriteResponse) adsData; - readBuffer = new ReadBuffer(adsReadWriteResponse.getData(), true); + readBuffer = new ReadBufferByteBased(adsReadWriteResponse.getData(), true); // When parsing a multi-item response, the error codes of each items come // in sequence and then come the values. for (String fieldName : readRequest.getFieldNames()) { @@ -432,7 +430,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements plcValue.getString().length() + 1 : (directAdsField.getAdsDataType() == AdsDataType.WSTRING) ? (plcValue.getString().length() + 1) * 2 : 0; try { - WriteBuffer writeBuffer = DataItemIO.staticSerialize(plcValue, + WriteBufferByteBased writeBuffer = DataItemIO.staticSerialize(plcValue, plcField.getAdsDataType().getDataFormatName(), stringLength, true); AdsData adsData = new AdsWriteRequest( directAdsField.getIndexGroup(), directAdsField.getIndexOffset(), writeBuffer.getData()); @@ -483,7 +481,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements plcValue.getString().length() + 1 : (field.getAdsDataType() == AdsDataType.WSTRING) ? (plcValue.getString().length() + 1) * 2 : 0; try { - final WriteBuffer itemWriteBuffer = DataItemIO.staticSerialize(plcValue, + final WriteBufferByteBased itemWriteBuffer = DataItemIO.staticSerialize(plcValue, field.getAdsDataType().getDataFormatName(), stringLength, true); int numBytes = itemWriteBuffer.getPos(); System.arraycopy(itemWriteBuffer.getData(), 0, writeBuffer, pos, numBytes); @@ -537,7 +535,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements parsePlcResponseCode(adsWriteResponse.getResult())); } else if (adsData instanceof AdsReadWriteResponse) { AdsReadWriteResponse adsReadWriteResponse = (AdsReadWriteResponse) adsData; - ReadBuffer readBuffer = new ReadBuffer(adsReadWriteResponse.getData(), true); + ReadBuffer readBuffer = new ReadBufferByteBased(adsReadWriteResponse.getData(), true); // When parsing a multi-item response, the error codes of each items come // in sequence and then come the values. for (String fieldName : writeRequest.getFieldNames()) { @@ -659,7 +657,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements future.completeExceptionally(new PlcException("Couldn't retrieve handle for symbolic field " + symbolicAdsField.getSymbolicAddress() + " got return code " + responseAdsData.getResult().name())); } else { - ReadBuffer readBuffer = new ReadBuffer(responseAdsData.getData(), true); + ReadBuffer readBuffer = new ReadBufferByteBased(responseAdsData.getData(), true); try { // Read the handle. long handle = readBuffer.readUnsignedLong(32); @@ -707,7 +705,7 @@ public class AdsProtocolLogic extends Plc4xProtocolBase<AmsTCPPacket> implements .check(adsDataResponse -> adsDataResponse instanceof AdsReadWriteResponse) .unwrap(adsDataResponse -> (AdsReadWriteResponse) adsDataResponse) .handle(responseAdsData -> { - ReadBuffer readBuffer = new ReadBuffer(responseAdsData.getData(), true); + ReadBuffer readBuffer = new ReadBufferByteBased(responseAdsData.getData(), true); Map<SymbolicAdsField, Long> returnCodes = new HashMap<>(); // In the response first come the return codes and the data-lengths for each item. symbolicAdsFields.forEach(symbolicAdsField -> { diff --git a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java index f6dd3c2..03961e8 100644 --- a/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java +++ b/plc4j/drivers/ads/src/test/java/org/apache/plc4x/protocol/ads/ManualParserSerializerTest.java @@ -22,13 +22,14 @@ import org.apache.commons.codec.binary.Hex; import org.apache.plc4x.java.ads.readwrite.AmsTCPPacket; import org.apache.plc4x.java.ads.readwrite.io.AmsTCPPacketIO; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; public class ManualParserSerializerTest { public static void main(String[] args) throws Exception { byte[] data = Hex.decodeHex("0000f1000000c0a817c80101feffc0a817140101530309000500d1000000000000002f00000000000000c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012a00a07d0f7e1c8e31489f8cf1006b3604b888defc88f64eb6fbb217d11fc5cf5f148b0abf05407c941a93b8263301db0f4940d66875727a0000000000d2040000ab6459032bbf7e03b888defcb8a5b249044de82ee03a2ab [...] //byte[] data = Hex.decodeHex("0000f1000000c0a817c80101feffc0a817140101530309000500d1000000000000002f00000000000000c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012a00a07d0f7e1c8e31489f8cf1006b3604b888defc"); - ReadBuffer readBuffer = new ReadBuffer(data, true); + ReadBuffer readBuffer = new ReadBufferByteBased(data, true); final AmsTCPPacket amsTCPPacket = AmsTCPPacketIO.staticParse(readBuffer); System.out.println(amsTCPPacket); } diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java index 4ff6fdb..ca81dc6 100644 --- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java +++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/api/conversation/canopen/CANOpenConversationBase.java @@ -27,7 +27,7 @@ import org.apache.plc4x.java.canopen.readwrite.io.DataItemIO; import org.apache.plc4x.java.canopen.readwrite.types.CANOpenDataType; import org.apache.plc4x.java.canopen.readwrite.types.CANOpenService; import org.apache.plc4x.java.spi.generation.ParseException; -import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; @@ -45,7 +45,7 @@ public abstract class CANOpenConversationBase { } protected PlcValue decodeFrom(byte[] data, CANOpenDataType type, int length) throws ParseException { - return DataItemIO.staticParse(new ReadBuffer(data, true), type, length); + return DataItemIO.staticParse(new ReadBufferByteBased(data, true), type, length); } protected <T> void onError(CompletableFuture<T> receiver, CANOpenSDOResponse response, Throwable error) { diff --git a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java index 6ef4ebd..9dad461 100644 --- a/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java +++ b/plc4j/drivers/canopen/src/main/java/org/apache/plc4x/java/canopen/protocol/CANOpenProtocolLogic.java @@ -62,9 +62,7 @@ import org.apache.plc4x.java.spi.ConversationContext; import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.spi.configuration.HasConfiguration; import org.apache.plc4x.java.spi.context.DriverContext; -import org.apache.plc4x.java.spi.generation.ParseException; -import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.*; import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse; import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionEvent; import org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionRequest; @@ -223,7 +221,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem try { String fieldName = writeRequest.getFieldNames().iterator().next(); - WriteBuffer buffer = DataItemIO.staticSerialize(writeValue, field.getCanOpenDataType(), writeValue.getLength(), true); + WriteBufferByteBased buffer = DataItemIO.staticSerialize(writeValue, field.getCanOpenDataType(), writeValue.getLength(), true); if (buffer != null) { final CANOpenPDOPayload payload = new CANOpenPDOPayload(new CANOpenPDO(buffer.getData())); context.sendToWire(factory.createBuilder() @@ -377,7 +375,7 @@ public class CANOpenProtocolLogic extends Plc4xProtocolBase<CANOpenFrame> implem CANOpenPDOField field = (CANOpenPDOField) handle.getField(); byte[] data = ((CANOpenPDOPayload) payload).getPdo().getData(); try { - PlcValue value = DataItemIO.staticParse(new ReadBuffer(data, true), field.getCanOpenDataType(), data.length); + PlcValue value = DataItemIO.staticParse(new ReadBufferByteBased(data, true), field.getCanOpenDataType(), data.length); DefaultPlcSubscriptionEvent event = new DefaultPlcSubscriptionEvent( Instant.now(), Collections.singletonMap( diff --git a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java index 7bbfd40..1a4f925 100644 --- a/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java +++ b/plc4j/drivers/canopen/src/test/java/org/apache/plc4x/java/canopen/ManualParserTest.java @@ -20,6 +20,7 @@ package org.apache.plc4x.java.canopen; import org.apache.commons.codec.binary.Hex; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -44,7 +45,7 @@ public class ManualParserTest { @Test public void readBufferTest() throws Exception { - ReadBuffer buffer = new ReadBuffer(new byte[]{(byte) 0xA1, 0x05, 0x00, 0x00}, true); + ReadBuffer buffer = new ReadBufferByteBased(new byte[]{(byte) 0xA1, 0x05, 0x00, 0x00}, true); int value = buffer.readInt(32); assertEquals(value, 0x5A1); @@ -77,7 +78,7 @@ public class ManualParserTest { public final static SocketCanFrameStub parse(String hex) throws Exception { byte[] input = Hex.decodeHex(hex.toCharArray()); - ReadBuffer readBuffer = new ReadBuffer(input, true); + ReadBufferByteBased readBuffer = new ReadBufferByteBased(input, true); int rawId = readBuffer.readInt(32); boolean extended = (rawId & EXTENDED_FRAME_FORMAT_FLAG) != 0; boolean remote = (rawId & REMOTE_TRANSMISSION_FLAG) != 0; diff --git a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java index b0197cc..bc4e9fd 100644 --- a/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java +++ b/plc4j/drivers/eip/src/main/java/org/apache/plc4x/java/eip/readwrite/protocol/EipProtocolLogic.java @@ -34,6 +34,7 @@ import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.spi.configuration.HasConfiguration; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.messages.*; import org.apache.plc4x.java.spi.messages.utils.ResponseItem; import org.apache.plc4x.java.spi.transaction.RequestTransactionManager; @@ -278,7 +279,7 @@ public class EipProtocolLogic extends Plc4xProtocolBase<EipPacket> implements Ha MultipleServiceResponse responses = (MultipleServiceResponse) p; int nb = responses.getServiceNb(); CipService[] arr = new CipService[nb]; - ReadBuffer read = new ReadBuffer(responses.getServicesData(), true); + ReadBufferByteBased read = new ReadBufferByteBased(responses.getServicesData(), true); int total = (int) read.getTotalBytes(); for (int i = 0; i < nb; i++) { int length = 0; @@ -288,7 +289,7 @@ public class EipProtocolLogic extends Plc4xProtocolBase<EipPacket> implements Ha } else { length = responses.getOffsets()[i + 1] - offset - responses.getOffsets()[0]; //Calculate length with offsets (substracting first offset) } - ReadBuffer serviceBuf = new ReadBuffer(read.getBytes(offset, offset + length), true); + ReadBuffer serviceBuf = new ReadBufferByteBased(read.getBytes(offset, offset + length), true); CipService service = null; try { service = CipServiceIO.staticParse(read, length); @@ -489,7 +490,7 @@ public class EipProtocolLogic extends Plc4xProtocolBase<EipPacket> implements Ha MultipleServiceResponse resp = (MultipleServiceResponse) p; int nb = resp.getServiceNb(); CipService[] arr = new CipService[nb]; - ReadBuffer read = new ReadBuffer(resp.getServicesData()); + ReadBufferByteBased read = new ReadBufferByteBased(resp.getServicesData()); int total = (int) read.getTotalBytes(); for (int i = 0; i < nb; i++) { int length = 0; @@ -499,7 +500,7 @@ public class EipProtocolLogic extends Plc4xProtocolBase<EipPacket> implements Ha } else { length = resp.getOffsets()[i + 1] - offset; //Calculate length with offsets } - ReadBuffer serviceBuf = new ReadBuffer(read.getBytes(offset, length), true); + ReadBuffer serviceBuf = new ReadBufferByteBased(read.getBytes(offset, length), true); CipService service = null; try { service = CipServiceIO.staticParse(read, length); diff --git a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java index 2dc3169..71a42fe 100644 --- a/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java +++ b/plc4j/drivers/firmata/src/main/java/org/apache/plc4x/java/firmata/readwrite/utils/FirmataUtils.java @@ -20,12 +20,13 @@ package org.apache.plc4x.java.firmata.readwrite.utils; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.generation.WriteBuffer; public class FirmataUtils { public static boolean isSysexEnd(ReadBuffer io) { - return io.getBytes(io.getPos(), io.getPos() + 1)[0] == (byte) 0xF7; + return ((ReadBufferByteBased) io).getBytes(io.getPos(), io.getPos() + 1)[0] == (byte) 0xF7; } public static byte parseSysexString(ReadBuffer io) { diff --git a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java index 0bcbb7f..7c6bc5e 100644 --- a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java +++ b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/protocol/KnxNetIpProtocolLogic.java @@ -42,9 +42,7 @@ import org.apache.plc4x.java.spi.ConversationContext; import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.knxnetip.readwrite.*; import org.apache.plc4x.java.spi.context.DriverContext; -import org.apache.plc4x.java.spi.generation.ParseException; -import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.*; import org.apache.plc4x.java.spi.messages.*; import org.apache.plc4x.java.spi.messages.utils.ResponseItem; import org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration; @@ -288,7 +286,7 @@ public class KnxNetIpProtocolLogic extends Plc4xProtocolBase<KnxNetIpMessage> im // Use the data in the ets5 model to correctly check and serialize the PlcValue try { - final WriteBuffer writeBuffer = KnxDatapointIO.staticSerialize(value, + final WriteBufferByteBased writeBuffer = KnxDatapointIO.staticSerialize(value, groupAddress.getType()); final byte[] serialized = writeBuffer.getData(); dataFirstByte = serialized[0]; @@ -453,7 +451,7 @@ public class KnxNetIpProtocolLogic extends Plc4xProtocolBase<KnxNetIpMessage> im System.arraycopy(restBytes, 0, payload, 1, restBytes.length); // Decode the group address depending on the project settings. - ReadBuffer addressBuffer = new ReadBuffer(destinationGroupAddress); + ReadBuffer addressBuffer = new ReadBufferByteBased(destinationGroupAddress); final KnxGroupAddress knxGroupAddress = KnxGroupAddressIO.staticParse(addressBuffer, knxNetIpDriverContext.getGroupAddressType()); final String destinationAddress = toString(knxGroupAddress); @@ -472,7 +470,7 @@ public class KnxNetIpProtocolLogic extends Plc4xProtocolBase<KnxNetIpMessage> im toString(sourceAddress), destinationAddress)); // Parse the payload depending on the type of the group-address. - ReadBuffer rawDataReader = new ReadBuffer(payload); + ReadBuffer rawDataReader = new ReadBufferByteBased(payload); final PlcValue value = KnxDatapointIO.staticParse(rawDataReader, groupAddress.getType()); @@ -574,7 +572,7 @@ public class KnxNetIpProtocolLogic extends Plc4xProtocolBase<KnxNetIpMessage> im } protected byte[] toKnxAddressData(KnxNetIpField field) { - WriteBuffer address = new WriteBuffer(2); + WriteBufferByteBased address = new WriteBufferByteBased(2); try { switch (knxNetIpDriverContext.getGroupAddressType()) { case 3: diff --git a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java index 6b25941..575feb3 100644 --- a/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java +++ b/plc4j/drivers/knxnetip/src/main/java/org/apache/plc4x/java/knxnetip/utils/KnxHelper.java @@ -22,6 +22,7 @@ import org.apache.commons.codec.binary.Hex; import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.generation.WriteBuffer; public class KnxHelper { @@ -64,7 +65,7 @@ public class KnxHelper { public static void main(String[] args) throws Exception { final byte[] bytes = Hex.decodeHex("0C65"); - ReadBuffer io = new ReadBuffer(bytes); + ReadBuffer io = new ReadBufferByteBased(bytes); final double v = bytesToF16(io); System.out.println(v); } diff --git a/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java b/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java index c60de6c..f3d9a08 100644 --- a/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java +++ b/plc4j/drivers/knxnetip/src/test/java/org/apache/plc4x/java/knxnetip/IOTest.java @@ -25,7 +25,9 @@ import org.apache.commons.codec.binary.Hex; import org.apache.plc4x.java.knxnetip.readwrite.KnxNetIpMessage; import org.apache.plc4x.java.knxnetip.readwrite.io.KnxNetIpMessageIO; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.WriteBufferByteBased; import org.junit.jupiter.api.Test; import java.util.Arrays; @@ -36,7 +38,7 @@ public class IOTest { public void testXml() throws Exception { byte[] rData = Hex.decodeHex("061004200019047f02002900bce0110509d405008044a68000"); ObjectMapper mapper = new XmlMapper().enableDefaultTyping(); - ReadBuffer rBuf = new ReadBuffer(rData); + ReadBuffer rBuf = new ReadBufferByteBased(rData); KnxNetIpMessage packet = new KnxNetIpMessageIO().parse(rBuf); String xml = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(packet); System.out.println(xml); @@ -48,7 +50,7 @@ public class IOTest { public void testJson() throws Exception { byte[] rData = Hex.decodeHex("0610020500180801c0a82a46c4090801c0a82a46c40a0203"); ObjectMapper mapper = new ObjectMapper().enableDefaultTyping(); - ReadBuffer rBuf = new ReadBuffer(rData); + ReadBuffer rBuf = new ReadBufferByteBased(rData); KnxNetIpMessage packet = new KnxNetIpMessageIO().parse(rBuf); String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(packet); System.out.println(json); @@ -67,7 +69,7 @@ public class IOTest { // Benchmark the parsing code KnxNetIpMessage packet = null; for(int i = 0; i < numRunsParse; i++) { - ReadBuffer rBuf = new ReadBuffer(rData); + ReadBuffer rBuf = new ReadBufferByteBased(rData); packet = KnxNetIpMessageIO.staticParse(rBuf); } long endParsing = System.currentTimeMillis(); @@ -79,7 +81,7 @@ public class IOTest { int numRunsSerialize = 20000; byte[] oData = null; for(int i = 0; i < numRunsSerialize; i++) { - WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes()); + WriteBufferByteBased wBuf = new WriteBufferByteBased(packet.getLengthInBytes()); KnxNetIpMessageIO.staticSerialize(wBuf, packet); oData = wBuf.getData(); } diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java index 264c0e2..d1b9991 100644 --- a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/protocol/ModbusProtocolLogic.java @@ -36,9 +36,7 @@ import org.apache.plc4x.java.modbus.readwrite.io.DataItemIO; import org.apache.plc4x.java.spi.ConversationContext; import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.spi.configuration.HasConfiguration; -import org.apache.plc4x.java.spi.generation.ParseException; -import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.*; import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest; import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse; import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest; @@ -378,7 +376,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme } ModbusPDUReadInputRegistersRequest req = (ModbusPDUReadInputRegistersRequest) request; ModbusPDUReadInputRegistersResponse resp = (ModbusPDUReadInputRegistersResponse) response; - ReadBuffer io = new ReadBuffer(resp.getValue()); + ReadBuffer io = new ReadBufferByteBased(resp.getValue()); if(fieldDataTypeSize < 2) { io.readByte(8); } @@ -390,7 +388,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme } ModbusPDUReadHoldingRegistersRequest req = (ModbusPDUReadHoldingRegistersRequest) request; ModbusPDUReadHoldingRegistersResponse resp = (ModbusPDUReadHoldingRegistersResponse) response; - ReadBuffer io = new ReadBuffer(resp.getValue()); + ReadBuffer io = new ReadBufferByteBased(resp.getValue()); if((dataType != ModbusDataType.STRING) && fieldDataTypeSize < 2) { io.readByte(8); } @@ -407,11 +405,11 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme if (resp.getItems().length == 2 && resp.getItems().length == req.getItems().length) { //If request was split over file records, two groups in reponse should be received. - io = new ReadBuffer(ArrayUtils.addAll(resp.getItems()[0].getData(), resp.getItems()[1].getData())); + io = new ReadBufferByteBased(ArrayUtils.addAll(resp.getItems()[0].getData(), resp.getItems()[1].getData())); dataLength = (short) (resp.getItems()[0].getLengthInBytes() + resp.getItems()[1].getLengthInBytes() - (2 * FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH)); } else if (resp.getItems().length == 1 && resp.getItems().length == req.getItems().length) { //If request was within a single file record, one group should be received. - io = new ReadBuffer(resp.getItems()[0].getData()); + io = new ReadBufferByteBased(resp.getItems()[0].getData()); dataLength = (short) (resp.getItems()[0].getLengthInBytes() - FC_EXTENDED_REGISTERS_GROUP_HEADER_LENGTH); } else { throw new PlcRuntimeException("Unexpected number of groups in response. " + @@ -428,7 +426,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme private byte[] fromPlcValue(PlcField field, PlcValue plcValue) { ModbusDataType fieldDataType = ((ModbusField) field).getDataType(); try { - WriteBuffer buffer; + WriteBufferByteBased buffer; if(plcValue instanceof PlcList) { buffer = DataItemIO.staticSerialize(plcValue, fieldDataType, plcValue.getLength(), false); byte[] data = buffer.getData(); @@ -469,7 +467,7 @@ public class ModbusProtocolLogic extends Plc4xProtocolBase<ModbusTcpADU> impleme } private PlcValue readBooleanList(int count, byte[] data) throws ParseException { - ReadBuffer io = new ReadBuffer(data); + ReadBuffer io = new ReadBufferByteBased(data); if(count == 1) { return DataItemIO.staticParse(io, ModbusDataType.BOOL, 1); } diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java index 543a863..64b6aba 100644 --- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java +++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/field/S7Field.java @@ -33,6 +33,7 @@ import org.apache.plc4x.java.s7.readwrite.types.MemoryArea; import org.apache.plc4x.java.s7.readwrite.types.TransportSize; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.utils.XmlSerializable; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -250,7 +251,7 @@ public class S7Field implements PlcField, XmlSerializable { } else if (PLC_PROXY_ADDRESS_PATTERN.matcher(fieldString).matches()) { try { byte[] addressData = Hex.decodeHex(fieldString.replaceAll("[-]", "")); - ReadBuffer rb = new ReadBuffer(addressData); + ReadBuffer rb = new ReadBufferByteBased(addressData); final S7Address s7Address = S7AddressIO.staticParse(rb); if (s7Address instanceof S7AddressAny) { S7AddressAny s7AddressAny = (S7AddressAny) s7Address; diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java index 7c7087c..40903d1 100644 --- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java +++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java @@ -29,6 +29,7 @@ import org.apache.plc4x.java.api.messages.PlcWriteRequest; import org.apache.plc4x.java.api.messages.PlcWriteResponse; import org.apache.plc4x.java.api.model.PlcField; import org.apache.plc4x.java.api.types.PlcResponseCode; +import org.apache.plc4x.java.spi.generation.*; import org.apache.plc4x.java.spi.values.PlcNull; import org.apache.plc4x.java.api.value.PlcValue; import org.apache.plc4x.java.spi.values.IEC61131ValueHandler; @@ -41,9 +42,6 @@ import org.apache.plc4x.java.s7.readwrite.field.S7Field; import org.apache.plc4x.java.spi.ConversationContext; import org.apache.plc4x.java.spi.Plc4xProtocolBase; import org.apache.plc4x.java.spi.context.DriverContext; -import org.apache.plc4x.java.spi.generation.ParseException; -import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; import org.apache.plc4x.java.spi.messages.DefaultPlcReadRequest; import org.apache.plc4x.java.spi.messages.DefaultPlcReadResponse; import org.apache.plc4x.java.spi.messages.DefaultPlcWriteRequest; @@ -514,7 +512,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { try { DataTransportSize transportSize = field.getDataType().getDataTransportSize(); int stringLength = (field instanceof S7StringField) ? ((S7StringField) field).getStringLength() : 254; - WriteBuffer writeBuffer = DataItemIO.staticSerialize(plcValue, field.getDataType().getDataProtocolId(), + WriteBufferByteBased writeBuffer = DataItemIO.staticSerialize(plcValue, field.getDataType().getDataProtocolId(), stringLength); if(writeBuffer != null) { byte[] data = writeBuffer.getData(); @@ -527,7 +525,7 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> { } private PlcValue parsePlcValue(S7Field field, ByteBuf data) { - ReadBuffer readBuffer = new ReadBuffer(data.array()); + ReadBuffer readBuffer = new ReadBufferByteBased(data.array()); try { int stringLength = (field instanceof S7StringField) ? ((S7StringField) field).getStringLength() : 254; if (field.getNumberOfElements() == 1) { diff --git a/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java b/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java index a6d9c34..60ad96f 100644 --- a/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java +++ b/plc4j/drivers/s7/src/test/java/BenchmarkGeneratedS7.java @@ -21,7 +21,9 @@ import org.apache.commons.codec.binary.Hex; import org.apache.plc4x.java.s7.readwrite.TPKTPacket; import org.apache.plc4x.java.s7.readwrite.io.TPKTPacketIO; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.WriteBufferByteBased; import java.util.Arrays; @@ -36,7 +38,7 @@ public class BenchmarkGeneratedS7 { // Benchmark the parsing code TPKTPacket packet = null; for(int i = 0; i < numRunsParse; i++) { - ReadBuffer rBuf = new ReadBuffer(rData); + ReadBuffer rBuf = new ReadBufferByteBased(rData); packet = TPKTPacketIO.staticParse(rBuf); } long endParsing = System.currentTimeMillis(); @@ -48,7 +50,7 @@ public class BenchmarkGeneratedS7 { int numRunsSerialize = 2000000; byte[] oData = null; for(int i = 0; i < numRunsSerialize; i++) { - WriteBuffer wBuf = new WriteBuffer(packet.getLengthInBytes()); + WriteBufferByteBased wBuf = new WriteBufferByteBased(packet.getLengthInBytes()); TPKTPacketIO.staticSerialize(wBuf, packet); oData = wBuf.getData(); } diff --git a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java index 546914f..832440c 100644 --- a/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java +++ b/plc4j/drivers/simulated/src/main/java/org/apache/plc4x/java/simulated/connection/SimulatedDevice.java @@ -28,6 +28,7 @@ import org.apache.plc4x.java.simulated.readwrite.types.SimulatedDataTypeSizes; import org.apache.plc4x.java.spi.generation.ParseException; import org.apache.plc4x.java.spi.generation.ReadBuffer; +import org.apache.plc4x.java.spi.generation.ReadBufferByteBased; import org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField; import org.apache.plc4x.java.spi.values.IEC61131ValueHandler; import org.apache.plc4x.java.simulated.field.SimulatedField; @@ -122,7 +123,7 @@ public class SimulatedDevice { byte[] b = new byte[fieldDataTypeSize * field.getNumberOfElements()]; new Random().nextBytes(b); - ReadBuffer io = new ReadBuffer(b); + ReadBuffer io = new ReadBufferByteBased(b); try { return DataItemIO.staticParse(io, field.getPlcDataType(), field.getNumberOfElements()); } catch (ParseException e) { diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java index f5fc6f1..4398574 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/GeneratedDriverByteToMessageCodec.java @@ -22,10 +22,7 @@ import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import org.apache.commons.codec.binary.Hex; -import org.apache.plc4x.java.spi.generation.Message; -import org.apache.plc4x.java.spi.generation.MessageIO; -import org.apache.plc4x.java.spi.generation.ReadBuffer; -import org.apache.plc4x.java.spi.generation.WriteBuffer; +import org.apache.plc4x.java.spi.generation.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,7 +46,7 @@ public abstract class GeneratedDriverByteToMessageCodec<T extends Message> exten @Override protected void encode(ChannelHandlerContext ctx, T packet, ByteBuf byteBuf) { try { - WriteBuffer buffer = new WriteBuffer(packet.getLengthInBytes(), !bigEndian); + WriteBufferByteBased buffer = new WriteBufferByteBased(packet.getLengthInBytes(), !bigEndian); io.serialize(buffer, packet); byteBuf.writeBytes(buffer.getData()); LOGGER.debug("Sending bytes to PLC for message {} as data {}", packet, Hex.encodeHexString(buffer.getData())); @@ -74,7 +71,7 @@ public abstract class GeneratedDriverByteToMessageCodec<T extends Message> exten // Read the packet data into a new ReadBuffer bytes = new byte[packetSize]; byteBuf.readBytes(bytes); - ReadBuffer readBuffer = new ReadBuffer(bytes, !bigEndian); + ReadBuffer readBuffer = new ReadBufferByteBased(bytes, !bigEndian); // Parse the packet. T packet = io.parse(readBuffer, parserArgs); diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java index 1beef09..1c8f329 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java @@ -1,311 +1,124 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. */ package org.apache.plc4x.java.spi.generation; -import com.github.jinahya.bit.io.ArrayByteInput; -import org.apache.plc4x.java.api.exceptions.PlcRuntimeException; -import org.apache.plc4x.java.spi.generation.io.MyDefaultBitInput; - -import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; -import java.nio.charset.Charset; -public class ReadBuffer { +public interface ReadBuffer { + int getPos(); - private final MyDefaultBitInput bi; - private final boolean littleEndian; - private final long totalBytes; + boolean hasMore(int numBits); - public ReadBuffer(byte[] input) { - this(input, false); - } + void pullContext(String logicalName); - public ReadBuffer(byte[] input, boolean littleEndian) { - ArrayByteInput abi = new ArrayByteInput(input); - this.bi = new MyDefaultBitInput(abi); - this.littleEndian = littleEndian; - this.totalBytes = input.length; - } + boolean readBit(String logicalName) throws ParseException; - public int getPos() { - return (int) bi.getPos(); + default boolean readBit() throws ParseException { + return readBit(""); } - public byte[] getBytes(int startPos, int endPos) { - int numBytes = endPos - startPos; - byte[] data = new byte[numBytes]; - System.arraycopy(bi.getDelegate().getSource(), startPos, data, 0, numBytes); - return data; - } + byte readUnsignedByte(String logicalName, int bitLength) throws ParseException; - public long getTotalBytes() { - return totalBytes; + default byte readUnsignedByte(int bitLength) throws ParseException { + return readUnsignedByte("", bitLength); } - public boolean hasMore(int numBits) { - return (numBits / 8) <= (totalBytes - getPos()); - } + short readUnsignedShort(String logicalName, int bitLength) throws ParseException; - public byte peekByte(int offset) throws ParseException { - // Remember the old index. - int oldIndex = bi.getDelegate().getIndex(); - try { - // Set the delegate to the desired position. - bi.getDelegate().index(oldIndex + offset); - // Read the byte. - return bi.readByte(false, 8); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } finally { - // Reset the delegate to the old index. - bi.getDelegate().index(oldIndex); - } + default short readUnsignedShort(int bitLength) throws ParseException { + return readUnsignedShort("", bitLength); } - public boolean readBit() throws ParseException { - try { - return bi.readBoolean(); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } - } + int readUnsignedInt(String logicalName, int bitLength) throws ParseException; - public byte readUnsignedByte(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("unsigned byte must contain at least 1 bit"); - } - if (bitLength > 7) { - throw new ParseException("unsigned byte can only contain max 4 bits"); - } - try { - return bi.readByte(true, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + default int readUnsignedInt(int bitLength) throws ParseException { + return readUnsignedInt("", bitLength); } - public short readUnsignedShort(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("unsigned short must contain at least 1 bit"); - } - if (bitLength > 15) { - throw new ParseException("unsigned short can only contain max 8 bits"); - } - try { - // No need to flip here as we're only reading one byte. - return bi.readShort(true, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } - } + long readUnsignedLong(String logicalName, int bitLength) throws ParseException; - public int readUnsignedInt(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("unsigned int must contain at least 1 bit"); - } - if (bitLength > 31) { - throw new ParseException("unsigned int can only contain max 16 bits"); - } - try { - if (littleEndian) { - int intValue = bi.readInt(true, bitLength); - return Integer.reverseBytes(intValue) >>> 16; - } - return bi.readInt(true, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + default long readUnsignedLong(int bitLength) throws ParseException { + return readUnsignedLong("", bitLength); } - public long readUnsignedLong(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("unsigned long must contain at least 1 bit"); - } - if (bitLength > 63) { - throw new ParseException("unsigned long can only contain max 32 bits"); - } - try { - if (littleEndian) { - final long longValue = bi.readLong(true, bitLength); - return Long.reverseBytes(longValue) >>> 32; - } - return bi.readLong(true, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } - } + BigInteger readUnsignedBigInteger(String logicalName, int bitLength) throws ParseException; - public BigInteger readUnsignedBigInteger(int bitLength) throws ParseException { - //Support specific case where value less than 64 bits and big endian. - if (bitLength <= 0) { - throw new ParseException("unsigned long must contain at least 1 bit"); - } - if (bitLength > 64) { - throw new ParseException("unsigned long can only contain max 64 bits"); - } - try { - // Read as signed value - Long val = bi.readLong(false, bitLength); - if (littleEndian) { - val = Long.reverseBytes(val); - } - if (val >= 0) { - return BigInteger.valueOf(val); - } else { - BigInteger constant = BigInteger.valueOf(Long.MAX_VALUE).multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(2)); - return BigInteger.valueOf(val).add(constant); - } - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + default BigInteger readUnsignedBigInteger(int bitLength) throws ParseException { + return readUnsignedBigInteger("", bitLength); } - public byte readByte(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("byte must contain at least 1 bit"); - } - if (bitLength > 8) { - throw new ParseException("byte can only contain max 8 bits"); - } - try { - return bi.readByte(false, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + byte readByte(String logicalName, int bitLength) throws ParseException; + + default byte readByte(int bitLength) throws ParseException { + return readByte("", bitLength); } - public short readShort(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("short must contain at least 1 bit"); - } - if (bitLength > 16) { - throw new ParseException("short can only contain max 16 bits"); - } - try { - if (littleEndian) { - return Short.reverseBytes(bi.readShort(false, bitLength)); - } - return bi.readShort(false, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + short readShort(String logicalName, int bitLength) throws ParseException; + + default short readShort(int bitLength) throws ParseException { + return readShort("", bitLength); } - public int readInt(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("int must contain at least 1 bit"); - } - if (bitLength > 32) { - throw new ParseException("int can only contain max 32 bits"); - } - try { - if (littleEndian) { - return Integer.reverseBytes(bi.readInt(false, bitLength)); - } - return bi.readInt(false, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + int readInt(String logicalName, int bitLength) throws ParseException; + + default int readInt(int bitLength) throws ParseException { + return readInt("", bitLength); } - public long readLong(int bitLength) throws ParseException { - if (bitLength <= 0) { - throw new ParseException("long must contain at least 1 bit"); - } - if (bitLength > 64) { - throw new ParseException("long can only contain max 64 bits"); - } - try { - if (littleEndian) { - return Long.reverseBytes(bi.readLong(false, bitLength)); - } - return bi.readLong(false, bitLength); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + long readLong(String logicalName, int bitLength) throws ParseException; + + default long readLong(int bitLength) throws ParseException { + return readLong("", bitLength); } - public BigInteger readBigInteger(int bitLength) throws ParseException { - throw new UnsupportedOperationException("not implemented yet"); + BigInteger readBigInteger(String logicalName, int bitLength) throws ParseException; + + default BigInteger readBigInteger(int bitLength) throws ParseException { + return readBigInteger("", bitLength); } - public float readFloat(int bitLength) throws ParseException { - try { - if (bitLength == 16) { - // https://en.wikipedia.org/wiki/Half-precision_floating-point_format - final boolean sign = bi.readBoolean(); - final byte exponent = bi.readByte(true, 5); - final short fraction = bi.readShort(true, 10); - if ((exponent >= 1) && (exponent <= 30)) { - return (sign ? 1 : -1) * (2 ^ (exponent - 15)) * (1 + (fraction / 10f)); - } else if (exponent == 0) { - if (fraction == 0) { - return 0.0f; - } else { - return (sign ? 1 : -1) * (2 ^ (-14)) * (fraction / 10f); - } - } else if (exponent == 31) { - if (fraction == 0) { - return sign ? Float.POSITIVE_INFINITY : Float.NEGATIVE_INFINITY; - } else { - return Float.NaN; - } - } else { - throw new NumberFormatException(); - } - } else if (bitLength == 32) { - int intValue = readInt(32); - return Float.intBitsToFloat(intValue); - } else { - throw new UnsupportedOperationException("unsupported bit length (only 16 and 32 supported)"); - } - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + float readFloat(String logicalName, int bitLength) throws ParseException; + + default float readFloat(int bitLength) throws ParseException { + return readFloat("", bitLength); } - public double readDouble(int bitLength) throws ParseException { - if(bitLength == 64) { - long longValue = readLong(64); - return Double.longBitsToDouble(longValue); - } else { - throw new UnsupportedOperationException("unsupported bit length (only 64 supported)"); - } + double readDouble(String logicalName, int bitLength) throws ParseException; + + default double readDouble(int bitLength) throws ParseException { + return readDouble("", bitLength); } - public BigDecimal readBigDecimal(int bitLength) throws ParseException { - throw new UnsupportedOperationException("not implemented yet"); + BigDecimal readBigDecimal(String logicalName, int bitLength) throws ParseException; + + default BigDecimal readBigDecimal(int bitLength) throws ParseException { + return readBigDecimal("", bitLength); } - public String readString(int bitLength, String encoding) { - byte[] strBytes = new byte[bitLength / 8]; - for (int i = 0; (i < (bitLength / 8)) && hasMore(8); i++) { - try { - strBytes[i] = readByte(8); - } catch (Exception e) { - throw new PlcRuntimeException(e); - } - } - //replaceAll function removes and leading ' char or hypens. - return new String(strBytes, Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]",""))); + String readString(String logicalName, int bitLength, String encoding); + + default String readString(int bitLength, String encoding) { + return readString("", bitLength,encoding); } + + void closeContext(String logicalName); } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java similarity index 83% copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java copy to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java index 1beef09..5e35310 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBuffer.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java @@ -28,23 +28,24 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; -public class ReadBuffer { +public class ReadBufferByteBased implements ReadBuffer { private final MyDefaultBitInput bi; private final boolean littleEndian; private final long totalBytes; - public ReadBuffer(byte[] input) { + public ReadBufferByteBased(byte[] input) { this(input, false); } - public ReadBuffer(byte[] input, boolean littleEndian) { + public ReadBufferByteBased(byte[] input, boolean littleEndian) { ArrayByteInput abi = new ArrayByteInput(input); this.bi = new MyDefaultBitInput(abi); this.littleEndian = littleEndian; this.totalBytes = input.length; } + @Override public int getPos() { return (int) bi.getPos(); } @@ -60,6 +61,7 @@ public class ReadBuffer { return totalBytes; } + @Override public boolean hasMore(int numBits) { return (numBits / 8) <= (totalBytes - getPos()); } @@ -80,7 +82,12 @@ public class ReadBuffer { } } - public boolean readBit() throws ParseException { + @Override + public void pullContext(String logicalName) { + } + + @Override + public boolean readBit(String logicalName) throws ParseException { try { return bi.readBoolean(); } catch (IOException e) { @@ -88,7 +95,8 @@ public class ReadBuffer { } } - public byte readUnsignedByte(int bitLength) throws ParseException { + @Override + public byte readUnsignedByte(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("unsigned byte must contain at least 1 bit"); } @@ -102,7 +110,8 @@ public class ReadBuffer { } } - public short readUnsignedShort(int bitLength) throws ParseException { + @Override + public short readUnsignedShort(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("unsigned short must contain at least 1 bit"); } @@ -117,7 +126,8 @@ public class ReadBuffer { } } - public int readUnsignedInt(int bitLength) throws ParseException { + @Override + public int readUnsignedInt(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("unsigned int must contain at least 1 bit"); } @@ -135,7 +145,8 @@ public class ReadBuffer { } } - public long readUnsignedLong(int bitLength) throws ParseException { + @Override + public long readUnsignedLong(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("unsigned long must contain at least 1 bit"); } @@ -153,7 +164,8 @@ public class ReadBuffer { } } - public BigInteger readUnsignedBigInteger(int bitLength) throws ParseException { + @Override + public BigInteger readUnsignedBigInteger(String logicalName, int bitLength) throws ParseException { //Support specific case where value less than 64 bits and big endian. if (bitLength <= 0) { throw new ParseException("unsigned long must contain at least 1 bit"); @@ -178,7 +190,8 @@ public class ReadBuffer { } } - public byte readByte(int bitLength) throws ParseException { + @Override + public byte readByte(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("byte must contain at least 1 bit"); } @@ -192,7 +205,8 @@ public class ReadBuffer { } } - public short readShort(int bitLength) throws ParseException { + @Override + public short readShort(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("short must contain at least 1 bit"); } @@ -209,7 +223,8 @@ public class ReadBuffer { } } - public int readInt(int bitLength) throws ParseException { + @Override + public int readInt(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("int must contain at least 1 bit"); } @@ -226,7 +241,8 @@ public class ReadBuffer { } } - public long readLong(int bitLength) throws ParseException { + @Override + public long readLong(String logicalName, int bitLength) throws ParseException { if (bitLength <= 0) { throw new ParseException("long must contain at least 1 bit"); } @@ -243,11 +259,13 @@ public class ReadBuffer { } } - public BigInteger readBigInteger(int bitLength) throws ParseException { + @Override + public BigInteger readBigInteger(String logicalName, int bitLength) throws ParseException { throw new UnsupportedOperationException("not implemented yet"); } - public float readFloat(int bitLength) throws ParseException { + @Override + public float readFloat(String logicalName, int bitLength) throws ParseException { try { if (bitLength == 16) { // https://en.wikipedia.org/wiki/Half-precision_floating-point_format @@ -272,7 +290,7 @@ public class ReadBuffer { throw new NumberFormatException(); } } else if (bitLength == 32) { - int intValue = readInt(32); + int intValue = readInt(logicalName,32); return Float.intBitsToFloat(intValue); } else { throw new UnsupportedOperationException("unsupported bit length (only 16 and 32 supported)"); @@ -282,24 +300,27 @@ public class ReadBuffer { } } - public double readDouble(int bitLength) throws ParseException { + @Override + public double readDouble(String logicalName, int bitLength) throws ParseException { if(bitLength == 64) { - long longValue = readLong(64); + long longValue = readLong(logicalName,64); return Double.longBitsToDouble(longValue); } else { throw new UnsupportedOperationException("unsupported bit length (only 64 supported)"); } } - public BigDecimal readBigDecimal(int bitLength) throws ParseException { + @Override + public BigDecimal readBigDecimal(String logicalName, int bitLength) throws ParseException { throw new UnsupportedOperationException("not implemented yet"); } - public String readString(int bitLength, String encoding) { + @Override + public String readString(String logicalName, int bitLength, String encoding) { byte[] strBytes = new byte[bitLength / 8]; for (int i = 0; (i < (bitLength / 8)) && hasMore(8); i++) { try { - strBytes[i] = readByte(8); + strBytes[i] = readByte(logicalName,8); } catch (Exception e) { throw new PlcRuntimeException(e); } @@ -308,4 +329,9 @@ public class ReadBuffer { return new String(strBytes, Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]",""))); } + + @Override + public void closeContext(String logicalName) { + } + } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java index 26a37fa..5593f44 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/StaticHelper.java @@ -18,8 +18,6 @@ */ package org.apache.plc4x.java.spi.generation; -import org.apache.commons.codec.binary.Hex; - import java.util.Collection; public class StaticHelper { @@ -29,7 +27,7 @@ public class StaticHelper { Object[] arr = (Object[]) obj; int numBytes = 0; for (Object element : arr) { - if(element instanceof Message) { + if (element instanceof Message) { numBytes += ((Message) element).getLengthInBytes(); } else { throw new RuntimeException( @@ -42,36 +40,36 @@ public class StaticHelper { } public static int COUNT(Object obj) { - if(obj == null) { + if (obj == null) { return 0; } if (obj.getClass().isArray()) { - if(obj.getClass().getComponentType() != null && obj.getClass().getComponentType().isPrimitive()) { - if(obj.getClass().getComponentType() == boolean.class) { + if (obj.getClass().getComponentType() != null && obj.getClass().getComponentType().isPrimitive()) { + if (obj.getClass().getComponentType() == boolean.class) { boolean[] arr = (boolean[]) obj; return arr.length; } - if(obj.getClass().getComponentType() == byte.class) { - byte[] arr = (byte []) obj; + if (obj.getClass().getComponentType() == byte.class) { + byte[] arr = (byte[]) obj; return arr.length; } - if(obj.getClass().getComponentType() == short.class) { - short[] arr = (short []) obj; + if (obj.getClass().getComponentType() == short.class) { + short[] arr = (short[]) obj; return arr.length; } - if(obj.getClass().getComponentType() == int.class) { - int[] arr = (int []) obj; + if (obj.getClass().getComponentType() == int.class) { + int[] arr = (int[]) obj; return arr.length; } - if(obj.getClass().getComponentType() == long.class) { - long[] arr = (long []) obj; + if (obj.getClass().getComponentType() == long.class) { + long[] arr = (long[]) obj; return arr.length; } - if(obj.getClass().getComponentType() == float.class) { - float[] arr = (float []) obj; + if (obj.getClass().getComponentType() == float.class) { + float[] arr = (float[]) obj; return arr.length; } - if(obj.getClass().getComponentType() == double.class) { + if (obj.getClass().getComponentType() == double.class) { double[] arr = (double[]) obj; return arr.length; } @@ -99,23 +97,28 @@ public class StaticHelper { } public static double toFloat(ReadBuffer io, boolean signed, int bitsExponent, int bitsMantissa) { + return toFloat(io, "", signed, bitsExponent, bitsMantissa); + } + + // TODO: refactor so that we only emit one logical name + public static double toFloat(ReadBuffer io, String logicalName, boolean signed, int bitsExponent, int bitsMantissa) { try { if (signed && bitsExponent == 8 && bitsMantissa == 23) { - return io.readFloat(32); + return io.readFloat(logicalName, 32); } else if (signed && bitsExponent == 11 & bitsMantissa == 52) { - return io.readDouble(64); + return io.readDouble(logicalName, 64); } - boolean negative = (signed) && io.readBit(); - long exponent = io.readUnsignedLong(bitsExponent); + boolean negative = (signed) && io.readBit(logicalName); + long exponent = io.readUnsignedLong(logicalName, bitsExponent); exponent = exponent - (((long) Math.pow(2, bitsExponent) / 2) - 1); double mantissa = 1D; - for(int i = 1; i <= bitsMantissa; i++) { - if(io.readBit()) { + for (int i = 1; i <= bitsMantissa; i++) { + if (io.readBit(logicalName)) { mantissa += Math.pow(2, (double) i * -1); } } return ((negative) ? -1 : 1) * mantissa * Math.pow(2, exponent); - } catch(ParseException e) { + } catch (ParseException e) { return 0.0f; } } @@ -132,16 +135,4 @@ public class StaticHelper { return 0; } - public static void main(String[] args) throws Exception { - /*final byte[] bytes = Hex.decodeHex("420B9000"); - ReadBuffer io = new ReadBuffer(bytes); - final double v = toFloat(io, true, 8, 23); - System.out.println(v);*/ - - final byte[] bytes = Hex.decodeHex("0C65"); - ReadBuffer io = new ReadBuffer(bytes); - final double v = toFloat(io, true, 4, 11); - System.out.println(v); - } - } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java index b8c94fd..cc74f17 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java @@ -1,277 +1,121 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. */ package org.apache.plc4x.java.spi.generation; -import com.github.jinahya.bit.io.BufferByteOutput; -import org.apache.plc4x.java.spi.generation.io.MyDefaultBitOutput; - -import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.Charset; -public class WriteBuffer { +public interface WriteBuffer { + int getPos(); - private final ByteBuffer bb; - private final BufferByteOutput bbo; - private final MyDefaultBitOutput bo; - private final boolean littleEndian; + void pushContext(String logicalName); - public WriteBuffer(int size) { - this(size, false); - } + void writeBit(String logicalName, boolean value) throws ParseException; - public WriteBuffer(int size, boolean littleEndian) { - bb = ByteBuffer.allocate(size); - bbo = new BufferByteOutput(bb); - bo = new MyDefaultBitOutput(bbo); - this.littleEndian = littleEndian; + default void writeBit(boolean value) throws ParseException { + writeBit("", value); } - public byte[] getData() { - return bb.array(); - } + void writeUnsignedByte(String logicalName, int bitLength, byte value) throws ParseException; - public int getPos() { - return (int) bo.getPos(); + default void writeUnsignedByte(int bitLength, byte value) throws ParseException { + writeUnsignedByte("", bitLength,value); } - public byte[] getBytes(int startPos, int endPos) { - int numBytes = endPos - startPos; - byte[] data = new byte[numBytes]; - System.arraycopy(bb.array(), startPos, data, 0, numBytes); - return data; - } + void writeUnsignedShort(String logicalName, int bitLength, short value) throws ParseException; - public void writeBit(boolean value) throws ParseException { - try { - bo.writeBoolean(value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + default void writeUnsignedShort(int bitLength, short value) throws ParseException { + writeUnsignedShort("", bitLength, value); } - public void writeUnsignedByte(int bitLength, byte value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("unsigned byte must contain at least 1 bit"); - } - if(bitLength > 8) { - throw new ParseException("unsigned byte can only contain max 8 bits"); - } - try { - bo.writeByte(true, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } - } + void writeUnsignedInt(String logicalName, int bitLength, int value) throws ParseException; - public void writeUnsignedShort(int bitLength, short value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("unsigned short must contain at least 1 bit"); - } - if(bitLength > 16) { - throw new ParseException("unsigned short can only contain max 16 bits"); - } - try { - bo.writeShort(true, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + default void writeUnsignedInt(int bitLength, int value) throws ParseException { + writeUnsignedInt("", bitLength, value); } - public void writeUnsignedInt(int bitLength, int value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("unsigned int must contain at least 1 bit"); - } - if(bitLength > 32) { - throw new ParseException("unsigned int can only contain max 32 bits"); - } - try { - if(littleEndian) { - value = Integer.reverseBytes(value) >> 16; - } - bo.writeInt(true, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } - } + void writeUnsignedLong(String logicalName, int bitLength, long value) throws ParseException; - public void writeUnsignedLong(int bitLength, long value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("unsigned long must contain at least 1 bit"); - } - if(bitLength > 63) { - throw new ParseException("unsigned long can only contain max 63 bits"); - } - try { - if(littleEndian) { - value = Long.reverseBytes(value) >> 32; - } - bo.writeLong(true, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + default void writeUnsignedLong(int bitLength, long value) throws ParseException { + writeUnsignedLong("", bitLength, value); } - public void writeUnsignedBigInteger(int bitLength, BigInteger value) throws ParseException { - try { - if (bitLength == 64) { - if(littleEndian) { - if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) { - writeLong(32, value.longValue()); - writeLong(32, value.shiftRight(32).longValue()); - } else { - writeLong(bitLength, value.longValue()); - } - } else { - if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) { - writeLong(32, value.shiftRight(32).longValue()); - writeLong(32, value.longValue()); - } else { - writeLong(bitLength, value.longValue()); - } - } - } else if (bitLength < 64){ - writeUnsignedLong(bitLength, value.longValue()); - } else { - throw new ParseException("Unsigned Big Integer can only contain max 64 bits"); - } - } catch (ArithmeticException e) { - throw new ParseException("Error reading", e); - } + void writeUnsignedBigInteger(String logicalName, int bitLength, BigInteger value) throws ParseException; + + default void writeUnsignedBigInteger(int bitLength, BigInteger value) throws ParseException { + writeUnsignedBigInteger("", bitLength, value); } - public void writeByte(int bitLength, byte value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("byte must contain at least 1 bit"); - } - if(bitLength > 8) { - throw new ParseException("byte can only contain max 8 bits"); - } - try { - bo.writeByte(false, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + void writeByte(String logicalName, int bitLength, byte value) throws ParseException; + + default void writeByte(int bitLength, byte value) throws ParseException { + writeByte("", bitLength, value); } - public void writeShort(int bitLength, short value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("short must contain at least 1 bit"); - } - if(bitLength > 16) { - throw new ParseException("short can only contain max 16 bits"); - } - try { - if(littleEndian) { - value = Short.reverseBytes(value); - } - bo.writeShort(false, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + void writeShort(String logicalName, int bitLength, short value) throws ParseException; + + default void writeShort(int bitLength, short value) throws ParseException { + writeShort("", bitLength, value); } - public void writeInt(int bitLength, int value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("int must contain at least 1 bit"); - } - if(bitLength > 32) { - throw new ParseException("int can only contain max 32 bits"); - } - try { - if(littleEndian) { - value = Integer.reverseBytes(value); - } - bo.writeInt(false, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + void writeInt(String logicalName, int bitLength, int value) throws ParseException; + + default void writeInt(int bitLength, int value) throws ParseException { + writeInt("", bitLength, value); } - public void writeLong(int bitLength, long value) throws ParseException { - if(bitLength <= 0) { - throw new ParseException("long must contain at least 1 bit"); - } - if(bitLength > 64) { - throw new ParseException("long can only contain max 64 bits"); - } - try { - if(littleEndian) { - value = Long.reverseBytes(value); - } - bo.writeLong(false, bitLength, value); - } catch (IOException e) { - throw new ParseException("Error reading", e); - } + void writeLong(String logicalName, int bitLength, long value) throws ParseException; + + default void writeLong(int bitLength, long value) throws ParseException { + writeLong("", bitLength, value); } - public void writeBigInteger(int bitLength, BigInteger value) throws ParseException { - try { - if(bitLength > 64) { - throw new ParseException("Big Integer can only contain max 64 bits"); - } - writeLong(bitLength, value.longValue()); - } catch (ArithmeticException e) { - throw new ParseException("Error reading", e); - } + void writeBigInteger(String logicalName, int bitLength, BigInteger value) throws ParseException; + + default void writeBigInteger(int bitLength, BigInteger value) throws ParseException { + writeBigInteger("", bitLength, value); } - public void writeFloat(float value, int bitsExponent, int bitsMantissa) throws ParseException { - if (bitsExponent != 8 || bitsMantissa != 23) { - throw new UnsupportedOperationException("Exponent and/or Mantissa non standard size"); - } - writeInt(1 + bitsExponent + bitsMantissa, Float.floatToRawIntBits(value)); + void writeFloat(String logicalName, float value, int bitsExponent, int bitsMantissa) throws ParseException; + + default void writeFloat(float value, int bitsExponent, int bitsMantissa) throws ParseException { + writeFloat("", value, bitsExponent,bitsMantissa); } - public void writeDouble(double value, int bitsExponent, int bitsMantissa) throws ParseException { - if (bitsExponent != 11 || bitsMantissa != 52) { - throw new UnsupportedOperationException("Exponent and/or Mantissa non standard size"); - } - writeLong(1 + bitsExponent + bitsMantissa, Double.doubleToRawLongBits(value)); + void writeDouble(String logicalName, double value, int bitsExponent, int bitsMantissa) throws ParseException; + + default void writeDouble(double value, int bitsExponent, int bitsMantissa) throws ParseException { + writeDouble("", value,bitsExponent,bitsMantissa); } - public void writeBigDecimal(int bitLength, BigDecimal value) throws ParseException { - throw new UnsupportedOperationException("not implemented yet"); + void writeBigDecimal(String logicalName, int bitLength, BigDecimal value) throws ParseException; + + default void writeBigDecimal(int bitLength, BigDecimal value) throws ParseException { + writeBigDecimal("", bitLength, value); } - public void writeString(int bitLength, String encoding, String value) throws ParseException { - final byte[] bytes = value.getBytes(Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]",""))); - int fixedByteLength = bitLength / 8; - - if (bitLength == 0) { - fixedByteLength = bytes.length; - } - - try { - for (int i = 0; i < fixedByteLength; i++) { - if (i >= bytes.length) { - bo.writeByte(false, 8, (byte) 0x00); - } else { - bo.writeByte(false, 8, bytes[i]); - } - } - } catch (IOException e) { - throw new ParseException("Error writing string", e); - } + void writeString(String logicalName, int bitLength, String encoding, String value) throws ParseException; + + default void writeString(int bitLength, String encoding, String value) throws ParseException { + writeString("", bitLength,encoding, value); } + void popContext(String logicalName); } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java similarity index 71% copy from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java copy to plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java index b8c94fd..a85815c 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBuffer.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java @@ -28,20 +28,20 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.charset.Charset; -public class WriteBuffer { +public class WriteBufferByteBased implements WriteBuffer { private final ByteBuffer bb; - private final BufferByteOutput bbo; + private final BufferByteOutput<?> bbo; private final MyDefaultBitOutput bo; private final boolean littleEndian; - public WriteBuffer(int size) { + public WriteBufferByteBased(int size) { this(size, false); } - public WriteBuffer(int size, boolean littleEndian) { + public WriteBufferByteBased(int size, boolean littleEndian) { bb = ByteBuffer.allocate(size); - bbo = new BufferByteOutput(bb); + bbo = new BufferByteOutput<>(bb); bo = new MyDefaultBitOutput(bbo); this.littleEndian = littleEndian; } @@ -50,6 +50,7 @@ public class WriteBuffer { return bb.array(); } + @Override public int getPos() { return (int) bo.getPos(); } @@ -61,7 +62,13 @@ public class WriteBuffer { return data; } - public void writeBit(boolean value) throws ParseException { + @Override + public void pushContext(String logicalName) { + + } + + @Override + public void writeBit(String logicalName, boolean value) throws ParseException { try { bo.writeBoolean(value); } catch (IOException e) { @@ -69,7 +76,8 @@ public class WriteBuffer { } } - public void writeUnsignedByte(int bitLength, byte value) throws ParseException { + @Override + public void writeUnsignedByte(String logicalName, int bitLength, byte value) throws ParseException { if(bitLength <= 0) { throw new ParseException("unsigned byte must contain at least 1 bit"); } @@ -83,7 +91,8 @@ public class WriteBuffer { } } - public void writeUnsignedShort(int bitLength, short value) throws ParseException { + @Override + public void writeUnsignedShort(String logicalName, int bitLength, short value) throws ParseException { if(bitLength <= 0) { throw new ParseException("unsigned short must contain at least 1 bit"); } @@ -97,7 +106,8 @@ public class WriteBuffer { } } - public void writeUnsignedInt(int bitLength, int value) throws ParseException { + @Override + public void writeUnsignedInt(String logicalName, int bitLength, int value) throws ParseException { if(bitLength <= 0) { throw new ParseException("unsigned int must contain at least 1 bit"); } @@ -114,7 +124,8 @@ public class WriteBuffer { } } - public void writeUnsignedLong(int bitLength, long value) throws ParseException { + @Override + public void writeUnsignedLong(String logicalName, int bitLength, long value) throws ParseException { if(bitLength <= 0) { throw new ParseException("unsigned long must contain at least 1 bit"); } @@ -131,26 +142,27 @@ public class WriteBuffer { } } - public void writeUnsignedBigInteger(int bitLength, BigInteger value) throws ParseException { + @Override + public void writeUnsignedBigInteger(String logicalName, int bitLength, BigInteger value) throws ParseException { try { if (bitLength == 64) { if(littleEndian) { if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) { - writeLong(32, value.longValue()); - writeLong(32, value.shiftRight(32).longValue()); + writeLong(logicalName,32, value.longValue()); + writeLong(logicalName,32, value.shiftRight(32).longValue()); } else { - writeLong(bitLength, value.longValue()); + writeLong(logicalName,bitLength, value.longValue()); } } else { if (value.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) >= 0) { - writeLong(32, value.shiftRight(32).longValue()); - writeLong(32, value.longValue()); + writeLong(logicalName,32, value.shiftRight(32).longValue()); + writeLong(logicalName,32, value.longValue()); } else { - writeLong(bitLength, value.longValue()); + writeLong(logicalName,bitLength, value.longValue()); } } } else if (bitLength < 64){ - writeUnsignedLong(bitLength, value.longValue()); + writeUnsignedLong(logicalName,bitLength, value.longValue()); } else { throw new ParseException("Unsigned Big Integer can only contain max 64 bits"); } @@ -159,7 +171,8 @@ public class WriteBuffer { } } - public void writeByte(int bitLength, byte value) throws ParseException { + @Override + public void writeByte(String logicalName, int bitLength, byte value) throws ParseException { if(bitLength <= 0) { throw new ParseException("byte must contain at least 1 bit"); } @@ -173,7 +186,8 @@ public class WriteBuffer { } } - public void writeShort(int bitLength, short value) throws ParseException { + @Override + public void writeShort(String logicalName, int bitLength, short value) throws ParseException { if(bitLength <= 0) { throw new ParseException("short must contain at least 1 bit"); } @@ -190,7 +204,8 @@ public class WriteBuffer { } } - public void writeInt(int bitLength, int value) throws ParseException { + @Override + public void writeInt(String logicalName, int bitLength, int value) throws ParseException { if(bitLength <= 0) { throw new ParseException("int must contain at least 1 bit"); } @@ -207,7 +222,8 @@ public class WriteBuffer { } } - public void writeLong(int bitLength, long value) throws ParseException { + @Override + public void writeLong(String logicalName, int bitLength, long value) throws ParseException { if(bitLength <= 0) { throw new ParseException("long must contain at least 1 bit"); } @@ -224,36 +240,41 @@ public class WriteBuffer { } } - public void writeBigInteger(int bitLength, BigInteger value) throws ParseException { + @Override + public void writeBigInteger(String logicalName, int bitLength, BigInteger value) throws ParseException { try { if(bitLength > 64) { throw new ParseException("Big Integer can only contain max 64 bits"); } - writeLong(bitLength, value.longValue()); + writeLong(logicalName, bitLength, value.longValue()); } catch (ArithmeticException e) { throw new ParseException("Error reading", e); } } - public void writeFloat(float value, int bitsExponent, int bitsMantissa) throws ParseException { + @Override + public void writeFloat(String logicalName, float value, int bitsExponent, int bitsMantissa) throws ParseException { if (bitsExponent != 8 || bitsMantissa != 23) { throw new UnsupportedOperationException("Exponent and/or Mantissa non standard size"); } - writeInt(1 + bitsExponent + bitsMantissa, Float.floatToRawIntBits(value)); + writeInt(logicalName,1 + bitsExponent + bitsMantissa, Float.floatToRawIntBits(value)); } - public void writeDouble(double value, int bitsExponent, int bitsMantissa) throws ParseException { + @Override + public void writeDouble(String logicalName, double value, int bitsExponent, int bitsMantissa) throws ParseException { if (bitsExponent != 11 || bitsMantissa != 52) { throw new UnsupportedOperationException("Exponent and/or Mantissa non standard size"); } - writeLong(1 + bitsExponent + bitsMantissa, Double.doubleToRawLongBits(value)); + writeLong(logicalName,1 + bitsExponent + bitsMantissa, Double.doubleToRawLongBits(value)); } - public void writeBigDecimal(int bitLength, BigDecimal value) throws ParseException { + @Override + public void writeBigDecimal(String logicalName, int bitLength, BigDecimal value) throws ParseException { throw new UnsupportedOperationException("not implemented yet"); } - public void writeString(int bitLength, String encoding, String value) throws ParseException { + @Override + public void writeString(String logicalName, int bitLength, String encoding, String value) throws ParseException { final byte[] bytes = value.getBytes(Charset.forName(encoding.replaceAll("[^a-zA-Z0-9]",""))); int fixedByteLength = bitLength / 8; @@ -274,4 +295,9 @@ public class WriteBuffer { } } + @Override + public void popContext(String logicalName) { + + } + } diff --git a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java index 6d75aa7..6346954 100644 --- a/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java +++ b/plc4j/spi/src/test/java/org/apache/plc4x/java/spi/generation/ReadBufferTest.java @@ -22,7 +22,7 @@ import org.junit.jupiter.api.Test; import java.nio.charset.StandardCharsets; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class ReadBufferTest { @@ -32,8 +32,8 @@ class ReadBufferTest { @Test void readString() { String value = new String("abcdef"); - final ReadBuffer buffer = new ReadBuffer(value.getBytes(StandardCharsets.UTF_8)); - String answer = buffer.readString(value.length() * 8, "UTF-8"); + final ReadBuffer buffer = new ReadBufferByteBased(value.getBytes(StandardCharsets.UTF_8)); + String answer = buffer.readString("", value.length() * 8, "UTF-8"); assertEquals(value, answer); } diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java index 6701efd..95122b4 100644 --- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java +++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/driver/DriverTestsuiteRunner.java @@ -424,7 +424,7 @@ public class DriverTestsuiteRunner extends XmlTestsuiteRunner { private byte[] getBytesFromXml(Element referenceXml, boolean bigEndian) throws DriverTestsuiteException { final String className = referenceXml.attributeValue(new QName("className")); - final WriteBuffer writeBuffer = new WriteBuffer(1024, !bigEndian); + final WriteBufferByteBased writeBuffer = new WriteBufferByteBased(1024, !bigEndian); try { final MessageIO messageIO = getMessageIOType(className).newInstance(); final String referenceXmlString = referenceXml.asXML(); @@ -449,7 +449,7 @@ public class DriverTestsuiteRunner extends XmlTestsuiteRunner { private void validateMessage(Element referenceXml, List<String> parserArguments, byte[] data, boolean bigEndian) throws DriverTestsuiteException { final ObjectMapper mapper = new XmlMapper().enableDefaultTyping().registerModule(new TestSuiteMappingModule()); - final ReadBuffer readBuffer = new ReadBuffer(data, !bigEndian); + final ReadBufferByteBased readBuffer = new ReadBufferByteBased(data, !bigEndian); try { final String className = referenceXml.attributeValue(new QName("className")); final MessageIO<?,?> messageIO = getMessageIOType(className).newInstance(); diff --git a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java index 6a6409f..811cb4f 100644 --- a/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java +++ b/plc4j/utils/test-utils/src/main/java/org/apache/plc4x/test/parserserializer/ParserSerializerTestsuiteRunner.java @@ -129,7 +129,7 @@ public class ParserSerializerTestsuiteRunner extends XmlTestsuiteRunner { private void run(ParserSerializerTestsuite testSuite, Testcase testcase) throws ParserSerializerTestsuiteException { ObjectMapper mapper = new XmlMapper().enableDefaultTyping().registerModule(new TestSuiteMappingModule()); - ReadBuffer readBuffer = new ReadBuffer(testcase.getRaw(), testSuite.isLittleEndian()); + ReadBufferByteBased readBuffer = new ReadBufferByteBased(testcase.getRaw(), testSuite.isLittleEndian()); String referenceXml = testcase.getXml().elements().get(0).asXML(); MessageIO messageIO = getMessageIOForTestcase(testcase); @@ -141,7 +141,7 @@ public class ParserSerializerTestsuiteRunner extends XmlTestsuiteRunner { System.out.println(xmlString); throw new ParserSerializerTestsuiteException("Differences were found after parsing.\n" + diff.toString()); } - WriteBuffer writeBuffer = new WriteBuffer(((Message) msg).getLengthInBytes(), testSuite.isLittleEndian()); + WriteBufferByteBased writeBuffer = new WriteBufferByteBased(((Message) msg).getLengthInBytes(), testSuite.isLittleEndian()); messageIO.serialize(writeBuffer, msg); byte[] data = writeBuffer.getData(); if (testcase.getRaw().length != data.length) {
