aboutsummaryrefslogtreecommitdiff
path: root/src/helper/crc32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/helper/crc32.c')
-rw-r--r--src/helper/crc32.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/helper/crc32.c b/src/helper/crc32.c
new file mode 100644
index 0000000..441a46c
--- /dev/null
+++ b/src/helper/crc32.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/***************************************************************************
+ * Copyright (C) 2013-2014 by Franck Jullien *
+ * elec4fun@gmail.com *
+ * *
+ * Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg *
+ * marian.buschsieweke@ovgu.de *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "crc32.h"
+#include <stdint.h>
+#include <stddef.h>
+
+static uint32_t crc_le_step(uint32_t poly, uint32_t crc, uint32_t data_in,
+ unsigned int data_bits)
+{
+ for (unsigned int i = 0; i < data_bits; i++) {
+ uint32_t d, c;
+ d = ((data_in >> i) & 0x1) ? 0xffffffff : 0;
+ c = (crc & 0x1) ? 0xffffffff : 0;
+ crc = crc >> 1;
+ crc = crc ^ ((d ^ c) & poly);
+ }
+
+ return crc;
+}
+
+uint32_t crc32_le(uint32_t poly, uint32_t seed, const void *_data,
+ size_t data_len)
+{
+ if (((uintptr_t)_data & 0x3) || (data_len & 0x3)) {
+ /* data is unaligned, processing data one byte at a time */
+ const uint8_t *data = _data;
+ for (size_t i = 0; i < data_len; i++)
+ seed = crc_le_step(poly, seed, data[i], 8);
+ } else {
+ /* data is aligned, processing 32 bit at a time */
+ data_len >>= 2;
+ const uint32_t *data = _data;
+ for (size_t i = 0; i < data_len; i++)
+ seed = crc_le_step(poly, seed, data[i], 32);
+ }
+
+ return seed;
+}