aboutsummaryrefslogtreecommitdiff
path: root/src/leb128.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/leb128.c')
-rw-r--r--src/leb128.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/leb128.c b/src/leb128.c
new file mode 100644
index 0000000..14b7967
--- /dev/null
+++ b/src/leb128.c
@@ -0,0 +1,61 @@
+#include <leb128.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+/* The functions below are (somewhat heavily) modified versions of those
+ * provided by the wac project: https://github.com/kanaka/wac */
+
+/*
+ * Copyright (C) Joel Martin <github@martintribe.org>
+ * The wac project is licensed under the MPL 2.0 (Mozilla Public License
+ * 2.0). The text of the MPL 2.0 license is included below and can be
+ * found at https://www.mozilla.org/MPL/2.0/
+ */
+
+static int read_LEB(FILE *const f, const unsigned maxbits,
+ const bool sign, unsigned long long *const out)
+{
+ unsigned long long result = 0;
+ unsigned shift = 0, bcnt = 0;
+ uint8_t byte;
+
+ for (;;)
+ {
+ if (!fread(&byte, sizeof byte, 1, f))
+ return -1;
+
+ result |= (unsigned long long)(byte & 0x7f) << shift;
+ shift += 7;
+
+ if (!(byte & 0x80))
+ break;
+ else if (++bcnt > (maxbits + 7 - 1) / 7)
+ {
+ fprintf(stderr, "%s: overflow\n", __func__);
+ return -1;
+ }
+ }
+
+ if (sign && (shift < maxbits) && (byte & 0x40))
+ result |= -1ll << shift;
+
+ *out = result;
+ return 0;
+}
+
+int leb128_read_unsigned(FILE *const f, const unsigned maxbits,
+ unsigned long long *const out)
+{
+ return read_LEB(f, maxbits, false, out);
+}
+
+int leb128_read_signed(FILE *const f, const unsigned maxbits,
+ long long *const out)
+{
+ unsigned long long value;
+ const int ret = read_LEB(f, maxbits, true, &value);
+
+ *out = value;
+ return ret;
+}