@@ -29,12 +29,17 @@ debug
2929
3030extern (C++ ) struct Array (T)
3131{
32- size_t length;
32+ uint length;
3333
3434private :
35- T[] data;
3635 enum SMALLARRAYCAP = 1 ;
37- T[SMALLARRAYCAP ] smallarray; // inline storage for small arrays
36+ uint allocated = SMALLARRAYCAP ;
37+ union
38+ {
39+ T[SMALLARRAYCAP ] smallarray; // inline storage for small arrays
40+ T* _ptr;
41+ }
42+ extern (D ) inout (T)* data() inout pure nothrow { return allocated <= SMALLARRAYCAP ? smallarray.ptr : _ptr; }
3843
3944public :
4045 /* ******************
@@ -44,7 +49,7 @@ public:
4449 this (size_t dim) pure nothrow scope
4550 {
4651 reserve (dim);
47- this .length = dim;
52+ this .length = cast ( uint ) dim;
4853 }
4954
5055 @disable this (this );
@@ -53,13 +58,14 @@ public:
5358 {
5459 debug (stomp)
5560 {
56- if (data.ptr )
57- memset(data.ptr , 0xFF , data.length * T.sizeof);
61+ if (allocated > SMALLARRAYCAP )
62+ memset(_ptr , 0xFF , allocated * T.sizeof);
5863 }
59- if (data.ptr && data.ptr != &smallarray[ 0 ] )
60- mem.xfree(data.ptr );
64+ if (allocated > SMALLARRAYCAP )
65+ mem.xfree(_ptr );
6166 }
6267
68+ @trusted :
6369 // this is using a template constraint because of ambiguity with this(size_t) when T is
6470 // int, and c++ header generation doesn't accept wrapping this in static if
6571 extern (D ) this ()(T[] elems ... ) pure nothrow if (is (T == struct ) || is (T == class ))
@@ -141,18 +147,18 @@ public:
141147 return toString.ptr;
142148 }
143149
144- ref Array push (T ptr ) return pure nothrow
150+ ref Array push (T p ) return pure nothrow
145151 {
146152 reserve (1 );
147- data[length++ ] = ptr ;
153+ data[length++ ] = p ;
148154 return this ;
149155 }
150156
151157 extern (D ) ref Array pushSlice(T[] a) return pure nothrow
152158 {
153159 const oldLength = length;
154160 setDim(oldLength + a.length);
155- memcpy(data.ptr + oldLength, a.ptr, a.length * T.sizeof);
161+ memcpy(data + oldLength, a.ptr, a.length * T.sizeof);
156162 return this ;
157163 }
158164
@@ -164,87 +170,82 @@ public:
164170
165171 void reserve (size_t nentries) pure nothrow
166172 {
167- // printf("Array::reserve: length = %d, data.length = %d, nentries = %d\n", cast(int)length, cast(int)data.length , cast(int)nentries);
173+ // printf("Array::reserve: length = %d, data.allocated = %d, nentries = %d\n", cast(int)length, cast(int)data.allocated , cast(int)nentries);
168174
169175 // Cold path
170176 void enlarge (size_t nentries)
171177 {
178+ static if (uint .max < size_t .max)
179+ assert (length + nentries <= uint .max);
180+
172181 pragma (inline, false ); // never inline cold path
173- if (data.length == 0 )
182+ if (allocated == 0 )
174183 {
175184 // Not properly initialized, someone memset it to zero
176- if (nentries <= SMALLARRAYCAP )
177- {
178- data = SMALLARRAYCAP ? smallarray[] : null ;
179- }
180- else
185+ if (nentries > SMALLARRAYCAP )
181186 {
182187 auto p = cast (T* )mem.xmalloc(nentries * T.sizeof);
183- data = p[ 0 .. nentries] ;
188+ _ptr = p;
184189 }
190+ allocated = cast (uint )nentries;
185191 }
186- else if (data.length = = SMALLARRAYCAP )
192+ else if (allocated < = SMALLARRAYCAP )
187193 {
188194 const allocdim = length + nentries;
189195 auto p = cast (T* )mem.xmalloc(allocdim * T.sizeof);
190196 memcpy(p, smallarray.ptr, length * T.sizeof);
191- data = p[0 .. allocdim];
197+ _ptr = p;
198+ allocated = cast (uint )allocdim;
192199 }
193200 else
194201 {
195202 /* Increase size by 1.5x to avoid excessive memory fragmentation
196203 */
197204 auto increment = length / 2 ;
198205 if (nentries > increment) // if 1.5 is not enough
199- increment = nentries;
206+ increment = cast ( uint ) nentries;
200207 const allocdim = length + increment;
201208 debug (stomp)
202209 {
203210 // always move using allocate-copy-stomp-free
204211 auto p = cast (T* )mem.xmalloc(allocdim * T.sizeof);
205- memcpy(p, data.ptr, length * T.sizeof);
206- memset(data.ptr, 0xFF , data.length * T.sizeof);
207- mem.xfree(data.ptr);
208- data = p[0 .. allocdim];
212+ memcpy(p, _ptr, length * T.sizeof);
213+ memset(_ptr, 0xFF , allocated * T.sizeof);
214+ mem.xfree(_ptr);
209215 }
210216 else
211217 {
212- auto p = cast (T* )mem.xrealloc(data.ptr, allocdim * T.sizeof);
213- data = p[0 .. allocdim];
218+ auto p = cast (T* )mem.xrealloc(_ptr, allocdim * T.sizeof);
214219 }
220+ _ptr = p;
221+ allocated = cast (uint )allocdim;
215222 }
216223
217224 debug (stomp)
218225 {
219- if (data.ptr)
220- {
221- if (length < data.length)
222- memset(data.ptr + length, 0xFF , (data.length - length) * T.sizeof);
223- }
226+ if (length < allocated)
227+ memset(data + length, 0xFF , (allocated - length) * T.sizeof);
224228 }
225229 else
226230 {
227231 if (mem.isGCEnabled)
228232 {
229- if (data.ptr)
230- {
231- if (length < data.length)
232- memset(data.ptr + length, 0xFF , (data.length - length) * T.sizeof);
233- }
233+ if (length < allocated)
234+ memset(data + length, 0xFF , (allocated - length) * T.sizeof);
234235 }
235236 }
236237 }
237238
238- if (data.length - length < nentries) // false means hot path
239+ if (allocated - length < nentries) // false means hot path
239240 enlarge(nentries);
240241 }
241242
242243 void remove (size_t i) pure nothrow @nogc
243244 {
244245 if (length - i - 1 )
245- memmove(data.ptr + i, data.ptr + i + 1 , (length - i - 1 ) * T.sizeof);
246+ memmove(data + i, data + i + 1 , (length - i - 1 ) * T.sizeof);
246247 length-- ;
247- debug (stomp) memset(data.ptr + length, 0xFF , T.sizeof);
248+ debug (stomp) memset(data + length, 0xFF , T.sizeof);
248249 }
249250
250251 void insert (size_t index, typeof (this )* a) pure nothrow
@@ -254,8 +255,8 @@ public:
254255 size_t d = a.length;
255256 reserve (d);
256257 if (length != index)
257- memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof);
258- memcpy(data.ptr + index, a.data.ptr , d * T.sizeof);
258+ memmove(data + index + d, data + index, (length - index) * T.sizeof);
259+ memcpy(data + index, a.data, d * T.sizeof);
259260 length += d;
260261 }
261262 }
@@ -265,16 +266,16 @@ public:
265266 size_t d = a.length;
266267 reserve (d);
267268 if (length != index)
268- memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof);
269- memcpy(data.ptr + index, a.ptr, d * T.sizeof);
269+ memmove(data + index + d, data + index, (length - index) * T.sizeof);
270+ memcpy(data + index, a.ptr, d * T.sizeof);
270271 length += d;
271272 }
272273
273- void insert (size_t index, T ptr ) pure nothrow
274+ void insert (size_t index, T p ) pure nothrow
274275 {
275276 reserve (1 );
276- memmove(data.ptr + index + 1 , data.ptr + index, (length - index) * T.sizeof);
277- data[index] = ptr ;
277+ memmove(data + index + 1 , data + index, (length - index) * T.sizeof);
278+ data[index] = p ;
278279 length++ ;
279280 }
280281
@@ -285,7 +286,7 @@ public:
285286 return ;
286287 reserve (count);
287288 if (length != index)
288- memmove(data.ptr + index + count, data.ptr + index, (length - index) * T.sizeof);
289+ memmove(data + index + count, data + index, (length - index) * T.sizeof);
289290 data[index .. index + count] = value;
290291 length += count;
291292 }
@@ -296,13 +297,13 @@ public:
296297 {
297298 reserve (newdim - length);
298299 }
299- length = newdim;
300+ length = cast ( uint ) newdim;
300301 }
301302
302303 size_t find (T ptr) const nothrow pure
303304 {
304305 foreach (i; 0 .. length)
305- if (data [i] is ptr)
306+ if (this [i] is ptr)
306307 return i;
307308 return size_t .max;
308309 }
@@ -314,30 +315,27 @@ public:
314315
315316 ref inout (T) opIndex (size_t i) inout nothrow pure
316317 {
317- debug
318- // This is called so often the array bounds become expensive
319- return data[i];
320- else
321- return data.ptr[i];
318+ debug assert (i < length);
319+ return allocated <= SMALLARRAYCAP ? smallarray.ptr[i] : _ptr[i];
322320 }
323321
324322 inout (T)* tdata () inout pure nothrow @nogc @trusted
325323 {
326- return data.ptr ;
324+ return data;
327325 }
328326
329327 Array! T* copy () const pure nothrow
330328 {
331329 auto a = new Array! T();
332330 a.setDim(length);
333- memcpy(a.data.ptr , data.ptr , length * T.sizeof);
331+ memcpy(a.data, data, length * T.sizeof);
334332 return a;
335333 }
336334
337335 void shift (T ptr) pure nothrow
338336 {
339337 reserve (1 );
340- memmove(data.ptr + 1 , data.ptr , length * T.sizeof);
338+ memmove(data + 1 , data, length * T.sizeof);
341339 data[0 ] = ptr;
342340 length++ ;
343341 }
@@ -390,7 +388,7 @@ public:
390388 {
391389 if (this .length < 2 )
392390 return this ;
393- qsort(this .data.ptr , this .length, T.sizeof, &arraySortWrapper! (T, pred));
391+ qsort(this .data, this .length, T.sizeof, &arraySortWrapper! (T, pred));
394392 return this ;
395393 }
396394
0 commit comments