Add &default_insert attribute for tables

This is based on the discussion in zeek/zeek#2668. Using &default with tables
can be confusing as the default value is not inserted. The following example
prints an empty table at the end even new Service records was instantiated.

    type Service: record {
        occurrences: count &default=0;
        last_seen: time &default=network_time();
    };

    global services: table[string] of Service &default=Service();

    event zeek_init()
        {
        services["http"]$occurrences += 1;
        services["http"]$last_seen = network_time();

        print services;
        }

Changing above &default to &default_insert will insert the newly created
default value upon a missed lookup and act less surprising.

Other examples that caused confusion previously revolved around table of sets
 or table of vectors and `add` or `+=` not working as expected.

    tbl_of_vector["http"] += 1
    add tbl_of_set["http"][1];
This commit is contained in:
Arne Welzel 2023-07-07 17:05:00 +02:00
parent 81ce83590d
commit 431767d04b
22 changed files with 230 additions and 13 deletions

View file

@ -2137,7 +2137,10 @@ bool TableVal::IsSubsetOf(const TableVal& tv) const
ValPtr TableVal::Default(const ValPtr& index)
{
const auto& def_attr = GetAttr(detail::ATTR_DEFAULT);
auto def_attr = GetAttr(detail::ATTR_DEFAULT);
if ( ! def_attr )
def_attr = GetAttr(detail::ATTR_DEFAULT_INSERT);
if ( ! def_attr )
return nullptr;
@ -2268,7 +2271,13 @@ ValPtr TableVal::FindOrDefault(const ValPtr& index)
if ( auto rval = Find(index) )
return rval;
return Default(index);
// If the default came from a &default_insert attribute,
// insert the value upon a missed lookup.
auto def = Default(index);
if ( def && GetAttr(detail::ATTR_DEFAULT_INSERT) )
Assign(index, def);
return def;
}
bool TableVal::Contains(const IPAddr& addr) const
@ -2768,7 +2777,9 @@ void TableVal::InitDefaultFunc(detail::Frame* f)
if ( def_val )
return;
const auto& def_attr = GetAttr(detail::ATTR_DEFAULT);
auto def_attr = GetAttr(detail::ATTR_DEFAULT);
if ( ! def_attr )
def_attr = GetAttr(detail::ATTR_DEFAULT_INSERT);
if ( ! def_attr )
return;