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 <stddef.h> // for size_t
8 : : #include <inttypes.h>
9 : :
10 : : #include <algorithm>
11 : :
12 : : #include <glib-object.h>
13 : : #include <glib.h>
14 : :
15 : : #include <js/PropertyAndElement.h>
16 : : #include <js/RootingAPI.h>
17 : : #include <js/TypeDecls.h>
18 : : #include <jsapi.h> // for JS_NewPlainObject
19 : :
20 : : #include "gi/cwrapper.h"
21 : : #include "gi/enumeration.h"
22 : : #include "gi/info.h"
23 : : #include "gi/wrapperutils.h"
24 : : #include "gjs/auto.h"
25 : : #include "gjs/jsapi-util.h"
26 : : #include "gjs/macros.h"
27 : : #include "util/log.h"
28 : :
29 : : GJS_JSAPI_RETURN_CONVENTION
30 : 2192 : static bool gjs_define_enum_value(JSContext* cx, JS::HandleObject in_object,
31 : : const GI::ValueInfo& info) {
32 : 2192 : const char* value_name = info.name();
33 : 2192 : int64_t value_val = info.value();
34 : :
35 : : /* g-i converts enum members such as GDK_GRAVITY_SOUTH_WEST to
36 : : * Gdk.GravityType.south-west (where 'south-west' is value_name) Convert
37 : : * back to all SOUTH_WEST.
38 : : */
39 : 2192 : Gjs::AutoChar fixed_name{g_ascii_strup(value_name, -1)};
40 [ + + ]: 23922 : for (size_t i = 0; fixed_name[i]; ++i) {
41 : 21730 : char c = fixed_name[i];
42 [ + + + + ]: 21730 : if (!(g_ascii_isupper(c) || g_ascii_isdigit(c)))
43 : 1524 : fixed_name[i] = '_';
44 : : }
45 : :
46 : 2192 : gjs_debug(GJS_DEBUG_GENUM,
47 : : "Defining enum value %s (fixed from %s) %" PRId64,
48 : : fixed_name.get(), value_name, value_val);
49 : :
50 [ - + ]: 2192 : if (!JS_DefineProperty(cx, in_object, fixed_name,
51 : : static_cast<double>(value_val),
52 : : GJS_MODULE_PROP_FLAGS)) {
53 : 0 : gjs_throw(cx,
54 : : "Unable to define enumeration value %s %" PRId64
55 : : " (no memory most likely)",
56 : : fixed_name.get(), value_val);
57 : 0 : return false;
58 : : }
59 : :
60 : 2192 : return true;
61 : 2192 : }
62 : :
63 : 239 : bool gjs_define_enum_values(JSContext* cx, JS::HandleObject in_object,
64 : : const GI::EnumInfo& info) {
65 : : /* Fill in enum values first, so we don't define the enum itself until we're
66 : : * sure we can finish successfully.
67 : : */
68 : 239 : auto iter = info.values();
69 : 239 : return std::all_of(iter.begin(), iter.end(),
70 : 2192 : [cx, in_object](const GI::AutoValueInfo& value_info) {
71 : 2192 : return gjs_define_enum_value(cx, in_object,
72 : 4384 : value_info);
73 : 239 : });
74 : : }
75 : :
76 : 225 : bool gjs_define_enumeration(JSContext* cx, JS::HandleObject in_object,
77 : : const GI::EnumInfo& info) {
78 : : /* An enumeration is simply an object containing integer attributes for each
79 : : * enum value. It does not have a special JSClass.
80 : : *
81 : : * We could make this more typesafe and also print enum values as strings if
82 : : * we created a class for each enum and made the enum values instances of
83 : : * that class. However, it would have a lot more overhead and just be more
84 : : * complicated in general. I think this is fine.
85 : : */
86 : :
87 : 225 : const char* enum_name = info.name();
88 : :
89 : 225 : JS::RootedObject enum_obj{cx, JS_NewPlainObject(cx)};
90 [ - + ]: 225 : if (!enum_obj) {
91 : 0 : gjs_throw(cx, "Could not create enumeration %s.%s", info.ns(),
92 : : enum_name);
93 : 0 : return false;
94 : : }
95 : :
96 : 225 : GType gtype = info.gtype();
97 : :
98 : 225 : if (!gjs_define_enum_values(cx, enum_obj, info) ||
99 [ + - + - ]: 450 : !gjs_define_static_methods(cx, enum_obj, gtype, info) ||
100 [ - + - + ]: 450 : !gjs_wrapper_define_gtype_prop(cx, enum_obj, gtype))
101 : 0 : return false;
102 : :
103 : 225 : gjs_debug(GJS_DEBUG_GENUM, "Defining %s.%s as %p", info.ns(), enum_name,
104 : 225 : enum_obj.get());
105 : :
106 [ - + ]: 225 : if (!JS_DefineProperty(cx, in_object, enum_name, enum_obj,
107 : : GJS_MODULE_PROP_FLAGS)) {
108 : 0 : gjs_throw(
109 : : cx,
110 : : "Unable to define enumeration property (no memory most likely)");
111 : 0 : return false;
112 : : }
113 : :
114 : 225 : return true;
115 : 225 : }
|