blob: 876b70fb5bea8b9e86153dca45acc3ac5053b16b [file] [log] [blame]
// Copyright 2017 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 "byte_buffer.h"
namespace btlib {
namespace common {
size_t ByteBuffer::Copy(MutableByteBuffer* out_buffer,
size_t pos,
size_t size) const {
ZX_ASSERT(out_buffer);
ZX_ASSERT_MSG(pos <= this->size(), "invalid offset (pos = %zu)", pos);
size_t write_size = std::min(size, this->size() - pos);
ZX_ASSERT_MSG(write_size <= out_buffer->size(),
"|out_buffer| is not large enough for copy!");
std::memcpy(out_buffer->mutable_data(), data() + pos, write_size);
return write_size;
}
const BufferView ByteBuffer::view(size_t pos, size_t size) const {
ZX_ASSERT_MSG(pos <= this->size(), "invalid offset (pos = %zu)", pos);
return BufferView(data() + pos, std::min(size, this->size() - pos));
}
fxl::StringView ByteBuffer::AsString() const {
return fxl::StringView(reinterpret_cast<const char*>(data()), size());
}
std::string ByteBuffer::ToString() const {
return AsString().ToString();
}
void MutableByteBuffer::Write(const uint8_t* data, size_t size, size_t pos) {
if (!size)
return;
ZX_ASSERT(data);
ZX_ASSERT_MSG(pos <= this->size(),
"invalid offset (pos: %zu, buffer size: %zu", pos,
this->size());
ZX_ASSERT_MSG(size <= this->size() - pos,
"buffer not large enough! (required: %zu, available: %zu)",
size, this->size() - pos);
std::memcpy(mutable_data() + pos, data, size);
}
void MutableByteBuffer::FillWithRandomBytes() {
if (size()) {
zx_cprng_draw(mutable_data(), size());
}
}
MutableBufferView MutableByteBuffer::mutable_view(size_t pos, size_t size) {
ZX_ASSERT_MSG(pos <= this->size(), "invalid offset (pos = %zu)", pos);
return MutableBufferView(mutable_data() + pos,
std::min(size, this->size() - pos));
}
DynamicByteBuffer::DynamicByteBuffer() : buffer_size_(0u) {}
DynamicByteBuffer::DynamicByteBuffer(size_t buffer_size)
: buffer_size_(buffer_size) {
if (buffer_size == 0)
return;
buffer_ = std::make_unique<uint8_t[]>(buffer_size);
// TODO(armansito): For now this is dumb but we should properly handle the
// case when we're out of memory.
ZX_ASSERT_MSG(buffer_.get(), "failed to allocate buffer");
}
DynamicByteBuffer::DynamicByteBuffer(const ByteBuffer& buffer)
: buffer_size_(buffer.size()),
buffer_(buffer.size() ? std::make_unique<uint8_t[]>(buffer.size())
: nullptr) {
ZX_ASSERT_MSG(!buffer_size_ || buffer_.get(),
"|buffer| cannot be nullptr when |buffer_size| is non-zero");
buffer.Copy(this);
}
DynamicByteBuffer::DynamicByteBuffer(size_t buffer_size,
std::unique_ptr<uint8_t[]> buffer)
: buffer_size_(buffer_size), buffer_(std::move(buffer)) {
ZX_ASSERT_MSG(!buffer_size_ || buffer_.get(),
"|buffer| cannot be nullptr when |buffer_size| is non-zero");
}
DynamicByteBuffer::DynamicByteBuffer(DynamicByteBuffer&& other) {
buffer_size_ = other.buffer_size_;
other.buffer_size_ = 0u;
buffer_ = std::move(other.buffer_);
}
DynamicByteBuffer& DynamicByteBuffer::operator=(DynamicByteBuffer&& other) {
buffer_size_ = other.buffer_size_;
other.buffer_size_ = 0u;
buffer_ = std::move(other.buffer_);
return *this;
}
const uint8_t* DynamicByteBuffer::data() const {
return buffer_.get();
}
uint8_t* DynamicByteBuffer::mutable_data() {
return buffer_.get();
}
size_t DynamicByteBuffer::size() const {
return buffer_size_;
}
void DynamicByteBuffer::Fill(uint8_t value) {
memset(buffer_.get(), value, buffer_size_);
}
ByteBuffer::const_iterator DynamicByteBuffer::cbegin() const {
return buffer_.get();
}
ByteBuffer::const_iterator DynamicByteBuffer::cend() const {
return buffer_.get() + buffer_size_;
}
BufferView::BufferView(const ByteBuffer& buffer, size_t size) {
*this = buffer.view(0u, size);
}
BufferView::BufferView(const fxl::StringView& string) {
size_ = string.size();
bytes_ = reinterpret_cast<const uint8_t*>(string.data());
}
BufferView::BufferView(const void* bytes, size_t size)
: size_(size), bytes_(static_cast<const uint8_t*>(bytes)) {
// If |size| non-zero then |bytes| cannot be nullptr.
ZX_ASSERT_MSG(!size_ || bytes_, "|bytes_| cannot be nullptr if |size_| > 0");
}
BufferView::BufferView() : size_(0u), bytes_(nullptr) {}
const uint8_t* BufferView::data() const {
return bytes_;
}
size_t BufferView::size() const {
return size_;
}
ByteBuffer::const_iterator BufferView::cbegin() const {
return bytes_;
}
ByteBuffer::const_iterator BufferView::cend() const {
return bytes_ + size_;
}
MutableBufferView::MutableBufferView(MutableByteBuffer* buffer) {
ZX_ASSERT(buffer);
size_ = buffer->size();
bytes_ = buffer->mutable_data();
}
MutableBufferView::MutableBufferView(void* bytes, size_t size)
: size_(size), bytes_(static_cast<uint8_t*>(bytes)) {
// If |size| non-zero then |bytes| cannot be nullptr.
ZX_ASSERT_MSG(!size_ || bytes_, "|bytes_| cannot be nullptr if |size_| > 0");
}
MutableBufferView::MutableBufferView() : size_(0u), bytes_(nullptr) {}
const uint8_t* MutableBufferView::data() const {
return bytes_;
}
size_t MutableBufferView::size() const {
return size_;
}
ByteBuffer::const_iterator MutableBufferView::cbegin() const {
return bytes_;
}
ByteBuffer::const_iterator MutableBufferView::cend() const {
return bytes_ + size_;
}
uint8_t* MutableBufferView::mutable_data() {
return bytes_;
}
void MutableBufferView::Fill(uint8_t value) {
memset(bytes_, value, size_);
}
} // namespace common
} // namespace btlib