Merge pull request #3376 from harfbuzz/auto-vector

[vector] Automatic item allocation / destruction
This commit is contained in:
Behdad Esfahbod 2022-01-18 07:28:07 -08:00 committed by GitHub
commit 0b54f92416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 14 deletions

View File

@ -186,7 +186,7 @@ struct graph_t
~graph_t () ~graph_t ()
{ {
vertices_.fini_deep (); vertices_.fini ();
} }
bool in_error () const bool in_error () const
@ -309,7 +309,7 @@ struct graph_t
remap_all_obj_indices (id_map, &sorted_graph); remap_all_obj_indices (id_map, &sorted_graph);
hb_swap (vertices_, sorted_graph); hb_swap (vertices_, sorted_graph);
sorted_graph.fini_deep (); sorted_graph.fini ();
} }
/* /*
@ -369,7 +369,7 @@ struct graph_t
remap_all_obj_indices (id_map, &sorted_graph); remap_all_obj_indices (id_map, &sorted_graph);
hb_swap (vertices_, sorted_graph); hb_swap (vertices_, sorted_graph);
sorted_graph.fini_deep (); sorted_graph.fini ();
} }
/* /*

View File

@ -82,6 +82,7 @@ struct hb_vector_t
void fini () void fini ()
{ {
shrink_vector (0);
hb_free (arrayZ); hb_free (arrayZ);
init (); init ();
} }
@ -223,13 +224,73 @@ struct hb_vector_t
new (std::addressof (new_array[i])) Type (); new (std::addressof (new_array[i])) Type ();
for (unsigned i = 0; i < (unsigned) length; i++) for (unsigned i = 0; i < (unsigned) length; i++)
new_array[i] = std::move (arrayZ[i]); new_array[i] = std::move (arrayZ[i]);
for (unsigned i = 0; i < (unsigned) length; i++) unsigned old_length = length;
arrayZ[i].~Type (); shrink_vector (0);
length = old_length;
hb_free (arrayZ); hb_free (arrayZ);
} }
return new_array; return new_array;
} }
template <typename T = Type,
hb_enable_if (std::is_trivially_constructible<T>::value ||
!std::is_default_constructible<T>::value)>
void
grow_vector (unsigned size)
{
memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ));
length = size;
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_constructible<T>::value &&
std::is_default_constructible<T>::value)>
void
grow_vector (unsigned size)
{
while (length < size)
{
length++;
new (std::addressof (arrayZ[length - 1])) Type ();
}
}
template <typename T = Type,
hb_enable_if (std::is_trivially_destructible<T>::value)>
void
shrink_vector (unsigned size)
{
length = size;
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_destructible<T>::value)>
void
shrink_vector (unsigned size)
{
while ((unsigned) length > size)
{
arrayZ[(unsigned) length - 1].~Type ();
length--;
}
}
template <typename T = Type,
hb_enable_if (std::is_trivially_copy_assignable<T>::value)>
void
shift_down_vector (unsigned i)
{
memmove (static_cast<void *> (&arrayZ[i - 1]),
static_cast<void *> (&arrayZ[i]),
(length - i) * sizeof (Type));
}
template <typename T = Type,
hb_enable_if (!std::is_trivially_copy_assignable<T>::value)>
void
shift_down_vector (unsigned i)
{
for (; i < length; i++)
arrayZ[i - 1] = std::move (arrayZ[i]);
}
/* Allocate for size but don't adjust length. */ /* Allocate for size but don't adjust length. */
bool alloc (unsigned int size) bool alloc (unsigned int size)
{ {
@ -272,8 +333,9 @@ struct hb_vector_t
return false; return false;
if (size > length) if (size > length)
// XXX reconstruct objects?! / destruct objects... grow_vector (size);
memset (arrayZ + length, 0, (size - length) * sizeof (*arrayZ)); else if (size < length)
shrink_vector (size);
length = size; length = size;
return true; return true;
@ -282,25 +344,28 @@ struct hb_vector_t
Type pop () Type pop ()
{ {
if (!length) return Null (Type); if (!length) return Null (Type);
return std::move (arrayZ[--length]); /* Does this move actually work? */ Type v = std::move (arrayZ[length - 1]);
// XXX Destruct? arrayZ[length - 1].~Type ();
length--;
return v;
} }
void remove (unsigned int i) void remove (unsigned int i)
{ {
if (unlikely (i >= length)) if (unlikely (i >= length))
return; return;
memmove (static_cast<void *> (&arrayZ[i]), arrayZ[i].~Type ();
static_cast<void *> (&arrayZ[i + 1]), shift_down_vector (i + 1);
(length - i - 1) * sizeof (Type));
length--; length--;
} }
void shrink (int size_) void shrink (int size_)
{ {
unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;
if (size < length) if (size >= length)
length = size; return;
shrink_vector (size);
} }
template <typename T> template <typename T>