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 | |
34 | typedef 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 | |
111 | typedef 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 */ |
126 | GLIB_AVAILABLE_IN_ALL |
127 | const gchar * g_variant_type_info_get_type_string (GVariantTypeInfo *typeinfo); |
128 | |
129 | GLIB_AVAILABLE_IN_ALL |
130 | void g_variant_type_info_query (GVariantTypeInfo *typeinfo, |
131 | guint *alignment, |
132 | gsize *size); |
133 | GLIB_AVAILABLE_IN_2_60 |
134 | gsize g_variant_type_info_query_depth (GVariantTypeInfo *typeinfo); |
135 | |
136 | /* array */ |
137 | GLIB_AVAILABLE_IN_ALL |
138 | GVariantTypeInfo * g_variant_type_info_element (GVariantTypeInfo *typeinfo); |
139 | GLIB_AVAILABLE_IN_ALL |
140 | void g_variant_type_info_query_element (GVariantTypeInfo *typeinfo, |
141 | guint *alignment, |
142 | gsize *size); |
143 | |
144 | /* structure */ |
145 | GLIB_AVAILABLE_IN_ALL |
146 | gsize g_variant_type_info_n_members (GVariantTypeInfo *typeinfo); |
147 | GLIB_AVAILABLE_IN_ALL |
148 | const GVariantMemberInfo * g_variant_type_info_member_info (GVariantTypeInfo *typeinfo, |
149 | gsize index); |
150 | |
151 | /* new/ref/unref */ |
152 | GLIB_AVAILABLE_IN_ALL |
153 | GVariantTypeInfo * g_variant_type_info_get (const GVariantType *type); |
154 | GLIB_AVAILABLE_IN_ALL |
155 | GVariantTypeInfo * g_variant_type_info_ref (GVariantTypeInfo *typeinfo); |
156 | GLIB_AVAILABLE_IN_ALL |
157 | void g_variant_type_info_unref (GVariantTypeInfo *typeinfo); |
158 | GLIB_AVAILABLE_IN_ALL |
159 | void g_variant_type_info_assert_no_infos (void); |
160 | |
161 | #endif /* __G_VARIANT_TYPE_INFO_H__ */ |
162 | |