@@ -16,36 +16,56 @@ internal JsonSeparatorNamingPolicy(bool lowercase, char separator) =>
16
16
17
17
public override string ConvertName ( string name )
18
18
{
19
- int bufferLength = name . Length * 2 ;
20
- char [ ] ? buffer = bufferLength > 512
19
+ // Rented buffer 20% longer that the input.
20
+ int bufferLength = ( 12 * name . Length ) / 10 ;
21
+ char [ ] ? buffer = bufferLength > JsonConstants . StackallocCharThreshold
21
22
? ArrayPool < char > . Shared . Rent ( bufferLength )
22
23
: null ;
23
24
24
25
int resultLength = 0 ;
25
26
Span < char > result = buffer is null
26
- ? stackalloc char [ 512 ]
27
+ ? stackalloc char [ JsonConstants . StackallocCharThreshold ]
27
28
: buffer ;
28
29
29
- void WriteWord ( ref Span < char > result , ReadOnlySpan < char > word )
30
+ void ExpandBuffer ( ref Span < char > result )
31
+ {
32
+ var bufferNew = ArrayPool < char > . Shared . Rent ( bufferLength *= 2 ) ;
33
+
34
+ result . CopyTo ( bufferNew ) ;
35
+
36
+ if ( buffer is not null )
37
+ {
38
+ ArrayPool < char > . Shared . Return ( buffer , clearArray : true ) ;
39
+ }
40
+
41
+ buffer = bufferNew ;
42
+ result = buffer ;
43
+ }
44
+
45
+ void WriteWord ( ReadOnlySpan < char > word , ref Span < char > result )
30
46
{
31
47
if ( word . IsEmpty )
48
+ {
32
49
return ;
50
+ }
33
51
34
- int required = result . IsEmpty
35
- ? word . Length
36
- : word . Length + 1 ;
52
+ Span < char > destination = result . Slice ( resultLength != 0
53
+ ? resultLength + 1
54
+ : resultLength ) ;
37
55
38
- if ( required >= result . Length )
56
+ int written ;
57
+ while ( true )
39
58
{
40
- int bufferLength = result . Length * 2 ;
41
- char [ ] bufferNew = ArrayPool < char > . Shared . Rent ( bufferLength ) ;
42
-
43
- result . CopyTo ( bufferNew ) ;
59
+ written = _lowercase
60
+ ? word . ToLowerInvariant ( destination )
61
+ : word . ToUpperInvariant ( destination ) ;
44
62
45
- if ( buffer is not null )
46
- ArrayPool < char > . Shared . Return ( buffer ) ;
63
+ if ( written > 0 )
64
+ {
65
+ break ;
66
+ }
47
67
48
- buffer = bufferNew ;
68
+ ExpandBuffer ( ref result ) ;
49
69
}
50
70
51
71
if ( resultLength != 0 )
@@ -54,18 +74,7 @@ void WriteWord(ref Span<char> result, ReadOnlySpan<char> word)
54
74
resultLength += 1 ;
55
75
}
56
76
57
- Span < char > destination = result . Slice ( resultLength ) ;
58
-
59
- if ( _lowercase )
60
- {
61
- word . ToLowerInvariant ( destination ) ;
62
- }
63
- else
64
- {
65
- word . ToUpperInvariant ( destination ) ;
66
- }
67
-
68
- resultLength += word . Length ;
77
+ resultLength += written ;
69
78
}
70
79
71
80
int first = 0 ;
@@ -81,7 +90,7 @@ void WriteWord(ref Span<char> result, ReadOnlySpan<char> word)
81
90
currentCategoryUnicode >= UnicodeCategory . ConnectorPunctuation &&
82
91
currentCategoryUnicode <= UnicodeCategory . OtherPunctuation )
83
92
{
84
- WriteWord ( ref result , chars . Slice ( first , index - first ) ) ;
93
+ WriteWord ( chars . Slice ( first , index - first ) , ref result ) ;
85
94
86
95
previousCategory = CharCategory . Boundary ;
87
96
first = index + 1 ;
@@ -102,7 +111,7 @@ void WriteWord(ref Span<char> result, ReadOnlySpan<char> word)
102
111
if ( currentCategory == CharCategory . Lowercase && char . IsUpper ( next ) ||
103
112
next == '_' )
104
113
{
105
- WriteWord ( ref result , chars . Slice ( first , index - first + 1 ) ) ;
114
+ WriteWord ( chars . Slice ( first , index - first + 1 ) , ref result ) ;
106
115
107
116
previousCategory = CharCategory . Boundary ;
108
117
first = index + 1 ;
@@ -114,7 +123,7 @@ void WriteWord(ref Span<char> result, ReadOnlySpan<char> word)
114
123
currentCategoryUnicode == UnicodeCategory . UppercaseLetter &&
115
124
char . IsLower ( next ) )
116
125
{
117
- WriteWord ( ref result , chars . Slice ( first , index - first ) ) ;
126
+ WriteWord ( chars . Slice ( first , index - first ) , ref result ) ;
118
127
119
128
previousCategory = CharCategory . Boundary ;
120
129
first = index ;
@@ -126,14 +135,14 @@ void WriteWord(ref Span<char> result, ReadOnlySpan<char> word)
126
135
}
127
136
}
128
137
129
- WriteWord ( ref result , chars . Slice ( first ) ) ;
138
+ WriteWord ( chars . Slice ( first ) , ref result ) ;
130
139
131
- name = result
132
- . Slice ( 0 , resultLength )
133
- . ToString ( ) ;
140
+ name = result . Slice ( 0 , resultLength ) . ToString ( ) ;
134
141
135
142
if ( buffer is not null )
136
- ArrayPool < char > . Shared . Return ( buffer ) ;
143
+ {
144
+ ArrayPool < char > . Shared . Return ( buffer , clearArray : true ) ;
145
+ }
137
146
138
147
return name ;
139
148
}
0 commit comments