chiark / gitweb /
sd-bus: rename "connection name" to "description" for the sd-bus API too
[elogind.git] / src / libsystemd / sd-bus / bus-gvariant.c
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
27 int bus_gvariant_get_size(const char *signature) {
28         const char *p;
29         int sum = 0, r;
30
31         /* For fixed size structs. Fails for variable size structs. */
32
33         p = signature;
34         while (*p != 0) {
35                 size_t n;
36
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;
45
46                         r = bus_gvariant_get_alignment(t);
47                         if (r < 0)
48                                 return r;
49
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;
104         }
105
106         r = bus_gvariant_get_alignment(signature);
107         if (r < 0)
108                 return r;
109
110         return ALIGN_TO(sum, r);
111 }
112
113 int 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
193 int 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 }