1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright 2013 Lennart Poettering
11 #include "bus-gvariant.h"
12 #include "bus-signature.h"
15 int bus_gvariant_get_size(const char *signature) {
19 /* For fixed size structs. Fails for variable size structs. */
25 r = signature_element_length(p, &n);
34 r = bus_gvariant_get_alignment(t);
38 sum = ALIGN_TO(sum, r);
43 case SD_BUS_TYPE_BOOLEAN:
44 case SD_BUS_TYPE_BYTE:
48 case SD_BUS_TYPE_INT16:
49 case SD_BUS_TYPE_UINT16:
53 case SD_BUS_TYPE_INT32:
54 case SD_BUS_TYPE_UINT32:
55 case SD_BUS_TYPE_UNIX_FD:
59 case SD_BUS_TYPE_INT64:
60 case SD_BUS_TYPE_UINT64:
61 case SD_BUS_TYPE_DOUBLE:
65 case SD_BUS_TYPE_STRUCT_BEGIN:
66 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
68 /* unary type () has fixed size of 1 */
73 memcpy(t, p + 1, n - 2);
76 r = bus_gvariant_get_size(t);
85 case SD_BUS_TYPE_STRING:
86 case SD_BUS_TYPE_OBJECT_PATH:
87 case SD_BUS_TYPE_SIGNATURE:
88 case SD_BUS_TYPE_ARRAY:
89 case SD_BUS_TYPE_VARIANT:
93 assert_not_reached("Unknown signature type");
99 r = bus_gvariant_get_alignment(signature);
103 return ALIGN_TO(sum, r);
106 int bus_gvariant_get_alignment(const char *signature) {
107 size_t alignment = 1;
112 while (*p != 0 && alignment < 8) {
116 r = signature_element_length(p, &n);
122 case SD_BUS_TYPE_BYTE:
123 case SD_BUS_TYPE_BOOLEAN:
124 case SD_BUS_TYPE_STRING:
125 case SD_BUS_TYPE_OBJECT_PATH:
126 case SD_BUS_TYPE_SIGNATURE:
130 case SD_BUS_TYPE_INT16:
131 case SD_BUS_TYPE_UINT16:
135 case SD_BUS_TYPE_INT32:
136 case SD_BUS_TYPE_UINT32:
137 case SD_BUS_TYPE_UNIX_FD:
141 case SD_BUS_TYPE_INT64:
142 case SD_BUS_TYPE_UINT64:
143 case SD_BUS_TYPE_DOUBLE:
144 case SD_BUS_TYPE_VARIANT:
148 case SD_BUS_TYPE_ARRAY: {
151 memcpy(t, p + 1, n - 1);
154 a = bus_gvariant_get_alignment(t);
158 case SD_BUS_TYPE_STRUCT_BEGIN:
159 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
162 memcpy(t, p + 1, n - 2);
165 a = bus_gvariant_get_alignment(t);
170 assert_not_reached("Unknown signature type");
176 assert(a > 0 && a <= 8);
177 if ((size_t) a > alignment)
178 alignment = (size_t) a;
186 int bus_gvariant_is_fixed_size(const char *signature) {
196 r = signature_element_length(p, &n);
202 case SD_BUS_TYPE_STRING:
203 case SD_BUS_TYPE_OBJECT_PATH:
204 case SD_BUS_TYPE_SIGNATURE:
205 case SD_BUS_TYPE_ARRAY:
206 case SD_BUS_TYPE_VARIANT:
209 case SD_BUS_TYPE_BYTE:
210 case SD_BUS_TYPE_BOOLEAN:
211 case SD_BUS_TYPE_INT16:
212 case SD_BUS_TYPE_UINT16:
213 case SD_BUS_TYPE_INT32:
214 case SD_BUS_TYPE_UINT32:
215 case SD_BUS_TYPE_UNIX_FD:
216 case SD_BUS_TYPE_INT64:
217 case SD_BUS_TYPE_UINT64:
218 case SD_BUS_TYPE_DOUBLE:
221 case SD_BUS_TYPE_STRUCT_BEGIN:
222 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
225 memcpy(t, p + 1, n - 2);
228 r = bus_gvariant_is_fixed_size(t);
235 assert_not_reached("Unknown signature type");
244 size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
245 if (sz + extra <= 0xFF)
247 else if (sz + extra*2 <= 0xFFFF)
249 else if (sz + extra*4 <= 0xFFFFFFFF)
255 size_t bus_gvariant_read_word_le(void *p, size_t sz) {
265 return *(uint8_t*) p;
270 return le16toh(x.u16);
272 return le32toh(x.u32);
274 return le64toh(x.u64);
276 assert_not_reached("unknown word width");
279 void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
287 assert(sz == 8 || (value < (1ULL << (sz*8))));
290 *(uint8_t*) p = value;
293 x.u16 = htole16((uint16_t) value);
295 x.u32 = htole32((uint32_t) value);
297 x.u64 = htole64((uint64_t) value);
299 assert_not_reached("unknown word width");