1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "bus-gvariant.h"
23 #include "bus-signature.h"
26 int bus_gvariant_get_size(const char *signature) {
30 /* For fixed size structs. Fails for variable size structs. */
36 r = signature_element_length(p, &n);
45 r = bus_gvariant_get_alignment(t);
49 sum = ALIGN_TO(sum, r);
54 case SD_BUS_TYPE_BOOLEAN:
55 case SD_BUS_TYPE_BYTE:
59 case SD_BUS_TYPE_INT16:
60 case SD_BUS_TYPE_UINT16:
64 case SD_BUS_TYPE_INT32:
65 case SD_BUS_TYPE_UINT32:
66 case SD_BUS_TYPE_UNIX_FD:
70 case SD_BUS_TYPE_INT64:
71 case SD_BUS_TYPE_UINT64:
72 case SD_BUS_TYPE_DOUBLE:
76 case SD_BUS_TYPE_STRUCT_BEGIN:
77 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
79 /* unary type () has fixed size of 1 */
84 memcpy(t, p + 1, n - 2);
87 r = bus_gvariant_get_size(t);
96 case SD_BUS_TYPE_STRING:
97 case SD_BUS_TYPE_OBJECT_PATH:
98 case SD_BUS_TYPE_SIGNATURE:
99 case SD_BUS_TYPE_ARRAY:
100 case SD_BUS_TYPE_VARIANT:
104 assert_not_reached("Unknown signature type");
110 r = bus_gvariant_get_alignment(signature);
114 return ALIGN_TO(sum, r);
117 int bus_gvariant_get_alignment(const char *signature) {
118 size_t alignment = 1;
123 while (*p != 0 && alignment < 8) {
127 r = signature_element_length(p, &n);
133 case SD_BUS_TYPE_BYTE:
134 case SD_BUS_TYPE_BOOLEAN:
135 case SD_BUS_TYPE_STRING:
136 case SD_BUS_TYPE_OBJECT_PATH:
137 case SD_BUS_TYPE_SIGNATURE:
141 case SD_BUS_TYPE_INT16:
142 case SD_BUS_TYPE_UINT16:
146 case SD_BUS_TYPE_INT32:
147 case SD_BUS_TYPE_UINT32:
148 case SD_BUS_TYPE_UNIX_FD:
152 case SD_BUS_TYPE_INT64:
153 case SD_BUS_TYPE_UINT64:
154 case SD_BUS_TYPE_DOUBLE:
155 case SD_BUS_TYPE_VARIANT:
159 case SD_BUS_TYPE_ARRAY: {
162 memcpy(t, p + 1, n - 1);
165 a = bus_gvariant_get_alignment(t);
169 case SD_BUS_TYPE_STRUCT_BEGIN:
170 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
173 memcpy(t, p + 1, n - 2);
176 a = bus_gvariant_get_alignment(t);
181 assert_not_reached("Unknown signature type");
187 assert(a > 0 && a <= 8);
188 if ((size_t) a > alignment)
189 alignment = (size_t) a;
197 int bus_gvariant_is_fixed_size(const char *signature) {
207 r = signature_element_length(p, &n);
213 case SD_BUS_TYPE_STRING:
214 case SD_BUS_TYPE_OBJECT_PATH:
215 case SD_BUS_TYPE_SIGNATURE:
216 case SD_BUS_TYPE_ARRAY:
217 case SD_BUS_TYPE_VARIANT:
220 case SD_BUS_TYPE_BYTE:
221 case SD_BUS_TYPE_BOOLEAN:
222 case SD_BUS_TYPE_INT16:
223 case SD_BUS_TYPE_UINT16:
224 case SD_BUS_TYPE_INT32:
225 case SD_BUS_TYPE_UINT32:
226 case SD_BUS_TYPE_UNIX_FD:
227 case SD_BUS_TYPE_INT64:
228 case SD_BUS_TYPE_UINT64:
229 case SD_BUS_TYPE_DOUBLE:
232 case SD_BUS_TYPE_STRUCT_BEGIN:
233 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
236 memcpy(t, p + 1, n - 2);
239 r = bus_gvariant_is_fixed_size(t);
246 assert_not_reached("Unknown signature type");
255 size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) {
256 if (sz + extra <= 0xFF)
258 else if (sz + extra*2 <= 0xFFFF)
260 else if (sz + extra*4 <= 0xFFFFFFFF)
266 size_t bus_gvariant_read_word_le(void *p, size_t sz) {
276 return *(uint8_t*) p;
281 return le16toh(x.u16);
283 return le32toh(x.u32);
285 return le64toh(x.u64);
287 assert_not_reached("unknown word width");
290 void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) {
298 assert(sz == 8 || (value < (1ULL << (sz*8))));
301 *(uint8_t*) p = value;
304 x.u16 = htole16((uint16_t) value);
306 x.u32 = htole32((uint32_t) value);
308 x.u64 = htole64((uint64_t) value);
310 assert_not_reached("unknown word width");