Exemplo n.º 1
0
Arquivo: param.c Projeto: goizueta/gjs
static JSBool
param_new_internal(JSContext *cx,
                   uintN      argc,
                   jsval     *vp)
{
    jsval *argv = JS_ARGV(cx, vp);
    GParamSpec *pspec = NULL;
    JSBool ret = JS_FALSE;
    gchar *method_name;

    gchar *prop_name;
    JSObject *prop_gtype_jsobj;
    GType prop_gtype;
    GType prop_type;
    gchar *nick;
    gchar *blurb;
    GParamFlags flags;

    if (!gjs_parse_args(cx, "GObject.ParamSpec._new_internal",
                        "!sossi", argc, argv,
                        "prop_name", &prop_name,
                        "prop_gtype", &prop_gtype_jsobj,
                        "nick", &nick,
                        "blurb", &blurb,
                        "flags", &flags))
        return JS_FALSE;

    prop_gtype = gjs_gtype_get_actual_gtype(cx, prop_gtype_jsobj);
    prop_type = G_TYPE_FUNDAMENTAL(prop_gtype);

    method_name = g_strdup_printf("GObject.ParamSpec.%s",
                                  g_type_name(prop_type));

    argv += 5;
    argc -= 5;

    switch (prop_type) {
    case G_TYPE_UCHAR:
    case G_TYPE_CHAR:
	{
	    gchar *minimum, *maximum, *default_value;

            if (!gjs_parse_args(cx, method_name,
                                "sss", argc, argv,
                                "minimum", &minimum,
                                "maximum", &maximum,
                                "default_value", &default_value))
                goto out;

            if (prop_type == G_TYPE_CHAR)
                pspec = g_param_spec_char(prop_name, nick, blurb,
                                          minimum[0], maximum[0], default_value[0],
                                          flags);
            else
                pspec = g_param_spec_uchar(prop_name, nick, blurb,
                                           minimum[0], maximum[0], default_value[0],
                                           flags);
 
            g_free(minimum);
            g_free(maximum);
            g_free(default_value);
	}
	break;
    case G_TYPE_INT:
    case G_TYPE_UINT:
    case G_TYPE_LONG:
    case G_TYPE_ULONG:
    case G_TYPE_INT64:
    case G_TYPE_UINT64:
        {
            gint64 minimum, maximum, default_value;

            if (!gjs_parse_args(cx, method_name,
                                "ttt", argc, argv,
                                "minimum", &minimum,
                                "maximum", &maximum,
                                "default_value", &default_value))
                goto out;

            switch (prop_type) {
            case G_TYPE_INT:
                pspec = g_param_spec_int(prop_name, nick, blurb,
                                         minimum, maximum, default_value, flags);
                break;
            case G_TYPE_UINT:
                pspec = g_param_spec_uint(prop_name, nick, blurb,
                                          minimum, maximum, default_value, flags);
                break;
            case G_TYPE_LONG:
                pspec = g_param_spec_long(prop_name, nick, blurb,
                                          minimum, maximum, default_value, flags);
                break;
            case G_TYPE_ULONG:
                pspec = g_param_spec_ulong(prop_name, nick, blurb,
                                           minimum, maximum, default_value, flags);
                break;
            case G_TYPE_INT64:
                pspec = g_param_spec_int64(prop_name, nick, blurb,
                                           minimum, maximum, default_value, flags);
                break;
            case G_TYPE_UINT64:
                pspec = g_param_spec_uint64(prop_name, nick, blurb,
                                            minimum, maximum, default_value, flags);
                break;
            }
        }
        break;
    case G_TYPE_BOOLEAN:
        {
            gboolean default_value;

            if (!gjs_parse_args(cx, method_name,
                                "b", argc, argv,
                                "default_value", &default_value))
                goto out;

            default_value = JSVAL_TO_BOOLEAN(argv[0]);

            pspec = g_param_spec_boolean(prop_name, nick, blurb,
                                         default_value, flags);
        }
        break;
    case G_TYPE_ENUM:
        {
            JSObject *gtype_jsobj;
            GType gtype;
            GIEnumInfo *info;
            gint64 default_value;

            if (!gjs_parse_args(cx, method_name,
                                "ot", argc, argv,
                                "gtype", &gtype_jsobj,
                                "default_value", &default_value))
                goto out;

            gtype = gjs_gtype_get_actual_gtype(cx, gtype_jsobj);
            if (gtype == G_TYPE_NONE) {
                gjs_throw(cx, "Passed invalid GType to GParamSpecEnum constructor");
                goto out;
            }

            info = g_irepository_find_by_gtype(g_irepository_get_default(), gtype);

            if (!_gjs_enum_value_is_valid(cx, info, default_value))
                goto out;

            pspec = g_param_spec_enum(prop_name, nick, blurb,
                                      gtype, default_value, flags);
        }
        break;
    case G_TYPE_FLAGS:
        {
            JSObject *gtype_jsobj;
            GType gtype;
            gint64 default_value;

            if (!gjs_parse_args(cx, method_name,
                                "ot", argc, argv,
                                "gtype", &gtype_jsobj,
                                "default_value", &default_value))
                goto out;

            gtype = gjs_gtype_get_actual_gtype(cx, gtype_jsobj);
            if (gtype == G_TYPE_NONE) {
                gjs_throw(cx, "Passed invalid GType to GParamSpecFlags constructor");
                goto out;
            }

            if (!_gjs_flags_value_is_valid(cx, gtype, default_value))
                goto out;

            pspec = g_param_spec_flags(prop_name, nick, blurb,
                                       gtype, default_value, flags);
        }
        break;
    case G_TYPE_FLOAT:
    case G_TYPE_DOUBLE:
        {
	    gfloat minimum, maximum, default_value;

            if (!gjs_parse_args(cx, "GObject.ParamSpec.float",
                                "fff", argc, argv,
                                "minimum", &minimum,
                                "maximum", &maximum,
                                "default_value", &default_value))
                goto out;

            if (prop_type == G_TYPE_FLOAT)
                pspec = g_param_spec_float(prop_name, nick, blurb,
                                           minimum, maximum, default_value, flags);
            else
                pspec = g_param_spec_double(prop_name, nick, blurb,
                                            minimum, maximum, default_value, flags);
        }
        break;
    case G_TYPE_STRING:
        {
            gchar *default_value;

            if (!gjs_parse_args(cx, method_name,
                                "s", argc, argv,
                                "default_value", &default_value))
                goto out;

            pspec = g_param_spec_string(prop_name, nick, blurb,
                                        default_value, flags);

            g_free (default_value);
        }
        break;
    case G_TYPE_PARAM:
        pspec = g_param_spec_param(prop_name, nick, blurb, prop_type, flags);
        break;
    case G_TYPE_BOXED:
        pspec = g_param_spec_boxed(prop_name, nick, blurb, prop_type, flags);
        break;
    case G_TYPE_POINTER:
        pspec = g_param_spec_pointer(prop_name, nick, blurb, flags);
        break;
    case G_TYPE_OBJECT:
        pspec = g_param_spec_object(prop_name, nick, blurb, prop_type, flags);
        break;
    default:
        gjs_throw(cx,
                  "Could not create param spec for type '%s'",
                  g_type_name(prop_gtype));
        goto out;
    }

    ret = JS_TRUE;

    jsval foo = OBJECT_TO_JSVAL(gjs_param_from_g_param(cx, pspec));

    JS_SET_RVAL(cx, vp, foo);
 out:

    g_free(method_name);
    g_free(prop_name);
    g_free(nick);
    g_free(blurb);

    return ret;
}
Exemplo n.º 2
0
static JSBool
gjs_value_from_g_value_internal(JSContext    *context,
                                jsval        *value_p,
                                const GValue *gvalue,
                                gboolean      no_copy,
                                GSignalQuery *signal_query,
                                gint          arg_n)
{
    GType gtype;

    gtype = G_VALUE_TYPE(gvalue);

    gjs_debug_marshal(GJS_DEBUG_GCLOSURE,
                      "Converting gtype %s to jsval",
                      g_type_name(gtype));

    if (gtype == G_TYPE_STRING) {
        const char *v;
        v = g_value_get_string(gvalue);
        if (v == NULL) {
            gjs_debug_marshal(GJS_DEBUG_GCLOSURE,
                              "Converting NULL string to JSVAL_NULL");
            *value_p = JSVAL_NULL;
        } else {
            if (!gjs_string_from_utf8(context, v, -1, value_p))
                return JS_FALSE;
        }
    } else if (gtype == G_TYPE_CHAR) {
        char v;
        v = g_value_get_schar(gvalue);
        *value_p = INT_TO_JSVAL(v);
    } else if (gtype == G_TYPE_UCHAR) {
        unsigned char v;
        v = g_value_get_uchar(gvalue);
        *value_p = INT_TO_JSVAL(v);
    } else if (gtype == G_TYPE_INT) {
        int v;
        v = g_value_get_int(gvalue);
        return JS_NewNumberValue(context, v, value_p);
    } else if (gtype == G_TYPE_UINT) {
        uint v;
        v = g_value_get_uint(gvalue);
        return JS_NewNumberValue(context, v, value_p);
    } else if (gtype == G_TYPE_DOUBLE) {
        double d;
        d = g_value_get_double(gvalue);
        return JS_NewNumberValue(context, d, value_p);
    } else if (gtype == G_TYPE_FLOAT) {
        double d;
        d = g_value_get_float(gvalue);
        return JS_NewNumberValue(context, d, value_p);
    } else if (gtype == G_TYPE_BOOLEAN) {
        gboolean v;
        v = g_value_get_boolean(gvalue);
        *value_p = BOOLEAN_TO_JSVAL(v);
    } else if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
        GObject *gobj;
        JSObject *obj;

        gobj = g_value_get_object(gvalue);

        obj = gjs_object_from_g_object(context, gobj);
        *value_p = OBJECT_TO_JSVAL(obj);
    } else if (gtype == G_TYPE_STRV) {
        if (!gjs_array_from_strv (context,
                                  value_p,
                                  g_value_get_boxed (gvalue))) {
            gjs_throw(context, "Failed to convert strv to array");
            return JS_FALSE;
        }
    } else if (g_type_is_a(gtype, G_TYPE_HASH_TABLE) ||
               g_type_is_a(gtype, G_TYPE_ARRAY) ||
               g_type_is_a(gtype, G_TYPE_BYTE_ARRAY) ||
               g_type_is_a(gtype, G_TYPE_PTR_ARRAY)) {
        gjs_throw(context,
                  "Unable to introspect element-type of container in GValue");
        return JS_FALSE;
    } else if (g_type_is_a(gtype, G_TYPE_BOXED) ||
               g_type_is_a(gtype, G_TYPE_VARIANT)) {
        GjsBoxedCreationFlags boxed_flags;
        GIBaseInfo *info;
        void *gboxed;
        JSObject *obj;

        if (g_type_is_a(gtype, G_TYPE_BOXED))
            gboxed = g_value_get_boxed(gvalue);
        else
            gboxed = g_value_get_variant(gvalue);
        boxed_flags = GJS_BOXED_CREATION_NONE;

        /* special case GError */
        if (g_type_is_a(gtype, G_TYPE_ERROR)) {
            obj = gjs_error_from_gerror(context, gboxed, FALSE);
            *value_p = OBJECT_TO_JSVAL(obj);

            return TRUE;
        }

        /* The only way to differentiate unions and structs is from
         * their g-i info as both GBoxed */
        info = g_irepository_find_by_gtype(g_irepository_get_default(),
                                           gtype);
        if (info == NULL) {
            gjs_throw(context,
                      "No introspection information found for %s",
                      g_type_name(gtype));
            return JS_FALSE;
        }

        if (g_base_info_get_type(info) == GI_INFO_TYPE_STRUCT &&
            g_struct_info_is_foreign((GIStructInfo*)info)) {
            JSBool ret;
            GIArgument arg;
            arg.v_pointer = gboxed;
            ret = gjs_struct_foreign_convert_from_g_argument(context, value_p, info, &arg);
            g_base_info_unref(info);
            return ret;
        }

        switch (g_base_info_get_type(info)) {
        case GI_INFO_TYPE_BOXED:
        case GI_INFO_TYPE_STRUCT:
            if (no_copy)
                boxed_flags |= GJS_BOXED_CREATION_NO_COPY;
            obj = gjs_boxed_from_c_struct(context, (GIStructInfo *)info, gboxed, boxed_flags);
            break;
        case GI_INFO_TYPE_UNION:
            obj = gjs_union_from_c_union(context, (GIUnionInfo *)info, gboxed);
            break;
        default:
            gjs_throw(context,
                      "Unexpected introspection type %d for %s",
                      g_base_info_get_type(info),
                      g_type_name(gtype));
            g_base_info_unref(info);
            return JS_FALSE;
        }

        *value_p = OBJECT_TO_JSVAL(obj);
        g_base_info_unref(info);
    } else if (g_type_is_a(gtype, G_TYPE_ENUM)) {
        return convert_int_to_enum(context, value_p, gtype, g_value_get_enum(gvalue));
    } else if (g_type_is_a(gtype, G_TYPE_PARAM)) {
        GParamSpec *gparam;
        JSObject *obj;

        gparam = g_value_get_param(gvalue);

        obj = gjs_param_from_g_param(context, gparam);
        *value_p = OBJECT_TO_JSVAL(obj);
    } else if (signal_query && g_type_is_a(gtype, G_TYPE_POINTER)) {
        JSBool res;
        GArgument arg;
        GIArgInfo *arg_info;
        GIBaseInfo *obj;
        GISignalInfo *signal_info;
        GITypeInfo type_info;

        obj = g_irepository_find_by_gtype(NULL, signal_query->itype);
        if (!obj) {
            gjs_throw(context, "Signal argument with GType %s isn't introspectable",
                      g_type_name(signal_query->itype));
            return JS_FALSE;
        }

        signal_info = g_object_info_find_signal((GIObjectInfo*)obj, signal_query->signal_name);

        if (!signal_info) {
            gjs_throw(context, "Unknown signal.");
            g_base_info_unref((GIBaseInfo*)obj);
            return JS_FALSE;
        }
        arg_info = g_callable_info_get_arg(signal_info, arg_n - 1);
        g_arg_info_load_type(arg_info, &type_info);

        arg.v_pointer = g_value_get_pointer(gvalue);

        res = gjs_value_from_g_argument(context, value_p, &type_info, &arg, TRUE);

        g_base_info_unref((GIBaseInfo*)arg_info);
        g_base_info_unref((GIBaseInfo*)signal_info);
        g_base_info_unref((GIBaseInfo*)obj);
        return res;
    } else if (g_type_is_a(gtype, G_TYPE_POINTER)) {
        gpointer pointer;

        pointer = g_value_get_pointer(gvalue);

        if (pointer == NULL) {
            *value_p = JSVAL_NULL;
        } else {
            gjs_throw(context,
                      "Can't convert non-null pointer to JS value");
            return JS_FALSE;
        }
    } else if (g_value_type_transformable(gtype, G_TYPE_DOUBLE)) {
        GValue double_value = { 0, };
        double v;
        g_value_init(&double_value, G_TYPE_DOUBLE);
        g_value_transform(gvalue, &double_value);
        v = g_value_get_double(&double_value);
        return JS_NewNumberValue(context, v, value_p);
    } else if (g_value_type_transformable(gtype, G_TYPE_INT)) {
        GValue int_value = { 0, };
        int v;
        g_value_init(&int_value, G_TYPE_INT);
        g_value_transform(gvalue, &int_value);
        v = g_value_get_int(&int_value);
        return JS_NewNumberValue(context, v, value_p);
    } else {
        gjs_throw(context,
                  "Don't know how to convert GType %s to JavaScript object",
                  g_type_name(gtype));
        return JS_FALSE;
    }

    return JS_TRUE;
}