Example #1
0
/*
 * Convert a JavaSignature object into a human-readable string format as seen
 * in Java source files, e.g. "byte", or "int[][]" or "java.lang.String".
 * The caller is responsible for freeing the resulting string.
 *
 * If an error is encountered, NULL is returned and an error reported.
 */
const char *
jsj_ConvertJavaSignatureToHRString(JSContext *cx,
                                   JavaSignature *signature)
{
    char *sig;
    JavaSignature *acs;

    if (signature->type == JAVA_SIGNATURE_ARRAY) {
        /* An array class */
        const char *component_signature_string;
        acs = signature->array_component_signature;
        component_signature_string =
            jsj_ConvertJavaSignatureToHRString(cx, acs);
        if (!component_signature_string)
            return NULL;
        sig = JS_smprintf("%s[]", component_signature_string);
        JS_smprintf_free((char*)component_signature_string);

    } else {
        /* A primitive class or a non-array object class */
        sig = JS_smprintf("%s", signature->name);
    }

    if (!sig) {
        JS_ReportOutOfMemory(cx);
        return NULL;
    }
    return sig;
}
Example #2
0
/*
 * Convert a JS value to a Java value of the given type signature.  The cost
 * variable is incremented if coercion is required, e.g. the source value is
 * a string, but the target type is a boolean.
 *
 * Returns JS_FALSE if no conversion is possible, either because the jsval has
 * a type that is wholly incompatible with the Java value, or because a scalar
 * jsval can't be represented in a variable of the target type without loss of
 * precision, e.g. the source value is "4.2" but the destination type is byte.
 * If conversion is not possible and java_value is non-NULL, the JS error
 * reporter is called with an appropriate message.
 */  
JSBool
jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v_arg,
                              JavaSignature *signature,
                              int *cost, jvalue *java_value, JSBool *is_local_refp)
{
    JavaSignatureChar type;
    jsval v;
    JSBool success = JS_FALSE;

    /* Initialize to default case, in which no new Java object is
       synthesized to perform the conversion and, therefore, no JNI local
       references are being held. */
    *is_local_refp = JS_FALSE;   
    
    type = signature->type;
    v = v_arg;
    switch (type) {
    case JAVA_SIGNATURE_BOOLEAN:
        if (!JSVAL_IS_BOOLEAN(v)) {
            if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v))
                goto conversion_error;
            if (JSVAL_IS_VOID(v))
                goto conversion_error;
            (*cost)++;
        }
        if (java_value)
            java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE);
        break;

    case JAVA_SIGNATURE_SHORT:
        JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value);
        break;

    case JAVA_SIGNATURE_BYTE:
        JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value);
        break;

    case JAVA_SIGNATURE_CHAR:
        /* A one-character string can be converted into a character */
        if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) {
            v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v)));
        }
        JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value);
        break;

    case JAVA_SIGNATURE_INT:
        JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value);
        break;

    case JAVA_SIGNATURE_LONG:
#if defined(XP_MAC) || (defined(XP_OS2) && !defined(HAVE_LONG_LONG))
        JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value);
#else
        JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value);
#endif
        break;
    
    case JAVA_SIGNATURE_FLOAT:
        if (!JSVAL_IS_NUMBER(v)) {
            if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v))
                goto conversion_error;
            (*cost)++;
        }
        if (java_value) {
            if (JSVAL_IS_INT(v))
                java_value->f = (jfloat) JSVAL_TO_INT(v);
            else
                java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v);
        }
        break;

    case JAVA_SIGNATURE_DOUBLE:
        if (!JSVAL_IS_NUMBER(v)) {
            if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v))
                goto conversion_error;
            (*cost)++;
        }
        if (java_value) {
            if (JSVAL_IS_INT(v))
                java_value->d = (jdouble) JSVAL_TO_INT(v);
            else
                java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v);
        }
        break;

    /* Non-primitive (reference) type */
    default:
        JS_ASSERT(IS_REFERENCE_TYPE(type));
        if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost,
            &java_value->l, is_local_refp))
            goto conversion_error;
        break;

    case JAVA_SIGNATURE_UNKNOWN:
    case JAVA_SIGNATURE_VOID:
        JS_ASSERT(0);
        return JS_FALSE;
    }

    /* Success */
    return JS_TRUE;

numeric_conversion_error:
    success = JS_TRUE;
    /* Fall through ... */

conversion_error:

    if (java_value) {
        const char *jsval_string;
        const char *class_name;
        JSString *jsstr;

        jsval_string = NULL;
        jsstr = JS_ValueToString(cx, v_arg);
        if (jsstr)
            jsval_string = JS_GetStringBytes(jsstr);
        if (!jsval_string)
            jsval_string = "";
        
        class_name = jsj_ConvertJavaSignatureToHRString(cx, signature);
        JS_ReportErrorNumber(cx, jsj_GetErrorMessage, NULL, 
                             JSJMSG_CANT_CONVERT_JS, jsval_string,
                             class_name);

        return JS_FALSE;
    }
    return success;
}