diff --git a/auxil/bifcl b/auxil/bifcl index 624e5525f5..e72531a9ef 160000 --- a/auxil/bifcl +++ b/auxil/bifcl @@ -1 +1 @@ -Subproject commit 624e5525f54d4a15c35687d42301045f1769d3e1 +Subproject commit e72531a9efe4e6edb1589cb07ae41053023d0612 diff --git a/src/CompHash.cc b/src/CompHash.cc index 086d645f6a..c1b283ec46 100644 --- a/src/CompHash.cc +++ b/src/CompHash.cc @@ -101,7 +101,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0, case TYPE_INTERNAL_INT: { bro_int_t* kp = AlignAndPadType(kp0); - *kp = v->ForceAsInt(); + *kp = v->AsInt(); kp1 = reinterpret_cast(kp+1); } break; @@ -109,7 +109,7 @@ char* CompositeHash::SingleValHash(bool type_check, char* kp0, case TYPE_INTERNAL_UNSIGNED: { bro_uint_t* kp = AlignAndPadType(kp0); - *kp = v->ForceAsUInt(); + *kp = v->AsCount(); kp1 = reinterpret_cast(kp+1); } break; @@ -407,8 +407,10 @@ std::unique_ptr CompositeHash::ComputeSingletonHash(const Val* v, bool switch ( singleton_tag ) { case TYPE_INTERNAL_INT: + return std::make_unique(v->AsInt()); + case TYPE_INTERNAL_UNSIGNED: - return std::make_unique(v->ForceAsInt()); + return std::make_unique(v->AsCount()); case TYPE_INTERNAL_ADDR: return v->AsAddr().MakeHashKey(); @@ -855,7 +857,7 @@ const char* CompositeHash::RecoverOneVal( if ( ! f ) reporter->InternalError("failed to look up unique function id %" PRIu32 " in CompositeHash::RecoverOneVal()", *kp); - *pval = make_intrusive(f); + *pval = make_intrusive(f); const auto& pvt = (*pval)->GetType(); if ( ! pvt ) diff --git a/src/Conn.cc b/src/Conn.cc index 1a27863f94..9bd79d5b98 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -434,7 +434,7 @@ void Connection::AppendAddl(const char* str) { 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"; cv->Assign(6, make_intrusive(util::fmt(format, old, str))); diff --git a/src/Expr.cc b/src/Expr.cc index c148c5538f..dd23a546fa 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -1853,7 +1853,7 @@ ValPtr EqExpr::Fold(Val* v1, Val* v2) const { if ( op1->GetType()->Tag() == TYPE_PATTERN ) { - RE_Matcher* re = v1->AsPattern(); + auto re = dynamic_cast(v1); const String* s = v2->AsString(); if ( tag == EXPR_EQ ) 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 ) { - RE_Matcher* re = v1->AsPattern(); + auto re = dynamic_cast(v1); const String* s = v2->AsString(); return val_mgr->Bool(re->MatchAnywhere(s) != 0); } @@ -4412,7 +4412,7 @@ LambdaExpr::LambdaExpr(std::unique_ptr arg_ing, // Update lamb's name dummy_func->SetName(my_name.c_str()); - auto v = make_intrusive(std::move(dummy_func)); + auto v = make_intrusive(std::move(dummy_func)); id->SetVal(std::move(v)); id->SetType(ingredients->id->GetType()); id->SetConst(); @@ -4502,7 +4502,7 @@ ValPtr LambdaExpr::Eval(Frame* f) const // Allows for lookups by the receiver. lamb->SetName(my_name.c_str()); - return make_intrusive(std::move(lamb)); + return make_intrusive(std::move(lamb)); } void LambdaExpr::ExprDescribe(ODesc* d) const diff --git a/src/File.cc b/src/File.cc index 66b125fe16..7ab0137467 100644 --- a/src/File.cc +++ b/src/File.cc @@ -331,7 +331,7 @@ void File::RaiseOpenEvent() return; FilePtr bf{NewRef{}, this}; - auto* event = new Event(::file_opened, {make_intrusive(std::move(bf))}); + auto* event = new Event(::file_opened, {make_intrusive(std::move(bf))}); event_mgr.Dispatch(event, true); } diff --git a/src/Func.cc b/src/Func.cc index 0206fc7485..ed90e3b95a 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -702,7 +702,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, reporter->InternalError("built-in function %s multiply defined", Name()); type = id->GetType(); - id->SetVal(make_intrusive(IntrusivePtr{NewRef{}, this})); + id->SetVal(make_intrusive(IntrusivePtr{NewRef{}, this})); id->SetConst(); } diff --git a/src/ID.cc b/src/ID.cc index 7341f4782b..45695a16d8 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -87,7 +87,7 @@ FuncPtr id::find_func(std::string_view name) reporter->InternalError("Expected variable '%s' to be a function", std::string(name).data()); - return v->AsFuncPtr(); + return dynamic_cast(v.get())->AsFuncPtr(); } void id::detail::init_types() @@ -162,17 +162,18 @@ void ID::SetVal(ValPtr v) type->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT ) { EventHandler* handler = event_registry->Lookup(name); + auto func = dynamic_cast(val.get())->AsFuncPtr(); if ( ! handler ) { handler = new EventHandler(name); - handler->SetFunc(val->AsFuncPtr()); + handler->SetFunc(func); event_registry->Register(handler); } else { // Otherwise, internally defined events cannot // have local handler. - handler->SetFunc(val->AsFuncPtr()); + handler->SetFunc(func); } } } diff --git a/src/Reporter.cc b/src/Reporter.cc index 241c8aa050..6f6000dbd5 100644 --- a/src/Reporter.cc +++ b/src/Reporter.cc @@ -369,11 +369,11 @@ bool Reporter::PermitFlowWeird(const char* name, bool Reporter::PermitExpiredConnWeird(const char* name, const RecordVal& conn_id) { - auto conn_tuple = std::make_tuple(conn_id.GetField("orig_h")->AsAddr(), - conn_id.GetField("resp_h")->AsAddr(), - conn_id.GetField("orig_p")->AsPortVal()->Port(), - conn_id.GetField("resp_p")->AsPortVal()->Port(), - conn_id.GetField("resp_p")->AsPortVal()->PortType()); + auto conn_tuple = std::make_tuple(conn_id.GetAddrField("orig_h"), + conn_id.GetAddrField("resp_h"), + conn_id.GetPortValField("orig_p")->Port(), + conn_id.GetPortValField("resp_p")->Port(), + conn_id.GetPortValField("resp_p")->PortType()); auto& map = expired_conn_weird_state[conn_tuple]; diff --git a/src/Sessions.cc b/src/Sessions.cc index 15dfb91cb1..30d2686a6e 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -318,7 +318,7 @@ Connection* NetSessions::FindConnection(Val* v) return nullptr; RecordType* vr = vt->AsRecordType(); - auto vl = v->AsRecord(); + auto vl = dynamic_cast(v); int orig_h, orig_p; // indices into record's value list int resp_h, resp_p; @@ -346,11 +346,11 @@ Connection* NetSessions::FindConnection(Val* v) // types, too. } - const IPAddr& orig_addr = (*vl)[orig_h]->AsAddr(); - const IPAddr& resp_addr = (*vl)[resp_h]->AsAddr(); + const IPAddr& orig_addr = vl->GetAddrField(orig_h); + const IPAddr& resp_addr = vl->GetAddrField(resp_h); - PortVal* orig_portv = (*vl)[orig_p]->AsPortVal(); - PortVal* resp_portv = (*vl)[resp_p]->AsPortVal(); + const PortVal* orig_portv = vl->GetPortValField(orig_p); + const PortVal* resp_portv = vl->GetPortValField(resp_p); ConnID id; diff --git a/src/SmithWaterman.cc b/src/SmithWaterman.cc index 30613ff1ab..826690726f 100644 --- a/src/SmithWaterman.cc +++ b/src/SmithWaterman.cc @@ -109,19 +109,19 @@ Substring::Vec* Substring::VecFromPolicy(VectorVal* vec) if ( ! v ) continue; - const String* str = v->AsRecordVal()->GetField(0)->AsString(); + const String* str = v->AsRecordVal()->GetStringField(0); auto* substr = new Substring(*str); const VectorVal* aligns = v->AsRecordVal()->GetField(1)->AsVectorVal(); for ( unsigned int j = 1; j <= aligns->Size(); ++j ) { const RecordVal* align = aligns->AsVectorVal()->At(j)->AsRecordVal(); - const String* str = align->GetField(0)->AsString(); - int index = align->GetField(1)->AsCount(); + const String* str = align->GetStringField(0); + int index = align->GetCountField(1); substr->AddAlignment(str, index); } - bool new_alignment = v->AsRecordVal()->GetField(2)->AsBool(); + bool new_alignment = v->AsRecordVal()->GetBoolField(2); substr->MarkNewAlignment(new_alignment); result->push_back(substr); diff --git a/src/Stats.cc b/src/Stats.cc index 0265eb850e..2479349093 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -324,7 +324,7 @@ void ProfileLogger::Log() if ( profiling_update ) { event_mgr.Dispatch(new Event(profiling_update, { - make_intrusive(IntrusivePtr{NewRef{}, file}), + make_intrusive(IntrusivePtr{NewRef{}, file}), val_mgr->Bool(expensive), })); } diff --git a/src/Val.cc b/src/Val.cc index f9027c7e9d..1343a4caf0 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -46,41 +46,8 @@ using namespace std; namespace zeek { -Val::Val(Func* f) : Val({NewRef{}, f}) - {} - -Val::Val(FuncPtr f) - : val(f.release()), type(val.func_val->GetType()) - {} - -static const FileTypePtr& GetStringFileType() noexcept - { - static auto string_file_type - = make_intrusive(base_type(TYPE_STRING)); - - return string_file_type; - } - -Val::Val(File* f) : Val({AdoptRef{}, f}) - {} - -Val::Val(FilePtr f) - : val(f.release()), type(GetStringFileType()) - { - assert(val.file_val->GetType()->Tag() == TYPE_STRING); - } - Val::~Val() { - if ( type->InternalType() == TYPE_INTERNAL_STRING ) - delete val.string_val; - - else if ( type->Tag() == TYPE_FUNC ) - Unref(val.func_val); - - else if ( type->Tag() == TYPE_FILE ) - Unref(val.file_val); - #ifdef DEBUG delete [] bound_id; #endif @@ -153,25 +120,8 @@ ValPtr Val::DoClone(CloneState* state) return {NewRef{}, this}; case TYPE_INTERNAL_OTHER: - // Derived classes are responsible for this. Exception: - // Functions and files. There aren't any derived classes. - if ( type->Tag() == TYPE_FUNC ) - return make_intrusive(AsFunc()->DoClone()); - - if ( type->Tag() == TYPE_FILE ) - { - // I think we can just ref the file here - it is unclear what else - // to do. In the case of cached files, I think this is equivalent - // to what happened before - serialization + unserialization just - // have you the same pointer that you already had. In the case of - // non-cached files, the behavior now is different; in the past, - // serialize + unserialize gave you a new file object because the - // old one was not in the list anymore. This object was - // automatically opened. This does not happen anymore - instead you - // get the non-cached pointer back which is brought back into the - // cache when written too. - return {NewRef{}, this}; - } + // Derived classes are responsible for this, other than + // the weirdo "type" pseudo-value. if ( type->Tag() == TYPE_TYPE ) // These are immutable, essentially. @@ -187,18 +137,12 @@ ValPtr Val::DoClone(CloneState* state) return nullptr; } -FuncPtr Val::AsFuncPtr() const - { - CHECK_TAG(type->Tag(), TYPE_FUNC, "Val::Func", type_name) - return {NewRef{}, val.func_val}; - } - bool Val::IsZero() const { switch ( type->InternalType() ) { - case TYPE_INTERNAL_INT: return val.int_val == 0; - case TYPE_INTERNAL_UNSIGNED: return val.uint_val == 0; - case TYPE_INTERNAL_DOUBLE: return val.double_val == 0.0; + case TYPE_INTERNAL_INT: return AsInt() == 0; + case TYPE_INTERNAL_UNSIGNED: return AsCount() == 0; + case TYPE_INTERNAL_DOUBLE: return AsDouble() == 0.0; default: return false; } @@ -207,9 +151,9 @@ bool Val::IsZero() const bool Val::IsOne() const { switch ( type->InternalType() ) { - case TYPE_INTERNAL_INT: return val.int_val == 1; - case TYPE_INTERNAL_UNSIGNED: return val.uint_val == 1; - case TYPE_INTERNAL_DOUBLE: return val.double_val == 1.0; + case TYPE_INTERNAL_INT: return AsInt() == 1; + case TYPE_INTERNAL_UNSIGNED: return AsCount() == 1; + case TYPE_INTERNAL_DOUBLE: return AsDouble() == 1.0; default: return false; } @@ -218,10 +162,10 @@ bool Val::IsOne() const bro_int_t Val::InternalInt() const { if ( type->InternalType() == TYPE_INTERNAL_INT ) - return val.int_val; + return AsInt(); else if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED ) // ### should check here for overflow - return static_cast(val.uint_val); + return static_cast(AsCount()); else InternalWarning("bad request for InternalInt"); @@ -231,7 +175,7 @@ bro_int_t Val::InternalInt() const bro_uint_t Val::InternalUnsigned() const { if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED ) - return val.uint_val; + return AsCount(); else InternalWarning("bad request for InternalUnsigned"); @@ -241,7 +185,7 @@ bro_uint_t Val::InternalUnsigned() const double Val::InternalDouble() const { if ( type->InternalType() == TYPE_INTERNAL_DOUBLE ) - return val.double_val; + return AsDouble(); else InternalWarning("bad request for InternalDouble"); @@ -251,11 +195,11 @@ double Val::InternalDouble() const bro_int_t Val::CoerceToInt() const { if ( type->InternalType() == TYPE_INTERNAL_INT ) - return val.int_val; + return AsInt(); else if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED ) - return static_cast(val.uint_val); + return static_cast(AsCount()); else if ( type->InternalType() == TYPE_INTERNAL_DOUBLE ) - return static_cast(val.double_val); + return static_cast(AsDouble()); else InternalWarning("bad request for CoerceToInt"); @@ -265,11 +209,11 @@ bro_int_t Val::CoerceToInt() const bro_uint_t Val::CoerceToUnsigned() const { if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED ) - return val.uint_val; + return AsCount(); else if ( type->InternalType() == TYPE_INTERNAL_INT ) - return static_cast(val.int_val); + return static_cast(AsInt()); else if ( type->InternalType() == TYPE_INTERNAL_DOUBLE ) - return static_cast(val.double_val); + return static_cast(AsDouble()); else InternalWarning("bad request for CoerceToUnsigned"); @@ -279,11 +223,11 @@ bro_uint_t Val::CoerceToUnsigned() const double Val::CoerceToDouble() const { if ( type->InternalType() == TYPE_INTERNAL_DOUBLE ) - return val.double_val; + return AsDouble(); else if ( type->InternalType() == TYPE_INTERNAL_INT ) - return static_cast(val.int_val); + return static_cast(AsInt()); else if ( type->InternalType() == TYPE_INTERNAL_UNSIGNED ) - return static_cast(val.uint_val); + return static_cast(AsCount()); else InternalWarning("bad request for CoerceToDouble"); @@ -296,24 +240,16 @@ ValPtr Val::SizeVal() const case TYPE_INTERNAL_INT: // Return abs value. However abs() only works on ints and llabs // doesn't work on Mac OS X 10.5. So we do it by hand - if ( val.int_val < 0 ) - return val_mgr->Count(-val.int_val); + if ( AsInt() < 0 ) + return val_mgr->Count(-AsInt()); else - return val_mgr->Count(val.int_val); + return val_mgr->Count(AsInt()); case TYPE_INTERNAL_UNSIGNED: - return val_mgr->Count(val.uint_val); + return val_mgr->Count(AsCount()); case TYPE_INTERNAL_DOUBLE: - return make_intrusive(fabs(val.double_val)); - - case TYPE_INTERNAL_OTHER: - if ( type->Tag() == TYPE_FUNC ) - return val_mgr->Count(val.func_val->GetType()->ParamList()->GetTypes().size()); - - if ( type->Tag() == TYPE_FILE ) - return make_intrusive(val.file_val->Size()); - break; + return make_intrusive(fabs(AsDouble())); default: break; @@ -364,23 +300,23 @@ void Val::ValDescribe(ODesc* d) const } switch ( type->InternalType() ) { - case TYPE_INTERNAL_INT: d->Add(val.int_val); break; - case TYPE_INTERNAL_UNSIGNED: d->Add(val.uint_val); break; - case TYPE_INTERNAL_DOUBLE: d->Add(val.double_val); break; - case TYPE_INTERNAL_STRING: d->AddBytes(val.string_val); break; - case TYPE_INTERNAL_ADDR: d->Add(val.addr_val->AsString().c_str()); break; + case TYPE_INTERNAL_INT: d->Add(AsInt()); break; + case TYPE_INTERNAL_UNSIGNED: d->Add(AsCount()); break; + case TYPE_INTERNAL_DOUBLE: d->Add(AsDouble()); break; + case TYPE_INTERNAL_STRING: d->AddBytes(AsString()); break; + + case TYPE_INTERNAL_ADDR: + d->Add(AsAddr().AsString().c_str()); + break; case TYPE_INTERNAL_SUBNET: - d->Add(val.subnet_val->AsString().c_str()); + d->Add(AsSubNet().AsString().c_str()); break; case TYPE_INTERNAL_ERROR: d->AddCS("error"); break; + case TYPE_INTERNAL_OTHER: - if ( type->Tag() == TYPE_FUNC ) - AsFunc()->Describe(d); - else if ( type->Tag() == TYPE_FILE ) - AsFile()->Describe(d); - else if ( type->Tag() == TYPE_TYPE ) + if ( type->Tag() == TYPE_TYPE ) d->Add(type->AsTypeType()->GetType()->GetName()); else d->Add(""); @@ -710,7 +646,7 @@ void IntervalVal::ValDescribe(ODesc* d) const unit_word{ Microseconds, "usec" }, }; - double v = val.double_val; + double v = AsDouble(); if ( v == 0.0 ) { @@ -772,7 +708,7 @@ void IntervalVal::ValDescribe(ODesc* d) const ValPtr PortVal::SizeVal() const { - return val_mgr->Int(val.uint_val); + return val_mgr->Int(uint_val); } uint32_t PortVal::Mask(uint32_t port_num, TransportProto port_type) @@ -806,13 +742,13 @@ uint32_t PortVal::Mask(uint32_t port_num, TransportProto port_type) return port_num; } -PortVal::PortVal(uint32_t p) : Val(bro_uint_t(p), TYPE_PORT) +PortVal::PortVal(uint32_t p) : CountVal(bro_uint_t(p), base_type(TYPE_PORT)) { } uint32_t PortVal::Port() const { - uint32_t p = static_cast(val.uint_val); + uint32_t p = static_cast(uint_val); return p & ~PORT_SPACE_MASK; } @@ -830,22 +766,22 @@ string PortVal::Protocol() const bool PortVal::IsTCP() const { - return (val.uint_val & PORT_SPACE_MASK) == TCP_PORT_MASK; + return (uint_val & PORT_SPACE_MASK) == TCP_PORT_MASK; } bool PortVal::IsUDP() const { - return (val.uint_val & PORT_SPACE_MASK) == UDP_PORT_MASK; + return (uint_val & PORT_SPACE_MASK) == UDP_PORT_MASK; } bool PortVal::IsICMP() const { - return (val.uint_val & PORT_SPACE_MASK) == ICMP_PORT_MASK; + return (uint_val & PORT_SPACE_MASK) == ICMP_PORT_MASK; } void PortVal::ValDescribe(ODesc* d) const { - uint32_t p = static_cast(val.uint_val); + uint32_t p = static_cast(uint_val); d->Add(p & ~PORT_SPACE_MASK); d->Add("/"); d->Add(Protocol()); @@ -857,40 +793,44 @@ ValPtr PortVal::DoClone(CloneState* state) return {NewRef{}, this}; } -AddrVal::AddrVal(const char* text) : Val(new IPAddr(text), TYPE_ADDR) +AddrVal::AddrVal(const char* text) : Val(base_type(TYPE_ADDR)) { + addr_val = new IPAddr(text); } AddrVal::AddrVal(const std::string& text) : AddrVal(text.c_str()) { } -AddrVal::AddrVal(uint32_t addr) : Val(new IPAddr(IPv4, &addr, IPAddr::Network), TYPE_ADDR) +AddrVal::AddrVal(uint32_t addr) : Val(base_type(TYPE_ADDR)) { + addr_val = new IPAddr(IPv4, &addr, IPAddr::Network); // ### perhaps do gethostbyaddr here? } -AddrVal::AddrVal(const uint32_t addr[4]) : Val(new IPAddr(IPv6, addr, IPAddr::Network), TYPE_ADDR) +AddrVal::AddrVal(const uint32_t addr[4]) : Val(base_type(TYPE_ADDR)) { + addr_val = new IPAddr(IPv6, addr, IPAddr::Network); } -AddrVal::AddrVal(const IPAddr& addr) : Val(new IPAddr(addr), TYPE_ADDR) +AddrVal::AddrVal(const IPAddr& addr) : Val(base_type(TYPE_ADDR)) { + addr_val = new IPAddr(addr); } AddrVal::~AddrVal() { - delete val.addr_val; + delete addr_val; } unsigned int AddrVal::MemoryAllocation() const { - return padded_sizeof(*this) + val.addr_val->MemoryAllocation(); + return padded_sizeof(*this) + addr_val->MemoryAllocation(); } ValPtr AddrVal::SizeVal() const { - if ( val.addr_val->GetFamily() == IPv4 ) + if ( addr_val->GetFamily() == IPv4 ) return val_mgr->Count(32); else return val_mgr->Count(128); @@ -902,14 +842,17 @@ ValPtr AddrVal::DoClone(CloneState* state) return {NewRef{}, this}; } -SubNetVal::SubNetVal(const char* text) : Val(new IPPrefix(), TYPE_SUBNET) +SubNetVal::SubNetVal(const char* text) : Val(base_type(TYPE_SUBNET)) { - if ( ! IPPrefix::ConvertString(text, val.subnet_val) ) + subnet_val = new IPPrefix(); + + if ( ! IPPrefix::ConvertString(text, subnet_val) ) reporter->Error("Bad string in SubNetVal ctor: %s", text); } -SubNetVal::SubNetVal(const char* text, int width) : Val(new IPPrefix(text, width), TYPE_SUBNET) +SubNetVal::SubNetVal(const char* text, int width) : Val(base_type(TYPE_SUBNET)) { + subnet_val = new IPPrefix(text, width); } SubNetVal::SubNetVal(uint32_t addr, int width) : SubNetVal(IPAddr{IPv4, &addr, IPAddr::Network}, width) @@ -920,48 +863,50 @@ SubNetVal::SubNetVal(const uint32_t* addr, int width) : SubNetVal(IPAddr{IPv6, a { } -SubNetVal::SubNetVal(const IPAddr& addr, int width) : Val(new IPPrefix(addr, width), TYPE_SUBNET) +SubNetVal::SubNetVal(const IPAddr& addr, int width) : Val(base_type(TYPE_SUBNET)) { + subnet_val = new IPPrefix(addr, width); } -SubNetVal::SubNetVal(const IPPrefix& prefix) : Val(new IPPrefix(prefix), TYPE_SUBNET) +SubNetVal::SubNetVal(const IPPrefix& prefix) : Val(base_type(TYPE_SUBNET)) { + subnet_val = new IPPrefix(prefix); } SubNetVal::~SubNetVal() { - delete val.subnet_val; + delete subnet_val; } const IPAddr& SubNetVal::Prefix() const { - return val.subnet_val->Prefix(); + return subnet_val->Prefix(); } int SubNetVal::Width() const { - return val.subnet_val->Length(); + return subnet_val->Length(); } unsigned int SubNetVal::MemoryAllocation() const { - return padded_sizeof(*this) + val.subnet_val->MemoryAllocation(); + return padded_sizeof(*this) + subnet_val->MemoryAllocation(); } ValPtr SubNetVal::SizeVal() const { - int retained = 128 - val.subnet_val->LengthIPv6(); + int retained = 128 - subnet_val->LengthIPv6(); return make_intrusive(pow(2.0, double(retained))); } void SubNetVal::ValDescribe(ODesc* d) const { - d->Add(string(*val.subnet_val).c_str()); + d->Add(string(*subnet_val).c_str()); } IPAddr SubNetVal::Mask() const { - if ( val.subnet_val->Length() == 0 ) + if ( subnet_val->Length() == 0 ) { // We need to special-case a mask width of zero, since // the compiler doesn't guarantee that 1 << 32 yields 0. @@ -976,7 +921,7 @@ IPAddr SubNetVal::Mask() const uint32_t* mp = m; uint32_t w; - for ( w = val.subnet_val->Length(); w >= 32; w -= 32 ) + for ( w = subnet_val->Length(); w >= 32; w -= 32 ) *(mp++) = 0xffffffff; *mp = ~((1 << (32 - w)) - 1); @@ -990,7 +935,7 @@ IPAddr SubNetVal::Mask() const bool SubNetVal::Contains(const IPAddr& addr) const { - return val.subnet_val->Contains(addr); + return subnet_val->Contains(addr); } ValPtr SubNetVal::DoClone(CloneState* state) @@ -999,8 +944,9 @@ ValPtr SubNetVal::DoClone(CloneState* state) return {NewRef{}, this}; } -StringVal::StringVal(String* s) : Val(s, TYPE_STRING) +StringVal::StringVal(String* s) : Val(base_type(TYPE_STRING)) { + string_val = s; } // The following adds a NUL at the end. @@ -1017,9 +963,14 @@ StringVal::StringVal(const string& s) : StringVal(s.length(), s.data()) { } +StringVal::~StringVal() + { + delete string_val; + } + ValPtr StringVal::SizeVal() const { - return val_mgr->Count(val.string_val->Len()); + return val_mgr->Count(string_val->Len()); } int StringVal::Len() @@ -1045,7 +996,7 @@ string StringVal::ToStdString() const StringVal* StringVal::ToUpper() { - val.string_val->ToUpper(); + string_val->ToUpper(); return this; } @@ -1054,14 +1005,14 @@ void StringVal::ValDescribe(ODesc* d) const // Should reintroduce escapes ? ### if ( d->WantQuotes() ) d->Add("\""); - d->AddBytes(val.string_val); + d->AddBytes(string_val); if ( d->WantQuotes() ) d->Add("\""); } unsigned int StringVal::MemoryAllocation() const { - return padded_sizeof(*this) + val.string_val->MemoryAllocation(); + return padded_sizeof(*this) + string_val->MemoryAllocation(); } StringValPtr StringVal::Replace( @@ -1155,19 +1106,76 @@ ValPtr StringVal::DoClone(CloneState* state) // instead of creating a new copy, but we first need to be careful and // audit whether anything internal actually does mutate it. return state->NewClone(this, make_intrusive( - new String((u_char*) val.string_val->Bytes(), - val.string_val->Len(), true))); + new String((u_char*) string_val->Bytes(), + string_val->Len(), true))); + } + +FuncVal::FuncVal(FuncPtr f) : Val(f->GetType()) + { + func_val = std::move(f); + } + +FuncPtr FuncVal::AsFuncPtr() const + { + return func_val; + } + +ValPtr FuncVal::SizeVal() const + { + return val_mgr->Count(func_val->GetType()->ParamList()->GetTypes().size()); + } + +void FuncVal::ValDescribe(ODesc* d) const + { + func_val->Describe(d); + } + +ValPtr FuncVal::DoClone(CloneState* state) + { + return make_intrusive(func_val->DoClone()); + } + +FileVal::FileVal(FilePtr f) +: Val(make_intrusive(base_type(TYPE_STRING))) + { + file_val = std::move(f); + assert(file_val->GetType()->Tag() == TYPE_STRING); + } + +ValPtr FileVal::SizeVal() const + { + return make_intrusive(file_val->Size()); + } + +void FileVal::ValDescribe(ODesc* d) const + { + file_val->Describe(d); + } + +ValPtr FileVal::DoClone(CloneState* state) + { + // I think we can just ref the file here - it is unclear what else + // to do. In the case of cached files, I think this is equivalent + // to what happened before - serialization + unserialization just + // have you the same pointer that you already had. In the case of + // non-cached files, the behavior now is different; in the past, + // serialize + unserialize gave you a new file object because the + // old one was not in the list anymore. This object was + // automatically opened. This does not happen anymore - instead you + // get the non-cached pointer back which is brought back into the + // cache when written too. + return {NewRef{}, this}; } PatternVal::PatternVal(RE_Matcher* re) : Val(base_type(TYPE_PATTERN)) { - val.re_val = re; + re_val = re; } PatternVal::~PatternVal() { - delete AsPattern(); + delete re_val; } bool PatternVal::AddTo(Val* v, bool /* is_first_init */) const @@ -1192,7 +1200,17 @@ bool PatternVal::AddTo(Val* v, bool /* is_first_init */) const void PatternVal::SetMatcher(RE_Matcher* re) { delete AsPattern(); - val.re_val = re; + re_val = re; + } + +bool PatternVal::MatchExactly(const String* s) const + { + return re_val->MatchExactly(s); + } + +bool PatternVal::MatchAnywhere(const String* s) const + { + return re_val->MatchAnywhere(s); } void PatternVal::ValDescribe(ODesc* d) const @@ -1204,7 +1222,7 @@ void PatternVal::ValDescribe(ODesc* d) const unsigned int PatternVal::MemoryAllocation() const { - return padded_sizeof(*this) + val.re_val->MemoryAllocation(); + return padded_sizeof(*this) + re_val->MemoryAllocation(); } ValPtr PatternVal::DoClone(CloneState* state) @@ -1212,8 +1230,8 @@ ValPtr PatternVal::DoClone(CloneState* state) // We could likely treat this type as immutable and return a reference // instead of creating a new copy, but we first need to be careful and // audit whether anything internal actually does mutate it. - auto re = new RE_Matcher(val.re_val->PatternText(), - val.re_val->AnywherePatternText()); + auto re = new RE_Matcher(re_val->PatternText(), + re_val->AnywherePatternText()); re->Compile(); return state->NewClone(this, make_intrusive(re)); } @@ -1442,8 +1460,8 @@ void TableVal::Init(TableTypePtr t) subnets = nullptr; table_hash = new detail::CompositeHash(table_type->GetIndices()); - val.table_val = new PDict; - val.table_val->SetDeleteFunc(table_entry_val_delete_func); + table_val = new PDict; + table_val->SetDeleteFunc(table_entry_val_delete_func); } TableVal::~TableVal() @@ -1452,36 +1470,35 @@ TableVal::~TableVal() detail::timer_mgr->Cancel(timer); delete table_hash; - delete AsTable(); + delete table_val; delete subnets; } void TableVal::RemoveAll() { // Here we take the brute force approach. - delete AsTable(); - val.table_val = new PDict; - val.table_val->SetDeleteFunc(table_entry_val_delete_func); + delete table_val; + table_val = new PDict; + table_val->SetDeleteFunc(table_entry_val_delete_func); } int TableVal::Size() const { - return AsTable()->Length(); + return table_val->Length(); } int TableVal::RecursiveSize() const { - int n = AsTable()->Length(); + int n = table_val->Length(); if ( GetType()->IsSet() || GetType()->AsTableType()->Yield()->Tag() != TYPE_TABLE ) return n; - PDict* v = val.table_val; - IterCookie* c = v->InitForIteration(); + IterCookie* c = table_val->InitForIteration(); TableEntryVal* tv; - while ( (tv = v->NextEntry(c)) ) + while ( (tv = table_val->NextEntry(c)) ) { if ( tv->GetVal() ) n += tv->GetVal()->AsTableVal()->RecursiveSize(); @@ -1577,7 +1594,7 @@ bool TableVal::Assign(ValPtr index, std::unique_ptr k, TableEntryVal* new_entry_val = new TableEntryVal(std::move(new_val)); detail::HashKey k_copy(k->Key(), k->Size(), k->Hash()); - TableEntryVal* old_entry_val = AsNonConstTable()->Insert(k.get(), new_entry_val, iterators_invalidated); + TableEntryVal* old_entry_val = table_val->Insert(k.get(), new_entry_val, iterators_invalidated); // If the dictionary index already existed, the insert may free up the // memory allocated to the key bytes, so have to assume k is invalid @@ -1652,12 +1669,11 @@ bool TableVal::AddTo(Val* val, bool is_first_init, bool propagate_ops) const return false; } - const PDict* tbl = AsTable(); - IterCookie* c = tbl->InitForIteration(); + IterCookie* c = table_val->InitForIteration(); detail::HashKey* k; TableEntryVal* v; - while ( (v = tbl->NextEntry(k, c)) ) + while ( (v = table_val->NextEntry(k, c)) ) { std::unique_ptr hk{k}; @@ -1700,11 +1716,10 @@ bool TableVal::RemoveFrom(Val* val) const return false; } - const PDict* tbl = AsTable(); - IterCookie* c = tbl->InitForIteration(); + IterCookie* c = table_val->InitForIteration(); detail::HashKey* k; - while ( tbl->NextEntry(k, c) ) + while ( table_val->NextEntry(k, c) ) { // Not sure that this is 100% sound, since the HashKey // comes from one table but is being used in another. @@ -1722,9 +1737,8 @@ TableValPtr TableVal::Intersection(const TableVal& tv) const { auto result = make_intrusive(table_type); - const PDict* t0 = AsTable(); + const PDict* t0 = table_val; const PDict* t1 = tv.AsTable(); - PDict* t2 = result->AsNonConstTable(); // Figure out which is smaller; assign it to t1. if ( t1->Length() > t0->Length() ) @@ -1741,7 +1755,7 @@ TableValPtr TableVal::Intersection(const TableVal& tv) const // Here we leverage the same assumption about consistent // hashes as in TableVal::RemoveFrom above. if ( t0->Lookup(k) ) - t2->Insert(k, new TableEntryVal(nullptr)); + result->Insert(k, new TableEntryVal(nullptr)); delete k; } @@ -1751,7 +1765,7 @@ TableValPtr TableVal::Intersection(const TableVal& tv) const bool TableVal::EqualTo(const TableVal& tv) const { - const PDict* t0 = AsTable(); + const PDict* t0 = table_val; const PDict* t1 = tv.AsTable(); if ( t0->Length() != t1->Length() ) @@ -1778,7 +1792,7 @@ bool TableVal::EqualTo(const TableVal& tv) const bool TableVal::IsSubsetOf(const TableVal& tv) const { - const PDict* t0 = AsTable(); + const PDict* t0 = table_val; const PDict* t1 = tv.AsTable(); if ( t0->Length() > t1->Length() ) @@ -1958,15 +1972,13 @@ const ValPtr& TableVal::Find(const ValPtr& index) return Val::nil; } - const PDict* tbl = AsTable(); - - if ( tbl->Length() > 0 ) + if ( table_val->Length() > 0 ) { auto k = MakeHashKey(*index); if ( k ) { - TableEntryVal* v = AsTable()->Lookup(k.get()); + TableEntryVal* v = table_val->Lookup(k.get()); if ( v ) { @@ -2074,7 +2086,7 @@ bool TableVal::UpdateTimestamp(Val* index) if ( ! k ) return false; - v = AsTable()->Lookup(k.get()); + v = table_val->Lookup(k.get()); } if ( ! v ) @@ -2264,11 +2276,16 @@ void TableVal::SendToStore(const Val* index, const TableEntryVal* new_entry_val, } } +void TableVal::Insert(detail::HashKey* k, TableEntryVal* tev) + { + table_val->Insert(k, tev); + } + ValPtr TableVal::Remove(const Val& index, bool broker_forward, bool* iterators_invalidated) { auto k = MakeHashKey(index); - TableEntryVal* v = k ? AsNonConstTable()->RemoveEntry(k.get(), iterators_invalidated) : nullptr; + TableEntryVal* v = k ? table_val->RemoveEntry(k.get(), iterators_invalidated) : nullptr; ValPtr va; if ( v ) @@ -2296,7 +2313,7 @@ ValPtr TableVal::Remove(const Val& index, bool broker_forward, bool* iterators_i ValPtr TableVal::Remove(const detail::HashKey& k, bool* iterators_invalidated) { - TableEntryVal* v = AsNonConstTable()->RemoveEntry(k, iterators_invalidated); + TableEntryVal* v = table_val->RemoveEntry(k, iterators_invalidated); ValPtr va; if ( v ) @@ -2331,11 +2348,10 @@ ListValPtr TableVal::ToListVal(TypeTag t) const { auto l = make_intrusive(t); - const PDict* tbl = AsTable(); - IterCookie* c = tbl->InitForIteration(); + IterCookie* c = table_val->InitForIteration(); detail::HashKey* k; - while ( tbl->NextEntry(k, c) ) + while ( table_val->NextEntry(k, c) ) { auto index = table_hash->RecoverVals(*k); @@ -2385,8 +2401,7 @@ const detail::AttrPtr& TableVal::GetAttr(detail::AttrTag t) const void TableVal::Describe(ODesc* d) const { - const PDict* tbl = AsTable(); - int n = tbl->Length(); + int n = table_val->Length(); if ( d->IsBinary() || d->IsPortable() ) { @@ -2402,12 +2417,12 @@ void TableVal::Describe(ODesc* d) const d->PushIndent(); } - IterCookie* c = tbl->InitForIteration(); + IterCookie* c = table_val->InitForIteration(); for ( int i = 0; i < n; ++i ) { detail::HashKey* k; - TableEntryVal* v = tbl->NextEntry(k, c); + TableEntryVal* v = table_val->NextEntry(k, c); if ( ! v ) reporter->InternalError("hash table underflow in TableVal::Describe"); @@ -2459,7 +2474,7 @@ void TableVal::Describe(ODesc* d) const } } - if ( tbl->NextEntry(c) ) + if ( table_val->NextEntry(c) ) reporter->InternalError("hash table overflow in TableVal::Describe"); if ( d->IsPortable() || d->IsReadable() ) @@ -2547,8 +2562,6 @@ void TableVal::DoExpire(double t) if ( ! type ) return; // FIX ME ### - PDict* tbl = AsNonConstTable(); - double timeout = GetExpireTime(); if ( timeout < 0 ) @@ -2558,8 +2571,8 @@ void TableVal::DoExpire(double t) if ( ! expire_cookie ) { - expire_cookie = tbl->InitForIteration(); - tbl->MakeRobustCookie(expire_cookie); + expire_cookie = table_val->InitForIteration(); + table_val->MakeRobustCookie(expire_cookie); } detail::HashKey* k = nullptr; @@ -2568,7 +2581,7 @@ void TableVal::DoExpire(double t) bool modified = false; for ( int i = 0; i < zeek::detail::table_incremental_step && - (v = tbl->NextEntry(k, expire_cookie)); ++i ) + (v = table_val->NextEntry(k, expire_cookie)); ++i ) { if ( v->ExpireAccessTime() == 0 ) { @@ -2592,7 +2605,7 @@ void TableVal::DoExpire(double t) // function modified or deleted the table // value, so look it up again. v_saved = v; - v = tbl->Lookup(k); + v = table_val->Lookup(k); if ( ! v ) { // user-provided function deleted it @@ -2620,7 +2633,7 @@ void TableVal::DoExpire(double t) reporter->InternalWarning("index not in prefix table"); } - tbl->RemoveEntry(k); + table_val->RemoveEntry(k); if ( change_func ) { if ( ! idx ) @@ -2744,15 +2757,14 @@ ValPtr TableVal::DoClone(CloneState* state) auto tv = make_intrusive(table_type); state->NewClone(this, tv); - const PDict* tbl = AsTable(); - IterCookie* cookie = tbl->InitForIteration(); + IterCookie* cookie = table_val->InitForIteration(); detail::HashKey* key; TableEntryVal* val; - while ( (val = tbl->NextEntry(key, cookie)) ) + while ( (val = table_val->NextEntry(key, cookie)) ) { TableEntryVal* nval = val->Clone(state); - tv->AsNonConstTable()->Insert(key, nval); + tv->Insert(key, nval); if ( subnets ) { @@ -2788,18 +2800,17 @@ unsigned int TableVal::MemoryAllocation() const { unsigned int size = 0; - PDict* v = val.table_val; - IterCookie* c = v->InitForIteration(); + IterCookie* c = table_val->InitForIteration(); TableEntryVal* tv; - while ( (tv = v->NextEntry(c)) ) + while ( (tv = table_val->NextEntry(c)) ) { if ( tv->GetVal() ) size += tv->GetVal()->MemoryAllocation(); size += padded_sizeof(TableEntryVal); } - return size + padded_sizeof(*this) + val.table_val->MemoryAllocation() + return size + padded_sizeof(*this) + table_val->MemoryAllocation() + table_hash->MemoryAllocation(); } @@ -2839,15 +2850,14 @@ void TableVal::DoneParsing() TableVal::ParseTimeTableState TableVal::DumpTableState() { - const PDict* tbl = AsTable(); - IterCookie* cookie = tbl->InitForIteration(); + IterCookie* cookie = table_val->InitForIteration(); detail::HashKey* key; TableEntryVal* val; ParseTimeTableState rval; - while ( (val = tbl->NextEntry(key, cookie)) ) + while ( (val = table_val->NextEntry(key, cookie)) ) { rval.emplace_back(RecreateIndex(*key), val->GetVal()); delete key; @@ -2881,7 +2891,7 @@ RecordVal::RecordVal(RecordTypePtr t, bool init_fields) : Val(std::move(t)) origin = nullptr; auto rt = GetType()->AsRecordType(); int n = rt->NumFields(); - auto vl = val.record_val = new std::vector; + auto vl = record_val = new std::vector; vl->reserve(n); if ( run_state::is_parsing ) @@ -2908,7 +2918,7 @@ RecordVal::RecordVal(RecordTypePtr t, bool init_fields) : Val(std::move(t)) if ( run_state::is_parsing ) parse_time_records[rt].pop_back(); - delete AsNonConstRecord(); + delete record_val; throw; } @@ -2945,7 +2955,7 @@ RecordVal::RecordVal(RecordTypePtr t, bool init_fields) : Val(std::move(t)) RecordVal::~RecordVal() { - delete AsNonConstRecord(); + delete record_val; } ValPtr RecordVal::SizeVal() const @@ -2955,7 +2965,7 @@ ValPtr RecordVal::SizeVal() const void RecordVal::Assign(int field, ValPtr new_val) { - (*AsNonConstRecord())[field] = std::move(new_val); + (*record_val)[field] = std::move(new_val); Modified(); } @@ -2966,7 +2976,7 @@ void RecordVal::Assign(int field, Val* new_val) ValPtr RecordVal::GetFieldOrDefault(int field) const { - const auto& val = (*AsRecord())[field]; + const auto& val = (*record_val)[field]; if ( val ) return val; @@ -2985,16 +2995,15 @@ void RecordVal::ResizeParseTimeRecords(RecordType* rt) for ( auto& rv : rvs ) { - auto vs = rv->val.record_val; - int current_length = vs->size(); + int current_length = rv->NumFields(); auto required_length = rt->NumFields(); if ( required_length > current_length ) { - vs->reserve(required_length); + rv->Reserve(required_length); for ( auto i = current_length; i < required_length; ++i ) - vs->emplace_back(rt->FieldDefault(i)); + rv->AppendField(rt->FieldDefault(i)); } } } @@ -3103,8 +3112,7 @@ TableValPtr RecordVal::GetRecordFieldsVal() const void RecordVal::Describe(ODesc* d) const { - auto vl = AsRecord(); - auto n = vl->size(); + auto n = record_val->size(); auto record_type = GetType()->AsRecordType(); if ( d->IsBinary() || d->IsPortable() ) @@ -3127,7 +3135,7 @@ void RecordVal::Describe(ODesc* d) const if ( ! d->IsBinary() ) d->Add("="); - const auto& v = (*vl)[i]; + const auto& v = (*record_val)[i]; if ( v ) v->Describe(d); @@ -3141,8 +3149,7 @@ void RecordVal::Describe(ODesc* d) const void RecordVal::DescribeReST(ODesc* d) const { - auto vl = AsRecord(); - auto n = vl->size(); + auto n = record_val->size(); auto record_type = GetType()->AsRecordType(); d->Add("{"); @@ -3156,7 +3163,7 @@ void RecordVal::DescribeReST(ODesc* d) const d->Add(record_type->FieldName(i)); d->Add("="); - const auto& v = (*vl)[i]; + const auto& v = (*record_val)[i]; if ( v ) v->Describe(d); @@ -3179,10 +3186,10 @@ ValPtr RecordVal::DoClone(CloneState* state) rv->origin = nullptr; state->NewClone(this, rv); - for ( const auto& vlv : *val.record_val) + for ( const auto& vlv : *record_val) { auto v = vlv ? vlv->Clone(state) : nullptr; - rv->val.record_val->emplace_back(std::move(v)); + rv->AppendField(std::move(v)); } return rv; @@ -3191,7 +3198,7 @@ ValPtr RecordVal::DoClone(CloneState* state) unsigned int RecordVal::MemoryAllocation() const { unsigned int size = 0; - const auto& vl = *AsRecord(); + const auto& vl = *record_val; for ( const auto& v : vl ) { @@ -3206,12 +3213,12 @@ unsigned int RecordVal::MemoryAllocation() const ValPtr EnumVal::SizeVal() const { - return val_mgr->Int(val.int_val); + return val_mgr->Int(AsInt()); } void EnumVal::ValDescribe(ODesc* d) const { - const char* ename = type->AsEnumType()->Lookup(val.int_val); + const char* ename = type->AsEnumType()->Lookup(int_val); if ( ! ename ) ename = ""; @@ -3230,17 +3237,17 @@ VectorVal::VectorVal(VectorType* t) : VectorVal({NewRef{}, t}) VectorVal::VectorVal(VectorTypePtr t) : Val(std::move(t)) { - val.vector_val = new vector(); + vector_val = new vector(); } VectorVal::~VectorVal() { - delete val.vector_val; + delete vector_val; } ValPtr VectorVal::SizeVal() const { - return val_mgr->Count(uint32_t(val.vector_val->size())); + return val_mgr->Count(uint32_t(vector_val->size())); } bool VectorVal::Assign(unsigned int index, ValPtr element) @@ -3249,10 +3256,10 @@ bool VectorVal::Assign(unsigned int index, ValPtr element) ! same_type(element->GetType(), GetType()->AsVectorType()->Yield(), false) ) return false; - if ( index >= val.vector_val->size() ) - val.vector_val->resize(index + 1); + if ( index >= vector_val->size() ) + vector_val->resize(index + 1); - (*val.vector_val)[index] = std::move(element); + (*vector_val)[index] = std::move(element); Modified(); return true; @@ -3280,12 +3287,12 @@ bool VectorVal::Insert(unsigned int index, ValPtr element) vector::iterator it; - if ( index < val.vector_val->size() ) - it = std::next(val.vector_val->begin(), index); + if ( index < vector_val->size() ) + it = std::next(vector_val->begin(), index); else - it = val.vector_val->end(); + it = vector_val->end(); - val.vector_val->insert(it, std::move(element)); + vector_val->insert(it, std::move(element)); Modified(); return true; @@ -3293,11 +3300,11 @@ bool VectorVal::Insert(unsigned int index, ValPtr element) bool VectorVal::Remove(unsigned int index) { - if ( index >= val.vector_val->size() ) + if ( index >= vector_val->size() ) return false; - auto it = std::next(val.vector_val->begin(), index); - val.vector_val->erase(it); + auto it = std::next(vector_val->begin(), index); + vector_val->erase(it); Modified(); return true; @@ -3329,39 +3336,49 @@ bool VectorVal::AddTo(Val* val, bool /* is_first_init */) const const ValPtr& VectorVal::At(unsigned int index) const { - if ( index >= val.vector_val->size() ) + if ( index >= vector_val->size() ) return Val::nil; - return (*val.vector_val)[index]; + return (*vector_val)[index]; + } + +void VectorVal::Sort(bool cmp_func(const ValPtr& a, const ValPtr& b)) + { + sort(vector_val->begin(), vector_val->end(), cmp_func); } unsigned int VectorVal::Resize(unsigned int new_num_elements) { - unsigned int oldsize = val.vector_val->size(); - val.vector_val->reserve(new_num_elements); - val.vector_val->resize(new_num_elements); + unsigned int oldsize = vector_val->size(); + vector_val->reserve(new_num_elements); + vector_val->resize(new_num_elements); return oldsize; } unsigned int VectorVal::ResizeAtLeast(unsigned int new_num_elements) { - unsigned int old_size = val.vector_val->size(); + unsigned int old_size = vector_val->size(); if ( new_num_elements <= old_size ) return old_size; return Resize(new_num_elements); } +void VectorVal::Reserve(unsigned int num_elements) + { + vector_val->reserve(num_elements); + } + ValPtr VectorVal::DoClone(CloneState* state) { auto vv = make_intrusive(GetType()); - vv->val.vector_val->reserve(val.vector_val->size()); + vv->Reserve(vector_val->size()); state->NewClone(this, vv); - for ( unsigned int i = 0; i < val.vector_val->size(); ++i ) + for ( unsigned int i = 0; i < vector_val->size(); ++i ) { - auto v = (*val.vector_val)[i]->Clone(state); - vv->val.vector_val->push_back(std::move(v)); + auto v = (*vector_val)[i]->Clone(state); + vv->Assign(vv->Size(), std::move(v)); } return vv; @@ -3371,17 +3388,17 @@ void VectorVal::ValDescribe(ODesc* d) const { d->Add("["); - if ( val.vector_val->size() > 0 ) - for ( unsigned int i = 0; i < (val.vector_val->size() - 1); ++i ) + if ( vector_val->size() > 0 ) + for ( unsigned int i = 0; i < (vector_val->size() - 1); ++i ) { - if ( (*val.vector_val)[i] ) - (*val.vector_val)[i]->Describe(d); + if ( (*vector_val)[i] ) + (*vector_val)[i]->Describe(d); d->Add(", "); } - if ( val.vector_val->size() && - (*val.vector_val)[val.vector_val->size() - 1] ) - (*val.vector_val)[val.vector_val->size() - 1]->Describe(d); + if ( vector_val->size() && + (*vector_val)[vector_val->size() - 1] ) + (*vector_val)[vector_val->size() - 1]->Describe(d); d->Add("]"); } @@ -3534,9 +3551,9 @@ bool same_atomic_val(const Val* v1, const Val* v2) case TYPE_INTERNAL_STRING: return Bstr_eq(v1->AsString(), v2->AsString()); case TYPE_INTERNAL_ADDR: - return v1->AsAddr() == v2->AsAddr(); + return &v1->AsAddr() == &v2->AsAddr(); case TYPE_INTERNAL_SUBNET: - return v1->AsSubNet() == v2->AsSubNet(); + return &v1->AsSubNet() == &v2->AsSubNet(); default: reporter->InternalWarning("same_atomic_val called for non-atomic value"); @@ -3664,17 +3681,17 @@ bool can_cast_value_to_type(const Type* s, Type* t) ValPtr Val::MakeBool(bool b) { - return IntrusivePtr{AdoptRef{}, new Val(bro_int_t(b), TYPE_BOOL)}; + return make_intrusive(b); } ValPtr Val::MakeInt(bro_int_t i) { - return IntrusivePtr{AdoptRef{}, new Val(i, TYPE_INT)}; + return make_intrusive(i); } ValPtr Val::MakeCount(bro_uint_t u) { - return IntrusivePtr{AdoptRef{}, new Val(u, TYPE_COUNT)}; + return make_intrusive(u); } ValManager::ValManager() diff --git a/src/Val.h b/src/Val.h index c4dfd208d6..ed8af338a4 100644 --- a/src/Val.h +++ b/src/Val.h @@ -88,67 +88,21 @@ using TableValPtr = IntrusivePtr; using ValPtr = IntrusivePtr; using VectorValPtr = IntrusivePtr; -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* table_val; - std::vector* record_val; - std::vector* 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* value) noexcept - : table_val(value) {} -}; - class Val : public Obj { public: 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.")]] Val(double d, TypeTag 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 // no other remaining references. explicit Val(FilePtr f); +#endif // Extra arg to differentiate from protected version. Val(TypePtr t, bool type_type) @@ -174,7 +129,7 @@ public: {} Val() - : val(bro_int_t(0)), type(base_type(TYPE_ERROR)) + : type(base_type(TYPE_ERROR)) {} ~Val() override; @@ -221,41 +176,23 @@ public: IntrusivePtr GetType() const { return cast_intrusive(type); } -#define CONST_ACCESSOR(tag, ctype, accessor, name) \ - const ctype name() const \ - { \ - CHECK_TAG(type->Tag(), tag, "Val::CONST_ACCESSOR", type_name) \ - return val.accessor; \ - } +#define UNDERLYING_ACCESSOR_DECL(ztype, ctype, name) \ + ctype name() const; - // Needed for g++ 4.3's pickiness. -#define CONST_ACCESSOR2(tag, ctype, accessor, name) \ - ctype name() const \ - { \ - CHECK_TAG(type->Tag(), tag, "Val::CONST_ACCESSOR", type_name) \ - return val.accessor; \ - } - - CONST_ACCESSOR2(TYPE_BOOL, bool, int_val, AsBool) - CONST_ACCESSOR2(TYPE_INT, bro_int_t, int_val, AsInt) - CONST_ACCESSOR2(TYPE_COUNT, bro_uint_t, uint_val, AsCount) - CONST_ACCESSOR2(TYPE_DOUBLE, double, double_val, AsDouble) - CONST_ACCESSOR2(TYPE_TIME, double, double_val, AsTime) - CONST_ACCESSOR2(TYPE_INTERVAL, double, double_val, AsInterval) - 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*, table_val, AsTable) - CONST_ACCESSOR(TYPE_RECORD, std::vector*, 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*, vector_val, AsVector) - - const IPPrefix& AsSubNet() const - { - CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name) - return *val.subnet_val; - } +UNDERLYING_ACCESSOR_DECL(IntVal, bro_int_t, AsInt) +UNDERLYING_ACCESSOR_DECL(BoolVal, bool, AsBool) +UNDERLYING_ACCESSOR_DECL(EnumVal, int, AsEnum) +UNDERLYING_ACCESSOR_DECL(CountVal, bro_uint_t, AsCount) +UNDERLYING_ACCESSOR_DECL(DoubleVal, double, AsDouble) +UNDERLYING_ACCESSOR_DECL(TimeVal, double, AsTime) +UNDERLYING_ACCESSOR_DECL(IntervalVal, double, AsInterval) +UNDERLYING_ACCESSOR_DECL(AddrVal, const IPAddr&, AsAddr) +UNDERLYING_ACCESSOR_DECL(SubNetVal, const IPPrefix&, AsSubNet) +UNDERLYING_ACCESSOR_DECL(StringVal, const String*, AsString) +UNDERLYING_ACCESSOR_DECL(FuncVal, Func*, AsFunc) +UNDERLYING_ACCESSOR_DECL(FileVal, File*, AsFile) +UNDERLYING_ACCESSOR_DECL(PatternVal, const RE_Matcher*, AsPattern) +UNDERLYING_ACCESSOR_DECL(TableVal, const PDict*, AsTable) zeek::Type* AsType() const { @@ -263,48 +200,6 @@ public: 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*, 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(); const PatternVal* AsPatternVal() const; @@ -361,6 +256,7 @@ public: protected: + // Friends with access to Clone(). friend class EnumType; friend class ListVal; friend class RecordVal; @@ -375,23 +271,10 @@ protected: static ValPtr MakeInt(bro_int_t i); static ValPtr MakeCount(bro_uint_t u); - template - Val(V&& v, TypeTag t) noexcept - : val(std::forward(v)), type(base_type(t)) - {} - - template - Val(V&& v, TypePtr t) noexcept - : val(std::forward(v)), type(std::move(t)) - {} - explicit Val(TypePtr t) noexcept : type(std::move(t)) {} - ACCESSOR(TYPE_TABLE, PDict*, table_val, AsNonConstTable) - ACCESSOR(TYPE_RECORD, std::vector*, record_val, AsNonConstRecord) - // For internal use by the Val::Clone() methods. struct CloneState { // Caches a cloned value for later reuse during the same @@ -405,7 +288,6 @@ protected: ValPtr Clone(CloneState* state); virtual ValPtr DoClone(CloneState* state); - BroValUnion val; TypePtr type; #ifdef DEBUG @@ -505,6 +387,67 @@ private: 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 Milliseconds 1e-3 #define Seconds 1.0 @@ -512,31 +455,24 @@ extern ValManager* val_mgr; #define Hours (60*Minutes) #define Days (24*Hours) -class IntervalVal final : public Val { +class IntervalVal final : public DoubleVal { public: IntervalVal(double quantity, double units = Seconds) - : Val(quantity * units, base_type(TYPE_INTERVAL)) + : DoubleVal(quantity * units, base_type(TYPE_INTERVAL)) {} protected: void ValDescribe(ODesc* d) const override; }; -class TimeVal final : public Val { +class TimeVal final : public DoubleVal { public: TimeVal(double t) - : Val(t, base_type(TYPE_TIME)) + : DoubleVal(t, base_type(TYPE_TIME)) {} }; -class DoubleVal final : public Val { -public: - DoubleVal(double v) - : Val(v, base_type(TYPE_DOUBLE)) - {} -}; - -class PortVal final : public Val { +class PortVal final : public CountVal { public: ValPtr SizeVal() const override; @@ -585,10 +521,15 @@ public: explicit AddrVal(const uint32_t addr[4]); // IPv6. explicit AddrVal(const IPAddr& addr); + const IPAddr& UnderlyingVal() const { return *addr_val; } + unsigned int MemoryAllocation() const override; protected: ValPtr DoClone(CloneState* state) override; + +private: + IPAddr* addr_val; }; class SubNetVal final : public Val { @@ -609,11 +550,16 @@ public: bool Contains(const IPAddr& addr) const; + const IPPrefix& UnderlyingVal() const { return *subnet_val; } + unsigned int MemoryAllocation() const override; protected: void ValDescribe(ODesc* d) const override; ValPtr DoClone(CloneState* state) override; + +private: + IPPrefix* subnet_val; }; class StringVal final : public Val { @@ -622,6 +568,7 @@ public: explicit StringVal(const char* s); explicit StringVal(const std::string& s); StringVal(int length, const char* s); + ~StringVal() override; ValPtr SizeVal() const override; @@ -637,6 +584,8 @@ public: std::string ToStdString() const; StringVal* ToUpper(); + const String* UnderlyingVal() const { return string_val; } + unsigned int MemoryAllocation() const override; StringValPtr Replace(RE_Matcher* re, const String& repl, @@ -649,6 +598,43 @@ public: protected: void ValDescribe(ODesc* d) const 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 { @@ -660,11 +646,19 @@ public: 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; protected: void ValDescribe(ODesc* d) const override; ValPtr DoClone(CloneState* state) override; + +private: + RE_Matcher* re_val; }; // ListVals are mainly used to index tables that have more than one @@ -754,7 +748,7 @@ protected: 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 // anyway. int expire_access_time; @@ -997,6 +991,9 @@ public: const detail::AttributesPtr& GetAttrs() const { return attrs; } + const PDict* UnderlyingVal() const + { return table_val; } + // Returns the size of the table. int Size() const; int RecursiveSize() const; @@ -1104,6 +1101,9 @@ protected: // Sends data on to backing Broker Store 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; TableTypePtr table_type; @@ -1122,6 +1122,9 @@ protected: static TableRecordDependencies parse_time_table_record_dependencies; static ParseTimeTableStates parse_time_table_states; + +private: + PDict* table_val; }; class RecordVal final : public Val, public notifier::detail::Modifiable { @@ -1158,9 +1161,29 @@ public: void Assign(int field, std::nullptr_t) { Assign(field, ValPtr{}); } - [[deprecated("Remove in v4.1. Use GetField().")]] - Val* Lookup(int field) const // Does not Ref() value. - { return (*AsRecord())[field].get(); } + /** + * Appends a value to the record's fields. The caller is responsible + * 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. @@ -1168,7 +1191,7 @@ public: * @return The value at the given field index. */ 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. @@ -1233,6 +1256,27 @@ public: IntrusivePtr GetFieldOrDefault(const char* field) const { return cast_intrusive(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 * exist in the record type, it's an internal error: abort. @@ -1293,12 +1337,17 @@ protected: using RecordTypeValMap = std::unordered_map>; static RecordTypeValMap parse_time_records; + +private: + std::vector* record_val; }; -class EnumVal final : public Val { +class EnumVal final : public IntVal { public: ValPtr SizeVal() const override; + int UnderlyingVal() const { return int_val; } + protected: friend class Val; friend class EnumType; @@ -1306,7 +1355,7 @@ protected: template friend IntrusivePtr 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; @@ -1374,6 +1423,16 @@ public: */ 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().")]] Val* Lookup(unsigned int index) const { return At(index).get(); } @@ -1385,7 +1444,7 @@ public: return At(static_cast(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 // shrink a vector? The return value is the old size. @@ -1394,6 +1453,9 @@ public: // Won't shrink size. 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; } /** @@ -1413,11 +1475,43 @@ public: // Removes an element at a specific position. 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* UnderlyingVal() const + { return vector_val; } + protected: void ValDescribe(ODesc* d) const override; ValPtr DoClone(CloneState* state) override; + +private: + std::vector* vector_val; }; +#define UNDERLYING_ACCESSOR_DEF(ztype, ctype, name) \ + inline ctype Val::name() const \ + { return dynamic_cast(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*, AsTable) + + // Checks the given value for consistency with the given type. If an // 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 diff --git a/src/Var.cc b/src/Var.cc index 001c0f7b36..13679f26aa 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -322,7 +322,7 @@ static void make_var(const IDPtr& id, TypePtr t, InitClass c, ExprPtr init, // defined. std::vector inits; auto f = make_intrusive(id, nullptr, inits, 0, 0); - id->SetVal(make_intrusive(std::move(f))); + id->SetVal(make_intrusive(std::move(f))); } } @@ -750,11 +750,12 @@ void end_func(StmtPtr body) ingredients->frame_size, ingredients->priority); - ingredients->id->SetVal(make_intrusive(std::move(f))); + ingredients->id->SetVal(make_intrusive(std::move(f))); ingredients->id->SetConst(); } - auto func = cast_intrusive(ingredients->id->GetVal()->AsFuncPtr()); + auto func_ptr = cast_intrusive(ingredients->id->GetVal())->AsFuncPtr(); + auto func = cast_intrusive(func_ptr); func->SetScope(ingredients->scope); analyze_func(std::move(func)); diff --git a/src/analyzer/protocol/krb/krb-analyzer.pac b/src/analyzer/protocol/krb/krb-analyzer.pac index 70074fd9d3..aad056ee94 100644 --- a/src/analyzer/protocol/krb/krb-analyzer.pac +++ b/src/analyzer/protocol/krb/krb-analyzer.pac @@ -263,7 +263,7 @@ refine connection KRB_Conn += { rv->Assign(1, zeek::val_mgr->Bool(${msg.ap_options.mutual_required})); 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 ) rvticket->Assign(5, authenticationinfo); diff --git a/src/analyzer/protocol/rpc/NFS.cc b/src/analyzer/protocol/rpc/NFS.cc index c7a77ae0a5..bf1fb00bc2 100644 --- a/src/analyzer/protocol/rpc/NFS.cc +++ b/src/analyzer/protocol/rpc/NFS.cc @@ -176,7 +176,7 @@ bool NFS_Interp::RPC_BuildReply(RPC_CallInfo* c, BifEnum::rpc_status rpc_status, case BifEnum::NFS3::PROC_READ: 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); event = nfs_proc_read; break; diff --git a/src/analyzer/protocol/tcp/functions.bif b/src/analyzer/protocol/tcp/functions.bif index 38a379b8b9..fe82b8c15b 100644 --- a/src/analyzer/protocol/tcp/functions.bif +++ b/src/analyzer/protocol/tcp/functions.bif @@ -127,7 +127,7 @@ function get_contents_file%(cid: conn_id, direction: count%): file auto cf = c->GetRootAnalyzer()->GetContentsFile(direction); if ( cf ) - return zeek::make_intrusive(std::move(cf)); + return zeek::make_intrusive(std::move(cf)); } // Return some sort of error value. @@ -136,5 +136,5 @@ function get_contents_file%(cid: conn_id, direction: count%): file else zeek::emit_builtin_error("no contents file for given direction"); - return zeek::make_intrusive(zeek::make_intrusive(stderr, "-", "w")); + return zeek::make_intrusive(zeek::make_intrusive(stderr, "-", "w")); %} diff --git a/src/broker/Data.cc b/src/broker/Data.cc index e5f459b952..ddb643766f 100644 --- a/src/broker/Data.cc +++ b/src/broker/Data.cc @@ -127,7 +127,7 @@ struct val_converter { auto file = File::Get(a.data()); if ( file ) - return make_intrusive(std::move(file)); + return make_intrusive(std::move(file)); return nullptr; } diff --git a/src/broker/Manager.cc b/src/broker/Manager.cc index b6c39f8326..091783935d 100644 --- a/src/broker/Manager.cc +++ b/src/broker/Manager.cc @@ -436,7 +436,7 @@ bool Manager::PublishEvent(string topic, RecordVal* args) if ( ! args->GetField(0) ) return false; - auto event_name = args->GetField(0)->AsString()->CheckString(); + auto event_name = args->GetStringField(0)->CheckString(); auto vv = args->GetField(1)->AsVectorVal(); broker::vector xs; xs.reserve(vv->Size()); diff --git a/src/broker/Store.cc b/src/broker/Store.cc index 7cd5425b90..2cd288d0b4 100644 --- a/src/broker/Store.cc +++ b/src/broker/Store.cc @@ -69,7 +69,7 @@ broker::backend_options to_backend_options(broker::backend backend, case broker::backend::sqlite: { auto path = options->GetField(0)->AsRecordVal() - ->GetField(0)->AsStringVal()->CheckString(); + ->GetStringField(0)->CheckString(); return {{"path", path}}; } diff --git a/src/file_analysis/File.cc b/src/file_analysis/File.cc index a54fd19585..f7fab6bc81 100644 --- a/src/file_analysis/File.cc +++ b/src/file_analysis/File.cc @@ -120,7 +120,7 @@ void File::UpdateLastActivityTime() 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) diff --git a/src/iosource/pcap/pcap.bif b/src/iosource/pcap/pcap.bif index 0201cd4bbd..bb2cf53633 100644 --- a/src/iosource/pcap/pcap.bif +++ b/src/iosource/pcap/pcap.bif @@ -44,7 +44,7 @@ function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool bool success = true; 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; return zeek::val_mgr->Bool(success); @@ -73,7 +73,7 @@ function Pcap::install_pcap_filter%(id: PcapFilterID%): bool bool success = true; zeek::iosource::PktSrc* ps = zeek::iosource_mgr->GetPktSrc(); - if ( ps && ! ps->SetFilter(id->ForceAsInt()) ) + if ( ps && ! ps->SetFilter(id->AsInt()) ) success = false; return zeek::val_mgr->Bool(success); diff --git a/src/logging/Manager.cc b/src/logging/Manager.cc index 889d4630f6..b6d50f4c95 100644 --- a/src/logging/Manager.cc +++ b/src/logging/Manager.cc @@ -1534,7 +1534,7 @@ std::string Manager::FormatRotationPath(EnumValPtr writer, ri->Assign(2, open); ri->Assign(3, close); ri->Assign(4, val_mgr->Bool(terminating)); - ri->Assign(5, std::move(postprocessor)); + ri->Assign(5, std::move(postprocessor)); std::string rval; @@ -1543,7 +1543,7 @@ std::string Manager::FormatRotationPath(EnumValPtr writer, auto res = rotation_format_func->Invoke(ri); auto rp_val = res->AsRecordVal(); 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(); if ( ! util::streq(dir, "") && ! util::detail::ensure_intermediate_dirs(dir) ) diff --git a/src/option.bif b/src/option.bif index 92429330e7..6ced7a00dd 100644 --- a/src/option.bif +++ b/src/option.bif @@ -209,6 +209,7 @@ function Option::set_change_handler%(ID: string, on_change: any, priority: int & return zeek::val_mgr->False(); } - i->AddOptionHandler(on_change->AsFuncPtr(), -priority); + auto func = dynamic_cast(on_change)->AsFuncPtr(); + i->AddOptionHandler(func, -priority); return zeek::val_mgr->True(); %} diff --git a/src/reporter.bif b/src/reporter.bif index 339243c8e0..02956f43b7 100644 --- a/src/reporter.bif +++ b/src/reporter.bif @@ -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. 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()); if ( ! file ) diff --git a/src/strings.bif b/src/strings.bif index 7e4bbfdfcd..13f14c5770 100644 --- a/src/strings.bif +++ b/src/strings.bif @@ -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 %{ zeek::detail::SWParams sw_params( - params->AsRecordVal()->GetField(0)->AsCount(), - zeek::detail::SWVariant(params->AsRecordVal()->GetField(1)->AsCount())); + params->AsRecordVal()->GetCountField(0), + zeek::detail::SWVariant(params->AsRecordVal()->GetCountField(1))); auto* subseq = zeek::detail::smith_waterman(s1->AsString(), s2->AsString(), sw_params); 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 function str_split%(s: string, idx: index_vec%): string_vec &deprecated="Remove in v4.1. Use str_split_indices." %{ - auto idx_v = idx->AsVector(); - zeek::String::IdxVec indices(idx_v->size()); + auto idx_v = dynamic_cast(idx); + auto n = idx_v->Size(); + zeek::String::IdxVec indices(n); unsigned int i; - for ( i = 0; i < idx_v->size(); i++ ) - indices[i] = (*idx_v)[i]->AsCount(); + for ( i = 0; i < n; i++ ) + indices[i] = idx_v->CountAt(i); zeek::String::Vec* result = s->AsString()->Split(indices); auto result_v = zeek::make_intrusive(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 function str_split_indices%(s: string, idx: index_vec%): string_vec %{ - auto idx_v = idx->AsVector(); - zeek::String::IdxVec indices(idx_v->size()); + auto idx_v = dynamic_cast(idx); + auto n = idx_v->Size(); + zeek::String::IdxVec indices(n); unsigned int i; - for ( i = 0; i < idx_v->size(); i++ ) - indices[i] = (*idx_v)[i]->AsCount(); + for ( i = 0; i < n; i++ ) + indices[i] = idx_v->CountAt(i); zeek::String::Vec* result = s->AsString()->Split(indices); auto result_v = zeek::make_intrusive(zeek::id::string_vec); diff --git a/src/supervisor/Supervisor.cc b/src/supervisor/Supervisor.cc index 38eda9dcd0..91743f580f 100644 --- a/src/supervisor/Supervisor.cc +++ b/src/supervisor/Supervisor.cc @@ -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 rval; - rval.name = node->GetField("name")->AsString()->CheckString(); + rval.name = node->GetStringField("name")->CheckString(); const auto& iface_val = node->GetField("interface"); if ( iface_val ) @@ -1273,9 +1273,9 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node) auto rv = v->GetVal()->AsRecordVal(); Supervisor::ClusterEndpoint ep; - ep.role = static_cast(rv->GetField("role")->AsEnum()); - ep.host = rv->GetField("host")->AsAddr().AsString(); - ep.port = rv->GetField("p")->AsPortVal()->Port(); + ep.role = static_cast(rv->GetEnumField("role")); + ep.host = rv->GetAddrField("host").AsString(); + ep.port = rv->GetPortValField("p")->Port(); const auto& iface = rv->GetField("interface"); diff --git a/src/threading/SerialTypes.h b/src/threading/SerialTypes.h index d709e840e8..e66a913026 100644 --- a/src/threading/SerialTypes.h +++ b/src/threading/SerialTypes.h @@ -111,8 +111,8 @@ struct Value { struct subnet_t { addr_t prefix; uint8_t length; }; /** - * This union is a subset of BroValUnion, including only the types we - * can log directly. See IsCompatibleType(). + * This union is a subset of the "underlying" values in Val subclasses, + * including only the types we can log directly. See IsCompatibleType(). */ union _val { bro_int_t int_val; diff --git a/src/zeek.bif b/src/zeek.bif index 0444a881de..8f21cebde2 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -1432,7 +1432,7 @@ function sort%(v: any, ...%) : any if ( ! comp && ! IsIntegral(elt_type->Tag()) ) zeek::emit_builtin_error("comparison function required for sort() with non-integral types"); - auto& vv = *v->AsVector(); + auto vv = dynamic_cast(v); if ( comp ) { @@ -1447,14 +1447,14 @@ function sort%(v: any, ...%) : any sort_function_comp = comp; - sort(vv.begin(), vv.end(), sort_function); + vv->Sort(sort_function); } else { if ( elt_type->InternalType() == zeek::TYPE_INTERNAL_UNSIGNED ) - sort(vv.begin(), vv.end(), unsigned_sort_function); + vv->Sort(unsigned_sort_function); else - sort(vv.begin(), vv.end(), signed_sort_function); + vv->Sort(signed_sort_function); } return rval; @@ -1502,8 +1502,8 @@ function order%(v: any, ...%) : index_vec if ( ! comp && ! IsIntegral(elt_type->Tag()) ) zeek::emit_builtin_error("comparison function required for order() with non-integral types"); - auto& vv = *v->AsVector(); - auto n = vv.size(); + auto vv = dynamic_cast(v); + auto n = vv->Size(); // Set up initial mapping of indices directly to corresponding // elements. @@ -1513,7 +1513,7 @@ function order%(v: any, ...%) : index_vec for ( i = 0; i < n; ++i ) { ind_vv[i] = i; - index_map.emplace_back(&vv[i]); + index_map.emplace_back(&vv->At(i)); } if ( comp ) @@ -2410,15 +2410,17 @@ function addr_to_counts%(a: addr%): index_vec ## .. zeek:see:: addr_to_counts function counts_to_addr%(v: index_vec%): addr %{ - if ( v->AsVector()->size() == 1 ) + auto vv = dynamic_cast(v); + + if ( vv->Size() == 1 ) { - return zeek::make_intrusive(htonl((*v->AsVector())[0]->AsCount())); + return zeek::make_intrusive(htonl(vv->CountAt(0))); } - else if ( v->AsVector()->size() == 4 ) + else if ( vv->Size() == 4 ) { uint32_t bytes[4]; for ( int i = 0; i < 4; ++i ) - bytes[i] = htonl((*v->AsVector())[i]->AsCount()); + bytes[i] = htonl(vv->CountAt(i)); return zeek::make_intrusive(bytes); } else @@ -3526,13 +3528,13 @@ function lookup_connection%(cid: conn_id%): connection %%{ const char* conn_id_string(zeek::Val* c) { - const auto& id = (*(c->AsRecord()))[0]; - auto vl = id->AsRecord(); + auto id = dynamic_cast(c)->GetField(0); + auto id_r = dynamic_cast(id.get()); - const zeek::IPAddr& orig_h = (*vl)[0]->AsAddr(); - uint32_t orig_p = (*vl)[1]->AsPortVal()->Port(); - const zeek::IPAddr& resp_h = (*vl)[2]->AsAddr(); - uint32_t resp_p = (*vl)[3]->AsPortVal()->Port(); + const zeek::IPAddr& orig_h = id_r->GetAddrField(0); + uint32_t orig_p = id_r->GetPortValField(1)->Port(); + const zeek::IPAddr& resp_h = id_r->GetAddrField(2); + 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, 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; u_char *data; - auto pkt_vl = pkt->AsRecord(); + auto pkt_r = dynamic_cast(pkt); - ts.tv_sec = (*pkt_vl)[0]->AsCount(); - ts.tv_usec = (*pkt_vl)[1]->AsCount(); - caplen = (*pkt_vl)[2]->AsCount(); - len = (*pkt_vl)[3]->AsCount(); - data = (*pkt_vl)[4]->AsString()->Bytes(); - link_type = (*pkt_vl)[5]->AsEnum(); + ts.tv_sec = pkt_r->GetCountField(0); + ts.tv_usec = pkt_r->GetCountField(1); + caplen = pkt_r->GetCountField(2); + len = pkt_r->GetCountField(3); + data = pkt_r->GetStringField(4)->Bytes(); + link_type = pkt_r->GetEnumField(5); Packet p(link_type, &ts, caplen, len, data, true); addl_pkt_dumper->Dump(&p); @@ -4592,9 +4594,9 @@ function open%(f: string%): file const char* file = f->CheckString(); if ( zeek::util::streq(file, "-") ) - return zeek::make_intrusive(zeek::make_intrusive(stdout, "-", "w")); + return zeek::make_intrusive(zeek::make_intrusive(stdout, "-", "w")); else - return zeek::make_intrusive(zeek::make_intrusive(file, "w")); + return zeek::make_intrusive(zeek::make_intrusive(file, "w")); %} ## 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 function open_for_append%(f: string%): file %{ - return zeek::make_intrusive(zeek::make_intrusive(f->CheckString(), "a")); + return zeek::make_intrusive(zeek::make_intrusive(f->CheckString(), "a")); %} ## Closes an open file and flushes any buffered content.