blob: 17fbeb9d4683c0430b27adda461a0ffbf3d45d5b [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"
Brian Silverman8fce7482020-01-05 13:18:21 -080010
11namespace wpi {
12
13uint64_t SizeUleb128(uint64_t val) {
14 size_t count = 0;
15 do {
16 val >>= 7;
17 ++count;
18 } while (val != 0);
19 return count;
20}
21
22uint64_t WriteUleb128(SmallVectorImpl<char>& dest, uint64_t val) {
23 size_t count = 0;
24
25 do {
Austin Schuh812d0d12021-11-04 20:16:48 -070026 uint8_t byte = val & 0x7f;
Brian Silverman8fce7482020-01-05 13:18:21 -080027 val >>= 7;
28
Austin Schuh812d0d12021-11-04 20:16:48 -070029 if (val != 0) {
Brian Silverman8fce7482020-01-05 13:18:21 -080030 byte |= 0x80; // mark this byte to show that more bytes will follow
Austin Schuh812d0d12021-11-04 20:16:48 -070031 }
Brian Silverman8fce7482020-01-05 13:18:21 -080032
33 dest.push_back(byte);
34 count++;
35 } while (val != 0);
36
37 return count;
38}
39
Austin Schuh812d0d12021-11-04 20:16:48 -070040void WriteUleb128(raw_ostream& os, uint64_t val) {
41 do {
42 uint8_t byte = val & 0x7f;
43 val >>= 7;
44
45 if (val != 0) {
46 byte |= 0x80; // mark this byte to show that more bytes will follow
47 }
48
49 os << byte;
50 } while (val != 0);
51}
52
Brian Silverman8fce7482020-01-05 13:18:21 -080053uint64_t ReadUleb128(const char* addr, uint64_t* ret) {
54 uint64_t result = 0;
55 int shift = 0;
56 size_t count = 0;
57
58 while (1) {
59 unsigned char byte = *reinterpret_cast<const unsigned char*>(addr);
60 addr++;
61 count++;
62
Austin Schuh812d0d12021-11-04 20:16:48 -070063 result |= (byte & 0x7fULL) << shift;
Brian Silverman8fce7482020-01-05 13:18:21 -080064 shift += 7;
65
Austin Schuh812d0d12021-11-04 20:16:48 -070066 if (!(byte & 0x80)) {
67 break;
68 }
Brian Silverman8fce7482020-01-05 13:18:21 -080069 }
70
71 *ret = result;
72
73 return count;
74}
75
76bool ReadUleb128(raw_istream& is, uint64_t* ret) {
77 uint64_t result = 0;
78 int shift = 0;
79
80 while (1) {
81 unsigned char byte;
82 is.read(reinterpret_cast<char*>(&byte), 1);
Austin Schuh812d0d12021-11-04 20:16:48 -070083 if (is.has_error()) {
84 return false;
85 }
Brian Silverman8fce7482020-01-05 13:18:21 -080086
Austin Schuh812d0d12021-11-04 20:16:48 -070087 result |= (byte & 0x7fULL) << shift;
Brian Silverman8fce7482020-01-05 13:18:21 -080088 shift += 7;
89
Austin Schuh812d0d12021-11-04 20:16:48 -070090 if (!(byte & 0x80)) {
91 break;
92 }
Brian Silverman8fce7482020-01-05 13:18:21 -080093 }
94
95 *ret = result;
96
97 return true;
98}
99
James Kuszmaulcf324122023-01-14 14:07:17 -0800100std::optional<uint64_t> Uleb128Reader::ReadOne(std::span<const uint8_t>* in) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700101 while (!in->empty()) {
102 uint8_t byte = in->front();
103 *in = wpi::drop_front(*in);
104
105 m_result |= (byte & 0x7fULL) << m_shift;
106 m_shift += 7;
107
108 if (!(byte & 0x80)) {
109 uint64_t result = m_result;
110 m_result = 0;
111 m_shift = 0;
112 return result;
113 }
114 }
115 return std::nullopt;
116}
117
Brian Silverman8fce7482020-01-05 13:18:21 -0800118} // namespace wpi