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