blob: e2ce18029351a9a4379d8ddd58f7f6f3b86eeadb [file] [log] [blame]
// Copyright 2021 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
//
// http://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 <flasher/logging.hpp>
#include <flasher/ops.hpp>
#include <stdplus/exception.hpp>
#include <algorithm>
#include <cstddef>
#include <format>
#include <stdexcept>
#include <vector>
namespace flasher
{
namespace ops
{
void read(Device& dev, size_t dev_offset, File& file, size_t file_offset,
Mutate& mutate, size_t max_size, std::optional<size_t> stride_size)
{
if (dev_offset > dev.getSize())
{
throw std::invalid_argument(std::format(
"Device smaller than offset, {} < {}", dev.getSize(), dev_offset));
}
size_t stride = stride_size ? *stride_size : dev.recommendedStride();
if (stride == 0)
{
throw std::invalid_argument("Stride cannot be 0");
}
std::vector<std::byte> dev_buf_v(stride * 2);
const std::span<std::byte> dev_buf(dev_buf_v);
std::span<std::byte> dev_data;
max_size = std::min(max_size, dev.getSize() - dev_offset);
while (max_size > 0)
{
while (dev_data.size() < stride && max_size > dev_data.size())
{
auto new_size = std::min(stride, max_size - dev_data.size());
auto new_dev_data = dev.readAt(
dev_buf.subspan(dev_data.size(), new_size), dev_offset);
LOG(LogLevel::Info, " RD@{}#{}", dev_offset, new_dev_data.size());
mutate.reverse(new_dev_data, dev_offset);
dev_data =
dev_buf.subspan(0, dev_data.size() + new_dev_data.size());
dev_offset += new_dev_data.size();
}
auto written = file.writeAt(dev_data, file_offset);
LOG(LogLevel::Info, " WF@{}#{}", file_offset, written.size());
file_offset += written.size();
std::memmove(dev_data.data(), dev_data.data() + written.size(),
dev_data.size() - written.size());
dev_data = dev_data.subspan(0, dev_data.size() - written.size());
max_size -= written.size();
}
LOG(LogLevel::Info, "\n");
}
} // namespace ops
} // namespace flasher