blob: 210fc4d6265fdbb18578211d11f0818ab946c565 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <lib/elfldltl/dwarf/encoding.h>
#include <lib/stdcompat/bit.h>
namespace elfldltl::dwarf {
std::optional<Uleb128> Uleb128::Read(cpp20::span<const std::byte> bytes) {
Uleb128 result;
unsigned int shift = 0;
while (!bytes.empty() && shift < 64) [[likely]] {
++result.size_bytes;
const uint8_t byte = static_cast<uint8_t>(bytes.front());
result.value |= static_cast<uint64_t>(byte & 0x7f) << shift;
if ((byte & 0x80) == 0) {
return result;
}
bytes = bytes.subspan(1);
shift += 7;
}
return std::nullopt;
}
std::optional<Sleb128> Sleb128::Read(cpp20::span<const std::byte> bytes) {
Sleb128 result;
unsigned int shift = 0;
while (!bytes.empty() && shift < 64) [[likely]] {
++result.size_bytes;
const uint8_t byte = static_cast<uint8_t>(bytes.front());
result.value |= cpp20::bit_cast<int64_t>(static_cast<uint64_t>(byte & 0x7f) << shift);
if ((byte & 0x80) == 0) {
// Shift up and then back down to sign-extend.
shift = 64 - (shift + 7);
result.value = (result.value << shift) >> shift;
return result;
}
bytes = bytes.subspan(1);
shift += 7;
}
return std::nullopt;
}
} // namespace elfldltl::dwarf