diff --git a/changelog/std-algorithm-iteration-joiner.dd b/changelog/std-algorithm-iteration-joiner.dd new file mode 100644 index 000000000..0ae4b2796 --- /dev/null +++ b/changelog/std-algorithm-iteration-joiner.dd @@ -0,0 +1,19 @@ +The performance of `std.algorithm.iteration.joiner` has been improved + +$(H4 DMD) + +$(CONSOLE +> dmd -O -inline -release ./joiner.d && ./joiner +before.joiner = 57 secs, 834 ms, 289 μs, and 3 hnsecs +new.joiner = 44 secs, 936 ms, 706 μs, and 5 hnsecs +) + +$(H4 LDC) + +$(CONSOLE +> ldmd -O3 -release -inline joiner.d && ./joiner +before.joiner = 5 secs, 180 ms, 193 μs, and 7 hnsecs +new.joiner = 3 secs, 168 ms, 560 μs, and 6 hnsecs +) + +The benchmark code can be found $(LINK2 https://gist.github.com/wilzbach/ffd5d20639766a831fd4b1962572897a, here). diff --git a/std/uni.d b/std/uni.d index 0f9962c58..e52920236 100644 --- a/std/uni.d +++ b/std/uni.d @@ -9003,16 +9003,18 @@ if (isSomeString!S || (isRandomAccessRange!S && hasLength!S && hasSlicing!S && i { import std.array : appender, array; import std.ascii : isASCII; - import std.utf : byDchar; + import std.utf : byDchar, codeLength; + + alias C = ElementEncodingType!S; auto r = s.byDchar; - for (size_t i; !r.empty; ++i, r.popFront()) + for (size_t i; !r.empty; i += r.front.codeLength!C , r.popFront()) { auto cOuter = r.front; ushort idx = indexFn(cOuter); if (idx == ushort.max) continue; - auto result = appender!(ElementEncodingType!S[])(); + auto result = appender!(C[])(); result.reserve(s.length); result.put(s[0 .. i]); foreach (dchar c; s[i .. $].byDchar) @@ -9062,6 +9064,11 @@ if (isSomeString!S || (isRandomAccessRange!S && hasLength!S && hasSlicing!S && i assert(s == "abcdefghij"); } +@safe unittest // 18993 +{ + static assert(`몬스터/A`.toLower.length == `몬스터/a`.toLower.length); +} + // generic toUpper/toLower on whole range, returns range private auto toCaser(alias indexFn, uint maxIdx, alias tableFn, alias asciiConvert, Range)(Range str)