1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "bus-gvariant.h"
11 #include "bus-signature.h"
14 int bus_gvariant_get_size(const char *signature) {
18 /* For fixed size structs. Fails for variable size structs. */
24 r = signature_element_length(p, &n);
33 r = bus_gvariant_get_alignment(t);
37 sum = ALIGN_TO(sum, r);
42 case SD_BUS_TYPE_BOOLEAN:
43 case SD_BUS_TYPE_BYTE:
47 case SD_BUS_TYPE_INT16:
48 case SD_BUS_TYPE_UINT16:
52 case SD_BUS_TYPE_INT32:
53 case SD_BUS_TYPE_UINT32:
54 case SD_BUS_TYPE_UNIX_FD:
58 case SD_BUS_TYPE_INT64:
59 case SD_BUS_TYPE_UINT64:
60 case SD_BUS_TYPE_DOUBLE:
64 case SD_BUS_TYPE_STRUCT_BEGIN:
65 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
67 /* unary type () has fixed size of 1 */
72 memcpy(t, p + 1, n - 2);
75 r = bus_gvariant_get_size(t);
84 case SD_BUS_TYPE_STRING:
85 case SD_BUS_TYPE_OBJECT_PATH:
86 case SD_BUS_TYPE_SIGNATURE:
87 case SD_BUS_TYPE_ARRAY:
88 case SD_BUS_TYPE_VARIANT:
92 assert_not_reached("Unknown signature type");
98 r = bus_gvariant_get_alignment(signature);
102 return ALIGN_TO(sum, r);
105 int bus_gvariant_get_alignment(const char *signature) {
106 size_t alignment = 1;
111 while (*p != 0 && alignment < 8) {
115 r = signature_element_length(p, &n);
121 case SD_BUS_TYPE_BYTE:
122 case SD_BUS_TYPE_BOOLEAN:
123 case SD_BUS_TYPE_STRING:
124 case SD_BUS_TYPE_OBJECT_PATH:
125 case SD_BUS_TYPE_SIGNATURE:
129 case SD_BUS_TYPE_INT16:
130 case SD_BUS_TYPE_UINT16:
134 case SD_BUS_TYPE_INT32:
135 case SD_BUS_TYPE_UINT32:
136 case SD_BUS_TYPE_UNIX_FD:
140 case SD_BUS_TYPE_INT64:
141 case SD_BUS_TYPE_UINT64:
142 case SD_BUS_TYPE_DOUBLE:
143 case SD_BUS_TYPE_VARIANT:
147 case SD_BUS_TYPE_ARRAY: {
150 memcpy(t, p + 1, n - 1);
153 a = bus_gvariant_get_alignment(t);
157 case SD_BUS_TYPE_STRUCT_BEGIN:
158 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
161 memcpy(t, p + 1, n - 2);
164 a = bus_gvariant_get_alignment(t);
169 assert_not_reached("Unknown signature type");
175 assert(a > 0 && a <= 8);
176 if ((size_t) a > alignment)
177 alignment = (size_t) a;
185 int bus_gvariant_is_fixed_size(const char *signature) {
195 r = signature_element_length(p, &n);
201 case SD_BUS_TYPE_STRING:
202 case SD_BUS_TYPE_OBJECT_PATH:
203 case SD_BUS_TYPE_SIGNATURE:
204 case SD_BUS_TYPE_ARRAY:
205 case SD_BUS_TYPE_VARIANT:
208 case SD_BUS_TYPE_BYTE:
209 case SD_BUS_TYPE_BOOLEAN:
210 case SD_BUS_TYPE_INT16:
211 case SD_BUS_TYPE_UINT16:
212 case SD_BUS_TYPE_INT32:
213 case SD_BUS_TYPE_UINT32:
214 case SD_BUS_TYPE_UNIX_FD:
215 case SD_BUS_TYPE_INT64:
216 case SD_BUS_TYPE_UINT64:
217 case SD_BUS_TYPE_DOUBLE:
220 case SD_BUS_TYPE_STRUCT_BEGIN:
221 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
224 memcpy(t, p + 1, n - 2);
227 r = bus_gvariant_is_fixed_size(t);
234 assert_not_reached("Unknown signature type");
243 size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
244 if (sz + extra <= 0xFF)
246 else if (sz + extra*2 <= 0xFFFF)
248 else if (sz + extra*4 <= 0xFFFFFFFF)
254 size_t bus_gvariant_read_word_le(void *p, size_t sz) {
264 return *(uint8_t*) p;
269 return le16toh(x.u16);
271 return le32toh(x.u32);
273 return le64toh(x.u64);
275 assert_not_reached("unknown word width");
278 void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
286 assert(sz == 8 || (value < (1ULL << (sz*8))));
289 *(uint8_t*) p = value;
292 x.u16 = htole16((uint16_t) value);
294 x.u32 = htole32((uint32_t) value);
296 x.u64 = htole64((uint64_t) value);
298 assert_not_reached("unknown word width");