Skip to content

Commit 0e06416

Browse files
authored
Fix signature of VCustomSource#SeekCallback (fixes #171) (#172)
* Fix signature of VCustomSource#SeekCallback (fixes #171) Previously the offset was mistyped as a `*void`/`MemorySegment`. It was now changed to be a `gint64`/`long`. Additionally, the `int whence` parameter was replaced with a new `SeekWhence` enum that provides more type safety and discoverability for implementers. To test, a sample was added to provide a `VCustomSource` based on a `FileHandle` that implements seeking, testing it against a TIF image. * Regenerate docs to reflect changed API
1 parent 0d498ab commit 0e06416

18 files changed

+477
-267
lines changed

core/src/main/java/app/photofox/vipsffm/VCustomSource.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,55 @@ public final class VCustomSource extends VSource {
1616
@FunctionalInterface
1717
public interface ReadCallback {
1818

19+
/**
20+
* Read data from the input and write it to the provided memory segment
21+
*
22+
* @param dataPointer Pointer to the memory segment where the data should be written
23+
* @param length The maximum number of bytes to read
24+
* @return The number of bytes actually read, or -1 on error
25+
*/
1926
long read(MemorySegment dataPointer, long length);
2027
}
2128

2229
@FunctionalInterface
2330
public interface SeekCallback {
2431

25-
long seek(int whence);
32+
/**
33+
* Seek to a specific position in the input
34+
*
35+
* @param offset Relative offset in bytes from the position specified by {@code whence}
36+
* @param whence Where to seek from, one of {@link SeekWhence}
37+
* @return the new position in the input, or -1 on error
38+
*/
39+
long seek(long offset, SeekWhence whence);
40+
}
41+
42+
public enum SeekWhence {
43+
/** Seek from the beginning of the input */
44+
SEEK_SET(0),
45+
/** Seek from the current position in the input */
46+
SEEK_CUR(1),
47+
/** Seek from the end of the input */
48+
SEEK_END(2);
49+
50+
private final int value;
51+
52+
public static SeekWhence fromValue(int value) {
53+
return switch (value) {
54+
case 0 -> SEEK_SET;
55+
case 1 -> SEEK_CUR;
56+
case 2 -> SEEK_END;
57+
default -> throw new IllegalArgumentException("Unknown seek whence value: " + value);
58+
};
59+
}
60+
61+
SeekWhence(int value) {
62+
this.value = value;
63+
}
64+
65+
public int getValue() {
66+
return value;
67+
}
2668
}
2769

2870
private final VCustomSource.ReadCallback readCallback;
@@ -39,7 +81,7 @@ public VCustomSource(
3981

4082
attachReadSignal(arena, this);
4183
if (seekCallback != null) {
42-
attachSeekSignal(arena, this, seekCallback);
84+
attachSeekSignal(arena, this);
4385
}
4486
}
4587

@@ -78,17 +120,17 @@ public long apply(
78120
}
79121
}
80122

81-
private void attachSeekSignal(Arena arena, VSource source, SeekCallback seekCallback) {
123+
private void attachSeekSignal(Arena arena, VSource source) {
82124
var callback = new CustomStreamSeekCallback.Function() {
83125

84126
@Override
85127
public long apply(
86128
MemorySegment source,
87-
MemorySegment data,
129+
long offset,
88130
int whence,
89131
MemorySegment handle
90132
) {
91-
return seekCallback.seek(whence);
133+
return seekCallback.seek(offset, SeekWhence.fromValue(whence));
92134
}
93135
};
94136
var callbackPointer = CustomStreamSeekCallback.allocate(callback, arena);

core/src/main/java/app/photofox/vipsffm/jextract/CustomStreamSeekCallback.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
/**
1616
* {@snippet lang=c :
17-
* typedef gint64 (*CustomStreamSeekCallback)(VipsSourceCustom *, void *, int, void *)
17+
* typedef gint64 (*CustomStreamSeekCallback)(VipsSourceCustom *, gint64, int, void *)
1818
* }
1919
*/
2020
public class CustomStreamSeekCallback {
@@ -27,13 +27,13 @@ public class CustomStreamSeekCallback {
2727
* The function pointer signature, expressed as a functional interface
2828
*/
2929
public interface Function {
30-
long apply(MemorySegment source, MemorySegment data, int whence, MemorySegment handle);
30+
long apply(MemorySegment source, long offset, int whence, MemorySegment handle);
3131
}
3232

3333
private static final FunctionDescriptor $DESC = FunctionDescriptor.of(
34-
VipsRaw.C_LONG_LONG,
35-
VipsRaw.C_POINTER,
34+
VipsRaw.C_LONG,
3635
VipsRaw.C_POINTER,
36+
VipsRaw.C_LONG,
3737
VipsRaw.C_INT,
3838
VipsRaw.C_POINTER
3939
);
@@ -60,9 +60,9 @@ public static MemorySegment allocate(CustomStreamSeekCallback.Function fi, Arena
6060
/**
6161
* Invoke the upcall stub {@code funcPtr}, with given parameters
6262
*/
63-
public static long invoke(MemorySegment funcPtr,MemorySegment source, MemorySegment data, int whence, MemorySegment handle) {
63+
public static long invoke(MemorySegment funcPtr,MemorySegment source, long offset, int whence, MemorySegment handle) {
6464
try {
65-
return (long) DOWN$MH.invokeExact(funcPtr, source, data, whence, handle);
65+
return (long) DOWN$MH.invokeExact(funcPtr, source, offset, whence, handle);
6666
} catch (Throwable ex$) {
6767
throw new AssertionError("should not reach here", ex$);
6868
}

0 commit comments

Comments
 (0)