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