]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/xml.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "string-util.h"
18 static void inc_lines(unsigned *line
, const char *s
, size_t n
) {
27 f
= memchr(p
, '\n', n
);
37 /* We don't actually do real XML here. We only read a simplistic
38 * subset, that is a bit less strict that XML and lacks all the more
39 * complex features, like entities, or namespaces. However, we do
40 * support some HTML5-like simplifications */
42 int xml_tokenize(const char **p
, char **name
, void **state
, unsigned *line
) {
43 const char *c
, *e
, *b
;
52 t
= PTR_TO_INT(*state
);
55 if (t
== STATE_NULL
) {
70 e
= strchrnul(c
, '<');
73 ret
= strndup(c
, e
- c
);
77 inc_lines(line
, c
, e
- c
);
81 *state
= INT_TO_PTR(STATE_TEXT
);
89 if (startswith(b
, "!--")) {
91 e
= strstr(b
+ 3, "-->");
95 inc_lines(line
, b
, e
+ 3 - b
);
102 /* Processing instruction */
104 e
= strstr(b
+ 1, "?>");
108 inc_lines(line
, b
, e
+ 2 - b
);
117 e
= strchr(b
+ 1, '>');
121 inc_lines(line
, b
, e
+ 1 - b
);
134 e
= strpbrk(b
, WHITESPACE
"/>");
138 ret
= strndup(b
, e
- b
);
144 *state
= INT_TO_PTR(STATE_TAG
);
151 b
= c
+ strspn(c
, WHITESPACE
);
155 inc_lines(line
, c
, b
- c
);
157 e
= b
+ strcspn(b
, WHITESPACE
"=/>");
161 ret
= strndup(b
, e
- b
);
167 *state
= INT_TO_PTR(STATE_ATTRIBUTE
);
169 return XML_ATTRIBUTE_NAME
;
172 if (startswith(b
, "/>")) {
175 *name
= NULL
; /* For empty tags we return a NULL name, the caller must be prepared for that */
177 *state
= INT_TO_PTR(STATE_TEXT
);
179 return XML_TAG_CLOSE_EMPTY
;
189 case STATE_ATTRIBUTE
:
194 if (IN_SET(*c
, '\'', '"')) {
195 /* Tag with a quoted value */
201 inc_lines(line
, c
, e
- c
);
203 ret
= strndup(c
+1, e
- c
- 1);
209 *state
= INT_TO_PTR(STATE_TAG
);
211 return XML_ATTRIBUTE_VALUE
;
215 /* Tag with a value without quotes */
217 b
= strpbrk(c
, WHITESPACE
">");
221 ret
= strndup(c
, b
- c
);
227 *state
= INT_TO_PTR(STATE_TAG
);
228 return XML_ATTRIBUTE_VALUE
;
237 assert_not_reached("Bad state");