mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 16:18:19 +00:00
Implement standard-library-compatible iterators for Dictionary
This commit is contained in:
parent
9e9998c6e5
commit
892124378c
16 changed files with 834 additions and 254 deletions
163
src/Val.cc
163
src/Val.cc
|
@ -495,13 +495,15 @@ static void BuildJSON(threading::formatter::JSON::NullDoubleWriter& writer, Val*
|
|||
else
|
||||
writer.StartObject();
|
||||
|
||||
detail::HashKey* k;
|
||||
std::unique_ptr<detail::HashKey> k;
|
||||
TableEntryVal* entry;
|
||||
auto c = table->InitForIteration();
|
||||
while ( (entry = table->NextEntry(k, c)) )
|
||||
|
||||
for ( const auto& te : *table )
|
||||
{
|
||||
entry = te.GetValue<TableEntryVal*>();
|
||||
k = te.GetHashKey();
|
||||
|
||||
auto lv = tval->RecreateIndex(*k);
|
||||
delete k;
|
||||
Val* entry_key = lv->Length() == 1 ? lv->Idx(0).get() : lv.get();
|
||||
|
||||
if ( tval->GetType()->IsSet() )
|
||||
|
@ -1438,7 +1440,7 @@ void TableVal::Init(TableTypePtr t)
|
|||
table_type = std::move(t);
|
||||
expire_func = nullptr;
|
||||
expire_time = nullptr;
|
||||
expire_cookie = nullptr;
|
||||
expire_iterator = nullptr;
|
||||
timer = nullptr;
|
||||
def_val = nullptr;
|
||||
|
||||
|
@ -1460,6 +1462,7 @@ TableVal::~TableVal()
|
|||
delete table_hash;
|
||||
delete table_val;
|
||||
delete subnets;
|
||||
delete expire_iterator;
|
||||
}
|
||||
|
||||
void TableVal::RemoveAll()
|
||||
|
@ -1483,11 +1486,9 @@ int TableVal::RecursiveSize() const
|
|||
GetType()->AsTableType()->Yield()->Tag() != TYPE_TABLE )
|
||||
return n;
|
||||
|
||||
IterCookie* c = table_val->InitForIteration();
|
||||
|
||||
TableEntryVal* tv;
|
||||
while ( (tv = table_val->NextEntry(c)) )
|
||||
for ( const auto& ve : *table_val )
|
||||
{
|
||||
auto* tv = ve.GetValue<TableEntryVal*>();
|
||||
if ( tv->GetVal() )
|
||||
n += tv->GetVal()->AsTableVal()->RecursiveSize();
|
||||
}
|
||||
|
@ -1657,15 +1658,12 @@ bool TableVal::AddTo(Val* val, bool is_first_init, bool propagate_ops) const
|
|||
return false;
|
||||
}
|
||||
|
||||
IterCookie* c = table_val->InitForIteration();
|
||||
|
||||
detail::HashKey* k;
|
||||
TableEntryVal* v;
|
||||
while ( (v = table_val->NextEntry(k, c)) )
|
||||
for ( const auto& tble : *table_val )
|
||||
{
|
||||
std::unique_ptr<detail::HashKey> hk{k};
|
||||
auto k = tble.GetHashKey();
|
||||
auto* v = tble.GetValue<TableEntryVal*>();
|
||||
|
||||
if ( is_first_init && t->AsTable()->Lookup(k) )
|
||||
if ( is_first_init && t->AsTable()->Lookup(k.get()) )
|
||||
{
|
||||
auto key = table_hash->RecoverVals(*k);
|
||||
// ### Shouldn't complain if their values are equal.
|
||||
|
@ -1675,12 +1673,12 @@ bool TableVal::AddTo(Val* val, bool is_first_init, bool propagate_ops) const
|
|||
|
||||
if ( type->IsSet() )
|
||||
{
|
||||
if ( ! t->Assign(v->GetVal(), std::move(hk), nullptr) )
|
||||
if ( ! t->Assign(v->GetVal(), std::move(k), nullptr) )
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ! t->Assign(nullptr, std::move(hk), v->GetVal()) )
|
||||
if ( ! t->Assign(nullptr, std::move(k), v->GetVal()) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1704,18 +1702,15 @@ bool TableVal::RemoveFrom(Val* val) const
|
|||
return false;
|
||||
}
|
||||
|
||||
IterCookie* c = table_val->InitForIteration();
|
||||
|
||||
detail::HashKey* k;
|
||||
while ( table_val->NextEntry(k, c) )
|
||||
for ( const auto& tble : *table_val )
|
||||
{
|
||||
// Not sure that this is 100% sound, since the HashKey
|
||||
// comes from one table but is being used in another.
|
||||
// OTOH, they are both the same type, so as long as
|
||||
// we don't have hash keys that are keyed per dictionary,
|
||||
// it should work ...
|
||||
auto k = tble.GetHashKey();
|
||||
t->Remove(*k);
|
||||
delete k;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1736,16 +1731,15 @@ TableValPtr TableVal::Intersection(const TableVal& tv) const
|
|||
t0 = tmp;
|
||||
}
|
||||
|
||||
IterCookie* c = t1->InitForIteration();
|
||||
detail::HashKey* k;
|
||||
while ( t1->NextEntry(k, c) )
|
||||
const PDict<TableEntryVal>* tbl = AsTable();
|
||||
for ( const auto& tble : *tbl )
|
||||
{
|
||||
auto k = tble.GetHashKey();
|
||||
|
||||
// Here we leverage the same assumption about consistent
|
||||
// hashes as in TableVal::RemoveFrom above.
|
||||
if ( t0->Lookup(k) )
|
||||
result->table_val->Insert(k, new TableEntryVal(nullptr));
|
||||
|
||||
delete k;
|
||||
if ( t0->Lookup(k.get()) )
|
||||
result->table_val->Insert(k.get(), new TableEntryVal(nullptr));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -1759,20 +1753,14 @@ bool TableVal::EqualTo(const TableVal& tv) const
|
|||
if ( t0->Length() != t1->Length() )
|
||||
return false;
|
||||
|
||||
IterCookie* c = t0->InitForIteration();
|
||||
detail::HashKey* k;
|
||||
while ( t0->NextEntry(k, c) )
|
||||
for ( const auto& tble : *t0 )
|
||||
{
|
||||
auto k = tble.GetHashKey();
|
||||
|
||||
// Here we leverage the same assumption about consistent
|
||||
// hashes as in TableVal::RemoveFrom above.
|
||||
if ( ! t1->Lookup(k) )
|
||||
{
|
||||
delete k;
|
||||
t0->StopIteration(c);
|
||||
if ( ! t1->Lookup(k.get()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
delete k;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1786,20 +1774,14 @@ bool TableVal::IsSubsetOf(const TableVal& tv) const
|
|||
if ( t0->Length() > t1->Length() )
|
||||
return false;
|
||||
|
||||
IterCookie* c = t0->InitForIteration();
|
||||
detail::HashKey* k;
|
||||
while ( t0->NextEntry(k, c) )
|
||||
for ( const auto& tble : *t0 )
|
||||
{
|
||||
auto k = tble.GetHashKey();
|
||||
|
||||
// Here we leverage the same assumption about consistent
|
||||
// hashes as in TableVal::RemoveFrom above.
|
||||
if ( ! t1->Lookup(k) )
|
||||
{
|
||||
delete k;
|
||||
t0->StopIteration(c);
|
||||
if ( ! t1->Lookup(k.get()) )
|
||||
return false;
|
||||
}
|
||||
|
||||
delete k;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -2331,11 +2313,9 @@ ListValPtr TableVal::ToListVal(TypeTag t) const
|
|||
{
|
||||
auto l = make_intrusive<ListVal>(t);
|
||||
|
||||
IterCookie* c = table_val->InitForIteration();
|
||||
|
||||
detail::HashKey* k;
|
||||
while ( table_val->NextEntry(k, c) )
|
||||
for ( const auto& tble : *table_val )
|
||||
{
|
||||
auto k = tble.GetHashKey();
|
||||
auto index = table_hash->RecoverVals(*k);
|
||||
|
||||
if ( t == TYPE_ANY )
|
||||
|
@ -2348,8 +2328,6 @@ ListValPtr TableVal::ToListVal(TypeTag t) const
|
|||
|
||||
l->Append(index->Idx(0));
|
||||
}
|
||||
|
||||
delete k;
|
||||
}
|
||||
|
||||
return l;
|
||||
|
@ -2400,16 +2378,16 @@ void TableVal::Describe(ODesc* d) const
|
|||
d->PushIndent();
|
||||
}
|
||||
|
||||
IterCookie* c = table_val->InitForIteration();
|
||||
auto iter = table_val->begin();
|
||||
|
||||
for ( int i = 0; i < n; ++i )
|
||||
{
|
||||
detail::HashKey* k;
|
||||
TableEntryVal* v = table_val->NextEntry(k, c);
|
||||
|
||||
if ( ! v )
|
||||
if ( iter == table_val->end() )
|
||||
reporter->InternalError("hash table underflow in TableVal::Describe");
|
||||
|
||||
auto k = iter->GetHashKey();
|
||||
auto* v = iter->GetValue<TableEntryVal*>();
|
||||
|
||||
auto vl = table_hash->RecoverVals(*k);
|
||||
int dim = vl->Length();
|
||||
|
||||
|
@ -2434,8 +2412,6 @@ void TableVal::Describe(ODesc* d) const
|
|||
|
||||
vl->Describe(d);
|
||||
|
||||
delete k;
|
||||
|
||||
if ( table_type->IsSet() )
|
||||
{ // We're a set, not a table.
|
||||
if ( d->IsReadable() )
|
||||
|
@ -2455,9 +2431,11 @@ void TableVal::Describe(ODesc* d) const
|
|||
d->Add(" @");
|
||||
d->Add(util::detail::fmt_access_time(v->ExpireAccessTime()));
|
||||
}
|
||||
|
||||
++iter;
|
||||
}
|
||||
|
||||
if ( table_val->NextEntry(c) )
|
||||
if ( iter != table_val->end() )
|
||||
reporter->InternalError("hash table overflow in TableVal::Describe");
|
||||
|
||||
if ( d->IsPortable() || d->IsReadable() )
|
||||
|
@ -2552,20 +2530,23 @@ void TableVal::DoExpire(double t)
|
|||
// error, it has been reported already.
|
||||
return;
|
||||
|
||||
if ( ! expire_cookie )
|
||||
if ( ! expire_iterator )
|
||||
{
|
||||
expire_cookie = table_val->InitForIteration();
|
||||
table_val->MakeRobustCookie(expire_cookie);
|
||||
auto it = table_val->begin_robust();
|
||||
expire_iterator = new RobustDictIterator(std::move(it));
|
||||
}
|
||||
|
||||
detail::HashKey* k = nullptr;
|
||||
std::unique_ptr<detail::HashKey> k = nullptr;
|
||||
TableEntryVal* v = nullptr;
|
||||
TableEntryVal* v_saved = nullptr;
|
||||
bool modified = false;
|
||||
|
||||
for ( int i = 0; i < zeek::detail::table_incremental_step &&
|
||||
(v = table_val->NextEntry(k, expire_cookie)); ++i )
|
||||
*expire_iterator != table_val->end_robust(); ++i, ++(*expire_iterator) )
|
||||
{
|
||||
k = (*expire_iterator)->GetHashKey();
|
||||
v = (*expire_iterator)->GetValue<TableEntryVal*>();
|
||||
|
||||
if ( v->ExpireAccessTime() == 0 )
|
||||
{
|
||||
// This happens when we insert val while network_time
|
||||
|
@ -2588,12 +2569,11 @@ void TableVal::DoExpire(double t)
|
|||
// function modified or deleted the table
|
||||
// value, so look it up again.
|
||||
v_saved = v;
|
||||
v = table_val->Lookup(k);
|
||||
v = table_val->Lookup(k.get());
|
||||
|
||||
if ( ! v )
|
||||
{ // user-provided function deleted it
|
||||
v = v_saved;
|
||||
delete k;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2602,7 +2582,6 @@ void TableVal::DoExpire(double t)
|
|||
// User doesn't want us to expire
|
||||
// this now.
|
||||
v->SetExpireAccess(run_state::network_time - timeout + secs);
|
||||
delete k;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2616,7 +2595,7 @@ void TableVal::DoExpire(double t)
|
|||
reporter->InternalWarning("index not in prefix table");
|
||||
}
|
||||
|
||||
table_val->RemoveEntry(k);
|
||||
table_val->RemoveEntry(k.get());
|
||||
if ( change_func )
|
||||
{
|
||||
if ( ! idx )
|
||||
|
@ -2628,16 +2607,15 @@ void TableVal::DoExpire(double t)
|
|||
delete v;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
delete k;
|
||||
}
|
||||
|
||||
if ( modified )
|
||||
Modified();
|
||||
|
||||
if ( ! v )
|
||||
if ( (*expire_iterator) == table_val->end_robust() )
|
||||
{
|
||||
expire_cookie = nullptr;
|
||||
delete expire_iterator;
|
||||
expire_iterator = nullptr;
|
||||
InitTimer(zeek::detail::table_expire_interval);
|
||||
}
|
||||
else
|
||||
|
@ -2740,22 +2718,19 @@ ValPtr TableVal::DoClone(CloneState* state)
|
|||
auto tv = make_intrusive<TableVal>(table_type);
|
||||
state->NewClone(this, tv);
|
||||
|
||||
IterCookie* cookie = table_val->InitForIteration();
|
||||
|
||||
detail::HashKey* key;
|
||||
TableEntryVal* val;
|
||||
while ( (val = table_val->NextEntry(key, cookie)) )
|
||||
const PDict<TableEntryVal>* tbl = AsTable();
|
||||
for ( const auto& tble : *table_val )
|
||||
{
|
||||
auto key = tble.GetHashKey();
|
||||
auto* val = tble.GetValue<TableEntryVal*>();
|
||||
TableEntryVal* nval = val->Clone(state);
|
||||
tv->table_val->Insert(key, nval);
|
||||
tv->table_val->Insert(key.get(), nval);
|
||||
|
||||
if ( subnets )
|
||||
{
|
||||
auto idx = RecreateIndex(*key);
|
||||
tv->subnets->Insert(idx.get(), nval);
|
||||
}
|
||||
|
||||
delete key;
|
||||
}
|
||||
|
||||
tv->attrs = attrs;
|
||||
|
@ -2783,11 +2758,9 @@ unsigned int TableVal::MemoryAllocation() const
|
|||
{
|
||||
unsigned int size = 0;
|
||||
|
||||
IterCookie* c = table_val->InitForIteration();
|
||||
|
||||
TableEntryVal* tv;
|
||||
while ( (tv = table_val->NextEntry(c)) )
|
||||
for ( const auto& ve : *table_val )
|
||||
{
|
||||
auto* tv = ve.GetValue<TableEntryVal*>();
|
||||
if ( tv->GetVal() )
|
||||
size += tv->GetVal()->MemoryAllocation();
|
||||
size += padded_sizeof(TableEntryVal);
|
||||
|
@ -2833,17 +2806,13 @@ void TableVal::DoneParsing()
|
|||
|
||||
TableVal::ParseTimeTableState TableVal::DumpTableState()
|
||||
{
|
||||
IterCookie* cookie = table_val->InitForIteration();
|
||||
|
||||
detail::HashKey* key;
|
||||
TableEntryVal* val;
|
||||
|
||||
ParseTimeTableState rval;
|
||||
|
||||
while ( (val = table_val->NextEntry(key, cookie)) )
|
||||
for ( const auto& tble : *table_val )
|
||||
{
|
||||
auto key = tble.GetHashKey();
|
||||
auto* val = tble.GetValue<TableEntryVal*>();
|
||||
|
||||
rval.emplace_back(RecreateIndex(*key), val->GetVal());
|
||||
delete key;
|
||||
}
|
||||
|
||||
RemoveAll();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue