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");