1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: Field 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 <glib.h>
28
29 #include <girepository/girepository.h>
30 #include "gibaseinfo-private.h"
31 #include "girepository-private.h"
32 #include "gitypelib-internal.h"
33 #include "config.h"
34 #include "gifieldinfo.h"
35
36 /**
37 * GIFieldInfo:
38 *
39 * A `GIFieldInfo` struct represents a field of a struct, union, or object.
40 *
41 * The `GIFieldInfo` is fetched by calling
42 * [method@GIRepository.StructInfo.get_field],
43 * [method@GIRepository.UnionInfo.get_field] or
44 * [method@GIRepository.ObjectInfo.get_field].
45 *
46 * A field has a size, type and a struct offset associated and a set of flags,
47 * which are currently `GI_FIELD_IS_READABLE` or `GI_FIELD_IS_WRITABLE`.
48 *
49 * See also: [type@GIRepository.StructInfo], [type@GIRepository.UnionInfo],
50 * [type@GIRepository.ObjectInfo]
51 *
52 * Since: 2.80
53 */
54
55 /**
56 * gi_field_info_get_flags:
57 * @info: a #GIFieldInfo
58 *
59 * Obtain the flags for this `GIFieldInfo`. See
60 * [flags@GIRepository.FieldInfoFlags] for possible flag values.
61 *
62 * Returns: the flags
63 * Since: 2.80
64 */
65 GIFieldInfoFlags
66 gi_field_info_get_flags (GIFieldInfo *info)
67 {
68 GIFieldInfoFlags flags;
69 GIRealInfo *rinfo = (GIRealInfo *)info;
70 FieldBlob *blob;
71
72 g_return_val_if_fail (info != NULL, 0);
73 g_return_val_if_fail (GI_IS_FIELD_INFO (info), 0);
74
75 blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
76
77 flags = 0;
78
79 if (blob->readable)
80 flags = flags | GI_FIELD_IS_READABLE;
81
82 if (blob->writable)
83 flags = flags | GI_FIELD_IS_WRITABLE;
84
85 return flags;
86 }
87
88 /**
89 * gi_field_info_get_size:
90 * @info: a #GIFieldInfo
91 *
92 * Obtain the size of the field member, in bits. This is how
93 * much space you need to allocate to store the field.
94 *
95 * Returns: the field size, in bits
96 * Since: 2.80
97 */
98 gsize
99 gi_field_info_get_size (GIFieldInfo *info)
100 {
101 GIRealInfo *rinfo = (GIRealInfo *)info;
102 FieldBlob *blob;
103
104 g_return_val_if_fail (info != NULL, 0);
105 g_return_val_if_fail (GI_IS_FIELD_INFO (info), 0);
106
107 blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
108
109 return blob->bits;
110 }
111
112 /**
113 * gi_field_info_get_offset:
114 * @info: a #GIFieldInfo
115 *
116 * Obtain the offset of the field member, in bytes. This is relative
117 * to the beginning of the struct or union.
118 *
119 * Returns: the field offset, in bytes
120 * Since: 2.80
121 */
122 gsize
123 gi_field_info_get_offset (GIFieldInfo *info)
124 {
125 GIRealInfo *rinfo = (GIRealInfo *)info;
126 FieldBlob *blob;
127
128 g_return_val_if_fail (info != NULL, 0);
129 g_return_val_if_fail (GI_IS_FIELD_INFO (info), 0);
130
131 blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
132
133 return blob->struct_offset;
134 }
135
136 /**
137 * gi_field_info_get_type_info:
138 * @info: a #GIFieldInfo
139 *
140 * Obtain the type of a field as a [type@GIRepository.TypeInfo].
141 *
142 * Returns: (transfer full): the [type@GIRepository.TypeInfo]. Free the struct
143 * by calling [method@GIRepository.BaseInfo.unref] when done.
144 * Since: 2.80
145 */
146 GITypeInfo *
147 gi_field_info_get_type_info (GIFieldInfo *info)
148 {
149 GIRealInfo *rinfo = (GIRealInfo *)info;
150 Header *header = (Header *)rinfo->typelib->data;
151 FieldBlob *blob;
152 GIRealInfo *type_info;
153
154 g_return_val_if_fail (info != NULL, NULL);
155 g_return_val_if_fail (GI_IS_FIELD_INFO (info), NULL);
156
157 blob = (FieldBlob *)&rinfo->typelib->data[rinfo->offset];
158
159 if (blob->has_embedded_type)
160 {
161 type_info = (GIRealInfo *) gi_info_new (GI_INFO_TYPE_TYPE,
162 (GIBaseInfo*)info, rinfo->typelib,
163 rinfo->offset + header->field_blob_size);
164 type_info->type_is_embedded = TRUE;
165 }
166 else
167 return gi_type_info_new ((GIBaseInfo*)info, rinfo->typelib, rinfo->offset + G_STRUCT_OFFSET (FieldBlob, type));
168
169 return (GITypeInfo *) type_info;
170 }
171
172 /**
173 * gi_field_info_get_field: (skip)
174 * @field_info: a #GIFieldInfo
175 * @mem: pointer to a block of memory representing a C structure or union
176 * @value: a [type@GIRepository.Argument] into which to store the value retrieved
177 *
178 * Reads a field identified by a `GIFieldInfo` from a C structure or
179 * union.
180 *
181 * This only handles fields of simple C types. It will fail for a field of a
182 * composite type like a nested structure or union even if that is actually
183 * readable.
184 *
185 * Returns: `TRUE` if reading the field succeeded, `FALSE` otherwise
186 * Since: 2.80
187 */
188 gboolean
189 gi_field_info_get_field (GIFieldInfo *field_info,
190 gpointer mem,
191 GIArgument *value)
192 {
193 int offset;
194 GITypeInfo *type_info;
195 gboolean result = FALSE;
196
197 g_return_val_if_fail (field_info != NULL, FALSE);
198 g_return_val_if_fail (GI_IS_FIELD_INFO (field_info), FALSE);
199
200 if ((gi_field_info_get_flags (field_info) & GI_FIELD_IS_READABLE) == 0)
201 return FALSE;
202
203 offset = gi_field_info_get_offset (field_info);
204 type_info = gi_field_info_get_type_info (field_info);
205
206 if (gi_type_info_is_pointer (type_info))
207 {
208 value->v_pointer = G_STRUCT_MEMBER (gpointer, mem, offset);
209 result = TRUE;
210 }
211 else
212 {
213 switch (gi_type_info_get_tag (type_info))
214 {
215 case GI_TYPE_TAG_VOID:
216 g_warning("Field %s: should not be have void type",
217 gi_base_info_get_name ((GIBaseInfo *)field_info));
218 break;
219 case GI_TYPE_TAG_BOOLEAN:
220 value->v_boolean = G_STRUCT_MEMBER (gboolean, mem, offset) != FALSE;
221 result = TRUE;
222 break;
223 case GI_TYPE_TAG_INT8:
224 case GI_TYPE_TAG_UINT8:
225 value->v_uint8 = G_STRUCT_MEMBER (guint8, mem, offset);
226 result = TRUE;
227 break;
228 case GI_TYPE_TAG_INT16:
229 case GI_TYPE_TAG_UINT16:
230 value->v_uint16 = G_STRUCT_MEMBER (guint16, mem, offset);
231 result = TRUE;
232 break;
233 case GI_TYPE_TAG_INT32:
234 case GI_TYPE_TAG_UINT32:
235 case GI_TYPE_TAG_UNICHAR:
236 value->v_uint32 = G_STRUCT_MEMBER (guint32, mem, offset);
237 result = TRUE;
238 break;
239 case GI_TYPE_TAG_INT64:
240 case GI_TYPE_TAG_UINT64:
241 value->v_uint64 = G_STRUCT_MEMBER (guint64, mem, offset);
242 result = TRUE;
243 break;
244 case GI_TYPE_TAG_GTYPE:
245 value->v_size = G_STRUCT_MEMBER (gsize, mem, offset);
246 result = TRUE;
247 break;
248 case GI_TYPE_TAG_FLOAT:
249 value->v_float = G_STRUCT_MEMBER (gfloat, mem, offset);
250 result = TRUE;
251 break;
252 case GI_TYPE_TAG_DOUBLE:
253 value->v_double = G_STRUCT_MEMBER (gdouble, mem, offset);
254 result = TRUE;
255 break;
256 case GI_TYPE_TAG_ARRAY:
257 /* We don't check the array type and that it is fixed-size,
258 we trust g-ir-compiler to do the right thing */
259 value->v_pointer = G_STRUCT_MEMBER_P (mem, offset);
260 result = TRUE;
261 break;
262 case GI_TYPE_TAG_UTF8:
263 case GI_TYPE_TAG_FILENAME:
264 case GI_TYPE_TAG_GLIST:
265 case GI_TYPE_TAG_GSLIST:
266 case GI_TYPE_TAG_GHASH:
267 g_warning("Field %s: type %s should have is_pointer set",
268 gi_base_info_get_name ((GIBaseInfo *)field_info),
269 gi_type_tag_to_string (gi_type_info_get_tag (type_info)));
270 break;
271 case GI_TYPE_TAG_ERROR:
272 /* Needs to be handled by the language binding directly */
273 break;
274 case GI_TYPE_TAG_INTERFACE:
275 {
276 GIBaseInfo *interface = gi_type_info_get_interface (type_info);
277 switch (gi_base_info_get_info_type (interface))
278 {
279 case GI_INFO_TYPE_STRUCT:
280 case GI_INFO_TYPE_UNION:
281 case GI_INFO_TYPE_BOXED:
282 /* Needs to be handled by the language binding directly */
283 break;
284 case GI_INFO_TYPE_OBJECT:
285 break;
286 case GI_INFO_TYPE_ENUM:
287 case GI_INFO_TYPE_FLAGS:
288 {
289 /* FIXME: there's a mismatch here between the value->v_int we use
290 * here and the gint64 result returned from gi_value_info_get_value().
291 * But to switch this to gint64, we'd have to make gi_function_info_invoke()
292 * translate value->v_int64 to the proper ABI for an enum function
293 * call parameter, which will usually be int, and then fix up language
294 * bindings.
295 */
296 GITypeTag storage_type = gi_enum_info_get_storage_type ((GIEnumInfo *)interface);
297 switch (storage_type)
298 {
299 case GI_TYPE_TAG_INT8:
300 case GI_TYPE_TAG_UINT8:
301 value->v_int = (gint)G_STRUCT_MEMBER (guint8, mem, offset);
302 result = TRUE;
303 break;
304 case GI_TYPE_TAG_INT16:
305 case GI_TYPE_TAG_UINT16:
306 value->v_int = (gint)G_STRUCT_MEMBER (guint16, mem, offset);
307 result = TRUE;
308 break;
309 case GI_TYPE_TAG_INT32:
310 case GI_TYPE_TAG_UINT32:
311 value->v_int = (gint)G_STRUCT_MEMBER (guint32, mem, offset);
312 result = TRUE;
313 break;
314 case GI_TYPE_TAG_INT64:
315 case GI_TYPE_TAG_UINT64:
316 value->v_int = (gint)G_STRUCT_MEMBER (guint64, mem, offset);
317 result = TRUE;
318 break;
319 default:
320 g_warning("Field %s: Unexpected enum storage type %s",
321 gi_base_info_get_name ((GIBaseInfo *)field_info),
322 gi_type_tag_to_string (storage_type));
323 break;
324 }
325 break;
326 }
327 case GI_INFO_TYPE_VFUNC:
328 case GI_INFO_TYPE_CALLBACK:
329 g_warning("Field %s: Interface type %d should have is_pointer set",
330 gi_base_info_get_name ((GIBaseInfo *)field_info),
331 gi_base_info_get_info_type (interface));
332 break;
333 case GI_INFO_TYPE_INVALID:
334 case GI_INFO_TYPE_INTERFACE:
335 case GI_INFO_TYPE_FUNCTION:
336 case GI_INFO_TYPE_CONSTANT:
337 case GI_INFO_TYPE_INVALID_0:
338 case GI_INFO_TYPE_VALUE:
339 case GI_INFO_TYPE_SIGNAL:
340 case GI_INFO_TYPE_PROPERTY:
341 case GI_INFO_TYPE_FIELD:
342 case GI_INFO_TYPE_ARG:
343 case GI_INFO_TYPE_TYPE:
344 case GI_INFO_TYPE_UNRESOLVED:
345 g_warning("Field %s: Interface type %d not expected",
346 gi_base_info_get_name ((GIBaseInfo *)field_info),
347 gi_base_info_get_info_type (interface));
348 break;
349 default:
350 break;
351 }
352
353 gi_base_info_unref ((GIBaseInfo *)interface);
354 break;
355 }
356 break;
357 default:
358 break;
359 }
360 }
361
362 gi_base_info_unref ((GIBaseInfo *)type_info);
363
364 return result;
365 }
366
367 /**
368 * gi_field_info_set_field: (skip)
369 * @field_info: a #GIFieldInfo
370 * @mem: pointer to a block of memory representing a C structure or union
371 * @value: a [type@GIRepository.Argument] holding the value to store
372 *
373 * Writes a field identified by a `GIFieldInfo` to a C structure or
374 * union.
375 *
376 * This only handles fields of simple C types. It will fail for a field of a
377 * composite type like a nested structure or union even if that is actually
378 * writable. Note also that that it will refuse to write fields where memory
379 * management would by required. A field with a type such as `char *` must be
380 * set with a setter function.
381 *
382 * Returns: `TRUE` if writing the field succeeded, `FALSE` otherwise
383 * Since: 2.80
384 */
385 gboolean
386 gi_field_info_set_field (GIFieldInfo *field_info,
387 gpointer mem,
388 const GIArgument *value)
389 {
390 int offset;
391 GITypeInfo *type_info;
392 gboolean result = FALSE;
393
394 g_return_val_if_fail (field_info != NULL, FALSE);
395 g_return_val_if_fail (GI_IS_FIELD_INFO (field_info), FALSE);
396
397 if ((gi_field_info_get_flags (field_info) & GI_FIELD_IS_WRITABLE) == 0)
398 return FALSE;
399
400 offset = gi_field_info_get_offset (field_info);
401 type_info = gi_field_info_get_type_info (field_info);
402
403 if (!gi_type_info_is_pointer (type_info))
404 {
405 switch (gi_type_info_get_tag (type_info))
406 {
407 case GI_TYPE_TAG_VOID:
408 g_warning("Field %s: should not be have void type",
409 gi_base_info_get_name ((GIBaseInfo *)field_info));
410 break;
411 case GI_TYPE_TAG_BOOLEAN:
412 G_STRUCT_MEMBER (gboolean, mem, offset) = value->v_boolean != FALSE;
413 result = TRUE;
414 break;
415 case GI_TYPE_TAG_INT8:
416 case GI_TYPE_TAG_UINT8:
417 G_STRUCT_MEMBER (guint8, mem, offset) = value->v_uint8;
418 result = TRUE;
419 break;
420 case GI_TYPE_TAG_INT16:
421 case GI_TYPE_TAG_UINT16:
422 G_STRUCT_MEMBER (guint16, mem, offset) = value->v_uint16;
423 result = TRUE;
424 break;
425 case GI_TYPE_TAG_INT32:
426 case GI_TYPE_TAG_UINT32:
427 case GI_TYPE_TAG_UNICHAR:
428 G_STRUCT_MEMBER (guint32, mem, offset) = value->v_uint32;
429 result = TRUE;
430 break;
431 case GI_TYPE_TAG_INT64:
432 case GI_TYPE_TAG_UINT64:
433 G_STRUCT_MEMBER (guint64, mem, offset) = value->v_uint64;
434 result = TRUE;
435 break;
436 case GI_TYPE_TAG_GTYPE:
437 G_STRUCT_MEMBER (gsize, mem, offset) = value->v_size;
438 result = TRUE;
439 break;
440 case GI_TYPE_TAG_FLOAT:
441 G_STRUCT_MEMBER (gfloat, mem, offset) = value->v_float;
442 result = TRUE;
443 break;
444 case GI_TYPE_TAG_DOUBLE:
445 G_STRUCT_MEMBER (gdouble, mem, offset)= value->v_double;
446 result = TRUE;
447 break;
448 case GI_TYPE_TAG_UTF8:
449 case GI_TYPE_TAG_FILENAME:
450 case GI_TYPE_TAG_ARRAY:
451 case GI_TYPE_TAG_GLIST:
452 case GI_TYPE_TAG_GSLIST:
453 case GI_TYPE_TAG_GHASH:
454 g_warning("Field %s: type %s should have is_pointer set",
455 gi_base_info_get_name ((GIBaseInfo *)field_info),
456 gi_type_tag_to_string (gi_type_info_get_tag (type_info)));
457 break;
458 case GI_TYPE_TAG_ERROR:
459 /* Needs to be handled by the language binding directly */
460 break;
461 case GI_TYPE_TAG_INTERFACE:
462 {
463 GIBaseInfo *interface = gi_type_info_get_interface (type_info);
464 switch (gi_base_info_get_info_type (interface))
465 {
466 case GI_INFO_TYPE_STRUCT:
467 case GI_INFO_TYPE_UNION:
468 case GI_INFO_TYPE_BOXED:
469 /* Needs to be handled by the language binding directly */
470 break;
471 case GI_INFO_TYPE_OBJECT:
472 break;
473 case GI_INFO_TYPE_ENUM:
474 case GI_INFO_TYPE_FLAGS:
475 {
476 /* See FIXME above
477 */
478 GITypeTag storage_type = gi_enum_info_get_storage_type ((GIEnumInfo *)interface);
479 switch (storage_type)
480 {
481 case GI_TYPE_TAG_INT8:
482 case GI_TYPE_TAG_UINT8:
483 G_STRUCT_MEMBER (guint8, mem, offset) = (guint8)value->v_int;
484 result = TRUE;
485 break;
486 case GI_TYPE_TAG_INT16:
487 case GI_TYPE_TAG_UINT16:
488 G_STRUCT_MEMBER (guint16, mem, offset) = (guint16)value->v_int;
489 result = TRUE;
490 break;
491 case GI_TYPE_TAG_INT32:
492 case GI_TYPE_TAG_UINT32:
493 G_STRUCT_MEMBER (guint32, mem, offset) = (guint32)value->v_int;
494 result = TRUE;
495 break;
496 case GI_TYPE_TAG_INT64:
497 case GI_TYPE_TAG_UINT64:
498 G_STRUCT_MEMBER (guint64, mem, offset) = (guint64)value->v_int;
499 result = TRUE;
500 break;
501 default:
502 g_warning("Field %s: Unexpected enum storage type %s",
503 gi_base_info_get_name ((GIBaseInfo *)field_info),
504 gi_type_tag_to_string (storage_type));
505 break;
506 }
507 break;
508 }
509 break;
510 case GI_INFO_TYPE_VFUNC:
511 case GI_INFO_TYPE_CALLBACK:
512 g_warning("Field%s: Interface type %d should have is_pointer set",
513 gi_base_info_get_name ((GIBaseInfo *)field_info),
514 gi_base_info_get_info_type (interface));
515 break;
516 case GI_INFO_TYPE_INVALID:
517 case GI_INFO_TYPE_INTERFACE:
518 case GI_INFO_TYPE_FUNCTION:
519 case GI_INFO_TYPE_CONSTANT:
520 case GI_INFO_TYPE_INVALID_0:
521 case GI_INFO_TYPE_VALUE:
522 case GI_INFO_TYPE_SIGNAL:
523 case GI_INFO_TYPE_PROPERTY:
524 case GI_INFO_TYPE_FIELD:
525 case GI_INFO_TYPE_ARG:
526 case GI_INFO_TYPE_TYPE:
527 case GI_INFO_TYPE_UNRESOLVED:
528 g_warning("Field %s: Interface type %d not expected",
529 gi_base_info_get_name ((GIBaseInfo *)field_info),
530 gi_base_info_get_info_type (interface));
531 break;
532 default:
533 break;
534 }
535
536 gi_base_info_unref ((GIBaseInfo *)interface);
537 break;
538 }
539 break;
540 default:
541 break;
542 }
543 } else {
544 switch (gi_type_info_get_tag (type_info))
545 {
546 case GI_TYPE_TAG_INTERFACE:
547 {
548 GIBaseInfo *interface = gi_type_info_get_interface (type_info);
549 switch (gi_base_info_get_info_type (interface))
550 {
551 case GI_INFO_TYPE_OBJECT:
552 case GI_INFO_TYPE_INTERFACE:
553 G_STRUCT_MEMBER (gpointer, mem, offset) = (gpointer)value->v_pointer;
554 result = TRUE;
555 break;
556 default:
557 break;
558 }
559 gi_base_info_unref ((GIBaseInfo *)interface);
560 }
561 break;
562 default:
563 break;
564 }
565 }
566
567 gi_base_info_unref ((GIBaseInfo *)type_info);
568
569 return result;
570 }
571
572 void
573 gi_field_info_class_init (gpointer g_class,
574 gpointer class_data)
575 {
576 GIBaseInfoClass *info_class = g_class;
577
578 info_class->info_type = GI_INFO_TYPE_FIELD;
579 }