poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/3] Rewrite ios_write_int and ios_write_uint.


From: Egeyar Bagcioglu
Subject: [PATCH 2/3] Rewrite ios_write_int and ios_write_uint.
Date: Fri, 3 Jan 2020 04:54:53 +0300

2020-01-03 Egeyar Bagcioglu <address@hidden>

        * src/ios.c (IOS_PUT_C_ERR_CHCK): New macro.
        (ios_write_int_fast): New function.
        (ios_write_int_common): Likewise.
        (ios_write_int): Rewrite.
        (ios_write_uint): Rewrite.
---
 ChangeLog |   8 +
 src/ios.c | 743 ++++++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 566 insertions(+), 185 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 19004f17..28a94b36 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2020-01-03 Egeyar Bagcioglu <address@hidden>
+
+       * src/ios.c (IOS_PUT_C_ERR_CHCK): New macro.
+       (ios_write_int_fast): New function.
+       (ios_write_int_common): Likewise.
+       (ios_write_int): Rewrite.
+       (ios_write_uint): Rewrite.
+
 2020-01-03 Egeyar Bagcioglu <address@hidden>
 
        * src/ios.c (ios_mask_first_byte): Replace this function with ...
diff --git a/src/ios.c b/src/ios.c
index db25264f..7e70bed7 100644
--- a/src/ios.c
+++ b/src/ios.c
@@ -40,6 +40,13 @@
   (c) = ret;                                    \
 }
 
+#define IOS_PUT_C_ERR_CHCK(c, io)              \
+{                                              \
+  if (io->dev_if->put_c ((io)->dev, (char)(c)) \
+      == IOD_EOF)                              \
+    return IOS_EIOBJ;                          \
+}
+
 #define IOS_READ_INTO_CHARRAY_1BYTE(charray)           \
 {                                                      \
   IOS_GET_C_ERR_CHCK((charray)[0], io);                        \
@@ -906,6 +913,537 @@ ios_read_string (ios io, ios_off offset, int flags, char 
**value)
   return IOS_OK;
 }
 
+static inline int
+ios_write_int_fast (ios io, int flags,
+                   int bits,
+                   enum ios_endian endian,
+                   uint64_t value)
+{
+  switch (bits)
+    {
+    case 8:
+      IOS_PUT_C_ERR_CHCK(value, io);
+      return IOS_OK;
+
+    case 16:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    case 24:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    case 32:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    case 40:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    case 48:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 40, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 40, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    case 56:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 40, io);
+         IOS_PUT_C_ERR_CHCK(value >> 48, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 48, io);
+         IOS_PUT_C_ERR_CHCK(value >> 40, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    case 64:
+      if (endian == IOS_ENDIAN_LSB)
+       {
+         IOS_PUT_C_ERR_CHCK(value, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 40, io);
+         IOS_PUT_C_ERR_CHCK(value >> 48, io);
+         IOS_PUT_C_ERR_CHCK(value >> 56, io);
+       }
+      else
+       {
+         IOS_PUT_C_ERR_CHCK(value >> 56, io);
+         IOS_PUT_C_ERR_CHCK(value >> 48, io);
+         IOS_PUT_C_ERR_CHCK(value >> 40, io);
+         IOS_PUT_C_ERR_CHCK(value >> 32, io);
+         IOS_PUT_C_ERR_CHCK(value >> 24, io);
+         IOS_PUT_C_ERR_CHCK(value >> 16, io);
+         IOS_PUT_C_ERR_CHCK(value >> 8, io);
+         IOS_PUT_C_ERR_CHCK(value, io);
+       }
+      return IOS_OK;
+
+    default:
+      assert (0);
+      break;
+    }
+}
+
+int
+ios_write_int_common (ios io, ios_off offset, int flags,
+                     int bits,
+                     enum ios_endian endian,
+                     uint64_t value)
+{
+  /* 64 bits might span at most 9 bytes.  */
+  uint64_t c[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+  /* Number of signifcant bits in the first byte.  */
+  int firstbyte_bits = 8 - (offset % 8);
+
+  /* (Total number of bytes that need to be read) - 1.  */
+  int bytes_minus1 = (bits - firstbyte_bits + 7) / 8;
+
+  /* Number of significant bits in the last byte.  */
+  int lastbyte_bits = (bits + (offset % 8)) % 8;
+  lastbyte_bits = lastbyte_bits == 0 ? 8 : lastbyte_bits;
+
+  switch (bytes_minus1)
+  {
+  case 0:
+    {
+      /* We are altering only a single byte.  */
+      uint64_t head, tail;
+      IOS_GET_C_ERR_CHCK(head, io);
+      tail = head;
+      IOS_CHAR_GET_MSB(&head, offset % 8);
+      IOS_CHAR_GET_LSB(&tail, 8 - lastbyte_bits);
+      /* We will write starting from offset / 8.  */
+      if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+       return IOS_EIOFF;
+
+      /* Write the byte back without changing the surrounding bits.  */
+      c[0] = head | tail | (value << (8 - lastbyte_bits));
+      IOS_PUT_C_ERR_CHCK(c[0], io);
+      return IOS_OK;
+    }
+
+  case 1:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB && bits > 8)
+      {
+       /* Convert to the little endian format. For example a 12-bit-long
+          number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+          with leading 0s.  */
+       value = ((value & 0xff) << (bits % 8))
+               | (value & 0xff00) >> 8;
+      }
+    c[0] |= value >> lastbyte_bits;
+    c[1] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    return IOS_OK;
+
+  case 2:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      if (bits <= 16)
+       value = ((value & 0xff) << (bits % 8))
+               | (value & 0xff00) >> 8;
+      else
+       value = ((value & 0xff) << (8 + bits % 8))
+               | (value & 0xff00) >> (8 - bits % 8)
+               | (value & 0xff0000) >> 16;
+    }
+    c[0] |= value >> (8 + lastbyte_bits);
+    c[1] = (value >> lastbyte_bits) & 0xff;
+    c[2] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    return IOS_OK;
+
+  case 3:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      if (bits <= 24)
+       value = ((value & 0xff) << (8 + bits % 8))
+               | (value & 0xff00) >> (8 - bits % 8)
+               | (value & 0xff0000) >> 16;
+      else
+       value = ((value & 0xff) << (16 + bits % 8))
+               | (value & 0xff00) << (bits % 8)
+               | (value & 0xff0000) >> (16 - bits % 8)
+               | (value & 0xff000000) >> 24;
+    }
+    c[0] |= value >> (16 + lastbyte_bits);
+    c[1] = (value >> (8 + lastbyte_bits)) & 0xff;
+    c[2] = (value >> lastbyte_bits) & 0xff;
+    c[3] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    IOS_PUT_C_ERR_CHCK(c[3], io);
+    return IOS_OK;
+
+  case 4:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      if (bits <= 32)
+       value = ((value & 0xff) << (16 + bits % 8))
+               | (value & 0xff00) << (bits % 8)
+               | (value & 0xff0000) >> (16 - bits % 8)
+               | (value & 0xff000000) >> 24;
+      else
+       value = ((value & 0xff) << (24 + bits % 8))
+               | (value & 0xff00) << (8 + bits % 8)
+               | (value & 0xff0000) >> (8 - bits % 8)
+               | (value & 0xff000000) >> (24 - bits % 8)
+               | (value & 0xff00000000) >> 32;
+    }
+    c[0] |= value >> (24 + lastbyte_bits);
+    c[1] = (value >> (16 + lastbyte_bits)) & 0xff;
+    c[2] = (value >> (8 + lastbyte_bits)) & 0xff;
+    c[3] = (value >> lastbyte_bits) & 0xff;
+    c[4] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    IOS_PUT_C_ERR_CHCK(c[3], io);
+    IOS_PUT_C_ERR_CHCK(c[4], io);
+    return IOS_OK;
+
+  case 5:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      if (bits <= 40)
+       value = ((value & 0xff) << (24 + bits % 8))
+               | (value & 0xff00) << (8 + bits % 8)
+               | (value & 0xff0000) >> (8 - bits % 8)
+               | (value & 0xff000000) >> (24 - bits % 8)
+               | (value & 0xff00000000) >> 32;
+      else
+       value = ((value & 0xff) << (32 + bits % 8))
+               | (value & 0xff00) << (16 + bits % 8)
+               | (value & 0xff0000) << (bits % 8)
+               | (value & 0xff000000) >> (16 - bits % 8)
+               | (value & 0xff00000000) >> (32 - bits % 8)
+               | (value & 0xff0000000000) >> 40;
+    }
+    c[0] |= value >> (32 + lastbyte_bits);
+    c[1] = (value >> (24 + lastbyte_bits)) & 0xff;
+    c[2] = (value >> (16 + lastbyte_bits)) & 0xff;
+    c[3] = (value >> (8 + lastbyte_bits)) & 0xff;
+    c[4] = (value >> lastbyte_bits) & 0xff;
+    c[5] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    IOS_PUT_C_ERR_CHCK(c[3], io);
+    IOS_PUT_C_ERR_CHCK(c[4], io);
+    IOS_PUT_C_ERR_CHCK(c[5], io);
+    return IOS_OK;
+
+  case 6:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      if (bits <= 48)
+       value = ((value & 0xff) << (32 + bits % 8))
+               | (value & 0xff00) << (16 + bits % 8)
+               | (value & 0xff0000) << (bits % 8)
+               | (value & 0xff000000) >> (16 - bits % 8)
+               | (value & 0xff00000000) >> (32 - bits % 8)
+               | (value & 0xff0000000000) >> 40;
+      else
+       value = ((value & 0xff) << (40 + bits % 8))
+               | (value & 0xff00) << (24 + bits % 8)
+               | (value & 0xff0000) << (8 + bits % 8)
+               | (value & 0xff000000) >> (8 - bits % 8)
+               | (value & 0xff00000000) >> (24 - bits % 8)
+               | (value & 0xff0000000000) >> (40 - bits % 8)
+               | (value & 0xff000000000000) >> 48;
+    }
+    c[0] |= value >> (40 + lastbyte_bits);
+    c[1] = (value >> (32 + lastbyte_bits)) & 0xff;
+    c[2] = (value >> (24 + lastbyte_bits)) & 0xff;
+    c[3] = (value >> (16 + lastbyte_bits)) & 0xff;
+    c[4] = (value >> (8 + lastbyte_bits)) & 0xff;
+    c[5] = (value >> lastbyte_bits) & 0xff;
+    c[6] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    IOS_PUT_C_ERR_CHCK(c[3], io);
+    IOS_PUT_C_ERR_CHCK(c[4], io);
+    IOS_PUT_C_ERR_CHCK(c[5], io);
+    IOS_PUT_C_ERR_CHCK(c[6], io);
+    return IOS_OK;
+
+  case 7:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      if (bits <= 56)
+       value = ((value & 0xff) << (40 + bits % 8))
+               | (value & 0xff00) << (24 + bits % 8)
+               | (value & 0xff0000) << (8 + bits % 8)
+               | (value & 0xff000000) >> (8 - bits % 8)
+               | (value & 0xff00000000) >> (24 - bits % 8)
+               | (value & 0xff0000000000) >> (40 - bits % 8)
+               | (value & 0xff000000000000) >> 48;
+      else
+       value = ((value & 0xff) << (48 + bits % 8))
+               | (value & 0xff00) << (32 + bits % 8)
+               | (value & 0xff0000) << (16 + bits % 8)
+               | (value & 0xff000000) << (bits % 8)
+               | (value & 0xff00000000) >> (16 - bits % 8)
+               | (value & 0xff0000000000) >> (32 - bits % 8)
+               | (value & 0xff000000000000) >> (48 - bits % 8)
+               | (value & 0xff00000000000000) >> 56;
+    }
+    c[0] |= value >> (48 + lastbyte_bits);
+    c[1] = (value >> (40 + lastbyte_bits)) & 0xff;
+    c[2] = (value >> (32 + lastbyte_bits)) & 0xff;
+    c[3] = (value >> (24 + lastbyte_bits)) & 0xff;
+    c[4] = (value >> (16 + lastbyte_bits)) & 0xff;
+    c[5] = (value >> (8 + lastbyte_bits)) & 0xff;
+    c[6] = (value >> lastbyte_bits) & 0xff;
+    c[7] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    IOS_PUT_C_ERR_CHCK(c[3], io);
+    IOS_PUT_C_ERR_CHCK(c[4], io);
+    IOS_PUT_C_ERR_CHCK(c[5], io);
+    IOS_PUT_C_ERR_CHCK(c[6], io);
+    IOS_PUT_C_ERR_CHCK(c[7], io);
+    return IOS_OK;
+
+  case 8:
+    /* Correctly set the unmodified leading bits of the first byte.  */
+    IOS_GET_C_ERR_CHCK(c[0], io);
+    IOS_CHAR_GET_MSB(&c[0], offset % 8);
+    /* Correctly set the unmodified trailing bits of the last byte.  */
+    if (io->dev_if->seek (io->dev, offset / 8 + bytes_minus1, IOD_SEEK_SET) == 
-1)
+      return IOS_EIOFF;
+    IOS_GET_C_ERR_CHCK(c[bytes_minus1], io);
+    IOS_CHAR_GET_LSB(&c[bytes_minus1], 8 - lastbyte_bits);
+    /* We will write starting from offset / 8.  */
+    if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+      return IOS_EIOFF;
+
+    if (endian == IOS_ENDIAN_LSB)
+    {
+      /* Convert to the little endian format. For example a 12-bit-long
+        number's bits get reordered as 7-6-5-4-3-2-1-0-11-10-9-8
+        with leading 0s.  */
+      value = ((value & 0xff) << (48 + bits % 8))
+             | (value & 0xff00) << (32 + bits % 8)
+             | (value & 0xff0000) << (16 + bits % 8)
+             | (value & 0xff000000) << (bits % 8)
+             | (value & 0xff00000000) >> (16 - bits % 8)
+             | (value & 0xff0000000000) >> (32 - bits % 8)
+             | (value & 0xff000000000000) >> (48 - bits % 8)
+             | (value & 0xff00000000000000) >> 56;
+    }
+    c[0] |= value >> (56 + lastbyte_bits);
+    c[1] = (value >> (48 + lastbyte_bits)) & 0xff;
+    c[2] = (value >> (40 + lastbyte_bits)) & 0xff;
+    c[3] = (value >> (32 + lastbyte_bits)) & 0xff;
+    c[4] = (value >> (24 + lastbyte_bits)) & 0xff;
+    c[5] = (value >> (16 + lastbyte_bits)) & 0xff;
+    c[6] = (value >> (8 + lastbyte_bits)) & 0xff;
+    c[7] = (value >> lastbyte_bits) & 0xff;
+    c[8] |= (value << (8 - lastbyte_bits)) & 0xff;
+    IOS_PUT_C_ERR_CHCK(c[0], io);
+    IOS_PUT_C_ERR_CHCK(c[1], io);
+    IOS_PUT_C_ERR_CHCK(c[2], io);
+    IOS_PUT_C_ERR_CHCK(c[3], io);
+    IOS_PUT_C_ERR_CHCK(c[4], io);
+    IOS_PUT_C_ERR_CHCK(c[5], io);
+    IOS_PUT_C_ERR_CHCK(c[6], io);
+    IOS_PUT_C_ERR_CHCK(c[7], io);
+    IOS_PUT_C_ERR_CHCK(c[8], io);
+    return IOS_OK;
+
+  default:
+    assert(0);
+  }
+}
+
 int
 ios_write_int (ios io, ios_off offset, int flags,
                int bits,
@@ -913,96 +1451,20 @@ ios_write_int (ios io, ios_off offset, int flags,
                enum ios_nenc nenc,
                int64_t value)
 {
-  if (offset % 8 == 0)
-    {
-      if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET)
-          == -1)
-        return IOS_EIOFF;
+  /* We always need to start reading or writing from offset / 8  */
+  if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+    return IOS_EIOFF;
 
-      switch (bits)
-        {
-        case 32:
-          {
-            int32_t c1, c2, c3, c4;
-
-            c1 = (value >> 24) & 0xff;
-            c2 = (value >> 16) & 0xff;
-            c3 = (value >> 8) & 0xff;
-            c4 = value & 0xff;
-
-            if (io->dev_if->put_c (io->dev, c1)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c2)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c3)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c4)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            break;
-          }
-        case 64:
-          {
-            int32_t c1, c2, c3, c4, c5, c6, c7, c8;
-
-            c1 = (value >> 56) & 0xff;
-            c2 = (value >> 48) & 0xff;
-            c3 = (value >> 40) & 0xff;
-            c4 = (value >> 32) & 0xff;
-            c5 = (value >> 24) & 0xff;
-            c6 = (value >> 16) & 0xff;
-            c7 = (value >> 8) & 0xff;
-            c8 = value & 0xff;
-
-            if (io->dev_if->put_c (io->dev, c1)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c2)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c3)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c4)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c5)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c6)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c7)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c8)
-                == IOD_EOF)
-              return IOS_EIOFF;
-            break;
-          }
-        default:
-          assert (0);
-          break;
-        }
-    }
-  else
-    assert (0);
+  /* Fast track for byte-aligned 8x bits  */
+  if (offset % 8 == 0 && bits % 8 == 0)
+    return ios_write_int_fast (io, flags, bits, endian, value);
 
-  return IOS_OK;
+  /* Shift the sign bit right.  */
+  int unused_bits = 64 - bits;
+  uint64_t uvalue = ((uint64_t) (value << unused_bits)) >> unused_bits;
+
+  /* Fall into the case for the unaligned and the sizes other than 8k.  */
+  return ios_write_int_common(io, offset, flags, bits, endian, uvalue);
 }
 
 int
@@ -1011,105 +1473,16 @@ ios_write_uint (ios io, ios_off offset, int flags,
                 enum ios_endian endian,
                 uint64_t value)
 {
-  /* XXX: writeme.  */
-
-
-  if (offset % 8 == 0)
-    {
-      if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET)
-          == -1)
-        return IOS_EIOFF;
-
-      switch (bits)
-        {
-        case 8:
-          if (io->dev_if->put_c (io->dev, (int) value)
-              == IOD_EOF)
-            return IOS_EIOBJ;
-          break;
-        case 32:
-          {
-            int32_t c1, c2, c3, c4;
-
-            c1 = (value >> 24) & 0xff;
-            c2 = (value >> 16) & 0xff;
-            c3 = (value >> 8) & 0xff;
-            c4 = value & 0xff;
-
-            if (io->dev_if->put_c (io->dev, c1)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c2)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c3)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c4)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            break;
-          }
-        case 64:
-          {
-            int32_t c1, c2, c3, c4, c5, c6, c7, c8;
-
-            c1 = (value >> 56) & 0xff;
-            c2 = (value >> 48) & 0xff;
-            c3 = (value >> 40) & 0xff;
-            c4 = (value >> 32) & 0xff;
-            c5 = (value >> 24) & 0xff;
-            c6 = (value >> 16) & 0xff;
-            c7 = (value >> 8) & 0xff;
-            c8 = value & 0xff;
-
-            if (io->dev_if->put_c (io->dev, c1)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c2)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c3)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c4)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c5)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c6)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c7)
-                == IOD_EOF)
-              return IOS_EIOFF;
-
-            if (io->dev_if->put_c (io->dev, c8)
-                == IOD_EOF)
-              return IOS_EIOFF;
-            break;
-          }
-        default:
-          assert (0);
-          break;
-        }
-    }
-  else
-    assert (0);
+  /* We always need to start reading or writing from offset / 8  */
+  if (io->dev_if->seek (io->dev, offset / 8, IOD_SEEK_SET) == -1)
+    return IOS_EIOFF;
 
+  /* Fast track for byte-aligned 8x bits  */
+  if (offset % 8 == 0 && bits % 8 == 0)
+    return ios_write_int_fast (io, flags, bits, endian, value);
 
-  return IOS_OK;
+  /* Fall into the case for the unaligned and the sizes other than 8k.  */
+  return ios_write_int_common(io, offset, flags, bits, endian, value);
 }
 
 int
-- 
2.20.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]