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