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 382962b  - Fixed a bug not propagating the positive or negative values 
when reading fractions of a short, int or long.
382962b is described below

commit 382962b22b4dbb0b02e117c379bff9635bd7cc7d
Author: Christofer Dutz <[email protected]>
AuthorDate: Wed Jul 8 15:01:32 2020 +0200

    - Fixed a bug not propagating the positive or negative values when reading 
fractions of a short, int or long.
---
 sandbox/plc4c/spi/src/read_buffer.c       | 104 +++++++++++++++++++++++++++---
 sandbox/plc4c/spi/test/read_buffer_test.c |  42 +++++++++++-
 2 files changed, 137 insertions(+), 9 deletions(-)

diff --git a/sandbox/plc4c/spi/src/read_buffer.c 
b/sandbox/plc4c/spi/src/read_buffer.c
index 3be5fd8..8c87f9a 100644
--- a/sandbox/plc4c/spi/src/read_buffer.c
+++ b/sandbox/plc4c/spi/src/read_buffer.c
@@ -206,17 +206,29 @@ plc4c_return_code plc4c_spi_read_unsigned_bits_internal(
 }
 
 bool plc4c_spi_read_buffer_is_negative_internal(uint8_t num_bits, int8_t 
value) {
-  int8_t tmp_value = value >> (num_bits - 1);
+  int8_t tmp_value = value >> num_bits;
   return (tmp_value & 1) != 0;
 }
 
-plc4c_return_code plc4c_spi_fill_sign_internal(uint8_t num_bits, int8_t* 
value) {
-  if(plc4c_spi_read_buffer_is_negative_internal(num_bits, *value)) {
+bool plc4c_spi_fill_sign_internal(uint8_t num_bits, int8_t* value) {
+  // Find out how many bytes the value has.
+  uint8_t num_bytes_total = (num_bits / 8) + ((num_bits % 8 != 0) ? 1 : 0);
+
+  // If this is big endian, go to the highest level byte.
+  if (!plc4c_is_bigendian()) {
+    value = value + (num_bytes_total - 1);
+  }
+
+  if(plc4c_spi_read_buffer_is_negative_internal((num_bits - 1) % 8, *value)) {
     // Set all bits above {num_bits} to 1
     int8_t tmp_value = *value;
-    tmp_value = tmp_value | (255 & bit_matrix[num_bits][0]);
+    if(num_bits % 8 != 0) {
+      tmp_value = tmp_value | bit_matrix[7 - (num_bits % 8)][0];
+    }
     *value = tmp_value;
+    return true;
   }
+  return false;
 }
 
 plc4c_return_code plc4c_spi_read_buffer_create(uint8_t* data, uint16_t length,
@@ -405,24 +417,100 @@ uint8_t num_bits) { return OK;
 plc4c_return_code plc4c_spi_read_signed_byte(plc4c_spi_read_buffer* buf,
                                              uint8_t num_bits, int8_t* value) {
   plc4c_return_code res = plc4c_spi_read_unsigned_byte(buf, num_bits, 
(uint8_t*) value);
-  plc4c_spi_fill_sign_internal(num_bits, value);
+  if(res == OK) {
+    plc4c_spi_fill_sign_internal(num_bits, value);
+  }
   return res;
 }
 
 plc4c_return_code plc4c_spi_read_signed_short(plc4c_spi_read_buffer* buf,
                                               uint8_t num_bits,
                                               int16_t* value) {
-  return plc4c_spi_read_unsigned_byte(buf, num_bits, (uint16_t*) value);
+  plc4c_return_code res = plc4c_spi_read_unsigned_short(buf, num_bits, 
(uint16_t*) value);
+  if(res == OK) {
+    if(plc4c_spi_fill_sign_internal(num_bits, (int8_t*) value)) {
+      // Potentially fill all higher level bytes with 255
+      if(num_bits <= 8) {
+        *value = *value | 65280;
+      }
+    } else {
+      // Potentially fill all higher level bytes with 0
+      if(num_bits <= 8) {
+        *value = *value & 255;
+      }
+    }
+  }
+  return res;
 }
 
 plc4c_return_code plc4c_spi_read_signed_int(plc4c_spi_read_buffer* buf,
                                             uint8_t num_bits, int32_t* value) {
-  return plc4c_spi_read_unsigned_byte(buf, num_bits, (uint32_t*) value);
+  plc4c_return_code res = plc4c_spi_read_unsigned_int(buf, num_bits, 
(uint32_t*) value);
+  if(res == OK) {
+    if(plc4c_spi_fill_sign_internal(num_bits, (int8_t*) value)) {
+      // Potentially fill all higher level bytes with 255
+      if(num_bits <= 8) {
+        *value = *value | 4294967040;
+      } else if(num_bits <= 16) {
+        *value = *value | 4294901760;
+      } else if(num_bits <= 24) {
+        *value = *value | 4278190080;
+      }
+    } else {
+      // Potentially fill all higher level bytes with 0
+      if(num_bits <= 8) {
+        *value = *value & 255;
+      } else if(num_bits <= 16) {
+        *value = *value & 65535;
+      } else if(num_bits <= 24) {
+        *value = *value & 16777215;
+      }
+    }
+  }
+  return res;
 }
 
 plc4c_return_code plc4c_spi_read_signed_long(plc4c_spi_read_buffer* buf,
                                              uint8_t num_bits, int64_t* value) 
{
-  return plc4c_spi_read_unsigned_byte(buf, num_bits, (uint64_t*) value);
+  plc4c_return_code res = plc4c_spi_read_unsigned_long(buf, num_bits, 
(uint64_t*) value);
+  if(res == OK) {
+    if(plc4c_spi_fill_sign_internal(num_bits, (int8_t*) value)) {
+      // Potentially fill all higher level bytes with 255
+      if(num_bits <= 8) {
+        *value = *value | 18446744073709551360;
+      } else if(num_bits <= 16) {
+        *value = *value | 18446744073709486080;
+      } else if(num_bits <= 24) {
+        *value = *value | 18446744073692774400;
+      } else if(num_bits <= 32) {
+        *value = *value | 18446744069414584320;
+      } else if(num_bits <= 40) {
+        *value = *value | 18446742974197923840;
+      } else if(num_bits <= 48) {
+        *value = *value | 18446462598732840960;
+      } else if(num_bits <= 56) {
+        *value = *value | 18374686479671623680;
+      }
+    } else {
+      // Potentially fill all higher level bytes with 0
+      if(num_bits <= 8) {
+        *value = *value & 255;
+      } else if(num_bits <= 16) {
+        *value = *value & 65535;
+      } else if(num_bits <= 24) {
+        *value = *value & 16777215;
+      } else if(num_bits <= 32) {
+        *value = *value & 4294967295;
+      } else if(num_bits <= 40) {
+        *value = *value & 1099511627775;
+      } else if(num_bits <= 48) {
+        *value = *value & 281474976710655;
+      } else if(num_bits <= 56) {
+        *value = *value & 72057594037927935;
+      }
+    }
+  }
+  return res;
 }
 
 // TODO: Not sure which type to use in this case ...
diff --git a/sandbox/plc4c/spi/test/read_buffer_test.c 
b/sandbox/plc4c/spi/test/read_buffer_test.c
index 4d5ed64..191377c 100644
--- a/sandbox/plc4c/spi/test/read_buffer_test.c
+++ b/sandbox/plc4c/spi/test/read_buffer_test.c
@@ -441,7 +441,6 @@ void test_plc4c_spi_read_unsigned_long(void) {
   test_plc4c_spi_read_unsigned_long_args("Full long starting at bit 3", 
read_buffer, 61, OK, 72623859790382856);
 }
 
-
 void test_plc4c_spi_read_signed_byte_args(char* message,
                                             plc4c_spi_read_buffer* 
read_buffer, uint8_t num_bits,
                                             plc4c_return_code 
expected_return_code, int8_t expected_value) {
@@ -495,6 +494,46 @@ void test_plc4c_spi_read_signed_byte(void) {
   test_plc4c_spi_read_signed_byte_args("Exceed read-buffer size (Part 2)", 
read_buffer2, 10, OUT_OF_RANGE, -1);
 }
 
+void test_plc4c_spi_read_signed_short_args(char* message,
+                                          plc4c_spi_read_buffer* read_buffer, 
uint8_t num_bits,
+                                          plc4c_return_code 
expected_return_code, int16_t expected_value) {
+  printf("Running read_buffer read_signed_byte test: %s", message);
+
+  int16_t value = -1;
+  plc4c_return_code result =
+      plc4c_spi_read_signed_short(read_buffer, num_bits, &value);
+
+  TEST_ASSERT_EQUAL_INT(expected_return_code, result);
+  TEST_ASSERT_EQUAL_INT(expected_value, value);
+
+  printf(" -> OK\n");
+}
+
+void test_plc4c_spi_read_signed_short(void) {
+  // Prepare input data
+  uint8_t data[] = {255, 214, 3};
+  plc4c_spi_read_buffer* read_buffer;
+  plc4c_spi_read_buffer_create(data, 3, &read_buffer);
+  // Run test
+  // Read all the full bytes
+  test_plc4c_spi_read_signed_short_args("Simple full signed short 1", 
read_buffer, 16, OK, -42);
+
+  // Read the only part of a short (having to fill up 1s)
+  read_buffer->curPosByte = 0;
+  read_buffer->curPosBit = 4;
+  test_plc4c_spi_read_signed_short_args("Simple 12 bit signed short", 
read_buffer, 12, OK, -42);
+
+  // Read an even shorter part of a short (having to fill up even more 1s)
+  read_buffer->curPosByte = 1;
+  read_buffer->curPosBit = 1;
+  test_plc4c_spi_read_signed_short_args("Simple 7 bit signed short", 
read_buffer, 7, OK, -42);
+
+  // Read an even shorter part of a short (This time however the value should
+  // be positive and hence the higher level byte should be filled with 0s)
+  read_buffer->curPosByte = 1;
+  read_buffer->curPosBit = 2;
+  test_plc4c_spi_read_signed_short_args("Simple 6 bit signed short", 
read_buffer, 6, OK, 22);
+}
 
 void test_plc4c_spi_read_buffer(void) {
   test_plc4c_spi_read_buffer_create();
@@ -508,4 +547,5 @@ void test_plc4c_spi_read_buffer(void) {
   test_plc4c_spi_read_unsigned_int();
   test_plc4c_spi_read_unsigned_long();
   test_plc4c_spi_read_signed_byte();
+  test_plc4c_spi_read_signed_short();
 }
\ No newline at end of file

Reply via email to