Skip to content

Commit 5bc9253

Browse files
do not split surrogates in ParameterInstance.ToDisplayText() (#1705)
1 parent 601a1ae commit 5bc9253

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

src/BenchmarkDotNet/Parameters/ParameterInstance.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,33 @@ private static string Trim(string value, int maxDisplayTextInnerLength)
7171

7272
var postfix = $" [{value.Length}]";
7373
const string dots = "(...)";
74-
int take = (maxDisplayTextInnerLength - postfix.Length - dots.Length) / 2;
7574

76-
return value.Substring(0, take) + dots + value.Substring(value.Length - take, take) + postfix;
75+
var takeFromStart = (maxDisplayTextInnerLength - postfix.Length - dots.Length) / 2;
76+
var takeFromEnd = takeFromStart;
77+
78+
if (IsFirstCharInSurrogatePair(value[takeFromStart-1]))
79+
{
80+
takeFromStart = Math.Max(0, takeFromStart - 1);
81+
}
82+
83+
if (IsSecondCharInSurrogatePair(value[value.Length - takeFromEnd]))
84+
{
85+
takeFromEnd = Math.Max(0, takeFromEnd - 1);
86+
}
87+
88+
var result = value.Substring(0, takeFromStart) + dots + value.Substring(value.Length - takeFromEnd, takeFromEnd) + postfix;
89+
90+
return result;
91+
}
92+
93+
private static bool IsFirstCharInSurrogatePair(char c)
94+
{
95+
return BitConverter.IsLittleEndian ? char.IsHighSurrogate(c) : char.IsLowSurrogate(c);
96+
}
97+
98+
private static bool IsSecondCharInSurrogatePair(char c)
99+
{
100+
return BitConverter.IsLittleEndian ? char.IsLowSurrogate(c) : char.IsHighSurrogate(c);
77101
}
78102
}
79103
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using BenchmarkDotNet.Attributes;
7+
using Xunit;
8+
9+
namespace BenchmarkDotNet.IntegrationTests
10+
{
11+
public class ParamSourceTests: BenchmarkTestExecutor
12+
{
13+
[Fact]
14+
public void ParamSourceCanHandleStringWithSurrogates()
15+
{
16+
CanExecute<ParamSourceIsStringWithSurrogates>(CreateSimpleConfig());
17+
}
18+
19+
public class ParamSourceIsStringWithSurrogates
20+
{
21+
public IEnumerable<string> StringValues
22+
{
23+
get
24+
{
25+
yield return "a" + string.Join("", Enumerable.Repeat("😀", 40)) + "a";
26+
yield return "a" + string.Join("", Enumerable.Repeat("😀", 40));
27+
yield return string.Join("", Enumerable.Repeat("😀", 40)) + "a";
28+
yield return string.Join("", Enumerable.Repeat("😀", 40));
29+
}
30+
}
31+
32+
[ParamsSource(nameof(StringValues))]
33+
public string _ { get; set; }
34+
35+
[Benchmark]
36+
public void Method() { }
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)