readDoctype reads a directive (until `>`).
()
| 545 | |
| 546 | // readDoctype reads a directive (until `>`). |
| 547 | func (d *Decoder) readDoctype() ([]byte, bool) { |
| 548 | if !d.checkAndDiscardPrefix(doctypeStart) { |
| 549 | if d.err == nil { |
| 550 | d.setSyntaxErrorf("invalid sequence <! not part of <!DOCTYPE, <!--, or <![CDATA[") |
| 551 | } |
| 552 | return nil, false |
| 553 | } |
| 554 | |
| 555 | d.buf.Reset() |
| 556 | |
| 557 | var ( |
| 558 | inQuote byte // Quote character of the current quote (' or "), 0 if not in quote |
| 559 | inBrackets bool // Whether we are inside brackets ([...] |
| 560 | ) |
| 561 | |
| 562 | // Read until '>' |
| 563 | for { |
| 564 | b, ok := d.mustReadByte() |
| 565 | if !ok { |
| 566 | return nil, false |
| 567 | } |
| 568 | |
| 569 | d.buf.WriteByte(b) |
| 570 | |
| 571 | switch { |
| 572 | case b == inQuote: |
| 573 | // We met the closing quote, exit quote mode. |
| 574 | inQuote = 0 |
| 575 | |
| 576 | case inQuote != 0: |
| 577 | // Inside a quote, do nothing. |
| 578 | |
| 579 | case b == '"' || b == '\'': |
| 580 | // We met an opening quote, enter quote mode. |
| 581 | inQuote = b |
| 582 | |
| 583 | case b == ']': |
| 584 | // We met a closing bracket. |
| 585 | // If we are not inside brackets, this is an error. |
| 586 | if !inBrackets { |
| 587 | d.setSyntaxErrorf("unexpected ']' in directive") |
| 588 | return nil, false |
| 589 | } |
| 590 | // Otherwise, exit brackets mode. |
| 591 | inBrackets = false |
| 592 | |
| 593 | case b == '[': |
| 594 | // We met an opening bracket. |
| 595 | // If we are already inside brackets, this is an error. |
| 596 | if inBrackets { |
| 597 | d.setSyntaxErrorf("nested '[' in directive") |
| 598 | return nil, false |
| 599 | } |
| 600 | // Otherwise, enter brackets mode. |
| 601 | inBrackets = true |
| 602 | |
| 603 | case inBrackets: |
| 604 | // Inside brackets, do nothing |
no test coverage detected