blob: 533a920ef12fa7f8584ce05eb2dbab850a230914 [file] [log] [blame]
// Copyright 2019 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.
// -----------------------------------------------------------------------------
//
// DataSource implementation.
//
// Author: Yannis Guyon (yguyon@google.com)
#include "src/utils/data_source.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
namespace WP2 {
//------------------------------------------------------------------------------
bool DataSource::TryGetNext(size_t num_bytes, const uint8_t** data_pointer) {
if (num_bytes > GetNumNextBytes()) {
if (!Fetch(num_bytes)) return false;
// Fetch must return false if there isn't enough data.
assert(num_bytes <= GetNumNextBytes());
}
assert(data_pointer != nullptr);
*data_pointer = available_bytes_ + num_read_bytes_;
return true;
}
size_t DataSource::GetNumNextBytes() const {
return num_available_bytes_ - std::min(num_available_bytes_, num_read_bytes_);
}
size_t DataSource::GetNumReadBytes() const { return num_read_bytes_; }
size_t DataSource::GetNumDiscardedBytes() const { return num_discarded_bytes_; }
void DataSource::MarkNumBytesAsRead(size_t num_bytes) {
num_read_bytes_ += num_bytes;
}
void DataSource::UnmarkAllReadBytes() { num_read_bytes_ = 0; }
void DataSource::Discard(size_t num_bytes) {
if (num_bytes >= num_available_bytes_) {
available_bytes_ = nullptr;
num_available_bytes_ = 0;
} else {
available_bytes_ += num_bytes;
num_available_bytes_ -= num_bytes;
}
num_read_bytes_ -= std::min(num_bytes, num_read_bytes_);
OnDiscard(num_bytes);
num_discarded_bytes_ += num_bytes;
}
//------------------------------------------------------------------------------
const uint8_t* DataSource::DataHandle::GetBytes() const {
if (data_source_ != nullptr && data_source_->available_bytes_ != nullptr &&
offset_ >= data_source_->num_discarded_bytes_) {
const size_t offset_in_available_bytes =
offset_ - data_source_->num_discarded_bytes_;
if (data_source_->num_available_bytes_ >=
offset_in_available_bytes + size_) {
return data_source_->available_bytes_ + offset_in_available_bytes;
}
}
return nullptr;
}
bool DataSource::TryGetNext(size_t num_bytes, DataHandle* data_handle) {
const uint8_t* data_pointer;
if (TryGetNext(num_bytes, &data_pointer)) {
const size_t offset =
(data_pointer - available_bytes_) + num_discarded_bytes_;
*data_handle = DataHandle(this, offset, num_bytes);
return true;
}
return false;
}
bool DataSource::TryReadNext(size_t num_bytes, DataHandle* data_handle) {
if (TryGetNext(num_bytes, data_handle)) {
MarkNumBytesAsRead(num_bytes);
return true;
}
return false;
}
void DataSource::Reset() {
num_read_bytes_ = 0;
num_discarded_bytes_ = 0;
available_bytes_ = nullptr;
num_available_bytes_ = 0;
}
//------------------------------------------------------------------------------
void ExternalDataSource::Update(const uint8_t* data, size_t data_size) {
if (num_discarded_bytes_ >= data_size) {
available_bytes_ = nullptr;
num_available_bytes_ = 0;
} else {
available_bytes_ = data + num_discarded_bytes_;
num_available_bytes_ = data_size - num_discarded_bytes_;
}
}
// With this simple version of DataSource there is no way of getting more data
// through Fetch(). There is nothing to discard OnDisposal() either.
bool ExternalDataSource::Fetch(size_t) { return false; }
void ExternalDataSource::OnDiscard(size_t) {}
//------------------------------------------------------------------------------
} // namespace WP2