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

source code of gtk/subprojects/glib/glib/gvarianttypeinfo.h