mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
read bits from base stream
PiperOrigin-RevId: 726515524
This commit is contained in:
committed by
Copybara-Service
parent
00e6b231f6
commit
788984f182
@@ -514,6 +514,7 @@ let package = Package(
|
||||
"internal/platform/feature_flags_test.cc",
|
||||
"internal/platform/cancelable_alarm_test.cc",
|
||||
"internal/platform/crypto_test.cc",
|
||||
"internal/platform/base_input_stream_test.cc",
|
||||
"internal/platform/byte_array_test.cc",
|
||||
"internal/platform/bluetooth_utils_test.cc",
|
||||
"internal/platform/credential_storage_impl_test.cc",
|
||||
|
||||
@@ -397,6 +397,7 @@ cc_test(
|
||||
cc_test(
|
||||
name = "platform_util_test",
|
||||
srcs = [
|
||||
"base_input_stream_test.cc",
|
||||
"byte_utils_test.cc",
|
||||
],
|
||||
deps = [
|
||||
|
||||
@@ -38,6 +38,27 @@ ExceptionOr<ByteArray> BaseInputStream::Read(std::int64_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::uint8_t> BaseInputStream::ReadBits(int bits) {
|
||||
if (bits > 8) {
|
||||
return std::nullopt;
|
||||
}
|
||||
if (bits_unused_ == 0) {
|
||||
if (!IsAvailable(1)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
bits_buffer_ = (uint8_t)buffer_.data()[position_++];
|
||||
bits_unused_ = 8;
|
||||
}
|
||||
if (bits_unused_ < bits) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
uint8_t mask = (1 << bits) - 1;
|
||||
uint8_t value = (bits_buffer_ >> (bits_unused_ - bits)) & mask;
|
||||
bits_unused_ -= bits;
|
||||
return value;
|
||||
}
|
||||
|
||||
std::optional<std::uint8_t> BaseInputStream::ReadUint8() {
|
||||
constexpr int byte_size = sizeof(std::uint8_t);
|
||||
std::optional<ByteArray> read_bytes = ReadBytes(byte_size);
|
||||
@@ -153,6 +174,10 @@ std::optional<std::int64_t> BaseInputStream::ReadInt64() {
|
||||
}
|
||||
|
||||
std::optional<ByteArray> BaseInputStream::ReadBytes(int size) {
|
||||
if (bits_unused_ != 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ExceptionOr<ByteArray> read_bytes_result = Read(size);
|
||||
if (!read_bytes_result.ok()) {
|
||||
return std::nullopt;
|
||||
|
||||
@@ -47,6 +47,9 @@ class BaseInputStream : public InputStream {
|
||||
return {Exception::kSuccess};
|
||||
}
|
||||
|
||||
// Reads less than 8 bits from the stream, returning the value if available.
|
||||
// The read bits cannot across a byte boundary.
|
||||
std::optional<std::uint8_t> ReadBits(int bits);
|
||||
std::optional<std::uint8_t> ReadUint8();
|
||||
std::optional<std::int8_t> ReadInt8();
|
||||
std::optional<std::uint16_t> ReadUint16();
|
||||
@@ -62,6 +65,8 @@ class BaseInputStream : public InputStream {
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t bits_unused_{0};
|
||||
uint8_t bits_buffer_{0};
|
||||
ByteArray &buffer_;
|
||||
size_t position_{0};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "internal/platform/base_input_stream.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace {
|
||||
|
||||
TEST(BaseInputStreamTest, ReadBits) {
|
||||
std::string data{static_cast<char>(0b01011100)};
|
||||
ByteArray byte_array(data);
|
||||
BaseInputStream stream{byte_array};
|
||||
EXPECT_EQ(stream.ReadBits(1), 0);
|
||||
EXPECT_EQ(stream.ReadBits(2), 2);
|
||||
EXPECT_EQ(stream.ReadBits(3), 7);
|
||||
EXPECT_FALSE(stream.ReadBits(5).has_value());
|
||||
EXPECT_EQ(stream.ReadBits(2), 0);
|
||||
EXPECT_FALSE(stream.ReadBits(1).has_value());
|
||||
}
|
||||
|
||||
TEST(BaseInputStreamTest, ReadBitsExceedsByteBoundary) {
|
||||
std::string data = "ab";
|
||||
ByteArray byte_array(data);
|
||||
BaseInputStream stream{byte_array};
|
||||
EXPECT_FALSE(stream.ReadBits(9).has_value());
|
||||
EXPECT_EQ(stream.ReadBits(1), 0);
|
||||
EXPECT_FALSE(stream.ReadInt16().has_value());
|
||||
}
|
||||
|
||||
TEST(BaseInputStreamTest, ReadUintValues) {
|
||||
std::string data = "\xff\xf1\x0f\x0e\x01\x02\x01\x01\x01\x02\x03\x04\x05\x06";
|
||||
ByteArray byte_array(data);
|
||||
BaseInputStream stream{byte_array};
|
||||
EXPECT_EQ(stream.ReadUint16(), 0xfff1);
|
||||
EXPECT_EQ(stream.ReadUint32(), 0x0f0e0102);
|
||||
EXPECT_EQ(stream.ReadUint64(), 0x0101010203040506);
|
||||
}
|
||||
|
||||
TEST(BaseInputStreamTest, ReadIntValues) {
|
||||
std::string data = "\xff\xf1\x0f\x0e\x01\x02\x01\x01\x01\x02\x03\x04\x05\x06";
|
||||
ByteArray byte_array(data);
|
||||
BaseInputStream stream{byte_array};
|
||||
EXPECT_EQ(stream.ReadInt16(), static_cast<int16_t>(0xfff1));
|
||||
EXPECT_EQ(stream.ReadInt32(), static_cast<int32_t>(0x0f0e0102));
|
||||
EXPECT_EQ(stream.ReadInt64(), static_cast<int64_t>(0x0101010203040506));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace nearby
|
||||
Reference in New Issue
Block a user