size_t reader::chained_reader_impl::read_some()

in src/native/io/reader.cpp [135:189]


size_t reader::chained_reader_impl::read_some(uint64_t offset, std::span<char> buffer) const
{
	if ((buffer.size() == 0) || (m_length == 0))
	{
		return 0;
	}

	auto lower_bound = std::lower_bound(m_offsets.begin(), m_offsets.end(), offset);

	if (lower_bound < m_offsets.begin())
	{
		std::string msg = "reader::chained_reader_impl::slice(): lower_bound too low. lower_bound: "
		                + std::to_string(*lower_bound) + ", m_offset.begin(): " + std::to_string(*m_offsets.begin());

		throw errors::user_exception(errors::error_code::io_reader_slice_bound_error, msg);
	}

	auto index = static_cast<size_t>(lower_bound - m_offsets.begin());

	if (index != 0)
	{
		// This is past the last offset value, try last reader.
		if (index >= m_offsets.size())
		{
			index = m_offsets.size() - 1;
		}
		else if (offset < m_offsets[index])
		{
			index--;
		}
	}

	uint64_t offset_in_reader = offset - m_offsets[index];

	auto remaining      = buffer.size();
	uint64_t total_read = 0;
	while (remaining > 0 && index < m_readers.size())
	{
		auto &reader = m_readers[index];
		std::span<char> remaining_buffer{buffer.data() + total_read, remaining};
		auto actual_read = reader.read_some(offset_in_reader, remaining_buffer);

		if (actual_read == 0)
		{
			break;
		}

		remaining -= actual_read;
		total_read += actual_read;
		index++;
		offset_in_reader = 0;
	}

	return total_read;
}