mirror of
https://github.com/zeek/zeek.git
synced 2025-10-09 10:08:20 +00:00
206 lines
7.2 KiB
C++
206 lines
7.2 KiB
C++
// See the file "COPYING" in the main distribution directory for copyright.
|
|
|
|
// Low-level representation of Zeek scripting values.
|
|
|
|
#pragma once
|
|
|
|
#include "zeek/zeek-config.h"
|
|
|
|
namespace zeek {
|
|
|
|
class AddrVal;
|
|
class EnumVal;
|
|
class File;
|
|
class Func;
|
|
class ListVal;
|
|
class OpaqueVal;
|
|
class PatternVal;
|
|
class RecordVal;
|
|
class StringVal;
|
|
class SubNetVal;
|
|
class TableVal;
|
|
class TypeVal;
|
|
class Val;
|
|
class VectorVal;
|
|
|
|
using AddrValPtr = IntrusivePtr<AddrVal>;
|
|
using EnumValPtr = IntrusivePtr<EnumVal>;
|
|
using ListValPtr = IntrusivePtr<ListVal>;
|
|
using OpaqueValPtr = IntrusivePtr<OpaqueVal>;
|
|
using PatternValPtr = IntrusivePtr<PatternVal>;
|
|
using RecordValPtr = IntrusivePtr<RecordVal>;
|
|
using StringValPtr = IntrusivePtr<StringVal>;
|
|
using SubNetValPtr = IntrusivePtr<SubNetVal>;
|
|
using TableValPtr = IntrusivePtr<TableVal>;
|
|
using TypeValPtr = IntrusivePtr<TypeVal>;
|
|
using ValPtr = IntrusivePtr<Val>;
|
|
using VectorValPtr = IntrusivePtr<VectorVal>;
|
|
|
|
namespace detail {
|
|
class ZBody;
|
|
}
|
|
|
|
// Note that a ZVal by itself is ambiguous: it doesn't track its type.
|
|
// This makes them consume less memory and cheaper to copy. It does
|
|
// however require a separate way to determine the type. Generally
|
|
// this is doable using surrounding context, or can be statically
|
|
// determined in the case of optimization/compilation.
|
|
//
|
|
// An alternative would be to use std::variant, but it will be larger
|
|
// due to needing to track the variant type, and it won't allow access
|
|
// to the managed_val member, which both simplifies memory management
|
|
// and is also required for sharing of ZAM frame slots.
|
|
|
|
union ZVal {
|
|
// Constructor for hand-populating the values.
|
|
ZVal() { managed_val = nullptr; }
|
|
|
|
// Construct from a given higher-level script value with a given type.
|
|
ZVal(ValPtr v, const TypePtr& t);
|
|
|
|
// Construct an empty value compatible with the given type.
|
|
ZVal(const TypePtr& t);
|
|
|
|
// Construct directly.
|
|
ZVal(bool v) { int_val = v; }
|
|
ZVal(zeek_int_t v) { int_val = v; }
|
|
ZVal(zeek_uint_t v) { uint_val = v; }
|
|
ZVal(double v) { double_val = v; }
|
|
|
|
ZVal(StringVal* v) { string_val = v; }
|
|
ZVal(AddrVal* v) { addr_val = v; }
|
|
ZVal(SubNetVal* v) { subnet_val = v; }
|
|
ZVal(File* v) { file_val = v; }
|
|
ZVal(Func* v) { func_val = v; }
|
|
ZVal(ListVal* v) { list_val = v; }
|
|
ZVal(OpaqueVal* v) { opaque_val = v; }
|
|
ZVal(PatternVal* v) { re_val = v; }
|
|
ZVal(TableVal* v) { table_val = v; }
|
|
ZVal(RecordVal* v) { record_val = v; }
|
|
ZVal(VectorVal* v) { vector_val = v; }
|
|
ZVal(TypeVal* v) { type_val = v; }
|
|
ZVal(Val* v) { any_val = v; }
|
|
|
|
ZVal(StringValPtr v) { string_val = v.release(); }
|
|
ZVal(AddrValPtr v) { addr_val = v.release(); }
|
|
ZVal(SubNetValPtr v) { subnet_val = v.release(); }
|
|
ZVal(ListValPtr v) { list_val = v.release(); }
|
|
ZVal(OpaqueValPtr v) { opaque_val = v.release(); }
|
|
ZVal(PatternValPtr v) { re_val = v.release(); }
|
|
ZVal(TableValPtr v) { table_val = v.release(); }
|
|
ZVal(RecordValPtr v) { record_val = v.release(); }
|
|
ZVal(VectorValPtr v) { vector_val = v.release(); }
|
|
ZVal(TypeValPtr v) { type_val = v.release(); }
|
|
|
|
// Convert to a higher-level script value. The caller needs to
|
|
// ensure that they're providing the correct type.
|
|
ValPtr ToVal(const TypePtr& t) const;
|
|
|
|
zeek_int_t AsInt() const { return int_val; }
|
|
zeek_uint_t AsCount() const { return uint_val; }
|
|
double AsDouble() const { return double_val; }
|
|
|
|
StringVal* AsString() const { return string_val; }
|
|
AddrVal* AsAddr() const { return addr_val; }
|
|
SubNetVal* AsSubNet() const { return subnet_val; }
|
|
File* AsFile() const { return file_val; }
|
|
Func* AsFunc() const { return func_val; }
|
|
ListVal* AsList() const { return list_val; }
|
|
OpaqueVal* AsOpaque() const { return opaque_val; }
|
|
PatternVal* AsPattern() const { return re_val; }
|
|
TableVal* AsTable() const { return table_val; }
|
|
RecordVal* AsRecord() const { return record_val; }
|
|
VectorVal* AsVector() const { return vector_val; }
|
|
TypeVal* AsType() const { return type_val; }
|
|
Val* AsAny() const { return any_val; }
|
|
|
|
Obj* ManagedVal() const { return managed_val; }
|
|
void ClearManagedVal() { managed_val = nullptr; }
|
|
|
|
// The following return references that can be used to
|
|
// populate the ZVal. Handy for compiled ZAM code.
|
|
zeek_int_t& AsIntRef() { return int_val; }
|
|
zeek_uint_t& AsCountRef() { return uint_val; }
|
|
double& AsDoubleRef() { return double_val; }
|
|
StringVal*& AsStringRef() { return string_val; }
|
|
AddrVal*& AsAddrRef() { return addr_val; }
|
|
SubNetVal*& AsSubNetRef() { return subnet_val; }
|
|
File*& AsFileRef() { return file_val; }
|
|
Func*& AsFuncRef() { return func_val; }
|
|
ListVal*& AsListRef() { return list_val; }
|
|
OpaqueVal*& AsOpaqueRef() { return opaque_val; }
|
|
PatternVal*& AsPatternRef() { return re_val; }
|
|
TableVal*& AsTableRef() { return table_val; }
|
|
RecordVal*& AsRecordRef() { return record_val; }
|
|
VectorVal*& AsVectorRef() { return vector_val; }
|
|
TypeVal*& AsTypeRef() { return type_val; }
|
|
Val*& AsAnyRef() { return any_val; }
|
|
Obj*& ManagedValRef() { return managed_val; }
|
|
|
|
// True if a given type is one for which we manage the associated
|
|
// memory internally.
|
|
static bool IsManagedType(const TypePtr& t);
|
|
|
|
// Deletes a managed value. Caller needs to ensure that the ZVal
|
|
// indeed holds such.
|
|
static void DeleteManagedType(ZVal& v) { Unref(v.ManagedVal()); }
|
|
|
|
// Deletes a possibly-managed value.
|
|
static void DeleteIfManaged(ZVal& v, const TypePtr& t) {
|
|
if ( IsManagedType(t) )
|
|
DeleteManagedType(v);
|
|
}
|
|
|
|
// Specifies the address of a flag to set if a ZVal is accessed
|
|
// that was missing (a nil pointer). Used to generate run-time
|
|
// error messages. We use an address-based interface so that
|
|
// this flag can be combined with a general-purpose error flag,
|
|
// allowing inner loops to only have to test a single flag.
|
|
static void SetZValNilStatusAddr(bool* _zval_was_nil_addr) { zval_was_nil_addr = _zval_was_nil_addr; }
|
|
|
|
private:
|
|
friend class RecordVal;
|
|
friend class VectorVal;
|
|
|
|
// Used for bool, int, enum.
|
|
zeek_int_t int_val;
|
|
|
|
// Used for count and port.
|
|
zeek_uint_t uint_val;
|
|
|
|
// Used for double, time, interval.
|
|
double double_val;
|
|
|
|
// The types are all variants of Val, or more fundamentally Obj.
|
|
// They are raw pointers rather than IntrusivePtr's because
|
|
// unions can't contain the latter. For memory management, we use
|
|
// Ref/Unref.
|
|
StringVal* string_val;
|
|
AddrVal* addr_val;
|
|
SubNetVal* subnet_val;
|
|
File* file_val;
|
|
Func* func_val;
|
|
ListVal* list_val;
|
|
OpaqueVal* opaque_val;
|
|
PatternVal* re_val;
|
|
TableVal* table_val;
|
|
RecordVal* record_val;
|
|
VectorVal* vector_val;
|
|
TypeVal* type_val;
|
|
|
|
// Used for "any" values.
|
|
Val* any_val;
|
|
|
|
// Used for generic access to managed (derived-from-Obj) objects.
|
|
Obj* managed_val;
|
|
|
|
// A class-wide status variable set to true when a missing
|
|
// value was accessed. Only germane for managed types, since
|
|
// we don't track the presence of non-managed types. Static
|
|
// because often the caller won't have direct access to the
|
|
// particular ZVal that produces the issue, and just wants to
|
|
// know whether it occurred at some point.
|
|
static bool* zval_was_nil_addr;
|
|
};
|
|
|
|
} // namespace zeek
|