AK+LibCore: Add BufferedSocket::can_read_up_to_delimiter()

This method (unlike can_read_line) ensures that the delimiter is present
in the buffer, and doesn't return true after eof when the delimiter is
absent.
This commit is contained in:
Ali Mohammad Pur 2024-01-20 16:20:48 +03:30 committed by Andreas Kling
parent 4d1d88aa16
commit 4f6c9f410c
Notes: sideshowbarker 2024-07-17 18:06:52 +09:00
3 changed files with 23 additions and 6 deletions

View File

@ -175,15 +175,21 @@ public:
return Optional<Match> {};
}
// Returns whether a line can be read, populating the buffer in the process.
ErrorOr<bool> can_read_line()
// Populates the buffer, and returns whether it is possible to read up to the given delimiter.
ErrorOr<bool> can_read_up_to_delimiter(ReadonlyBytes delimiter)
{
if (stream().is_eof())
return m_buffer.used_space() > 0;
return m_buffer.offset_of(delimiter).has_value();
auto maybe_match = TRY(find_and_populate_until_any_of(Array { "\n"sv }));
auto maybe_match = TRY(find_and_populate_until_any_of(Array { StringView { delimiter } }));
if (maybe_match.has_value())
return true;
return stream().is_eof() && m_buffer.offset_of(delimiter).has_value();
}
bool is_eof_with_data_left_over() const
{
return stream().is_eof() && m_buffer.used_space() > 0;
}
@ -292,10 +298,14 @@ public:
}
ErrorOr<StringView> read_line(Bytes buffer) { return m_helper.read_line(move(buffer)); }
ErrorOr<bool> can_read_line()
{
return TRY(m_helper.can_read_up_to_delimiter("\n"sv.bytes())) || m_helper.is_eof_with_data_left_over();
}
ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) { return m_helper.read_until(move(buffer), move(candidate)); }
template<size_t N>
ErrorOr<Bytes> read_until_any_of(Bytes buffer, Array<StringView, N> candidates) { return m_helper.read_until_any_of(move(buffer), move(candidates)); }
ErrorOr<bool> can_read_line() { return m_helper.can_read_line(); }
ErrorOr<bool> can_read_up_to_delimiter(ReadonlyBytes delimiter) { return m_helper.can_read_up_to_delimiter(delimiter); }
size_t buffer_size() const { return m_helper.buffer_size(); }

View File

@ -532,6 +532,8 @@ TEST_CASE(buffered_file_without_newlines)
auto can_read_line = TRY_OR_FAIL(ro_file->can_read_line());
EXPECT(can_read_line);
auto can_read_up_to_newline = TRY_OR_FAIL(ro_file->can_read_up_to_delimiter("\n"sv.bytes()));
EXPECT(!can_read_up_to_newline);
Array<u8, new_newlines_message.length() + 1> buffer;
EXPECT(ro_file->read_line(buffer).release_value() == new_newlines_message);
}

View File

@ -369,6 +369,7 @@ public:
virtual ErrorOr<StringView> read_line(Bytes buffer) = 0;
virtual ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) = 0;
virtual ErrorOr<bool> can_read_line() = 0;
virtual ErrorOr<bool> can_read_up_to_delimiter(ReadonlyBytes delimiter) = 0;
virtual size_t buffer_size() const = 0;
};
@ -413,10 +414,14 @@ public:
virtual void set_notifications_enabled(bool enabled) override { m_helper.stream().set_notifications_enabled(enabled); }
virtual ErrorOr<StringView> read_line(Bytes buffer) override { return m_helper.read_line(move(buffer)); }
virtual ErrorOr<bool> can_read_line() override
{
return TRY(m_helper.can_read_up_to_delimiter("\n"sv.bytes())) || m_helper.is_eof_with_data_left_over();
}
virtual ErrorOr<Bytes> read_until(Bytes buffer, StringView candidate) override { return m_helper.read_until(move(buffer), move(candidate)); }
template<size_t N>
ErrorOr<Bytes> read_until_any_of(Bytes buffer, Array<StringView, N> candidates) { return m_helper.read_until_any_of(move(buffer), move(candidates)); }
virtual ErrorOr<bool> can_read_line() override { return m_helper.can_read_line(); }
virtual ErrorOr<bool> can_read_up_to_delimiter(ReadonlyBytes delimiter) override { return m_helper.can_read_up_to_delimiter(delimiter); }
virtual size_t buffer_size() const override { return m_helper.buffer_size(); }