aboutsummaryrefslogtreecommitdiff
path: root/core/encoding/varint/leb128.odin
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-16 18:14:01 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2022-04-16 18:14:01 +0200
commit6d0ba8d1898adabceafc6a181395f5d158176a04 (patch)
tree0b6e7db592e98f46d87b421974eface1f1e195a9 /core/encoding/varint/leb128.odin
parentb6f3fa6ee1a57058ea189be155839d7c6ab4fd23 (diff)
[LEB128] Add byte-at-a-time ILEB decoder.
Diffstat (limited to 'core/encoding/varint/leb128.odin')
-rw-r--r--core/encoding/varint/leb128.odin42
1 files changed, 28 insertions, 14 deletions
diff --git a/core/encoding/varint/leb128.odin b/core/encoding/varint/leb128.odin
index 4cad1da76..f8fcc7de5 100644
--- a/core/encoding/varint/leb128.odin
+++ b/core/encoding/varint/leb128.odin
@@ -66,32 +66,46 @@ decode_uleb128 :: proc {decode_uleb128_buffer, decode_uleb128_byte}
// Decode a slice of bytes encoding a signed LEB128 integer into value and number of bytes used.
// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
-decode_ileb128 :: proc(buf: []u8) -> (val: i128, size: int, err: Error) {
- shift: uint
-
+decode_ileb128_buffer :: proc(buf: []u8) -> (val: i128, size: int, err: Error) {
if len(buf) == 0 {
return 0, 0, .Buffer_Too_Small
}
for v in buf {
- size += 1
-
- // 18 * 7 bits = 126, which including sign means we can have a 19th byte.
- if size > LEB128_MAX_BYTES || size == LEB128_MAX_BYTES && v > 0x7f {
- return 0, 0, .Value_Too_Large
+ val, size, err = decode_ileb128_byte(v, size, val)
+ if err != .Buffer_Too_Small {
+ return
}
+ }
+
+ if err == .Buffer_Too_Small {
+ val, size = 0, 0
+ }
+ return
+}
- val |= i128(v & 0x7f) << shift
- shift += 7
+// Decode a a signed LEB128 integer into value and number of bytes used, one byte at a time.
+// Returns `size` == 0 for an invalid value, empty slice, or a varint > 18 bytes.
+decode_ileb128_byte :: proc(input: u8, offset: int, accumulator: i128) -> (val: i128, size: int, err: Error) {
+ size = offset + 1
+ shift := uint(offset * 7)
- if v < 128 { break }
+ // 18 * 7 bits = 126, which including sign means we can have a 19th byte.
+ if size > LEB128_MAX_BYTES || size == LEB128_MAX_BYTES && input > 0x7f {
+ return 0, 0, .Value_Too_Large
}
- if buf[size - 1] & 0x40 == 0x40 {
- val |= max(i128) << shift
+ val = accumulator | i128(input & 0x7f) << shift
+
+ if input < 128 {
+ if input & 0x40 == 0x40 {
+ val |= max(i128) << (shift + 7)
+ }
+ return val, size, .None
}
- return
+ return val, size, .Buffer_Too_Small
}
+decode_ileb128 :: proc{decode_ileb128_buffer, decode_ileb128_byte}
// Encode `val` into `buf` as an unsigned LEB128 encoded series of bytes.
// `buf` must be appropriately sized.