in source/topic_tree.c [686:782]
int aws_mqtt_topic_tree_transaction_remove(
struct aws_mqtt_topic_tree *tree,
struct aws_array_list *transaction,
const struct aws_byte_cursor *topic_filter,
void **old_userdata) {
AWS_PRECONDITION(tree);
AWS_PRECONDITION(transaction);
AWS_PRECONDITION(topic_filter);
AWS_LOGF_DEBUG(
AWS_LS_MQTT_TOPIC_TREE,
"tree=%p: Removing topic filter \"" PRInSTR "\" from topic tree",
(void *)tree,
AWS_BYTE_CURSOR_PRI(*topic_filter));
/* Initialize output parameter to a safe default */
if (old_userdata) {
*old_userdata = NULL;
}
/* Default to error because that's what handle_error will do in all cases except node not found */
int result = AWS_OP_ERR;
struct topic_tree_action *action = s_topic_tree_action_create(transaction);
if (!action) {
return AWS_OP_ERR;
}
struct aws_array_list sub_topic_parts;
AWS_ZERO_STRUCT(sub_topic_parts);
if (aws_array_list_init_dynamic(&sub_topic_parts, tree->allocator, 1, sizeof(struct aws_byte_cursor))) {
AWS_LOGF_ERROR(AWS_LS_MQTT_TOPIC_TREE, "tree=%p: Failed to initialize topic parts array", (void *)tree);
goto handle_error;
}
if (aws_byte_cursor_split_on_char(topic_filter, '/', &sub_topic_parts)) {
AWS_LOGF_ERROR(AWS_LS_MQTT_TOPIC_TREE, "tree=%p: Failed to split topic filter", (void *)tree);
goto handle_error;
}
const size_t sub_parts_len = aws_array_list_length(&sub_topic_parts);
if (!sub_parts_len) {
AWS_LOGF_ERROR(AWS_LS_MQTT_TOPIC_TREE, "tree=%p: Failed to get topic parts length", (void *)tree);
goto handle_error;
}
s_topic_tree_action_to_remove(action, tree->allocator, sub_parts_len);
struct aws_mqtt_topic_node *current = tree->root;
if (aws_array_list_push_back(&action->to_remove, ¤t)) {
AWS_LOGF_ERROR(AWS_LS_MQTT_TOPIC_TREE, "tree=%p: Failed to insert root node into to_remove list", (void *)tree);
goto handle_error;
}
for (size_t i = 0; i < sub_parts_len; ++i) {
/* Get the current topic part */
struct aws_byte_cursor *sub_part = NULL;
aws_array_list_get_at_ptr(&sub_topic_parts, (void **)&sub_part, i);
/* Find mid-node */
struct aws_hash_element *elem = NULL;
aws_hash_table_find(¤t->subtopics, sub_part, &elem);
if (elem) {
/* If the node exists, just traverse it */
current = elem->value;
if (aws_array_list_push_back(&action->to_remove, ¤t)) {
AWS_LOGF_ERROR(
AWS_LS_MQTT_TOPIC_TREE, "tree=%p: Failed to insert topic node into to_remove list", (void *)tree);
goto handle_error;
}
} else {
/* If not, abandon ship */
goto handle_not_found;
}
}
action->node_to_update = current;
aws_array_list_clean_up(&sub_topic_parts);
if (old_userdata) {
*old_userdata = current->userdata;
}
return AWS_OP_SUCCESS;
handle_not_found:
result = AWS_OP_SUCCESS;
handle_error:
aws_array_list_clean_up(&sub_topic_parts);
s_topic_tree_action_destroy(action);
aws_array_list_pop_back(transaction);
return result;
}