Showing with 67 additions and 2 deletions.
  1. +18 −1 changelog.dd
  2. +11 −0 src/object.d
  3. +38 −1 src/rt/aaA.d
19 changes: 18 additions & 1 deletion changelog.dd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ $(BUGSTITLE Library Changes,

$(LI $(RELATIVE_LINK2 TypeInfo.initializer, `TypeInfo.init` has been renamed to
`TypeInfo.initializer`.))
)
$(LI $(RELATIVE_LINK2 aa-clear, A `clear` method has been added to associative
arrays to remove all elements.))
)

$(BUGSTITLE Library Changes,
Expand All @@ -28,6 +29,22 @@ $(LI $(LNAME2 TypeInfo.initializer, `TypeInfo.init` has been renamed to
2.074.0 release, so that the type property `init` takes over.
)
)
$(LI $(LNAME2 aa-clear, A `clear` method has been added to associative
arrays to remove all elements.)

$(P One can now use `aa.clear()` to remove all elements from an
associative array. This allows removing all elements from all
references to the same array (setting to `null` just reset the
reference, but did not removed the elements from other references).
)

-------
auto aa = ["first" : "entry", "second": "entry"];
auto aa2 = aa1; // reference to the same AA
aa.clear(); // still retains its current capacity for faster imports
assert(aa2.length == 0); // other references affected
-------
)
)


Expand Down
11 changes: 11 additions & 0 deletions src/object.d
Original file line number Diff line number Diff line change
Expand Up @@ -1864,6 +1864,7 @@ extern (C)
inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize, const TypeInfo tiValArray) pure nothrow;
inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow;
void* _aaRehash(void** pp, in TypeInfo keyti) pure nothrow;
void _aaClear(void* p) pure nothrow;

// alias _dg_t = extern(D) int delegate(void*);
// int _aaApply(void* aa, size_t keysize, _dg_t dg);
Expand Down Expand Up @@ -1897,6 +1898,16 @@ void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure

alias AssociativeArray(Key, Value) = Value[Key];

void clear(T : Value[Key], Value, Key)(T aa)
{
_aaClear(*cast(void **) &aa);
}

void clear(T : Value[Key], Value, Key)(T* aa)
{
_aaClear(*cast(void **) aa);
}

T rehash(T : Value[Key], Value, Key)(T aa)
{
_aaRehash(cast(void**)&aa, typeid(Value[Key]));
Expand Down
39 changes: 38 additions & 1 deletion src/rt/aaA.d
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private:
auto obuckets = buckets;
buckets = allocBuckets(ndim);

foreach (ref b; obuckets)
foreach (ref b; obuckets[firstUsed .. $])
if (b.filled)
*findSlotInsert(b.hash) = b;

Expand All @@ -152,6 +152,15 @@ private:
deleted = 0;
GC.free(obuckets.ptr); // safe to free b/c impossible to reference
}

void clear() pure nothrow
{
import core.stdc.string : memset;
// clear all data, but don't change bucket array length
memset(&buckets[firstUsed], 0, (buckets.length - firstUsed) * Bucket.sizeof);
deleted = used = 0;
firstUsed = cast(uint) dim;
}
}

//==============================================================================
Expand Down Expand Up @@ -425,6 +434,15 @@ extern (C) bool _aaDelX(AA aa, in TypeInfo keyti, in void* pkey)
return false;
}

/// Remove all elements from AA.
extern (C) void _aaClear(AA aa) pure nothrow
{
if (!aa.empty)
{
aa.impl.clear();
}
}

/// Rehash AA
extern (C) void* _aaRehash(AA* paa, in TypeInfo keyti) pure nothrow
{
Expand Down Expand Up @@ -932,3 +950,22 @@ unittest
GC.runFinalizers((cast(char*)(&entryDtor))[0 .. 1]);
assert(T.dtor == 6 && T.postblit == 2);
}

// for aa.clear
pure nothrow unittest
{
int[int] aa;
assert(aa.length == 0);
foreach (i; 0 .. 100)
aa[i] = i * 2;
assert(aa.length == 100);
auto aa2 = aa;
assert(aa2.length == 100);
aa.clear();
assert(aa.length == 0);
assert(aa2.length == 0);

aa2[5] = 6;
assert(aa.length == 1);
assert(aa[5] == 6);
}