mirror of
https://github.com/darlinghq/xcbuild.git
synced 2024-11-27 05:50:27 +00:00
Simplify pre-allocating BOM indexes and BOM tree entries.
Use a single reserve method to reserve space in BOM indexes or in a BOM tree's entry index, rather than specifying on initialization. This better supports reserving additional space after allocation, which is needed in any case, without sacrificing performance.
This commit is contained in:
parent
8e36066203
commit
57e8d04685
@ -41,12 +41,6 @@ struct bom_context;
|
||||
struct bom_context *
|
||||
bom_alloc_empty(struct bom_context_memory memory);
|
||||
|
||||
struct bom_context *
|
||||
bom_alloc_empty2(struct bom_context_memory memory, uint32_t index_count);
|
||||
|
||||
void
|
||||
bom_alloc_indexes(struct bom_context *context, uint32_t index_count);
|
||||
|
||||
struct bom_context *
|
||||
bom_alloc_load(struct bom_context_memory memory);
|
||||
|
||||
@ -67,6 +61,9 @@ bom_index_iterate(struct bom_context *context, bom_index_iterator iterator, void
|
||||
void *
|
||||
bom_index_get(struct bom_context *context, uint32_t index, size_t *data_len);
|
||||
|
||||
void
|
||||
bom_index_reserve(struct bom_context *context, size_t count);
|
||||
|
||||
uint32_t
|
||||
bom_index_add(struct bom_context *context, const void *data, size_t data_len);
|
||||
|
||||
@ -95,15 +92,9 @@ struct bom_tree_context;
|
||||
struct bom_tree_context *
|
||||
bom_tree_alloc_empty(struct bom_context *context, const char *variable_name);
|
||||
|
||||
struct bom_tree_context *
|
||||
bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, uint32_t index_count);
|
||||
|
||||
struct bom_tree_context *
|
||||
bom_tree_alloc_load(struct bom_context *context, const char *variable_name);
|
||||
|
||||
void
|
||||
bom_tree_clear(struct bom_tree_context *tree);
|
||||
|
||||
void
|
||||
bom_tree_free(struct bom_tree_context *tree);
|
||||
|
||||
@ -118,6 +109,9 @@ typedef void (*bom_tree_iterator)(struct bom_tree_context *tree, void *key, size
|
||||
void
|
||||
bom_tree_iterate(struct bom_tree_context *tree, bom_tree_iterator iterator, void *ctx);
|
||||
|
||||
void
|
||||
bom_tree_reserve(struct bom_tree_context *tree, size_t count);
|
||||
|
||||
void
|
||||
bom_tree_add(struct bom_tree_context *tree, const void *key, size_t key_len, const void *value, size_t value_len);
|
||||
|
||||
|
@ -58,7 +58,7 @@ extern "C" {
|
||||
*
|
||||
* Some BOM variables contain trees, most commonly the "Paths" variable
|
||||
* found in standard BOM archives. BOM trees are a header in the variable's
|
||||
* data section, has an index pointing to the root of the tree. Each item
|
||||
* data section with an index pointing to the root of the tree. Each item
|
||||
* in the tree has indexes pointing to both key and value data for that item.
|
||||
*/
|
||||
|
||||
|
@ -39,12 +39,6 @@ _bom_alloc(struct bom_context_memory memory)
|
||||
|
||||
struct bom_context *
|
||||
bom_alloc_empty(struct bom_context_memory memory)
|
||||
{
|
||||
return bom_alloc_empty2(memory, 2);
|
||||
}
|
||||
|
||||
struct bom_context *
|
||||
bom_alloc_empty2(struct bom_context_memory memory, uint32_t index_count)
|
||||
{
|
||||
struct bom_context *context = _bom_alloc(memory);
|
||||
if (context == NULL) {
|
||||
@ -54,7 +48,7 @@ bom_alloc_empty2(struct bom_context_memory memory, uint32_t index_count)
|
||||
|
||||
size_t header_size = sizeof(struct bom_header);
|
||||
size_t index_size = sizeof(struct bom_index_header);
|
||||
size_t freelist_size = sizeof(struct bom_index_header) + sizeof(struct bom_index) * (index_count + 2);
|
||||
size_t freelist_size = sizeof(struct bom_index_header) + sizeof(struct bom_index) * 2;
|
||||
size_t variables_size = sizeof(struct bom_variables);
|
||||
context->memory.resize(&context->memory, header_size + index_size + freelist_size + variables_size);
|
||||
|
||||
@ -241,6 +235,24 @@ bom_index_get(struct bom_context *context, uint32_t index, size_t *data_len)
|
||||
return (void *)header + ioffset;
|
||||
}
|
||||
|
||||
void
|
||||
bom_index_reserve(struct bom_context *context, size_t count)
|
||||
{
|
||||
assert(context != NULL);
|
||||
assert(context->iteration_count == 0 && "cannot mutate while iterating");
|
||||
struct bom_header *header = (struct bom_header *)context->memory.data;
|
||||
|
||||
/* Insert space for extra indexes at the end of the currently allocated space. */
|
||||
uint32_t index_point = ntohl(header->index_offset) + ntohl(header->index_length);
|
||||
size_t new_index_length = ntohl(header->index_length) + sizeof(struct bom_index) * count;
|
||||
ptrdiff_t index_delta = sizeof(struct bom_index) * count;
|
||||
_bom_address_resize(context, index_point, index_delta);
|
||||
|
||||
/* Re-fetch, invalidated by resize. */
|
||||
header = (struct bom_header *)context->memory.data;
|
||||
header->index_length = htonl(new_index_length);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
bom_index_add(struct bom_context *context, const void *data, size_t data_len)
|
||||
{
|
||||
@ -412,21 +424,3 @@ bom_variable_add(struct bom_context *context, const char *name, int data_index)
|
||||
header->trailer_len = htonl(ntohl(header->trailer_len) + variable_delta);
|
||||
}
|
||||
|
||||
void
|
||||
bom_alloc_indexes(struct bom_context *context, uint32_t index_count)
|
||||
{
|
||||
assert(context != NULL);
|
||||
assert(context->iteration_count == 0 && "cannot mutate while iterating");
|
||||
struct bom_header *header = (struct bom_header *)context->memory.data;
|
||||
|
||||
/* Insert space for extra indexes at the end of the currently allocated space. */
|
||||
uint32_t index_point = ntohl(header->index_offset) + ntohl(header->index_length);
|
||||
size_t new_index_length = ntohl(header->index_length) + sizeof(struct bom_index) * index_count;
|
||||
ptrdiff_t index_delta = sizeof(struct bom_index) * index_count;
|
||||
_bom_address_resize(context, index_point, index_delta);
|
||||
|
||||
/* Re-fetch, invalidated by resize. */
|
||||
header = (struct bom_header *)context->memory.data;
|
||||
header->index_length = htonl(new_index_length);
|
||||
}
|
||||
|
||||
|
@ -52,12 +52,6 @@ _bom_tree_alloc(struct bom_context *context, const char *variable_name)
|
||||
|
||||
struct bom_tree_context *
|
||||
bom_tree_alloc_empty(struct bom_context *context, const char *variable_name)
|
||||
{
|
||||
return bom_tree_alloc_empty2(context, variable_name, 0);
|
||||
}
|
||||
|
||||
struct bom_tree_context *
|
||||
bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, uint32_t index_count)
|
||||
{
|
||||
struct bom_tree_context *tree_context = _bom_tree_alloc(context, variable_name);
|
||||
if (tree_context == NULL) {
|
||||
@ -65,8 +59,7 @@ bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, ui
|
||||
}
|
||||
|
||||
|
||||
size_t entry_size = sizeof(struct bom_tree_entry) + (sizeof(struct bom_tree_entry_indexes) * index_count);
|
||||
struct bom_tree_entry *entry = malloc(entry_size);
|
||||
struct bom_tree_entry *entry = malloc(sizeof(*entry));
|
||||
if (entry == NULL) {
|
||||
bom_tree_free(tree_context);
|
||||
return NULL;
|
||||
@ -83,7 +76,7 @@ bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, ui
|
||||
entry->count = htons(0);
|
||||
entry->forward = htonl(0);
|
||||
entry->backward = htonl(0);
|
||||
int entry_index = bom_index_add(tree_context->context, entry, entry_size);
|
||||
uint32_t entry_index = bom_index_add(tree_context->context, entry, sizeof(*entry));
|
||||
free(entry);
|
||||
|
||||
strncpy(tree->magic, "tree", 4);
|
||||
@ -92,7 +85,7 @@ bom_tree_alloc_empty2(struct bom_context *context, const char *variable_name, ui
|
||||
tree->node_size = htonl(4096); // todo
|
||||
tree->path_count = htonl(0);
|
||||
tree->unknown3 = 0;
|
||||
int tree_index = bom_index_add(tree_context->context, tree, sizeof(*tree));
|
||||
uint32_t tree_index = bom_index_add(tree_context->context, tree, sizeof(*tree));
|
||||
free(tree);
|
||||
|
||||
bom_variable_add(tree_context->context, tree_context->variable_name, tree_index);
|
||||
@ -108,7 +101,7 @@ bom_tree_alloc_load(struct bom_context *context, const char *variable_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
if (tree_index == -1) {
|
||||
bom_tree_free(tree_context);
|
||||
return NULL;
|
||||
@ -124,9 +117,6 @@ bom_tree_alloc_load(struct bom_context *context, const char *variable_name)
|
||||
return tree_context;
|
||||
}
|
||||
|
||||
void
|
||||
bom_tree_clear(struct bom_tree_context *tree_context);
|
||||
|
||||
void
|
||||
bom_tree_free(struct bom_tree_context *tree_context)
|
||||
{
|
||||
@ -138,8 +128,6 @@ bom_tree_free(struct bom_tree_context *tree_context)
|
||||
free(tree_context);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct bom_context *
|
||||
bom_tree_context_get(struct bom_tree_context *tree_context)
|
||||
{
|
||||
@ -154,7 +142,6 @@ bom_tree_variable_get(struct bom_tree_context *tree_context)
|
||||
return tree_context->variable_name;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterator, void *ctx)
|
||||
{
|
||||
@ -162,7 +149,7 @@ bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterat
|
||||
|
||||
tree_context->tree_iterating++;
|
||||
|
||||
int tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
struct bom_tree *tree = (struct bom_tree *)bom_index_get(tree_context->context, tree_index, NULL);
|
||||
|
||||
struct bom_tree_entry *paths = (struct bom_tree_entry *)bom_index_get(tree_context->context, ntohl(tree->child), NULL);
|
||||
@ -173,7 +160,7 @@ bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterat
|
||||
}
|
||||
|
||||
while (paths != NULL) {
|
||||
for (unsigned int i = 0; i < ntohs(paths->count); i++) {
|
||||
for (size_t i = 0; i < ntohs(paths->count); i++) {
|
||||
struct bom_tree_entry_indexes *indexes = &paths->indexes[i];
|
||||
|
||||
size_t key_len;
|
||||
@ -196,6 +183,19 @@ bom_tree_iterate(struct bom_tree_context *tree_context, bom_tree_iterator iterat
|
||||
tree_context->tree_iterating--;
|
||||
}
|
||||
|
||||
void
|
||||
bom_tree_reserve(struct bom_tree_context *tree_context, size_t count)
|
||||
{
|
||||
assert(tree_context != NULL);
|
||||
assert(tree_context->tree_iterating == 0);
|
||||
|
||||
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
struct bom_tree *tree = (struct bom_tree *)bom_index_get(tree_context->context, tree_index, NULL);
|
||||
|
||||
uint32_t paths_index = ntohl(tree->child);
|
||||
bom_index_append(tree_context->context, paths_index, sizeof(struct bom_tree_entry_indexes) * count);
|
||||
}
|
||||
|
||||
void
|
||||
bom_tree_add(struct bom_tree_context *tree_context, const void *key, size_t key_len, const void *value, size_t value_len)
|
||||
{
|
||||
@ -204,13 +204,13 @@ bom_tree_add(struct bom_tree_context *tree_context, const void *key, size_t key_
|
||||
assert(value != NULL);
|
||||
assert(tree_context->tree_iterating == 0);
|
||||
|
||||
int key_index = bom_index_add(tree_context->context, key, key_len);
|
||||
int value_index = bom_index_add(tree_context->context, value, value_len);
|
||||
uint32_t key_index = bom_index_add(tree_context->context, key, key_len);
|
||||
uint32_t value_index = bom_index_add(tree_context->context, value, value_len);
|
||||
|
||||
int tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
uint32_t tree_index = bom_variable_get(tree_context->context, tree_context->variable_name);
|
||||
struct bom_tree *tree = (struct bom_tree *)bom_index_get(tree_context->context, tree_index, NULL);
|
||||
|
||||
int paths_index = ntohl(tree->child);
|
||||
uint32_t paths_index = ntohl(tree->child);
|
||||
|
||||
size_t paths_length;
|
||||
struct bom_tree_entry *paths = (struct bom_tree_entry *)bom_index_get(tree_context->context, paths_index, &paths_length);
|
||||
@ -224,7 +224,7 @@ bom_tree_add(struct bom_tree_context *tree_context, const void *key, size_t key_
|
||||
paths = (struct bom_tree_entry *)bom_index_get(tree_context->context, paths_index, &paths_length);
|
||||
}
|
||||
|
||||
int entry_index = ntohs(paths->count);
|
||||
size_t entry_index = ntohs(paths->count);
|
||||
|
||||
/* Set the indexes for the inserted entry. */
|
||||
struct bom_tree_entry_indexes *indexes = &paths->indexes[entry_index];
|
||||
|
@ -89,7 +89,7 @@ write() const
|
||||
uint32_t facet_count = _facets.size();
|
||||
uint32_t rendition_count = _renditions.size() + _rawRenditions.size();
|
||||
uint32_t bom_index_count = 6 + facet_count * 2 + rendition_count * 2;
|
||||
bom_alloc_indexes(_bom.get(), bom_index_count);
|
||||
bom_index_reserve(_bom.get(), bom_index_count);
|
||||
|
||||
/* Write header. */
|
||||
struct car_header *header = (struct car_header *)malloc(sizeof(struct car_header));
|
||||
@ -142,7 +142,8 @@ write() const
|
||||
bom_variable_add(_bom.get(), car_key_format_variable, key_format_index);
|
||||
|
||||
/* Write facets. */
|
||||
struct bom_tree_context *facets_tree_context = bom_tree_alloc_empty2(_bom.get(), car_facet_keys_variable, facet_count);
|
||||
struct bom_tree_context *facets_tree_context = bom_tree_alloc_empty(_bom.get(), car_facet_keys_variable);
|
||||
bom_tree_reserve(facets_tree_context, facet_count);
|
||||
if (facets_tree_context != NULL) {
|
||||
for (auto const &item : _facets) {
|
||||
auto facet_value = item.second.write();
|
||||
@ -157,7 +158,8 @@ write() const
|
||||
}
|
||||
|
||||
/* Write renditions. */
|
||||
struct bom_tree_context *renditions_tree_context = bom_tree_alloc_empty2(_bom.get(), car_renditions_variable, rendition_count);
|
||||
struct bom_tree_context *renditions_tree_context = bom_tree_alloc_empty(_bom.get(), car_renditions_variable);
|
||||
bom_tree_reserve(renditions_tree_context, rendition_count);
|
||||
if (renditions_tree_context != NULL) {
|
||||
for (auto const &item : _renditions) {
|
||||
auto attributes_value = item.second.attributes().write(keyfmt->num_identifiers, keyfmt->identifier_list);
|
||||
|
@ -110,7 +110,8 @@ TEST(Writer, TestWriter100)
|
||||
/* Write out. */
|
||||
/* Write with half the required number of pre-allocated indexes */
|
||||
int preallocated_index_count = 6 + create_facet_count * 2 + create_rendition_count * 2;
|
||||
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty2(bom_context_memory(NULL, 0), preallocated_index_count / 2), bom_free);
|
||||
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty(bom_context_memory(NULL, 0)), bom_free);
|
||||
bom_index_reserve(writer_bom.get(), preallocated_index_count / 2);
|
||||
EXPECT_NE(writer_bom, nullptr);
|
||||
|
||||
auto writer = car::Writer::Create(std::move(writer_bom));
|
||||
@ -188,7 +189,8 @@ TEST(Writer, TestWriter100Optimal)
|
||||
* Each tree entry (facet or rendition) requires 2: one key index, one value index.
|
||||
*/
|
||||
unsigned int preallocated_index_count = 6 + create_facet_count * 2 + create_rendition_count * 2;
|
||||
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty2(bom_context_memory(NULL, 0), preallocated_index_count), bom_free);
|
||||
auto writer_bom = car::Writer::unique_ptr_bom(bom_alloc_empty(bom_context_memory(NULL, 0)), bom_free);
|
||||
bom_index_reserve(writer_bom.get(), preallocated_index_count);
|
||||
EXPECT_NE(writer_bom, nullptr);
|
||||
|
||||
auto writer = car::Writer::Create(std::move(writer_bom));
|
||||
|
Loading…
Reference in New Issue
Block a user