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 ()
{
vertices_.fini_deep ();
vertices_.fini ();
}
bool in_error () const
@ -309,7 +309,7 @@ struct graph_t
remap_all_obj_indices (id_map, &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);
hb_swap (vertices_, sorted_graph);
sorted_graph.fini_deep ();
sorted_graph.fini ();
}
/*

View File

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