1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "bus-gvariant.h"
11 #include "bus-signature.h"
14 int bus_gvariant_get_size(const char *signature
) {
18 /* For fixed size structs. Fails for variable size structs. */
24 r
= signature_element_length(p
, &n
);
33 r
= bus_gvariant_get_alignment(t
);
37 sum
= ALIGN_TO(sum
, r
);
42 case SD_BUS_TYPE_BOOLEAN
:
43 case SD_BUS_TYPE_BYTE
:
47 case SD_BUS_TYPE_INT16
:
48 case SD_BUS_TYPE_UINT16
:
52 case SD_BUS_TYPE_INT32
:
53 case SD_BUS_TYPE_UINT32
:
54 case SD_BUS_TYPE_UNIX_FD
:
58 case SD_BUS_TYPE_INT64
:
59 case SD_BUS_TYPE_UINT64
:
60 case SD_BUS_TYPE_DOUBLE
:
64 case SD_BUS_TYPE_STRUCT_BEGIN
:
65 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
67 /* unary type () has fixed size of 1 */
72 memcpy(t
, p
+ 1, n
- 2);
75 r
= bus_gvariant_get_size(t
);
84 case SD_BUS_TYPE_STRING
:
85 case SD_BUS_TYPE_OBJECT_PATH
:
86 case SD_BUS_TYPE_SIGNATURE
:
87 case SD_BUS_TYPE_ARRAY
:
88 case SD_BUS_TYPE_VARIANT
:
92 assert_not_reached("Unknown signature type");
98 r
= bus_gvariant_get_alignment(signature
);
102 return ALIGN_TO(sum
, r
);
105 int bus_gvariant_get_alignment(const char *signature
) {
106 size_t alignment
= 1;
111 while (*p
!= 0 && alignment
< 8) {
115 r
= signature_element_length(p
, &n
);
121 case SD_BUS_TYPE_BYTE
:
122 case SD_BUS_TYPE_BOOLEAN
:
123 case SD_BUS_TYPE_STRING
:
124 case SD_BUS_TYPE_OBJECT_PATH
:
125 case SD_BUS_TYPE_SIGNATURE
:
129 case SD_BUS_TYPE_INT16
:
130 case SD_BUS_TYPE_UINT16
:
134 case SD_BUS_TYPE_INT32
:
135 case SD_BUS_TYPE_UINT32
:
136 case SD_BUS_TYPE_UNIX_FD
:
140 case SD_BUS_TYPE_INT64
:
141 case SD_BUS_TYPE_UINT64
:
142 case SD_BUS_TYPE_DOUBLE
:
143 case SD_BUS_TYPE_VARIANT
:
147 case SD_BUS_TYPE_ARRAY
: {
150 memcpy(t
, p
+ 1, n
- 1);
153 a
= bus_gvariant_get_alignment(t
);
157 case SD_BUS_TYPE_STRUCT_BEGIN
:
158 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
161 memcpy(t
, p
+ 1, n
- 2);
164 a
= bus_gvariant_get_alignment(t
);
169 assert_not_reached("Unknown signature type");
175 assert(a
> 0 && a
<= 8);
176 if ((size_t) a
> alignment
)
177 alignment
= (size_t) a
;
185 int bus_gvariant_is_fixed_size(const char *signature
) {
195 r
= signature_element_length(p
, &n
);
201 case SD_BUS_TYPE_STRING
:
202 case SD_BUS_TYPE_OBJECT_PATH
:
203 case SD_BUS_TYPE_SIGNATURE
:
204 case SD_BUS_TYPE_ARRAY
:
205 case SD_BUS_TYPE_VARIANT
:
208 case SD_BUS_TYPE_BYTE
:
209 case SD_BUS_TYPE_BOOLEAN
:
210 case SD_BUS_TYPE_INT16
:
211 case SD_BUS_TYPE_UINT16
:
212 case SD_BUS_TYPE_INT32
:
213 case SD_BUS_TYPE_UINT32
:
214 case SD_BUS_TYPE_UNIX_FD
:
215 case SD_BUS_TYPE_INT64
:
216 case SD_BUS_TYPE_UINT64
:
217 case SD_BUS_TYPE_DOUBLE
:
220 case SD_BUS_TYPE_STRUCT_BEGIN
:
221 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
224 memcpy(t
, p
+ 1, n
- 2);
227 r
= bus_gvariant_is_fixed_size(t
);
234 assert_not_reached("Unknown signature type");
243 size_t bus_gvariant_determine_word_size(size_t sz
, size_t extra
) {
244 if (sz
+ extra
<= 0xFF)
246 else if (sz
+ extra
*2 <= 0xFFFF)
248 else if (sz
+ extra
*4 <= 0xFFFFFFFF)
254 size_t bus_gvariant_read_word_le(void *p
, size_t sz
) {
264 return *(uint8_t*) p
;
269 return le16toh(x
.u16
);
271 return le32toh(x
.u32
);
273 return le64toh(x
.u64
);
275 assert_not_reached("unknown word width");
278 void bus_gvariant_write_word_le(void *p
, size_t sz
, size_t value
) {
286 assert(sz
== 8 || (value
< (1ULL << (sz
*8))));
289 *(uint8_t*) p
= value
;
292 x
.u16
= htole16((uint16_t) value
);
294 x
.u32
= htole32((uint32_t) value
);
296 x
.u64
= htole64((uint64_t) value
);
298 assert_not_reached("unknown word width");