pjfanning opened a new pull request, #1437: URL: https://github.com/apache/poi/pull/1437
Follow-up to #1436, which fixes the same class of problem in `rangeConditionalPattern`. Repro: `new DataFormatter().formatRawCellContents(1.5, -1, "#".repeat(20_000) + "/")`. Any format containing `#/` or `?/` reaches `fractionPattern`. The old regex took about 2.5 s on a 5,000-character run of `#` and about 28 s on 20,000. Cause: in `(?:([#\d]+)\s+)?(#+)\s*/\s*([#\d]+)`, `find()` retries from every position inside a run of `#` or digits, and each attempt scans to the end of the run, so the cost is quadratic. Fix: `(?:(?<![#\d])([#\d]++)\s+)?(?<!#)(#++)\s*/\s*([#\d]+)` - The lookbehinds stop a match from starting inside a run. A match that starts after a `#`, or a whole-part group that starts after a `#` or digit, can always be extended one character to the left. So `find()` would already have returned that earlier match, and the leftmost match is unchanged. - The possessive quantifiers only drop backtracking that can't succeed, because what follows each run (`\s` or `/`) can't be a `#` or digit. I compared the old and new patterns on all 1.4M strings up to length 10 built from `[#1 /]` (the characters left after `fractionStripper`). Start, end and all three groups are identical. The new pattern takes a few ms on inputs of 20,000 to 40,000 characters. `testFractionWithLongRun` times out after 10 s before the change and passes after. `TestDataFormatter`, `TestHSSFDataFormatter`, `TestFractionFormat`, `org.apache.poi.ss.format.*`, `TestCellFormatPart`, `TestDataFormatterAgainstExcel` and `TestXSSFDataFormat` pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
