Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Replace AssociativeArray struct with UFCS methods #668

Merged
1 commit merged into from
Feb 9, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
187 changes: 97 additions & 90 deletions src/object.di
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ class TypeInfo_AssociativeArray : TypeInfo
{
TypeInfo value;
TypeInfo key;
TypeInfo impl;
}

class TypeInfo_Vector : TypeInfo
Expand Down Expand Up @@ -354,18 +353,18 @@ extern (C)
{
// from druntime/src/rt/aaA.d

size_t _aaLen(in void* p) pure nothrow;
void* _aaGetX(void** pp, const TypeInfo keyti, in size_t valuesize, in void* pkey);
inout(void)* _aaGetRvalueX(inout void* p, in TypeInfo keyti, in size_t valuesize, in void* pkey);
// size_t _aaLen(in void* p) pure nothrow;
// void* _aaGetX(void** pp, const TypeInfo keyti, in size_t valuesize, in void* pkey);
// inout(void)* _aaGetRvalueX(inout void* p, in TypeInfo keyti, in size_t valuesize, in void* pkey);
inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize) pure nothrow;
inout(void)[] _aaKeys(inout void* p, in size_t keysize) pure nothrow;
void* _aaRehash(void** pp, in TypeInfo keyti) pure nothrow;

extern (D) alias scope int delegate(void *) _dg_t;
int _aaApply(void* aa, size_t keysize, _dg_t dg);
// extern (D) alias scope int delegate(void *) _dg_t;
// int _aaApply(void* aa, size_t keysize, _dg_t dg);

extern (D) alias scope int delegate(void *, void *) _dg2_t;
int _aaApply2(void* aa, size_t keysize, _dg2_t dg);
// extern (D) alias scope int delegate(void *, void *) _dg2_t;
// int _aaApply2(void* aa, size_t keysize, _dg2_t dg);

private struct AARange { void* impl, current; }
AARange _aaRange(void* aa);
Expand All @@ -375,112 +374,120 @@ extern (C)
void _aaRangePopFront(ref AARange r);
}

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

Value[Key] rehash(T : Value[Key], Value, Key)(auto ref T aa)
{
private:
void* p;
_aaRehash(cast(void**)&aa, typeid(Value[Key]));
return aa;
}

public:
@property size_t length() const { return _aaLen(p); }
Value[Key] rehash(T : Value[Key], Value, Key)(T* aa)
{
__aaRehash(cast(void**)aa, typeid(Value[Key]));
return aa;
}

Value[Key] rehash()
Value[Key] dup(T : Value[Key], Value, Key)(T aa) if (is(typeof({
ref Value get(); // pseudo lvalue of Value
Value[Key] r; r[Key.init] = get();
// bug 10720 - check whether Value is copyable
})))
{
Value[Key] result;
foreach (k, v; aa)
{
auto p = _aaRehash(cast(void**) &p, typeid(Value[Key]));
return *cast(Value[Key]*)(&p);
result[k] = v;
}
return result;
}

// Note: can't make `values` and `keys` inout as it is used
// e.g. in Phobos like `ReturnType!(aa.keys)` instead of `typeof(aa.keys)`
// which will result in `inout` propagation.
Value[Key] dup(T : Value[Key], Value, Key)(T* aa) if (is(typeof((*aa).dup)))
{
return (*aa).dup;
}

inout(Value)[] inout_values() inout @property
{
auto a = _aaValues(p, Key.sizeof, Value.sizeof);
return *cast(inout Value[]*) &a;
}
@disable Value[Key] dup(T : Value[Key], Value, Key)(T aa) if (!is(typeof({
ref Value get(); // pseudo lvalue of Value
Value[Key] r; r[Key.init] = get();
// bug 10720 - check whether Value is copyable
})));

inout(Key)[] inout_keys() inout @property
{
auto a = _aaKeys(p, Key.sizeof);
return *cast(inout Key[]*) &a;
}
Value[Key] dup(T : Value[Key], Value, Key)(T* aa) if (!is(typeof((*aa).dup)));

Value[] values() @property
{ return inout_values; }
auto byKey(T : Value[Key], Value, Key)(T aa)
{
static struct Result
{
AARange r;

Key[] keys() @property
{ return inout_keys; }
@property bool empty() { return _aaRangeEmpty(r); }
@property ref Key front() { return *cast(Key*)_aaRangeFrontKey(r); }
void popFront() { _aaRangePopFront(r); }
Result save() { return this; }
}

const(Value)[] values() const @property
{ return inout_values; }
return Result(_aaRange(cast(void*)aa));
}

const(Key)[] keys() const @property
{ return inout_keys; }
auto byKey(T : Value[Key], Value, Key)(T *aa)
{
return (*aa).byKey();
}

int opApply(scope int delegate(ref Key, ref Value) dg)
auto byValue(T : Value[Key], Value, Key)(T aa)
{
static struct Result
{
return _aaApply2(p, Key.sizeof, cast(_dg2_t)dg);
}
AARange r;

int opApply(scope int delegate(ref Value) dg)
{
return _aaApply(p, Key.sizeof, cast(_dg_t)dg);
@property bool empty() { return _aaRangeEmpty(r); }
@property ref Value front() { return *cast(Value*)_aaRangeFrontValue(r); }
void popFront() { _aaRangePopFront(r); }
Result save() { return this; }
}

Value get(Key key, lazy Value defaultValue)
{
auto p = key in *cast(Value[Key]*)(&p);
return p ? *p : defaultValue;
}
return Result(_aaRange(cast(void*)aa));
}

static if (is(typeof({
ref Value get(); // pseudo lvalue of Value
Value[Key] r; r[Key.init] = get();
// bug 10720 - check whether Value is copyable
})))
{
Value[Key] dup()
{
Value[Key] result;
foreach (k, v; this)
{
result[k] = v;
}
return result;
}
}
else
@disable Value[Key] dup(); // for better error message
auto byValue(T : Value[Key], Value, Key)(T *aa)
{
return (*aa).byValue();
}

auto byKey()
{
static struct Result
{
AARange r;
Key[] keys(T : Value[Key], Value, Key)(T aa)
{
auto a = cast(void[])_aaKeys(cast(inout(void)*)aa, Key.sizeof);
return *cast(Key[]*)&a;
}

@property bool empty() { return _aaRangeEmpty(r); }
@property ref Key front() { return *cast(Key*)_aaRangeFrontKey(r); }
void popFront() { _aaRangePopFront(r); }
Result save() { return this; }
}
Key[] keys(T : Value[Key], Value, Key)(T *aa)
{
return (*aa).keys();
}

return Result(_aaRange(p));
}
Value[] values(T : Value[Key], Value, Key)(T aa)
{
auto a = cast(void[])_aaValues(cast(inout(void)*)aa, Key.sizeof, Value.sizeof);
return *cast(Value[]*)&a;
}

auto byValue()
{
static struct Result
{
AARange r;
Value[] values(T : Value[Key], Value, Key)(T *aa)
{
return (*aa).values();
}

@property bool empty() { return _aaRangeEmpty(r); }
@property ref Value front() { return *cast(Value*)_aaRangeFrontValue(r); }
void popFront() { _aaRangePopFront(r); }
Result save() { return this; }
}
Value get(T : Value[Key], Value, Key, K, V)(T aa, K key, lazy V defaultValue)
if (is(typeof(aa[key] = defaultValue)))
{
auto p = key in aa;
return p ? *p : cast(Value)defaultValue;
}

return Result(_aaRange(p));
}
Value get(T : Value[Key], Value, Key, K, V)(T* aa, K key, lazy V defaultValue)
if (is(typeof((*aa).get(key, defaultValue))))
{
return (*aa).get(key, defaultValue);
}

// Scheduled for deprecation in December 2012.
Expand Down