| 91 | | auto q = text.eatAttrName (p); |
|---|
| 92 | | |
|---|
| 93 | | if (*q == ':') |
|---|
| 94 | | { |
|---|
| 95 | | prefix = p[0 .. q - p]; |
|---|
| 96 | | q = text.eatAttrName (p = q + 1); |
|---|
| 97 | | localName = p[0 .. q - p]; |
|---|
| 98 | | } |
|---|
| 99 | | else |
|---|
| 100 | | { |
|---|
| 101 | | prefix = null; |
|---|
| 102 | | localName = p[0 .. q - p]; |
|---|
| 103 | | } |
|---|
| 104 | | |
|---|
| 105 | | type = XmlTokenType.Attribute; |
|---|
| 106 | | if (*q <= 32) |
|---|
| 107 | | { |
|---|
| 108 | | auto e = text.end; |
|---|
| 109 | | do { |
|---|
| 110 | | if (++q >= e) |
|---|
| 111 | | return doEndOfStream; |
|---|
| 112 | | } while (*q <= 32); |
|---|
| 113 | | } |
|---|
| 114 | | |
|---|
| 115 | | if (*q is '=') |
|---|
| 116 | | return doAttributeValue (q + 1); |
|---|
| 117 | | return false; |
|---|
| 118 | | } |
|---|
| 119 | | |
|---|
| 120 | | /*********************************************************************** |
|---|
| 121 | | |
|---|
| 122 | | ***********************************************************************/ |
|---|
| 123 | | |
|---|
| 124 | | private bool doEndEmptyElement() |
|---|
| 125 | | { |
|---|
| 126 | | if (text[0..2] != "/>") |
|---|
| 127 | | return doUnexpected("/>"); |
|---|
| | 77 | if (*p <= 32) |
|---|
| | 78 | { |
|---|
| | 79 | while (*++p <= 32) |
|---|
| | 80 | if (p >= text.end) |
|---|
| | 81 | return doEndOfStream; |
|---|
| | 82 | text.point = p; |
|---|
| | 83 | } |
|---|
| | 84 | |
|---|
| | 85 | if (type >= XmlTokenType.EndElement) |
|---|
| | 86 | return doMain; |
|---|
| | 87 | |
|---|
| | 88 | // in element |
|---|
| | 89 | switch (*p) |
|---|
| | 90 | { |
|---|
| | 91 | case '/': |
|---|
| | 92 | return doEndEmptyElement; |
|---|
| | 93 | |
|---|
| | 94 | case '>': |
|---|
| | 95 | ++depth; |
|---|
| | 96 | ++text.point; |
|---|
| | 97 | return doMain; |
|---|
| | 98 | |
|---|
| | 99 | default: |
|---|
| | 100 | return doAttributeName; |
|---|
| | 101 | } |
|---|
| | 102 | } |
|---|
| 129 | | type = XmlTokenType.EndEmptyElement; |
|---|
| 130 | | localName = prefix = null; |
|---|
| 131 | | text.point += 2; |
|---|
| 132 | | return true; |
|---|
| 133 | | } |
|---|
| 134 | | |
|---|
| 135 | | /*********************************************************************** |
|---|
| 136 | | |
|---|
| 137 | | ***********************************************************************/ |
|---|
| 138 | | |
|---|
| 139 | | private bool doComment() |
|---|
| 140 | | { |
|---|
| 141 | | auto p = text.point; |
|---|
| 142 | | |
|---|
| 143 | | while (text.good) |
|---|
| 144 | | { |
|---|
| 145 | | if (! text.forwardLocate('-')) |
|---|
| 146 | | return doUnexpectedEOF; |
|---|
| 147 | | |
|---|
| 148 | | if (text[0..3] == "-->") |
|---|
| 149 | | { |
|---|
| 150 | | rawValue = p [0 .. text.point - p]; |
|---|
| 151 | | type = XmlTokenType.Comment; |
|---|
| 152 | | //prefix = null; |
|---|
| 153 | | text.point += 3; |
|---|
| 154 | | return true; |
|---|
| 155 | | } |
|---|
| 156 | | ++text.point; |
|---|
| 157 | | } |
|---|
| 158 | | |
|---|
| 159 | | return doUnexpectedEOF; |
|---|
| 160 | | } |
|---|
| 161 | | |
|---|
| 162 | | /*********************************************************************** |
|---|
| 163 | | |
|---|
| 164 | | ***********************************************************************/ |
|---|
| 165 | | |
|---|
| 166 | | private bool doCData() |
|---|
| 167 | | { |
|---|
| 168 | | auto p = text.point; |
|---|
| 169 | | |
|---|
| 170 | | while (text.good) |
|---|
| 171 | | { |
|---|
| 172 | | if (! text.forwardLocate(']')) |
|---|
| 173 | | return doUnexpectedEOF; |
|---|
| 174 | | |
|---|
| 175 | | if (text[0..3] == "]]>") |
|---|
| 176 | | { |
|---|
| 177 | | type = XmlTokenType.CData; |
|---|
| 178 | | rawValue = p [0 .. text.point - p]; |
|---|
| 179 | | //prefix = null; |
|---|
| 180 | | text.point += 3; |
|---|
| 181 | | return true; |
|---|
| 182 | | } |
|---|
| 183 | | ++text.point; |
|---|
| 184 | | } |
|---|
| 185 | | |
|---|
| 186 | | return doUnexpectedEOF; |
|---|
| 187 | | } |
|---|
| 188 | | |
|---|
| 189 | | /*********************************************************************** |
|---|
| 190 | | |
|---|
| 191 | | ***********************************************************************/ |
|---|
| 192 | | |
|---|
| 193 | | private bool doPI() |
|---|
| 194 | | { |
|---|
| 195 | | auto p = text.point; |
|---|
| 196 | | text.eatElemName; |
|---|
| 197 | | ++text.point; |
|---|
| 198 | | |
|---|
| 199 | | while (text.good) |
|---|
| 200 | | { |
|---|
| 201 | | if (! text.forwardLocate('\?')) |
|---|
| 202 | | return doUnexpectedEOF; |
|---|
| 203 | | |
|---|
| 204 | | if (text.point[1] == '>') |
|---|
| 205 | | { |
|---|
| 206 | | type = XmlTokenType.PI; |
|---|
| 207 | | rawValue = p [0 .. text.point - p]; |
|---|
| 208 | | text.point += 2; |
|---|
| 209 | | return true; |
|---|
| 210 | | } |
|---|
| 211 | | ++text.point; |
|---|
| 212 | | } |
|---|
| 213 | | return doUnexpectedEOF; |
|---|
| 214 | | } |
|---|
| 215 | | |
|---|
| 216 | | /*********************************************************************** |
|---|
| 217 | | |
|---|
| 218 | | ***********************************************************************/ |
|---|
| 219 | | |
|---|
| 220 | | private bool doDoctype() |
|---|
| 221 | | { |
|---|
| 222 | | text.eatSpace; |
|---|
| 223 | | auto p = text.point; |
|---|
| 224 | | |
|---|
| 225 | | while (text.good) |
|---|
| 226 | | { |
|---|
| 227 | | if (*text.point == '>') |
|---|
| 228 | | { |
|---|
| 229 | | type = XmlTokenType.Doctype; |
|---|
| 230 | | rawValue = p [0 .. text.point - p]; |
|---|
| 231 | | prefix = null; |
|---|
| 232 | | ++text.point; |
|---|
| 233 | | return true; |
|---|
| 234 | | } |
|---|
| 235 | | else |
|---|
| 236 | | if (*text.point == '[') |
|---|
| 237 | | { |
|---|
| 238 | | ++text.point; |
|---|
| 239 | | text.forwardLocate(']'); |
|---|
| 240 | | ++text.point; |
|---|
| 241 | | } |
|---|
| 242 | | else |
|---|
| 243 | | ++text.point; |
|---|
| 244 | | } |
|---|
| 245 | | |
|---|
| 246 | | if (! text.good) |
|---|
| 247 | | return doUnexpectedEOF; |
|---|
| 248 | | return true; |
|---|
| 249 | | } |
|---|
| 250 | | |
|---|
| 251 | | /*********************************************************************** |
|---|
| 252 | | |
|---|
| 253 | | ***********************************************************************/ |
|---|
| 254 | | |
|---|
| 255 | | private bool doUnexpectedEOF() |
|---|
| 256 | | { |
|---|
| 257 | | return error ("Unexpected EOF"); |
|---|
| 258 | | } |
|---|
| 259 | | |
|---|
| 260 | | /*********************************************************************** |
|---|
| 261 | | |
|---|
| 262 | | ***********************************************************************/ |
|---|
| 263 | | |
|---|
| 264 | | private bool doUnexpected(char[] msg = null) |
|---|
| 265 | | { |
|---|
| 266 | | return error ("Unexpected event " ~ msg ~ " " ~ Integer.toString(type)); |
|---|
| 267 | | } |
|---|
| 268 | | |
|---|
| 269 | | /*********************************************************************** |
|---|
| 270 | | |
|---|
| 271 | | ***********************************************************************/ |
|---|
| 272 | | |
|---|
| 273 | | private bool doEndOfStream() |
|---|
| 274 | | { |
|---|
| 275 | | return false; |
|---|
| 276 | | } |
|---|
| 277 | | |
|---|
| 278 | | /*********************************************************************** |
|---|
| 279 | | |
|---|
| 280 | | ***********************************************************************/ |
|---|
| 281 | | |
|---|
| 282 | | private bool doMain() |
|---|
| | 104 | /*********************************************************************** |
|---|
| | 105 | |
|---|
| | 106 | ***********************************************************************/ |
|---|
| | 107 | |
|---|
| | 108 | private XmlTokenType doMain() |
|---|
| 413 | | if (type >= XmlTokenType.EndElement) |
|---|
| 414 | | return doMain; |
|---|
| 415 | | |
|---|
| 416 | | // in element |
|---|
| 417 | | switch (*p) |
|---|
| 418 | | { |
|---|
| 419 | | case '/': |
|---|
| 420 | | return doEndEmptyElement; |
|---|
| 421 | | |
|---|
| 422 | | case '>': |
|---|
| 423 | | ++depth; |
|---|
| | 249 | if (*q <= 32) |
|---|
| | 250 | { |
|---|
| | 251 | while (*++q <= 32) {} |
|---|
| | 252 | if (q >= e) |
|---|
| | 253 | return doUnexpectedEOF; |
|---|
| | 254 | } |
|---|
| | 255 | |
|---|
| | 256 | if (*q is '=') |
|---|
| | 257 | { |
|---|
| | 258 | while (*++q <= 32) {} |
|---|
| | 259 | if (q >= e) |
|---|
| | 260 | return doUnexpectedEOF; |
|---|
| | 261 | |
|---|
| | 262 | auto quote = *q; |
|---|
| | 263 | switch (quote) |
|---|
| | 264 | { |
|---|
| | 265 | case '"': |
|---|
| | 266 | case '\'': |
|---|
| | 267 | p = q + 1; |
|---|
| | 268 | while (*++q != quote) {} |
|---|
| | 269 | //q = text.forwardLocate(p, quote); |
|---|
| | 270 | if (q < e) |
|---|
| | 271 | { |
|---|
| | 272 | rawValue = p[0 .. q - p]; |
|---|
| | 273 | text.point = q + 1; //Skip end quote |
|---|
| | 274 | return type = XmlTokenType.Attribute; |
|---|
| | 275 | } |
|---|
| | 276 | return doUnexpectedEOF; |
|---|
| | 277 | |
|---|
| | 278 | default: |
|---|
| | 279 | return doUnexpected("\' or \""); |
|---|
| | 280 | } |
|---|
| | 281 | } |
|---|
| | 282 | |
|---|
| | 283 | return doUnexpected (q[0..1]); |
|---|
| | 284 | } |
|---|
| | 285 | |
|---|
| | 286 | /*********************************************************************** |
|---|
| | 287 | |
|---|
| | 288 | ***********************************************************************/ |
|---|
| | 289 | |
|---|
| | 290 | private XmlTokenType doEndEmptyElement() |
|---|
| | 291 | { |
|---|
| | 292 | if (text.point[0] is '/' && text.point[1] is '>') |
|---|
| | 293 | { |
|---|
| | 294 | localName = prefix = null; |
|---|
| | 295 | text.point += 2; |
|---|
| | 296 | return type = XmlTokenType.EndEmptyElement; |
|---|
| | 297 | } |
|---|
| | 298 | return doUnexpected("/>"); |
|---|
| | 299 | } |
|---|
| | 300 | |
|---|
| | 301 | /*********************************************************************** |
|---|
| | 302 | |
|---|
| | 303 | ***********************************************************************/ |
|---|
| | 304 | |
|---|
| | 305 | private XmlTokenType doComment() |
|---|
| | 306 | { |
|---|
| | 307 | auto p = text.point; |
|---|
| | 308 | |
|---|
| | 309 | while (text.good) |
|---|
| | 310 | { |
|---|
| | 311 | if (! text.forwardLocate('-')) |
|---|
| | 312 | return doUnexpectedEOF; |
|---|
| | 313 | |
|---|
| | 314 | if (text[0..3] == "-->") |
|---|
| | 315 | { |
|---|
| | 316 | rawValue = p [0 .. text.point - p]; |
|---|
| | 317 | //prefix = null; |
|---|
| | 318 | text.point += 3; |
|---|
| | 319 | return type = XmlTokenType.Comment; |
|---|
| | 320 | } |
|---|
| | 321 | ++text.point; |
|---|
| | 322 | } |
|---|
| | 323 | |
|---|
| | 324 | return doUnexpectedEOF; |
|---|
| | 325 | } |
|---|
| | 326 | |
|---|
| | 327 | /*********************************************************************** |
|---|
| | 328 | |
|---|
| | 329 | ***********************************************************************/ |
|---|
| | 330 | |
|---|
| | 331 | private XmlTokenType doCData() |
|---|
| | 332 | { |
|---|
| | 333 | auto p = text.point; |
|---|
| | 334 | |
|---|
| | 335 | while (text.good) |
|---|
| | 336 | { |
|---|
| | 337 | if (! text.forwardLocate(']')) |
|---|
| | 338 | return doUnexpectedEOF; |
|---|
| | 339 | |
|---|
| | 340 | if (text[0..3] == "]]>") |
|---|
| | 341 | { |
|---|
| | 342 | rawValue = p [0 .. text.point - p]; |
|---|
| | 343 | //prefix = null; |
|---|
| | 344 | text.point += 3; |
|---|
| | 345 | return type = XmlTokenType.CData; |
|---|
| | 346 | } |
|---|
| | 347 | ++text.point; |
|---|
| | 348 | } |
|---|
| | 349 | |
|---|
| | 350 | return doUnexpectedEOF; |
|---|
| | 351 | } |
|---|
| | 352 | |
|---|
| | 353 | /*********************************************************************** |
|---|
| | 354 | |
|---|
| | 355 | ***********************************************************************/ |
|---|
| | 356 | |
|---|
| | 357 | private XmlTokenType doPI() |
|---|
| | 358 | { |
|---|
| | 359 | auto p = text.point; |
|---|
| | 360 | text.eatElemName; |
|---|
| | 361 | ++text.point; |
|---|
| | 362 | |
|---|
| | 363 | while (text.good) |
|---|
| | 364 | { |
|---|
| | 365 | if (! text.forwardLocate('\?')) |
|---|
| | 366 | return doUnexpectedEOF; |
|---|
| | 367 | |
|---|
| | 368 | if (text.point[1] == '>') |
|---|
| | 369 | { |
|---|
| | 370 | rawValue = p [0 .. text.point - p]; |
|---|
| | 371 | text.point += 2; |
|---|
| | 372 | return type = XmlTokenType.PI; |
|---|
| | 373 | } |
|---|
| | 374 | ++text.point; |
|---|
| | 375 | } |
|---|
| | 376 | return doUnexpectedEOF; |
|---|
| | 377 | } |
|---|
| | 378 | |
|---|
| | 379 | /*********************************************************************** |
|---|
| | 380 | |
|---|
| | 381 | ***********************************************************************/ |
|---|
| | 382 | |
|---|
| | 383 | private XmlTokenType doDoctype() |
|---|
| | 384 | { |
|---|
| | 385 | text.eatSpace; |
|---|
| | 386 | auto p = text.point; |
|---|
| | 387 | |
|---|
| | 388 | while (text.good) |
|---|
| | 389 | { |
|---|
| | 390 | if (*text.point == '>') |
|---|
| | 391 | { |
|---|
| | 392 | rawValue = p [0 .. text.point - p]; |
|---|
| | 393 | prefix = null; |
|---|
| | 394 | ++text.point; |
|---|
| | 395 | return type = XmlTokenType.Doctype; |
|---|
| | 396 | } |
|---|
| | 397 | else |
|---|
| | 398 | if (*text.point == '[') |
|---|
| | 399 | { |
|---|
| 425 | | return doMain; |
|---|
| 426 | | |
|---|
| 427 | | default: |
|---|
| 428 | | break; |
|---|
| 429 | | } |
|---|
| 430 | | return doAttributeName; |
|---|
| 431 | | } |
|---|
| 432 | | |
|---|
| 433 | | /*********************************************************************** |
|---|
| 434 | | |
|---|
| 435 | | ***********************************************************************/ |
|---|
| 436 | | |
|---|
| 437 | | private bool doAttributeValue(Ch* q) |
|---|
| 438 | | { |
|---|
| 439 | | auto p = text.eatSpace (q); |
|---|
| 440 | | auto quote = *p++; |
|---|
| 441 | | |
|---|
| 442 | | switch (quote) |
|---|
| 443 | | { |
|---|
| 444 | | case '"': |
|---|
| 445 | | case '\'': |
|---|
| 446 | | q = text.forwardLocate(p, quote); |
|---|
| 447 | | rawValue = p[0 .. q - p]; |
|---|
| 448 | | text.point = q + 1; //Skip end quote |
|---|
| 449 | | return true; |
|---|
| 450 | | |
|---|
| 451 | | default: |
|---|
| 452 | | return doUnexpected("\' or \""); |
|---|
| 453 | | } |
|---|
| 454 | | } |
|---|
| 455 | | |
|---|
| 456 | | /*********************************************************************** |
|---|
| 457 | | |
|---|
| 458 | | ***********************************************************************/ |
|---|
| 459 | | |
|---|
| 460 | | private bool error (char[] msg) |
|---|
| | 401 | text.forwardLocate(']'); |
|---|
| | 402 | ++text.point; |
|---|
| | 403 | } |
|---|
| | 404 | else |
|---|
| | 405 | ++text.point; |
|---|
| | 406 | } |
|---|
| | 407 | |
|---|
| | 408 | if (! text.good) |
|---|
| | 409 | return doUnexpectedEOF; |
|---|
| | 410 | return XmlTokenType.Doctype; |
|---|
| | 411 | } |
|---|
| | 412 | |
|---|
| | 413 | /*********************************************************************** |
|---|
| | 414 | |
|---|
| | 415 | ***********************************************************************/ |
|---|
| | 416 | |
|---|
| | 417 | private XmlTokenType doUnexpectedEOF() |
|---|
| | 418 | { |
|---|
| | 419 | return error ("Unexpected EOF"); |
|---|
| | 420 | } |
|---|
| | 421 | |
|---|
| | 422 | /*********************************************************************** |
|---|
| | 423 | |
|---|
| | 424 | ***********************************************************************/ |
|---|
| | 425 | |
|---|
| | 426 | private XmlTokenType doUnexpected(char[] msg = null) |
|---|
| | 427 | { |
|---|
| | 428 | return error ("Unexpected event " ~ msg ~ " " ~ Integer.toString(type)); |
|---|
| | 429 | } |
|---|
| | 430 | |
|---|
| | 431 | /*********************************************************************** |
|---|
| | 432 | |
|---|
| | 433 | ***********************************************************************/ |
|---|
| | 434 | |
|---|
| | 435 | private XmlTokenType doEndOfStream() |
|---|
| | 436 | { |
|---|
| | 437 | return XmlTokenType.Done; |
|---|
| | 438 | } |
|---|
| | 439 | |
|---|
| | 440 | /*********************************************************************** |
|---|