PureXML/Sources/XPath
Mihaela Mihaljevic 9d0d92bda3
perf(xpath): make translate() and the substring search functions linear (#308)
translate(string, from, to) ran from.firstIndex(of: character) for every
character of the source, so a large from/to map made it O(string * from). And
contains/substring-before/substring-after matched the needle at every position
of the haystack (Array.starts(with:) per index), O(n*m) and quadratic on a
repetitive string, which is a denial-of-service vector on untrusted input.

translate() now builds a from-character to replacement map (and a delete set)
once, first occurrence winning, and translates each source character with an
O(1) lookup. The substring search is Knuth-Morris-Pratt, O(n+m), which never
rescans. The results are unchanged.

A 4000-character large-alphabet translate drops ~0.13s to ~0.002s; a 16000-
character repetitive contains drops ~0.054s to ~0.0002s. The full suite, the
W3C XPath/XSLT and Apache Xalan corpora, and the WASM build stay green;
TranslateFunctionTests and SubstringSearchTests pin the semantics.
2026-06-26 00:11:49 +02:00
..
Axis.swift perf(xpath): skip the document-order sort for an already-ordered single step (#283) 2026-06-25 05:04:00 +02:00
AxisNavigation.swift perf(xpath): cache and fuse the following-sibling/preceding-sibling axes (#306) 2026-06-25 22:41:32 +02:00
Budget.swift
Compiler.swift
CompilerDescendantFusion.swift perf(xpath): fuse // into a descendant step for non-positional predicates (#281) 2026-06-25 03:21:03 +02:00
CompilerPaths.swift perf(xpath): fuse // into a descendant step for non-positional predicates (#281) 2026-06-25 03:21:03 +02:00
CoreFunctions.swift
EvaluationContext.swift perf(xpath): cache and fuse the following-sibling/preceding-sibling axes (#306) 2026-06-25 22:41:32 +02:00
Evaluator.swift perf(xpath): skip the document-order sort for an already-ordered single step (#283) 2026-06-25 05:04:00 +02:00
EvaluatorOperators.swift
EvaluatorSteps.swift perf(xpath): cache and fuse the following-sibling/preceding-sibling axes (#306) 2026-06-25 22:41:32 +02:00
Expression.swift
EXSLTFunctions.swift fix(xslt): make key(), id(), and EXSLT set functions linear over wide fan-outs (#300) 2026-06-25 18:45:08 +02:00
NodeFunctions.swift
NodeTest.swift
Query.swift
QueryError.swift
Selection.swift
SiblingIndexCache.swift fix(xpath): cache the attribute index for document-order keys (#305) 2026-06-25 22:01:13 +02:00
Step.swift
StringFunctions.swift perf(xpath): make translate() and the substring search functions linear (#308) 2026-06-26 00:11:49 +02:00
Value.swift
XPathNode.swift fix(xpath): cache the attribute index for document-order keys (#305) 2026-06-25 22:01:13 +02:00