/**
  Template Java/C wrapper code for an MPU Library.

  This should be included after defining JMETHOD and CMETHOD, for example:

  #define JMETHOD(M) Java_nxm_dsp_lib_DemodNative_##M
  #define CMETHOD(M) Demod_##M

  Note: the "##" is the token pasting preprocessing operator in the #define above

  @author Jeff Schoen
  @version $Id: MPULibWrappers.h,v 1.5 2011/07/27 18:45:15 ntn Exp $
*/
#include "native.h"

#define PTR (void*)
#define CPTR (void*)(jpointer)
#define JPTR (jlong)(jpointer)

void* CMETHOD(alloc) ();
int_4 CMETHOD(setkey)(void* handle, char* key, void* data, int_4 len);
int_4 CMETHOD(getkey)(void* handle, char* key, void* data, int_4 len);
int_4 CMETHOD(init)  (void* handle);
int_4 CMETHOD(work)  (void* handle,int_4 n);
int_4 CMETHOD(work1) (void* handle,void* buf1,int_4 n1);
int_4 CMETHOD(work2) (void* handle,void* buf1,int_4 n1,void* buf2,int_4 n2);
int_4 CMETHOD(work3) (void* handle,void* buf1,int_4 n1,void* buf2,int_4 n2,void* buf3,int_4 n3);
int_4 CMETHOD(free)  (void* handle);

#ifndef WORKBUFFERS
#define WORKBUFFERS 2
#endif

JNIEXPORT jlong JNICALL JMETHOD(alloc) (JNIEnv *env, jobject obj) {
  return JPTR CMETHOD(alloc)();
}

JNIEXPORT jint  JNICALL JMETHOD(setkey) (JNIEnv *env, jobject obj, jlong handle,
		jstring key, jobject buffer, jint len) {
  char *ckey = (char*)GetString(key);
  jbyte *buf = GetArray(buffer), *bufp = buf;
  jint status, needpad = (ckey[0]=='S' && ckey[1]==':' && buf[len]!=0);
  if (needpad) { bufp = malloc(len+1); memcpy(bufp,buf,len); bufp[len]=0; }
  status = (jint)CMETHOD(setkey) (CPTR handle,ckey,(void*)bufp,len);
  if (needpad) free(bufp);
  ReleaseArray(buffer,buf);
  ReleaseString(key,ckey);
  return status;
}

JNIEXPORT jint  JNICALL JMETHOD(getkey) (JNIEnv *env, jobject obj, jlong handle,
		jstring key, jobject buffer, jint len) {
  char *ckey = (char*)GetString(key);
  jbyte *buf = GetArray(buffer);
  jint status = (jint)CMETHOD(getkey) (CPTR handle,ckey,(void*)buf,len);
  ReleaseArray(buffer,buf);
  ReleaseString(key,ckey);
  return status;
}

JNIEXPORT jint  JNICALL JMETHOD(init) (JNIEnv *env, jobject obj, jlong handle) {
  return (jint)CMETHOD(init) (CPTR handle);
}

JNIEXPORT jint  JNICALL JMETHOD(work) (JNIEnv *env, jobject obj, jlong handle,
		jint n) {
#if WORKBUFFERS == 0
  jint status = (jint)CMETHOD(work) (CPTR handle,n);
  return status;
#else
  return -1;
#endif
}

JNIEXPORT jint  JNICALL JMETHOD(work1) (JNIEnv *env, jobject obj, jlong handle,
		jobject buffer1, jint n1) {
#if WORKBUFFERS == 1
  jbyte *buf1 = GetArray(buffer1);
  jint status = (jint)CMETHOD(work1) (CPTR handle,PTR buf1,n1);
  ReleaseArray(buffer1,buf1);
  return status;
#else
  return -1;
#endif
}

JNIEXPORT jint  JNICALL JMETHOD(work2) (JNIEnv *env, jobject obj, jlong handle,
		jobject buffer1, jint n1, jobject buffer2, jint n2) {
#if WORKBUFFERS == 2
  jbyte *buf1 = GetArray(buffer1);
  jbyte *buf2 = GetArray(buffer2);
  jint status = (jint)CMETHOD(work2) (CPTR handle,PTR buf1,n1,PTR buf2,n2);
  ReleaseArray(buffer1,buf1);
  ReleaseArray(buffer2,buf2);
  return status;
#else
  return -1;
#endif
}

JNIEXPORT jint  JNICALL JMETHOD(work3) (JNIEnv *env, jobject obj, jlong handle,
		jobject buffer1, jint n1, jobject buffer2, jint n2, jobject buffer3, jint n3) {
#if WORKBUFFERS == 3
  jbyte *buf1 = GetArray(buffer1);
  jbyte *buf2 = GetArray(buffer2);
  jbyte *buf3 = GetArray(buffer3);
  jint status = (jint)CMETHOD(work3) (CPTR handle,PTR buf1,n1,PTR buf2,n2,PTR buf3,n3);
  ReleaseArray(buffer1,buf1);
  ReleaseArray(buffer2,buf2);
  ReleaseArray(buffer3,buf3);
  return status;
#else
  return -1;
#endif
}

JNIEXPORT jint  JNICALL JMETHOD(free) (JNIEnv *env, jobject obj, jlong handle) {
  return (jint)CMETHOD(free) (CPTR handle);
}
