/*
 * Class:     net_jpountz_lz4_LZ4
 * Method:    LZ4_compressHC
 * Signature: ([BII[BI)I
 */
JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compressHC
  (JNIEnv *env, jclass cls, jbyteArray src, jint srcOff, jint srcLen, jbyteArray dest, jint destOff, jint maxDestLen) {

  char* in;
  char* out;
  jint compressed;
  
  in = (char*) (*env)->GetPrimitiveArrayCritical(env, src, 0);
  if (in == NULL) {
    throw_OOM(env);
    return 0;
  } 
  out = (char*) (*env)->GetPrimitiveArrayCritical(env, dest, 0);
  if (out == NULL) {
    throw_OOM(env);
    return 0;
  }

  compressed = LZ4_compressHC_limitedOutput(in + srcOff, out + destOff, srcLen, maxDestLen);

  (*env)->ReleasePrimitiveArrayCritical(env, src, in, 0);
  (*env)->ReleasePrimitiveArrayCritical(env, src, out, 0);

  return compressed;

}
/*
 * Class:     net_jpountz_lz4_LZ4JNI
 * Method:    LZ4_decompress_safe_withPrefix64k
 * Signature: ([BII[BII)I
 */
JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1decompress_1safe_1withPrefix64k
  (JNIEnv *env, jclass cls, jbyteArray src, jint srcOff, jint srcLen, jbyteArray dest, jint destOff, jint maxDestLen) {

  char* in;
  char* out;
  jint decompressed;

  in = (char*) (*env)->GetPrimitiveArrayCritical(env, src, 0);
  if (in == NULL) {
    throw_OOM(env);
    return 0;
  }
  out = (char*) (*env)->GetPrimitiveArrayCritical(env, dest, 0);
  if (out == NULL) {
    throw_OOM(env);
    return 0;
  }

  decompressed = LZ4_decompress_safe_withPrefix64k(in + srcOff, out + destOff, srcLen, maxDestLen);

  (*env)->ReleasePrimitiveArrayCritical(env, src, in, 0);
  (*env)->ReleasePrimitiveArrayCritical(env, src, out, 0);

  return decompressed;

}
/*
 * Class:     net_jpountz_lz4_LZ4
 * Method:    LZ4_decompress
 * Signature: ([BI[BII)I
 */
JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1decompress
(JNIEnv *env, jclass cls, jbyteArray src, jint srcOff, jbyteArray dest, jint destOff, jint destLen) {

    char* in = (char*) (*env)->GetPrimitiveArrayCritical(env, src, 0);
    if (in == NULL) {
        throw_OOM(env);
        return 0;
    }
    char* out = (char*) (*env)->GetPrimitiveArrayCritical(env, dest, 0);
    if (out == NULL) {
        throw_OOM(env);
        return 0;
    }

    jint compressed = LZ4_uncompress(in + srcOff, out + destOff, destLen);

    (*env)->ReleasePrimitiveArrayCritical(env, src, in, 0);
    (*env)->ReleasePrimitiveArrayCritical(env, src, out, 0);

    return compressed;

}
/*
 * Class:     net_jpountz_xxhash_XXHashJNI
 * Method:    XXH32_init
 * Signature: (I)J
 */
JNIEXPORT jlong JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH32_1init
  (JNIEnv *env, jclass cls, jint seed) {

  XXH32_state_t *state = XXH32_createState();
  if (XXH32_reset(state, seed) != XXH_OK) {
    XXH32_freeState(state);
    throw_OOM(env);
    return 0;
  }

  return (jlong) state;

}
/*
 * Class:     net_jpountz_lz4_LZ4
 * Method:    LZ4_compressHC
 * Signature: ([BII[BI)I
 */
JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compressHC
  (JNIEnv *env, jclass cls, jbyteArray srcArray, jobject srcBuffer, jint srcOff, jint srcLen, jbyteArray destArray, jobject destBuffer, jint destOff, jint maxDestLen) {

  char* in;
  char* out;
  jint compressed;

  if (srcArray != NULL) {
	  in = (char*) (*env)->GetPrimitiveArrayCritical(env, srcArray, 0);
  } else {
	  in = (char*) (*env)->GetDirectBufferAddress(env, srcBuffer);
  }
  if (in == NULL) {
	throw_OOM(env);
	return 0;
  }
  if (destArray != NULL) {
	  out = (char*) (*env)->GetPrimitiveArrayCritical(env, destArray, 0);
  } else {
	  out = (char*) (*env)->GetDirectBufferAddress(env, destBuffer);
  }
  if (out == NULL) {
    throw_OOM(env);
    return 0;
  }

  compressed = LZ4_compressHC_limitedOutput(in + srcOff, out + destOff, srcLen, maxDestLen);

  if (destArray != NULL) {
	  (*env)->ReleasePrimitiveArrayCritical(env, destArray, out, 0);
  }
  if (srcArray != NULL) {
	  (*env)->ReleasePrimitiveArrayCritical(env, srcArray, in, 0);
  }

  return compressed;

}
/*
 * Class:     net_jpountz_xxhash_XXHashJNI
 * Method:    XXH64_update
 * Signature: (J[BII)V
 */
JNIEXPORT void JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH64_1update
  (JNIEnv *env, jclass cls, jlong state, jbyteArray src, jint off, jint len) {

  char* in = (char*) (*env)->GetPrimitiveArrayCritical(env, src, 0);
  if (in == NULL) {
    throw_OOM(env);
    return;
  }

  XXH64_update((XXH64_state_t*) state, in + off, len);

  (*env)->ReleasePrimitiveArrayCritical(env, src, in, 0);

}
/*
 * Class:     net_jpountz_xxhash_XXHashJNI
 * Method:    XXH32
 * Signature: ([BIII)I
 */
JNIEXPORT jint JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH32
  (JNIEnv *env, jclass cls, jbyteArray buf, jint off, jint len, jint seed) {

  char* in = (char*) (*env)->GetPrimitiveArrayCritical(env, buf, 0);
  if (in == NULL) {
    throw_OOM(env);
    return 0;
  }

  jint h32 = XXH32(in + off, len, seed);

  (*env)->ReleasePrimitiveArrayCritical(env, buf, in, 0);

  return h32;
}
/*
 * Class:     net_jpountz_xxhash_XXHashJNI
 * Method:    XXH32BB
 * Signature: (Ljava/nio/ByteBuffer;III)I
 */
JNIEXPORT jint JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH32BB
  (JNIEnv *env, jclass cls, jobject buf, jint off, jint len, jint seed) {

  char* in;
  jint h32;

  in = (char*) (*env)->GetDirectBufferAddress(env, buf);
  if (in == NULL) {
    throw_OOM(env);
    return 0;
  }

  h32 = XXH32(in + off, len, seed);

  return h32;

}
/*
 * Class:     net_jpountz_xxhash_XXHashJNI
 * Method:    XXH64BB
 * Signature: (Ljava/nio/ByteBuffer;IIJ)J
 */
JNIEXPORT jlong JNICALL Java_net_jpountz_xxhash_XXHashJNI_XXH64BB
  (JNIEnv *env, jclass cls, jobject buf, jint off, jint len, jlong seed) {

  char* in;
  jlong h64;

  in = (char*) (*env)->GetDirectBufferAddress(env, buf);
  if (in == NULL) {
    throw_OOM(env);
    return 0;
  }

  h64 = XXH64(in + off, len, seed);

  return h64;

}