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
15namespace __sanitizer {
16
17template <typename T, typename It>
18It 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
35template <typename T, typename It>
36It 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
54template <typename T, typename It>
55It 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
68template <typename T, typename It>
69It 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