static trg_files_tree_node *trg_file_parser_node_insert(trg_files_tree_node
                                                        * top,
                                                        trg_files_tree_node
                                                        * last,
                                                        JsonObject * file,
                                                        gint index,
                                                        JsonArray *
                                                        enabled,
                                                        JsonArray *
                                                        priorities)
{
    gchar **path = g_strsplit(file_get_name(file), "/", -1);
    trg_files_tree_node *lastIter = last;
    GList *parentList = NULL;
    gchar *path_el;
    GList *li;
    int i;

    /* Build up a list of pointers to each parent trg_files_tree_node
     * reversing the order as it iterates over its parent.
     */
    if (lastIter)
        while ((lastIter = lastIter->parent))
            parentList = g_list_prepend(parentList, lastIter);

    li = parentList;
    lastIter = top;

    /* Iterate over the path list which contains each file/directory
     * component of the path in order.
     */
    for (i = 0; (path_el = path[i]); i++) {
        gboolean isFile = !path[i + 1];
        trg_files_tree_node *target_node = NULL;

        /* No point checking for files. If there is a last parents iterator
         * check it for a shortcut. I'm assuming that these come in order of
         * directory at least to give performance a boost.
         */
        if (li && !isFile) {
            trg_files_tree_node *lastPathNode =
                (trg_files_tree_node *) li->data;

            if (!g_strcmp0(lastPathNode->name, path[i])) {
                target_node = lastPathNode;
                li = g_list_next(li);
            } else {
                /* No need to check any further. */
                li = NULL;
            }
        }

        if (!target_node && lastIter && lastIter->childrenHash && !isFile)
          target_node = g_hash_table_lookup(lastIter->childrenHash, path_el);

        /* Node needs creating */

        if (!target_node) {
            target_node = g_new0(trg_files_tree_node, 1);
            target_node->name = g_strdup(path[i]);
            target_node->parent = lastIter;
            trg_files_tree_node_add_child(lastIter, target_node);
        }

        lastIter = target_node;

        /* Files have more properties set here than for files.
         * Directories are updated from here too, by trg_files_tree_update_ancestors
         * working up the parents.
         */
        if (isFile) {
            target_node->length = file_get_length(file);
            target_node->bytesCompleted = file_get_bytes_completed(file);
            target_node->index = index;
            target_node->enabled =
                (gint) json_array_get_int_element(enabled, index);
            target_node->priority =
                (gint) json_array_get_int_element(priorities, index);

            trg_files_tree_update_ancestors(target_node);
        } else {
            target_node->index = -1;
        }
    }

    g_list_free(parentList);
    g_strfreev(path);

    return lastIter;
}
static trg_files_tree_node *trg_file_parser_node_insert(trg_files_tree_node
                                                        * top,
                                                        trg_files_tree_node
                                                        * last,
                                                        be_node *
                                                        file_node,
                                                        gint index)
{
    be_node *file_length_node = be_dict_find(file_node, "length", BE_INT);
    be_node *file_path_list = be_dict_find(file_node, "path", BE_LIST);
    trg_files_tree_node *lastIter = last;
    GList *parentList = NULL;
    be_node *path_el_node;
    GList *li;
    int i;

    if (!file_path_list || !file_length_node)
        return NULL;

    if (lastIter)
        while ((lastIter = lastIter->parent))
            parentList = g_list_prepend(parentList, lastIter);

    li = parentList;
    lastIter = top;

    /* Iterate over the path list which contains each file/directory
     * component of the path in order.
     */
    for (i = 0; (path_el_node = file_path_list->val.l[i]); i++) {
        gboolean isFile = !file_path_list->val.l[i + 1];
        trg_files_tree_node *target_node = NULL;

        if (li && !isFile) {
            trg_files_tree_node *lastPathNode = (trg_files_tree_node *) li->data;

            if (!g_strcmp0(lastPathNode->name, path_el_node->val.s)) {
                target_node = lastPathNode;
                li = g_list_next(li);
            } else {
                li = NULL;
            }
        }

        if (!target_node && lastIter && lastIter->childrenHash && !isFile)
          target_node = g_hash_table_lookup(lastIter->childrenHash, path_el_node->val.s);

        if (!target_node) {
            target_node = g_new0(trg_files_tree_node, 1);
            target_node->name = g_strdup(path_el_node->val.s);
            target_node->parent = lastIter;
            trg_files_tree_node_add_child(lastIter, target_node);
        }

        if (isFile) {
            target_node->length = (gint64) file_length_node->val.i;

            while (lastIter) {
                lastIter->length += target_node->length;
                lastIter = lastIter->parent;
            }
        }

        target_node->index = isFile ? index : -1;
        lastIter = target_node;
    }

    g_list_free(parentList);

    return lastIter;
}