From bdf991fe763b17bc4ac7014483f782664c2fdad1 Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Mon, 16 Jan 2023 15:46:59 +0100 Subject: [PATCH] LibCore: Calculate the correct seek offset for buffered streams --- Tests/LibCore/TestLibCoreStream.cpp | 70 +++++++++++++++++++++++++++++ Userland/Libraries/LibCore/Stream.h | 4 ++ 2 files changed, 74 insertions(+) diff --git a/Tests/LibCore/TestLibCoreStream.cpp b/Tests/LibCore/TestLibCoreStream.cpp index 8c6dc9fed0..48fb655ec8 100644 --- a/Tests/LibCore/TestLibCoreStream.cpp +++ b/Tests/LibCore/TestLibCoreStream.cpp @@ -468,6 +468,76 @@ TEST_CASE(buffered_small_file_read) EXPECT(!file->can_read_line().value()); } +TEST_CASE(buffered_file_tell_and_seek) +{ + auto file = Core::Stream::File::open("/usr/Tests/LibCore/small.txt"sv, Core::Stream::OpenMode::Read).release_value(); + auto buffered_file = Core::Stream::BufferedFile::create(move(file)).release_value(); + + // Initial state. + { + auto current_offset = buffered_file->tell().release_value(); + EXPECT_EQ(current_offset, 0); + } + + // Read a character. + { + auto character = buffered_file->read_value().release_value(); + EXPECT_EQ(character, 'W'); + auto current_offset = buffered_file->tell().release_value(); + EXPECT_EQ(current_offset, 1); + } + + // Read one more character. + { + auto character = buffered_file->read_value().release_value(); + EXPECT_EQ(character, 'e'); + auto current_offset = buffered_file->tell().release_value(); + EXPECT_EQ(current_offset, 2); + } + + // Seek seven characters forward. + { + auto current_offset = buffered_file->seek(7, Core::Stream::SeekMode::FromCurrentPosition).release_value(); + EXPECT_EQ(current_offset, 9); + } + + // Read a character again. + { + auto character = buffered_file->read_value().release_value(); + EXPECT_EQ(character, 'o'); + auto current_offset = buffered_file->tell().release_value(); + EXPECT_EQ(current_offset, 10); + } + + // Seek five characters backwards. + { + auto current_offset = buffered_file->seek(-5, Core::Stream::SeekMode::FromCurrentPosition).release_value(); + EXPECT_EQ(current_offset, 5); + } + + // Read a character. + { + auto character = buffered_file->read_value().release_value(); + EXPECT_EQ(character, 'h'); + auto current_offset = buffered_file->tell().release_value(); + EXPECT_EQ(current_offset, 6); + } + + // Seek back to the beginning. + { + auto current_offset = buffered_file->seek(0, Core::Stream::SeekMode::SetPosition).release_value(); + EXPECT_EQ(current_offset, 0); + } + + // Read the first character. + { + auto character = buffered_file->read_value().release_value(); + EXPECT_EQ(character, 'W'); + auto current_offset = buffered_file->tell().release_value(); + EXPECT_EQ(current_offset, 1); + } +} + constexpr auto buffered_sent_data = "Well hello friends!\n:^)\nThis shouldn't be present. :^("sv; constexpr auto first_line = "Well hello friends!"sv; constexpr auto second_line = ":^)"sv; diff --git a/Userland/Libraries/LibCore/Stream.h b/Userland/Libraries/LibCore/Stream.h index d00fc00f9d..e17d24184f 100644 --- a/Userland/Libraries/LibCore/Stream.h +++ b/Userland/Libraries/LibCore/Stream.h @@ -875,8 +875,12 @@ public: virtual void close() override { m_helper.stream().close(); } virtual ErrorOr seek(i64 offset, SeekMode mode) override { + if (mode == SeekMode::FromCurrentPosition) + offset = offset - m_helper.buffered_data_size(); + auto result = TRY(m_helper.stream().seek(offset, mode)); m_helper.clear_buffer(); + return result; } virtual ErrorOr truncate(off_t length) override