Remove BroValUnion by hoisting underlying Val subclass values into subclasses

This commit is contained in:
Vern Paxson 2020-11-10 15:18:54 -08:00 committed by Tim Wojtulewicz
parent 49ca8e2163
commit 7f92a573d2
29 changed files with 632 additions and 512 deletions

@ -1 +1 @@
Subproject commit 624e5525f54d4a15c35687d42301045f1769d3e1 Subproject commit e72531a9efe4e6edb1589cb07ae41053023d0612

View file

@ -101,7 +101,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0,
case TYPE_INTERNAL_INT: case TYPE_INTERNAL_INT:
{ {
bro_int_t* kp = AlignAndPadType<bro_int_t>(kp0); bro_int_t* kp = AlignAndPadType<bro_int_t>(kp0);
*kp = v->ForceAsInt(); *kp = v->AsInt();
kp1 = reinterpret_cast<char*>(kp+1); kp1 = reinterpret_cast<char*>(kp+1);
} }
break; break;
@ -109,7 +109,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0,
case TYPE_INTERNAL_UNSIGNED: case TYPE_INTERNAL_UNSIGNED:
{ {
bro_uint_t* kp = AlignAndPadType<bro_uint_t>(kp0); bro_uint_t* kp = AlignAndPadType<bro_uint_t>(kp0);
*kp = v->ForceAsUInt(); *kp = v->AsCount();
kp1 = reinterpret_cast<char*>(kp+1); kp1 = reinterpret_cast<char*>(kp+1);
} }
break; break;
@ -407,8 +407,10 @@ std::unique_ptr<HashKey> CompositeHash::ComputeSingletonHash(const Val* v, bool
switch ( singleton_tag ) { switch ( singleton_tag ) {
case TYPE_INTERNAL_INT: case TYPE_INTERNAL_INT:
return std::make_unique<HashKey>(v->AsInt());
case TYPE_INTERNAL_UNSIGNED: case TYPE_INTERNAL_UNSIGNED:
return std::make_unique<HashKey>(v->ForceAsInt()); return std::make_unique<HashKey>(v->AsCount());
case TYPE_INTERNAL_ADDR: case TYPE_INTERNAL_ADDR:
return v->AsAddr().MakeHashKey(); return v->AsAddr().MakeHashKey();
@ -855,7 +857,7 @@ const char* CompositeHash::RecoverOneVal(
if ( ! f ) if ( ! f )
reporter->InternalError("failed to look up unique function id %" PRIu32 " in CompositeHash::RecoverOneVal()", *kp); reporter->InternalError("failed to look up unique function id %" PRIu32 " in CompositeHash::RecoverOneVal()", *kp);
*pval = make_intrusive<Val>(f); *pval = make_intrusive<FuncVal>(f);
const auto& pvt = (*pval)->GetType(); const auto& pvt = (*pval)->GetType();
if ( ! pvt ) if ( ! pvt )

View file

@ -434,7 +434,7 @@ void Connection::AppendAddl(const char* str)
{ {
const auto& cv = ConnVal(); const auto& cv = ConnVal();
const char* old = cv->GetField(6)->AsString()->CheckString(); const char* old = cv->GetStringField(6)->CheckString();
const char* format = *old ? "%s %s" : "%s%s"; const char* format = *old ? "%s %s" : "%s%s";
cv->Assign(6, make_intrusive<StringVal>(util::fmt(format, old, str))); cv->Assign(6, make_intrusive<StringVal>(util::fmt(format, old, str)));

View file

@ -1853,7 +1853,7 @@ ValPtr EqExpr::Fold(Val* v1, Val* v2) const
{ {
if ( op1->GetType()->Tag() == TYPE_PATTERN ) if ( op1->GetType()->Tag() == TYPE_PATTERN )
{ {
RE_Matcher* re = v1->AsPattern(); auto re = dynamic_cast<PatternVal*>(v1);
const String* s = v2->AsString(); const String* s = v2->AsString();
if ( tag == EXPR_EQ ) if ( tag == EXPR_EQ )
return val_mgr->Bool(re->MatchExactly(s)); return val_mgr->Bool(re->MatchExactly(s));
@ -4151,7 +4151,7 @@ ValPtr InExpr::Fold(Val* v1, Val* v2) const
{ {
if ( v1->GetType()->Tag() == TYPE_PATTERN ) if ( v1->GetType()->Tag() == TYPE_PATTERN )
{ {
RE_Matcher* re = v1->AsPattern(); auto re = dynamic_cast<PatternVal*>(v1);
const String* s = v2->AsString(); const String* s = v2->AsString();
return val_mgr->Bool(re->MatchAnywhere(s) != 0); return val_mgr->Bool(re->MatchAnywhere(s) != 0);
} }
@ -4412,7 +4412,7 @@ LambdaExpr::LambdaExpr(std::unique_ptr<function_ingredients> arg_ing,
// Update lamb's name // Update lamb's name
dummy_func->SetName(my_name.c_str()); dummy_func->SetName(my_name.c_str());
auto v = make_intrusive<Val>(std::move(dummy_func)); auto v = make_intrusive<FuncVal>(std::move(dummy_func));
id->SetVal(std::move(v)); id->SetVal(std::move(v));
id->SetType(ingredients->id->GetType()); id->SetType(ingredients->id->GetType());
id->SetConst(); id->SetConst();
@ -4502,7 +4502,7 @@ ValPtr LambdaExpr::Eval(Frame* f) const
// Allows for lookups by the receiver. // Allows for lookups by the receiver.
lamb->SetName(my_name.c_str()); lamb->SetName(my_name.c_str());
return make_intrusive<Val>(std::move(lamb)); return make_intrusive<FuncVal>(std::move(lamb));
} }
void LambdaExpr::ExprDescribe(ODesc* d) const void LambdaExpr::ExprDescribe(ODesc* d) const

View file

@ -331,7 +331,7 @@ void File::RaiseOpenEvent()
return; return;
FilePtr bf{NewRef{}, this}; FilePtr bf{NewRef{}, this};
auto* event = new Event(::file_opened, {make_intrusive<Val>(std::move(bf))}); auto* event = new Event(::file_opened, {make_intrusive<FileVal>(std::move(bf))});
event_mgr.Dispatch(event, true); event_mgr.Dispatch(event, true);
} }

View file

@ -702,7 +702,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name,
reporter->InternalError("built-in function %s multiply defined", Name()); reporter->InternalError("built-in function %s multiply defined", Name());
type = id->GetType<FuncType>(); type = id->GetType<FuncType>();
id->SetVal(make_intrusive<Val>(IntrusivePtr{NewRef{}, this})); id->SetVal(make_intrusive<FuncVal>(IntrusivePtr{NewRef{}, this}));
id->SetConst(); id->SetConst();
} }

View file

@ -87,7 +87,7 @@ FuncPtr id::find_func(std::string_view name)
reporter->InternalError("Expected variable '%s' to be a function", reporter->InternalError("Expected variable '%s' to be a function",
std::string(name).data()); std::string(name).data());
return v->AsFuncPtr(); return dynamic_cast<FuncVal*>(v.get())->AsFuncPtr();
} }
void id::detail::init_types() void id::detail::init_types()
@ -162,17 +162,18 @@ void ID::SetVal(ValPtr v)
type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT ) type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT )
{ {
EventHandler* handler = event_registry->Lookup(name); EventHandler* handler = event_registry->Lookup(name);
auto func = dynamic_cast<FuncVal*>(val.get())->AsFuncPtr();
if ( ! handler ) if ( ! handler )
{ {
handler = new EventHandler(name); handler = new EventHandler(name);
handler->SetFunc(val->AsFuncPtr()); handler->SetFunc(func);
event_registry->Register(handler); event_registry->Register(handler);
} }
else else
{ {
// Otherwise, internally defined events cannot // Otherwise, internally defined events cannot
// have local handler. // have local handler.
handler->SetFunc(val->AsFuncPtr()); handler->SetFunc(func);
} }
} }
} }

View file

@ -369,11 +369,11 @@ bool Reporter::PermitFlowWeird(const char* name,
bool Reporter::PermitExpiredConnWeird(const char* name, const RecordVal& conn_id) bool Reporter::PermitExpiredConnWeird(const char* name, const RecordVal& conn_id)
{ {
auto conn_tuple = std::make_tuple(conn_id.GetField("orig_h")->AsAddr(), auto conn_tuple = std::make_tuple(conn_id.GetAddrField("orig_h"),
conn_id.GetField("resp_h")->AsAddr(), conn_id.GetAddrField("resp_h"),
conn_id.GetField("orig_p")->AsPortVal()->Port(), conn_id.GetPortValField("orig_p")->Port(),
conn_id.GetField("resp_p")->AsPortVal()->Port(), conn_id.GetPortValField("resp_p")->Port(),
conn_id.GetField("resp_p")->AsPortVal()->PortType()); conn_id.GetPortValField("resp_p")->PortType());
auto& map = expired_conn_weird_state[conn_tuple]; auto& map = expired_conn_weird_state[conn_tuple];

View file

@ -318,7 +318,7 @@ Connection* NetSessions::FindConnection(Val* v)
return nullptr; return nullptr;
RecordType* vr = vt->AsRecordType(); RecordType* vr = vt->AsRecordType();
auto vl = v->AsRecord(); auto vl = dynamic_cast<RecordVal*>(v);
int orig_h, orig_p; // indices into record's value list int orig_h, orig_p; // indices into record's value list
int resp_h, resp_p; int resp_h, resp_p;
@ -346,11 +346,11 @@ Connection* NetSessions::FindConnection(Val* v)
// types, too. // types, too.
} }
const IPAddr& orig_addr = (*vl)[orig_h]->AsAddr(); const IPAddr& orig_addr = vl->GetAddrField(orig_h);
const IPAddr& resp_addr = (*vl)[resp_h]->AsAddr(); const IPAddr& resp_addr = vl->GetAddrField(resp_h);
PortVal* orig_portv = (*vl)[orig_p]->AsPortVal(); const PortVal* orig_portv = vl->GetPortValField(orig_p);
PortVal* resp_portv = (*vl)[resp_p]->AsPortVal(); const PortVal* resp_portv = vl->GetPortValField(resp_p);
ConnID id; ConnID id;

View file

@ -109,19 +109,19 @@ Substring::Vec* Substring::VecFromPolicy(VectorVal* vec)
if ( ! v ) if ( ! v )
continue; continue;
const String* str = v->AsRecordVal()->GetField(0)->AsString(); const String* str = v->AsRecordVal()->GetStringField(0);
auto* substr = new Substring(*str); auto* substr = new Substring(*str);
const VectorVal* aligns = v->AsRecordVal()->GetField(1)->AsVectorVal(); const VectorVal* aligns = v->AsRecordVal()->GetField(1)->AsVectorVal();
for ( unsigned int j = 1; j <= aligns->Size(); ++j ) for ( unsigned int j = 1; j <= aligns->Size(); ++j )
{ {
const RecordVal* align = aligns->AsVectorVal()->At(j)->AsRecordVal(); const RecordVal* align = aligns->AsVectorVal()->At(j)->AsRecordVal();
const String* str = align->GetField(0)->AsString(); const String* str = align->GetStringField(0);
int index = align->GetField(1)->AsCount(); int index = align->GetCountField(1);
substr->AddAlignment(str, index); substr->AddAlignment(str, index);
} }
bool new_alignment = v->AsRecordVal()->GetField(2)->AsBool(); bool new_alignment = v->AsRecordVal()->GetBoolField(2);
substr->MarkNewAlignment(new_alignment); substr->MarkNewAlignment(new_alignment);
result->push_back(substr); result->push_back(substr);

View file

@ -324,7 +324,7 @@ void ProfileLogger::Log()
if ( profiling_update ) if ( profiling_update )
{ {
event_mgr.Dispatch(new Event(profiling_update, { event_mgr.Dispatch(new Event(profiling_update, {
make_intrusive<Val>(IntrusivePtr{NewRef{}, file}), make_intrusive<FileVal>(IntrusivePtr{NewRef{}, file}),
val_mgr->Bool(expensive), val_mgr->Bool(expensive),
})); }));
} }

File diff suppressed because it is too large Load diff

430
src/Val.h
View file

@ -88,67 +88,21 @@ using TableValPtr = IntrusivePtr<TableVal>;
using ValPtr = IntrusivePtr<Val>; using ValPtr = IntrusivePtr<Val>;
using VectorValPtr = IntrusivePtr<VectorVal>; using VectorValPtr = IntrusivePtr<VectorVal>;
union BroValUnion {
// Used for bool, int, enum.
bro_int_t int_val;
// Used for count, counter, port.
bro_uint_t uint_val;
// Used for addr
IPAddr* addr_val;
// Used for subnet
IPPrefix* subnet_val;
// Used for double, time, interval.
double double_val;
String* string_val;
Func* func_val;
File* file_val;
RE_Matcher* re_val;
PDict<TableEntryVal>* table_val;
std::vector<ValPtr>* record_val;
std::vector<ValPtr>* vector_val;
BroValUnion() = default;
constexpr BroValUnion(bro_int_t value) noexcept
: int_val(value) {}
constexpr BroValUnion(bro_uint_t value) noexcept
: uint_val(value) {}
constexpr BroValUnion(IPAddr* value) noexcept
: addr_val(value) {}
constexpr BroValUnion(IPPrefix* value) noexcept
: subnet_val(value) {}
constexpr BroValUnion(double value) noexcept
: double_val(value) {}
constexpr BroValUnion(String* value) noexcept
: string_val(value) {}
constexpr BroValUnion(Func* value) noexcept
: func_val(value) {}
constexpr BroValUnion(File* value) noexcept
: file_val(value) {}
constexpr BroValUnion(RE_Matcher* value) noexcept
: re_val(value) {}
constexpr BroValUnion(PDict<TableEntryVal>* value) noexcept
: table_val(value) {}
};
class Val : public Obj { class Val : public Obj {
public: public:
static inline const ValPtr nil; static inline const ValPtr nil;
#ifdef DEPRECATED
// We need to decide whether to keep these. It will be a pain
// since it's no longer possible to build these as Val objects.
// Instead, we'd need to (1) extend Val's to include an optional
// pointer-to-another-Val, (2) implement these constructors by
// constructing the proper Val subclass in addition, tracking
// it using the pointer, (3) redirect calls to the dependent methods
// to go to the subclass instead (tricky to get right), (4) destruct
// the additional subclass (easy), and (5) figure out how to test
// whether all the surgery works (seems quite hard).
[[deprecated("Remove in v4.1. Use IntervalVal(), TimeVal(), or DoubleVal() constructors.")]] [[deprecated("Remove in v4.1. Use IntervalVal(), TimeVal(), or DoubleVal() constructors.")]]
Val(double d, TypeTag t) Val(double d, TypeTag t)
: val(d), type(base_type(t)) : val(d), type(base_type(t))
@ -163,6 +117,7 @@ public:
// Note, the file will be closed after this Val is destructed if there's // Note, the file will be closed after this Val is destructed if there's
// no other remaining references. // no other remaining references.
explicit Val(FilePtr f); explicit Val(FilePtr f);
#endif
// Extra arg to differentiate from protected version. // Extra arg to differentiate from protected version.
Val(TypePtr t, bool type_type) Val(TypePtr t, bool type_type)
@ -174,7 +129,7 @@ public:
{} {}
Val() Val()
: val(bro_int_t(0)), type(base_type(TYPE_ERROR)) : type(base_type(TYPE_ERROR))
{} {}
~Val() override; ~Val() override;
@ -221,41 +176,23 @@ public:
IntrusivePtr<T> GetType() const IntrusivePtr<T> GetType() const
{ return cast_intrusive<T>(type); } { return cast_intrusive<T>(type); }
#define CONST_ACCESSOR(tag, ctype, accessor, name) \ #define UNDERLYING_ACCESSOR_DECL(ztype, ctype, name) \
const ctype name() const \ ctype name() const;
{ \
CHECK_TAG(type->Tag(), tag, "Val::CONST_ACCESSOR", type_name) \
return val.accessor; \
}
// Needed for g++ 4.3's pickiness. UNDERLYING_ACCESSOR_DECL(IntVal, bro_int_t, AsInt)
#define CONST_ACCESSOR2(tag, ctype, accessor, name) \ UNDERLYING_ACCESSOR_DECL(BoolVal, bool, AsBool)
ctype name() const \ UNDERLYING_ACCESSOR_DECL(EnumVal, int, AsEnum)
{ \ UNDERLYING_ACCESSOR_DECL(CountVal, bro_uint_t, AsCount)
CHECK_TAG(type->Tag(), tag, "Val::CONST_ACCESSOR", type_name) \ UNDERLYING_ACCESSOR_DECL(DoubleVal, double, AsDouble)
return val.accessor; \ UNDERLYING_ACCESSOR_DECL(TimeVal, double, AsTime)
} UNDERLYING_ACCESSOR_DECL(IntervalVal, double, AsInterval)
UNDERLYING_ACCESSOR_DECL(AddrVal, const IPAddr&, AsAddr)
CONST_ACCESSOR2(TYPE_BOOL, bool, int_val, AsBool) UNDERLYING_ACCESSOR_DECL(SubNetVal, const IPPrefix&, AsSubNet)
CONST_ACCESSOR2(TYPE_INT, bro_int_t, int_val, AsInt) UNDERLYING_ACCESSOR_DECL(StringVal, const String*, AsString)
CONST_ACCESSOR2(TYPE_COUNT, bro_uint_t, uint_val, AsCount) UNDERLYING_ACCESSOR_DECL(FuncVal, Func*, AsFunc)
CONST_ACCESSOR2(TYPE_DOUBLE, double, double_val, AsDouble) UNDERLYING_ACCESSOR_DECL(FileVal, File*, AsFile)
CONST_ACCESSOR2(TYPE_TIME, double, double_val, AsTime) UNDERLYING_ACCESSOR_DECL(PatternVal, const RE_Matcher*, AsPattern)
CONST_ACCESSOR2(TYPE_INTERVAL, double, double_val, AsInterval) UNDERLYING_ACCESSOR_DECL(TableVal, const PDict<TableEntryVal>*, AsTable)
CONST_ACCESSOR2(TYPE_ENUM, int, int_val, AsEnum)
CONST_ACCESSOR(TYPE_STRING, String*, string_val, AsString)
CONST_ACCESSOR(TYPE_FUNC, Func*, func_val, AsFunc)
CONST_ACCESSOR(TYPE_TABLE, PDict<TableEntryVal>*, table_val, AsTable)
CONST_ACCESSOR(TYPE_RECORD, std::vector<ValPtr>*, record_val, AsRecord)
CONST_ACCESSOR(TYPE_FILE, File*, file_val, AsFile)
CONST_ACCESSOR(TYPE_PATTERN, RE_Matcher*, re_val, AsPattern)
CONST_ACCESSOR(TYPE_VECTOR, std::vector<ValPtr>*, vector_val, AsVector)
const IPPrefix& AsSubNet() const
{
CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name)
return *val.subnet_val;
}
zeek::Type* AsType() const zeek::Type* AsType() const
{ {
@ -263,48 +200,6 @@ public:
return type.get(); return type.get();
} }
const IPAddr& AsAddr() const
{
if ( type->Tag() != TYPE_ADDR )
BadTag("Val::AsAddr", type_name(type->Tag()));
return *val.addr_val;
}
#define ACCESSOR(tag, ctype, accessor, name) \
ctype name() \
{ \
CHECK_TAG(type->Tag(), tag, "Val::ACCESSOR", type_name) \
return val.accessor; \
}
// Accessors for mutable values are called AsNonConst* and
// are protected to avoid external state changes.
// ACCESSOR(TYPE_STRING, String*, string_val, AsString)
ACCESSOR(TYPE_FUNC, Func*, func_val, AsFunc)
ACCESSOR(TYPE_FILE, File*, file_val, AsFile)
ACCESSOR(TYPE_PATTERN, RE_Matcher*, re_val, AsPattern)
ACCESSOR(TYPE_VECTOR, std::vector<ValPtr>*, vector_val, AsVector)
FuncPtr AsFuncPtr() const;
const IPPrefix& AsSubNet()
{
CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name)
return *val.subnet_val;
}
const IPAddr& AsAddr()
{
if ( type->Tag() != TYPE_ADDR )
BadTag("Val::AsAddr", type_name(type->Tag()));
return *val.addr_val;
}
// Gives fast access to the bits of something that is one of
// bool, int, count, or counter.
bro_int_t ForceAsInt() const { return val.int_val; }
bro_uint_t ForceAsUInt() const { return val.uint_val; }
PatternVal* AsPatternVal(); PatternVal* AsPatternVal();
const PatternVal* AsPatternVal() const; const PatternVal* AsPatternVal() const;
@ -361,6 +256,7 @@ public:
protected: protected:
// Friends with access to Clone().
friend class EnumType; friend class EnumType;
friend class ListVal; friend class ListVal;
friend class RecordVal; friend class RecordVal;
@ -375,23 +271,10 @@ protected:
static ValPtr MakeInt(bro_int_t i); static ValPtr MakeInt(bro_int_t i);
static ValPtr MakeCount(bro_uint_t u); static ValPtr MakeCount(bro_uint_t u);
template<typename V>
Val(V&& v, TypeTag t) noexcept
: val(std::forward<V>(v)), type(base_type(t))
{}
template<typename V>
Val(V&& v, TypePtr t) noexcept
: val(std::forward<V>(v)), type(std::move(t))
{}
explicit Val(TypePtr t) noexcept explicit Val(TypePtr t) noexcept
: type(std::move(t)) : type(std::move(t))
{} {}
ACCESSOR(TYPE_TABLE, PDict<TableEntryVal>*, table_val, AsNonConstTable)
ACCESSOR(TYPE_RECORD, std::vector<ValPtr>*, record_val, AsNonConstRecord)
// For internal use by the Val::Clone() methods. // For internal use by the Val::Clone() methods.
struct CloneState { struct CloneState {
// Caches a cloned value for later reuse during the same // Caches a cloned value for later reuse during the same
@ -405,7 +288,6 @@ protected:
ValPtr Clone(CloneState* state); ValPtr Clone(CloneState* state);
virtual ValPtr DoClone(CloneState* state); virtual ValPtr DoClone(CloneState* state);
BroValUnion val;
TypePtr type; TypePtr type;
#ifdef DEBUG #ifdef DEBUG
@ -505,6 +387,67 @@ private:
extern ValManager* val_mgr; extern ValManager* val_mgr;
class IntVal : public Val {
public:
IntVal(bro_int_t v)
: Val(base_type(TYPE_INT)), int_val(v)
{}
bro_int_t UnderlyingVal() const { return int_val; }
protected:
IntVal(bro_int_t v, TypePtr t)
: Val(std::move(t)), int_val(v)
{}
bro_int_t int_val;
};
class BoolVal final : public IntVal {
public:
BoolVal(bro_int_t v)
: IntVal(v, base_type(TYPE_BOOL))
{}
BoolVal(bool b)
: BoolVal(bro_int_t(b))
{}
bool UnderlyingVal() const { return int_val; }
};
class CountVal : public Val {
public:
CountVal(bro_uint_t v)
: Val(base_type(TYPE_COUNT)), uint_val(v)
{}
bro_uint_t UnderlyingVal() const { return uint_val; }
protected:
CountVal(bro_uint_t v, TypePtr t)
: Val(std::move(t)), uint_val(v)
{}
bro_int_t uint_val;
};
class DoubleVal : public Val {
public:
DoubleVal(double v)
: Val(base_type(TYPE_DOUBLE)), double_val(v)
{}
double UnderlyingVal() const { return double_val; }
protected:
DoubleVal(double v, TypePtr t)
: Val(std::move(t)), double_val(v)
{}
private:
double double_val;
};
#define Microseconds 1e-6 #define Microseconds 1e-6
#define Milliseconds 1e-3 #define Milliseconds 1e-3
#define Seconds 1.0 #define Seconds 1.0
@ -512,31 +455,24 @@ extern ValManager* val_mgr;
#define Hours (60*Minutes) #define Hours (60*Minutes)
#define Days (24*Hours) #define Days (24*Hours)
class IntervalVal final : public Val { class IntervalVal final : public DoubleVal {
public: public:
IntervalVal(double quantity, double units = Seconds) IntervalVal(double quantity, double units = Seconds)
: Val(quantity * units, base_type(TYPE_INTERVAL)) : DoubleVal(quantity * units, base_type(TYPE_INTERVAL))
{} {}
protected: protected:
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
}; };
class TimeVal final : public Val { class TimeVal final : public DoubleVal {
public: public:
TimeVal(double t) TimeVal(double t)
: Val(t, base_type(TYPE_TIME)) : DoubleVal(t, base_type(TYPE_TIME))
{} {}
}; };
class DoubleVal final : public Val { class PortVal final : public CountVal {
public:
DoubleVal(double v)
: Val(v, base_type(TYPE_DOUBLE))
{}
};
class PortVal final : public Val {
public: public:
ValPtr SizeVal() const override; ValPtr SizeVal() const override;
@ -585,10 +521,15 @@ public:
explicit AddrVal(const uint32_t addr[4]); // IPv6. explicit AddrVal(const uint32_t addr[4]); // IPv6.
explicit AddrVal(const IPAddr& addr); explicit AddrVal(const IPAddr& addr);
const IPAddr& UnderlyingVal() const { return *addr_val; }
unsigned int MemoryAllocation() const override; unsigned int MemoryAllocation() const override;
protected: protected:
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
private:
IPAddr* addr_val;
}; };
class SubNetVal final : public Val { class SubNetVal final : public Val {
@ -609,11 +550,16 @@ public:
bool Contains(const IPAddr& addr) const; bool Contains(const IPAddr& addr) const;
const IPPrefix& UnderlyingVal() const { return *subnet_val; }
unsigned int MemoryAllocation() const override; unsigned int MemoryAllocation() const override;
protected: protected:
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
private:
IPPrefix* subnet_val;
}; };
class StringVal final : public Val { class StringVal final : public Val {
@ -622,6 +568,7 @@ public:
explicit StringVal(const char* s); explicit StringVal(const char* s);
explicit StringVal(const std::string& s); explicit StringVal(const std::string& s);
StringVal(int length, const char* s); StringVal(int length, const char* s);
~StringVal() override;
ValPtr SizeVal() const override; ValPtr SizeVal() const override;
@ -637,6 +584,8 @@ public:
std::string ToStdString() const; std::string ToStdString() const;
StringVal* ToUpper(); StringVal* ToUpper();
const String* UnderlyingVal() const { return string_val; }
unsigned int MemoryAllocation() const override; unsigned int MemoryAllocation() const override;
StringValPtr Replace(RE_Matcher* re, const String& repl, StringValPtr Replace(RE_Matcher* re, const String& repl,
@ -649,6 +598,43 @@ public:
protected: protected:
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
private:
String* string_val;
};
class FuncVal final : public Val {
public:
explicit FuncVal(FuncPtr f);
FuncPtr AsFuncPtr() const;
ValPtr SizeVal() const override;
Func* UnderlyingVal() const { return func_val.get(); }
protected:
void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override;
private:
FuncPtr func_val;
};
class FileVal final : public Val {
public:
explicit FileVal(FilePtr f);
ValPtr SizeVal() const override;
File* UnderlyingVal() const { return file_val.get(); }
protected:
void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override;
private:
FilePtr file_val;
}; };
class PatternVal final : public Val { class PatternVal final : public Val {
@ -660,11 +646,19 @@ public:
void SetMatcher(RE_Matcher* re); void SetMatcher(RE_Matcher* re);
bool MatchExactly(const String* s) const;
bool MatchAnywhere(const String* s) const;
const RE_Matcher* UnderlyingVal() const { return re_val; }
unsigned int MemoryAllocation() const override; unsigned int MemoryAllocation() const override;
protected: protected:
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
private:
RE_Matcher* re_val;
}; };
// ListVals are mainly used to index tables that have more than one // ListVals are mainly used to index tables that have more than one
@ -754,7 +748,7 @@ protected:
ValPtr val; ValPtr val;
// The next entry stores seconds since Bro's start. We use ints here // The next entry stores seconds since Zeek's start. We use ints here
// to save a few bytes, as we do not need a high resolution for these // to save a few bytes, as we do not need a high resolution for these
// anyway. // anyway.
int expire_access_time; int expire_access_time;
@ -997,6 +991,9 @@ public:
const detail::AttributesPtr& GetAttrs() const const detail::AttributesPtr& GetAttrs() const
{ return attrs; } { return attrs; }
const PDict<TableEntryVal>* UnderlyingVal() const
{ return table_val; }
// Returns the size of the table. // Returns the size of the table.
int Size() const; int Size() const;
int RecursiveSize() const; int RecursiveSize() const;
@ -1104,6 +1101,9 @@ protected:
// Sends data on to backing Broker Store // Sends data on to backing Broker Store
void SendToStore(const Val* index, const TableEntryVal* new_entry_val, OnChangeType tpe); void SendToStore(const Val* index, const TableEntryVal* new_entry_val, OnChangeType tpe);
// Low-level insertion, not publicly available.
void Insert(detail::HashKey* k, TableEntryVal* tev);
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
TableTypePtr table_type; TableTypePtr table_type;
@ -1122,6 +1122,9 @@ protected:
static TableRecordDependencies parse_time_table_record_dependencies; static TableRecordDependencies parse_time_table_record_dependencies;
static ParseTimeTableStates parse_time_table_states; static ParseTimeTableStates parse_time_table_states;
private:
PDict<TableEntryVal>* table_val;
}; };
class RecordVal final : public Val, public notifier::detail::Modifiable { class RecordVal final : public Val, public notifier::detail::Modifiable {
@ -1158,9 +1161,29 @@ public:
void Assign(int field, std::nullptr_t) void Assign(int field, std::nullptr_t)
{ Assign(field, ValPtr{}); } { Assign(field, ValPtr{}); }
[[deprecated("Remove in v4.1. Use GetField().")]] /**
Val* Lookup(int field) const // Does not Ref() value. * Appends a value to the record's fields. The caller is responsible
{ return (*AsRecord())[field].get(); } * for ensuring that fields are appended in the correct orer and
* with the correct type.
* @param v The value to append.
*/
void AppendField(ValPtr v)
{ record_val->emplace_back(std::move(v)); }
/**
* Ensures that the record has enough internal storage for the
* given number of fields.
* @param n The number of fields.
*/
void Reserve(unsigned int n)
{ record_val->reserve(n); }
/**
* Returns the number of fields in the record.
* @return The number of fields in the record.
*/
unsigned int NumFields()
{ return record_val->size(); }
/** /**
* Returns the value of a given field index. * Returns the value of a given field index.
@ -1168,7 +1191,7 @@ public:
* @return The value at the given field index. * @return The value at the given field index.
*/ */
const ValPtr& GetField(int field) const const ValPtr& GetField(int field) const
{ return (*AsRecord())[field]; } { return (*record_val)[field]; }
/** /**
* Returns the value of a given field index as cast to type @c T. * Returns the value of a given field index as cast to type @c T.
@ -1233,6 +1256,27 @@ public:
IntrusivePtr<T> GetFieldOrDefault(const char* field) const IntrusivePtr<T> GetFieldOrDefault(const char* field) const
{ return cast_intrusive<T>(GetField(field)); } { return cast_intrusive<T>(GetField(field)); }
// The following return the given field converted to a particular
// underlying value. We provide these to enable efficient
// access to record fields (without requiring an intermediary Val)
// if we change the underlying representation of records.
#define GET_FIELD_AS(ctype, name ) \
ctype Get ## name ## Field(int field) const \
{ return GetField(field)->As ## name(); } \
ctype Get ## name ## Field(const char* field) const \
{ return GetField(field)->As ## name(); }
GET_FIELD_AS(bool, Bool)
GET_FIELD_AS(int, Enum)
GET_FIELD_AS(bro_int_t, Int)
GET_FIELD_AS(bro_uint_t, Count)
GET_FIELD_AS(double, Double)
GET_FIELD_AS(double, Time)
GET_FIELD_AS(double, Interval)
GET_FIELD_AS(const PortVal*, PortVal)
GET_FIELD_AS(const IPAddr&, Addr)
GET_FIELD_AS(const String*, String)
/** /**
* Looks up the value of a field by field name. If the field doesn't * Looks up the value of a field by field name. If the field doesn't
* exist in the record type, it's an internal error: abort. * exist in the record type, it's an internal error: abort.
@ -1293,12 +1337,17 @@ protected:
using RecordTypeValMap = std::unordered_map<RecordType*, std::vector<RecordValPtr>>; using RecordTypeValMap = std::unordered_map<RecordType*, std::vector<RecordValPtr>>;
static RecordTypeValMap parse_time_records; static RecordTypeValMap parse_time_records;
private:
std::vector<ValPtr>* record_val;
}; };
class EnumVal final : public Val { class EnumVal final : public IntVal {
public: public:
ValPtr SizeVal() const override; ValPtr SizeVal() const override;
int UnderlyingVal() const { return int_val; }
protected: protected:
friend class Val; friend class Val;
friend class EnumType; friend class EnumType;
@ -1306,7 +1355,7 @@ protected:
template<class T, class... Ts> template<class T, class... Ts>
friend IntrusivePtr<T> make_intrusive(Ts&&... args); friend IntrusivePtr<T> make_intrusive(Ts&&... args);
EnumVal(EnumTypePtr t, bro_int_t i) : Val(i, std::move(t)) EnumVal(EnumTypePtr t, bro_int_t i) : IntVal(i, std::move(t))
{} {}
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
@ -1374,6 +1423,16 @@ public:
*/ */
const ValPtr& At(unsigned int index) const; const ValPtr& At(unsigned int index) const;
/**
* Returns the given element treated as a Count type, to efficiently
* support a common type of vector access if we change the underlying
* vector representation.
* @param index The position in the vector of the element to return.
* @return The element's value, as a Count underlying representation.
*/
bro_uint_t CountAt(unsigned int index) const
{ return At(index)->AsCount(); }
[[deprecated("Remove in v4.1. Use At().")]] [[deprecated("Remove in v4.1. Use At().")]]
Val* Lookup(unsigned int index) const Val* Lookup(unsigned int index) const
{ return At(index).get(); } { return At(index).get(); }
@ -1385,7 +1444,7 @@ public:
return At(static_cast<unsigned int>(i)).get(); return At(static_cast<unsigned int>(i)).get();
} }
unsigned int Size() const { return val.vector_val->size(); } unsigned int Size() const { return vector_val->size(); }
// Is there any way to reclaim previously-allocated memory when you // Is there any way to reclaim previously-allocated memory when you
// shrink a vector? The return value is the old size. // shrink a vector? The return value is the old size.
@ -1394,6 +1453,9 @@ public:
// Won't shrink size. // Won't shrink size.
unsigned int ResizeAtLeast(unsigned int new_num_elements); unsigned int ResizeAtLeast(unsigned int new_num_elements);
// Reserves storage for at least the number of elements.
void Reserve(unsigned int num_elements);
notifier::detail::Modifiable* Modifiable() override { return this; } notifier::detail::Modifiable* Modifiable() override { return this; }
/** /**
@ -1413,11 +1475,43 @@ public:
// Removes an element at a specific position. // Removes an element at a specific position.
bool Remove(unsigned int index); bool Remove(unsigned int index);
/**
* Sorts the vector in place, using the given comparison function.
* @param cmp_func Comparison function for vector elements.
*/
void Sort(bool cmp_func(const ValPtr& a, const ValPtr& b));
const std::vector<ValPtr>* UnderlyingVal() const
{ return vector_val; }
protected: protected:
void ValDescribe(ODesc* d) const override; void ValDescribe(ODesc* d) const override;
ValPtr DoClone(CloneState* state) override; ValPtr DoClone(CloneState* state) override;
private:
std::vector<ValPtr>* vector_val;
}; };
#define UNDERLYING_ACCESSOR_DEF(ztype, ctype, name) \
inline ctype Val::name() const \
{ return dynamic_cast<const ztype*>(this)->UnderlyingVal(); }
UNDERLYING_ACCESSOR_DEF(IntVal, bro_int_t, AsInt)
UNDERLYING_ACCESSOR_DEF(BoolVal, bool, AsBool)
UNDERLYING_ACCESSOR_DEF(EnumVal, int, AsEnum)
UNDERLYING_ACCESSOR_DEF(CountVal, bro_uint_t, AsCount)
UNDERLYING_ACCESSOR_DEF(DoubleVal, double, AsDouble)
UNDERLYING_ACCESSOR_DEF(TimeVal, double, AsTime)
UNDERLYING_ACCESSOR_DEF(IntervalVal, double, AsInterval)
UNDERLYING_ACCESSOR_DEF(SubNetVal, const IPPrefix&, AsSubNet)
UNDERLYING_ACCESSOR_DEF(AddrVal, const IPAddr&, AsAddr)
UNDERLYING_ACCESSOR_DEF(StringVal, const String*, AsString)
UNDERLYING_ACCESSOR_DEF(FuncVal, Func*, AsFunc)
UNDERLYING_ACCESSOR_DEF(FileVal, File*, AsFile)
UNDERLYING_ACCESSOR_DEF(PatternVal, const RE_Matcher*, AsPattern)
UNDERLYING_ACCESSOR_DEF(TableVal, const PDict<TableEntryVal>*, AsTable)
// Checks the given value for consistency with the given type. If an // Checks the given value for consistency with the given type. If an
// exact match, returns it. If promotable, returns the promoted version. // exact match, returns it. If promotable, returns the promoted version.
// If not a match, generates an error message and return nil. If is_init is // If not a match, generates an error message and return nil. If is_init is

View file

@ -322,7 +322,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init,
// defined. // defined.
std::vector<IDPtr> inits; std::vector<IDPtr> inits;
auto f = make_intrusive<ScriptFunc>(id, nullptr, inits, 0, 0); auto f = make_intrusive<ScriptFunc>(id, nullptr, inits, 0, 0);
id->SetVal(make_intrusive<Val>(std::move(f))); id->SetVal(make_intrusive<FuncVal>(std::move(f)));
} }
} }
@ -750,11 +750,12 @@ void end_func(StmtPtr body)
ingredients->frame_size, ingredients->frame_size,
ingredients->priority); ingredients->priority);
ingredients->id->SetVal(make_intrusive<Val>(std::move(f))); ingredients->id->SetVal(make_intrusive<FuncVal>(std::move(f)));
ingredients->id->SetConst(); ingredients->id->SetConst();
} }
auto func = cast_intrusive<ScriptFunc>(ingredients->id->GetVal()->AsFuncPtr()); auto func_ptr = cast_intrusive<FuncVal>(ingredients->id->GetVal())->AsFuncPtr();
auto func = cast_intrusive<ScriptFunc>(func_ptr);
func->SetScope(ingredients->scope); func->SetScope(ingredients->scope);
analyze_func(std::move(func)); analyze_func(std::move(func));

View file

@ -263,7 +263,7 @@ refine connection KRB_Conn += {
rv->Assign(1, zeek::val_mgr->Bool(${msg.ap_options.mutual_required})); rv->Assign(1, zeek::val_mgr->Bool(${msg.ap_options.mutual_required}));
auto rvticket = proc_ticket(${msg.ticket}); auto rvticket = proc_ticket(${msg.ticket});
auto authenticationinfo = zeek_analyzer()->GetAuthenticationInfo(rvticket->GetField(2)->AsString(), rvticket->GetField(4)->AsString(), rvticket->GetField(3)->AsCount()); auto authenticationinfo = zeek_analyzer()->GetAuthenticationInfo(rvticket->GetStringField(2), rvticket->GetStringField(4), rvticket->GetCountField(3));
if ( authenticationinfo ) if ( authenticationinfo )
rvticket->Assign(5, authenticationinfo); rvticket->Assign(5, authenticationinfo);

View file

@ -176,7 +176,7 @@ bool NFS_Interp::RPC_BuildReply(RPC_CallInfo* c, BifEnum::rpc_status rpc_status,
case BifEnum::NFS3::PROC_READ: case BifEnum::NFS3::PROC_READ:
bro_uint_t offset; bro_uint_t offset;
offset = c->RequestVal()->AsRecordVal()->GetField(1)->AsCount(); offset = c->RequestVal()->AsRecordVal()->GetCountField(1);
reply = nfs3_read_reply(buf, n, nfs_status, offset); reply = nfs3_read_reply(buf, n, nfs_status, offset);
event = nfs_proc_read; event = nfs_proc_read;
break; break;

View file

@ -127,7 +127,7 @@ function get_contents_file%(cid: conn_id, direction: count%): file
auto cf = c->GetRootAnalyzer()->GetContentsFile(direction); auto cf = c->GetRootAnalyzer()->GetContentsFile(direction);
if ( cf ) if ( cf )
return zeek::make_intrusive<zeek::Val>(std::move(cf)); return zeek::make_intrusive<zeek::FileVal>(std::move(cf));
} }
// Return some sort of error value. // Return some sort of error value.
@ -136,5 +136,5 @@ function get_contents_file%(cid: conn_id, direction: count%): file
else else
zeek::emit_builtin_error("no contents file for given direction"); zeek::emit_builtin_error("no contents file for given direction");
return zeek::make_intrusive<zeek::Val>(zeek::make_intrusive<zeek::File>(stderr, "-", "w")); return zeek::make_intrusive<zeek::FileVal>(zeek::make_intrusive<zeek::File>(stderr, "-", "w"));
%} %}

View file

@ -127,7 +127,7 @@ struct val_converter {
auto file = File::Get(a.data()); auto file = File::Get(a.data());
if ( file ) if ( file )
return make_intrusive<Val>(std::move(file)); return make_intrusive<FileVal>(std::move(file));
return nullptr; return nullptr;
} }

View file

@ -436,7 +436,7 @@ bool Manager::PublishEvent(string topic, RecordVal* args)
if ( ! args->GetField(0) ) if ( ! args->GetField(0) )
return false; return false;
auto event_name = args->GetField(0)->AsString()->CheckString(); auto event_name = args->GetStringField(0)->CheckString();
auto vv = args->GetField(1)->AsVectorVal(); auto vv = args->GetField(1)->AsVectorVal();
broker::vector xs; broker::vector xs;
xs.reserve(vv->Size()); xs.reserve(vv->Size());

View file

@ -69,7 +69,7 @@ broker::backend_options to_backend_options(broker::backend backend,
case broker::backend::sqlite: case broker::backend::sqlite:
{ {
auto path = options->GetField(0)->AsRecordVal() auto path = options->GetField(0)->AsRecordVal()
->GetField(0)->AsStringVal()->CheckString(); ->GetStringField(0)->CheckString();
return {{"path", path}}; return {{"path", path}};
} }

View file

@ -120,7 +120,7 @@ void File::UpdateLastActivityTime()
double File::GetLastActivityTime() const double File::GetLastActivityTime() const
{ {
return val->GetField(last_active_idx)->AsTime(); return val->GetTimeField(last_active_idx);
} }
bool File::UpdateConnectionFields(Connection* conn, bool is_orig) bool File::UpdateConnectionFields(Connection* conn, bool is_orig)

View file

@ -44,7 +44,7 @@ function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool
bool success = true; bool success = true;
zeek::iosource::PktSrc* ps = zeek::iosource_mgr->GetPktSrc(); zeek::iosource::PktSrc* ps = zeek::iosource_mgr->GetPktSrc();
if ( ps && ! ps->PrecompileFilter(id->ForceAsInt(), s->CheckString()) ) if ( ps && ! ps->PrecompileFilter(id->AsInt(), s->CheckString()) )
success = false; success = false;
return zeek::val_mgr->Bool(success); return zeek::val_mgr->Bool(success);
@ -73,7 +73,7 @@ function Pcap::install_pcap_filter%(id: PcapFilterID%): bool
bool success = true; bool success = true;
zeek::iosource::PktSrc* ps = zeek::iosource_mgr->GetPktSrc(); zeek::iosource::PktSrc* ps = zeek::iosource_mgr->GetPktSrc();
if ( ps && ! ps->SetFilter(id->ForceAsInt()) ) if ( ps && ! ps->SetFilter(id->AsInt()) )
success = false; success = false;
return zeek::val_mgr->Bool(success); return zeek::val_mgr->Bool(success);

View file

@ -1534,7 +1534,7 @@ std::string Manager::FormatRotationPath(EnumValPtr writer,
ri->Assign<TimeVal>(2, open); ri->Assign<TimeVal>(2, open);
ri->Assign<TimeVal>(3, close); ri->Assign<TimeVal>(3, close);
ri->Assign(4, val_mgr->Bool(terminating)); ri->Assign(4, val_mgr->Bool(terminating));
ri->Assign<Val>(5, std::move(postprocessor)); ri->Assign<FuncVal>(5, std::move(postprocessor));
std::string rval; std::string rval;
@ -1543,7 +1543,7 @@ std::string Manager::FormatRotationPath(EnumValPtr writer,
auto res = rotation_format_func->Invoke(ri); auto res = rotation_format_func->Invoke(ri);
auto rp_val = res->AsRecordVal(); auto rp_val = res->AsRecordVal();
auto dir_val = rp_val->GetFieldOrDefault(0); auto dir_val = rp_val->GetFieldOrDefault(0);
auto prefix = rp_val->GetField(1)->AsString()->CheckString(); auto prefix = rp_val->GetStringField(1)->CheckString();
auto dir = dir_val->AsString()->CheckString(); auto dir = dir_val->AsString()->CheckString();
if ( ! util::streq(dir, "") && ! util::detail::ensure_intermediate_dirs(dir) ) if ( ! util::streq(dir, "") && ! util::detail::ensure_intermediate_dirs(dir) )

View file

@ -209,6 +209,7 @@ function Option::set_change_handler%(ID: string, on_change: any, priority: int &
return zeek::val_mgr->False(); return zeek::val_mgr->False();
} }
i->AddOptionHandler(on_change->AsFuncPtr(), -priority); auto func = dynamic_cast<FuncVal*>(on_change)->AsFuncPtr();
i->AddOptionHandler(func, -priority);
return zeek::val_mgr->True(); return zeek::val_mgr->True();
%} %}

View file

@ -148,7 +148,7 @@ function Reporter::conn_weird%(name: string, c: connection, addl: string &defaul
## Returns: true if the file was still valid, else false. ## Returns: true if the file was still valid, else false.
function Reporter::file_weird%(name: string, f: fa_file, addl: string &default="", source: string&default=""%): bool function Reporter::file_weird%(name: string, f: fa_file, addl: string &default="", source: string&default=""%): bool
%{ %{
auto fuid = f->AsRecordVal()->GetField(0)->AsStringVal(); auto fuid = f->AsRecordVal()->GetStringField(0);
auto file = zeek::file_mgr->LookupFile(fuid->CheckString()); auto file = zeek::file_mgr->LookupFile(fuid->CheckString());
if ( ! file ) if ( ! file )

View file

@ -684,8 +684,8 @@ function string_to_ascii_hex%(s: string%): string
function str_smith_waterman%(s1: string, s2: string, params: sw_params%) : sw_substring_vec function str_smith_waterman%(s1: string, s2: string, params: sw_params%) : sw_substring_vec
%{ %{
zeek::detail::SWParams sw_params( zeek::detail::SWParams sw_params(
params->AsRecordVal()->GetField(0)->AsCount(), params->AsRecordVal()->GetCountField(0),
zeek::detail::SWVariant(params->AsRecordVal()->GetField(1)->AsCount())); zeek::detail::SWVariant(params->AsRecordVal()->GetCountField(1)));
auto* subseq = zeek::detail::smith_waterman(s1->AsString(), s2->AsString(), sw_params); auto* subseq = zeek::detail::smith_waterman(s1->AsString(), s2->AsString(), sw_params);
auto result = zeek::VectorValPtr{zeek::AdoptRef{}, zeek::detail::Substring::VecToPolicy(subseq)}; auto result = zeek::VectorValPtr{zeek::AdoptRef{}, zeek::detail::Substring::VecToPolicy(subseq)};
@ -707,12 +707,13 @@ function str_smith_waterman%(s1: string, s2: string, params: sw_params%) : sw_su
## .. zeek:see:: split_string split_string1 split_string_all split_string_n ## .. zeek:see:: split_string split_string1 split_string_all split_string_n
function str_split%(s: string, idx: index_vec%): string_vec &deprecated="Remove in v4.1. Use str_split_indices." function str_split%(s: string, idx: index_vec%): string_vec &deprecated="Remove in v4.1. Use str_split_indices."
%{ %{
auto idx_v = idx->AsVector(); auto idx_v = dynamic_cast<VectorVal*>(idx);
zeek::String::IdxVec indices(idx_v->size()); auto n = idx_v->Size();
zeek::String::IdxVec indices(n);
unsigned int i; unsigned int i;
for ( i = 0; i < idx_v->size(); i++ ) for ( i = 0; i < n; i++ )
indices[i] = (*idx_v)[i]->AsCount(); indices[i] = idx_v->CountAt(i);
zeek::String::Vec* result = s->AsString()->Split(indices); zeek::String::Vec* result = s->AsString()->Split(indices);
auto result_v = zeek::make_intrusive<zeek::VectorVal>(zeek::id::string_vec); auto result_v = zeek::make_intrusive<zeek::VectorVal>(zeek::id::string_vec);
@ -745,12 +746,13 @@ function str_split%(s: string, idx: index_vec%): string_vec &deprecated="Remove
## .. zeek:see:: split_string split_string1 split_string_all split_string_n ## .. zeek:see:: split_string split_string1 split_string_all split_string_n
function str_split_indices%(s: string, idx: index_vec%): string_vec function str_split_indices%(s: string, idx: index_vec%): string_vec
%{ %{
auto idx_v = idx->AsVector(); auto idx_v = dynamic_cast<VectorVal*>(idx);
zeek::String::IdxVec indices(idx_v->size()); auto n = idx_v->Size();
zeek::String::IdxVec indices(n);
unsigned int i; unsigned int i;
for ( i = 0; i < idx_v->size(); i++ ) for ( i = 0; i < n; i++ )
indices[i] = (*idx_v)[i]->AsCount(); indices[i] = idx_v->CountAt(i);
zeek::String::Vec* result = s->AsString()->Split(indices); zeek::String::Vec* result = s->AsString()->Split(indices);
auto result_v = zeek::make_intrusive<zeek::VectorVal>(zeek::id::string_vec); auto result_v = zeek::make_intrusive<zeek::VectorVal>(zeek::id::string_vec);

View file

@ -1225,7 +1225,7 @@ static BifEnum::Supervisor::ClusterRole role_str_to_enum(std::string_view r)
Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node) Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node)
{ {
Supervisor::NodeConfig rval; Supervisor::NodeConfig rval;
rval.name = node->GetField("name")->AsString()->CheckString(); rval.name = node->GetStringField("name")->CheckString();
const auto& iface_val = node->GetField("interface"); const auto& iface_val = node->GetField("interface");
if ( iface_val ) if ( iface_val )
@ -1273,9 +1273,9 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node)
auto rv = v->GetVal()->AsRecordVal(); auto rv = v->GetVal()->AsRecordVal();
Supervisor::ClusterEndpoint ep; Supervisor::ClusterEndpoint ep;
ep.role = static_cast<BifEnum::Supervisor::ClusterRole>(rv->GetField("role")->AsEnum()); ep.role = static_cast<BifEnum::Supervisor::ClusterRole>(rv->GetEnumField("role"));
ep.host = rv->GetField("host")->AsAddr().AsString(); ep.host = rv->GetAddrField("host").AsString();
ep.port = rv->GetField("p")->AsPortVal()->Port(); ep.port = rv->GetPortValField("p")->Port();
const auto& iface = rv->GetField("interface"); const auto& iface = rv->GetField("interface");

View file

@ -111,8 +111,8 @@ struct Value {
struct subnet_t { addr_t prefix; uint8_t length; }; struct subnet_t { addr_t prefix; uint8_t length; };
/** /**
* This union is a subset of BroValUnion, including only the types we * This union is a subset of the "underlying" values in Val subclasses,
* can log directly. See IsCompatibleType(). * including only the types we can log directly. See IsCompatibleType().
*/ */
union _val { union _val {
bro_int_t int_val; bro_int_t int_val;

View file

@ -1432,7 +1432,7 @@ function sort%(v: any, ...%) : any
if ( ! comp && ! IsIntegral(elt_type->Tag()) ) if ( ! comp && ! IsIntegral(elt_type->Tag()) )
zeek::emit_builtin_error("comparison function required for sort() with non-integral types"); zeek::emit_builtin_error("comparison function required for sort() with non-integral types");
auto& vv = *v->AsVector(); auto vv = dynamic_cast<VectorVal*>(v);
if ( comp ) if ( comp )
{ {
@ -1447,14 +1447,14 @@ function sort%(v: any, ...%) : any
sort_function_comp = comp; sort_function_comp = comp;
sort(vv.begin(), vv.end(), sort_function); vv->Sort(sort_function);
} }
else else
{ {
if ( elt_type->InternalType() == zeek::TYPE_INTERNAL_UNSIGNED ) if ( elt_type->InternalType() == zeek::TYPE_INTERNAL_UNSIGNED )
sort(vv.begin(), vv.end(), unsigned_sort_function); vv->Sort(unsigned_sort_function);
else else
sort(vv.begin(), vv.end(), signed_sort_function); vv->Sort(signed_sort_function);
} }
return rval; return rval;
@ -1502,8 +1502,8 @@ function order%(v: any, ...%) : index_vec
if ( ! comp && ! IsIntegral(elt_type->Tag()) ) if ( ! comp && ! IsIntegral(elt_type->Tag()) )
zeek::emit_builtin_error("comparison function required for order() with non-integral types"); zeek::emit_builtin_error("comparison function required for order() with non-integral types");
auto& vv = *v->AsVector(); auto vv = dynamic_cast<VectorVal*>(v);
auto n = vv.size(); auto n = vv->Size();
// Set up initial mapping of indices directly to corresponding // Set up initial mapping of indices directly to corresponding
// elements. // elements.
@ -1513,7 +1513,7 @@ function order%(v: any, ...%) : index_vec
for ( i = 0; i < n; ++i ) for ( i = 0; i < n; ++i )
{ {
ind_vv[i] = i; ind_vv[i] = i;
index_map.emplace_back(&vv[i]); index_map.emplace_back(&vv->At(i));
} }
if ( comp ) if ( comp )
@ -2410,15 +2410,17 @@ function addr_to_counts%(a: addr%): index_vec
## .. zeek:see:: addr_to_counts ## .. zeek:see:: addr_to_counts
function counts_to_addr%(v: index_vec%): addr function counts_to_addr%(v: index_vec%): addr
%{ %{
if ( v->AsVector()->size() == 1 ) auto vv = dynamic_cast<VectorVal*>(v);
if ( vv->Size() == 1 )
{ {
return zeek::make_intrusive<zeek::AddrVal>(htonl((*v->AsVector())[0]->AsCount())); return zeek::make_intrusive<zeek::AddrVal>(htonl(vv->CountAt(0)));
} }
else if ( v->AsVector()->size() == 4 ) else if ( vv->Size() == 4 )
{ {
uint32_t bytes[4]; uint32_t bytes[4];
for ( int i = 0; i < 4; ++i ) for ( int i = 0; i < 4; ++i )
bytes[i] = htonl((*v->AsVector())[i]->AsCount()); bytes[i] = htonl(vv->CountAt(i));
return zeek::make_intrusive<zeek::AddrVal>(bytes); return zeek::make_intrusive<zeek::AddrVal>(bytes);
} }
else else
@ -3526,13 +3528,13 @@ function lookup_connection%(cid: conn_id%): connection
%%{ %%{
const char* conn_id_string(zeek::Val* c) const char* conn_id_string(zeek::Val* c)
{ {
const auto& id = (*(c->AsRecord()))[0]; auto id = dynamic_cast<const zeek::RecordVal*>(c)->GetField(0);
auto vl = id->AsRecord(); auto id_r = dynamic_cast<const zeek::RecordVal*>(id.get());
const zeek::IPAddr& orig_h = (*vl)[0]->AsAddr(); const zeek::IPAddr& orig_h = id_r->GetAddrField(0);
uint32_t orig_p = (*vl)[1]->AsPortVal()->Port(); uint32_t orig_p = id_r->GetPortValField(1)->Port();
const zeek::IPAddr& resp_h = (*vl)[2]->AsAddr(); const zeek::IPAddr& resp_h = id_r->GetAddrField(2);
uint32_t resp_p = (*vl)[3]->AsPortVal()->Port(); uint32_t resp_p = id_r->GetPortValField(3)->Port();
return zeek::util::fmt("%s/%u -> %s/%u\n", orig_h.AsString().c_str(), orig_p, return zeek::util::fmt("%s/%u -> %s/%u\n", orig_h.AsString().c_str(), orig_p,
resp_h.AsString().c_str(), resp_p); resp_h.AsString().c_str(), resp_p);
@ -3652,14 +3654,14 @@ function dump_packet%(pkt: pcap_packet, file_name: string%) : bool
uint32_t caplen, len, link_type; uint32_t caplen, len, link_type;
u_char *data; u_char *data;
auto pkt_vl = pkt->AsRecord(); auto pkt_r = dynamic_cast<RecordVal*>(pkt);
ts.tv_sec = (*pkt_vl)[0]->AsCount(); ts.tv_sec = pkt_r->GetCountField(0);
ts.tv_usec = (*pkt_vl)[1]->AsCount(); ts.tv_usec = pkt_r->GetCountField(1);
caplen = (*pkt_vl)[2]->AsCount(); caplen = pkt_r->GetCountField(2);
len = (*pkt_vl)[3]->AsCount(); len = pkt_r->GetCountField(3);
data = (*pkt_vl)[4]->AsString()->Bytes(); data = pkt_r->GetStringField(4)->Bytes();
link_type = (*pkt_vl)[5]->AsEnum(); link_type = pkt_r->GetEnumField(5);
Packet p(link_type, &ts, caplen, len, data, true); Packet p(link_type, &ts, caplen, len, data, true);
addl_pkt_dumper->Dump(&p); addl_pkt_dumper->Dump(&p);
@ -4592,9 +4594,9 @@ function open%(f: string%): file
const char* file = f->CheckString(); const char* file = f->CheckString();
if ( zeek::util::streq(file, "-") ) if ( zeek::util::streq(file, "-") )
return zeek::make_intrusive<zeek::Val>(zeek::make_intrusive<zeek::File>(stdout, "-", "w")); return zeek::make_intrusive<zeek::FileVal>(zeek::make_intrusive<zeek::File>(stdout, "-", "w"));
else else
return zeek::make_intrusive<zeek::Val>(zeek::make_intrusive<zeek::File>(file, "w")); return zeek::make_intrusive<zeek::FileVal>(zeek::make_intrusive<zeek::File>(file, "w"));
%} %}
## Opens a file for writing or appending. If a file with the same name already ## Opens a file for writing or appending. If a file with the same name already
@ -4609,7 +4611,7 @@ function open%(f: string%): file
## rmdir unlink rename ## rmdir unlink rename
function open_for_append%(f: string%): file function open_for_append%(f: string%): file
%{ %{
return zeek::make_intrusive<zeek::Val>(zeek::make_intrusive<zeek::File>(f->CheckString(), "a")); return zeek::make_intrusive<zeek::FileVal>(zeek::make_intrusive<zeek::File>(f->CheckString(), "a"));
%} %}
## Closes an open file and flushes any buffered content. ## Closes an open file and flushes any buffered content.