Documentation
¶
Overview ¶
Package xmlchar holds the character-level rules of XML 1.0 that every byte-level scanner in this framework needs.
It exists because the rules were copied instead of shared, and the copy went wrong. pkg/core/packet/parser_fast.go had a character-reference decoder that accepted `�`, control characters, surrogates and FFFE/FFFF — values XML has no way to represent — while encoding/xml rejects a document containing them. That was fixed in 1.19.2 by implementing the Char production from XML 1.0 §2.2. When pkg/xlsx grew its own scanner it grew its own decoder alongside, without that check, and the same bug came back: the fast path accepted `` and `` where the reference decoder errored.
A fast path that is more permissive than the parser it falls back to is worse than no fast path, because the result then depends on which one ran. One implementation, one set of tests.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CleanBytes ¶ added in v1.26.5
CleanBytes reports whether b is entirely text XML 1.0 can carry. It is the fast check for the reader, which runs it over a whole packet body: clean input never decodes a rune. Three passes, each over the whole slice: utf8.Valid (the standard library's word-at-a-time check), a word-at-a-time scan for C0 controls, and a search for EF BF BE / EF BF BF — U+FFFE and U+FFFF, the only well-formed UTF-8 the Char production excludes. Use FindBytes to locate what CleanBytes rejects.
func DecodeRef ¶
DecodeRef parses the body of a numeric character reference — the part between "&#" and ";", so "60" or "x3C" — and returns the rune it denotes.
ok=false covers every reason the reference is unusable: empty, a digit the base does not allow, a value past the Unicode maximum, or a code point the Char production forbids. The caller is expected to treat that as "this document is not something I can parse", not as a value to substitute.
func IsChar ¶
IsChar reports whether r is allowed as a character in an XML 1.0 document — the Char production of §2.2:
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
Excluded, and each for its own reason: most C0 controls have no representation at all; the surrogate range D800–DFFF is only meaningful inside UTF-16 and is not a character; FFFE and FFFF are permanently unassigned byte-order-mark sentinels.
Types ¶
type Bad ¶ added in v1.26.5
type Bad struct {
Offset int // byte offset of the bad spot
Rune rune // the character, when BadUTF8 is false
Byte byte // the first byte, when BadUTF8 is true
BadUTF8 bool
}
Bad is the first spot in a text that an XML 1.0 document cannot carry: either a byte that does not start valid UTF-8, or a well-formed character outside the Char production (U+0001, U+FFFE, …).
TDTP requires UTF-8 and nothing XML forbids, in every section and in every row. The writer refuses such text (naming where it is) and the reader refuses a packet carrying it, on the fast path exactly as encoding/xml does on the ordinary one.
func Find ¶ added in v1.26.5
Find returns the first spot in s that XML 1.0 cannot carry; ok is false when s is clean. ASCII is checked byte by byte without decoding, so clean ASCII text costs one comparison per byte.