Skip to content

Commit 7949a20

Browse files
committed
support bytebuffer updates on streaming hashes
In some cases ByteBuffers do not provide access to an underlying byte array without incurring copies, this is notably the case for off-heap direct bytebuffers. This patch provides a way to call update on streaming XXHASH instances against a ByteBuffer, which avoids the extra copy needed into a byte array.
1 parent a9c1b3a commit 7949a20

8 files changed

+89
-2
lines changed

src/build/source_templates/xxhash32_streaming.template

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import static net.jpountz.xxhash.XXHashConstants.*;
66
import static net.jpountz.util.${type}Utils.*;
77
import static net.jpountz.util.SafeUtils.checkRange;
88
import static java.lang.Integer.rotateLeft;
9+
import java.nio.ByteBuffer;
910

1011
/**
1112
* Streaming xxhash.
@@ -60,6 +61,11 @@ final class StreamingXXHash32Java${type} extends AbstractStreamingXXHash32Java {
6061
return h32;
6162
}
6263

64+
@Override
65+
public void update(ByteBuffer buf, int off, int len) {
66+
throw new RuntimeException("unimplemented");
67+
}
68+
6369
@Override
6470
public void update(byte[] buf, int off, int len) {
6571
checkRange(buf, off, len);
@@ -139,4 +145,3 @@ final class StreamingXXHash32Java${type} extends AbstractStreamingXXHash32Java {
139145
}
140146

141147
}
142-

src/build/source_templates/xxhash64_streaming.template

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import static net.jpountz.xxhash.XXHashConstants.*;
66
import static net.jpountz.util.${type}Utils.*;
77
import static net.jpountz.util.SafeUtils.checkRange;
88
import static java.lang.Long.rotateLeft;
9+
import java.nio.ByteBuffer;
910

1011
/**
1112
* Streaming xxhash.
@@ -84,6 +85,11 @@ final class StreamingXXHash64Java${type} extends AbstractStreamingXXHash64Java {
8485
return h64;
8586
}
8687

88+
@Override
89+
public void update(ByteBuffer buf, int off, int len) {
90+
throw new RuntimeException("unimplemented");
91+
}
92+
8793
@Override
8894
public void update(byte[] buf, int off, int len) {
8995
checkRange(buf, off, len);
@@ -163,4 +169,3 @@ final class StreamingXXHash64Java${type} extends AbstractStreamingXXHash64Java {
163169
}
164170

165171
}
166-

src/java/net/jpountz/xxhash/StreamingXXHash32.java

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.util.zip.Checksum;
44
import java.io.Closeable;
5+
import java.nio.ByteBuffer;
56

67
/*
78
* Copyright 2020 Adrien Grand and the lz4-java contributors.
@@ -71,6 +72,15 @@ interface Factory {
7172
*/
7273
public abstract void update(byte[] buf, int off, int len);
7374

75+
/**
76+
* Updates the value of the hash with buf[off:off+len].
77+
*
78+
* @param buf the input data
79+
* @param off the start offset in buf
80+
* @param len the number of bytes to hash
81+
*/
82+
public abstract void update(ByteBuffer buf, int off, int len);
83+
7484
/**
7585
* Resets this instance to the state it had right after instantiation. The
7686
* seed remains unchanged.

src/java/net/jpountz/xxhash/StreamingXXHash32JNI.java

+7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.jpountz.xxhash;
22

3+
import java.nio.ByteBuffer;
4+
35
/*
46
* Copyright 2020 Adrien Grand and the lz4-java contributors.
57
*
@@ -69,6 +71,11 @@ public synchronized void update(byte[] bytes, int off, int len) {
6971
XXHashJNI.XXH32_update(state, bytes, off, len);
7072
}
7173

74+
public synchronized void update(ByteBuffer buf, int off, int len) {
75+
checkState();
76+
XXHashJNI.XXH32BB_update(state, buf, off, len);
77+
}
78+
7279
@Override
7380
public synchronized void close() {
7481
if (state != 0) {

src/java/net/jpountz/xxhash/StreamingXXHash64.java

+10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package net.jpountz.xxhash;
22

33
import java.util.zip.Checksum;
4+
import java.nio.ByteBuffer;
45
import java.io.Closeable;
56

67
/*
@@ -71,6 +72,15 @@ interface Factory {
7172
*/
7273
public abstract void update(byte[] buf, int off, int len);
7374

75+
/**
76+
* Updates the value of the hash with buf[off:off+len].
77+
*
78+
* @param buf the input data
79+
* @param off the start offset in buf
80+
* @param len the number of bytes to hash
81+
*/
82+
public abstract void update(ByteBuffer buf, int off, int len);
83+
7484
/**
7585
* Resets this instance to the state it had right after instantiation. The
7686
* seed remains unchanged.

src/java/net/jpountz/xxhash/StreamingXXHash64JNI.java

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package net.jpountz.xxhash;
22

3+
import java.nio.ByteBuffer;
4+
35
/*
46
* Copyright 2020 Linnaea Von Lavia and the lz4-java contributors.
57
*
@@ -70,6 +72,12 @@ public synchronized void update(byte[] bytes, int off, int len) {
7072
XXHashJNI.XXH64_update(state, bytes, off, len);
7173
}
7274

75+
@Override
76+
public synchronized void update(ByteBuffer buf, int off, int len) {
77+
checkState();
78+
XXHashJNI.XXH64BB_update(state, buf, off, len);
79+
}
80+
7381
@Override
7482
public synchronized void close() {
7583
if (state != 0) {

src/java/net/jpountz/xxhash/XXHashJNI.java

+2
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ enum XXHashJNI {
3333
static native int XXH32BB(ByteBuffer input, int offset, int len, int seed);
3434
static native long XXH32_init(int seed);
3535
static native void XXH32_update(long state, byte[] input, int offset, int len);
36+
static native void XXH32BB_update(long state, ByteBuffer input, int offset, int len);
3637
static native int XXH32_digest(long state);
3738
static native void XXH32_free(long state);
3839

3940
static native long XXH64(byte[] input, int offset, int len, long seed);
4041
static native long XXH64BB(ByteBuffer input, int offset, int len, long seed);
4142
static native long XXH64_init(long seed);
4243
static native void XXH64_update(long state, byte[] input, int offset, int len);
44+
static native void XXH64BB_update(long state, ByteBuffer input, int offset, int len);
4345
static native long XXH64_digest(long state);
4446
static native void XXH64_free(long state);
4547
}

src/jni/net_jpountz_xxhash_XXHashJNI.c

+40
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,26 @@ JNIEXPORT void JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH32_1update
120120

121121
}
122122

123+
/*
124+
* Class: net_jpountz_xxhash_XXHashJNI
125+
* Method: XXH32BB_update
126+
* Signature: (JLjava/nio/ByteBuffer;II)V
127+
*/
128+
JNIEXPORT void JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH32BB_1update
129+
(JNIEnv *env, jclass cls, jlong state, jbyteArray src, jint off, jint len) {
130+
131+
char* in;
132+
jlong h64;
133+
134+
in = (char*) (*env)->GetDirectBufferAddress(env, src);
135+
if (in == NULL) {
136+
throw_OOM(env);
137+
return;
138+
}
139+
140+
XXH32_update((XXH32_state_t*) state, in + off, len);
141+
}
142+
123143
/*
124144
* Class: net_jpountz_xxhash_XXHashJNI
125145
* Method: XXH32_digest
@@ -230,6 +250,26 @@ JNIEXPORT void JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH64_1update
230250

231251
}
232252

253+
/*
254+
* Class: net_jpountz_xxhash_XXHashJNI
255+
* Method: XXH64BB_update
256+
* Signature: (JLjava/nio/ByteBuffer;II)V
257+
*/
258+
JNIEXPORT void JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH64BB_1update
259+
(JNIEnv *env, jclass cls, jlong state, jbyteArray src, jint off, jint len) {
260+
261+
char* in;
262+
jlong h64;
263+
264+
in = (char*) (*env)->GetDirectBufferAddress(env, src);
265+
if (in == NULL) {
266+
throw_OOM(env);
267+
return;
268+
}
269+
270+
XXH64_update((XXH64_state_t*) state, in + off, len);
271+
}
272+
233273
/*
234274
* Class: net_jpountz_xxhash_XXHashJNI
235275
* Method: XXH64_digest

0 commit comments

Comments
 (0)