]> sigrok.org Git - libsigrok.git/commitdiff
libsigrok-internal: add endianess helpers for floating point types
authorGerhard Sittig <redacted>
Thu, 11 Jun 2020 15:19:50 +0000 (17:19 +0200)
committerGerhard Sittig <redacted>
Fri, 24 Jul 2020 15:02:40 +0000 (17:02 +0200)
Extend the common set of endianess conversion helpers. Cover readers and
writers for little endian single and double precision and 64bit integer
values, including support to advance the read/write position.

src/libsigrok-internal.h

index de338888582ccc316b3101bdea9454e545c322a7..339c43bcf7c93417f0e83b994d0ff057f53f7634 100644 (file)
@@ -312,7 +312,7 @@ static inline int64_t read_i64le(const uint8_t *p)
 #define RL64S(x) read_i64le((const uint8_t *)(x))
 
 /**
- * Read a 32 bits big endian float out of memory.
+ * Read a 32 bits big endian float out of memory (single precision).
  * @param x a pointer to the input memory
  * @return the corresponding float
  */
@@ -335,7 +335,7 @@ static inline float read_fltbe(const uint8_t *p)
 #define RBFL(x) read_fltbe((const uint8_t *)(x))
 
 /**
- * Read a 32 bits little endian float out of memory.
+ * Read a 32 bits little endian float out of memory (single precision).
  * @param x a pointer to the input memory
  * @return the corresponding float
  */
@@ -357,6 +357,29 @@ static inline float read_fltle(const uint8_t *p)
 }
 #define RLFL(x) read_fltle((const uint8_t *)(x))
 
+/**
+ * Read a 64 bits little endian float out of memory (double precision).
+ * @param x a pointer to the input memory
+ * @return the corresponding floating point value
+ */
+static inline double read_dblle(const uint8_t *p)
+{
+       /*
+        * Implementor's note: Strictly speaking the "union" trick
+        * is not portable. But this phrase was found to work on the
+        * project's supported platforms, and serve well until a more
+        * appropriate phrase is found.
+        */
+       union { uint64_t u64; double flt; } u;
+       double f;
+
+       u.u64 = read_u64le(p);
+       f = u.flt;
+
+       return f;
+}
+#define RLDB(x) read_dblle((const uint8_t *)(x))
+
 /**
  * Write a 8 bits unsigned integer to memory.
  * @param p a pointer to the output memory
@@ -420,6 +443,24 @@ static inline void write_u32le(uint8_t *p, uint32_t x)
 }
 #define WL32(p, x) write_u32le((uint8_t *)(p), (uint32_t)(x))
 
+/**
+ * Write a 64 bits unsigned integer to memory stored as little endian.
+ * @param p a pointer to the output memory
+ * @param x the input unsigned integer
+ */
+static inline void write_u64le(uint8_t *p, uint64_t x)
+{
+       p[0] = x & 0xff; x >>= 8;
+       p[1] = x & 0xff; x >>= 8;
+       p[2] = x & 0xff; x >>= 8;
+       p[3] = x & 0xff; x >>= 8;
+       p[4] = x & 0xff; x >>= 8;
+       p[5] = x & 0xff; x >>= 8;
+       p[6] = x & 0xff; x >>= 8;
+       p[7] = x & 0xff; x >>= 8;
+}
+#define WL64(p, x) write_u64le((uint8_t *)(p), (uint64_t)(x))
+
 /**
  * Write a 32 bits float to memory stored as big endian.
  * @param p a pointer to the output memory
@@ -446,6 +487,19 @@ static inline void write_fltle(uint8_t *p, float x)
 }
 #define WLFL(p, x) write_fltle((uint8_t *)(p), float (x))
 
+/**
+ * Write a 64 bits float to memory stored as little endian.
+ * @param p a pointer to the output memory
+ * @param x the input floating point value
+ */
+static inline void write_dblle(uint8_t *p, double x)
+{
+       union { uint64_t u; double f; } u;
+       u.f = x;
+       write_u64le(p, u.u);
+}
+#define WLDB(p, x) write_dblle((uint8_t *)(p), float (x))
+
 /* Endianess conversion helpers with read/write position increment. */
 
 /**
@@ -584,6 +638,40 @@ static inline uint64_t read_u64le_inc(const uint8_t **p)
        return v;
 }
 
+/**
+ * Read 32bit float from raw memory (little endian format), increment read position.
+ * @param[in, out] p Pointer into byte stream.
+ * @return Retrieved float value.
+ */
+static inline float read_fltle_inc(const uint8_t **p)
+{
+       float v;
+
+       if (!p || !*p)
+               return 0;
+       v = read_fltle(*p);
+       *p += sizeof(v);
+
+       return v;
+}
+
+/**
+ * Read 64bit float from raw memory (little endian format), increment read position.
+ * @param[in, out] p Pointer into byte stream.
+ * @return Retrieved float value.
+ */
+static inline double read_dblle_inc(const uint8_t **p)
+{
+       double v;
+
+       if (!p || !*p)
+               return 0;
+       v = read_dblle(*p);
+       *p += sizeof(v);
+
+       return v;
+}
+
 /**
  * Write unsigned 8bit integer to raw memory, increment write position.
  * @param[in, out] p Pointer into byte stream.
@@ -649,6 +737,45 @@ static inline void write_u32le_inc(uint8_t **p, uint32_t x)
        *p += sizeof(x);
 }
 
+/**
+ * Write unsigned 64bit little endian integer to raw memory, increment write position.
+ * @param[in, out] p Pointer into byte stream.
+ * @param[in] x Value to write.
+ */
+static inline void write_u64le_inc(uint8_t **p, uint64_t x)
+{
+       if (!p || !*p)
+               return;
+       write_u64le(*p, x);
+       *p += sizeof(x);
+}
+
+/**
+ * Write single precision little endian float to raw memory, increment write position.
+ * @param[in, out] p Pointer into byte stream.
+ * @param[in] x Value to write.
+ */
+static inline void write_fltle_inc(uint8_t **p, float x)
+{
+       if (!p || !*p)
+               return;
+       write_fltle(*p, x);
+       *p += sizeof(x);
+}
+
+/**
+ * Write double precision little endian float to raw memory, increment write position.
+ * @param[in, out] p Pointer into byte stream.
+ * @param[in] x Value to write.
+ */
+static inline void write_dblle_inc(uint8_t **p, double x)
+{
+       if (!p || !*p)
+               return;
+       write_dblle(*p, x);
+       *p += sizeof(x);
+}
+
 /* Portability fixes for FreeBSD. */
 #ifdef __FreeBSD__
 #define LIBUSB_CLASS_APPLICATION 0xfe