Merge pull request #115710 from syntaxerror247/fix-seek

Fix `FileAccess.seek_end` behavior on Android
This commit is contained in:
Thaddeus Crews 2026-02-09 15:07:07 -06:00
commit 833889aec0
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
3 changed files with 52 additions and 3 deletions

View file

@ -425,7 +425,7 @@
<param index="0" name="position" type="int" default="0" />
<description>
Sets the file cursor to the specified position in bytes, from the end of the file. This changes the value returned by [method get_position].
[b]Note:[/b] This is an offset, so you should use negative numbers otherwise the file cursor will be at the end of the file.
[b]Note:[/b] This is an offset, so you should use negative numbers otherwise the file cursor will move past the end of the file.
</description>
</method>
<method name="set_extended_attribute" qualifiers="static">

View file

@ -203,8 +203,10 @@ internal abstract class DataAccess {
abstract fun write(buffer: ByteBuffer): Boolean
fun seekFromEnd(positionFromEnd: Long) {
val positionFromBeginning = max(0, size() - positionFromEnd)
seek(positionFromBeginning)
val positionFromBeginning = size() + positionFromEnd
if (positionFromBeginning >= 0) {
seek(positionFromBeginning)
}
}
abstract class FileChannelDataAccess(private val filePath: String) : DataAccess() {

View file

@ -248,4 +248,51 @@ TEST_CASE("[FileAccess] Get/Store floating point half precision values") {
}
}
TEST_CASE("[FileAccess] Cursor positioning") {
Ref<FileAccess> f = FileAccess::open(TestUtils::get_data_path("line_endings_lf.test.txt"), FileAccess::READ);
REQUIRE(f.is_valid());
String full = f->get_as_utf8_string();
int64_t len = full.length();
SUBCASE("Initial position is zero") {
f->seek(0);
CHECK(f->get_position() == 0);
}
SUBCASE("seek() moves cursor to absolute position") {
f->seek(5);
CHECK(f->get_position() == 5);
}
SUBCASE("seek() moves cursor beyond file size") {
f->seek(len + 10);
CHECK(f->get_position() == len + 10);
}
SUBCASE("seek_end() moves cursor to end of file") {
f->seek_end(0);
CHECK(f->get_position() == len);
}
SUBCASE("seek_end() with positive offset") {
f->seek_end(1);
CHECK(f->get_position() == len + 1);
}
SUBCASE("seek_end() with negative offset") {
f->seek_end(-1);
CHECK(f->get_position() == len - 1);
char last_char = full[full.length() - 1];
CHECK(f->get_8() == last_char);
}
SUBCASE("seek_end() beyond file size") {
f->seek(5);
f->seek_end(-len - 10); // seeking to a position below 0; ignored.
CHECK(f->get_position() == 5);
}
}
} // namespace TestFileAccess