aboutsummaryrefslogtreecommitdiff
path: root/src/io/leb128.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/io/leb128.c')
-rw-r--r--src/io/leb128.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/io/leb128.c b/src/io/leb128.c
new file mode 100644
index 0000000..a57d5c7
--- /dev/null
+++ b/src/io/leb128.c
@@ -0,0 +1,47 @@
+/*
+ * nanowasm, a tiny WebAssembly/Wasm interpreter
+ * Copyright (C) 2023-2024 Xavier Del Campo Romero
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include <nanowasm/types.h>
+#include <nanowasm/leb128.h>
+#include <nw/io.h>
+#include <nw/log.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+enum nw_state nwp_leb128(const struct nw_io_cfg *const cfg,
+ struct nw_sm_leb128 *const l, const unsigned maxbits, const bool sign)
+{
+ uint8_t byte;
+
+ for (;;)
+ {
+ const int n = cfg->read(&byte, sizeof byte, cfg->user);
+
+ if (n < 0)
+ return NW_FATAL;
+ else if (!n)
+ return NW_AGAIN;
+
+ l->result |= (unsigned long long)(byte & 0x7f) << l->shift;
+ l->shift += 7;
+
+ if (!(byte & 0x80))
+ break;
+ else if (++l->bcnt > (maxbits + 7u - 1u) / 7u)
+ {
+ LOG("%s: overflow\n", __func__);
+ return NW_FATAL;
+ }
+ }
+
+ if (sign && (l->shift < maxbits) && (byte & 0x40))
+ l->result |= -1ll << l->shift;
+
+ return NW_OK;
+}