You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2019/12/12 12:08:43 UTC

[plc4x] branch feature/big_integer_support_on_driver_base created (now cf9a33f)

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a change to branch feature/big_integer_support_on_driver_base
in repository https://gitbox.apache.org/repos/asf/plc4x.git.


      at cf9a33f  first draft of big integer support on driver base java

This branch includes the following new commits:

     new cf9a33f  first draft of big integer support on driver base java

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[plc4x] 01/01: first draft of big integer support on driver base java

Posted by sr...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch feature/big_integer_support_on_driver_base
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit cf9a33fc5c6e982a920bc45efb256dc31e566adb
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Thu Dec 12 13:08:28 2019 +0100

    first draft of big integer support on driver base java
---
 plc4j/utils/driver-base-java/pom.xml               |   6 +
 .../org/apache/plc4x/java/utils/WriteBuffer.java   | 106 ++++++++++----
 .../apache/plc4x/java/utils/WriteBufferTest.java   | 153 +++++++++++++++++++++
 3 files changed, 239 insertions(+), 26 deletions(-)

diff --git a/plc4j/utils/driver-base-java/pom.xml b/plc4j/utils/driver-base-java/pom.xml
index 2adef47..01f6afc 100644
--- a/plc4j/utils/driver-base-java/pom.xml
+++ b/plc4j/utils/driver-base-java/pom.xml
@@ -37,6 +37,12 @@
       <groupId>com.github.jinahya</groupId>
       <artifactId>bit-io</artifactId>
     </dependency>
+
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java b/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
index 8c14102..a0fd385 100644
--- a/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
+++ b/plc4j/utils/driver-base-java/src/main/java/org/apache/plc4x/java/utils/WriteBuffer.java
@@ -59,10 +59,10 @@ public class WriteBuffer {
     }
 
     public void writeUnsignedByte(int bitLength, byte value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("unsigned byte must contain at least 1 bit");
         }
-        if(bitLength > 4) {
+        if (bitLength > 4) {
             throw new ParseException("unsigned byte can only contain max 4 bits");
         }
         try {
@@ -73,10 +73,10 @@ public class WriteBuffer {
     }
 
     public void writeUnsignedShort(int bitLength, short value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("unsigned short must contain at least 1 bit");
         }
-        if(bitLength > 8) {
+        if (bitLength > 8) {
             throw new ParseException("unsigned short can only contain max 8 bits");
         }
         try {
@@ -87,14 +87,14 @@ public class WriteBuffer {
     }
 
     public void writeUnsignedInt(int bitLength, int value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("unsigned int must contain at least 1 bit");
         }
-        if(bitLength > 16) {
+        if (bitLength > 16) {
             throw new ParseException("unsigned int can only contain max 16 bits");
         }
         try {
-            if(!littleEndian) {
+            if (!littleEndian) {
                 value = Integer.reverseBytes(value) >> 16;
             }
             bo.writeInt(true, bitLength, value);
@@ -104,14 +104,14 @@ public class WriteBuffer {
     }
 
     public void writeUnsignedLong(int bitLength, long value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("unsigned long must contain at least 1 bit");
         }
-        if(bitLength > 32) {
+        if (bitLength > 32) {
             throw new ParseException("unsigned long can only contain max 32 bits");
         }
         try {
-            if(!littleEndian) {
+            if (!littleEndian) {
                 value = Long.reverseBytes(value) >> 32;
             }
             bo.writeLong(true, bitLength, value);
@@ -120,15 +120,11 @@ public class WriteBuffer {
         }
     }
 
-    public void writeUnsignedBigInteger(int bitLength, BigInteger value) throws ParseException {
-        throw new UnsupportedOperationException("not implemented yet");
-    }
-
     public void writeByte(int bitLength, byte value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("byte must contain at least 1 bit");
         }
-        if(bitLength > 8) {
+        if (bitLength > 8) {
             throw new ParseException("byte can only contain max 8 bits");
         }
         try {
@@ -139,14 +135,14 @@ public class WriteBuffer {
     }
 
     public void writeShort(int bitLength, short value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("short must contain at least 1 bit");
         }
-        if(bitLength > 16) {
+        if (bitLength > 16) {
             throw new ParseException("short can only contain max 16 bits");
         }
         try {
-            if(!littleEndian) {
+            if (!littleEndian) {
                 value = Short.reverseBytes(value);
             }
             bo.writeShort(false, bitLength, value);
@@ -156,14 +152,14 @@ public class WriteBuffer {
     }
 
     public void writeInt(int bitLength, int value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("int must contain at least 1 bit");
         }
-        if(bitLength > 32) {
+        if (bitLength > 32) {
             throw new ParseException("int can only contain max 32 bits");
         }
         try {
-            if(!littleEndian) {
+            if (!littleEndian) {
                 value = Integer.reverseBytes(value);
             }
             bo.writeInt(false, bitLength, value);
@@ -173,14 +169,14 @@ public class WriteBuffer {
     }
 
     public void writeLong(int bitLength, long value) throws ParseException {
-        if(bitLength <= 0) {
+        if (bitLength <= 0) {
             throw new ParseException("long must contain at least 1 bit");
         }
-        if(bitLength > 64) {
+        if (bitLength > 64) {
             throw new ParseException("long can only contain max 64 bits");
         }
         try {
-            if(!littleEndian) {
+            if (!littleEndian) {
                 value = Long.reverseBytes(value);
             }
             bo.writeLong(false, bitLength, value);
@@ -190,9 +186,67 @@ public class WriteBuffer {
     }
 
     public void writeBigInteger(int bitLength, BigInteger value) throws ParseException {
-        throw new UnsupportedOperationException("not implemented yet");
+        int actualBitLength = value.bitLength();
+        boolean negative = value.compareTo(BigInteger.ZERO) < 0;
+        int bitLengthIncludingPossibleSign = actualBitLength + (negative ? 1 : 0);
+        if (bitLength < bitLengthIncludingPossibleSign) {
+            throw new ParseException("bit length including possible sign " + bitLengthIncludingPossibleSign + " exceeds supplied bit length " + bitLength);
+        }
+        byte[] bytes = value.toByteArray();
+        int remainingBitLength = bitLengthIncludingPossibleSign;
+        try {
+            if (!littleEndian) {
+                // MSB in 0
+                for (int i = 0; i < bytes.length; i++) {
+                    int bitsToWrite = Math.max(Math.min(remainingBitLength, 8), 1);
+                    bo.writeByte(false, bitsToWrite, bytes[i]);
+                    remainingBitLength -= bitsToWrite;
+                }
+            } else {
+                // MSB in bytes.length
+                for (int i = bytes.length - 1; i >= 0; i--) {
+                    int bitsToWrite = Math.max(Math.min(remainingBitLength, 8), 1);
+                    bo.writeByte(false, bitsToWrite, bytes[i]);
+                    remainingBitLength -= bitsToWrite;
+                }
+            }
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
     }
 
+    public void writeUnsignedBigInteger(int bitLength, BigInteger value) throws ParseException {
+        if (value.compareTo(BigInteger.ZERO) < 0) {
+            throw new ParseException("value " + value + " is below 0");
+        }
+        int actualBitLength = value.bitLength();
+        if (bitLength < actualBitLength) {
+            throw new ParseException("bit length" + actualBitLength + " exceeds supplied bit length " + bitLength);
+        }
+        byte[] bytes = value.toByteArray();
+        int remainingBitLength = actualBitLength;
+        try {
+            if (!littleEndian) {
+                // MSB in 0
+                for (int i = 0; i < bytes.length; i++) {
+                    int bitsToWrite = Math.max(Math.min(remainingBitLength, 8), 1);
+                    bo.writeByte(false, bitsToWrite, bytes[i]);
+                    remainingBitLength -= bitsToWrite;
+                }
+            } else {
+                // MSB in bytes.length
+                for (int i = bytes.length - 1; i >= 0; i--) {
+                    int bitsToWrite = Math.max(Math.min(remainingBitLength, 8), 1);
+                    bo.writeByte(false, bitsToWrite, bytes[i]);
+                    remainingBitLength -= bitsToWrite;
+                }
+            }
+        } catch (IOException e) {
+            throw new ParseException("Error reading", e);
+        }
+    }
+
+
     public void writeFloat(int bitLength, float value) throws ParseException {
         throw new UnsupportedOperationException("not implemented yet");
     }
diff --git a/plc4j/utils/driver-base-java/src/test/java/org/apache/plc4x/java/utils/WriteBufferTest.java b/plc4j/utils/driver-base-java/src/test/java/org/apache/plc4x/java/utils/WriteBufferTest.java
new file mode 100644
index 0000000..08ecd77
--- /dev/null
+++ b/plc4j/utils/driver-base-java/src/test/java/org/apache/plc4x/java/utils/WriteBufferTest.java
@@ -0,0 +1,153 @@
+package org.apache.plc4x.java.utils;
+
+import org.apache.commons.io.HexDump;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigInteger;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class WriteBufferTest {
+
+    @Test
+    void getData() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeBit() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeUnsignedByte() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeUnsignedShort() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeUnsignedInt() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeUnsignedLong() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeUnsignedBigInteger() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeByte() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeShort() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeInt() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeLong() {
+        // TODO: implement me
+    }
+
+    @Nested
+    class WriteBigInteger {
+        @Nested
+        class BigEndian {
+
+            @Test
+            void zero() throws Exception {
+                WriteBuffer SUT = new WriteBuffer(1, false);
+                SUT.writeBigInteger(8, BigInteger.ZERO);
+                byte[] data = SUT.getData();
+                System.out.println(toHex(data));
+                // TODO: check right representation
+                assertArrayEquals(new byte[]{0b0000_0000}, data);
+                assertEquals(BigInteger.ZERO, new BigInteger(data));
+            }
+
+            @Test
+            void one() throws Exception {
+                WriteBuffer SUT = new WriteBuffer(1, false);
+                SUT.writeBigInteger(8, BigInteger.ONE);
+                byte[] data = SUT.getData();
+                System.out.println(toHex(data));
+                // TODO: check right representation
+                assertArrayEquals(new byte[]{0b0000_0001}, data);
+                assertEquals(BigInteger.ZERO, new BigInteger(data));
+            }
+
+            @Test
+            void minusOne() throws Exception {
+                WriteBuffer SUT = new WriteBuffer(1, false);
+                SUT.writeBigInteger(8, BigInteger.ZERO.subtract(BigInteger.ONE));
+                byte[] data = SUT.getData();
+                System.out.println(toHex(data));
+                // TODO: check right representation
+                assertArrayEquals(new byte[]{0b0000_0001}, data);
+                assertEquals(BigInteger.ZERO, new BigInteger(data));
+            }
+
+            @Test
+            void minus255() throws Exception {
+                WriteBuffer SUT = new WriteBuffer(1, false);
+                SUT.writeBigInteger(8, BigInteger.valueOf(-255L));
+                byte[] data = SUT.getData();
+                System.out.println(toHex(data));
+                // TODO: check right representation
+                assertArrayEquals(new byte[]{(byte) 0b1000_0000, 0b0000_0001}, data);
+                assertEquals(BigInteger.valueOf(-255L), new BigInteger(data));
+            }
+
+        }
+
+        @Nested
+        class LittleEndian {
+
+            @Test
+            void writeBigInteger_LE() throws Exception {
+                WriteBuffer SUT_LE = new WriteBuffer(8012, true);
+                SUT_LE.writeBigInteger(1, BigInteger.ZERO);
+            }
+        }
+    }
+
+    @Test
+    void writeFloat() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeDouble() {
+        // TODO: implement me
+    }
+
+    @Test
+    void writeBigDecimal() {
+        // TODO: implement me
+    }
+
+    public static String toHex(byte[] bytes) throws Exception {
+        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
+            HexDump.dump(bytes, 0, byteArrayOutputStream, 0);
+            return byteArrayOutputStream.toString();
+        }
+    }
+}
\ No newline at end of file