Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : * GObject introspection: Union 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 "giunioninfo.h"
34 : :
35 : : /**
36 : : * GIUnionInfo:
37 : : *
38 : : * `GIUnionInfo` represents a union type.
39 : : *
40 : : * A union has methods and fields. Unions can optionally have a
41 : : * discriminator, which is a field deciding what type of real union
42 : : * fields is valid for specified instance.
43 : : *
44 : : * Since: 2.80
45 : : */
46 : :
47 : : /**
48 : : * gi_union_info_get_n_fields:
49 : : * @info: a #GIUnionInfo
50 : : *
51 : : * Obtain the number of fields this union has.
52 : : *
53 : : * Returns: number of fields
54 : : * Since: 2.80
55 : : */
56 : : unsigned int
57 : 1 : gi_union_info_get_n_fields (GIUnionInfo *info)
58 : : {
59 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
60 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
61 : :
62 : 1 : return blob->n_fields;
63 : : }
64 : :
65 : : /**
66 : : * gi_union_info_get_field:
67 : : * @info: a #GIUnionInfo
68 : : * @n: a field index
69 : : *
70 : : * Obtain the type information for the field with the specified index.
71 : : *
72 : : * Returns: (transfer full): the [type@GIRepository.FieldInfo], free it with
73 : : * [method@GIRepository.BaseInfo.unref] when done.
74 : : * Since: 2.80
75 : : */
76 : : GIFieldInfo *
77 : 1 : gi_union_info_get_field (GIUnionInfo *info,
78 : : unsigned int n)
79 : : {
80 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
81 : 1 : Header *header = (Header *)rinfo->typelib->data;
82 : :
83 : 2 : return (GIFieldInfo *) gi_base_info_new (GI_INFO_TYPE_FIELD, (GIBaseInfo*)info, rinfo->typelib,
84 : 1 : rinfo->offset + header->union_blob_size +
85 : 1 : n * header->field_blob_size);
86 : : }
87 : :
88 : : /**
89 : : * gi_union_info_get_n_methods:
90 : : * @info: a #GIUnionInfo
91 : : *
92 : : * Obtain the number of methods this union has.
93 : : *
94 : : * Returns: number of methods
95 : : * Since: 2.80
96 : : */
97 : : unsigned int
98 : 2 : gi_union_info_get_n_methods (GIUnionInfo *info)
99 : : {
100 : 2 : GIRealInfo *rinfo = (GIRealInfo *)info;
101 : 2 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
102 : :
103 : 2 : return blob->n_functions;
104 : : }
105 : :
106 : : /**
107 : : * gi_union_info_get_method:
108 : : * @info: a #GIUnionInfo
109 : : * @n: a method index
110 : : *
111 : : * Obtain the type information for the method with the specified index.
112 : : *
113 : : * Returns: (transfer full): the [type@GIRepository.FunctionInfo], free it
114 : : * with [method@GIRepository.BaseInfo.unref] when done.
115 : : * Since: 2.80
116 : : */
117 : : GIFunctionInfo *
118 : 1 : gi_union_info_get_method (GIUnionInfo *info,
119 : : unsigned int n)
120 : : {
121 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
122 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
123 : 1 : Header *header = (Header *)rinfo->typelib->data;
124 : : size_t offset;
125 : :
126 : 1 : offset = rinfo->offset + header->union_blob_size
127 : 1 : + blob->n_fields * header->field_blob_size
128 : 1 : + n * header->function_blob_size;
129 : 1 : return (GIFunctionInfo *) gi_base_info_new (GI_INFO_TYPE_FUNCTION, (GIBaseInfo*)info,
130 : : rinfo->typelib, offset);
131 : : }
132 : :
133 : : /**
134 : : * gi_union_info_is_discriminated:
135 : : * @info: a #GIUnionInfo
136 : : *
137 : : * Return `TRUE` if this union contains a discriminator field.
138 : : *
139 : : * Returns: `TRUE` if this is a discriminated union, `FALSE` otherwise
140 : : * Since: 2.80
141 : : */
142 : : gboolean
143 : 1 : gi_union_info_is_discriminated (GIUnionInfo *info)
144 : : {
145 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
146 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
147 : :
148 : 1 : return blob->discriminated;
149 : : }
150 : :
151 : : /**
152 : : * gi_union_info_get_discriminator_offset:
153 : : * @info: a #GIUnionInfo
154 : : * @out_offset: (out) (optional): return location for the offset, in bytes, of
155 : : * the discriminator
156 : : *
157 : : * Obtain the offset of the discriminator field within the structure.
158 : : *
159 : : * The union must be discriminated, or `FALSE` will be returned.
160 : : *
161 : : * Returns: `TRUE` if the union is discriminated
162 : : * Since: 2.80
163 : : */
164 : : gboolean
165 : 1 : gi_union_info_get_discriminator_offset (GIUnionInfo *info,
166 : : size_t *out_offset)
167 : : {
168 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
169 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
170 : : size_t discriminator_offset;
171 : :
172 : 1 : discriminator_offset = (blob->discriminated) ? blob->discriminator_offset : 0;
173 : :
174 : 1 : if (out_offset != NULL)
175 : 1 : *out_offset = discriminator_offset;
176 : :
177 : 1 : return blob->discriminated;
178 : : }
179 : :
180 : : /**
181 : : * gi_union_info_get_discriminator_type:
182 : : * @info: a #GIUnionInfo
183 : : *
184 : : * Obtain the type information of the union discriminator.
185 : : *
186 : : * Returns: (transfer full) (nullable): the [type@GIRepository.TypeInfo], or
187 : : * `NULL` if the union is not discriminated. Free it with
188 : : * [method@GIRepository.BaseInfo.unref] when done.
189 : : * Since: 2.80
190 : : */
191 : : GITypeInfo *
192 : 1 : gi_union_info_get_discriminator_type (GIUnionInfo *info)
193 : : {
194 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
195 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
196 : :
197 : 1 : if (!blob->discriminated)
198 : 1 : return NULL;
199 : :
200 : 0 : return gi_type_info_new ((GIBaseInfo*)info, rinfo->typelib, rinfo->offset + 24);
201 : : }
202 : :
203 : : /**
204 : : * gi_union_info_get_discriminator:
205 : : * @info: a #GIUnionInfo
206 : : * @n: a union field index
207 : : *
208 : : * Obtain the discriminator value assigned for n-th union field, i.e. the n-th
209 : : * union field is the active one if the discriminator contains this
210 : : * constant.
211 : : *
212 : : * If the union is not discriminated, `NULL` is returned.
213 : : *
214 : : * Returns: (transfer full) (nullable): The [type@GIRepository.ConstantInfo], or
215 : : * `NULL` if the union is not discriminated. Free it with
216 : : * [method@GIRepository.BaseInfo.unref] when done.
217 : : * Since: 2.80
218 : : */
219 : : GIConstantInfo *
220 : 1 : gi_union_info_get_discriminator (GIUnionInfo *info,
221 : : size_t n)
222 : : {
223 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
224 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
225 : :
226 : 1 : if (blob->discriminated)
227 : : {
228 : 0 : Header *header = (Header *)rinfo->typelib->data;
229 : : size_t offset;
230 : :
231 : 0 : offset = rinfo->offset + header->union_blob_size
232 : 0 : + blob->n_fields * header->field_blob_size
233 : 0 : + blob->n_functions * header->function_blob_size
234 : 0 : + n * header->constant_blob_size;
235 : :
236 : 0 : return (GIConstantInfo *) gi_base_info_new (GI_INFO_TYPE_CONSTANT, (GIBaseInfo*)info,
237 : : rinfo->typelib, offset);
238 : : }
239 : :
240 : 1 : return NULL;
241 : : }
242 : :
243 : : /**
244 : : * gi_union_info_find_method:
245 : : * @info: a #GIUnionInfo
246 : : * @name: a method name
247 : : *
248 : : * Obtain the type information for the method named @name.
249 : : *
250 : : * Returns: (transfer full) (nullable): The [type@GIRepository.FunctionInfo], or
251 : : * `NULL` if none was found. Free it with [method@GIRepository.BaseInfo.unref]
252 : : * when done.
253 : : * Since: 2.80
254 : : */
255 : : GIFunctionInfo *
256 : 2 : gi_union_info_find_method (GIUnionInfo *info,
257 : : const char *name)
258 : : {
259 : : size_t offset;
260 : 2 : GIRealInfo *rinfo = (GIRealInfo *)info;
261 : 2 : Header *header = (Header *)rinfo->typelib->data;
262 : 2 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
263 : :
264 : 2 : offset = rinfo->offset + header->union_blob_size
265 : 2 : + blob->n_fields * header->field_blob_size;
266 : :
267 : 2 : return gi_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_functions, name);
268 : : }
269 : :
270 : : /**
271 : : * gi_union_info_get_size:
272 : : * @info: a #GIUnionInfo
273 : : *
274 : : * Obtain the total size of the union.
275 : : *
276 : : * Returns: size of the union, in bytes
277 : : * Since: 2.80
278 : : */
279 : : size_t
280 : 1 : gi_union_info_get_size (GIUnionInfo *info)
281 : : {
282 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
283 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
284 : :
285 : 1 : return blob->size;
286 : : }
287 : :
288 : : /**
289 : : * gi_union_info_get_alignment:
290 : : * @info: a #GIUnionInfo
291 : : *
292 : : * Obtain the required alignment of the union.
293 : : *
294 : : * Returns: required alignment, in bytes
295 : : * Since: 2.80
296 : : */
297 : : size_t
298 : 1 : gi_union_info_get_alignment (GIUnionInfo *info)
299 : : {
300 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
301 : 1 : UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
302 : :
303 : 1 : return blob->alignment;
304 : : }
305 : :
306 : : /**
307 : : * gi_union_info_get_copy_function_name:
308 : : * @info: a union information blob
309 : : *
310 : : * Retrieves the name of the copy function for @info, if any is set.
311 : : *
312 : : * Returns: (transfer none) (nullable): the name of the copy function, or `NULL`
313 : : * if none is set
314 : : * Since: 2.80
315 : : */
316 : : const char *
317 : 1 : gi_union_info_get_copy_function_name (GIUnionInfo *info)
318 : : {
319 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
320 : : UnionBlob *blob;
321 : :
322 : 1 : g_return_val_if_fail (info != NULL, NULL);
323 : 1 : g_return_val_if_fail (GI_IS_UNION_INFO (info), NULL);
324 : :
325 : 1 : blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
326 : :
327 : 1 : if (blob->copy_func)
328 : 0 : return gi_typelib_get_string (rinfo->typelib, blob->copy_func);
329 : :
330 : 1 : return NULL;
331 : : }
332 : :
333 : : /**
334 : : * gi_union_info_get_free_function_name:
335 : : * @info: a union information blob
336 : : *
337 : : * Retrieves the name of the free function for @info, if any is set.
338 : : *
339 : : * Returns: (transfer none) (nullable): the name of the free function, or `NULL`
340 : : * if none is set
341 : : * Since: 2.80
342 : : */
343 : : const char *
344 : 1 : gi_union_info_get_free_function_name (GIUnionInfo *info)
345 : : {
346 : 1 : GIRealInfo *rinfo = (GIRealInfo *)info;
347 : : UnionBlob *blob;
348 : :
349 : 1 : g_return_val_if_fail (info != NULL, NULL);
350 : 1 : g_return_val_if_fail (GI_IS_UNION_INFO (info), NULL);
351 : :
352 : 1 : blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
353 : :
354 : 1 : if (blob->free_func)
355 : 0 : return gi_typelib_get_string (rinfo->typelib, blob->free_func);
356 : :
357 : 1 : return NULL;
358 : : }
359 : :
360 : : void
361 : 4 : gi_union_info_class_init (gpointer g_class,
362 : : gpointer class_data)
363 : : {
364 : 4 : GIBaseInfoClass *info_class = g_class;
365 : :
366 : 4 : info_class->info_type = GI_INFO_TYPE_UNION;
367 : 4 : }
|