Use ReverseView to perform fewer allocations

The first attempt at a bug fix for @ symbols in selection buffer names
worked, but it was very inefficient. In particular, it allocated three
different vectors, and we really only needed the correct elements.
Manipulating iterators to give us the right slices of the existing
vector is far more efficient.

By reversing the original content and taking the last two, we're able to
get the number of selections and main selection without too much hassle.
The buffer name is everything from the start of the content to the
selection count. This gets us through with only one vector allocation.

Credit to @mawww for the optimization idea and for fixing my types.
This commit is contained in:
geppettodivacin 2020-02-01 17:24:08 -06:00
parent 5596b4b2b9
commit 39a2ab84fa
2 changed files with 18 additions and 15 deletions

View File

@ -1778,18 +1778,15 @@ SelectionList read_selections_from_register(char reg, Context& context)
// Use the last two values for timestamp and main_index to allow the buffer
// name to have @ symbols
struct error : runtime_error { error() : runtime_error{"expected <buffer>@<timestamp>@main_index"} {} };
const auto desc = content[0] | split<StringView>('@') | gather<Vector>();
const size_t desc_size = desc.size();
if (desc_size < 3)
throw new error;
auto const buffer_name_view = desc | drop(2);
auto const buffer_name_temp = accumulate (buffer_name_view, ""_str,
[](auto str1, auto str2) { return str1 + "@"_str + str2; });
auto const buffer_name = buffer_name_temp.substr (CharCount (1));
struct error : runtime_error { error(size_t) : runtime_error{"expected <buffer>@<timestamp>@main_index"} {} };
auto end_content = content[0] | reverse() | split('@') | transform([] (auto bounds) {
return StringView{bounds.second.base(), bounds.first.base()};
}) | static_gather<error, 2, false>();
const size_t main = str_to_int(end_content[0]);
const size_t timestamp = str_to_int(end_content[1]);
const auto buffer_name = StringView{ content[0].begin (), end_content[1].begin () - 1 };
Buffer& buffer = BufferManager::instance().get_buffer(buffer_name);
const size_t timestamp = str_to_int(desc[desc_size - 2]);
size_t main = str_to_int(desc[desc_size - 1]);
return selection_list_from_strings(buffer, ColumnType::Byte, content | skip(1), timestamp, main);
}

View File

@ -37,6 +37,12 @@ struct ReverseView
{
decltype(auto) begin() { return m_range.rbegin(); }
decltype(auto) end() { return m_range.rend(); }
decltype(auto) rbegin() { return m_range.begin(); }
decltype(auto) rend() { return m_range.end(); }
decltype(auto) begin() const { return m_range.rbegin(); }
decltype(auto) end() const { return m_range.rend(); }
decltype(auto) rbegin() const { return m_range.begin(); }
decltype(auto) rend() const { return m_range.end(); }
Range m_range;
};
@ -495,15 +501,15 @@ auto elements(bool exact_size = false)
}
template<typename ExceptionType, size_t... Indexes>
auto static_gather_impl(std::index_sequence<Indexes...>)
auto static_gather_impl(std::index_sequence<Indexes...>, bool exact_size)
{
return elements<ExceptionType, Indexes...>(true);
return elements<ExceptionType, Indexes...>(exact_size);
}
template<typename ExceptionType, size_t size>
template<typename ExceptionType, size_t size, bool exact_size=true>
auto static_gather()
{
return static_gather_impl<ExceptionType>(std::make_index_sequence<size>());
return static_gather_impl<ExceptionType>(std::make_index_sequence<size>(), exact_size);
}
}