Skip to content

Commit 8e7f2c9

Browse files
committed
SWIG: Handle negative offsets in VSIFSeekL
1 parent 6a5158c commit 8e7f2c9

4 files changed

Lines changed: 42 additions & 8 deletions

File tree

autotest/gcore/vsifile.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1415,17 +1415,27 @@ def test_vsifile_class_read_ascii(tmp_path):
14151415
assert f.read(10) == "permission"
14161416

14171417
# skip a character
1418-
f.seek(1, os.SEEK_CUR)
1418+
assert f.seek(1, os.SEEK_CUR) == 0
14191419
assert f.read(9) == "is hereby"
14201420

1421-
f.seek(0, os.SEEK_SET)
1421+
# seek backwards
1422+
assert f.seek(-2, os.SEEK_CUR) == 0
1423+
assert f.read(2) == "by"
1424+
1425+
# jump to beginning
1426+
assert f.seek(0, os.SEEK_SET) == 0
14221427
assert f.read(10) == "permission"
14231428

1429+
# can't jump before the beginning
1430+
pos = f.tell()
1431+
assert f.seek(-2, os.SEEK_SET) == -1
1432+
assert pos == f.tell()
1433+
14241434
# jump to end
1425-
f.seek(0, os.SEEK_END)
1435+
assert f.seek(0, os.SEEK_END) == 0
14261436
assert f.read(10) == ""
14271437

1428-
f.seek(-7, os.SEEK_END)
1438+
assert f.seek(-7, os.SEEK_END) == 0
14291439
assert f.read() == "person\n"
14301440

14311441
f.close()

autotest/pymod/gdaltest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2185,7 +2185,7 @@ def write(self, x):
21852185
gdal.VSIFWriteL(x, 1, len(x), self._fp)
21862186

21872187
def seek(self, offset, whence=0):
2188-
gdal.VSIFSeekL(self._fp, offset, whence)
2188+
return gdal.VSIFSeekL(self._fp, offset, whence)
21892189

21902190
def tell(self):
21912191
return gdal.VSIFTellL(self._fp)

swig/include/cpl.i

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -906,8 +906,33 @@ int VSIFFlushL( VSILFILE* fp );
906906

907907
VSI_RETVAL VSIFCloseL( VSILFILE* fp );
908908

909+
// Wrap VSIFSeekL to allow negative offsets
910+
%rename (VSIFSeekL) wrapper_VSIFSeekL;
911+
%inline {
912+
#if defined(SWIGPYTHON)
913+
int wrapper_VSIFSeekL( VSILFILE* fp, GIntBig offset, int whence) {
914+
#else
915+
VSI_RETVAL wrapper_VSIFSeekL( VSILFILE* fp, long offset, int whence) {
916+
#endif
917+
if (offset < 0) {
918+
switch (whence) {
919+
case SEEK_END: VSIFSeekL(fp, 0, SEEK_END);
920+
case SEEK_CUR:
921+
offset = VSIFTellL(fp) + offset;
922+
whence = SEEK_SET;
923+
break;
924+
default:
925+
VSIError(VSIE_FileError, "Cannot use negative offset with SEEK_SET");
926+
return -1;
927+
}
928+
}
929+
930+
return VSIFSeekL(fp, offset, whence);
931+
}
932+
}
933+
934+
909935
#if defined(SWIGPYTHON)
910-
int VSIFSeekL( VSILFILE* fp, GIntBig offset, int whence);
911936
GIntBig VSIFTellL( VSILFILE* fp );
912937
int VSIFTruncateL( VSILFILE* fp, GIntBig length );
913938

@@ -919,7 +944,6 @@ int VSISupportsSparseFiles( const char* utf8_path );
919944

920945
int VSIFGetRangeStatusL( VSILFILE* fp, GIntBig offset, GIntBig length );
921946
#else
922-
VSI_RETVAL VSIFSeekL( VSILFILE* fp, long offset, int whence);
923947
long VSIFTellL( VSILFILE* fp );
924948
VSI_RETVAL VSIFTruncateL( VSILFILE* fp, long length );
925949
#endif

swig/include/python/gdal_python.i

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ void wrapper_VSIGetMemFileBuffer(const char *utf8_path, GByte **out, vsi_l_offse
371371
raise ValueError("I/O operation on closed file.")
372372
%}
373373

374-
%pythonprepend VSIFSeekL %{
374+
%pythonprepend wrapper_VSIFSeekL %{
375375
if args[0].this is None:
376376
raise ValueError("I/O operation on closed file.")
377377
%}

0 commit comments

Comments
 (0)