convert RecordVal's to use vector<ZVal> as internal representation

This commit is contained in:
Vern Paxson 2021-02-24 17:02:47 -08:00
parent 348e14c326
commit 6121e409d3
4 changed files with 122 additions and 40 deletions

View file

@ -15,6 +15,7 @@
#include "zeek/Reporter.h"
#include "zeek/net_util.h"
#include "zeek/Dict.h"
#include "zeek/ZVal.h"
// We have four different port name spaces: TCP, UDP, ICMP, and UNKNOWN.
// We distinguish between them based on the bits specified in the *_PORT_MASK
@ -1023,12 +1024,23 @@ public:
/**
* Appends a value to the record's fields. The caller is responsible
* for ensuring that fields are appended in the correct orer and
* for ensuring that fields are appended in the correct order and
* with the correct type.
* @param v The value to append.
*/
void AppendField(ValPtr v)
{ record_val->emplace_back(std::move(v)); }
{
if ( v )
{
(*is_in_record)[record_val->size()] = true;
record_val->emplace_back(ZVal(v, v->GetType()));
}
else
{
(*is_in_record)[record_val->size()] = false;
record_val->emplace_back(ZVal());
}
}
/**
* Ensures that the record has enough internal storage for the
@ -1036,22 +1048,44 @@ public:
* @param n The number of fields.
*/
void Reserve(unsigned int n)
{ record_val->reserve(n); }
{
record_val->reserve(n);
is_in_record->reserve(n);
for ( auto i = is_in_record->size(); i < n; ++i )
is_in_record->emplace_back(false);
}
/**
* Returns the number of fields in the record.
* @return The number of fields in the record.
*/
unsigned int NumFields()
unsigned int NumFields() const
{ return record_val->size(); }
/**
* Returns true if the given field is in the record, false if
* it's missing.
* @param field The field index to retrieve.
* @return Whether there's a value for the given field index.
*/
bool HasField(int field) const
{
return (*is_in_record)[field];
}
/**
* Returns the value of a given field index.
* @param field The field index to retrieve.
* @return The value at the given field index.
*/
const ValPtr& GetField(int field) const
{ return (*record_val)[field]; }
ValPtr GetField(int field) const
{
if ( ! HasField(field) )
return nullptr;
return (*record_val)[field].ToVal(rt->GetFieldType(field));
}
/**
* Returns the value of a given field index as cast to type @c T.
@ -1078,7 +1112,7 @@ public:
* @return The value of the given field. If no such field name exists,
* a fatal error occurs.
*/
const ValPtr& GetField(const char* field) const;
ValPtr GetField(const char* field) const;
/**
* Returns the value of a given field name as cast to type @c T.
@ -1119,7 +1153,7 @@ public:
template <typename T>
auto GetFieldAs(int field) const -> std::invoke_result_t<decltype(&T::Get), T>
{
auto& field_ptr = GetField(field);
auto field_ptr = GetField(field);
auto field_val_ptr = static_cast<T*>(field_ptr.get());
return field_val_ptr->Get();
}
@ -1127,7 +1161,7 @@ public:
template <typename T>
auto GetFieldAs(const char* field) const -> std::invoke_result_t<decltype(&T::Get), T>
{
auto& field_ptr = GetField(field);
auto field_ptr = GetField(field);
auto field_val_ptr = static_cast<T*>(field_ptr.get());
return field_val_ptr->Get();
}
@ -1182,7 +1216,16 @@ protected:
static RecordTypeValMap parse_time_records;
private:
std::vector<ValPtr>* record_val;
// Keep this handy for quick access during low-level operations.
RecordTypePtr rt;
// Low-level values of each of the fields.
std::vector<ZVal>* record_val;
// Whether a given field exists - for optional fields, and because
// Zeek does not enforce that non-optional fields are actually
// present.
std::vector<bool>* is_in_record;
};
class EnumVal final : public detail::IntValImplementation {