aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavier.delcampo@orain.io>2020-05-20 14:35:59 +0200
committerXavier Del Campo Romero <xavier.delcampo@orain.io>2020-05-20 14:35:59 +0200
commit9e183ec0a6951723a80e8719525ccdbaecd62e17 (patch)
tree28cfe34fc80c14e66f89df8bbcec8e4ae55c594e
parent71a3db14a5383b73eb719b1d3f479d32fc81ad3a (diff)
64-bit support, C11 as requirement and other improvementsHEADmaster
- C11 support is required (although only on serializer.c, so the check has been moved there) since _Alignof is needed. - Added support for little/big endian 64-bit integers. - swap16, swap32 and swap64 now cast pointers to (uint8_t *) and (const uint8_t *) from the argument list so the explicit casts are no longer needed.
-rw-r--r--README.md24
-rw-r--r--serializer.c122
-rw-r--r--serializer.h4
3 files changed, 96 insertions, 54 deletions
diff --git a/README.md b/README.md
index f3b35ed..1ddfffe 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
-Serializer/deserializer library for C99
+Serializer/deserializer library for C11
=======================================
This library hopes to be useful under certain circumstances where a portable
implementation is desired to read/write data streams yet endianness and
alignment requirements need to be taken into account e.g.: network protocols,
-file formats, etc. As the title specifies, only a C99-compliant compiler is
+file formats, etc. As the title specifies, only a C11-compliant compiler is
required.
-Only 8-bit and 16/32-bit little-endian and big-endian values are supported.
+Only 8-bit and 16/32/64-bit little-endian and big-endian values are supported.
This means no support for bit fields, as some aspects of bit fields are
implementation-defined.
@@ -15,7 +15,7 @@ Usage
------
```{c}
-#include "serializer.h"
+#include <serializer.h>
#include <stdint.h>
#include <stdio.h>
@@ -27,25 +27,27 @@ int main()
uint16_t b;
uint32_t c;
uint16_t d;
+ uint64_t e;
+ uint64_t f;
} ex;
static const uint8_t data[] =
{
- 0x01, 0x33, 0xFF, 0xAC, 0xBB, 0xFA, 0xFA, 0xDE, 0xDE
+ 0x01, 0x33, 0xFF, 0xAC, 0xBB, 0xFA, 0xFA, 0xDE, 0xDD,
+ 0x12, 0x33, 0xFF, 0xAC, 0xBB, 0xFA, 0xFA, 0xDE,
+ 0x12, 0x33, 0xFF, 0xAC, 0xBB, 0xFA, 0xFA, 0xDE,
};
- deserialize("1/le2/be4/be2", &ex, sizeof ex, data, sizeof data);
- printf("a=%X, b=%X, c=%X, d=%X\n",
- ex.a, ex.b, ex.c, ex.d);
+ deserialize("1/le2/be4/be2/be8/le8", &ex, sizeof ex, data, sizeof data);
+ printf("a=%X, b=%X, c=%X, d=%X, e=%lX, f=%lX\n",
+ ex.a, ex.b, ex.c, ex.d, ex.e, ex.f);
return 0;
}
```
Output
------
-`a=1, b=FF33, c=ACBBFAFA, d=DEDE`
+`a=1, b=FF33, c=ACBBFAFA, d=DEDD, e=1233FFACBBFAFADE, f=DEFAFABBACFF3312`
TODO
----
Only deserialization is implemented. Serialization will be implemented in the future.
-
-64-bit support.
diff --git a/serializer.c b/serializer.c
index e094bc0..d108254 100644
--- a/serializer.c
+++ b/serializer.c
@@ -20,6 +20,10 @@
#include <string.h>
#include <stdint.h>
+#if __STDC_VERSION__ < 201112L
+#error C11 support is mandatory for serializer
+#endif
+
static bool little_endian(void)
{
return (const union {char c; int b;}){.c = 1}.b;
@@ -42,6 +46,8 @@ enum token
TOKEN_BE16BIT,
TOKEN_LE32BIT,
TOKEN_BE32BIT,
+ TOKEN_LE64BIT,
+ TOKEN_BE64BIT,
TOKEN_NOT_READY,
TOKEN_ERROR
};
@@ -134,6 +140,22 @@ static enum token get_multibyte(const char c, enum state *const state, enum endi
break;
+ case '8':
+
+ switch (*endianness)
+ {
+ case LITTLE_ENDIAN:
+ return TOKEN_LE64BIT;
+
+ case BIG_ENDIAN:
+ return TOKEN_BE64BIT;
+
+ default:
+ break;
+ }
+
+ break;
+
default:
break;
}
@@ -153,46 +175,72 @@ static enum token get_token(const char c, enum state *const state, enum endianne
return get[*state](c, state, endianness);
}
-static void read8(void *const dst, const void *const src)
+static void read8(void *const dst, const void *const src, const size_t sz)
{
*(uint8_t *)dst = *(const uint8_t *)src;
}
-static void swap32(void *dst, const void *const src)
+static void swap64(uint8_t *dst, const uint8_t *const src)
{
- *(uint8_t *)dst++ = *((const uint8_t *)src + 3);
- *(uint8_t *)dst++ = *((const uint8_t *)src + 2);
- *(uint8_t *)dst++ = *((const uint8_t *)src + 1);
- *(uint8_t *)dst = *(const uint8_t *)src;
+ *dst++ = *(src + 7);
+ *dst++ = *(src + 6);
+ *dst++ = *(src + 5);
+ *dst++ = *(src + 4);
+ *dst++ = *(src + 3);
+ *dst++ = *(src + 2);
+ *dst++ = *(src + 1);
+ *dst = *src;
}
-static void readbe32(void *const dst, const void *const src)
+static void readbe64(void *const dst, const void *const src, const size_t sz)
{
- enum
+ if (little_endian())
{
- SZ = sizeof (uint32_t)
- };
+ swap64(dst, src);
+ }
+ else
+ {
+ memmove(dst, src, sz);
+ }
+}
+static void readle64(void *const dst, const void *const src, const size_t sz)
+{
if (little_endian())
{
- swap32(dst, src);
+ memmove(dst, src, sz);
}
else
{
- memmove(dst, src, SZ);
+ swap64(dst, src);
}
}
-static void readle32(void *const dst, const void *const src)
+static void swap32(uint8_t *dst, const uint8_t *const src)
+{
+ *dst++ = *(src + 3);
+ *dst++ = *(src + 2);
+ *dst++ = *(src + 1);
+ *dst = *src;
+}
+
+static void readbe32(void *const dst, const void *const src, const size_t sz)
{
- enum
+ if (little_endian())
{
- SZ = sizeof (uint32_t)
- };
+ swap32(dst, src);
+ }
+ else
+ {
+ memmove(dst, src, sz);
+ }
+}
+static void readle32(void *const dst, const void *const src, const size_t sz)
+{
if (little_endian())
{
- memmove(dst, src, SZ);
+ memmove(dst, src, sz);
}
else
{
@@ -200,39 +248,29 @@ static void readle32(void *const dst, const void *const src)
}
}
-static void swap16(void *dst, const void *const src)
+static void swap16(uint8_t *dst, const uint8_t *const src)
{
- *(uint8_t *)dst++ = *((const uint8_t *)src + 1);
- *(uint8_t *)dst = *(const uint8_t *)src;
+ *dst++ = *(src + 1);
+ *dst = *src;
}
-static void readbe16(void *const dst, const void *const src)
+static void readbe16(void *const dst, const void *const src, const size_t sz)
{
- enum
- {
- SZ = sizeof (uint16_t)
- };
-
if (little_endian())
{
swap16(dst, src);
}
else
{
- memmove(dst, src, SZ);
+ memmove(dst, src, sz);
}
}
-static void readle16(void *const dst, const void *const src)
+static void readle16(void *const dst, const void *const src, const size_t sz)
{
- enum
- {
- SZ = sizeof (uint16_t)
- };
-
if (little_endian())
{
- memmove(dst, src, SZ);
+ memmove(dst, src, sz);
}
else
{
@@ -271,7 +309,9 @@ enum serializer_err deserialize(const char *format,
[TOKEN_LE16BIT] = sizeof (uint16_t),
[TOKEN_BE16BIT] = sizeof (uint16_t),
[TOKEN_LE32BIT] = sizeof (uint32_t),
- [TOKEN_BE32BIT] = sizeof (uint32_t)
+ [TOKEN_BE32BIT] = sizeof (uint32_t),
+ [TOKEN_LE64BIT] = sizeof (uint64_t),
+ [TOKEN_BE64BIT] = sizeof (uint64_t)
};
static const size_t aligns[] =
@@ -280,16 +320,20 @@ enum serializer_err deserialize(const char *format,
[TOKEN_LE16BIT] = _Alignof (uint16_t),
[TOKEN_BE16BIT] = _Alignof (uint16_t),
[TOKEN_LE32BIT] = _Alignof (uint32_t),
- [TOKEN_BE32BIT] = _Alignof (uint32_t)
+ [TOKEN_BE32BIT] = _Alignof (uint32_t),
+ [TOKEN_LE64BIT] = _Alignof (uint64_t),
+ [TOKEN_BE64BIT] = _Alignof (uint64_t)
};
- static void (*const read[])(void *dst, const void *src) =
+ static void (*const read[])(void *dst, const void *src, size_t sz) =
{
[TOKEN_8BIT] = read8,
[TOKEN_LE16BIT] = readle16,
[TOKEN_BE16BIT] = readbe16,
[TOKEN_LE32BIT] = readle32,
- [TOKEN_BE32BIT] = readbe32
+ [TOKEN_BE32BIT] = readbe32,
+ [TOKEN_LE64BIT] = readle64,
+ [TOKEN_BE64BIT] = readbe64
};
const size_t st = sizes[token];
@@ -304,7 +348,7 @@ enum serializer_err deserialize(const char *format,
return SERIALIZER_ERR_IN_OVERFLOW;
else if (out_sz + st <= sz)
{
- read[token]((uint8_t *)dst + out_sz, (const uint8_t *)src + in_sz);
+ read[token]((uint8_t *)dst + out_sz, (const uint8_t *)src + in_sz, st);
in_sz += st;
out_sz += st;
state = 0;
diff --git a/serializer.h b/serializer.h
index 091e0e8..2e16a7d 100644
--- a/serializer.h
+++ b/serializer.h
@@ -19,10 +19,6 @@
#include <stddef.h>
-#if __STDC_VERSION__ < 199901L
-#error C99 support is mandatory for serializer
-#endif /* __STDC_VERSION < 199901L */
-
#ifdef __cplusplus
extern "C"
{