From 515a52130e554c81a6d9cd3e2f28c0d48b716af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1nos=20Benjamin=20Antal?= Date: Fri, 20 Jan 2023 22:12:24 +0100 Subject: [PATCH] Prevent moving from valid frames during defregmentation of `MultiFrame` --- src/query/v2/multiframe.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/query/v2/multiframe.cpp b/src/query/v2/multiframe.cpp index 38cc7549a..477ef6c0c 100644 --- a/src/query/v2/multiframe.cpp +++ b/src/query/v2/multiframe.cpp @@ -54,15 +54,17 @@ bool MultiFrame::HasInvalidFrame() const noexcept { // NOLINTNEXTLINE (bugprone-exception-escape) void MultiFrame::DefragmentValidFrames() noexcept { - /* - from: https://en.cppreference.com/w/cpp/algorithm/remove - "Removing is done by shifting (by means of copy assignment (until C++11)move assignment (since C++11)) the elements - in the range in such a way that the elements that are not to be removed appear in the beginning of the range. - Relative order of the elements that remain is preserved and the physical size of the container is unchanged." - */ - - // NOLINTNEXTLINE (bugprone-unused-return-value) - std::remove_if(frames_.begin(), frames_.end(), [](auto &frame) { return !frame.IsValid(); }); + static constexpr auto kIsValid = [](const FrameWithValidity &frame) { return frame.IsValid(); }; + static constexpr auto kIsInvalid = [](const FrameWithValidity &frame) { return !frame.IsValid(); }; + auto first_invalid_frame = std::find_if(frames_.begin(), frames_.end(), kIsInvalid); + auto following_first_valid = std::find_if(first_invalid_frame, frames_.end(), kIsValid); + while (first_invalid_frame != frames_.end() && following_first_valid != frames_.end()) { + std::swap(*first_invalid_frame, *following_first_valid); + first_invalid_frame++; + first_invalid_frame = std::find_if(first_invalid_frame, frames_.end(), kIsInvalid); + following_first_valid++; + following_first_valid = std::find_if(following_first_valid, frames_.end(), kIsValid); + } } ValidFramesReader MultiFrame::GetValidFramesReader() { return ValidFramesReader{*this}; }