Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow obtaining and restoring the streaming hashes' internal state. #112

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 47 additions & 38 deletions src/build/source_templates/xxhash32_streaming.template
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,41 @@ final class StreamingXXHash32Java${type} extends AbstractStreamingXXHash32Java {
return new StreamingXXHash32Java${type}(seed);
}

@Override
public StreamingXXHash32 newStreamingHash(XXHash32State savedState) {
return new StreamingXXHash32Java${type}((XXHash32JavaState) savedState);
}

}

StreamingXXHash32Java${type}(int seed) {
super(seed);
}

StreamingXXHash32Java${type}(XXHash32JavaState savedState) {
super(savedState);
}

@Override
public int getValue() {
int h32;
if (totalLen >= 16) {
h32 = rotateLeft(v1, 1) + rotateLeft(v2, 7) + rotateLeft(v3, 12) + rotateLeft(v4, 18);
if (state.totalLen >= 16) {
h32 = rotateLeft(state.v1, 1) + rotateLeft(state.v2, 7) + rotateLeft(state.v3, 12) + rotateLeft(state.v4, 18);
} else {
h32 = seed + PRIME5;
h32 = state.seed + PRIME5;
}

h32 += totalLen;
h32 += state.totalLen;

int off = 0;
while (off <= memSize - 4) {
h32 += readIntLE(memory, off) * PRIME3;
while (off <= state.memSize - 4) {
h32 += readIntLE(state.memory, off) * PRIME3;
h32 = rotateLeft(h32, 17) * PRIME4;
off += 4;
}

while (off < memSize) {
h32 += (readByte(memory, off) & 0xFF) * PRIME5;
while (off < state.memSize) {
h32 += (readByte(state.memory, off) & 0xFF) * PRIME5;
h32 = rotateLeft(h32, 11) * PRIME1;
++off;
}
Expand All @@ -64,45 +73,45 @@ final class StreamingXXHash32Java${type} extends AbstractStreamingXXHash32Java {
public void update(byte[] buf, int off, int len) {
checkRange(buf, off, len);

totalLen += len;
state.totalLen += len;

if (memSize + len < 16) { // fill in tmp buffer
System.arraycopy(buf, off, memory, memSize, len);
memSize += len;
if (state.memSize + len < 16) { // fill in tmp buffer
System.arraycopy(buf, off, state.memory, state.memSize, len);
state.memSize += len;
return;
}

final int end = off + len;

if (memSize > 0) { // data left from previous update
System.arraycopy(buf, off, memory, memSize, 16 - memSize);
if (state.memSize > 0) { // data left from previous update
System.arraycopy(buf, off, state.memory, state.memSize, 16 - state.memSize);

v1 += readIntLE(memory, 0) * PRIME2;
v1 = rotateLeft(v1, 13);
v1 *= PRIME1;
state.v1 += readIntLE(state.memory, 0) * PRIME2;
state.v1 = rotateLeft(state.v1, 13);
state.v1 *= PRIME1;

v2 += readIntLE(memory, 4) * PRIME2;
v2 = rotateLeft(v2, 13);
v2 *= PRIME1;
state.v2 += readIntLE(state.memory, 4) * PRIME2;
state.v2 = rotateLeft(state.v2, 13);
state.v2 *= PRIME1;

v3 += readIntLE(memory, 8) * PRIME2;
v3 = rotateLeft(v3, 13);
v3 *= PRIME1;
state.v3 += readIntLE(state.memory, 8) * PRIME2;
state.v3 = rotateLeft(state.v3, 13);
state.v3 *= PRIME1;

v4 += readIntLE(memory, 12) * PRIME2;
v4 = rotateLeft(v4, 13);
v4 *= PRIME1;
state.v4 += readIntLE(state.memory, 12) * PRIME2;
state.v4 = rotateLeft(state.v4, 13);
state.v4 *= PRIME1;

off += 16 - memSize;
memSize = 0;
off += 16 - state.memSize;
state.memSize = 0;
}

{
final int limit = end - 16;
int v1 = this.v1;
int v2 = this.v2;
int v3 = this.v3;
int v4 = this.v4;
int v1 = state.v1;
int v2 = state.v2;
int v3 = state.v3;
int v4 = state.v4;

while (off <= limit) {
v1 += readIntLE(buf, off) * PRIME2;
Expand All @@ -126,15 +135,15 @@ final class StreamingXXHash32Java${type} extends AbstractStreamingXXHash32Java {
off += 4;
}

this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
this.v4 = v4;
state.v1 = v1;
state.v2 = v2;
state.v3 = v3;
state.v4 = v4;
}

if (off < end) {
System.arraycopy(buf, off, memory, 0, end - off);
memSize = end - off;
System.arraycopy(buf, off, state.memory, 0, end - off);
state.memSize = end - off;
}
}

Expand Down
95 changes: 52 additions & 43 deletions src/build/source_templates/xxhash64_streaming.template
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,29 @@ final class StreamingXXHash64Java${type} extends AbstractStreamingXXHash64Java {
return new StreamingXXHash64Java${type}(seed);
}

@Override
public StreamingXXHash64 newStreamingHash(XXHash64State savedState) {
return new StreamingXXHash64Java${type}((XXHash64JavaState) savedState);
}

}

StreamingXXHash64Java${type}(long seed) {
super(seed);
}

StreamingXXHash64Java${type}(XXHash64JavaState savedState) {
super(savedState);
}

@Override
public long getValue() {
long h64;
if (totalLen >= 32) {
long v1 = this.v1;
long v2 = this.v2;
long v3 = this.v3;
long v4 = this.v4;
if (state.totalLen >= 32) {
long v1 = state.v1;
long v2 = state.v2;
long v3 = state.v3;
long v4 = state.v4;

h64 = rotateLeft(v1, 1) + rotateLeft(v2, 7) + rotateLeft(v3, 12) + rotateLeft(v4, 18);

Expand All @@ -50,27 +59,27 @@ final class StreamingXXHash64Java${type} extends AbstractStreamingXXHash64Java {
v4 *= PRIME64_2; v4 = rotateLeft(v4, 31); v4 *= PRIME64_1; h64 ^= v4;
h64 = h64*PRIME64_1 + PRIME64_4;
} else {
h64 = seed + PRIME64_5;
h64 = state.seed + PRIME64_5;
}

h64 += totalLen;
h64 += state.totalLen;

int off = 0;
while (off <= memSize - 8) {
long k1 = readLongLE(memory, off);
while (off <= state.memSize - 8) {
long k1 = readLongLE(state.memory, off);
k1 *= PRIME64_2; k1 = rotateLeft(k1, 31); k1 *= PRIME64_1; h64 ^= k1;
h64 = rotateLeft(h64, 27) * PRIME64_1 + PRIME64_4;
off += 8;
}

if (off <= memSize - 4) {
h64 ^= (readIntLE(memory, off) & 0xFFFFFFFFL) * PRIME64_1;
if (off <= state.memSize - 4) {
h64 ^= (readIntLE(state.memory, off) & 0xFFFFFFFFL) * PRIME64_1;
h64 = rotateLeft(h64, 23) * PRIME64_2 + PRIME64_3;
off += 4;
}

while (off < memSize) {
h64 ^= (memory[off] & 0xFF) * PRIME64_5;
while (off < state.memSize) {
h64 ^= (state.memory[off] & 0xFF) * PRIME64_5;
h64 = rotateLeft(h64, 11) * PRIME64_1;
++off;
}
Expand All @@ -88,45 +97,45 @@ final class StreamingXXHash64Java${type} extends AbstractStreamingXXHash64Java {
public void update(byte[] buf, int off, int len) {
checkRange(buf, off, len);

totalLen += len;
state.totalLen += len;

if (memSize + len < 32) { // fill in tmp buffer
System.arraycopy(buf, off, memory, memSize, len);
memSize += len;
if (state.memSize + len < 32) { // fill in tmp buffer
System.arraycopy(buf, off, state.memory, state.memSize, len);
state.memSize += len;
return;
}

final int end = off + len;

if (memSize > 0) { // data left from previous update
System.arraycopy(buf, off, memory, memSize, 32 - memSize);
if (state.memSize > 0) { // data left from previous update
System.arraycopy(buf, off, state.memory, state.memSize, 32 - state.memSize);

v1 += readLongLE(memory, 0) * PRIME64_2;
v1 = rotateLeft(v1, 31);
v1 *= PRIME64_1;
state.v1 += readLongLE(state.memory, 0) * PRIME64_2;
state.v1 = rotateLeft(state.v1, 31);
state.v1 *= PRIME64_1;

v2 += readLongLE(memory, 8) * PRIME64_2;
v2 = rotateLeft(v2, 31);
v2 *= PRIME64_1;
state.v2 += readLongLE(state.memory, 8) * PRIME64_2;
state.v2 = rotateLeft(state.v2, 31);
state.v2 *= PRIME64_1;

v3 += readLongLE(memory, 16) * PRIME64_2;
v3 = rotateLeft(v3, 31);
v3 *= PRIME64_1;
state.v3 += readLongLE(state.memory, 16) * PRIME64_2;
state.v3 = rotateLeft(state.v3, 31);
state.v3 *= PRIME64_1;

v4 += readLongLE(memory, 24) * PRIME64_2;
v4 = rotateLeft(v4, 31);
v4 *= PRIME64_1;
state.v4 += readLongLE(state.memory, 24) * PRIME64_2;
state.v4 = rotateLeft(state.v4, 31);
state.v4 *= PRIME64_1;

off += 32 - memSize;
memSize = 0;
off += 32 - state.memSize;
state.memSize = 0;
}

{
final int limit = end - 32;
long v1 = this.v1;
long v2 = this.v2;
long v3 = this.v3;
long v4 = this.v4;
long v1 = state.v1;
long v2 = state.v2;
long v3 = state.v3;
long v4 = state.v4;

while (off <= limit) {
v1 += readLongLE(buf, off) * PRIME64_2;
Expand All @@ -150,15 +159,15 @@ final class StreamingXXHash64Java${type} extends AbstractStreamingXXHash64Java {
off += 8;
}

this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
this.v4 = v4;
state.v1 = v1;
state.v2 = v2;
state.v3 = v3;
state.v4 = v4;
}

if (off < end) {
System.arraycopy(buf, off, memory, 0, end - off);
memSize = end - off;
System.arraycopy(buf, off, state.memory, 0, end - off);
state.memSize = end - off;
}
}

Expand Down
27 changes: 13 additions & 14 deletions src/java/net/jpountz/xxhash/AbstractStreamingXXHash32Java.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,28 @@
* limitations under the License.
*/

import static net.jpountz.xxhash.XXHashConstants.PRIME1;
import static net.jpountz.xxhash.XXHashConstants.PRIME2;

abstract class AbstractStreamingXXHash32Java extends StreamingXXHash32 {

int v1, v2, v3, v4, memSize;
long totalLen;
final byte[] memory;
final XXHash32JavaState state;

AbstractStreamingXXHash32Java(int seed) {
super(seed);
memory = new byte[16];
reset();
state = new XXHash32JavaState(seed);
}

AbstractStreamingXXHash32Java(XXHash32JavaState savedState) {
super(savedState.seed);
state = new XXHash32JavaState(savedState);
}

@Override
public void reset() {
v1 = seed + PRIME1 + PRIME2;
v2 = seed + PRIME2;
v3 = seed + 0;
v4 = seed - PRIME1;
totalLen = 0;
memSize = 0;
state.reset();
}

@Override
public XXHash32State getState() {
// Return a copy of the internal state
return new XXHash32JavaState(state);
}
}
28 changes: 13 additions & 15 deletions src/java/net/jpountz/xxhash/AbstractStreamingXXHash64Java.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,28 @@
* limitations under the License.
*/

import static net.jpountz.xxhash.XXHashConstants.PRIME64_1;
import static net.jpountz.xxhash.XXHashConstants.PRIME64_2;

abstract class AbstractStreamingXXHash64Java extends StreamingXXHash64 {

int memSize;
long v1, v2, v3, v4;
long totalLen;
final byte[] memory;
final XXHash64JavaState state;

AbstractStreamingXXHash64Java(long seed) {
super(seed);
memory = new byte[32];
reset();
state = new XXHash64JavaState(seed);
}

AbstractStreamingXXHash64Java(XXHash64JavaState savedState) {
super(savedState.seed);
state = new XXHash64JavaState(savedState);
}

@Override
public void reset() {
v1 = seed + PRIME64_1 + PRIME64_2;
v2 = seed + PRIME64_2;
v3 = seed + 0;
v4 = seed - PRIME64_1;
totalLen = 0;
memSize = 0;
state.reset();
}

@Override
public XXHash64State getState() {
// Return a copy of the internal state
return new XXHash64JavaState(state);
}
}
Loading