blob: 965788332e6bbfa3069a21fe2da6c30ab3211d78 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
5#include "wpi/leb128.h"
6
Austin Schuh812d0d12021-11-04 20:16:48 -07007#include "wpi/SpanExtras.h"
Brian Silverman8fce7482020-01-05 13:18:21 -08008#include "wpi/raw_istream.h"
Austin Schuh812d0d12021-11-04 20:16:48 -07009#include "wpi/raw_ostream.h"
10#include "wpi/span.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080011
12namespace wpi {
13
14uint64_t SizeUleb128(uint64_t val) {
15 size_t count = 0;
16 do {
17 val >>= 7;
18 ++count;
19 } while (val != 0);
20 return count;
21}
22
23uint64_t WriteUleb128(SmallVectorImpl<char>& dest, uint64_t val) {
24 size_t count = 0;
25
26 do {
Austin Schuh812d0d12021-11-04 20:16:48 -070027 uint8_t byte = val & 0x7f;
Brian Silverman8fce7482020-01-05 13:18:21 -080028 val >>= 7;
29
Austin Schuh812d0d12021-11-04 20:16:48 -070030 if (val != 0) {
Brian Silverman8fce7482020-01-05 13:18:21 -080031 byte |= 0x80; // mark this byte to show that more bytes will follow
Austin Schuh812d0d12021-11-04 20:16:48 -070032 }
Brian Silverman8fce7482020-01-05 13:18:21 -080033
34 dest.push_back(byte);
35 count++;
36 } while (val != 0);
37
38 return count;
39}
40
Austin Schuh812d0d12021-11-04 20:16:48 -070041void WriteUleb128(raw_ostream& os, uint64_t val) {
42 do {
43 uint8_t byte = val & 0x7f;
44 val >>= 7;
45
46 if (val != 0) {
47 byte |= 0x80; // mark this byte to show that more bytes will follow
48 }
49
50 os << byte;
51 } while (val != 0);
52}
53
Brian Silverman8fce7482020-01-05 13:18:21 -080054uint64_t ReadUleb128(const char* addr, uint64_t* ret) {
55 uint64_t result = 0;
56 int shift = 0;
57 size_t count = 0;
58
59 while (1) {
60 unsigned char byte = *reinterpret_cast<const unsigned char*>(addr);
61 addr++;
62 count++;
63
Austin Schuh812d0d12021-11-04 20:16:48 -070064 result |= (byte & 0x7fULL) << shift;
Brian Silverman8fce7482020-01-05 13:18:21 -080065 shift += 7;
66
Austin Schuh812d0d12021-11-04 20:16:48 -070067 if (!(byte & 0x80)) {
68 break;
69 }
Brian Silverman8fce7482020-01-05 13:18:21 -080070 }
71
72 *ret = result;
73
74 return count;
75}
76
77bool ReadUleb128(raw_istream& is, uint64_t* ret) {
78 uint64_t result = 0;
79 int shift = 0;
80
81 while (1) {
82 unsigned char byte;
83 is.read(reinterpret_cast<char*>(&byte), 1);
Austin Schuh812d0d12021-11-04 20:16:48 -070084 if (is.has_error()) {
85 return false;
86 }
Brian Silverman8fce7482020-01-05 13:18:21 -080087
Austin Schuh812d0d12021-11-04 20:16:48 -070088 result |= (byte & 0x7fULL) << shift;
Brian Silverman8fce7482020-01-05 13:18:21 -080089 shift += 7;
90
Austin Schuh812d0d12021-11-04 20:16:48 -070091 if (!(byte & 0x80)) {
92 break;
93 }
Brian Silverman8fce7482020-01-05 13:18:21 -080094 }
95
96 *ret = result;
97
98 return true;
99}
100
Austin Schuh812d0d12021-11-04 20:16:48 -0700101std::optional<uint64_t> Uleb128Reader::ReadOne(span<const uint8_t>* in) {
102 while (!in->empty()) {
103 uint8_t byte = in->front();
104 *in = wpi::drop_front(*in);
105
106 m_result |= (byte & 0x7fULL) << m_shift;
107 m_shift += 7;
108
109 if (!(byte & 0x80)) {
110 uint64_t result = m_result;
111 m_result = 0;
112 m_shift = 0;
113 return result;
114 }
115 }
116 return std::nullopt;
117}
118
Brian Silverman8fce7482020-01-05 13:18:21 -0800119} // namespace wpi