11// Copyright (c) Six Labors.
22// Licensed under the Six Labors Split License.
33
4+ using System . Diagnostics . CodeAnalysis ;
45using System . Runtime . CompilerServices ;
56
67namespace SixLabors . ImageSharp . Drawing . Shapes . PolygonClipper ;
@@ -13,7 +14,6 @@ internal struct ArrayBuilder<T>
1314 where T : struct
1415{
1516 private const int DefaultCapacity = 4 ;
16- private const int MaxCoreClrArrayLength = 0x7FeFFFFF ;
1717
1818 // Starts out null, initialized on first Add.
1919 private T [ ] ? data ;
@@ -41,17 +41,14 @@ public int Length
4141
4242 set
4343 {
44- if ( value != this . size )
44+ if ( value > 0 )
4545 {
46- if ( value > 0 )
47- {
48- this . EnsureCapacity ( value ) ;
49- this . size = value ;
50- }
51- else
52- {
53- this . size = 0 ;
54- }
46+ this . EnsureCapacity ( value ) ;
47+ this . size = value ;
48+ }
49+ else
50+ {
51+ this . size = 0 ;
5552 }
5653 }
5754 }
@@ -81,10 +78,27 @@ public readonly ref T this[int index]
8178 public void Add ( T item )
8279 {
8380 int position = this . size ;
81+ T [ ] ? array = this . data ;
8482
85- // Expand the array.
86- this . Length ++ ;
87- this . data ! [ position ] = item ;
83+ if ( array != null && ( uint ) position < ( uint ) array . Length )
84+ {
85+ this . size = position + 1 ;
86+ array [ position ] = item ;
87+ }
88+ else
89+ {
90+ this . AddWithResize ( item ) ;
91+ }
92+ }
93+
94+ // Non-inline from Add to improve its code quality as uncommon path
95+ [ MethodImpl ( MethodImplOptions . NoInlining ) ]
96+ private void AddWithResize ( T item )
97+ {
98+ int size = this . size ;
99+ this . Grow ( size + 1 ) ;
100+ this . size = size + 1 ;
101+ this . data [ size ] = item ;
88102 }
89103
90104 /// <summary>
@@ -110,26 +124,33 @@ private void EnsureCapacity(int min)
110124 int length = this . data ? . Length ?? 0 ;
111125 if ( length < min )
112126 {
113- // Same expansion algorithm as List<T>.
114- uint newCapacity = length == 0 ? DefaultCapacity : ( uint ) length * 2u ;
115- if ( newCapacity > MaxCoreClrArrayLength )
116- {
117- newCapacity = MaxCoreClrArrayLength ;
118- }
127+ this . Grow ( min ) ;
128+ }
129+ }
119130
120- if ( newCapacity < min )
121- {
122- newCapacity = ( uint ) min ;
123- }
131+ [ MemberNotNull ( nameof ( this . data ) ) ]
132+ private void Grow ( int capacity )
133+ {
134+ // Same expansion algorithm as List<T>.
135+ int length = this . data ? . Length ?? 0 ;
136+ int newCapacity = length == 0 ? DefaultCapacity : length * 2 ;
137+ if ( ( uint ) newCapacity > Array . MaxLength )
138+ {
139+ newCapacity = Array . MaxLength ;
140+ }
124141
125- T [ ] array = new T [ newCapacity ] ;
142+ if ( newCapacity < capacity )
143+ {
144+ newCapacity = capacity ;
145+ }
126146
127- if ( this . size > 0 )
128- {
129- Array . Copy ( this . data ! , array , this . size ) ;
130- }
147+ T [ ] array = new T [ newCapacity ] ;
131148
132- this . data = array ;
149+ if ( this . size > 0 )
150+ {
151+ Array . Copy ( this . data ! , array , this . size ) ;
133152 }
153+
154+ this . data = array ;
134155 }
135156}
0 commit comments