]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/shared/xml.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
7 #include "string-util.h"
17 static void inc_lines(unsigned *line
, const char *s
, size_t n
) {
26 f
= memchr(p
, '\n', n
);
36 /* We don't actually do real XML here. We only read a simplistic
37 * subset, that is a bit less strict that XML and lacks all the more
38 * complex features, like entities, or namespaces. However, we do
39 * support some HTML5-like simplifications */
41 int xml_tokenize(const char **p
, char **name
, void **state
, unsigned *line
) {
42 const char *c
, *e
, *b
;
51 t
= PTR_TO_INT(*state
);
54 if (t
== STATE_NULL
) {
69 e
= strchrnul(c
, '<');
72 ret
= strndup(c
, e
- c
);
76 inc_lines(line
, c
, e
- c
);
80 *state
= INT_TO_PTR(STATE_TEXT
);
88 if (startswith(b
, "!--")) {
90 e
= strstr(b
+ 3, "-->");
94 inc_lines(line
, b
, e
+ 3 - b
);
101 /* Processing instruction */
103 e
= strstr(b
+ 1, "?>");
107 inc_lines(line
, b
, e
+ 2 - b
);
116 e
= strchr(b
+ 1, '>');
120 inc_lines(line
, b
, e
+ 1 - b
);
133 e
= strpbrk(b
, WHITESPACE
"/>");
137 ret
= strndup(b
, e
- b
);
143 *state
= INT_TO_PTR(STATE_TAG
);
150 b
= c
+ strspn(c
, WHITESPACE
);
154 inc_lines(line
, c
, b
- c
);
156 e
= b
+ strcspn(b
, WHITESPACE
"=/>");
160 ret
= strndup(b
, e
- b
);
166 *state
= INT_TO_PTR(STATE_ATTRIBUTE
);
168 return XML_ATTRIBUTE_NAME
;
171 if (startswith(b
, "/>")) {
174 *name
= NULL
; /* For empty tags we return a NULL name, the caller must be prepared for that */
176 *state
= INT_TO_PTR(STATE_TEXT
);
178 return XML_TAG_CLOSE_EMPTY
;
188 case STATE_ATTRIBUTE
:
193 if (IN_SET(*c
, '\'', '"')) {
194 /* Tag with a quoted value */
200 inc_lines(line
, c
, e
- c
);
202 ret
= strndup(c
+1, e
- c
- 1);
208 *state
= INT_TO_PTR(STATE_TAG
);
210 return XML_ATTRIBUTE_VALUE
;
214 /* Tag with a value without quotes */
216 b
= strpbrk(c
, WHITESPACE
">");
220 ret
= strndup(c
, b
- c
);
226 *state
= INT_TO_PTR(STATE_TAG
);
227 return XML_ATTRIBUTE_VALUE
;
236 assert_not_reached("Bad state");