]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-gvariant.c
po: Update German translation
[thirdparty/systemd.git] / src / libsystemd / sd-bus / bus-gvariant.c
CommitLineData
c1b9d935
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
22#include "util.h"
23#include "bus-type.h"
24#include "bus-gvariant.h"
25#include "bus-signature.h"
26
6647dc66
LP
27int bus_gvariant_get_size(const char *signature) {
28 const char *p;
29 int sum = 0, r;
c1b9d935 30
6647dc66 31 /* For fixed size structs. Fails for variable size structs. */
c1b9d935 32
6647dc66
LP
33 p = signature;
34 while (*p != 0) {
35 size_t n;
c1b9d935 36
6647dc66
LP
37 r = signature_element_length(p, &n);
38 if (r < 0)
39 return r;
40 else {
41 char t[n+1];
42
43 memcpy(t, p, n);
44 t[n] = 0;
c1b9d935 45
6647dc66
LP
46 r = bus_gvariant_get_alignment(t);
47 if (r < 0)
48 return r;
c1b9d935 49
6647dc66
LP
50 sum = ALIGN_TO(sum, r);
51 }
52
53 switch (*p) {
54
55 case SD_BUS_TYPE_BOOLEAN:
56 case SD_BUS_TYPE_BYTE:
57 sum += 1;
58 break;
59
60 case SD_BUS_TYPE_INT16:
61 case SD_BUS_TYPE_UINT16:
62 sum += 2;
63 break;
64
65 case SD_BUS_TYPE_INT32:
66 case SD_BUS_TYPE_UINT32:
67 case SD_BUS_TYPE_UNIX_FD:
68 sum += 4;
69 break;
70
71 case SD_BUS_TYPE_INT64:
72 case SD_BUS_TYPE_UINT64:
73 case SD_BUS_TYPE_DOUBLE:
74 sum += 8;
75 break;
76
77 case SD_BUS_TYPE_STRUCT_BEGIN:
78 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
79 char t[n-1];
80
81 memcpy(t, p + 1, n - 2);
82 t[n - 2] = 0;
83
84 r = bus_gvariant_get_size(t);
85 if (r < 0)
86 return r;
87
88 sum += r;
89 break;
90 }
91
92 case SD_BUS_TYPE_STRING:
93 case SD_BUS_TYPE_OBJECT_PATH:
94 case SD_BUS_TYPE_SIGNATURE:
95 case SD_BUS_TYPE_ARRAY:
96 case SD_BUS_TYPE_VARIANT:
97 return -EINVAL;
98
99 default:
100 assert_not_reached("Unknown signature type");
101 }
102
103 p += n;
c1b9d935
LP
104 }
105
6647dc66
LP
106 r = bus_gvariant_get_alignment(signature);
107 if (r < 0)
108 return r;
109
110 return ALIGN_TO(sum, r);
c1b9d935
LP
111}
112
113int bus_gvariant_get_alignment(const char *signature) {
114 size_t alignment = 1;
115 const char *p;
116 int r;
117
118 p = signature;
119 while (*p != 0 && alignment < 8) {
120 size_t n;
121 int a;
122
123 r = signature_element_length(p, &n);
124 if (r < 0)
125 return r;
126
127 switch (*p) {
128
129 case SD_BUS_TYPE_BYTE:
130 case SD_BUS_TYPE_BOOLEAN:
131 case SD_BUS_TYPE_STRING:
132 case SD_BUS_TYPE_OBJECT_PATH:
133 case SD_BUS_TYPE_SIGNATURE:
134 a = 1;
135 break;
136
137 case SD_BUS_TYPE_INT16:
138 case SD_BUS_TYPE_UINT16:
139 a = 2;
140 break;
141
142 case SD_BUS_TYPE_INT32:
143 case SD_BUS_TYPE_UINT32:
144 case SD_BUS_TYPE_UNIX_FD:
145 a = 4;
146 break;
147
148 case SD_BUS_TYPE_INT64:
149 case SD_BUS_TYPE_UINT64:
150 case SD_BUS_TYPE_DOUBLE:
151 case SD_BUS_TYPE_VARIANT:
152 a = 8;
153 break;
154
155 case SD_BUS_TYPE_ARRAY: {
156 char t[n];
157
158 memcpy(t, p + 1, n - 1);
159 t[n - 1] = 0;
160
161 a = bus_gvariant_get_alignment(t);
162 break;
163 }
164
165 case SD_BUS_TYPE_STRUCT_BEGIN:
166 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
167 char t[n-1];
168
169 memcpy(t, p + 1, n - 2);
170 t[n - 2] = 0;
171
172 a = bus_gvariant_get_alignment(t);
173 break;
174 }
175
176 default:
177 assert_not_reached("Unknown signature type");
178 }
179
180 if (a < 0)
181 return a;
182
183 assert(a > 0 && a <= 8);
184 if ((size_t) a > alignment)
185 alignment = (size_t) a;
186
187 p += n;
188 }
189
190 return alignment;
191}
192
193int bus_gvariant_is_fixed_size(const char *signature) {
194 const char *p;
195 int r;
196
197 assert(signature);
198
199 p = signature;
200 while (*p != 0) {
201 size_t n;
202
203 r = signature_element_length(p, &n);
204 if (r < 0)
205 return r;
206
207 switch (*p) {
208
209 case SD_BUS_TYPE_STRING:
210 case SD_BUS_TYPE_OBJECT_PATH:
211 case SD_BUS_TYPE_SIGNATURE:
212 case SD_BUS_TYPE_ARRAY:
213 case SD_BUS_TYPE_VARIANT:
214 return 0;
215
216 case SD_BUS_TYPE_BYTE:
217 case SD_BUS_TYPE_BOOLEAN:
218 case SD_BUS_TYPE_INT16:
219 case SD_BUS_TYPE_UINT16:
220 case SD_BUS_TYPE_INT32:
221 case SD_BUS_TYPE_UINT32:
222 case SD_BUS_TYPE_UNIX_FD:
223 case SD_BUS_TYPE_INT64:
224 case SD_BUS_TYPE_UINT64:
225 case SD_BUS_TYPE_DOUBLE:
226 break;
227
228 case SD_BUS_TYPE_STRUCT_BEGIN:
229 case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
230 char t[n-1];
231
232 memcpy(t, p + 1, n - 2);
233 t[n - 2] = 0;
234
235 r = bus_gvariant_is_fixed_size(t);
236 if (r <= 0)
237 return r;
238 break;
239 }
240
241 default:
242 assert_not_reached("Unknown signature type");
243 }
244
245 p += n;
246 }
247
248 return true;
249}