@@ -9,44 +9,72 @@ namespace Microsoft.AspNetCore.WebUtilities
9
9
{
10
10
public struct KeyValueAccumulator
11
11
{
12
- private Dictionary < string , List < string > > _accumulator ;
12
+ private Dictionary < string , StringValues > _accumulator ;
13
+ private Dictionary < string , List < string > > _expandingAccumulator ;
13
14
14
15
public void Append ( string key , string value )
15
16
{
16
17
if ( _accumulator == null )
17
18
{
18
- _accumulator = new Dictionary < string , List < string > > ( StringComparer . OrdinalIgnoreCase ) ;
19
+ _accumulator = new Dictionary < string , StringValues > ( StringComparer . OrdinalIgnoreCase ) ;
19
20
}
20
- List < string > values ;
21
+
22
+ StringValues values ;
21
23
if ( _accumulator . TryGetValue ( key , out values ) )
22
24
{
23
- values . Add ( value ) ;
25
+ if ( values . Count == 0 )
26
+ {
27
+ // Marker entry for this key to indicate entry already in expanding list dictionary
28
+ _expandingAccumulator [ key ] . Add ( value ) ;
29
+ }
30
+ else if ( values . Count == 1 )
31
+ {
32
+ // Second value for this key
33
+ _accumulator [ key ] = new string [ ] { values [ 0 ] , value } ;
34
+ }
35
+ else
36
+ {
37
+ // Third value for this key
38
+ // Add zero count entry and move to data to expanding list dictionary
39
+ _accumulator [ key ] = default ( StringValues ) ;
40
+
41
+ if ( _expandingAccumulator == null )
42
+ {
43
+ _expandingAccumulator = new Dictionary < string , List < string > > ( StringComparer . OrdinalIgnoreCase ) ;
44
+ }
45
+
46
+ // Already 3 entries so use starting allocated as 8; then use List's expansion mechanism for more
47
+ var list = new List < string > ( 8 ) ;
48
+ var array = values . ToArray ( ) ;
49
+
50
+ list . Add ( array [ 0 ] ) ;
51
+ list . Add ( array [ 1 ] ) ;
52
+ list . Add ( value ) ;
53
+
54
+ _expandingAccumulator [ key ] = list ;
55
+ }
24
56
}
25
57
else
26
58
{
27
- values = new List < string > ( 1 ) ;
28
- values . Add ( value ) ;
29
- _accumulator [ key ] = values ;
59
+ // First value for this key
60
+ _accumulator [ key ] = new StringValues ( value ) ;
30
61
}
31
62
}
32
63
33
64
public bool HasValues => _accumulator != null ;
34
65
35
66
public Dictionary < string , StringValues > GetResults ( )
36
67
{
37
- if ( _accumulator == null )
38
- {
39
- return new Dictionary < string , StringValues > ( StringComparer . OrdinalIgnoreCase ) ;
40
- }
41
-
42
- var results = new Dictionary < string , StringValues > ( _accumulator . Count , StringComparer . OrdinalIgnoreCase ) ;
43
-
44
- foreach ( var kv in _accumulator )
68
+ if ( _expandingAccumulator != null )
45
69
{
46
- results . Add ( kv . Key , kv . Value . Count == 1 ? new StringValues ( kv . Value [ 0 ] ) : new StringValues ( kv . Value . ToArray ( ) ) ) ;
70
+ // Coalesce count 3+ multi-value entries into _accumulator dictionary
71
+ foreach ( var entry in _expandingAccumulator )
72
+ {
73
+ _accumulator [ entry . Key ] = new StringValues ( entry . Value . ToArray ( ) ) ;
74
+ }
47
75
}
48
76
49
- return results ;
77
+ return _accumulator ?? new Dictionary < string , StringValues > ( 0 , StringComparer . OrdinalIgnoreCase ) ;
50
78
}
51
79
}
52
80
}
0 commit comments