Revision 238 (by dpavlin, 2004/03/08 17:46:16) tagging openisis 0.9.0
/*
	openisis - an open implementation of the CDS/ISIS database
	Version 0.8.x (patchlevel see file Version)
	Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	see README for more information
EOH */

/*
	$Id: openjsis.c,v 1.17 2003/04/08 00:20:53 kripke Exp $
	main file of openjsis java native lib.
*/

#include <stdlib.h> /* free */
#include <memory.h> /* memcpy */

#include "openisis.h"
#define index stupidgcc
/*
java/jdk1.3/include/jni.h:607: warning: declaration of `index' shadows global declaration
	jobject (JNICALL *GetObjectArrayElement)
		(JNIEnv *env, jobjectArray array, jsize index);
*/
#include "org/openisis/NativeDb.h"
#undef index



/* ************************************************************
	private types
*/
/* ************************************************************
	private data
*/
/* ************************************************************
	private functions
*/
static jobjectArray rec2bytes (JNIEnv* env, OpenIsisRec *r )
{
	jobjectArray jarr = 0;
	jintArray ia;
	jint ji;
	jbyteArray ba;
	int i;

	if ( ! r )
		return 0;

	jarr = (*env)->NewObjectArray( env, 1+r->len,
		(*env)->FindClass( env, "java/lang/Object" ), 0 );
	if ( ! jarr )
		return 0;

	ia = (*env)->NewIntArray( env, 1+r->len );
	(*env)->SetObjectArrayElement( env, jarr, 0, ia );

	ji = r->rowid;
	(*env)->SetIntArrayRegion( env, ia, 0, 1, &ji );

	for ( i=0; i<r->len; i++ ) {
		OpenIsisField *f = &r->field[i];
		ba = (*env)->NewByteArray( env, f->len );
		if ( ! ba )
			break;
		ji = f->tag;
		(*env)->SetIntArrayRegion( env, ia, i+1, 1, &ji );
		(*env)->SetByteArrayRegion( env, ba, 0, f->len, (jbyte*)f->val );
		(*env)->SetObjectArrayElement( env, jarr, i+1, ba );
	}
	return jarr;
}	/* rec2bytes */

static OpenIsisRec* bytes2rec ( JNIEnv* env, jobjectArray arr ) {
	jsize len;
	jsize alen;
	jintArray ia;
	jbyteArray ba;
	OpenIsisRec* rec;
	int i;
	jint ji;
	jint* tags;
	char *txt;

	/* initialize record */
	rec = 0;
	OPENISIS_RSPACE( rec, 8*1024, -1 );
	
	len = (*env)->GetArrayLength( env, arr );
	if ( 1 > len )
		return 0;

	ia = (*env)->GetObjectArrayElement( env, arr, 0 );
	if ( ! ia )
		return 0;

	(*env)->GetIntArrayRegion( env, ia, 0, 1, &ji );
	rec->rowid = ji;
	
	/* strip rowid / type description from length */
	--len;
	tags = malloc( len * sizeof( jint ) );
	(*env)->GetIntArrayRegion( env, ia, 1, len, tags );

	for ( i = 0; i < len; i++ ) {
		ba = (*env)->GetObjectArrayElement( env, arr, i + 1 );
		alen = (*env)->GetArrayLength( env, ba );
		txt = malloc( alen );
		memset( txt, 0, alen );
		(*env)->GetByteArrayRegion( env, ba, 0, alen, (jbyte*)txt );
		OPENISIS_RADD( rec, tags[ i ], txt, alen, 0 );
		if ( txt )
			free( txt );
	}
	if ( tags )
		free( tags );
	return rec;
} /* bytes2rec */


/* ************************************************************
	package functions
*/
/* ************************************************************
	public functions
*/
JNIEXPORT jshort JNICALL Java_org_openisis_NativeDb_nopen
  (JNIEnv* env, jclass cls, jstring jdbname, jobjectArray jargs)
{
	int db;
	const char *dbname = 0;
	const char **argv = 0;
	int argc = 0;
	jsize i;

	(void)cls;
	dbname = ! jdbname ? 0 :
		(*env)->GetStringUTFChars( env, jdbname, 0 );
	if ( jargs ) {
		argc = (*env)->GetArrayLength( env, jargs );
		argv = malloc( argc * sizeof(*argv) );
		if ( argv )
			for ( i=0; i<argc; i++ )
				argv[i] = (*env)->GetStringUTFChars( env,
					(*env)->GetObjectArrayElement( env, jargs, i ), 0 );
	}
	db = openIsisOpen( dbname, argv, argc );
	if ( dbname )
		(*env)->ReleaseStringUTFChars( env, jdbname, dbname );
	if ( argv )
		for ( i=0; i<argc; i++ )
			if ( argv[i] )
				(*env)->ReleaseStringUTFChars( env,
					(*env)->GetObjectArrayElement( env, jargs, i ), argv[i] );
	return db;
}	/* Java_org_openisis_Db_open */


JNIEXPORT jobjectArray JNICALL Java_org_openisis_NativeDb_nreadRow
  (JNIEnv* env, jclass cls, jshort db, jint rowid, jint tag, jbyteArray txt )
{
	OpenIsisRec *r;
	jobjectArray jarr = 0;
	(void)cls;
	if ( ! txt )
		r = openIsisReadRow( db, rowid );
	else {
		jsize l = (*env)->GetArrayLength( env, txt );
		char *search = malloc( l+1 );
		(*env)->GetByteArrayRegion( env, txt, 0, l, (jbyte*)search );
		search[l] = 0;
		r = openIsisScan( db, rowid, tag, search );
		free( search );
	}
	jarr = rec2bytes( env, r );
	if ( r ) free( r );
#ifndef NDEBUG
	fflush( stderr );
#endif
	return jarr;
}	/* Java_org_openisis_Db_readRow */

/*
 * please leave me in for debugging ;)
 * static int print ( OpenIsisRec *r )
{
	int i;
	if ( r ) {
		for ( i=0; i<r->len; i++ ) {
			if ( ! r->field[i].val ) {
				openIsisSMsg( 1, "%d.?=%d\n", r->rowid, r->field[i].len );
				continue;
			}
			openIsisSMsg( 1, "%d.%d=%.*s\n", r->rowid, r->field[i].tag,
				(int)r->field[i].len, r->field[i].val );
			if ( r->field[i].len && '^' == *r->field[i].val ) {
				OpenIsisRec *rf = openIsisReadField( 0, r->field+i );
				if ( rf ) {
					int j;
					for ( j=0; j<rf->len; j++ )
						openIsisSMsg( 1, "%d.%d.%c=%.*s\n",
							r->rowid, r->field[i].tag,
							(0x60 & (int)rf->field[j].tag ) ?
								(int)rf->field[j].tag : ' ',
							(int)rf->field[j].len, rf->field[j].val );
					free( rf );
				}
			}
		}
	}
	return ! r ? -1 : r->rowid;
}	*/

JNIEXPORT jshort JNICALL Java_org_openisis_NativeDb_nwriteRow
  (JNIEnv* env, jclass cls, jshort db, jobjectArray arr )
{
	OpenIsisRec *r;
	jint result;
	/* no warning */
	(void) cls;
	if ( ! arr )
		return -1;
	r = bytes2rec( env, arr );
	if ( ! r )
		return -1;
	result = openIsisWrite( db, r );
	if ( r )
		free( r );
	return result;
}

JNIEXPORT jshort JNICALL Java_org_openisis_NativeDb_nwriteXRow
  (JNIEnv* env, jclass cls, jshort db, jobjectArray arr, jobjectArray idx )
{
	OpenIsisRec *r;
	OpenIsisRec *i;
	jint result;
	/* no warning */
	(void) cls;
	if ( ! arr || ! idx )
		return -1;
	r = bytes2rec( env, arr );
	i = bytes2rec( env, idx );
	if ( ! r || ! i )
		return -1;
	result = openIsisWritex( db, r, i );
	if ( r )
		free( r );
	if ( i )
		free( i );
	return result;
}

JNIEXPORT jobjectArray JNICALL Java_org_openisis_NativeDb_nTerms
  (JNIEnv* env, jclass cls, jshort db, jbyteArray term, jbyteArray start )
{
	OpenIsisRec *r;
	jobjectArray jarr = 0;
	jsize lterm = (*env)->GetArrayLength( env, term );
	char *cterm = malloc( lterm+1 );
	union { OpenIsisRec r; char buf[4096]; } x;
	x.r.len   = 0;
	x.r.bytes = sizeof(x);
	(void)cls;
	(*env)->GetByteArrayRegion( env, term, 0, lterm, (jbyte*)cterm );
	cterm[lterm] = 0;
	if ( start ) {
		char *cstart;
		jsize lstart = (*env)->GetArrayLength( env, start );
		if ( 128 < lstart )
			lstart = 128;
		cstart = x.buf + sizeof(x.r);
		(*env)->GetByteArrayRegion( env, start, 0, lstart, (jbyte*)cstart );
		x.r.field[0].val = cstart;
		x.r.field[0].len = lstart;
		x.r.len = 1;
	}
	r = openIsisTerm( &x.r, db, cterm );
	free( cterm );
	jarr = rec2bytes( env, r );
#ifndef NDEBUG
	fflush( stderr );
#endif
	return jarr;
}	/* Java_org_openisis_Db_Terms */



JNIEXPORT jintArray JNICALL Java_org_openisis_NativeDb_nsearch
  (JNIEnv * env, jclass cls, jshort db, jbyteArray key, jint mode)
{
	jsize l;
	char *search;
	OpenIsisSet set;
	jintArray ia;
	(void)cls;
	if ( ! key )
		return 0;
	l = (*env)->GetArrayLength( env, key );
	search = malloc( l+1 );
	(*env)->GetByteArrayRegion( env, key, 0, l, (jbyte*)search );
	search[l] = 0;
	set.len = 0;
	openIsisQuery( &set, db, search, mode, 0 );
	free( search );
	if ( 0 >= set.len )
		return 0;
	ia = (*env)->NewIntArray( env, set.len );
	(*env)->SetIntArrayRegion( env, ia, 0, set.len, (jint*)set.id );
	return ia;
}	/* Java_org_openisis_Db_search */