/*
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 */