Skip to content

Commit

Permalink
windows/serialInterface: Further refinements to simplify and solve fo…
Browse files Browse the repository at this point in the history
…r a severe branching misprediction

Co-Authored-By: L. E. Segovia <[email protected]>
Co-Authored-By: dragonmux <[email protected]>
  • Loading branch information
dragonmux and amyspark committed Jan 15, 2024
1 parent f8f2289 commit 7413845
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions src/windows/serialInterface.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <string_view>
#include <fmt/format.h>
#include <substrate/console>
#include <substrate/index_sequence>
#include "windows/serialInterface.hxx"
#include "usbDevice.hxx"
#include "bmp.hxx"
Expand Down Expand Up @@ -287,7 +288,7 @@ void serialInterface_t::refillBuffer() const
// NOLINTNEXTLINE(readability-convert-member-functions-to-static)
std::string serialInterface_t::readPacket() const
{
std::array<char, bmp_t::maxPacketSize + 1U> packet{};
std::array<char, bmp_t::maxPacketSize> packet{};
size_t length{0};
// Try gathering a '#' terminated response
while (length < packet.size())
Expand All @@ -297,29 +298,33 @@ std::string serialInterface_t::readPacket() const
refillBuffer();

// Look for an end of message marker
size_t responseLength{0U};
while (readBufferOffset + responseLength < readBufferFullness && length + responseLength < readBuffer.size())
const auto responseLength
{
// If we've found one then stop scanning
if (readBuffer[readBufferOffset + responseLength++] == '#')
break;
}
[&]()
{
for (const auto offset : substrate::indexSequence_t{readBufferOffset, readBufferFullness})
{
if (readBuffer[offset] == '#')
return offset;
}
return readBufferFullness;
}()
};
// We now either have a remote end of message marker, or need all the data from the buffer
memcpy(packet.data() + length, readBuffer.data() + readBufferOffset, responseLength);
std::memcpy(packet.data() + length, readBuffer.data() + readBufferOffset, responseLength);
readBufferOffset += responseLength;
length += responseLength - 1U;
length += responseLength;
// If it's a remote end of message marker, break out the loop
if (packet[length] == '#')
if (responseLength != readBufferFullness)
{
++readBufferOffset;
break;
++length;
}
}

// Adjust the length to remove the beginning '&' (the ending '#' is already taken care of in the read loop)
--length;
// Make a new std::string of an appropriate length
std::string result(length + 1U, '\0');
// And copy the result string in, returning it
std::memcpy(result.data(), packet.data() + 1U, length);
// Make a new std::string of an appropriate length, copying the data in to return it
// Skip the first byte to remove the beginning '&' (the ending '#' is already taken care of in the read loop)
std::string result{packet.data() + 1U, length};
console.debug("Remote read: "sv, result);
return result;
}

0 comments on commit 7413845

Please sign in to comment.