PureXML/Sources
Mihaela Mihaljevic fe0400c3df perf(parsing): byte-path quote handling, lazy expanded-name check, byte-scan entity guard
Third profile-guided pass (#139, docs/benchmarks.md pass 27), targeting
scanContentMarkup(), which inlines the start-tag/attribute/namespace scanners
and carries ~46% of parse time.

scanAttributeValue's opening and closing quote checks ran on the Character
path (peek + advance, buffering the quote as a Character only to compare and
discard it) on every attribute value in the document; both now check the raw
byte first, reaching the byte fast path with no Character buffering, with the
Character path kept as the off-fast-path fallback for streaming sources. The
quote bytes are ASCII and non-CR/LF, so the raw byte and the normalized
stream agree, the same reasoning peekByte's other callers already rely on.

NamespaceContext.checkExpandedNames allocated a Set's native storage and
built a concatenated URI+local key string per element even when at most one
attribute carries a namespace URI, where no duplicate is possible (the
default namespace never applies to attributes, and xmlns declarations carry
no URI). Counting URI-bearing attributes first, with no allocation, and
returning early below two skips all of it on the overwhelming majority of
elements; for xml:* attributes specifically the key exceeded the small-string
limit, so this also removes a real per-element heap allocation.

EntityDecoder.decode/decodeLenient guarded with raw.contains("&"), a
grapheme-by-grapheme walk to find one ASCII byte, once per ampersand-bearing
text node or attribute value; raw.utf8.contains(0x26) finds the same byte
without decoding graphemes, the same shape as checkNameShape's colon check.

The quote-handling extraction into two helpers also resolves the cyclomatic
complexity the inline version tripped. Six new regression tests pin the
quote edge cases (empty value, single-quoted, a quote kind nested inside the
other, unterminated at end of input) plus byte/Character-path agreement for
each in the parser path differential.

Verified: full local suite (1858 tests) and full W3C XSTS suite (14383
groups) pass unchanged. Parse ~6.00x -> ~4.75x versus libxml2 at the
20000-item corpus, best of 5.
2026-07-12 12:27:00 +02:00
..
Canonical perf(canonical): make the prefix rewrite and node-subset emit depth-safe (#355) 2026-06-27 17:08:37 +02:00
Catalog feat(catalog): honor group-level prefer override 2026-06-08 18:05:03 +02:00
Emitting perf(serialize): scan bytes, not graphemes, to find characters to escape (#297) 2026-06-25 15:39:20 +02:00
HTML perf(html): make HTML serialization depth-safe (#353) 2026-06-27 16:22:54 +02:00
Model fix(xpath): make string-value extraction iterative and comment-correct (#351) 2026-06-26 20:44:49 +02:00
Parsing perf(parsing): byte-path quote handling, lazy expanded-name check, byte-scan entity guard 2026-07-12 12:27:00 +02:00
Pattern feat(pattern): streaming xmlPattern matching 2026-06-08 05:49:13 +02:00
Regex fix(schema): back XSD \i and \c with the XML 1.0 Appendix B name classes (#378) 2026-06-29 07:05:27 +02:00
Schema fix(schema): literal RecurseAsIfGroup for a non-repeating base choice 2026-07-05 08:58:35 +02:00
Stream chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
Validation chore(concurrency): justify every @unchecked Sendable / nonisolated(unsafe) (#387) 2026-06-29 15:12:02 +02:00
XInclude perf(xinclude): make XInclude processing depth-safe (#354) 2026-06-27 16:55:03 +02:00
XPath chore(concurrency): justify every @unchecked Sendable / nonisolated(unsafe) (#387) 2026-06-29 15:12:02 +02:00
XPointer perf(xpointer): linear-time string-range() search (#314) 2026-06-26 04:01:41 +02:00
XSLT chore(codeberg): update links for NodetteHQ 2026-07-05 12:59:57 +02:00
API.swift perf(parse): build the TreeNode tree directly from the event stream (#295) 2026-06-25 14:15:57 +02:00
Lint.swift feat(editor): unified lint surface merging parse and validation diagnostics 2026-06-08 13:18:29 +02:00
PureXML.swift feat(html): lenient HTML parser and serializer 2026-06-08 07:12:42 +02:00
QuickFix.swift feat(editor): structured quick-fixes from completions 2026-06-08 13:35:33 +02:00