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

sruehl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-plc4x.git

commit 0eaa9f953c1f0cf123b7b7f18f262b29d1a844ad
Author: Sebastian Rühl <sru...@apache.org>
AuthorDate: Wed May 30 15:10:32 2018 +0200

    added tests for LittleEndianDecoder/Encoder and fixed some bugs.
---
 .../ads/protocol/util/LittleEndianDecoder.java     | 35 +++++++++-
 .../ads/protocol/util/LittleEndianEncoder.java     | 34 ++++++---
 .../ads/protocol/util/LittleEndianDecoderTest.java | 80 ++++++++++++++++++++++
 .../ads/protocol/util/LittleEndianEncoderTest.java | 57 +++++++++++++++
 4 files changed, 195 insertions(+), 11 deletions(-)

diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
index c66a353..3539be0 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoder.java
@@ -38,6 +38,7 @@ public class LittleEndianDecoder {
         lengthMap.put(Short.class, 2L);
         lengthMap.put(Integer.class, 4L);
         lengthMap.put(Float.class, 4L);
+        lengthMap.put(Double.class, 8L);
         lengthMap.put(Calendar.class, 8L);
         LENGTH_MAP = Collections.unmodifiableMap(lengthMap);
     }
@@ -70,7 +71,10 @@ public class LittleEndianDecoder {
         } else if (datatype == Float.class && length < 4) {
             safeLengthAdsData = new byte[4];
             System.arraycopy(adsData, 0, safeLengthAdsData, 0, length);
-        } else if (datatype == Calendar.class || 
Calendar.class.isAssignableFrom(datatype) && length < 8) {
+        } else if (datatype == Double.class && length < 8) {
+            safeLengthAdsData = new byte[8];
+            System.arraycopy(adsData, 0, safeLengthAdsData, 0, length);
+        } else if ((datatype == Calendar.class || 
Calendar.class.isAssignableFrom(datatype)) && length < 8) {
             safeLengthAdsData = new byte[8];
             System.arraycopy(adsData, 0, safeLengthAdsData, 0, length);
         } else {
@@ -96,6 +100,9 @@ public class LittleEndianDecoder {
             } else if (datatype == Float.class) {
                 decodeFloat(safeLengthAdsData, i, result);
                 i += 4;
+            } else if (datatype == Double.class) {
+                decodeDouble(safeLengthAdsData, i, result);
+                i += 8;
             } else if (datatype == Calendar.class || 
Calendar.class.isAssignableFrom(datatype)) {
                 extractCalendar(safeLengthAdsData, i, result);
                 i += 8;
@@ -106,10 +113,14 @@ public class LittleEndianDecoder {
         return (List<T>) result;
     }
 
-    private static int decodeString(byte[] adsData, int i, int length, 
List<Object> result) {
+    private static int decodeString(byte[] adsData, int i, int length, 
List<Object> result) throws PlcProtocolException {
+        if (length < 2) {
+            throw new PlcProtocolException("String must be a null terminated 
byte array");
+        }
         int pos = i;
         StringBuilder builder = new StringBuilder();
-        while (adsData[pos] != (byte) 0x0 && pos < length) {
+        // TODO: check if we have at least a 0x0 space
+        while (pos < length && adsData[pos] != (byte) 0x0) {
             builder.append((char) adsData[pos]);
             pos++;
         }
@@ -145,6 +156,24 @@ public class LittleEndianDecoder {
         result.add(Float.intBitsToFloat(intValue));
     }
 
+    private static void decodeDouble(byte[] adsData, int i, List<Object> 
result) {
+        byte byteOne = adsData[i];
+        byte byteTwo = adsData[i + 1];
+        byte byteThree = adsData[i + 2];
+        byte byteFour = adsData[i + 3];
+        byte byteFive = adsData[i + 4];
+        byte byteSix = adsData[i + 5];
+        byte byteSeven = adsData[i + 6];
+        byte byteEigth = adsData[i + 7];
+        // TODO: check how ads expects this data
+        // Description of the Real number format:
+        // https://www.sps-lehrgang.de/zahlenformate-step7/#c144
+        // https://de.wikipedia.org/wiki/IEEE_754
+        long longValue = (long) (byteOne & 0xff) | ((long) (byteTwo & 0xff) << 
8) | ((long) (byteThree & 0xff) << 16) | ((long) (byteFour & 0xff) << 24)
+            | (long) (byteFive & 0xff) << 32 | ((long) (byteSix & 0xff) << 40) 
| ((long) (byteSeven & 0xff) << 48) | ((long) (byteEigth & 0xff) << 56);
+        result.add(Double.longBitsToDouble(longValue));
+    }
+
     private static void extractCalendar(byte[] adsData, int i, List<Object> 
result) {
         byte byteOne = adsData[i];
         byte byteTwo = adsData[i + 1];
diff --git 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
index 7ee8cbe..5c75a61 100644
--- 
a/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
+++ 
b/plc4j/protocols/ads/src/main/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoder.java
@@ -39,7 +39,7 @@ public class LittleEndianEncoder {
         // Utility class
     }
 
-    public static byte[] encodeData(Class<?> valueType, Object[] values) 
throws PlcProtocolException {
+    public static byte[] encodeData(Class<?> valueType, Object... values) 
throws PlcProtocolException {
         if (values.length == 0) {
             return new byte[]{};
         }
@@ -56,6 +56,8 @@ public class LittleEndianEncoder {
             result = 
encodeCalendar(Arrays.stream(values).map(Calendar.class::cast));
         } else if (valueType == Float.class) {
             result = encodeFloat(Arrays.stream(values).map(Float.class::cast));
+        } else if (valueType == Double.class) {
+            result = 
encodeDouble(Arrays.stream(values).map(Double.class::cast));
         } else if (valueType == String.class) {
             result = 
encodeString(Arrays.stream(values).map(String.class::cast));
         } else {
@@ -80,7 +82,7 @@ public class LittleEndianEncoder {
         }
     }
 
-    public static Stream<byte[]> encodeString(Stream<String> stringStream) {
+    private static Stream<byte[]> encodeString(Stream<String> stringStream) {
         // TODO: what do we do with utf-8 values with 2 bytes? what is the 
charset here?
         return stringStream
             .map(s -> s.getBytes(Charset.defaultCharset()))
@@ -88,7 +90,7 @@ public class LittleEndianEncoder {
             .map(bytes -> ArrayUtils.add(bytes, (byte) 0x0));
     }
 
-    public static Stream<byte[]> encodeFloat(Stream<Float> floatStream) {
+    private static Stream<byte[]> encodeFloat(Stream<Float> floatStream) {
         return floatStream
             // TODO: check how ads expects this data
             .map(Float::floatToIntBits)
@@ -100,7 +102,23 @@ public class LittleEndianEncoder {
             });
     }
 
-    public static Stream<byte[]> encodeInteger(Stream<Integer> integerStream) {
+    private static Stream<byte[]> encodeDouble(Stream<Double> doubleStream) {
+        return doubleStream
+            // TODO: check how ads expects this data
+            .map(Double::doubleToLongBits)
+            .map(longValue -> new byte[]{
+                (byte) (longValue & 0x00000000_000000ffL),
+                (byte) ((longValue & 0x00000000_0000ff00L) >> 8),
+                (byte) ((longValue & 0x00000000_00ff0000L) >> 16),
+                (byte) ((longValue & 0x00000000_ff000000L) >> 24),
+                (byte) ((longValue & 0x000000ff_00000000L) >> 32),
+                (byte) ((longValue & 0x0000ff00_00000000L) >> 40),
+                (byte) ((longValue & 0x00ff0000_00000000L) >> 48),
+                (byte) ((longValue & 0xff000000_00000000L) >> 56),
+            });
+    }
+
+    private static Stream<byte[]> encodeInteger(Stream<Integer> integerStream) 
{
         return integerStream
             .map(intValue -> new byte[]{
                 (byte) (intValue & 0x000000ff),
@@ -110,7 +128,7 @@ public class LittleEndianEncoder {
             });
     }
 
-    public static Stream<byte[]> encodeCalendar(Stream<Calendar> 
calendarStream) {
+    private static Stream<byte[]> encodeCalendar(Stream<Calendar> 
calendarStream) {
         return calendarStream
             .map(Calendar.class::cast)
             .map(Calendar::getTime)
@@ -132,7 +150,7 @@ public class LittleEndianEncoder {
     }
 
 
-    public static Stream<byte[]> encodeShort(Stream<Short> shortStream) {
+    private static Stream<byte[]> encodeShort(Stream<Short> shortStream) {
         return shortStream
             .map(shortValue -> new byte[]{
                 (byte) (shortValue & 0x00ff),
@@ -140,12 +158,12 @@ public class LittleEndianEncoder {
             });
     }
 
-    public static Stream<byte[]> encodeByte(Stream<Byte> byteStream) {
+    private static Stream<byte[]> encodeByte(Stream<Byte> byteStream) {
         return byteStream
             .map(aByte -> new byte[]{aByte});
     }
 
-    public static Stream<byte[]> encodeBoolean(Stream<Boolean> booleanStream) {
+    private static Stream<byte[]> encodeBoolean(Stream<Boolean> booleanStream) 
{
         return booleanStream
             .map(booleanValue -> new byte[]{booleanValue ? (byte) 0x01 : 
(byte) 0x00});
     }
diff --git 
a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoderTest.java
 
b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoderTest.java
new file mode 100644
index 0000000..c14d5cf
--- /dev/null
+++ 
b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianDecoderTest.java
@@ -0,0 +1,80 @@
+/*
+ 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.ads.protocol.util;
+
+import org.apache.plc4x.java.ads.api.commands.types.Length;
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+
+public class LittleEndianDecoderTest {
+
+    @Test
+    public void getLengthFor() {
+        assertEquals(LittleEndianDecoder.getLengthFor(Boolean.class, 0), 
Length.of(1));
+        assertEquals(LittleEndianDecoder.getLengthFor(Byte.class, 0), 
Length.of(1));
+        assertEquals(LittleEndianDecoder.getLengthFor(Short.class, 0), 
Length.of(2));
+        assertEquals(LittleEndianDecoder.getLengthFor(Integer.class, 0), 
Length.of(4));
+        assertEquals(LittleEndianDecoder.getLengthFor(Float.class, 0), 
Length.of(4));
+        assertEquals(LittleEndianDecoder.getLengthFor(Double.class, 0), 
Length.of(8));
+        assertEquals(LittleEndianDecoder.getLengthFor(Calendar.class, 0), 
Length.of(8));
+        
assertEquals(LittleEndianDecoder.getLengthFor(LittleEndianDecoderTest.class, 
666), Length.of(666));
+    }
+
+    @Test
+    public void decodeData() throws Exception {
+        assertEquals(asList(true, false), 
LittleEndianDecoder.decodeData(Boolean.class, new byte[]{0x1, 0x0}));
+
+        assertEquals(asList((byte) 0x1, (byte) 0x0), 
LittleEndianDecoder.decodeData(Byte.class, new byte[]{0x1, 0x0}));
+
+        assertEquals(singletonList((short) 1), 
LittleEndianDecoder.decodeData(Short.class, new byte[]{0x1}));
+        assertEquals(singletonList((short) 256), 
LittleEndianDecoder.decodeData(Short.class, new byte[]{0x0, 0x1}));
+        assertEquals(asList((short) 256, (short) 256), 
LittleEndianDecoder.decodeData(Short.class, new byte[]{0x0, 0x1, 0x0, 0x1}));
+
+        assertEquals(singletonList(1), 
LittleEndianDecoder.decodeData(Integer.class, new byte[]{0x1}));
+        assertEquals(singletonList(16777216), 
LittleEndianDecoder.decodeData(Integer.class, new byte[]{0x0, 0x0, 0x0, 0x1}));
+        assertEquals(asList(16777216, 16777216), 
LittleEndianDecoder.decodeData(Integer.class, new byte[]{0x0, 0x0, 0x0, 0x1, 
0x0, 0x0, 0x0, 0x1}));
+
+        assertEquals(singletonList(1.4E-45f), 
LittleEndianDecoder.decodeData(Float.class, new byte[]{0x1}));
+        assertEquals(singletonList(2.3509887E-38f), 
LittleEndianDecoder.decodeData(Float.class, new byte[]{0x0, 0x0, 0x0, 0x1}));
+        assertEquals(asList(2.3509887E-38f, 2.3509887E-38f), 
LittleEndianDecoder.decodeData(Float.class, new byte[]{0x0, 0x0, 0x0, 0x1, 0x0, 
0x0, 0x0, 0x1}));
+
+        assertEquals(singletonList(4.9E-324), 
LittleEndianDecoder.decodeData(Double.class, new byte[]{0x1}));
+        assertEquals(singletonList(7.2911220195563975E-304), 
LittleEndianDecoder.decodeData(Double.class, new byte[]{0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x1}));
+        assertEquals(asList(7.2911220195563975E-304, 7.2911220195563975E-304), 
LittleEndianDecoder.decodeData(Double.class, new byte[]{0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}));
+
+        Calendar calendar1 = Calendar.getInstance();
+        calendar1.setTime(new Date(-11644473600000L));
+        assertEquals(singletonList(calendar1), 
LittleEndianDecoder.decodeData(Calendar.class, new byte[]{0x1}));
+        Calendar calendar0x0001 = Calendar.getInstance();
+        calendar0x0001.setTime(new Date(-4438714196208L));
+        assertEquals(singletonList(calendar0x0001), 
LittleEndianDecoder.decodeData(Calendar.class, new byte[]{0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x1}));
+        assertEquals(asList(calendar0x0001, calendar0x0001), 
LittleEndianDecoder.decodeData(Calendar.class, new byte[]{0x0, 0x0, 0x0, 0x0, 
0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1}));
+
+        assertEquals(singletonList("plc4x"), 
LittleEndianDecoder.decodeData(String.class, new byte[]{0x70, 0x6c, 0x63, 0x34, 
0x78, 0x0}));
+        assertEquals(singletonList("plc4xplc4x"), 
LittleEndianDecoder.decodeData(String.class, new byte[]{0x70, 0x6c, 0x63, 0x34, 
0x78, 0x70, 0x6c, 0x63, 0x34, 0x78, 0x0}));
+        assertEquals(asList("plc4x", "plc4x"), 
LittleEndianDecoder.decodeData(String.class, new byte[]{0x70, 0x6c, 0x63, 0x34, 
0x78, 0x0, 0x70, 0x6c, 0x63, 0x34, 0x78, 0x0}));
+    }
+
+}
\ No newline at end of file
diff --git 
a/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoderTest.java
 
b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoderTest.java
new file mode 100644
index 0000000..110fd7c
--- /dev/null
+++ 
b/plc4j/protocols/ads/src/test/java/org/apache/plc4x/java/ads/protocol/util/LittleEndianEncoderTest.java
@@ -0,0 +1,57 @@
+/*
+ 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.ads.protocol.util;
+
+import org.junit.Test;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import static org.apache.plc4x.java.ads.util.Assert.assertByteEquals;
+
+public class LittleEndianEncoderTest {
+
+    @Test
+    public void encodeData() throws Exception {
+        assertByteEquals(new byte[]{0x01, 0x00, 0x01, 0x00}, 
LittleEndianEncoder.encodeData(Boolean.class, true, false, true, false));
+
+        assertByteEquals(new byte[]{0x12, 0x03, 0x05, 0x7f}, 
LittleEndianEncoder.encodeData(Byte.class, (byte) 0x12, (byte) 0x03, (byte) 
0x05, (byte) 0x7f));
+
+        assertByteEquals(new byte[]{0x1, 0x00}, 
LittleEndianEncoder.encodeData(Short.class, (short) 1));
+        assertByteEquals(new byte[]{0x0e, 0x00, 0x50, 0x00}, 
LittleEndianEncoder.encodeData(Short.class, (short) 14, (short) 80));
+
+        assertByteEquals(new byte[]{0x5a, 0x0a, 0x00, 0x00}, 
LittleEndianEncoder.encodeData(Integer.class, 2650));
+        assertByteEquals(new byte[]{0x5a, 0x0a, 0x00, 0x00, 0x50, 0x00, 0x00, 
0x00}, LittleEndianEncoder.encodeData(Integer.class, 2650, 80));
+
+        assertByteEquals(new byte[]{(byte) 0xc3, (byte) 0xf5, 0x48, 0x40}, 
LittleEndianEncoder.encodeData(Float.class, 3.14f));
+        assertByteEquals(new byte[]{(byte) 0xc3, (byte) 0xf5, 0x48, 0x40, 
0x14, (byte) 0xae, 0x07, 0x40}, LittleEndianEncoder.encodeData(Float.class, 
3.14f, 2.12f));
+
+        assertByteEquals(new byte[]{0x1F, (byte) 0x85, (byte) 0xEB, 0x51, 
(byte) 0xB8, 0x1E, 0x09, 0x40}, LittleEndianEncoder.encodeData(Double.class, 
3.14));
+        assertByteEquals(new byte[]{0x1F, (byte) 0x85, (byte) 0xEB, 0x51, 
(byte) 0xB8, 0x1E, 0x09, 0x40, (byte) 0xF6, 0x28, 0x5C, (byte) 0x8F, (byte) 
0xC2, (byte) 0xF5, 0x00, 0x40}, LittleEndianEncoder.encodeData(Double.class, 
3.14, 2.12));
+
+        Calendar calendar1 = Calendar.getInstance();
+        //calendar1.set(2003, Calendar.DECEMBER, 23, 13, 3, 0);
+        calendar1.setTime(new Date(1072180980436L));
+        assertByteEquals(new byte[]{(byte) 0x40, (byte) 0x79, (byte) 0xFB, 
(byte) 0xB5, (byte) 0x4C, (byte) 0xC9, (byte) 0xC3, (byte) 0x01}, 
LittleEndianEncoder.encodeData(Calendar.class, calendar1));
+
+        assertByteEquals(new byte[]{0x70, 0x6c, 0x63, 0x34, 0x78, 0x00}, 
LittleEndianEncoder.encodeData(String.class, "plc4x"));
+        assertByteEquals(new byte[]{0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 
0x72, 0x6c, 0x64, 0x21, 0x00}, LittleEndianEncoder.encodeData(String.class, 
"HelloWorld!"));
+        assertByteEquals(new byte[]{0x70, 0x6c, 0x63, 0x34, 0x78, 0x00, 0x48, 
0x65, 0x6c, 0x6c, 0x6f, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x00}, 
LittleEndianEncoder.encodeData(String.class, "plc4x", "HelloWorld!"));
+    }
+}
\ No newline at end of file

-- 
To stop receiving notification emails like this one, please contact
sru...@apache.org.

Reply via email to