diff --git a/src/Val.cc b/src/Val.cc index 10f7206c82..5f39fbba9a 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3269,8 +3269,11 @@ bool VectorVal::Assign(unsigned int index, ValPtr element) if ( ! CheckElementType(element) ) return false; - if ( index >= vector_val->size() ) + auto n = vector_val->size(); + + if ( index >= n ) { + AddHoles(index - n); vector_val->resize(index + 1); if ( yield_types ) yield_types->resize(index + 1); @@ -3314,14 +3317,14 @@ bool VectorVal::Insert(unsigned int index, ValPtr element) vector::iterator it; vector::iterator types_it; - const auto& t = element->GetType(); + auto n = vector_val->size(); - if ( index < vector_val->size() ) - { + if ( index < n ) + { // May need to delete previous element it = std::next(vector_val->begin(), index); if ( yield_types ) { - DeleteIfManaged(*it, t); + DeleteIfManaged(*it, element->GetType()); types_it = std::next(yield_types->begin(), index); } else if ( managed_yield ) @@ -3332,10 +3335,12 @@ bool VectorVal::Insert(unsigned int index, ValPtr element) it = vector_val->end(); if ( yield_types ) types_it = yield_types->end(); + AddHoles(index - n); } if ( yield_types ) { + const auto& t = element->GetType(); yield_types->insert(types_it, t); vector_val->insert(it, ZVal(std::move(element), t)); } @@ -3346,6 +3351,16 @@ bool VectorVal::Insert(unsigned int index, ValPtr element) return true; } +void VectorVal::AddHoles(int nholes) + { + TypePtr fill_t = yield_type; + if ( yield_type->Tag() == TYPE_VOID ) + fill_t = base_type(TYPE_ANY); + + for ( auto i = 0; i < nholes; ++i ) + vector_val->emplace_back(ZVal(fill_t)); + } + bool VectorVal::Remove(unsigned int index) { if ( index >= vector_val->size() ) diff --git a/src/Val.h b/src/Val.h index d5665d1dca..70961d0f59 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1571,6 +1571,9 @@ private: // element type-checked. bool CheckElementType(const ValPtr& element); + // Add the given number of "holes" to the end of a vector. + void AddHoles(int nholes); + std::vector* vector_val; // For homogeneous vectors (the usual case), the type of the diff --git a/src/ZVal.cc b/src/ZVal.cc index 17f94ef825..5480ae0da6 100644 --- a/src/ZVal.cc +++ b/src/ZVal.cc @@ -139,6 +139,86 @@ ZVal::ZVal(ValPtr v, const TypePtr& t) } } +ZVal::ZVal(const TypePtr& t) + { + switch ( t->Tag() ) { + case TYPE_BOOL: + case TYPE_INT: + case TYPE_ENUM: + int_val = 0; + break; + + case TYPE_COUNT: + case TYPE_PORT: + uint_val = 0; + break; + + case TYPE_DOUBLE: + case TYPE_INTERVAL: + case TYPE_TIME: + double_val = 0.0; + break; + + case TYPE_FUNC: + func_val = nullptr; + break; + + case TYPE_FILE: + file_val = nullptr; + break; + + case TYPE_LIST: + list_val = nullptr; + break; + + case TYPE_OPAQUE: + opaque_val = nullptr; + break; + + case TYPE_PATTERN: + re_val = nullptr; + break; + + case TYPE_TABLE: + table_val = nullptr; + break; + + case TYPE_VECTOR: + vector_val = nullptr; + break; + + case TYPE_RECORD: + record_val = nullptr; + break; + + case TYPE_STRING: + string_val = nullptr; + break; + + case TYPE_ADDR: + addr_val = nullptr; + break; + + case TYPE_SUBNET: + subnet_val = nullptr; + break; + + case TYPE_ANY: + any_val = nullptr; + break; + + case TYPE_TYPE: + type_val = nullptr; + break; + + case TYPE_ERROR: + case TYPE_TIMER: + case TYPE_UNION: + case TYPE_VOID: + reporter->InternalError("bad type in ZVal constructor"); + } + } + ValPtr ZVal::ToVal(const TypePtr& t) const { Val* v; diff --git a/src/ZVal.h b/src/ZVal.h index b05eb48ce6..f448e3ceef 100644 --- a/src/ZVal.h +++ b/src/ZVal.h @@ -43,6 +43,9 @@ union ZVal { // 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); + // 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;