1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Struct implementation
3 *
4 * Copyright (C) 2005 Matthias Clasen
5 * Copyright (C) 2008,2009 Red Hat, Inc.
6 *
7 * SPDX-License-Identifier: LGPL-2.1-or-later
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 */
24
25 #include "config.h"
26
27 #include <string.h>
28
29 #include <glib.h>
30
31 #include <girepository/girepository.h>
32 #include "gibaseinfo-private.h"
33 #include "girepository-private.h"
34 #include "gitypelib-internal.h"
35 #include "gistructinfo.h"
36
37 /**
38 * GIStructInfo:
39 *
40 * `GIStructInfo` represents a generic C structure type.
41 *
42 * A structure has methods and fields.
43 *
44 * Since: 2.80
45 */
46
47 /**
48 * gi_struct_info_get_n_fields:
49 * @info: a #GIStructInfo
50 *
51 * Obtain the number of fields this structure has.
52 *
53 * Returns: number of fields
54 * Since: 2.80
55 */
56 guint
57 gi_struct_info_get_n_fields (GIStructInfo *info)
58 {
59 GIRealInfo *rinfo = (GIRealInfo *)info;
60 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
61
62 return blob->n_fields;
63 }
64
65 /**
66 * gi_struct_info_get_field_offset:
67 * @info: a #GIStructInfo
68 * @n: index of queried field
69 *
70 * Obtain the offset of the specified field.
71 *
72 * Returns: field offset, in bytes
73 * Since: 2.80
74 */
75 static gint32
76 gi_struct_get_field_offset (GIStructInfo *info,
77 guint n)
78 {
79 GIRealInfo *rinfo = (GIRealInfo *)info;
80 Header *header = (Header *)rinfo->typelib->data;
81 guint32 offset = rinfo->offset + header->struct_blob_size;
82 FieldBlob *field_blob;
83
84 for (guint i = 0; i < n; i++)
85 {
86 field_blob = (FieldBlob *)&rinfo->typelib->data[offset];
87 offset += header->field_blob_size;
88 if (field_blob->has_embedded_type)
89 offset += header->callback_blob_size;
90 }
91
92 return offset;
93 }
94
95 /**
96 * gi_struct_info_get_field:
97 * @info: a #GIStructInfo
98 * @n: a field index
99 *
100 * Obtain the type information for field with specified index.
101 *
102 * Returns: (transfer full): The [class@GIRepository.FieldInfo]. Free it with
103 * [method@GIRepository.BaseInfo.unref] when done.
104 * Since: 2.80
105 */
106 GIFieldInfo *
107 gi_struct_info_get_field (GIStructInfo *info,
108 guint n)
109 {
110 GIRealInfo *rinfo = (GIRealInfo *)info;
111
112 return (GIFieldInfo *) gi_info_new (GI_INFO_TYPE_FIELD, (GIBaseInfo*)info, rinfo->typelib,
113 gi_struct_get_field_offset (info, n));
114 }
115
116 /**
117 * gi_struct_info_find_field:
118 * @info: a #GIStructInfo
119 * @name: a field name
120 *
121 * Obtain the type information for field named @name.
122 *
123 * Returns: (transfer full) (nullable): The [class@GIRepository.FieldInfo], or
124 * `NULL` if not found. Free it with [method@GIRepository.BaseInfo.unref] when
125 * done.
126 * Since: 2.80
127 */
128 GIFieldInfo *
129 gi_struct_info_find_field (GIStructInfo *info,
130 const gchar *name)
131 {
132 GIRealInfo *rinfo = (GIRealInfo *)info;
133 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
134 Header *header = (Header *)rinfo->typelib->data;
135 guint32 offset = rinfo->offset + header->struct_blob_size;
136 gint i;
137
138 for (i = 0; i < blob->n_fields; i++)
139 {
140 FieldBlob *field_blob = (FieldBlob *)&rinfo->typelib->data[offset];
141 const gchar *fname = (const gchar *)&rinfo->typelib->data[field_blob->name];
142
143 if (strcmp (name, fname) == 0)
144 {
145 return (GIFieldInfo *) gi_info_new (GI_INFO_TYPE_FIELD,
146 (GIBaseInfo* )info,
147 rinfo->typelib,
148 offset);
149 }
150
151 offset += header->field_blob_size;
152 if (field_blob->has_embedded_type)
153 offset += header->callback_blob_size;
154 }
155
156 return NULL;
157 }
158
159 /**
160 * gi_struct_info_get_n_methods:
161 * @info: a #GIStructInfo
162 *
163 * Obtain the number of methods this structure has.
164 *
165 * Returns: number of methods
166 * Since: 2.80
167 */
168 guint
169 gi_struct_info_get_n_methods (GIStructInfo *info)
170 {
171 GIRealInfo *rinfo = (GIRealInfo *)info;
172 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
173
174 return blob->n_methods;
175 }
176
177 /**
178 * gi_struct_info_get_method:
179 * @info: a #GIStructInfo
180 * @n: a method index
181 *
182 * Obtain the type information for method with specified index.
183 *
184 * Returns: (transfer full): The [class@GIRepository.FunctionInfo]. Free it with
185 * [method@GIRepository.BaseInfo.unref] when done.
186 * Since: 2.80
187 */
188 GIFunctionInfo *
189 gi_struct_info_get_method (GIStructInfo *info,
190 guint n)
191 {
192 GIRealInfo *rinfo = (GIRealInfo *)info;
193 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
194 Header *header = (Header *)rinfo->typelib->data;
195 gint offset;
196
197 offset = gi_struct_get_field_offset (info, blob->n_fields) + n * header->function_blob_size;
198 return (GIFunctionInfo *) gi_info_new (GI_INFO_TYPE_FUNCTION, (GIBaseInfo*)info,
199 rinfo->typelib, offset);
200 }
201
202 /**
203 * gi_struct_info_find_method:
204 * @info: a #GIStructInfo
205 * @name: a method name
206 *
207 * Obtain the type information for method named @name.
208 *
209 * Returns: (transfer full) (nullable): The [class@GIRepository.FunctionInfo],
210 * or `NULL` if none was found. Free it with
211 * [method@GIRepository.BaseInfo.unref] when done.
212 * Since: 2.80
213 */
214 GIFunctionInfo *
215 gi_struct_info_find_method (GIStructInfo *info,
216 const gchar *name)
217 {
218 gint offset;
219 GIRealInfo *rinfo = (GIRealInfo *)info;
220 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
221
222 offset = gi_struct_get_field_offset (info, blob->n_fields);
223 return gi_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_methods, name);
224 }
225
226 /**
227 * gi_struct_info_get_size:
228 * @info: a #GIStructInfo
229 *
230 * Obtain the total size of the structure.
231 *
232 * Returns: size of the structure, in bytes
233 * Since: 2.80
234 */
235 gsize
236 gi_struct_info_get_size (GIStructInfo *info)
237 {
238 GIRealInfo *rinfo = (GIRealInfo *)info;
239 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
240
241 return blob->size;
242 }
243
244 /**
245 * gi_struct_info_get_alignment:
246 * @info: a #GIStructInfo
247 *
248 * Obtain the required alignment of the structure.
249 *
250 * Returns: required alignment, in bytes
251 * Since: 2.80
252 */
253 gsize
254 gi_struct_info_get_alignment (GIStructInfo *info)
255 {
256 GIRealInfo *rinfo = (GIRealInfo *)info;
257 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
258
259 return blob->alignment;
260 }
261
262 /**
263 * gi_struct_info_is_foreign:
264 * @info: a #GIStructInfo
265 *
266 * Gets whether the structure is foreign, i.e. if it’s expected to be overridden
267 * by a native language binding instead of relying of introspected bindings.
268 *
269 * Returns: `TRUE` if the structure is foreign
270 * Since: 2.80
271 */
272 gboolean
273 gi_struct_info_is_foreign (GIStructInfo *info)
274 {
275 GIRealInfo *rinfo = (GIRealInfo *)info;
276 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
277
278 return blob->foreign;
279 }
280
281 /**
282 * gi_struct_info_is_gtype_struct:
283 * @info: a #GIStructInfo
284 *
285 * Return true if this structure represents the ‘class structure’ for some
286 * [class@GObject.Object] or `GInterface`.
287 *
288 * This function is mainly useful to hide this kind of structure from generated
289 * public APIs.
290 *
291 * Returns: `TRUE` if this is a class struct, `FALSE` otherwise
292 * Since: 2.80
293 */
294 gboolean
295 gi_struct_info_is_gtype_struct (GIStructInfo *info)
296 {
297 GIRealInfo *rinfo = (GIRealInfo *)info;
298 StructBlob *blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
299
300 return blob->is_gtype_struct;
301 }
302
303 /**
304 * gi_struct_info_get_copy_function_name:
305 * @info: a struct information blob
306 *
307 * Retrieves the name of the copy function for @info, if any is set.
308 *
309 * Returns: (transfer none) (nullable): the name of the copy function, or `NULL`
310 * if the structure has no copy function
311 * Since: 2.80
312 */
313 const char *
314 gi_struct_info_get_copy_function_name (GIStructInfo *info)
315 {
316 GIRealInfo *rinfo = (GIRealInfo *)info;
317 StructBlob *blob;
318
319 g_return_val_if_fail (info != NULL, NULL);
320 g_return_val_if_fail (GI_IS_STRUCT_INFO (info), NULL);
321
322 blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
323
324 if (blob->copy_func)
325 return gi_typelib_get_string (rinfo->typelib, blob->copy_func);
326
327 return NULL;
328 }
329
330 /**
331 * gi_struct_info_get_free_function_name:
332 * @info: a struct information blob
333 *
334 * Retrieves the name of the free function for @info, if any is set.
335 *
336 * Returns: (transfer none) (nullable): the name of the free function, or `NULL`
337 * if the structure has no free function
338 * Since: 2.80
339 */
340 const char *
341 gi_struct_info_get_free_function_name (GIStructInfo *info)
342 {
343 GIRealInfo *rinfo = (GIRealInfo *)info;
344 StructBlob *blob;
345
346 g_return_val_if_fail (info != NULL, NULL);
347 g_return_val_if_fail (GI_IS_STRUCT_INFO (info), NULL);
348
349 blob = (StructBlob *)&rinfo->typelib->data[rinfo->offset];
350
351 if (blob->free_func)
352 return gi_typelib_get_string (rinfo->typelib, blob->free_func);
353
354 return NULL;
355 }
356
357 void
358 gi_struct_info_class_init (gpointer g_class,
359 gpointer class_data)
360 {
361 GIBaseInfoClass *info_class = g_class;
362
363 info_class->info_type = GI_INFO_TYPE_STRUCT;
364 }