xref: /freebsd/contrib/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_leb128.h (revision 3e8eb5c7f4909209c042403ddee340b2ee7003a5)
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