Branch data Line data Source code
1 : : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 : : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
3 : : // SPDX-FileCopyrightText: 2008 litl, LLC
4 : :
5 : : #include <config.h>
6 : :
7 : : #include <girepository.h>
8 : : #include <glib-object.h>
9 : : #include <glib.h>
10 : :
11 : : #include <js/PropertyAndElement.h>
12 : : #include <js/RootingAPI.h>
13 : : #include <js/TypeDecls.h>
14 : : #include <jsapi.h> // for JS_NewPlainObject
15 : :
16 : : #include "gi/cwrapper.h"
17 : : #include "gi/enumeration.h"
18 : : #include "gi/wrapperutils.h"
19 : : #include "gjs/jsapi-util.h"
20 : : #include "gjs/macros.h"
21 : : #include "util/log.h"
22 : :
23 : : GJS_JSAPI_RETURN_CONVENTION
24 : : static bool
25 : 1533 : gjs_define_enum_value(JSContext *context,
26 : : JS::HandleObject in_object,
27 : : GIValueInfo *info)
28 : : {
29 : : const char* value_name;
30 : : gsize i;
31 : : gint64 value_val;
32 : :
33 : 1533 : value_name = g_base_info_get_name( (GIBaseInfo*) info);
34 : 1533 : value_val = g_value_info_get_value(info);
35 : :
36 : : /* g-i converts enum members such as GDK_GRAVITY_SOUTH_WEST to
37 : : * Gdk.GravityType.south-west (where 'south-west' is value_name)
38 : : * Convert back to all SOUTH_WEST.
39 : : */
40 : 1533 : GjsAutoChar fixed_name = g_ascii_strup(value_name, -1);
41 [ + + ]: 16897 : for (i = 0; fixed_name[i]; ++i) {
42 : 15364 : char c = fixed_name[i];
43 [ + + + + : 15364 : if (!(('A' <= c && c <= 'Z') ||
+ - ]
44 [ + + ]: 1205 : ('0' <= c && c <= '9')))
45 : 1075 : fixed_name[i] = '_';
46 : : }
47 : :
48 : 1533 : gjs_debug(GJS_DEBUG_GENUM,
49 : : "Defining enum value %s (fixed from %s) %" G_GINT64_MODIFIER "d",
50 : : fixed_name.get(), value_name, value_val);
51 : :
52 [ - + ]: 1533 : if (!JS_DefineProperty(context, in_object,
53 : : fixed_name, (double) value_val,
54 : : GJS_MODULE_PROP_FLAGS)) {
55 : 0 : gjs_throw(context,
56 : : "Unable to define enumeration value %s %" G_GINT64_FORMAT
57 : : " (no memory most likely)",
58 : : fixed_name.get(), value_val);
59 : 0 : return false;
60 : : }
61 : :
62 : 1533 : return true;
63 : 1533 : }
64 : :
65 : : bool
66 : 158 : gjs_define_enum_values(JSContext *context,
67 : : JS::HandleObject in_object,
68 : : GIEnumInfo *info)
69 : : {
70 : : int i, n_values;
71 : :
72 : : /* Fill in enum values first, so we don't define the enum itself until we're
73 : : * sure we can finish successfully.
74 : : */
75 : 158 : n_values = g_enum_info_get_n_values(info);
76 [ + + ]: 1691 : for (i = 0; i < n_values; ++i) {
77 : 1533 : GjsAutoBaseInfo value_info = g_enum_info_get_value(info, i);
78 : :
79 [ - + ]: 1533 : if (!gjs_define_enum_value(context, in_object, value_info))
80 : 0 : return false;
81 [ + - ]: 1533 : }
82 : 158 : return true;
83 : : }
84 : :
85 : : bool
86 : 147 : gjs_define_enumeration(JSContext *context,
87 : : JS::HandleObject in_object,
88 : : GIEnumInfo *info)
89 : : {
90 : : const char *enum_name;
91 : :
92 : : /* An enumeration is simply an object containing integer attributes for
93 : : * each enum value. It does not have a special JSClass.
94 : : *
95 : : * We could make this more typesafe and also print enum values as strings
96 : : * if we created a class for each enum and made the enum values instances
97 : : * of that class. However, it would have a lot more overhead and just
98 : : * be more complicated in general. I think this is fine.
99 : : */
100 : :
101 : 147 : enum_name = g_base_info_get_name( (GIBaseInfo*) info);
102 : :
103 : 147 : JS::RootedObject enum_obj(context, JS_NewPlainObject(context));
104 [ - + ]: 147 : if (!enum_obj) {
105 : 0 : gjs_throw(context, "Could not create enumeration %s.%s",
106 : : g_base_info_get_namespace(info), enum_name);
107 : 0 : return false;
108 : : }
109 : :
110 : 147 : GType gtype = g_registered_type_info_get_g_type(info);
111 : :
112 : 147 : if (!gjs_define_enum_values(context, enum_obj, info) ||
113 [ + - ]: 147 : !gjs_define_static_methods<InfoType::Enum>(context, enum_obj, gtype,
114 [ + - ]: 294 : info) ||
115 [ - + - + ]: 294 : !gjs_wrapper_define_gtype_prop(context, enum_obj, gtype))
116 : 0 : return false;
117 : :
118 : 147 : gjs_debug(GJS_DEBUG_GENUM,
119 : : "Defining %s.%s as %p",
120 : : g_base_info_get_namespace( (GIBaseInfo*) info),
121 : 147 : enum_name, enum_obj.get());
122 : :
123 [ - + ]: 147 : if (!JS_DefineProperty(context, in_object, enum_name, enum_obj,
124 : : GJS_MODULE_PROP_FLAGS)) {
125 : 0 : gjs_throw(context, "Unable to define enumeration property (no memory most likely)");
126 : 0 : return false;
127 : : }
128 : :
129 : 147 : return true;
130 : 147 : }
|