blob: 22379a0e32d0bbf9cf29662a1fc4402be70670b1 [file] [log] [blame]
/*******************************************************************************
* Copyright 2014 Trevor Robinson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.scurrilous.circe.crc;
import static com.scurrilous.circe.utils.NativeUtils.loadLibraryFromJar;
import static com.scurrilous.circe.utils.NativeUtils.libType;
import java.nio.ByteBuffer;
import com.scurrilous.circe.IncrementalIntHash;
import com.scurrilous.circe.impl.AbstractIncrementalIntHash;
import com.scurrilous.circe.params.CrcParameters;
/**
* Implementation of CRC-32C using the SSE 4.2 CRC instruction.
*/
public final class Sse42Crc32C extends AbstractIncrementalIntHash implements IncrementalIntHash {
private static final boolean SUPPORTED = checkSupported();
private static boolean checkSupported() {
try {
loadLibraryFromJar("/lib/libcirce-checksum." + libType());
return nativeSupported();
} catch (final Exception | UnsatisfiedLinkError e) {
return false;
}
}
/**
* Returns whether SSE 4.2 CRC-32C is supported on this system.
*
* @return true if this class is supported, false if not
*/
public static boolean isSupported() {
return SUPPORTED;
}
private final long config;
Sse42Crc32C() {
config = 0;
}
public Sse42Crc32C(int[] chunkWords) {
if (chunkWords.length == 0) {
config = 0;
} else {
config = allocConfig(chunkWords);
if (config == 0)
throw new RuntimeException("CRC32C configuration allocation failed");
}
}
@Override
protected void finalize() {
if (config != 0)
freeConfig(config);
}
@Override
public String algorithm() {
return CrcParameters.CRC32C.algorithm();
}
@Override
public int length() {
return 4;
}
@Override
public boolean supportsUnsafe() {
return true;
}
@Override
public int calculate(long address, long length) {
return nativeUnsafe(initial(), address, length, config);
}
@Override
public int resume(int current, ByteBuffer input) {
if (input.isDirect()) {
final int result = nativeDirectBuffer(current, input, input.position(), input.remaining(), config);
input.position(input.limit());
return result;
}
return super.resume(current, input);
}
@Override
public int resume(int current, long address, long length) {
return nativeUnsafe(current, address, length, config);
}
@Override
protected int initial() {
return 0;
}
@Override
protected int resumeUnchecked(int current, byte[] input, int index, int length) {
return nativeArray(current, input, index, length, config);
}
private static native boolean nativeSupported();
private static native int nativeArray(int current, byte[] input, int index, int length, long config);
private static native int nativeDirectBuffer(int current, ByteBuffer input, int offset, int length, long config);
private static native int nativeUnsafe(int current, long address, long length, long config);
private static native long allocConfig(int[] chunkWords);
private static native void freeConfig(long config);
}