mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
refactor(wrapAnsi): use WTF::find for character searches (#26200)
## Summary This PR addresses the review feedback from #26061 ([comment](https://github.com/oven-sh/bun/pull/26061#discussion_r2697257836)) requesting the use of `WTF::find` for newline searches in `wrapAnsi.cpp`. ## Changes ### 1. CRLF Normalization (lines 628-639) Replaced manual loop with `WTF::findNextNewline` which provides SIMD-optimized detection for `\r`, `\n`, and `\r\n` sequences. **Before:** ```cpp for (size_t i = 0; i < input.size(); ++i) { if (i + 1 < input.size() && input[i] == '\r' && input[i + 1] == '\n') { normalized.append(static_cast<Char>('\n')); i++; } else { normalized.append(input[i]); } } ``` **After:** ```cpp size_t pos = 0; while (pos < input.size()) { auto newline = WTF::findNextNewline(input, pos); if (newline.position == WTF::notFound) { normalized.append(std::span { input.data() + pos, input.size() - pos }); break; } if (newline.position > pos) normalized.append(std::span { input.data() + pos, newline.position - pos }); normalized.append(static_cast<Char>('\n')); pos = newline.position + newline.length; } ``` ### 2. Word Length Calculation (lines 524-533) Replaced manual loop with `WTF::find` for space character detection. **Before:** ```cpp for (const Char* it = lineStart; it <= lineEnd; ++it) { if (it == lineEnd || *it == ' ') { // word boundary logic } } ``` **After:** ```cpp auto lineSpan = std::span<const Char>(lineStart, lineEnd); size_t wordStartIdx = 0; while (wordStartIdx <= lineSpan.size()) { size_t spacePos = WTF::find(lineSpan, static_cast<Char>(' '), wordStartIdx); // word boundary logic using spacePos } ``` ## Benchmark Results Tested on Apple M4 Max. No performance regression observed - most benchmarks show slight improvements. | Benchmark | Before | After | Change | |-----------|--------|-------|--------| | Short text (45 chars) | 613 ns | 583 ns | -4.9% | | Medium text (810 chars) | 10.85 µs | 10.31 µs | -5.0% | | Long text (8100 chars) | 684 µs | 102 µs | -85% * | | Colored short | 1.26 µs | 806 ns | -36% | | Colored medium | 19.24 µs | 13.80 µs | -28% | | Japanese (full-width) | 7.74 µs | 7.43 µs | -4.0% | | Emoji text | 9.35 µs | 9.27 µs | -0.9% | | Hyperlink (OSC 8) | 5.73 µs | 5.58 µs | -2.6% | \* Large variance in baseline measurement ## Testing - All 35 existing tests pass - Manual verification of CRLF normalization and word wrapping edge cases --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -518,25 +518,32 @@ static void processLine(const Char* lineStart, const Char* lineEnd, size_t colum
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate word lengths
|
||||
// Calculate word lengths using WTF::find for space detection
|
||||
Vector<size_t> wordLengths;
|
||||
const Char* wordStart = lineStart;
|
||||
for (const Char* it = lineStart; it <= lineEnd; ++it) {
|
||||
if (it == lineEnd || *it == ' ') {
|
||||
if (wordStart < it) {
|
||||
wordLengths.append(stringWidth(wordStart, it, options.ambiguousIsNarrow));
|
||||
} else {
|
||||
wordLengths.append(0);
|
||||
}
|
||||
wordStart = it + 1;
|
||||
auto lineSpan = std::span<const Char>(lineStart, lineEnd);
|
||||
size_t wordStartIdx = 0;
|
||||
while (wordStartIdx <= lineSpan.size()) {
|
||||
size_t spacePos = WTF::find(lineSpan, static_cast<Char>(' '), wordStartIdx);
|
||||
size_t wordEndIdx = (spacePos == WTF::notFound) ? lineSpan.size() : spacePos;
|
||||
|
||||
if (wordStartIdx < wordEndIdx) {
|
||||
wordLengths.append(stringWidth(lineSpan.data() + wordStartIdx,
|
||||
lineSpan.data() + wordEndIdx,
|
||||
options.ambiguousIsNarrow));
|
||||
} else {
|
||||
wordLengths.append(0);
|
||||
}
|
||||
|
||||
if (spacePos == WTF::notFound)
|
||||
break;
|
||||
wordStartIdx = wordEndIdx + 1;
|
||||
}
|
||||
|
||||
// Start with empty first row
|
||||
rows.append(Row<Char>());
|
||||
|
||||
// Process each word
|
||||
wordStart = lineStart;
|
||||
const Char* wordStart = lineStart;
|
||||
size_t wordIndex = 0;
|
||||
|
||||
for (const Char* it = lineStart; it <= lineEnd; ++it) {
|
||||
@@ -625,17 +632,24 @@ static WTF::String wrapAnsiImpl(std::span<const Char> input, size_t columns, con
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
// Normalize \r\n to \n
|
||||
// Normalize \r\n to \n using WTF::findNextNewline
|
||||
Vector<Char> normalized;
|
||||
normalized.reserveCapacity(input.size());
|
||||
|
||||
for (size_t i = 0; i < input.size(); ++i) {
|
||||
if (i + 1 < input.size() && input[i] == '\r' && input[i + 1] == '\n') {
|
||||
normalized.append(static_cast<Char>('\n'));
|
||||
i++; // Skip next char
|
||||
} else {
|
||||
normalized.append(input[i]);
|
||||
size_t pos = 0;
|
||||
while (pos < input.size()) {
|
||||
auto newline = WTF::findNextNewline(input, pos);
|
||||
if (newline.position == WTF::notFound) {
|
||||
// Append remaining content
|
||||
normalized.append(std::span { input.data() + pos, input.size() - pos });
|
||||
break;
|
||||
}
|
||||
// Append content before newline
|
||||
if (newline.position > pos)
|
||||
normalized.append(std::span { input.data() + pos, newline.position - pos });
|
||||
// Always append \n regardless of original (\r, \n, or \r\n)
|
||||
normalized.append(static_cast<Char>('\n'));
|
||||
pos = newline.position + newline.length;
|
||||
}
|
||||
|
||||
// Process each line separately
|
||||
|
||||
Reference in New Issue
Block a user