diff --git a/src/Val.cc b/src/Val.cc index 08de37121c..eab52ef7db 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -380,6 +380,73 @@ bool Val::WouldOverflow(const BroType* from_type, const BroType* to_type, const return false; } +TableVal* Val::GetRecordFields() + { + TableVal* fields = new TableVal(internal_type("record_field_table")->AsTableType()); + + auto t = Type(); + + if ( t->Tag() != TYPE_RECORD && t->Tag() != TYPE_TYPE ) + { + reporter->Error("non-record value/type passed to record_fields"); + return fields; + } + + RecordType* rt = nullptr; + RecordVal* rv = nullptr; + + if ( t->Tag() == TYPE_RECORD ) + { + rt = t->AsRecordType(); + rv = AsRecordVal(); + } + else + { + t = t->AsTypeType()->Type(); + + if ( t->Tag() != TYPE_RECORD ) + { + reporter->Error("non-record value/type passed to record_fields"); + return fields; + } + + rt = t->AsRecordType(); + } + + for ( int i = 0; i < rt->NumFields(); ++i ) + { + BroType* ft = rt->FieldType(i); + TypeDecl* fd = rt->FieldDecl(i); + Val* fv = nullptr; + + if ( rv ) + fv = rv->Lookup(i); + + if ( fv ) + ::Ref(fv); + + bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0); + + RecordVal* nr = new RecordVal(internal_type("record_field")->AsRecordType()); + + if ( ft->Tag() == TYPE_RECORD ) + nr->Assign(0, new StringVal("record " + ft->GetName())); + else + nr->Assign(0, new StringVal(type_name(ft->Tag()))); + + nr->Assign(1, val_mgr->GetBool(logged)); + nr->Assign(2, fv); + nr->Assign(3, rt->FieldDefault(i)); + + Val* field_name = new StringVal(rt->FieldName(i)); + fields->Assign(field_name, nr); + Unref(field_name); + } + + return fields; + + } + IntervalVal::IntervalVal(double quantity, double units) : Val(quantity * units, TYPE_INTERVAL) { diff --git a/src/Val.h b/src/Val.h index 8e909f1a0c..b5fa130dd5 100644 --- a/src/Val.h +++ b/src/Val.h @@ -347,6 +347,8 @@ public: static bool WouldOverflow(const BroType* from_type, const BroType* to_type, const Val* val); + TableVal* GetRecordFields(); + protected: friend class EnumType; diff --git a/src/zeek.bif b/src/zeek.bif index da11a18681..afd7e26083 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -1981,68 +1981,7 @@ function lookup_ID%(id: string%) : any ## Returns: A table that describes the fields of a record. function record_fields%(rec: any%): record_field_table %{ - TableVal* fields = new TableVal(record_field_table); - - auto t = rec->Type(); - - if ( t->Tag() != TYPE_RECORD && t->Tag() != TYPE_TYPE ) - { - reporter->Error("non-record value/type passed to record_fields"); - return fields; - } - - RecordType* rt = nullptr; - RecordVal* rv = nullptr; - - if ( t->Tag() == TYPE_RECORD ) - { - rt = t->AsRecordType(); - rv = rec->AsRecordVal(); - } - else - { - t = t->AsTypeType()->Type(); - - if ( t->Tag() != TYPE_RECORD ) - { - reporter->Error("non-record value/type passed to record_fields"); - return fields; - } - - rt = t->AsRecordType(); - } - - for ( int i = 0; i < rt->NumFields(); ++i ) - { - BroType* ft = rt->FieldType(i); - TypeDecl* fd = rt->FieldDecl(i); - Val* fv = nullptr; - - if ( rv ) - fv = rv->Lookup(i); - - if ( fv ) - Ref(fv); - - bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0); - - RecordVal* nr = new RecordVal(record_field); - - if ( ft->Tag() == TYPE_RECORD ) - nr->Assign(0, new StringVal("record " + ft->GetName())); - else - nr->Assign(0, new StringVal(type_name(ft->Tag()))); - - nr->Assign(1, val_mgr->GetBool(logged)); - nr->Assign(2, fv); - nr->Assign(3, rt->FieldDefault(i)); - - Val* field_name = new StringVal(rt->FieldName(i)); - fields->Assign(field_name, nr); - Unref(field_name); - } - - return fields; + return rec->GetRecordFields(); %} ## Enables detailed collection of profiling statistics. Statistics include