1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2013 Lennart Poettering
13 #include "bus-gvariant.h"
14 #include "bus-signature.h"
17 int bus_gvariant_get_size(const char *signature) {
21 /* For fixed size structs. Fails for variable size structs. */
27 r = signature_element_length(p, &n);
36 r = bus_gvariant_get_alignment(t);
40 sum = ALIGN_TO(sum, r);
45 case SD_BUS_TYPE_BOOLEAN:
46 case SD_BUS_TYPE_BYTE:
50 case SD_BUS_TYPE_INT16:
51 case SD_BUS_TYPE_UINT16:
55 case SD_BUS_TYPE_INT32:
56 case SD_BUS_TYPE_UINT32:
57 case SD_BUS_TYPE_UNIX_FD:
61 case SD_BUS_TYPE_INT64:
62 case SD_BUS_TYPE_UINT64:
63 case SD_BUS_TYPE_DOUBLE:
67 case SD_BUS_TYPE_STRUCT_BEGIN:
68 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
70 /* unary type () has fixed size of 1 */
75 memcpy(t, p + 1, n - 2);
78 r = bus_gvariant_get_size(t);
87 case SD_BUS_TYPE_STRING:
88 case SD_BUS_TYPE_OBJECT_PATH:
89 case SD_BUS_TYPE_SIGNATURE:
90 case SD_BUS_TYPE_ARRAY:
91 case SD_BUS_TYPE_VARIANT:
95 assert_not_reached("Unknown signature type");
101 r = bus_gvariant_get_alignment(signature);
105 return ALIGN_TO(sum, r);
108 int bus_gvariant_get_alignment(const char *signature) {
109 size_t alignment = 1;
114 while (*p != 0 && alignment < 8) {
118 r = signature_element_length(p, &n);
124 case SD_BUS_TYPE_BYTE:
125 case SD_BUS_TYPE_BOOLEAN:
126 case SD_BUS_TYPE_STRING:
127 case SD_BUS_TYPE_OBJECT_PATH:
128 case SD_BUS_TYPE_SIGNATURE:
132 case SD_BUS_TYPE_INT16:
133 case SD_BUS_TYPE_UINT16:
137 case SD_BUS_TYPE_INT32:
138 case SD_BUS_TYPE_UINT32:
139 case SD_BUS_TYPE_UNIX_FD:
143 case SD_BUS_TYPE_INT64:
144 case SD_BUS_TYPE_UINT64:
145 case SD_BUS_TYPE_DOUBLE:
146 case SD_BUS_TYPE_VARIANT:
150 case SD_BUS_TYPE_ARRAY: {
153 memcpy(t, p + 1, n - 1);
156 a = bus_gvariant_get_alignment(t);
160 case SD_BUS_TYPE_STRUCT_BEGIN:
161 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
164 memcpy(t, p + 1, n - 2);
167 a = bus_gvariant_get_alignment(t);
172 assert_not_reached("Unknown signature type");
178 assert(a > 0 && a <= 8);
179 if ((size_t) a > alignment)
180 alignment = (size_t) a;
188 int bus_gvariant_is_fixed_size(const char *signature) {
198 r = signature_element_length(p, &n);
204 case SD_BUS_TYPE_STRING:
205 case SD_BUS_TYPE_OBJECT_PATH:
206 case SD_BUS_TYPE_SIGNATURE:
207 case SD_BUS_TYPE_ARRAY:
208 case SD_BUS_TYPE_VARIANT:
211 case SD_BUS_TYPE_BYTE:
212 case SD_BUS_TYPE_BOOLEAN:
213 case SD_BUS_TYPE_INT16:
214 case SD_BUS_TYPE_UINT16:
215 case SD_BUS_TYPE_INT32:
216 case SD_BUS_TYPE_UINT32:
217 case SD_BUS_TYPE_UNIX_FD:
218 case SD_BUS_TYPE_INT64:
219 case SD_BUS_TYPE_UINT64:
220 case SD_BUS_TYPE_DOUBLE:
223 case SD_BUS_TYPE_STRUCT_BEGIN:
224 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
227 memcpy(t, p + 1, n - 2);
230 r = bus_gvariant_is_fixed_size(t);
237 assert_not_reached("Unknown signature type");
246 size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
247 if (sz + extra <= 0xFF)
249 else if (sz + extra*2 <= 0xFFFF)
251 else if (sz + extra*4 <= 0xFFFFFFFF)
257 size_t bus_gvariant_read_word_le(void *p, size_t sz) {
267 return *(uint8_t*) p;
272 return le16toh(x.u16);
274 return le32toh(x.u32);
276 return le64toh(x.u64);
278 assert_not_reached("unknown word width");
281 void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
289 assert(sz == 8 || (value < (1ULL << (sz*8))));
292 *(uint8_t*) p = value;
295 x.u16 = htole16((uint16_t) value);
297 x.u32 = htole32((uint32_t) value);
299 x.u64 = htole64((uint64_t) value);
301 assert_not_reached("unknown word width");