mirror of
https://github.com/zeek/zeek.git
synced 2025-10-06 16:48:19 +00:00
Allow record_fields() string arguments that name a record type
This commit is contained in:
parent
295c28b48e
commit
63fe835acf
7 changed files with 92 additions and 35 deletions
37
src/Type.cc
37
src/Type.cc
|
@ -824,6 +824,43 @@ void RecordType::DescribeReST(ODesc* d, bool roles_only) const
|
||||||
d->PopType(this);
|
d->PopType(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TableVal* RecordType::GetRecordFieldsVal(const RecordVal* rv) const
|
||||||
|
{
|
||||||
|
auto rval = new TableVal(internal_type("record_field_table")->AsTableType());
|
||||||
|
|
||||||
|
for ( int i = 0; i < NumFields(); ++i )
|
||||||
|
{
|
||||||
|
const BroType* ft = FieldType(i);
|
||||||
|
const TypeDecl* fd = 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, FieldDefault(i));
|
||||||
|
|
||||||
|
Val* field_name = new StringVal(FieldName(i));
|
||||||
|
rval->Assign(field_name, nr);
|
||||||
|
Unref(field_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
const char* RecordType::AddFields(type_decl_list* others, attr_list* attr)
|
const char* RecordType::AddFields(type_decl_list* others, attr_list* attr)
|
||||||
{
|
{
|
||||||
assert(types);
|
assert(types);
|
||||||
|
|
|
@ -75,6 +75,7 @@ class VectorType;
|
||||||
class TypeType;
|
class TypeType;
|
||||||
class OpaqueType;
|
class OpaqueType;
|
||||||
class EnumVal;
|
class EnumVal;
|
||||||
|
class TableVal;
|
||||||
|
|
||||||
const int DOES_NOT_MATCH_INDEX = 0;
|
const int DOES_NOT_MATCH_INDEX = 0;
|
||||||
const int MATCHES_INDEX_SCALAR = 1;
|
const int MATCHES_INDEX_SCALAR = 1;
|
||||||
|
@ -483,6 +484,13 @@ public:
|
||||||
|
|
||||||
int NumFields() const { return num_fields; }
|
int NumFields() const { return num_fields; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a "record_field_table" value for introspection purposes.
|
||||||
|
* @param rv an optional record value, if given the values of
|
||||||
|
* all fields will be provided in the returned table.
|
||||||
|
*/
|
||||||
|
TableVal* GetRecordFieldsVal(const RecordVal* rv = nullptr) const;
|
||||||
|
|
||||||
// Returns 0 if all is ok, otherwise a pointer to an error message.
|
// Returns 0 if all is ok, otherwise a pointer to an error message.
|
||||||
// Takes ownership of list.
|
// Takes ownership of list.
|
||||||
const char* AddFields(type_decl_list* types, attr_list* attr);
|
const char* AddFields(type_decl_list* types, attr_list* attr);
|
||||||
|
|
43
src/Val.cc
43
src/Val.cc
|
@ -396,14 +396,12 @@ bool Val::WouldOverflow(const BroType* from_type, const BroType* to_type, const
|
||||||
|
|
||||||
TableVal* Val::GetRecordFields()
|
TableVal* Val::GetRecordFields()
|
||||||
{
|
{
|
||||||
TableVal* fields = new TableVal(internal_type("record_field_table")->AsTableType());
|
|
||||||
|
|
||||||
auto t = Type();
|
auto t = Type();
|
||||||
|
|
||||||
if ( t->Tag() != TYPE_RECORD && t->Tag() != TYPE_TYPE )
|
if ( t->Tag() != TYPE_RECORD && t->Tag() != TYPE_TYPE )
|
||||||
{
|
{
|
||||||
reporter->Error("non-record value/type passed to record_fields");
|
reporter->Error("non-record value/type passed to record_fields");
|
||||||
return fields;
|
return new TableVal(internal_type("record_field_table")->AsTableType());
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordType* rt = nullptr;
|
RecordType* rt = nullptr;
|
||||||
|
@ -421,43 +419,13 @@ TableVal* Val::GetRecordFields()
|
||||||
if ( t->Tag() != TYPE_RECORD )
|
if ( t->Tag() != TYPE_RECORD )
|
||||||
{
|
{
|
||||||
reporter->Error("non-record value/type passed to record_fields");
|
reporter->Error("non-record value/type passed to record_fields");
|
||||||
return fields;
|
return new TableVal(internal_type("record_field_table")->AsTableType());
|
||||||
}
|
}
|
||||||
|
|
||||||
rt = t->AsRecordType();
|
rt = t->AsRecordType();
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( int i = 0; i < rt->NumFields(); ++i )
|
return rt->GetRecordFieldsVal(rv);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is a static method in this file to avoid including json.hpp in Val.h since it's huge.
|
// This is a static method in this file to avoid including json.hpp in Val.h since it's huge.
|
||||||
|
@ -2665,6 +2633,11 @@ RecordVal* RecordVal::CoerceTo(RecordType* t, bool allow_orphaning)
|
||||||
return CoerceTo(t, 0, allow_orphaning);
|
return CoerceTo(t, 0, allow_orphaning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TableVal* RecordVal::GetRecordFieldsVal() const
|
||||||
|
{
|
||||||
|
return Type()->AsRecordType()->GetRecordFieldsVal(this);
|
||||||
|
}
|
||||||
|
|
||||||
void RecordVal::Describe(ODesc* d) const
|
void RecordVal::Describe(ODesc* d) const
|
||||||
{
|
{
|
||||||
const val_list* vl = AsRecord();
|
const val_list* vl = AsRecord();
|
||||||
|
|
|
@ -960,6 +960,11 @@ public:
|
||||||
|
|
||||||
void Describe(ODesc* d) const override;
|
void Describe(ODesc* d) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a "record_field_table" value for introspection purposes.
|
||||||
|
*/
|
||||||
|
TableVal* GetRecordFieldsVal() const;
|
||||||
|
|
||||||
// This is an experiment to associate a BroObj within the
|
// This is an experiment to associate a BroObj within the
|
||||||
// event engine to a record value in bro script.
|
// event engine to a record value in bro script.
|
||||||
void SetOrigin(BroObj* o) { origin = o; }
|
void SetOrigin(BroObj* o) { origin = o; }
|
||||||
|
|
13
src/zeek.bif
13
src/zeek.bif
|
@ -1994,6 +1994,19 @@ function lookup_ID%(id: string%) : any
|
||||||
## Returns: A table that describes the fields of a record.
|
## Returns: A table that describes the fields of a record.
|
||||||
function record_fields%(rec: any%): record_field_table
|
function record_fields%(rec: any%): record_field_table
|
||||||
%{
|
%{
|
||||||
|
if ( rec->Type()->Tag() == TYPE_STRING )
|
||||||
|
{
|
||||||
|
auto id = global_scope()->Lookup(rec->AsStringVal()->ToStdString());
|
||||||
|
|
||||||
|
if ( ! id || ! id->AsType() || id->AsType()->Tag() != TYPE_RECORD )
|
||||||
|
{
|
||||||
|
reporter->Error("record_fields string argument does not name a record type");
|
||||||
|
return new TableVal(internal_type("record_field_table")->AsTableType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return id->AsType()->AsRecordType()->GetRecordFieldsVal();
|
||||||
|
}
|
||||||
|
|
||||||
return rec->GetRecordFields();
|
return rec->GetRecordFields();
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -31,3 +31,20 @@ F
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
[myfield] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=Bar],
|
||||||
|
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[a] = [type_name=bool, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[m] = [type_name=record myrec, log=F, value=<uninitialized>, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
{
|
||||||
|
[b] = [type_name=string, log=F, value=<uninitialized>, default_val=Foo],
|
||||||
|
[c] = [type_name=double, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[e] = [type_name=any, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[a] = [type_name=count, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||||
|
[d] = [type_name=string, log=T, value=<uninitialized>, default_val=<uninitialized>]
|
||||||
|
}
|
||||||
|
|
|
@ -43,4 +43,8 @@ event zeek_init()
|
||||||
print t;
|
print t;
|
||||||
t = record_fields(x$e);
|
t = record_fields(x$e);
|
||||||
print t;
|
print t;
|
||||||
|
|
||||||
|
print record_fields("myrec");
|
||||||
|
print record_fields("tt");
|
||||||
|
print record_fields("r");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue