Change LGPL-2.1+ to LGPL-2.1-or-later
[platform/upstream/glib.git] / 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__ */