@@ -29,13 +29,24 @@ debug
2929
3030extern (C++ ) struct Array (T)
3131{
32- size_t length;
32+ size_t length () const { return data.used; }
33+ void length (size_t len) { data.used = cast (uint )len; }
3334
3435private :
35- T[] data;
3636 enum SMALLARRAYCAP = 1 ;
37- T[SMALLARRAYCAP ] smallarray; // inline storage for small arrays
38-
37+ struct A
38+ {
39+ uint allocated = SMALLARRAYCAP ;
40+ uint used;
41+ union
42+ {
43+ T[SMALLARRAYCAP ] smallarray; // inline storage for small arrays
44+ T* _ptr;
45+ }
46+ extern (D ) inout (T)* ptr() inout { return allocated <= SMALLARRAYCAP ? smallarray.ptr : _ptr; }
47+ }
48+ A data;
49+
3950public :
4051 /* ******************
4152 * Params:
@@ -44,7 +55,7 @@ public:
4455 this (size_t dim) pure nothrow scope
4556 {
4657 reserve (dim);
47- this .length = dim;
58+ this .data.used = cast ( uint ) dim;
4859 }
4960
5061 @disable this (this );
@@ -54,12 +65,13 @@ public:
5465 debug (stomp)
5566 {
5667 if (data.ptr)
57- memset(data.ptr, 0xFF , data.length * T.sizeof);
68+ memset(data.ptr, 0xFF , data.allocated * T.sizeof);
5869 }
59- if (data.ptr && data.ptr != &smallarray[ 0 ] )
70+ if (data.allocated > SMALLARRAYCAP )
6071 mem.xfree(data.ptr);
6172 }
6273
74+ @trusted :
6375 // this is using a template constraint because of ambiguity with this(size_t) when T is
6476 // int, and c++ header generation doesn't accept wrapping this in static if
6577 extern (D ) this ()(T[] elems ... ) pure nothrow if (is (T == struct ) || is (T == class ))
@@ -94,7 +106,7 @@ public:
94106 }
95107 else
96108 {
97- buf[u] = toStringFunc(a.data[u]);
109+ buf[u] = toStringFunc(a.data.ptr [u]);
98110 }
99111
100112 len += buf[u].length + seplen;
@@ -144,7 +156,7 @@ public:
144156 ref Array push (T ptr) return pure nothrow
145157 {
146158 reserve (1 );
147- data[length ++ ] = ptr;
159+ data.ptr[data.used ++ ] = ptr;
148160 return this ;
149161 }
150162
@@ -164,31 +176,32 @@ public:
164176
165177 void reserve (size_t nentries) pure nothrow
166178 {
167- // printf("Array::reserve: length = %d, data.length = %d, nentries = %d\n", cast(int)length, cast(int)data.length , cast(int)nentries);
179+ // printf("Array::reserve: length = %d, data.allocated = %d, nentries = %d\n", cast(int)length, cast(int)data.allocated , cast(int)nentries);
168180
169181 // Cold path
170182 void enlarge (size_t nentries)
171183 {
184+ static if (uint .max < size_t .max)
185+ assert (data.used + nentries <= uint .max);
186+
172187 pragma (inline, false ); // never inline cold path
173- if (data.length == 0 )
188+ if (data.allocated == 0 )
174189 {
175190 // Not properly initialized, someone memset it to zero
176- if (nentries <= SMALLARRAYCAP )
177- {
178- data = SMALLARRAYCAP ? smallarray[] : null ;
179- }
180- else
191+ if (nentries > SMALLARRAYCAP )
181192 {
182193 auto p = cast (T* )mem.xmalloc(nentries * T.sizeof);
183- data = p[ 0 .. nentries] ;
194+ data._ptr = p;
184195 }
196+ data.allocated = cast (uint )nentries;
185197 }
186- else if (data.length = = SMALLARRAYCAP )
198+ else if (data.allocated < = SMALLARRAYCAP )
187199 {
188200 const allocdim = length + nentries;
189201 auto p = cast (T* )mem.xmalloc(allocdim * T.sizeof);
190- memcpy(p, smallarray.ptr, length * T.sizeof);
191- data = p[0 .. allocdim];
202+ memcpy(p, data.smallarray.ptr, length * T.sizeof);
203+ data._ptr = p;
204+ data.allocated = cast (uint )allocdim;
192205 }
193206 else
194207 {
@@ -203,23 +216,23 @@ public:
203216 // always move using allocate-copy-stomp-free
204217 auto p = cast (T* )mem.xmalloc(allocdim * T.sizeof);
205218 memcpy(p, data.ptr, length * T.sizeof);
206- memset(data.ptr, 0xFF , data.length * T.sizeof);
219+ memset(data.ptr, 0xFF , data.allocated * T.sizeof);
207220 mem.xfree(data.ptr);
208- data = p[0 .. allocdim];
209221 }
210222 else
211223 {
212224 auto p = cast (T* )mem.xrealloc(data.ptr, allocdim * T.sizeof);
213- data = p[0 .. allocdim];
214225 }
226+ data._ptr = p;
227+ data.allocated = cast (uint )allocdim;
215228 }
216229
217230 debug (stomp)
218231 {
219232 if (data.ptr)
220233 {
221- if (length < data.length )
222- memset(data.ptr + length, 0xFF , (data.length - length) * T.sizeof);
234+ if (length < data.allocated )
235+ memset(data.ptr + length, 0xFF , (data.allocated - length) * T.sizeof);
223236 }
224237 }
225238 else
@@ -228,22 +241,22 @@ public:
228241 {
229242 if (data.ptr)
230243 {
231- if (length < data.length )
232- memset(data.ptr + length, 0xFF , (data.length - length) * T.sizeof);
244+ if (length < data.allocated )
245+ memset(data.ptr + length, 0xFF , (data.allocated - length) * T.sizeof);
233246 }
234247 }
235248 }
236249 }
237250
238- if (data.length - length < nentries) // false means hot path
251+ if (data.allocated - length < nentries) // false means hot path
239252 enlarge(nentries);
240253 }
241254
242255 void remove (size_t i) pure nothrow @nogc
243256 {
244257 if (length - i - 1 )
245258 memmove(data.ptr + i, data.ptr + i + 1 , (length - i - 1 ) * T.sizeof);
246- length -- ;
259+ data.used -- ;
247260 debug (stomp) memset(data.ptr + length, 0xFF , T.sizeof);
248261 }
249262
@@ -256,7 +269,7 @@ public:
256269 if (length != index)
257270 memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof);
258271 memcpy(data.ptr + index, a.data.ptr, d * T.sizeof);
259- length += d;
272+ data.used += d;
260273 }
261274 }
262275
@@ -267,15 +280,15 @@ public:
267280 if (length != index)
268281 memmove(data.ptr + index + d, data.ptr + index, (length - index) * T.sizeof);
269282 memcpy(data.ptr + index, a.ptr, d * T.sizeof);
270- length += d;
283+ data.used += d;
271284 }
272285
273286 void insert (size_t index, T ptr) pure nothrow
274287 {
275288 reserve (1 );
276289 memmove(data.ptr + index + 1 , data.ptr + index, (length - index) * T.sizeof);
277- data[index] = ptr;
278- length ++ ;
290+ data.ptr [index] = ptr;
291+ data.used ++ ;
279292 }
280293
281294 // / Insert 'count' copies of 'value' at 'index' position
@@ -286,8 +299,8 @@ public:
286299 reserve (count);
287300 if (length != index)
288301 memmove(data.ptr + index + count, data.ptr + index, (length - index) * T.sizeof);
289- data[index .. index + count] = value;
290- length += count;
302+ data.ptr [index .. index + count] = value;
303+ data.used += count;
291304 }
292305
293306 void setDim (size_t newdim) pure nothrow
@@ -296,13 +309,13 @@ public:
296309 {
297310 reserve (newdim - length);
298311 }
299- length = newdim;
312+ data.used = cast ( uint ) newdim;
300313 }
301314
302315 size_t find (T ptr) const nothrow pure
303316 {
304317 foreach (i; 0 .. length)
305- if (data[i] is ptr)
318+ if (data.ptr [i] is ptr)
306319 return i;
307320 return size_t .max;
308321 }
@@ -338,13 +351,13 @@ public:
338351 {
339352 reserve (1 );
340353 memmove(data.ptr + 1 , data.ptr, length * T.sizeof);
341- data[0 ] = ptr;
342- length ++ ;
354+ data.ptr [0 ] = ptr;
355+ data.used ++ ;
343356 }
344357
345358 void zero () nothrow pure @nogc
346359 {
347- data[0 .. length] = T.init;
360+ data.ptr [0 .. length] = T.init;
348361 }
349362
350363 T pop () nothrow pure @nogc
@@ -357,18 +370,18 @@ public:
357370 return result;
358371 }
359372 else
360- return data[-- length ];
373+ return data.ptr [-- data.used ];
361374 }
362375
363376 extern (D ) inout (T)[] opSlice () inout nothrow pure @nogc
364377 {
365- return data[0 .. length];
378+ return data.ptr [0 .. length];
366379 }
367380
368381 extern (D ) inout (T)[] opSlice (size_t a, size_t b) inout nothrow pure @nogc
369382 {
370383 assert (a <= b && b <= length);
371- return data[a .. b];
384+ return data.ptr [a .. b];
372385 }
373386
374387 /**
0 commit comments