1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "bus-gvariant.h"
9 #include "bus-signature.h"
12 int bus_gvariant_get_size(const char *signature
) {
16 /* For fixed size structs. Fails for variable size structs. */
22 r
= signature_element_length(p
, &n
);
31 r
= bus_gvariant_get_alignment(t
);
35 sum
= ALIGN_TO(sum
, r
);
40 case SD_BUS_TYPE_BOOLEAN
:
41 case SD_BUS_TYPE_BYTE
:
45 case SD_BUS_TYPE_INT16
:
46 case SD_BUS_TYPE_UINT16
:
50 case SD_BUS_TYPE_INT32
:
51 case SD_BUS_TYPE_UINT32
:
52 case SD_BUS_TYPE_UNIX_FD
:
56 case SD_BUS_TYPE_INT64
:
57 case SD_BUS_TYPE_UINT64
:
58 case SD_BUS_TYPE_DOUBLE
:
62 case SD_BUS_TYPE_STRUCT_BEGIN
:
63 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
65 /* unary type () has fixed size of 1 */
70 memcpy(t
, p
+ 1, n
- 2);
73 r
= bus_gvariant_get_size(t
);
82 case SD_BUS_TYPE_STRING
:
83 case SD_BUS_TYPE_OBJECT_PATH
:
84 case SD_BUS_TYPE_SIGNATURE
:
85 case SD_BUS_TYPE_ARRAY
:
86 case SD_BUS_TYPE_VARIANT
:
90 assert_not_reached("Unknown signature type");
96 r
= bus_gvariant_get_alignment(signature
);
100 return ALIGN_TO(sum
, r
);
103 int bus_gvariant_get_alignment(const char *signature
) {
104 size_t alignment
= 1;
109 while (*p
!= 0 && alignment
< 8) {
113 r
= signature_element_length(p
, &n
);
119 case SD_BUS_TYPE_BYTE
:
120 case SD_BUS_TYPE_BOOLEAN
:
121 case SD_BUS_TYPE_STRING
:
122 case SD_BUS_TYPE_OBJECT_PATH
:
123 case SD_BUS_TYPE_SIGNATURE
:
127 case SD_BUS_TYPE_INT16
:
128 case SD_BUS_TYPE_UINT16
:
132 case SD_BUS_TYPE_INT32
:
133 case SD_BUS_TYPE_UINT32
:
134 case SD_BUS_TYPE_UNIX_FD
:
138 case SD_BUS_TYPE_INT64
:
139 case SD_BUS_TYPE_UINT64
:
140 case SD_BUS_TYPE_DOUBLE
:
141 case SD_BUS_TYPE_VARIANT
:
145 case SD_BUS_TYPE_ARRAY
: {
148 memcpy(t
, p
+ 1, n
- 1);
151 a
= bus_gvariant_get_alignment(t
);
155 case SD_BUS_TYPE_STRUCT_BEGIN
:
156 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
159 memcpy(t
, p
+ 1, n
- 2);
162 a
= bus_gvariant_get_alignment(t
);
167 assert_not_reached("Unknown signature type");
173 assert(a
> 0 && a
<= 8);
174 if ((size_t) a
> alignment
)
175 alignment
= (size_t) a
;
183 int bus_gvariant_is_fixed_size(const char *signature
) {
193 r
= signature_element_length(p
, &n
);
199 case SD_BUS_TYPE_STRING
:
200 case SD_BUS_TYPE_OBJECT_PATH
:
201 case SD_BUS_TYPE_SIGNATURE
:
202 case SD_BUS_TYPE_ARRAY
:
203 case SD_BUS_TYPE_VARIANT
:
206 case SD_BUS_TYPE_BYTE
:
207 case SD_BUS_TYPE_BOOLEAN
:
208 case SD_BUS_TYPE_INT16
:
209 case SD_BUS_TYPE_UINT16
:
210 case SD_BUS_TYPE_INT32
:
211 case SD_BUS_TYPE_UINT32
:
212 case SD_BUS_TYPE_UNIX_FD
:
213 case SD_BUS_TYPE_INT64
:
214 case SD_BUS_TYPE_UINT64
:
215 case SD_BUS_TYPE_DOUBLE
:
218 case SD_BUS_TYPE_STRUCT_BEGIN
:
219 case SD_BUS_TYPE_DICT_ENTRY_BEGIN
: {
222 memcpy(t
, p
+ 1, n
- 2);
225 r
= bus_gvariant_is_fixed_size(t
);
232 assert_not_reached("Unknown signature type");
241 size_t bus_gvariant_determine_word_size(size_t sz
, size_t extra
) {
242 if (sz
+ extra
<= 0xFF)
244 else if (sz
+ extra
*2 <= 0xFFFF)
246 else if (sz
+ extra
*4 <= 0xFFFFFFFF)
252 size_t bus_gvariant_read_word_le(void *p
, size_t sz
) {
262 return *(uint8_t*) p
;
267 return le16toh(x
.u16
);
269 return le32toh(x
.u32
);
271 return le64toh(x
.u64
);
273 assert_not_reached("unknown word width");
276 void bus_gvariant_write_word_le(void *p
, size_t sz
, size_t value
) {
284 assert(sz
== 8 || (value
< (1ULL << (sz
*8))));
287 *(uint8_t*) p
= value
;
290 x
.u16
= htole16((uint16_t) value
);
292 x
.u32
= htole32((uint32_t) value
);
294 x
.u64
= htole64((uint64_t) value
);
296 assert_not_reached("unknown word width");