mirror of
https://github.com/zeek/zeek.git
synced 2025-10-04 07:38:19 +00:00
base support for differentiated record field accessors
This commit is contained in:
parent
0118b6ee38
commit
e363bab55f
2 changed files with 109 additions and 15 deletions
|
@ -344,8 +344,8 @@ Connection* NetSessions::FindConnection(Val* v)
|
||||||
const IPAddr& orig_addr = vl->GetFieldAs<AddrVal>(orig_h);
|
const IPAddr& orig_addr = vl->GetFieldAs<AddrVal>(orig_h);
|
||||||
const IPAddr& resp_addr = vl->GetFieldAs<AddrVal>(resp_h);
|
const IPAddr& resp_addr = vl->GetFieldAs<AddrVal>(resp_h);
|
||||||
|
|
||||||
const PortVal* orig_portv = vl->GetFieldAs<PortVal>(orig_p);
|
auto orig_portv = vl->GetFieldAs<PortVal>(orig_p);
|
||||||
const PortVal* resp_portv = vl->GetFieldAs<PortVal>(resp_p);
|
auto resp_portv = vl->GetFieldAs<PortVal>(resp_p);
|
||||||
|
|
||||||
ConnID id;
|
ConnID id;
|
||||||
|
|
||||||
|
|
118
src/Val.h
118
src/Val.h
|
@ -73,6 +73,7 @@ class EnumVal;
|
||||||
class OpaqueVal;
|
class OpaqueVal;
|
||||||
class VectorVal;
|
class VectorVal;
|
||||||
class TableEntryVal;
|
class TableEntryVal;
|
||||||
|
class TypeVal;
|
||||||
|
|
||||||
using AddrValPtr = IntrusivePtr<AddrVal>;
|
using AddrValPtr = IntrusivePtr<AddrVal>;
|
||||||
using EnumValPtr = IntrusivePtr<EnumVal>;
|
using EnumValPtr = IntrusivePtr<EnumVal>;
|
||||||
|
@ -446,14 +447,19 @@ public:
|
||||||
// Returns a masked port number
|
// Returns a masked port number
|
||||||
static uint32_t Mask(uint32_t port_num, TransportProto port_type);
|
static uint32_t Mask(uint32_t port_num, TransportProto port_type);
|
||||||
|
|
||||||
const PortVal* Get() const { return AsPortVal(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class ValManager;
|
friend class ValManager;
|
||||||
PortVal(uint32_t p);
|
PortVal(uint32_t p);
|
||||||
|
|
||||||
void ValDescribe(ODesc* d) const override;
|
void ValDescribe(ODesc* d) const override;
|
||||||
ValPtr DoClone(CloneState* state) override;
|
ValPtr DoClone(CloneState* state) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This method is just here to trick the interface in
|
||||||
|
// `RecordVal::GetFieldAs` into returning the right type.
|
||||||
|
// It shouldn't actually be used for anything.
|
||||||
|
friend class RecordVal;
|
||||||
|
PortValPtr Get() { return {NewRef{}, this}; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class AddrVal final : public Val {
|
class AddrVal final : public Val {
|
||||||
|
@ -996,6 +1002,39 @@ private:
|
||||||
PDict<TableEntryVal>* table_val;
|
PDict<TableEntryVal>* table_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// This would be way easier with is_convertible_v, but sadly that won't
|
||||||
|
// work here because Obj has deleted copy constructors (and for good
|
||||||
|
// reason). Instead we make up our own type trait here that basically
|
||||||
|
// combines a bunch of is_same traits into a single trait to make life
|
||||||
|
// easier in the definitions of GetFieldAs().
|
||||||
|
template <typename T>
|
||||||
|
struct is_zeek_val
|
||||||
|
{
|
||||||
|
static const bool value = std::disjunction_v<
|
||||||
|
std::is_same<AddrVal, T>,
|
||||||
|
std::is_same<BoolVal, T>,
|
||||||
|
std::is_same<CountVal, T>,
|
||||||
|
std::is_same<DoubleVal, T>,
|
||||||
|
std::is_same<EnumVal, T>,
|
||||||
|
std::is_same<FileVal, T>,
|
||||||
|
std::is_same<FuncVal, T>,
|
||||||
|
std::is_same<IntVal, T>,
|
||||||
|
std::is_same<IntervalVal, T>,
|
||||||
|
std::is_same<ListVal, T>,
|
||||||
|
std::is_same<OpaqueVal, T>,
|
||||||
|
std::is_same<PatternVal, T>,
|
||||||
|
std::is_same<PortVal, T>,
|
||||||
|
std::is_same<RecordVal, T>,
|
||||||
|
std::is_same<StringVal, T>,
|
||||||
|
std::is_same<SubNetVal, T>,
|
||||||
|
std::is_same<TableVal, T>,
|
||||||
|
std::is_same<TimeVal, T>,
|
||||||
|
std::is_same<TypeVal, T>,
|
||||||
|
std::is_same<VectorVal, T>>;
|
||||||
|
};
|
||||||
|
template <typename T>
|
||||||
|
inline constexpr bool is_zeek_val_v = is_zeek_val<T>::value;
|
||||||
|
|
||||||
class RecordVal final : public Val, public notifier::detail::Modifiable {
|
class RecordVal final : public Val, public notifier::detail::Modifiable {
|
||||||
public:
|
public:
|
||||||
explicit RecordVal(RecordTypePtr t, bool init_fields = true);
|
explicit RecordVal(RecordTypePtr t, bool init_fields = true);
|
||||||
|
@ -1148,22 +1187,77 @@ public:
|
||||||
|
|
||||||
// The following return the given field converted to a particular
|
// The following return the given field converted to a particular
|
||||||
// underlying value. We provide these to enable efficient
|
// underlying value. We provide these to enable efficient
|
||||||
// access to record fields (without requiring an intermediary Val)
|
// access to record fields (without requiring an intermediary Val).
|
||||||
// if we change the underlying representation of records.
|
// It is up to the caller to ensure that the field exists in the
|
||||||
template <typename T>
|
// record (using HasField(), if necessary).
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if_t<is_zeek_val_v<T>, bool> = true>
|
||||||
auto GetFieldAs(int field) const -> std::invoke_result_t<decltype(&T::Get), T>
|
auto GetFieldAs(int field) const -> std::invoke_result_t<decltype(&T::Get), T>
|
||||||
{
|
{
|
||||||
auto field_ptr = GetField(field);
|
if constexpr ( std::is_same_v<T, BoolVal> ||
|
||||||
auto field_val_ptr = static_cast<T*>(field_ptr.get());
|
std::is_same_v<T, IntVal> ||
|
||||||
return field_val_ptr->Get();
|
std::is_same_v<T, EnumVal> )
|
||||||
|
return record_val->at(field).int_val;
|
||||||
|
else if constexpr ( std::is_same_v<T, CountVal> )
|
||||||
|
return record_val->at(field).uint_val;
|
||||||
|
else if constexpr ( std::is_same_v<T, DoubleVal> ||
|
||||||
|
std::is_same_v<T, TimeVal> ||
|
||||||
|
std::is_same_v<T, IntervalVal> )
|
||||||
|
return record_val->at(field).double_val;
|
||||||
|
else if constexpr ( std::is_same_v<T, PortVal> )
|
||||||
|
return val_mgr->Port(record_val->at(field).uint_val);
|
||||||
|
else if constexpr ( std::is_same_v<T, StringVal> )
|
||||||
|
return record_val->at(field).string_val->Get();
|
||||||
|
else if constexpr ( std::is_same_v<T, AddrVal> )
|
||||||
|
return record_val->at(field).addr_val->Get();
|
||||||
|
else if constexpr ( std::is_same_v<T, SubNetVal> )
|
||||||
|
return record_val->at(field).subnet_val->Get();
|
||||||
|
else if constexpr ( std::is_same_v<T, File> )
|
||||||
|
return *(record_val->at(field).file_val);
|
||||||
|
else if constexpr ( std::is_same_v<T, Func> )
|
||||||
|
return *(record_val->at(field).func_val);
|
||||||
|
else if constexpr ( std::is_same_v<T, PatternVal> )
|
||||||
|
return record_val->at(field).re_val->Get();
|
||||||
|
else if constexpr ( std::is_same_v<T, RecordVal> )
|
||||||
|
return record_val->at(field).record_val;
|
||||||
|
else if constexpr ( std::is_same_v<T, VectorVal> )
|
||||||
|
return record_val->at(field).vector_val;
|
||||||
|
else if constexpr ( std::is_same_v<T, TableVal> )
|
||||||
|
return record_val->at(field).table_val->Get();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: error here, although because of the
|
||||||
|
// type trait it really shouldn't ever get here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
typename std::enable_if_t<!is_zeek_val_v<T>, bool> = true>
|
||||||
|
T GetFieldAs(int field) const
|
||||||
|
{
|
||||||
|
if constexpr ( std::is_integral_v<T> && std::is_signed_v<T> )
|
||||||
|
return record_val->at(field).int_val;
|
||||||
|
else if constexpr ( std::is_integral_v<T> &&
|
||||||
|
std::is_unsigned_v<T> )
|
||||||
|
return record_val->at(field).uint_val;
|
||||||
|
else if constexpr ( std::is_floating_point_v<T> )
|
||||||
|
return record_val->at(field).double_val;
|
||||||
|
|
||||||
|
// Could add other types here using type traits,
|
||||||
|
// such as is_same_v<T, std::string>, etc.
|
||||||
|
|
||||||
|
return T{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto GetFieldAs(const char* field) const -> std::invoke_result_t<decltype(&T::Get), T>
|
auto GetFieldAs(const char* field) const
|
||||||
{
|
{
|
||||||
auto field_ptr = GetField(field);
|
int idx = GetType()->AsRecordType()->FieldOffset(field);
|
||||||
auto field_val_ptr = static_cast<T*>(field_ptr.get());
|
|
||||||
return field_val_ptr->Get();
|
if ( idx < 0 )
|
||||||
|
reporter->InternalError("missing record field: %s", field);
|
||||||
|
|
||||||
|
return GetFieldAs<T>(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Describe(ODesc* d) const override;
|
void Describe(ODesc* d) const override;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue