(root)/
glib-2.79.0/
girepository/
giunioninfo.c
       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  guint
      57  gi_union_info_get_n_fields  (GIUnionInfo *info)
      58  {
      59    GIRealInfo *rinfo = (GIRealInfo *)info;
      60    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
      61  
      62    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  gi_union_info_get_field (GIUnionInfo *info,
      78                           guint        n)
      79  {
      80    GIRealInfo *rinfo = (GIRealInfo *)info;
      81    Header *header = (Header *)rinfo->typelib->data;
      82  
      83    return (GIFieldInfo *) gi_info_new (GI_INFO_TYPE_FIELD, (GIBaseInfo*)info, rinfo->typelib,
      84                                        rinfo->offset + header->union_blob_size +
      85                                        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  guint
      98  gi_union_info_get_n_methods (GIUnionInfo *info)
      99  {
     100    GIRealInfo *rinfo = (GIRealInfo *)info;
     101    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     102  
     103    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  gi_union_info_get_method (GIUnionInfo *info,
     119                            guint        n)
     120  {
     121    GIRealInfo *rinfo = (GIRealInfo *)info;
     122    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     123    Header *header = (Header *)rinfo->typelib->data;
     124    gint offset;
     125  
     126    offset = rinfo->offset + header->union_blob_size
     127      + blob->n_fields * header->field_blob_size
     128      + n * header->function_blob_size;
     129    return (GIFunctionInfo *) gi_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  gi_union_info_is_discriminated (GIUnionInfo *info)
     144  {
     145    GIRealInfo *rinfo = (GIRealInfo *)info;
     146    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     147  
     148    return blob->discriminated;
     149  }
     150  
     151  /**
     152   * gi_union_info_get_discriminator_offset:
     153   * @info: a #GIUnionInfo
     154   *
     155   * Returns the offset of the discriminator field in the structure.
     156   *
     157   * Returns: offset, in bytes, of the discriminator
     158   * Since: 2.80
     159   */
     160  guint
     161  gi_union_info_get_discriminator_offset (GIUnionInfo *info)
     162  {
     163    GIRealInfo *rinfo = (GIRealInfo *)info;
     164    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     165  
     166    return blob->discriminator_offset;
     167  }
     168  
     169  /**
     170   * gi_union_info_get_discriminator_type:
     171   * @info: a #GIUnionInfo
     172   *
     173   * Obtain the type information of the union discriminator.
     174   *
     175   * Returns: (transfer full): the [type@GIRepository.TypeInfo], free it with
     176   *   [method@GIRepository.BaseInfo.unref] when done.
     177   * Since: 2.80
     178   */
     179  GITypeInfo *
     180  gi_union_info_get_discriminator_type (GIUnionInfo *info)
     181  {
     182    GIRealInfo *rinfo = (GIRealInfo *)info;
     183  
     184    return gi_type_info_new ((GIBaseInfo*)info, rinfo->typelib, rinfo->offset + 24);
     185  }
     186  
     187  /**
     188   * gi_union_info_get_discriminator:
     189   * @info: a #GIUnionInfo
     190   * @n: a union field index
     191   *
     192   * Obtain the discriminator value assigned for n-th union field, i.e. the n-th
     193   * union field is the active one if the discriminator contains this
     194   * constant.
     195   *
     196   * If the union is not discriminated, `NULL` is returned.
     197   *
     198   * Returns: (transfer full) (nullable): The [type@GIRepository.ConstantInfo], or
     199   *   `NULL` if the union is not discriminated. Free it with
     200   *   [method@GIRepository.BaseInfo.unref] when done.
     201   * Since: 2.80
     202   */
     203  GIConstantInfo *
     204  gi_union_info_get_discriminator (GIUnionInfo *info,
     205                                   guint        n)
     206  {
     207    GIRealInfo *rinfo = (GIRealInfo *)info;
     208    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     209  
     210    if (blob->discriminated)
     211      {
     212        Header *header = (Header *)rinfo->typelib->data;
     213        gint offset;
     214  
     215        offset = rinfo->offset + header->union_blob_size
     216  	+ blob->n_fields * header->field_blob_size
     217  	+ blob->n_functions * header->function_blob_size
     218  	+ n * header->constant_blob_size;
     219  
     220        return (GIConstantInfo *) gi_info_new (GI_INFO_TYPE_CONSTANT, (GIBaseInfo*)info,
     221                                               rinfo->typelib, offset);
     222      }
     223  
     224    return NULL;
     225  }
     226  
     227  /**
     228   * gi_union_info_find_method:
     229   * @info: a #GIUnionInfo
     230   * @name: a method name
     231   *
     232   * Obtain the type information for the method named @name.
     233   *
     234   * Returns: (transfer full) (nullable): The [type@GIRepository.FunctionInfo], or
     235   *   `NULL` if none was found. Free it with [method@GIRepository.BaseInfo.unref]
     236   *   when done.
     237   * Since: 2.80
     238   */
     239  GIFunctionInfo *
     240  gi_union_info_find_method (GIUnionInfo *info,
     241                             const gchar *name)
     242  {
     243    gint offset;
     244    GIRealInfo *rinfo = (GIRealInfo *)info;
     245    Header *header = (Header *)rinfo->typelib->data;
     246    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     247  
     248    offset = rinfo->offset + header->union_blob_size
     249      + blob->n_fields * header->field_blob_size;
     250  
     251    return gi_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_functions, name);
     252  }
     253  
     254  /**
     255   * gi_union_info_get_size:
     256   * @info: a #GIUnionInfo
     257   *
     258   * Obtain the total size of the union.
     259   *
     260   * Returns: size of the union, in bytes
     261   * Since: 2.80
     262   */
     263  gsize
     264  gi_union_info_get_size (GIUnionInfo *info)
     265  {
     266    GIRealInfo *rinfo = (GIRealInfo *)info;
     267    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     268  
     269    return blob->size;
     270  }
     271  
     272  /**
     273   * gi_union_info_get_alignment:
     274   * @info: a #GIUnionInfo
     275   *
     276   * Obtain the required alignment of the union.
     277   *
     278   * Returns: required alignment, in bytes
     279   * Since: 2.80
     280   */
     281  gsize
     282  gi_union_info_get_alignment (GIUnionInfo *info)
     283  {
     284    GIRealInfo *rinfo = (GIRealInfo *)info;
     285    UnionBlob *blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     286  
     287    return blob->alignment;
     288  }
     289  
     290  /**
     291   * gi_union_info_get_copy_function_name:
     292   * @info: a union information blob
     293   *
     294   * Retrieves the name of the copy function for @info, if any is set.
     295   *
     296   * Returns: (transfer none) (nullable): the name of the copy function, or `NULL`
     297   *   if none is set
     298   * Since: 2.80
     299   */
     300  const char *
     301  gi_union_info_get_copy_function_name (GIUnionInfo *info)
     302  {
     303    GIRealInfo *rinfo = (GIRealInfo *)info;
     304    UnionBlob *blob;
     305  
     306    g_return_val_if_fail (info != NULL, NULL);
     307    g_return_val_if_fail (GI_IS_UNION_INFO (info), NULL);
     308  
     309    blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     310  
     311    if (blob->copy_func)
     312      return gi_typelib_get_string (rinfo->typelib, blob->copy_func);
     313  
     314    return NULL;
     315  }
     316  
     317  /**
     318   * gi_union_info_get_free_function_name:
     319   * @info: a union information blob
     320   *
     321   * Retrieves the name of the free function for @info, if any is set.
     322   *
     323   * Returns: (transfer none) (nullable): the name of the free function, or `NULL`
     324   *   if none is set
     325   * Since: 2.80
     326   */
     327  const char *
     328  gi_union_info_get_free_function_name (GIUnionInfo *info)
     329  {
     330    GIRealInfo *rinfo = (GIRealInfo *)info;
     331    UnionBlob *blob;
     332  
     333    g_return_val_if_fail (info != NULL, NULL);
     334    g_return_val_if_fail (GI_IS_UNION_INFO (info), NULL);
     335  
     336    blob = (UnionBlob *)&rinfo->typelib->data[rinfo->offset];
     337  
     338    if (blob->free_func)
     339      return gi_typelib_get_string (rinfo->typelib, blob->free_func);
     340  
     341    return NULL;
     342  }
     343  
     344  void
     345  gi_union_info_class_init (gpointer g_class,
     346                            gpointer class_data)
     347  {
     348    GIBaseInfoClass *info_class = g_class;
     349  
     350    info_class->info_type = GI_INFO_TYPE_UNION;
     351  }