diff options
Diffstat (limited to 'src/io/leb128.c')
| -rw-r--r-- | src/io/leb128.c | 47 |
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; +} |
