reader reader::chained_reader_impl::slice()

in src/native/io/reader.cpp [62:114]


reader reader::chained_reader_impl::slice(uint64_t offset, uint64_t length) const
{
	std::vector<reader> readers;

	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      = length;
	while ((remaining > 0) && (index < m_readers.size()))
	{
		auto &reader               = m_readers[index];
		auto reader_bytes_consumed = std::min(reader.size() - offset_in_reader, remaining);

		// If we're not taking the entire reader, then take a slice
		if (offset_in_reader || (reader_bytes_consumed < reader.size()))
		{
			readers.push_back(reader.slice(offset_in_reader, reader_bytes_consumed));
		}
		else
		{
			readers.push_back(reader);
		}

		remaining -= reader_bytes_consumed;
		offset_in_reader = 0;
		index++;
	}
	return reader::chain(readers);
}