(root)/
glib-2.79.0/
glib/
gvarianttypeinfo.h
       1  /*
       2   * Copyright © 2008 Ryan Lortie
       3   * Copyright © 2010 Codethink Limited
       4   *
       5   * SPDX-License-Identifier: LGPL-2.1-or-later
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General Public
      18   * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19   *
      20   * Author: Ryan Lortie <desrt@desrt.ca>
      21   */
      22  
      23  #ifndef __G_VARIANT_TYPE_INFO_H__
      24  #define __G_VARIANT_TYPE_INFO_H__
      25  
      26  #include <glib/gvarianttype.h>
      27  
      28  #define G_VARIANT_TYPE_INFO_CHAR_MAYBE      'm'
      29  #define G_VARIANT_TYPE_INFO_CHAR_ARRAY      'a'
      30  #define G_VARIANT_TYPE_INFO_CHAR_TUPLE      '('
      31  #define G_VARIANT_TYPE_INFO_CHAR_DICT_ENTRY '{'
      32  #define G_VARIANT_TYPE_INFO_CHAR_VARIANT    'v'
      33  #define g_variant_type_info_get_type_char(info) \
      34    (g_variant_type_info_get_type_string(info)[0])
      35  
      36  typedef struct _GVariantTypeInfo GVariantTypeInfo;
      37  
      38  /* < private >
      39   * GVariantMemberInfo:
      40   *
      41   * This structure describes how to construct a GVariant instance
      42   * corresponding to a given child of a tuple or dictionary entry in a
      43   * very short constant time.  It contains the typeinfo of the child,
      44   * along with 4 constants that allow the bounds of the child's
      45   * serialized data within the container's serialized data to be found
      46   * very efficiently.
      47   *
      48   * Since dictionary entries are serialized as if they were tuples of 2
      49   * items, the term "tuple" will be used here in the general sense to
      50   * refer to tuples and dictionary entries.
      51   *
      52   * BACKGROUND:
      53   *   The serialized data for a tuple contains an array of "offsets" at
      54   *   the end.  There is one "offset" in this array for each
      55   *   variable-sized item in the tuple (except for the last one).  The
      56   *   offset points to the end point of that item's serialized data.  The
      57   *   procedure for finding the start point is described below.  An
      58   *   offset is not needed for the last item because the end point of the
      59   *   last item is merely the end point of the container itself (after
      60   *   the offsets array has been accounted for).  An offset is not needed
      61   *   for fixed-sized items (like integers) because, due to their fixed
      62   *   size, the end point is a constant addition to the start point.
      63   *
      64   *   It is clear that the starting point of a given item in the tuple is
      65   *   determined by the items that precede it in the tuple.  Logically,
      66   *   the start point of a particular item in a given type of tuple can
      67   *   be determined entirely by the end point of the nearest
      68   *   variable-sized item that came before it (or from the start of the
      69   *   container itself in case there is no preceding variable-sized
      70   *   item).  In the case of "(isis)" for example, in order to find out
      71   *   the start point of the last string, one must start at the end point
      72   *   of the first string, align to 4 (for the integer's alignment) and
      73   *   then add 4 (for storing the integer).  That's the point where the
      74   *   string starts (since no special alignment is required for strings).
      75   *
      76   *   Of course, this process requires iterating over the types in the
      77   *   tuple up to the item of interest.  As it turns out, it is possible
      78   *   to determine 3 constants 'a', 'b', and 'c' for each item in the
      79   *   tuple, such that, given the ending offset of the nearest previous
      80   *   variable-sized item (prev_end), a very simple calculation can be
      81   *   performed to determine the start of the item of interest.
      82   *
      83   * The constants in this structure are used as follows:
      84   *
      85   * First, among the array of offsets contained in the tuple, 'i' is the
      86   * index of the offset that refers to the end of the variable-sized item
      87   * preceding the item of interest.  If no variable-sized items precede
      88   * this item, then 'i' will be -1.
      89   *
      90   * Let 'prev_end' be the end offset of the previous item (or 0 in the
      91   * case that there was no such item).  The start address of this item
      92   * can then be calculate using 'a', 'b', and 'c':
      93   *
      94   *    item_start = ((prev_end + a) & b) | c;
      95   *
      96   * For details about how 'a', 'b' and 'c' are calculated, see the
      97   * comments at the point of the implementation in gvariantypeinfo.c.
      98   *
      99   * The end address of the item is then determined in one of three ways,
     100   * according to the 'end_type' field.
     101   *
     102   *   - FIXED: For fixed sized items, the end address is equal to the
     103   *     start address plus the fixed size.
     104   *
     105   *   - LAST: For the last variable sized item in the tuple, the end
     106   *     address is equal to the end address of the tuple, minus the size
     107   *     of the offset array.
     108   *
     109   *   - OFFSET: For other variable sized items, the next index past 'i'
     110   *     (ie: 'i + 1') must be consulted to find the end of this item.
     111   */
     112  
     113  typedef struct
     114  {
     115    GVariantTypeInfo *type_info;
     116  
     117    gsize i, a;
     118    gint8 b, c;
     119  
     120    guint8 ending_type;
     121  } GVariantMemberInfo;
     122  
     123  #define G_VARIANT_MEMBER_ENDING_FIXED   0
     124  #define G_VARIANT_MEMBER_ENDING_LAST    1
     125  #define G_VARIANT_MEMBER_ENDING_OFFSET  2
     126  
     127  /* query */
     128  GLIB_AVAILABLE_IN_ALL
     129  const gchar *                   g_variant_type_info_get_type_string     (GVariantTypeInfo   *typeinfo);
     130  
     131  GLIB_AVAILABLE_IN_ALL
     132  void                            g_variant_type_info_query               (GVariantTypeInfo   *typeinfo,
     133                                                                           guint              *alignment,
     134                                                                           gsize              *size);
     135  GLIB_AVAILABLE_IN_2_60
     136  gsize                           g_variant_type_info_query_depth         (GVariantTypeInfo   *typeinfo);
     137  
     138  /* array */
     139  GLIB_AVAILABLE_IN_ALL
     140  GVariantTypeInfo *              g_variant_type_info_element             (GVariantTypeInfo   *typeinfo);
     141  GLIB_AVAILABLE_IN_ALL
     142  void                            g_variant_type_info_query_element       (GVariantTypeInfo   *typeinfo,
     143                                                                           guint              *alignment,
     144                                                                           gsize              *size);
     145  
     146  /* structure */
     147  GLIB_AVAILABLE_IN_ALL
     148  gsize                           g_variant_type_info_n_members           (GVariantTypeInfo   *typeinfo);
     149  GLIB_AVAILABLE_IN_ALL
     150  const GVariantMemberInfo *      g_variant_type_info_member_info         (GVariantTypeInfo   *typeinfo,
     151                                                                           gsize               index);
     152  
     153  /* new/ref/unref */
     154  GLIB_AVAILABLE_IN_ALL
     155  GVariantTypeInfo *              g_variant_type_info_get                 (const GVariantType *type);
     156  GLIB_AVAILABLE_IN_ALL
     157  GVariantTypeInfo *              g_variant_type_info_ref                 (GVariantTypeInfo   *typeinfo);
     158  GLIB_AVAILABLE_IN_ALL
     159  void                            g_variant_type_info_unref               (GVariantTypeInfo   *typeinfo);
     160  GLIB_AVAILABLE_IN_ALL
     161  void                            g_variant_type_info_assert_no_infos     (void);
     162  
     163  #endif /* __G_VARIANT_TYPE_INFO_H__ */