chiark / gitweb /
tree-wide: remove Lennart's copyright lines
[elogind.git] / src / libelogind / sd-bus / bus-signature.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 ***/
4
5 #include <util.h>
6
7 #include "sd-bus.h"
8
9 #include "bus-signature.h"
10 #include "bus-type.h"
11
12 static int signature_element_length_internal(
13                 const char *s,
14                 bool allow_dict_entry,
15                 unsigned array_depth,
16                 unsigned struct_depth,
17                 size_t *l) {
18
19         int r;
20
21         if (!s)
22                 return -EINVAL;
23
24         assert(l);
25
26         if (bus_type_is_basic(*s) || *s == SD_BUS_TYPE_VARIANT) {
27                 *l = 1;
28                 return 0;
29         }
30
31         if (*s == SD_BUS_TYPE_ARRAY) {
32                 size_t t;
33
34                 if (array_depth >= 32)
35                         return -EINVAL;
36
37                 r = signature_element_length_internal(s + 1, true, array_depth+1, struct_depth, &t);
38                 if (r < 0)
39                         return r;
40
41                 *l = t + 1;
42                 return 0;
43         }
44
45         if (*s == SD_BUS_TYPE_STRUCT_BEGIN) {
46                 const char *p = s + 1;
47
48                 if (struct_depth >= 32)
49                         return -EINVAL;
50
51                 while (*p != SD_BUS_TYPE_STRUCT_END) {
52                         size_t t;
53
54                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
55                         if (r < 0)
56                                 return r;
57
58                         p += t;
59                 }
60
61                 *l = p - s + 1;
62                 return 0;
63         }
64
65         if (*s == SD_BUS_TYPE_DICT_ENTRY_BEGIN && allow_dict_entry) {
66                 const char *p = s + 1;
67                 unsigned n = 0;
68
69                 if (struct_depth >= 32)
70                         return -EINVAL;
71
72                 while (*p != SD_BUS_TYPE_DICT_ENTRY_END) {
73                         size_t t;
74
75                         if (n == 0 && !bus_type_is_basic(*p))
76                                 return -EINVAL;
77
78                         r = signature_element_length_internal(p, false, array_depth, struct_depth+1, &t);
79                         if (r < 0)
80                                 return r;
81
82                         p += t;
83                         n++;
84                 }
85
86                 if (n != 2)
87                         return -EINVAL;
88
89                 *l = p - s + 1;
90                 return 0;
91         }
92
93         return -EINVAL;
94 }
95
96 int signature_element_length(const char *s, size_t *l) {
97         return signature_element_length_internal(s, true, 0, 0, l);
98 }
99
100 bool signature_is_single(const char *s, bool allow_dict_entry) {
101         int r;
102         size_t t;
103
104         if (!s)
105                 return false;
106
107         r = signature_element_length_internal(s, allow_dict_entry, 0, 0, &t);
108         if (r < 0)
109                 return false;
110
111         return s[t] == 0;
112 }
113
114 bool signature_is_pair(const char *s) {
115
116         if (!s)
117                 return false;
118
119         if (!bus_type_is_basic(*s))
120                 return false;
121
122         return signature_is_single(s + 1, false);
123 }
124
125 bool signature_is_valid(const char *s, bool allow_dict_entry) {
126         const char *p;
127         int r;
128
129         if (!s)
130                 return false;
131
132         p = s;
133         while (*p) {
134                 size_t t;
135
136                 r = signature_element_length_internal(p, allow_dict_entry, 0, 0, &t);
137                 if (r < 0)
138                         return false;
139
140                 p += t;
141         }
142
143         return p - s <= 255;
144 }