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;
+    }
+
+
+}