From 904834a66fa447fb9d80655f5c74b958d38f5854 Mon Sep 17 00:00:00 2001 From: Christofer Dutz Date: Fri, 14 Jun 2024 17:43:47 +0200 Subject: [PATCH] chore: Reverted the changes of PR #1632 as it had severe side-effects. --- .../java/modbus/types/ModbusByteOrder.java | 31 ++++++++ .../java/modbus}/utils/ByteOrderUtils.java | 33 ++++---- .../java/modbus/utils/ByteOrderUtilsTest.java | 79 +++++++++++++++++++ .../plc4x/java/spi/generation/ByteOrder.java | 9 +-- .../spi/generation/ReadBufferByteBased.java | 67 ++++------------ .../spi/generation/WriteBufferByteBased.java | 53 ++----------- 6 files changed, 151 insertions(+), 121 deletions(-) create mode 100644 plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java rename plc4j/{spi/src/main/java/org/apache/plc4x/java/spi => drivers/modbus/src/main/java/org/apache/plc4x/java/modbus}/utils/ByteOrderUtils.java (79%) create mode 100644 plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java diff --git a/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java new file mode 100644 index 00000000000..5ed24e339e8 --- /dev/null +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/types/ModbusByteOrder.java @@ -0,0 +1,31 @@ +/* + * 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 + * + * https://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.modbus.types; + +public enum ModbusByteOrder { + //A B C D + BIG_ENDIAN, + //D C B A + LITTLE_ENDIAN, + //B A D C + BIG_ENDIAN_WORD_SWAP, + //C D A B + LITTLE_ENDIAN_WORD_SWAP + +} diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ByteOrderUtils.java b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtils.java similarity index 79% rename from plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ByteOrderUtils.java rename to plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtils.java index f998dff7fb0..ba98349ad0a 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ByteOrderUtils.java +++ b/plc4j/drivers/modbus/src/main/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtils.java @@ -16,53 +16,55 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.plc4x.java.spi.utils; +package org.apache.plc4x.java.modbus.utils; public class ByteOrderUtils { + /** * Byte order is 'A B C D' * @param num int number * @return int number in big endian format */ - public static int BigEndian(int num){ + public static int toBigEndian(int num){ return num; } + /** * Byte order is 'D C B A' * @param num int number * @return int number in little endian format */ - public static int LittleEndian(int num){ + public static int toLittleEndian(int num){ return Integer.reverseBytes(num); } + /** * Byte order is 'B A D C' * @param num int number * @return int number in big endian swap format */ - public static int BigEndianWordSwap(int num){ + public static int toBigEndianWordSwap(int num){ return (num << 16)|(num >>> 16); } + /** * Byte order is 'C D A B' * @param num int number * @return int number in little endian swap format */ - public static int LittleEndianWordSwap(int num){ + public static int toLittleEndianWordSwap(int num){ return ((num&0xff00)>>>8)| ((num<<8)&0xff00)| ((num<<8)&0xff000000)| ((num &0xff000000)>>>8); } - - /** * Byte order is 'A B C D E F G H' * @param num long number * @return long number in big endian format */ - public static long BigEndian(long num){ + public static long toBigEndian(long num){ return num; } @@ -71,7 +73,7 @@ public static long BigEndian(long num){ * @param num long number * @return long number in little endian format */ - public static long LittleEndian(long num){ + public static long toLittleEndian(long num){ return Long.reverseBytes(num); } @@ -80,8 +82,7 @@ public static long LittleEndian(long num){ * @param num long number * @return long number in big endian format */ - public static long BigEndianWordSwap(long num){ - + public static long toBigEndianWordSwap(long num){ return (num & 0x00ff00ff00ff00ffL) << 8 | (num >>> 8) & 0x00ff00ff00ff00ffL; } @@ -90,13 +91,11 @@ public static long BigEndianWordSwap(long num){ * @param num long number * @return long number in little endian format */ - public static long LittleEndianWordSwap(long num){ - + public static long toLittleEndianWordSwap(long num){ return (num & 0xffff000000000000L) >>> 48 | - (num & 0x0000ffff00000000L) >>> 16 | - (num & 0x00000000ffff0000L) << 16 | - (num & 0x000000000000ffffL) << 48; + (num & 0x0000ffff00000000L) >>> 16 | + (num & 0x00000000ffff0000L) << 16 | + (num & 0x000000000000ffffL) << 48; } - } diff --git a/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java new file mode 100644 index 00000000000..6055fafb121 --- /dev/null +++ b/plc4j/drivers/modbus/src/test/java/org/apache/plc4x/java/modbus/utils/ByteOrderUtilsTest.java @@ -0,0 +1,79 @@ +/* + * 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.modbus.utils; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ByteOrderUtilsTest { + + static final int INT_INPUT = 0x01020304; + static final long LONG_INPUT = 0x0102030405060708L; + + @Test + void testIntToBigEndian() { + assertEquals(0x01020304, ByteOrderUtils.toBigEndian(INT_INPUT)); + assertEquals(INT_INPUT, ByteOrderUtils.toBigEndian(ByteOrderUtils.toBigEndian(INT_INPUT))); + } + + @Test + void testIntToLittleEndian() { + assertEquals(0x04030201, ByteOrderUtils.toLittleEndian(INT_INPUT)); + assertEquals(INT_INPUT, ByteOrderUtils.toLittleEndian(ByteOrderUtils.toLittleEndian(INT_INPUT))); + } + + @Test + void testIntToBigEndianWordSwap() { + assertEquals(0x03040102, ByteOrderUtils.toBigEndianWordSwap(INT_INPUT)); + assertEquals(INT_INPUT, ByteOrderUtils.toBigEndianWordSwap(ByteOrderUtils.toBigEndianWordSwap(INT_INPUT))); + } + + @Test + void testIntToLittleEndianWordSwap() { + assertEquals(0x02010403, ByteOrderUtils.toLittleEndianWordSwap(INT_INPUT)); + assertEquals(INT_INPUT, ByteOrderUtils.toLittleEndianWordSwap(ByteOrderUtils.toLittleEndianWordSwap(INT_INPUT))); + } + + @Test + void testLongToBigEndian() { + assertEquals(0x0102030405060708L, ByteOrderUtils.toBigEndian(LONG_INPUT)); + assertEquals(LONG_INPUT, ByteOrderUtils.toBigEndian(ByteOrderUtils.toBigEndian(LONG_INPUT))); + } + + @Test + void testLongToLittleEndian() { + assertEquals(0x0807060504030201L, ByteOrderUtils.toLittleEndian(LONG_INPUT)); + assertEquals(LONG_INPUT, ByteOrderUtils.toLittleEndian(ByteOrderUtils.toLittleEndian(LONG_INPUT))); + } + + @Test + void testLongToBigEndianWordSwap() { + assertEquals(0x0201040306050807L, ByteOrderUtils.toBigEndianWordSwap(LONG_INPUT)); + assertEquals(LONG_INPUT, ByteOrderUtils.toBigEndianWordSwap(ByteOrderUtils.toBigEndianWordSwap(LONG_INPUT))); + } + + @Test + void testLongToLittleEndianWordSwap() { + assertEquals(0x0708050603040102L, ByteOrderUtils.toLittleEndianWordSwap(LONG_INPUT)); + assertEquals(LONG_INPUT, ByteOrderUtils.toLittleEndianWordSwap(ByteOrderUtils.toLittleEndianWordSwap(LONG_INPUT))); + } + +} \ No newline at end of file diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ByteOrder.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ByteOrder.java index ec45830132f..f6d23bf803f 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ByteOrder.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ByteOrder.java @@ -19,13 +19,6 @@ package org.apache.plc4x.java.spi.generation; public enum ByteOrder { - //A B C D BIG_ENDIAN, - //D C B A - LITTLE_ENDIAN, - //B A D C - BIG_ENDIAN_WORD_SWAP, - //C D A B - LITTLE_ENDIAN_WORD_SWAP - + LITTLE_ENDIAN } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java index e351d66308a..f6dbffa3856 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java @@ -21,7 +21,6 @@ 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 org.apache.plc4x.java.spi.utils.ByteOrderUtils; import java.io.IOException; import java.math.BigDecimal; @@ -251,16 +250,11 @@ public int readUnsignedInt(String logicalName, int bitLength, WithReaderArgs... } return value; case "default": - switch (byteOrder){ - case LITTLE_ENDIAN: - return ByteOrderUtils.LittleEndian(bi.readInt(true, bitLength)); - case BIG_ENDIAN_WORD_SWAP: - return ByteOrderUtils.BigEndianWordSwap(bi.readInt(true, bitLength)); - case LITTLE_ENDIAN_WORD_SWAP: - return ByteOrderUtils.LittleEndianWordSwap(bi.readInt(true, bitLength)); - default: - return ByteOrderUtils.BigEndian(bi.readInt(true, bitLength)); + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + final int longValue = bi.readInt(true, bitLength); + return Integer.reverseBytes(longValue) >>> (32 - bitLength); } + return bi.readInt(true, bitLength); default: throw new ParseException("unsupported encoding '" + encoding + "'"); } @@ -309,17 +303,11 @@ public long readUnsignedLong(String logicalName, int bitLength, WithReaderArgs.. } return value; case "default": - final long longValue = bi.readLong(true, bitLength); - switch (byteOrder){ - case LITTLE_ENDIAN: - return ByteOrderUtils.LittleEndian(longValue); - case BIG_ENDIAN_WORD_SWAP: - return ByteOrderUtils.BigEndianWordSwap(longValue); - case LITTLE_ENDIAN_WORD_SWAP: - return ByteOrderUtils.LittleEndianWordSwap(longValue); - default: - return ByteOrderUtils.BigEndian(longValue); + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + final long longValue = bi.readLong(true, bitLength); + return Long.reverseBytes(longValue) >>> 32; } + return bi.readLong(true, bitLength); default: throw new ParseException("unsupported encoding '" + encoding + "'"); } @@ -371,20 +359,9 @@ public BigInteger readUnsignedBigInteger(String logicalName, int bitLength, With case "default": // Read as signed value long val = bi.readLong(false, bitLength); - switch (byteOrder){ - case LITTLE_ENDIAN: - val = ByteOrderUtils.LittleEndian(val); - break; - case BIG_ENDIAN_WORD_SWAP: - val = ByteOrderUtils.BigEndianWordSwap(val); - break; - case LITTLE_ENDIAN_WORD_SWAP: - val = ByteOrderUtils.LittleEndianWordSwap(val); - break; - default: - break; + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + val = Long.reverseBytes(val); } - if (val >= 0) { return BigInteger.valueOf(val); } else { @@ -441,16 +418,10 @@ public int readInt(String logicalName, int bitLength, WithReaderArgs... readerAr throw new ParseException("int can only contain max 32 bits"); } try { - switch (byteOrder){ - case LITTLE_ENDIAN: - return ByteOrderUtils.LittleEndian(bi.readInt(false, bitLength)); - case BIG_ENDIAN_WORD_SWAP: - return ByteOrderUtils.BigEndianWordSwap(bi.readInt(false, bitLength)); - case LITTLE_ENDIAN_WORD_SWAP: - return ByteOrderUtils.LittleEndianWordSwap(bi.readInt(false, bitLength)); - default: - return ByteOrderUtils.BigEndian(bi.readInt(false, bitLength)); + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + return Integer.reverseBytes(bi.readInt(false, bitLength)); } + return bi.readInt(false, bitLength); } catch (IOException e) { throw new ParseException("Error reading signed int", e); } @@ -465,16 +436,10 @@ public long readLong(String logicalName, int bitLength, WithReaderArgs... reader throw new ParseException("long can only contain max 64 bits"); } try { - switch (byteOrder){ - case LITTLE_ENDIAN: - return ByteOrderUtils.LittleEndian(bi.readLong(false, bitLength)); - case BIG_ENDIAN_WORD_SWAP: - return ByteOrderUtils.BigEndianWordSwap(bi.readLong(false, bitLength)); - case LITTLE_ENDIAN_WORD_SWAP: - return ByteOrderUtils.LittleEndianWordSwap(bi.readLong(false, bitLength)); - default: - return ByteOrderUtils.BigEndian(bi.readLong(false, bitLength)); + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + return Long.reverseBytes(bi.readLong(false, bitLength)); } + return bi.readLong(false, bitLength); } catch (IOException e) { throw new ParseException("Error reading signed long", e); } diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java index 1a4ead2a7c5..7b0bd65e2f1 100644 --- a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java +++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/WriteBufferByteBased.java @@ -21,7 +21,6 @@ import com.github.jinahya.bit.io.BufferByteOutput; import org.apache.commons.lang3.ArrayUtils; import org.apache.plc4x.java.spi.generation.io.MyDefaultBitOutput; -import org.apache.plc4x.java.spi.utils.ByteOrderUtils; import java.math.BigDecimal; import java.math.BigInteger; @@ -228,17 +227,8 @@ public void writeUnsignedInt(String logicalName, int bitLength, int value, WithW break; } case "default": - switch (byteOrder){ - case LITTLE_ENDIAN: - value = ByteOrderUtils.LittleEndian(value); - break; - case BIG_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.BigEndianWordSwap(value); - break; - case LITTLE_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.LittleEndianWordSwap(value); - break; - default: + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + value = Integer.reverseBytes(value) >> (32 - bitLength); } bo.writeInt(true, bitLength, value); break; @@ -295,17 +285,8 @@ public void writeUnsignedLong(String logicalName, int bitLength, long value, Wit break; } case "default": - switch (byteOrder){ - case LITTLE_ENDIAN: - value = ByteOrderUtils.LittleEndian(value); - break; - case BIG_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.BigEndianWordSwap(value); - break; - case LITTLE_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.LittleEndianWordSwap(value); - break; - default: + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + value = Long.reverseBytes(value) >> 32; } bo.writeLong(true, bitLength, value); break; @@ -389,17 +370,8 @@ public void writeInt(String logicalName, int bitLength, int value, WithWriterArg throw new SerializationException("int can only contain max 32 bits"); } try { - switch (byteOrder){ - case LITTLE_ENDIAN: - value = ByteOrderUtils.LittleEndian(value); - break; - case BIG_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.BigEndianWordSwap(value); - break; - case LITTLE_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.LittleEndianWordSwap(value); - break; - default: + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + value = Integer.reverseBytes(value); } bo.writeInt(false, bitLength, value); } catch (Exception e) { @@ -416,17 +388,8 @@ public void writeLong(String logicalName, int bitLength, long value, WithWriterA throw new SerializationException("long can only contain max 64 bits"); } try { - switch (byteOrder){ - case LITTLE_ENDIAN: - value = ByteOrderUtils.LittleEndian(value); - break; - case BIG_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.BigEndianWordSwap(value); - break; - case LITTLE_ENDIAN_WORD_SWAP: - value = ByteOrderUtils.LittleEndianWordSwap(value); - break; - default: + if (byteOrder == ByteOrder.LITTLE_ENDIAN) { + value = Long.reverseBytes(value); } bo.writeLong(false, bitLength, value); } catch (Exception e) {