xmlchar

package
v1.26.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 5 Imported by: 0

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 Clean added in v1.26.5

func Clean(s string) bool

Clean is CleanBytes for a string, read in place — no copy.

func CleanBytes added in v1.26.5

func CleanBytes(b []byte) bool

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

func DecodeRef(ref []byte) (rune, bool)

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

func IsChar(r rune) bool

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

func Find(s string) (Bad, bool)

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.

func FindBytes added in v1.26.5

func FindBytes(b []byte) (Bad, bool)

FindBytes is Find for a byte slice, without converting it to a string — the reader calls it on a packet's whole Data body.

func (Bad) String added in v1.26.5

func (b Bad) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL