mirror of
https://github.com/zeek/zeek.git
synced 2025-10-03 07:08:19 +00:00
New BiF record_field_vals() that returns the fields of a record in a
table with meta-information. Example: type r: record { a: count; b: string &default="Foo"; c: double &optional; d: string &log; }; event bro_init() { local x: r = [$a=42, $d="Bar"]; print record_fields(x); } This prints: { [a] = [type_name=record, log=F, value=42, default_val=<uninitialized>] [b] = [type_name=record, log=F, value=<uninitialized>, default_val=Foo], [c] = [type_name=record, log=F, value=<uninitialized>, default_val=<uninitialized>], [d] = [type_name=record, log=T, value=Bar, default_val=<uninitialized>], } This is one more step in Seth's quest for full inspection support. :-)
This commit is contained in:
parent
cdd8827cc4
commit
8bacb6eb3d
9 changed files with 99 additions and 9 deletions
|
@ -183,6 +183,17 @@ type script_id: record {
|
|||
value: any &optional;
|
||||
};
|
||||
|
||||
type id_table: table[string] of script_id;
|
||||
|
||||
type record_field: record {
|
||||
type_name: string;
|
||||
log: bool;
|
||||
value: any &optional;
|
||||
default_val: any &optional;
|
||||
};
|
||||
|
||||
type record_field_table: table[string] of record_field;
|
||||
|
||||
# The following two variables are defined here until the core is not
|
||||
# dependent on the names remaining as they are now.
|
||||
## This is the list of capture filters indexed by some user-definable ID.
|
||||
|
@ -190,8 +201,6 @@ global capture_filters: table[string] of string &redef;
|
|||
## This is the list of restriction filters indexed by some user-definable ID.
|
||||
global restrict_filters: table[string] of string &redef;
|
||||
|
||||
type id_table: table[string] of script_id;
|
||||
|
||||
# {precompile,install}_pcap_filter identify the filter by IDs
|
||||
type PcapFilterID: enum { None };
|
||||
|
||||
|
|
|
@ -248,6 +248,8 @@ int record_all_packets;
|
|||
|
||||
RecordType* script_id;
|
||||
TableType* id_table;
|
||||
RecordType* record_field;
|
||||
TableType* record_field_table;
|
||||
|
||||
StringVal* cmd_line_bpf_filter;
|
||||
|
||||
|
@ -550,4 +552,6 @@ void init_net_var()
|
|||
|
||||
script_id = internal_type("script_id")->AsRecordType();
|
||||
id_table = internal_type("id_table")->AsTableType();
|
||||
record_field = internal_type("record_field")->AsRecordType();
|
||||
record_field_table = internal_type("record_field_table")->AsTableType();
|
||||
}
|
||||
|
|
|
@ -251,6 +251,8 @@ extern int record_all_packets;
|
|||
|
||||
extern RecordType* script_id;
|
||||
extern TableType* id_table;
|
||||
extern RecordType* record_field;
|
||||
extern TableType* record_field_table;
|
||||
|
||||
extern StringVal* cmd_line_bpf_filter;
|
||||
|
||||
|
|
12
src/Type.cc
12
src/Type.cc
|
@ -987,6 +987,18 @@ BroType* RecordType::FieldType(int field) const
|
|||
}
|
||||
}
|
||||
|
||||
Val* RecordType::FieldDefault(int field) const
|
||||
{
|
||||
const TypeDecl* td = FieldDecl(field);
|
||||
|
||||
if ( ! td->attrs )
|
||||
return false;
|
||||
|
||||
const Attr* def_attr = td->attrs->FindAttr(ATTR_DEFAULT);
|
||||
|
||||
return def_attr ? def_attr->AttrExpr()->Eval(0) : 0;
|
||||
}
|
||||
|
||||
int RecordType::FieldOffset(const char* field) const
|
||||
{
|
||||
if ( types )
|
||||
|
|
|
@ -448,6 +448,7 @@ public:
|
|||
int HasField(const char* field) const;
|
||||
BroType* FieldType(const char* field) const;
|
||||
BroType* FieldType(int field) const;
|
||||
Val* FieldDefault(int field) const; // Ref's the returned value; 0 if none.
|
||||
|
||||
// A field's offset is its position in the type_decl_list,
|
||||
// starting at 0. Returns negative if the field doesn't exist.
|
||||
|
|
|
@ -2935,11 +2935,7 @@ Val* RecordVal::LookupWithDefault(int field) const
|
|||
if ( val )
|
||||
return val->Ref();
|
||||
|
||||
// Check for &default.
|
||||
const Attr* def_attr =
|
||||
record_type->FieldDecl(field)->attrs->FindAttr(ATTR_DEFAULT);
|
||||
|
||||
return def_attr ? def_attr->AttrExpr()->Eval(0) : 0;
|
||||
return record_type->FieldDefault(field);
|
||||
}
|
||||
|
||||
RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const
|
||||
|
|
38
src/bro.bif
38
src/bro.bif
|
@ -1657,6 +1657,44 @@ function global_ids%(%): id_table
|
|||
return ids;
|
||||
%}
|
||||
|
||||
function record_fields%(rec: any%): record_field_table
|
||||
%{
|
||||
TableVal* fields = new TableVal(record_field_table);
|
||||
|
||||
RecordVal* rv = rec->AsRecordVal();
|
||||
RecordType* rt = rv->Type()->AsRecordType();
|
||||
|
||||
if ( rt->Tag() != TYPE_RECORD )
|
||||
{
|
||||
reporter->Error("non-record passed to record_fields");
|
||||
return fields;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < rt->NumFields(); ++i )
|
||||
{
|
||||
BroType* ft = rt->FieldType(i);
|
||||
TypeDecl* fd = rt->FieldDecl(i);
|
||||
Val* fv = rv->Lookup(i);
|
||||
|
||||
if ( fv )
|
||||
Ref(fv);
|
||||
|
||||
bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0);
|
||||
|
||||
RecordVal* nr = new RecordVal(record_field);
|
||||
nr->Assign(0, new StringVal(type_name(rt->Tag())));
|
||||
nr->Assign(1, new Val(logged, TYPE_BOOL));
|
||||
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;
|
||||
%}
|
||||
|
||||
%%{
|
||||
#include "Anon.h"
|
||||
%%}
|
||||
|
|
8
testing/btest/Baseline/bifs.records_fields/out
Normal file
8
testing/btest/Baseline/bifs.records_fields/out
Normal file
|
@ -0,0 +1,8 @@
|
|||
[a=42, b=<uninitialized>, c=<uninitialized>, d=Bar]
|
||||
{
|
||||
[b] = [type_name=record, log=F, value=<uninitialized>, default_val=Foo],
|
||||
[d] = [type_name=record, log=T, value=Bar, default_val=<uninitialized>],
|
||||
[c] = [type_name=record, log=F, value=<uninitialized>, default_val=<uninitialized>],
|
||||
[a] = [type_name=record, log=F, value=42, default_val=<uninitialized>]
|
||||
}
|
||||
F
|
20
testing/btest/bifs/records_fields.bro
Normal file
20
testing/btest/bifs/records_fields.bro
Normal file
|
@ -0,0 +1,20 @@
|
|||
#
|
||||
# @TEST-EXEC: bro %INPUT >out
|
||||
# @TEST-EXEC: btest-diff out
|
||||
|
||||
type r: record {
|
||||
a: count;
|
||||
b: string &default="Foo";
|
||||
c: double &optional;
|
||||
d: string &log;
|
||||
};
|
||||
|
||||
event bro_init()
|
||||
{
|
||||
local x: r = [$a=42, $d="Bar"];
|
||||
print x;
|
||||
local t: record_field_table;
|
||||
t = record_fields(x);
|
||||
print t;
|
||||
print t["c"]?$value;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue