2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "bus-gvariant.h"
21 #include "bus-signature.h"
24 int bus_gvariant_get_size(const char *signature) {
28 /* For fixed size structs. Fails for variable size structs. */
34 r = signature_element_length(p, &n);
43 r = bus_gvariant_get_alignment(t);
47 sum = ALIGN_TO(sum, r);
52 case SD_BUS_TYPE_BOOLEAN:
53 case SD_BUS_TYPE_BYTE:
57 case SD_BUS_TYPE_INT16:
58 case SD_BUS_TYPE_UINT16:
62 case SD_BUS_TYPE_INT32:
63 case SD_BUS_TYPE_UINT32:
64 case SD_BUS_TYPE_UNIX_FD:
68 case SD_BUS_TYPE_INT64:
69 case SD_BUS_TYPE_UINT64:
70 case SD_BUS_TYPE_DOUBLE:
74 case SD_BUS_TYPE_STRUCT_BEGIN:
75 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
77 /* unary type () has fixed size of 1 */
82 memcpy(t, p + 1, n - 2);
85 r = bus_gvariant_get_size(t);
94 case SD_BUS_TYPE_STRING:
95 case SD_BUS_TYPE_OBJECT_PATH:
96 case SD_BUS_TYPE_SIGNATURE:
97 case SD_BUS_TYPE_ARRAY:
98 case SD_BUS_TYPE_VARIANT:
102 assert_not_reached("Unknown signature type");
108 r = bus_gvariant_get_alignment(signature);
112 return ALIGN_TO(sum, r);
115 int bus_gvariant_get_alignment(const char *signature) {
116 size_t alignment = 1;
121 while (*p != 0 && alignment < 8) {
125 r = signature_element_length(p, &n);
131 case SD_BUS_TYPE_BYTE:
132 case SD_BUS_TYPE_BOOLEAN:
133 case SD_BUS_TYPE_STRING:
134 case SD_BUS_TYPE_OBJECT_PATH:
135 case SD_BUS_TYPE_SIGNATURE:
139 case SD_BUS_TYPE_INT16:
140 case SD_BUS_TYPE_UINT16:
144 case SD_BUS_TYPE_INT32:
145 case SD_BUS_TYPE_UINT32:
146 case SD_BUS_TYPE_UNIX_FD:
150 case SD_BUS_TYPE_INT64:
151 case SD_BUS_TYPE_UINT64:
152 case SD_BUS_TYPE_DOUBLE:
153 case SD_BUS_TYPE_VARIANT:
157 case SD_BUS_TYPE_ARRAY: {
160 memcpy(t, p + 1, n - 1);
163 a = bus_gvariant_get_alignment(t);
167 case SD_BUS_TYPE_STRUCT_BEGIN:
168 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
171 memcpy(t, p + 1, n - 2);
174 a = bus_gvariant_get_alignment(t);
179 assert_not_reached("Unknown signature type");
185 assert(a > 0 && a <= 8);
186 if ((size_t) a > alignment)
187 alignment = (size_t) a;
195 int bus_gvariant_is_fixed_size(const char *signature) {
205 r = signature_element_length(p, &n);
211 case SD_BUS_TYPE_STRING:
212 case SD_BUS_TYPE_OBJECT_PATH:
213 case SD_BUS_TYPE_SIGNATURE:
214 case SD_BUS_TYPE_ARRAY:
215 case SD_BUS_TYPE_VARIANT:
218 case SD_BUS_TYPE_BYTE:
219 case SD_BUS_TYPE_BOOLEAN:
220 case SD_BUS_TYPE_INT16:
221 case SD_BUS_TYPE_UINT16:
222 case SD_BUS_TYPE_INT32:
223 case SD_BUS_TYPE_UINT32:
224 case SD_BUS_TYPE_UNIX_FD:
225 case SD_BUS_TYPE_INT64:
226 case SD_BUS_TYPE_UINT64:
227 case SD_BUS_TYPE_DOUBLE:
230 case SD_BUS_TYPE_STRUCT_BEGIN:
231 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
234 memcpy(t, p + 1, n - 2);
237 r = bus_gvariant_is_fixed_size(t);
244 assert_not_reached("Unknown signature type");
253 size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
254 if (sz + extra <= 0xFF)
256 else if (sz + extra*2 <= 0xFFFF)
258 else if (sz + extra*4 <= 0xFFFFFFFF)
264 size_t bus_gvariant_read_word_le(void *p, size_t sz) {
274 return *(uint8_t*) p;
279 return le16toh(x.u16);
281 return le32toh(x.u32);
283 return le64toh(x.u64);
285 assert_not_reached("unknown word width");
288 void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
296 assert(sz == 8 || (value < (1ULL << (sz*8))));
299 *(uint8_t*) p = value;
302 x.u16 = htole16((uint16_t) value);
304 x.u32 = htole32((uint32_t) value);
306 x.u64 = htole64((uint64_t) value);
308 assert_not_reached("unknown word width");