1 | //===-- sanitizer_leb128.h --------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef SANITIZER_LEB128_H |
10 | #define SANITIZER_LEB128_H |
11 | |
12 | #include "sanitizer_common.h" |
13 | #include "sanitizer_internal_defs.h" |
14 | |
15 | namespace __sanitizer { |
16 | |
17 | template <typename T, typename It> |
18 | It EncodeSLEB128(T value, It begin, It end) { |
19 | bool more; |
20 | do { |
21 | u8 byte = value & 0x7f; |
22 | // NOTE: this assumes that this signed shift is an arithmetic right shift. |
23 | value >>= 7; |
24 | more = !((((value == 0) && ((byte & 0x40) == 0)) || |
25 | ((value == -1) && ((byte & 0x40) != 0)))); |
26 | if (more) |
27 | byte |= 0x80; |
28 | if (UNLIKELY(begin == end)) |
29 | break; |
30 | *(begin++) = byte; |
31 | } while (more); |
32 | return begin; |
33 | } |
34 | |
35 | template <typename T, typename It> |
36 | It DecodeSLEB128(It begin, It end, T* v) { |
37 | T value = 0; |
38 | unsigned shift = 0; |
39 | u8 byte; |
40 | do { |
41 | if (UNLIKELY(begin == end)) |
42 | return begin; |
43 | byte = *(begin++); |
44 | T slice = byte & 0x7f; |
45 | value |= slice << shift; |
46 | shift += 7; |
47 | } while (byte >= 128); |
48 | if (shift < 64 && (byte & 0x40)) |
49 | value |= (-1ULL) << shift; |
50 | *v = value; |
51 | return begin; |
52 | } |
53 | |
54 | template <typename T, typename It> |
55 | It EncodeULEB128(T value, It begin, It end) { |
56 | do { |
57 | u8 byte = value & 0x7f; |
58 | value >>= 7; |
59 | if (value) |
60 | byte |= 0x80; |
61 | if (UNLIKELY(begin == end)) |
62 | break; |
63 | *(begin++) = byte; |
64 | } while (value); |
65 | return begin; |
66 | } |
67 | |
68 | template <typename T, typename It> |
69 | It DecodeULEB128(It begin, It end, T* v) { |
70 | T value = 0; |
71 | unsigned shift = 0; |
72 | u8 byte; |
73 | do { |
74 | if (UNLIKELY(begin == end)) |
75 | return begin; |
76 | byte = *(begin++); |
77 | T slice = byte & 0x7f; |
78 | value += slice << shift; |
79 | shift += 7; |
80 | } while (byte >= 128); |
81 | *v = value; |
82 | return begin; |
83 | } |
84 | |
85 | } // namespace __sanitizer |
86 | |
87 | #endif // SANITIZER_LEB128_H |
88 | |