Skip to content

Commit c261fa1

Browse files
authored
Merge pull request #110 from CyberShadow/pull-20180510-052258
dynamicarray fixes + resize method
2 parents d045889 + 9933171 commit c261fa1

File tree

3 files changed

+106
-28
lines changed

3 files changed

+106
-28
lines changed

src/containers/dynamicarray.d

Lines changed: 102 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
148148
else
149149
(() @trusted => memcpy(arr.ptr + l, init.ptr, T.sizeof))();
150150
}
151-
arr[l++] = value;
151+
emplace(arr[l++], value);
152152
}
153153

154154
/// ditto
@@ -189,29 +189,8 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
189189
import std.traits: hasElaborateAssign, hasElaborateDestructor;
190190
static if (is(T == struct) && (hasElaborateAssign!T || hasElaborateDestructor!T))
191191
{
192-
// If a destructor is run before blit or assignment involves
193-
// more than just a blit, ensure that arr[l] is in a valid
194-
// state before assigning to it.
195-
import core.stdc.string : memcpy, memset;
196-
const init = typeid(T).initializer();
197-
if (init.ptr is null) // null pointer means initialize to 0s
198-
{
199-
foreach (ref value; rhs)
200-
{
201-
// We could call memset just once for the entire range
202-
// but this way has better memory locality.
203-
(() @trusted => memset(arr.ptr + l, 0, T.sizeof))();
204-
arr[l++] = value;
205-
}
206-
}
207-
else
208-
{
209-
foreach (ref value; rhs)
210-
{
211-
(() @trusted => memcpy(arr.ptr + l, init.ptr, T.sizeof))();
212-
arr[l++] = value;
213-
}
214-
}
192+
foreach (ref value; rhs)
193+
emplace(arr[l++], value);
215194
}
216195
else
217196
{
@@ -288,6 +267,51 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
288267
}
289268
}
290269

270+
static if (is(typeof({T value;}))) // default construction is allowed
271+
{
272+
/**
273+
* Change the array length.
274+
* When growing, initialize new elements to the default value.
275+
*/
276+
void resize(size_t n)
277+
{
278+
resize(n, T.init);
279+
}
280+
}
281+
282+
/**
283+
* Change the array length.
284+
* When growing, initialize new elements to the given value.
285+
*/
286+
void resize(size_t n, T value)
287+
{
288+
if (arr.length < n)
289+
reserve(n);
290+
291+
if (l < n) // Growing?
292+
{
293+
import std.traits: hasElaborateAssign, hasElaborateDestructor;
294+
static if (is(T == struct) && (hasElaborateAssign!T || hasElaborateDestructor!T))
295+
{
296+
foreach (i; l..n)
297+
emplace(arr[l], value);
298+
}
299+
else
300+
arr[l..n] = value;
301+
}
302+
else
303+
{
304+
static if ((is(T == struct) || is(T == union))
305+
&& __traits(hasMember, T, "__xdtor"))
306+
{
307+
foreach (i; n..l)
308+
arr[i].__xdtor();
309+
}
310+
}
311+
312+
l = n;
313+
}
314+
291315
/**
292316
* Remove the item at the given index from the array.
293317
*/
@@ -377,6 +401,13 @@ struct DynamicArray(T, Allocator = Mallocator, bool supportGC = shouldAddGCRange
377401

378402
private:
379403

404+
static void emplace(ref ContainerStorageType!T target, ref AppendT source)
405+
{
406+
(cast(void[])((&target)[0..1]))[] = cast(void[])((&source)[0..1]);
407+
static if (__traits(hasMember, T, "__xpostblit"))
408+
target.__xpostblit();
409+
}
410+
380411
import containers.internal.storage_type : ContainerStorageType;
381412
import containers.internal.element_type : ContainerElementType;
382413
import containers.internal.mixins : AllocatorState;
@@ -588,3 +619,50 @@ version(emsi_containers_unittest) @nogc unittest
588619
a ~= a;
589620
assert(a[] == "abcdefabcdef");
590621
}
622+
623+
version(emsi_containers_unittest) unittest
624+
{
625+
static struct S
626+
{
627+
bool initialized;
628+
@nogc:
629+
@disable this();
630+
this(int) { initialized = true; }
631+
~this() { assert(initialized); }
632+
}
633+
634+
auto s = S(0);
635+
636+
DynamicArray!S arr;
637+
arr.insertBack(s);
638+
arr ~= [s];
639+
}
640+
641+
version(emsi_containers_unittest) @nogc unittest
642+
{
643+
DynamicArray!int a;
644+
a.resize(5, 42);
645+
assert(a.length == 5);
646+
assert(a[2] == 42);
647+
a.resize(3, 17);
648+
assert(a.length == 3);
649+
assert(a[2] == 42);
650+
651+
struct Counter
652+
{
653+
@nogc:
654+
static int count;
655+
@disable this();
656+
this(int) { count++; }
657+
this(this) { count++; }
658+
~this() { count--; }
659+
}
660+
661+
DynamicArray!Counter b;
662+
assert(Counter.count == 0);
663+
static assert(!is(typeof(b.resize(5))));
664+
b.resize(5, Counter(0));
665+
assert(Counter.count == 5);
666+
b.resize(3, Counter(0));
667+
assert(Counter.count == 3);
668+
}

src/containers/hashmap.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ private:
549549
unittest
550550
{
551551
import std.uuid : randomUUID;
552-
import std.algorithm.iteration : walkLength;
552+
import std.range.primitives : walkLength;
553553

554554
auto hm = HashMap!(string, int)(16);
555555
assert (hm.length == 0);

src/containers/treemap.d

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ version(emsi_containers_unittest) @system unittest
257257

258258
version(emsi_containers_unittest) unittest
259259
{
260-
import std.algorithm.iteration : walkLength;
260+
import std.range.primitives : walkLength;
261261
import std.stdio : stdout;
262262
import stdx.allocator.building_blocks.allocator_list : AllocatorList;
263263
import stdx.allocator.building_blocks.free_list : FreeList;
@@ -305,7 +305,7 @@ version(emsi_containers_unittest) unittest
305305
version(emsi_containers_unittest) unittest
306306
{
307307
import std.uuid : randomUUID;
308-
import std.algorithm.iteration : walkLength;
308+
import std.range.primitives : walkLength;
309309

310310
auto hm = TreeMap!(string, int)();
311311
assert (hm.length == 0);
@@ -398,7 +398,7 @@ version(emsi_containers_unittest) unittest
398398
version(emsi_containers_unittest) unittest
399399
{
400400
import std.uuid : randomUUID;
401-
import std.algorithm.iteration : walkLength;
401+
import std.range.primitives : walkLength;
402402
import std.stdio;
403403

404404
auto hm = TreeMap!(string, int)();

0 commit comments

Comments
 (0)