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