Skip to content

Commit

Permalink
Added byKey and byValue ranges.
Browse files Browse the repository at this point in the history
  • Loading branch information
andralex committed Jan 16, 2012
1 parent 94f4a46 commit cd7b477
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 51 deletions.
147 changes: 125 additions & 22 deletions src/object_.d
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,75 @@ extern (C)

struct AssociativeArray(Key, Value)
{
void* p;
private:
// Duplicates of the stuff found in druntime/src/rt/aaA.d
struct Slot
{
Slot *next;
hash_t hash;
Key key;
Value value;
}

struct Hashtable
{
Slot*[] b;
size_t nodes;
TypeInfo keyti;
Slot*[4] binit;
}

void* p; // really Hashtable*

struct Range
{
// State
Slot*[] slots;
Slot* current;

this(void * aa)
{
auto pImpl = cast(Hashtable*) aa;
slots = pImpl.b;
nextSlot();
}

void nextSlot()
{
foreach (i, slot; slots)
{
if (!slot) continue;
current = slot;
slots = slots.ptr[i .. slots.length];
break;
}
}

public:
@property bool empty() const
{
return current is null;
}

@property ref inout(Slot) front() inout
{
assert(current);
return *current;
}

void popFront()
{
assert(current);
current = current.next;
if (!current)
{
slots = slots[1 .. $];
nextSlot();
}
}
}

public:

@property size_t length() { return _aaLen(p); }

Expand Down Expand Up @@ -2049,27 +2117,6 @@ struct AssociativeArray(Key, Value)
return _aaApply(p, Key.sizeof, cast(_dg_t)dg);
}

int delegate(int delegate(ref Key) dg) byKey()
{
// Discard the Value part and just do the Key
int foo(int delegate(ref Key) dg)
{
int byKeydg(ref Key key, ref Value value)
{
return dg(key);
}

return _aaApply2(p, Key.sizeof, cast(_dg2_t)&byKeydg);
}

return &foo;
}

int delegate(int delegate(ref Value) dg) byValue()
{
return &opApply;
}

Value get(Key key, lazy Value defaultValue)
{
auto p = key in *cast(Value[Key]*)(&p);
Expand All @@ -2086,13 +2133,69 @@ struct AssociativeArray(Key, Value)
}
return result;
}

@property auto byKey()
{
static struct Result
{
Range state;

this(void* p)
{
state = Range(p);
}

@property ref Key front()
{
return state.front.key;
}

alias state this;
}

return Result(p);
}

@property auto byValue()
{
static struct Result
{
Range state;

this(void* p)
{
state = Range(p);
}

@property ref Value front()
{
return state.front.value;
}

alias state this;
}

return Result(p);
}
}

unittest
{
auto a = [ 1:"one", 2:"two", 3:"three" ];
auto b = a.dup;
assert(b == [ 1:"one", 2:"two", 3:"three" ]);

int[] c;
foreach (k; a.byKey)
{
c ~= k;
}

assert(c.length == 3);
c.sort;
assert(c[0] == 1);
assert(c[1] == 2);
assert(c[2] == 3);
}
unittest
{
Expand Down
58 changes: 29 additions & 29 deletions src/rt/aaA.d
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ private

extern (C) void* gc_malloc( size_t sz, uint ba = 0 );
extern (C) void gc_free( void* p );

// Convenience function to make sure the NO_INTERIOR gets set on the
// aaA arrays.
aaA*[] newaaA(size_t len)
aaA*[] newaaA(size_t len)
{
auto ptr = cast(aaA**) gc_malloc(
len * (aaA*).sizeof, BlkAttr.NO_INTERIOR);
Expand Down Expand Up @@ -595,54 +595,54 @@ unittest
extern (D) alias int delegate(void *) dg_t;

int _aaApply(AA aa, size_t keysize, dg_t dg)
{ int result;
{
if (!aa.a)
{
return 0;
}

immutable alignsize = aligntsize(keysize);
//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);

auto alignsize = aligntsize(keysize);

if (aa.a)
foreach (e; aa.a.b)
{
Loop:
foreach (e; aa.a.b)
while (e)
{
while (e)
{
result = dg(cast(void *)(e + 1) + alignsize);
if (result)
break Loop;
e = e.next;
}
auto result = dg(cast(void *)(e + 1) + alignsize);
if (result)
return result;
e = e.next;
}
}
return result;
return 0;
}

// dg is D, but _aaApply2() is C
extern (D) alias int delegate(void *, void *) dg2_t;

int _aaApply2(AA aa, size_t keysize, dg2_t dg)
{ int result;
{
if (!aa.a)
{
return 0;
}

//printf("_aaApply(aa = x%llx, keysize = %d, dg = x%llx)\n", aa.a, keysize, dg);

auto alignsize = aligntsize(keysize);
immutable alignsize = aligntsize(keysize);

if (aa.a)
foreach (e; aa.a.b)
{
Loop:
foreach (e; aa.a.b)
while (e)
{
while (e)
{
result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + alignsize);
if (result)
break Loop;
e = e.next;
}
auto result = dg(e + 1, cast(void *)(e + 1) + alignsize);
if (result)
return result;
e = e.next;
}
}
return result;

return 0;
}


Expand Down

0 comments on commit cd7b477

Please sign in to comment.