Allow iterating over bif functions with result type vector of any.

This changes the internal type that is used to signal that a vector
is unspecified from any to void.

I tried to verify that the behavior of Bro is still the same. After
a lot of playing around, I think everything still should worl as before.

However, it might be good for someone to take a look at this.

addresses BIT-1144
This commit is contained in:
Bernhard Amann 2014-02-25 15:30:29 -08:00
parent 58eb9bbf28
commit b3bd509b3f
11 changed files with 66 additions and 7 deletions

View file

@ -39,6 +39,13 @@ type count_set: set[count];
## directly and then remove this alias. ## directly and then remove this alias.
type index_vec: vector of count; type index_vec: vector of count;
## A vector of any, used by some builtin functions to store a list of varying types.
##
## .. todo:: We need this type definition only for declaring builtin functions
## via ``bifcl``. We should extend ``bifcl`` to understand composite types
## directly and then remove this alias.
type any_vec: vector of any;
## A vector of strings. ## A vector of strings.
## ##
## .. todo:: We need this type definition only for declaring builtin functions ## .. todo:: We need this type definition only for declaring builtin functions

View file

@ -3819,7 +3819,9 @@ VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list,
if ( constructor_list->Exprs().length() == 0 ) if ( constructor_list->Exprs().length() == 0 )
{ {
// vector(). // vector().
SetType(new ::VectorType(base_type(TYPE_ANY))); // By default, assign VOID type here. A vector with
// void type set is seen as an unspecified vector.
SetType(new ::VectorType(base_type(TYPE_VOID)));
return; return;
} }

View file

@ -1626,6 +1626,21 @@ VectorType::~VectorType()
Unref(yield_type); Unref(yield_type);
} }
BroType* VectorType::YieldType()
{
// cheat around the fact that we use void internally to
// mark a vector as being unspecified
if ( IsUnspecifiedVector() )
{
BroType* ret = ::base_type(TYPE_ANY);
Unref(ret); // unref, because this won't be held by anyone.
assert(ret);
return ret;
}
return yield_type;
}
int VectorType::MatchesIndex(ListExpr*& index) const int VectorType::MatchesIndex(ListExpr*& index) const
{ {
expr_list& el = index->Exprs(); expr_list& el = index->Exprs();
@ -1645,7 +1660,7 @@ int VectorType::MatchesIndex(ListExpr*& index) const
bool VectorType::IsUnspecifiedVector() const bool VectorType::IsUnspecifiedVector() const
{ {
return yield_type->Tag() == TYPE_ANY; return yield_type->Tag() == TYPE_VOID;
} }
IMPLEMENT_SERIAL(VectorType, SER_VECTOR_TYPE); IMPLEMENT_SERIAL(VectorType, SER_VECTOR_TYPE);

View file

@ -572,7 +572,7 @@ class VectorType : public BroType {
public: public:
VectorType(BroType* t); VectorType(BroType* t);
virtual ~VectorType(); virtual ~VectorType();
BroType* YieldType() { return yield_type; } BroType* YieldType();
int MatchesIndex(ListExpr*& index) const; int MatchesIndex(ListExpr*& index) const;

View file

@ -2976,7 +2976,9 @@ VectorVal::~VectorVal()
bool VectorVal::Assign(unsigned int index, Val* element, Opcode op) bool VectorVal::Assign(unsigned int index, Val* element, Opcode op)
{ {
if ( element && if ( element &&
! same_type(element->Type(), vector_type->YieldType(), 0) ) ! same_type(element->Type(), vector_type->YieldType(), 0) &&
// if we are unspecified, you can assign anything to us.
! vector_type->IsUnspecifiedVector() )
{ {
Unref(element); Unref(element);
return false; return false;
@ -3139,7 +3141,7 @@ bool VectorVal::DoUnserialize(UnserialInfo* info)
for ( int i = 0; i < len; ++i ) for ( int i = 0; i < len; ++i )
{ {
Val* v; Val* v;
UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY)); UNSERIALIZE_OPTIONAL(v, Val::Unserialize(info, TYPE_ANY)); // accept any type
Assign(i, v); Assign(i, v);
} }

View file

@ -656,6 +656,8 @@ protected:
DECLARE_SERIAL(PatternVal); DECLARE_SERIAL(PatternVal);
}; };
// ListVals are mainly used to index tables that have more than one
// element in their index.
class ListVal : public Val { class ListVal : public Val {
public: public:
ListVal(TypeTag t); ListVal(TypeTag t);

View file

@ -49,7 +49,7 @@ function topk_add%(handle: opaque of topk, value: any%): any
## ##
## .. bro:see:: topk_init topk_add topk_count topk_epsilon ## .. bro:see:: topk_init topk_add topk_count topk_epsilon
## topk_size topk_sum topk_merge topk_merge_prune ## topk_size topk_sum topk_merge topk_merge_prune
function topk_get_top%(handle: opaque of topk, k: count%): any function topk_get_top%(handle: opaque of topk, k: count%): any_vec
%{ %{
assert(handle); assert(handle);
probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle; probabilistic::TopkVal* h = (probabilistic::TopkVal*) handle;

View file

@ -79,3 +79,12 @@
0 0
8 8
0 0
0, c
1, e
2, d
0, c
1, e
2, d
0, c
1, e
2, d

View file

@ -0,0 +1 @@
[5, Hi, 127.0.0.1]

View file

@ -148,7 +148,17 @@ event bro_init()
print topk_count(k3, "d"); print topk_count(k3, "d");
print topk_epsilon(k3, "d"); print topk_epsilon(k3, "d");
local styped: vector of count;
styped = topk_get_top(k3, 3);
for ( i in styped )
print i, styped[i];
local anytyped: vector of any;
anytyped = topk_get_top(k3, 3);
for ( i in anytyped )
print i, anytyped[i];
local suntyped = topk_get_top(k3, 3);
for ( i in suntyped )
print i, suntyped[i];
} }

View file

@ -0,0 +1,11 @@
# @TEST-EXEC: bro -b %INPUT >output 2>&1
# @TEST-EXEC: btest-diff output
# Test assignment behavior of unspecified vectors
local a = vector();
a[0] = 5;
a[1] = "Hi";
a[2] = 127.0.0.1;
print a;