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