Interactive Bootstraps“Numbers in detail” →Source please

a1e20c78fe50ec48754cfeb8703fad83ad4ffb2b
🐶
Add [u]leb128 implementation

⟨leb128.c⟩≡

@@ -0,0+1,97@@
1
+#include "leb128.h"
2
+
3
+// ceil(sizeof(uintptr_t) * 8 / 7)
4
+// = (sizeof(uintptr_t) * 8 + sizeof(uintptr_t) - 1) / 7
5
+#define MAX_CODES ((sizeof(uintptr_t) * 9 - 1) / 7)
6
+
7
+uint8_t uleb128_bytes(uintptr_t value) {
8
+	int i = 0;
9
+	for (i = 0; i < MAX_CODES; i++) {
10
+		if (value < 128) {
11
+			i++;
12
+			break;
13
+		} else {
14
+			value = value >> 7;
15
+		}
16
+	}
17
+	return i;
18
+}
19
+
20
+uint8_t uleb128_encode(uintptr_t value, uint8_t *data) {
21
+	int i = 0;
22
+	for (i = 0; i < MAX_CODES; i++) {
23
+		if (value < 128) {
24
+			data[i] = value;
25
+			i++;
26
+			break;
27
+		} else {
28
+			data[i] = (value & 127) | 128;
29
+			value = value >> 7;
30
+		}
31
+	}
32
+	return i;
33
+}
34
+
35
+uvalue_size uleb128_decode(uint8_t *data) {
36
+	uvalue_size ret = {.value = 0};
37
+	for (ret.size = 0; ret.size < MAX_CODES; ret.size++) {
38
+		uintptr_t shift = 7 * ret.size;
39
+		uintptr_t continue_bit = 128llu << shift;
40
+		ret.value |= (uintptr_t)data[ret.size] << shift;
41
+		if ((ret.value & continue_bit) == 0) {
42
+			ret.size++;
43
+			break;
44
+		} else {
45
+			ret.value &= ~continue_bit;
46
+		}
47
+	}
48
+	return ret;
49
+}
50
+
51
+uint8_t leb128_bytes(intptr_t value) {
52
+	_Static_assert((-1 >> 1) == -1, "Shift is not arithmetic");
53
+	int i = 0;
54
+	for (i = 0; i < MAX_CODES; i++) {
55
+		if (-64 <= value && value < 64) {
56
+			i++;
57
+			break;
58
+		} else {
59
+			value = value >> 7;
60
+		}
61
+	}
62
+	return i;
63
+}
64
+
65
+uint8_t leb128_encode(intptr_t value, uint8_t *data) {
66
+	_Static_assert((-1 >> 1) == -1, "Shift is not arithmetic");
67
+	int i = 0;
68
+	for (i = 0; i < MAX_CODES; i++) {
69
+		if (-64 <= value && value < 64) {
70
+			data[i] = value & 127;
71
+			i++;
72
+			break;
73
+		} else {
74
+			data[i] = (value & 127) | 128;
75
+			value = value >> 7;
76
+		}
77
+	}
78
+	return i;
79
+}
80
+
81
+value_size leb128_decode(uint8_t *data) {
82
+	value_size ret = {.value = 0};
83
+	for (ret.size = 0; ret.size < MAX_CODES; ret.size++) {
84
+		intptr_t shift = 7 * ret.size;
85
+		intptr_t continue_bit = 128llu << shift;
86
+		ret.value |= (intptr_t)data[ret.size] << shift;
87
+		if ((ret.value & continue_bit) == 0) {
88
+			// Sign extend
89
+			ret.value |= ((ret.value << 1) & continue_bit) * ~0llu;
90
+			ret.size++;
91
+			break;
92
+		} else {
93
+			ret.value &= ~continue_bit;
94
+		}
95
+	}
96
+	return ret;
97
+}