restore support for vectors with holes

remove vestigial comment
This commit is contained in:
Vern Paxson 2021-04-14 18:16:46 -07:00
parent ff393dbd8a
commit c1903afb3b
2 changed files with 94 additions and 57 deletions

View file

@ -3241,7 +3241,7 @@ ValPtr TypeVal::DoClone(CloneState* state)
VectorVal::VectorVal(VectorTypePtr t) : Val(t) VectorVal::VectorVal(VectorTypePtr t) : Val(t)
{ {
vector_val = new vector<ZVal>(); vector_val = new vector<std::optional<ZVal>>();
yield_type = t->Yield(); yield_type = t->Yield();
auto y_tag = yield_type->Tag(); auto y_tag = yield_type->Tag();
@ -3255,14 +3255,19 @@ VectorVal::~VectorVal()
{ {
int n = yield_types->size(); int n = yield_types->size();
for ( auto i = 0; i < n; ++i ) for ( auto i = 0; i < n; ++i )
ZVal::DeleteIfManaged((*vector_val)[i], (*yield_types)[i]); {
auto& elem = (*vector_val)[i];
if ( elem )
ZVal::DeleteIfManaged(*elem, (*yield_types)[i]);
}
delete yield_types; delete yield_types;
} }
else if ( managed_yield ) else if ( managed_yield )
{ {
for ( auto& elem : *vector_val ) for ( auto& elem : *vector_val )
ZVal::DeleteManagedType(elem); if ( elem )
ZVal::DeleteManagedType(*elem);
} }
delete vector_val; delete vector_val;
@ -3320,7 +3325,9 @@ bool VectorVal::Assign(unsigned int index, ValPtr element)
if ( index >= n ) if ( index >= n )
{ {
if ( index > n )
AddHoles(index - n); AddHoles(index - n);
vector_val->resize(index + 1); vector_val->resize(index + 1);
if ( yield_types ) if ( yield_types )
yield_types->resize(index + 1); yield_types->resize(index + 1);
@ -3330,14 +3337,21 @@ bool VectorVal::Assign(unsigned int index, ValPtr element)
{ {
const auto& t = element->GetType(); const auto& t = element->GetType();
(*yield_types)[index] = t; (*yield_types)[index] = t;
ZVal::DeleteIfManaged((*vector_val)[index], t); auto& elem = (*vector_val)[index];
(*vector_val)[index] = ZVal(std::move(element), t); if ( elem )
ZVal::DeleteIfManaged(*elem, t);
elem = ZVal(std::move(element), t);
} }
else else
{ {
if ( managed_yield ) auto& elem = (*vector_val)[index];
ZVal::DeleteManagedType((*vector_val)[index]); if ( managed_yield && elem )
(*vector_val)[index] = ZVal(std::move(element), yield_type); ZVal::DeleteManagedType(*elem);
if ( element )
elem = ZVal(std::move(element), yield_type);
else
elem = std::nullopt;
} }
Modified(); Modified();
@ -3361,7 +3375,7 @@ bool VectorVal::Insert(unsigned int index, ValPtr element)
if ( ! CheckElementType(element) ) if ( ! CheckElementType(element) )
return false; return false;
vector<ZVal>::iterator it; vector<std::optional<ZVal>>::iterator it;
vector<TypePtr>::iterator types_it; vector<TypePtr>::iterator types_it;
auto n = vector_val->size(); auto n = vector_val->size();
@ -3371,20 +3385,25 @@ bool VectorVal::Insert(unsigned int index, ValPtr element)
it = std::next(vector_val->begin(), index); it = std::next(vector_val->begin(), index);
if ( yield_types ) if ( yield_types )
{ {
ZVal::DeleteIfManaged(*it, element->GetType()); if ( *it )
ZVal::DeleteIfManaged(**it, element->GetType());
types_it = std::next(yield_types->begin(), index); types_it = std::next(yield_types->begin(), index);
} }
else if ( managed_yield ) else if ( managed_yield )
ZVal::DeleteManagedType(*it); ZVal::DeleteManagedType(**it);
} }
else else
{ {
it = vector_val->end(); it = vector_val->end();
if ( yield_types ) if ( yield_types )
types_it = yield_types->end(); types_it = yield_types->end();
if ( index > n )
AddHoles(index - n); AddHoles(index - n);
} }
if ( element )
{
if ( yield_types ) if ( yield_types )
{ {
const auto& t = element->GetType(); const auto& t = element->GetType();
@ -3393,6 +3412,9 @@ bool VectorVal::Insert(unsigned int index, ValPtr element)
} }
else else
vector_val->insert(it, ZVal(std::move(element), yield_type)); vector_val->insert(it, ZVal(std::move(element), yield_type));
}
else
vector_val->insert(it, std::nullopt);
Modified(); Modified();
return true; return true;
@ -3405,7 +3427,7 @@ void VectorVal::AddHoles(int nholes)
fill_t = base_type(TYPE_ANY); fill_t = base_type(TYPE_ANY);
for ( auto i = 0; i < nholes; ++i ) for ( auto i = 0; i < nholes; ++i )
vector_val->emplace_back(ZVal(fill_t)); vector_val->emplace_back(std::nullopt);
} }
bool VectorVal::Remove(unsigned int index) bool VectorVal::Remove(unsigned int index)
@ -3418,12 +3440,13 @@ bool VectorVal::Remove(unsigned int index)
if ( yield_types ) if ( yield_types )
{ {
auto types_it = std::next(yield_types->begin(), index); auto types_it = std::next(yield_types->begin(), index);
ZVal::DeleteIfManaged(*it, *types_it); if ( *it )
ZVal::DeleteIfManaged(**it, *types_it);
yield_types->erase(types_it); yield_types->erase(types_it);
} }
else if ( managed_yield ) else if ( managed_yield )
ZVal::DeleteManagedType(*it); ZVal::DeleteManagedType(**it);
vector_val->erase(it); vector_val->erase(it);
@ -3460,33 +3483,33 @@ ValPtr VectorVal::At(unsigned int index) const
if ( index >= vector_val->size() ) if ( index >= vector_val->size() )
return Val::nil; return Val::nil;
auto& elem = (*vector_val)[index];
if ( ! elem )
return Val::nil;
const auto& t = yield_types ? (*yield_types)[index] : yield_type; const auto& t = yield_types ? (*yield_types)[index] : yield_type;
return (*vector_val)[index].ToVal(t); return elem->ToVal(t);
} }
static Func* sort_function_comp = nullptr; static Func* sort_function_comp = nullptr;
// Used for indirect sorting to support order(). // Used for indirect sorting to support order().
static std::vector<const ZVal*> index_map; static std::vector<const std::optional<ZVal>*> index_map;
// The yield type of the vector being sorted. // The yield type of the vector being sorted.
static TypePtr sort_type; static TypePtr sort_type;
static bool sort_type_is_managed = false;
static bool sort_function(const ZVal& a, const ZVal& b) static bool sort_function(const std::optional<ZVal>& a, const std::optional<ZVal>& b)
{ {
// Missing values are only applicable for managed types. if ( ! a )
if ( sort_type_is_managed ) return false;
{
if ( ! a.ManagedVal() )
return 0;
if ( ! b.ManagedVal() )
return 1;
}
auto a_v = a.ToVal(sort_type); if ( ! b )
auto b_v = b.ToVal(sort_type); return true;
auto a_v = a->ToVal(sort_type);
auto b_v = b->ToVal(sort_type);
auto result = sort_function_comp->Invoke(a_v, b_v); auto result = sort_function_comp->Invoke(a_v, b_v);
int int_result = result->CoerceToInt(); int int_result = result->CoerceToInt();
@ -3494,19 +3517,37 @@ static bool sort_function(const ZVal& a, const ZVal& b)
return int_result < 0; return int_result < 0;
} }
static bool signed_sort_function (const ZVal& a, const ZVal& b) static bool signed_sort_function(const std::optional<ZVal>& a, const std::optional<ZVal>& b)
{ {
return a.AsInt() < b.AsInt(); if ( ! a )
return false;
if ( ! b )
return true;
return a->AsInt() < b->AsInt();
} }
static bool unsigned_sort_function (const ZVal& a, const ZVal& b) static bool unsigned_sort_function(const std::optional<ZVal>& a, const std::optional<ZVal>& b)
{ {
return a.AsCount() < b.AsCount(); if ( ! a )
return false;
if ( ! b )
return true;
return a->AsCount() < b->AsCount();
} }
static bool double_sort_function (const ZVal& a, const ZVal& b) static bool double_sort_function(const std::optional<ZVal>& a, const std::optional<ZVal>& b)
{ {
return a.AsDouble() < b.AsDouble(); if ( ! a )
return false;
if ( ! b )
return true;
return a->AsDouble() < b->AsDouble();
} }
static bool indirect_sort_function(size_t a, size_t b) static bool indirect_sort_function(size_t a, size_t b)
@ -3535,9 +3576,8 @@ void VectorVal::Sort(Func* cmp_func)
reporter->RuntimeError(GetLocationInfo(), "cannot sort a vector-of-any"); reporter->RuntimeError(GetLocationInfo(), "cannot sort a vector-of-any");
sort_type = yield_type; sort_type = yield_type;
sort_type_is_managed = ZVal::IsManagedType(sort_type);
bool (*sort_func)(const ZVal&, const ZVal&); bool (*sort_func)(const std::optional<ZVal>&, const std::optional<ZVal>&);
if ( cmp_func ) if ( cmp_func )
{ {
@ -3572,7 +3612,6 @@ VectorValPtr VectorVal::Order(Func* cmp_func)
} }
sort_type = yield_type; sort_type = yield_type;
sort_type_is_managed = ZVal::IsManagedType(sort_type);
bool (*sort_func)(size_t, size_t); bool (*sort_func)(size_t, size_t);
@ -3666,8 +3705,9 @@ ValPtr VectorVal::DoClone(CloneState* state)
for ( auto i = 0; i < n; ++i ) for ( auto i = 0; i < n; ++i )
{ {
auto vc = At(i)->Clone(state); auto elem = At(i);
vv->Append(std::move(vc)); if ( elem )
vv->Assign(i, elem->Clone(state));
} }
return vv; return vv;

View file

@ -1505,10 +1505,6 @@ public:
*/ */
bool Assign(unsigned int index, ValPtr element); bool Assign(unsigned int index, ValPtr element);
// Note: the following nullptr method can also go upon removing the above.
void Assign(unsigned int index, std::nullptr_t)
{ Assign(index, ValPtr{}); }
/** /**
* Assigns a given value to multiple indices in the vector. * Assigns a given value to multiple indices in the vector.
* @param index The starting index to assign to. * @param index The starting index to assign to.
@ -1581,18 +1577,19 @@ public:
/** /**
* Returns the given element in a given underlying representation. * Returns the given element in a given underlying representation.
* Enables efficient vector access. Caller must ensure that the * Enables efficient vector access. Caller must ensure that the
* index lies within the vector's range. * index lies within the vector's range, and does not point to
* a "hole".
* @param index The position in the vector of the element to return. * @param index The position in the vector of the element to return.
* @return The element's underlying value. * @return The element's underlying value.
*/ */
bro_uint_t CountAt(unsigned int index) const bro_uint_t CountAt(unsigned int index) const
{ return (*vector_val)[index].uint_val; } { return (*vector_val)[index]->uint_val; }
const RecordVal* RecordValAt(unsigned int index) const const RecordVal* RecordValAt(unsigned int index) const
{ return (*vector_val)[index].record_val; } { return (*vector_val)[index]->record_val; }
bool BoolAt(unsigned int index) const bool BoolAt(unsigned int index) const
{ return static_cast<bool>((*vector_val)[index].uint_val); } { return static_cast<bool>((*vector_val)[index]->uint_val); }
const StringVal* StringValAt(unsigned int index) const const StringVal* StringValAt(unsigned int index) const
{ return (*vector_val)[index].string_val; } { return (*vector_val)[index]->string_val; }
const String* StringAt(unsigned int index) const const String* StringAt(unsigned int index) const
{ return StringValAt(index)->AsString(); } { return StringValAt(index)->AsString(); }
@ -1601,7 +1598,7 @@ protected:
* Returns the element at a given index or nullptr if it does not exist. * Returns the element at a given index or nullptr if it does not exist.
* @param index The position in the vector of the element to return. * @param index The position in the vector of the element to return.
* @return The element at the given index or nullptr if the index * @return The element at the given index or nullptr if the index
* does not exist (it's greater than or equal to vector's current size). * does not exist.
* *
* Protected to ensure callers pick one of the differentiated accessors * Protected to ensure callers pick one of the differentiated accessors
* above, as appropriate, with ValAt() providing the original semantics. * above, as appropriate, with ValAt() providing the original semantics.
@ -1624,7 +1621,7 @@ private:
// Add the given number of "holes" to the end of a vector. // Add the given number of "holes" to the end of a vector.
void AddHoles(int nholes); void AddHoles(int nholes);
std::vector<ZVal>* vector_val; std::vector<std::optional<ZVal>>* vector_val;
// For homogeneous vectors (the usual case), the type of the // For homogeneous vectors (the usual case), the type of the
// elements. Will be TYPE_VOID for empty vectors created using // elements. Will be TYPE_VOID for empty vectors created using