You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2024/06/14 13:59:11 UTC
(plc4x) branch develop updated: add support for Modbus BIG_ENDIAN_WORD_SWAP and LITTLE_ENDIAN_WORD_SWAP (#1632)
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/develop by this push:
new a864274606 add support for Modbus BIG_ENDIAN_WORD_SWAP and LITTLE_ENDIAN_WORD_SWAP (#1632)
a864274606 is described below
commit a864274606e3b503ca2273b84fff0e898271b33c
Author: StrawberryBlue <64...@users.noreply.github.com>
AuthorDate: Fri Jun 14 21:59:07 2024 +0800
add support for Modbus BIG_ENDIAN_WORD_SWAP and LITTLE_ENDIAN_WORD_SWAP (#1632)
modbus support BIG_ENDIAN_WORD_SWAP
modbus support LITTLE_ENDIAN_WORD_SWAP
---
.../plc4x/java/spi/generation/ByteOrder.java | 9 ++-
.../java/spi/generation/ReadBufferByteBased.java | 67 ++++++++++++-----
.../java/spi/generation/WriteBufferByteBased.java | 53 +++++++++++---
.../plc4x/java/spi/utils/ByteOrderUtils.java | 84 ++++++++++++++++++++++
4 files changed, 188 insertions(+), 25 deletions(-)
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 f6d23bf803..ec45830132 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,6 +19,13 @@
package org.apache.plc4x.java.spi.generation;
public enum ByteOrder {
+ //A B C D
BIG_ENDIAN,
- LITTLE_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/generation/ReadBufferByteBased.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/generation/ReadBufferByteBased.java
index f6dbffa385..e351d66308 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,6 +21,7 @@ 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 org.apache.plc4x.java.spi.utils.ByteOrderUtils;
import java.io.IOException;
import java.math.BigDecimal;
@@ -250,11 +251,16 @@ public class ReadBufferByteBased implements ReadBuffer, BufferCommons {
}
return value;
case "default":
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- final int longValue = bi.readInt(true, bitLength);
- return Integer.reverseBytes(longValue) >>> (32 - bitLength);
+ 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));
}
- return bi.readInt(true, bitLength);
default:
throw new ParseException("unsupported encoding '" + encoding + "'");
}
@@ -303,11 +309,17 @@ public class ReadBufferByteBased implements ReadBuffer, BufferCommons {
}
return value;
case "default":
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- final long longValue = bi.readLong(true, bitLength);
- return Long.reverseBytes(longValue) >>> 32;
+ 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);
}
- return bi.readLong(true, bitLength);
default:
throw new ParseException("unsupported encoding '" + encoding + "'");
}
@@ -359,9 +371,20 @@ public class ReadBufferByteBased implements ReadBuffer, BufferCommons {
case "default":
// Read as signed value
long val = bi.readLong(false, bitLength);
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- val = Long.reverseBytes(val);
+ 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 (val >= 0) {
return BigInteger.valueOf(val);
} else {
@@ -418,10 +441,16 @@ public class ReadBufferByteBased implements ReadBuffer, BufferCommons {
throw new ParseException("int can only contain max 32 bits");
}
try {
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- return Integer.reverseBytes(bi.readInt(false, bitLength));
+ 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));
}
- return bi.readInt(false, bitLength);
} catch (IOException e) {
throw new ParseException("Error reading signed int", e);
}
@@ -436,10 +465,16 @@ public class ReadBufferByteBased implements ReadBuffer, BufferCommons {
throw new ParseException("long can only contain max 64 bits");
}
try {
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- return Long.reverseBytes(bi.readLong(false, bitLength));
+ 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));
}
- 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 7b0bd65e2f..1a4ead2a7c 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,6 +21,7 @@ package org.apache.plc4x.java.spi.generation;
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;
@@ -227,8 +228,17 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
break;
}
case "default":
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- value = Integer.reverseBytes(value) >> (32 - bitLength);
+ 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:
}
bo.writeInt(true, bitLength, value);
break;
@@ -285,8 +295,17 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
break;
}
case "default":
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- value = Long.reverseBytes(value) >> 32;
+ 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:
}
bo.writeLong(true, bitLength, value);
break;
@@ -370,8 +389,17 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
throw new SerializationException("int can only contain max 32 bits");
}
try {
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- value = Integer.reverseBytes(value);
+ 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:
}
bo.writeInt(false, bitLength, value);
} catch (Exception e) {
@@ -388,8 +416,17 @@ public class WriteBufferByteBased implements WriteBuffer, BufferCommons {
throw new SerializationException("long can only contain max 64 bits");
}
try {
- if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
- value = Long.reverseBytes(value);
+ 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:
}
bo.writeLong(false, bitLength, value);
} catch (Exception e) {
diff --git a/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ByteOrderUtils.java b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ByteOrderUtils.java
new file mode 100644
index 0000000000..6d2c30756d
--- /dev/null
+++ b/plc4j/spi/src/main/java/org/apache/plc4x/java/spi/utils/ByteOrderUtils.java
@@ -0,0 +1,84 @@
+package org.apache.plc4x.java.spi.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){
+ 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){
+ 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){
+ 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){
+ 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){
+ return num;
+ }
+
+ /**
+ * Byte order is 'H G F E D C B A'
+ * @param num long number
+ * @return long number in little endian format
+ */
+ public static long LittleEndian(long num){
+ return Long.reverseBytes(num);
+ }
+
+ /**
+ * Byte order is 'B A D C F E H G'
+ * @param num long number
+ * @return long number in big endian format
+ */
+ public static long BigEndianWordSwap(long num){
+
+ return (num & 0x00ff00ff00ff00ffL) << 8 | (num >>> 8) & 0x00ff00ff00ff00ffL;
+ }
+
+ /**
+ * Byte order is 'G H E F C D A B'
+ * @param num long number
+ * @return long number in little endian format
+ */
+ public static long LittleEndianWordSwap(long num){
+
+ return (num & 0xffff000000000000L) >>> 48 |
+ (num & 0x0000ffff00000000L) >>> 16 |
+ (num & 0x00000000ffff0000L) << 16 |
+ (num & 0x000000000000ffffL) << 48;
+ }
+
+
+}