Add blank classes for DoJa graphics3d.
[SquirrelJME.git] / emulators / emulator-base-native / c / jniHelper.c
blob53f644b4b4f3c37259724cb3290e4004485a587c
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
11 #include <jni.h>
13 #include "squirreljme.h"
14 #include "sjme/debug.h"
16 sjme_jboolean sjme_jni_checkVMException(JNIEnv* env)
18 /* Was there an exception? */
19 if ((*env)->ExceptionCheck(env))
21 /* Debug print it. */
22 (*env)->ExceptionDescribe(env);
24 /* Did fail! */
25 return SJME_JNI_TRUE;
28 return SJME_JNI_FALSE;
31 jintArray sjme_jni_mappedArrayInt(JNIEnv* env,
32 jint* buf, jint off, jint len)
34 #if 0
35 /* We need this to get raw arrays. */
36 byteBufferClassy = (*env)->FindClass(env, "java/nio/ByteBuffer");
37 if (byteBufferClassy == NULL)
38 sjme_die("No ByteBuffer?");
40 /* Create a byte buffer around the buffer. */
41 byteBuffer = (*env)->NewDirectByteBuffer(env,
42 (void*)(((sjme_intPointer)buf) + ((sjme_intPointer)bufOff)), bufLen);
43 if (byteBuffer == NULL)
44 return SJME_ERROR_CANNOT_CREATE;
45 #endif
47 sjme_todo("Impl?");
48 return NULL;
51 void sjme_jni_throwMLECallError(JNIEnv* env, sjme_errorCode code)
53 sjme_jni_throwThrowable(env, code,
54 "cc/squirreljme/jvm/mle/exceptions/MLECallError");
57 void sjme_jni_throwThrowable(JNIEnv* env, sjme_errorCode code,
58 sjme_lpcstr type)
60 #define BUF_SIZE 512
61 jclass tossingClass;
62 char buf[BUF_SIZE];
64 /* Get the class where the exception is. */
65 tossingClass = (*env)->FindClass(env, type);
66 if (tossingClass == NULL)
68 sjme_die("Could not find exception class?");
69 return;
72 /* Generate a message accordingly. */
73 memset(buf, 0, sizeof(buf));
74 snprintf(buf, BUF_SIZE - 1, "Native error: %d",
75 (int)sjme_error_default(code));
76 buf[BUF_SIZE - 1] = 0;
78 /* Throw it. */
79 if ((*env)->ThrowNew(env, tossingClass, buf) != 0)
80 sjme_die("Could not throw a new throwable?");
81 #undef BUF_SIZE
84 void sjme_jni_throwVMException(JNIEnv* env, sjme_errorCode code)
86 sjme_jni_throwThrowable(env, code,
87 "cc/squirreljme/emulator/vm/VMException");
90 void* sjme_jni_recoverPointer(JNIEnv* env, sjme_lpcstr className,
91 jobject instance)
93 jclass classy;
94 jclass baseClassy;
95 jmethodID pointerMethod;
97 /* Does not map. */
98 if (instance == NULL)
99 return NULL;
101 /* Fail. */
102 if (env == NULL || className == NULL)
104 sjme_jni_throwMLECallError(env, SJME_ERROR_NULL_ARGUMENTS);
105 return NULL;
108 /* Locate class. */
109 classy = (*env)->FindClass(env, className);
110 baseClassy = (*env)->FindClass(env, DESC_DYLIB_HAS_OBJECT_POINTER);
111 if (classy == NULL || baseClassy == NULL)
113 sjme_jni_throwMLECallError(env, SJME_ERROR_INVALID_CLASS_NAME);
114 return NULL;
117 /* Incorrect type. */
118 if (!(*env)->IsInstanceOf(env, instance, classy) ||
119 !(*env)->IsInstanceOf(env, instance, baseClassy))
121 sjme_jni_throwMLECallError(env, SJME_ERROR_CLASS_CAST);
122 return NULL;
125 /* Get pointer object method. */
126 pointerMethod = (*env)->GetMethodID(env, baseClassy,
127 "objectPointer", "()J");
128 if (pointerMethod == NULL)
129 sjme_die("No objectPointer() in instance?");
131 /* Cast pencil data. */
132 return (void*)((intptr_t)((*env)->CallLongMethod(
133 env, instance, pointerMethod)));
136 sjme_scritchui_pencil sjme_jni_recoverPencil(JNIEnv* env, jobject g)
138 /* Does not map. */
139 if (g == NULL)
140 return NULL;
142 return (sjme_scritchui_pencil)sjme_jni_recoverPointer(env,
143 DESC_DYLIB_PENCIL, g);
146 sjme_scritchui_pencilFont sjme_jni_recoverFont(JNIEnv* env,
147 jobject fontInstance)
149 /* Does not map. */
150 if (fontInstance == NULL)
151 return NULL;
153 return (sjme_scritchui_pencilFont)sjme_jni_recoverPointer(env,
154 DESC_DYLIB_PENCILFONT, fontInstance);
157 sjme_errorCode sjme_jni_fillFrontEnd(JNIEnv* env, sjme_frontEnd* into,
158 jobject ref)
160 JavaVM* vm;
162 if (env == NULL || into == NULL)
163 return SJME_ERROR_NULL_ARGUMENTS;
165 /* Store referenced VM. */
166 vm = NULL;
167 (*env)->GetJavaVM(env, &vm);
168 into->data = vm;
170 /* Need to reference an object? */
171 if (ref != NULL)
172 into->wrapper = (*env)->NewGlobalRef(env, ref);
173 else
174 into->wrapper = NULL;
176 return SJME_ERROR_NONE;
179 sjme_errorCode sjme_jni_recoverEnv(
180 sjme_attrInOutNotNull JNIEnv** outEnv,
181 sjme_attrInNotNull JavaVM* inVm)
183 JNIEnv* env;
184 jint jniError;
186 if (outEnv == NULL || inVm == NULL)
187 return SJME_ERROR_NULL_ARGUMENTS;
189 /* Try to get the environment for the current thread. */
190 env = NULL;
191 jniError = (*inVm)->GetEnv(inVm, (void**)&env, JNI_VERSION_1_1);
192 if (jniError != JNI_OK || env == NULL)
193 return SJME_ERROR_NO_JAVA_ENVIRONMENT;
195 /* Success! */
196 *outEnv = env;
197 return SJME_ERROR_NONE;
200 sjme_errorCode sjme_jni_recoverEnvFrontEnd(
201 sjme_attrInOutNotNull JNIEnv** outEnv,
202 sjme_attrInNotNull const sjme_frontEnd* inFrontEnd)
204 if (outEnv == NULL || inFrontEnd == NULL)
205 return SJME_ERROR_NULL_ARGUMENTS;
207 /* Forward. */
208 return sjme_jni_recoverEnv(outEnv, inFrontEnd->data);
211 static sjme_errorCode sjme_jni_jstringCharAt(
212 sjme_attrInNotNull const sjme_charSeq* inSeq,
213 sjme_attrInPositive sjme_jint inIndex,
214 sjme_attrOutNotNull sjme_jchar* outChar)
216 sjme_errorCode error;
217 JNIEnv* env;
218 jstring string;
219 const jchar* stringChars;
220 jboolean isCopy;
221 jint len;
223 if (inSeq == NULL || outChar == NULL)
224 return SJME_ERROR_NULL_ARGUMENTS;
226 /* Recover env. */
227 env = NULL;
228 if (sjme_error_is(error = sjme_jni_recoverEnvFrontEnd(
229 &env, &inSeq->frontEnd)) || env == NULL)
230 return sjme_error_default(error);
232 /* Get string. */
233 string = inSeq->frontEnd.wrapper;
235 /* Not within the string bounds? */
236 len = (*env)->GetStringLength(env, string);
237 if (inIndex < 0 || inIndex >= len)
238 return SJME_ERROR_INDEX_OUT_OF_BOUNDS;
240 /* Need to access characters just to read one, sadly. */
241 isCopy = JNI_FALSE;
242 stringChars = (*env)->GetStringChars(env, string, &isCopy);
244 /* Copy character. */
245 *outChar = stringChars[inIndex];
247 /* Cleanup. */
248 (*env)->ReleaseStringChars(env, string, stringChars);
250 /* Success! */
251 return SJME_ERROR_NONE;
254 static sjme_errorCode sjme_jni_jstringDelete(
255 sjme_attrInNotNull sjme_charSeq* inSeq)
257 sjme_errorCode error;
258 JNIEnv* env;
259 jstring string;
261 if (inSeq == NULL)
262 return SJME_ERROR_NULL_ARGUMENTS;
264 /* Recover env. */
265 env = NULL;
266 if (sjme_error_is(error = sjme_jni_recoverEnvFrontEnd(
267 &env, &inSeq->frontEnd)) || env == NULL)
268 return sjme_error_default(error);
270 /* Get string. */
271 string = inSeq->frontEnd.wrapper;
273 /* Remove global reference. */
274 (*env)->DeleteGlobalRef(env, string);
275 inSeq->frontEnd.wrapper = NULL;
277 /* Success! */
278 return SJME_ERROR_NONE;
281 static sjme_errorCode sjme_jni_jstringLength(
282 sjme_attrInNotNull const sjme_charSeq* inSeq,
283 sjme_attrOutNotNull sjme_jint* outLen)
285 sjme_errorCode error;
286 JNIEnv* env;
287 jstring string;
289 if (inSeq == NULL || outLen == NULL)
290 return SJME_ERROR_NULL_ARGUMENTS;
292 /* Recover env. */
293 env = NULL;
294 if (sjme_error_is(error = sjme_jni_recoverEnvFrontEnd(
295 &env, &inSeq->frontEnd)) || env == NULL)
296 return sjme_error_default(error);
298 /* Get string. */
299 string = inSeq->frontEnd.wrapper;
301 /* Get string length. */
302 *outLen = (*env)->GetStringLength(env, string);
304 /* Success! */
305 return SJME_ERROR_NONE;
308 static const sjme_charSeq_functions sjme_jni_jstringFunctions =
310 .charAt = sjme_jni_jstringCharAt,
311 .delete = sjme_jni_jstringDelete,
312 .length = sjme_jni_jstringLength,
315 sjme_errorCode sjme_jni_jstringCharSeqStatic(
316 sjme_attrInNotNull JNIEnv* env,
317 sjme_attrInNotNull sjme_charSeq* inOutSeq,
318 sjme_attrInNotNull jstring inString)
320 sjme_frontEnd frontEnd;
321 sjme_errorCode error;
323 if (env == NULL || inOutSeq == NULL || inString == NULL)
324 return SJME_ERROR_NULL_ARGUMENTS;
326 /* Setup front end. */
327 memset(&frontEnd, 0, sizeof(frontEnd));
328 if (sjme_error_is(error = sjme_jni_fillFrontEnd(env,
329 &frontEnd, inString)))
330 return sjme_error_default(error);
332 /* Initialize via forward. */
333 return sjme_charSeq_newStatic(
334 inOutSeq, &sjme_jni_jstringFunctions,
335 NULL,
336 &frontEnd);
339 jlong sjme_jni_jlong(sjme_jlong value)
341 return value.full;
344 sjme_errorCode sjme_jni_pushWeakLink(
345 sjme_attrInNotNull JNIEnv* env,
346 sjme_attrInNotNull jobject javaObject,
347 sjme_attrInNotNull sjme_alloc_weak nativeWeak)
349 jclass collectorClass;
350 jmethodID pushMethod;
352 if (env == NULL || javaObject == NULL || nativeWeak == NULL)
353 return SJME_ERROR_NULL_ARGUMENTS;
355 /* Find collector class. */
356 collectorClass = (*env)->FindClass(env, DESC_DYLIB_COLLECTOR);
357 if (collectorClass == NULL)
358 return SJME_ERROR_JNI_EXCEPTION;
360 /* Find push method. */
361 pushMethod = (*env)->GetStaticMethodID(env, collectorClass,
362 "__push", "(Ljava/lang/Object;J)V");
363 if (pushMethod == NULL)
364 return SJME_ERROR_JNI_EXCEPTION;
366 /* Call it. */
367 (*env)->CallStaticVoidMethod(env, collectorClass, pushMethod,
368 javaObject, (jlong)nativeWeak);
370 /* Check for failure. */
371 if (sjme_jni_checkVMException(env))
372 return SJME_ERROR_JNI_EXCEPTION;
374 /* Success! */
375 return SJME_ERROR_NONE;
378 sjme_errorCode sjme_jni_arrayType(
379 sjme_attrInNotNull JNIEnv* env,
380 sjme_attrInNotNull jobject array,
381 sjme_attrOutNotNull sjme_basicTypeId* outType)
383 jclass classy;
385 if (env == NULL || array == NULL || outType == NULL)
386 return SJME_ERROR_NULL_ARGUMENTS;
388 if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[Z")))
389 *outType = SJME_BASIC_TYPE_ID_BOOLEAN;
390 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[B")))
391 *outType = SJME_BASIC_TYPE_ID_BYTE;
392 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[S")))
393 *outType = SJME_BASIC_TYPE_ID_SHORT;
394 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[C")))
395 *outType = SJME_BASIC_TYPE_ID_CHARACTER;
396 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[I")))
397 *outType = SJME_BASIC_TYPE_ID_INTEGER;
398 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[J")))
399 *outType = SJME_BASIC_TYPE_ID_LONG;
400 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[F")))
401 *outType = SJME_BASIC_TYPE_ID_FLOAT;
402 else if ((*env)->IsInstanceOf(env, array, (*env)->FindClass(env, "[D")))
403 *outType = SJME_BASIC_TYPE_ID_DOUBLE;
404 else
405 return SJME_ERROR_INVALID_ARGUMENT;
407 /* Success! */
408 return SJME_ERROR_NONE;
411 sjme_errorCode sjme_jni_arrayGetElements(
412 sjme_attrInNotNull JNIEnv* env,
413 sjme_attrInNotNull jobject array,
414 sjme_attrOutNotNull sjme_pointer* rawBuf,
415 sjme_attrOutNotNull jboolean* isCopy,
416 sjme_attrOutNullable sjme_jint* typeSize)
418 sjme_errorCode error;
419 sjme_javaTypeId type;
421 if (env == NULL || array == NULL || rawBuf == NULL || isCopy == NULL)
422 return SJME_ERROR_NULL_ARGUMENTS;
424 /* Get array type. */
425 type = -1;
426 if (sjme_error_is(error = sjme_jni_arrayType(env, array,
427 &type)) || type < 0)
428 return sjme_error_default(error);
430 /* Depends on the type. */
431 switch (type)
433 case SJME_BASIC_TYPE_ID_BOOLEAN:
434 *rawBuf = (*env)->GetBooleanArrayElements(env, array, isCopy);
435 if (typeSize != NULL)
436 *typeSize = 1;
437 break;
439 case SJME_BASIC_TYPE_ID_BYTE:
440 *rawBuf = (*env)->GetByteArrayElements(env, array, isCopy);
441 if (typeSize != NULL)
442 *typeSize = 1;
443 break;
445 case SJME_BASIC_TYPE_ID_SHORT:
446 *rawBuf = (*env)->GetShortArrayElements(env, array, isCopy);
447 if (typeSize != NULL)
448 *typeSize = 2;
449 break;
451 case SJME_BASIC_TYPE_ID_CHARACTER:
452 *rawBuf = (*env)->GetCharArrayElements(env, array, isCopy);
453 if (typeSize != NULL)
454 *typeSize = 2;
455 break;
457 case SJME_BASIC_TYPE_ID_INTEGER:
458 *rawBuf = (*env)->GetIntArrayElements(env, array, isCopy);
459 if (typeSize != NULL)
460 *typeSize = 4;
461 break;
463 case SJME_BASIC_TYPE_ID_LONG:
464 *rawBuf = (*env)->GetLongArrayElements(env, array, isCopy);
465 if (typeSize != NULL)
466 *typeSize = 8;
467 break;
469 case SJME_BASIC_TYPE_ID_FLOAT:
470 *rawBuf = (*env)->GetFloatArrayElements(env, array, isCopy);
471 if (typeSize != NULL)
472 *typeSize = 4;
473 break;
475 case SJME_BASIC_TYPE_ID_DOUBLE:
476 *rawBuf = (*env)->GetDoubleArrayElements(env, array, isCopy);
477 if (typeSize != NULL)
478 *typeSize = 8;
479 break;
481 default:
482 return SJME_ERROR_INVALID_ARGUMENT;
485 /* Success! */
486 return SJME_ERROR_NONE;
489 sjme_errorCode sjme_jni_arrayReleaseElements(
490 sjme_attrInNotNull JNIEnv* env,
491 sjme_attrInNotNull jarray array,
492 sjme_attrInNotNull sjme_pointer rawBuf)
494 sjme_errorCode error;
495 sjme_javaTypeId type;
497 if (env == NULL || array == NULL || rawBuf == NULL)
498 return SJME_ERROR_NULL_ARGUMENTS;
500 /* Get array type. */
501 type = -1;
502 if (sjme_error_is(error = sjme_jni_arrayType(env, array,
503 &type)) || type < 0)
504 return sjme_error_default(error);
506 /* Depends on the type. */
507 switch (type)
509 case SJME_BASIC_TYPE_ID_BOOLEAN:
510 (*env)->ReleaseBooleanArrayElements(env, array, rawBuf, 0);
511 break;
513 case SJME_BASIC_TYPE_ID_BYTE:
514 (*env)->ReleaseByteArrayElements(env, array, rawBuf, 0);
515 break;
517 case SJME_BASIC_TYPE_ID_SHORT:
518 (*env)->ReleaseShortArrayElements(env, array, rawBuf, 0);
519 break;
521 case SJME_BASIC_TYPE_ID_CHARACTER:
522 (*env)->ReleaseCharArrayElements(env, array, rawBuf, 0);
523 break;
525 case SJME_BASIC_TYPE_ID_INTEGER:
526 (*env)->ReleaseIntArrayElements(env, array, rawBuf, 0);
527 break;
529 case SJME_BASIC_TYPE_ID_LONG:
530 (*env)->ReleaseLongArrayElements(env, array, rawBuf, 0);
531 break;
533 case SJME_BASIC_TYPE_ID_FLOAT:
534 (*env)->ReleaseFloatArrayElements(env, array, rawBuf, 0);
535 break;
537 case SJME_BASIC_TYPE_ID_DOUBLE:
538 (*env)->ReleaseDoubleArrayElements(env, array, rawBuf, 0);
539 break;
541 default:
542 return SJME_ERROR_INVALID_ARGUMENT;
545 /* Success! */
546 return SJME_ERROR_NONE;