Generator/RB_Sort_Items [ Functions ]

FUNCTION

Sort the items in all the headers according to the order specified in the 'item order' block in the robodoc.rc file.

SYNOPSIS

static void RB_Sort_Items(
    struct RB_header **headers,
    long header_count )

SOURCE

{
    int                 n_order = configuration.item_order.number;

    if ( n_order )
    {
        int                 i = 0;
        int                 j = 0;
        int                 max_number_of_items = 0;
        struct RB_Item    **items = NULL;
        struct RB_Item    **items_sorted = NULL;

        RB_Say( "Sorting items in %d headers.\n", SAY_DEBUG, header_count );

        /* Compute the maximum number of items in any given header */
        for ( j = 0; j < header_count; ++j )
        {
            struct RB_header   *header;
            struct RB_Item     *item;
            int                 item_count = 0;

            header = headers[j];
            for ( item = header->items; item; item = item->next )
            {
                ++item_count;
            }

            if ( item_count > max_number_of_items )
            {
                max_number_of_items = item_count;
            }
        }
        /* Allocate an array for the items, this makes it easier to
         * sort. */

        RB_Say( "Largest header has %d items.\n", SAY_DEBUG,
                max_number_of_items );

        if ( max_number_of_items == 0 )
        {
            /* No items in any of the headers, do nothing */
        }
        else
        {
            items = calloc( max_number_of_items, sizeof( struct RB_Item * ) );
            items_sorted =
                calloc( max_number_of_items, sizeof( struct RB_Item * ) );

            /* Sort items */
            for ( j = 0; j < header_count; ++j )
            {
                struct RB_header   *header = NULL;
                struct RB_Item     *item = NULL;
                int                 item_index = 0;
                int                 sorted_item_index = 0;
                int                 item_count = 0;

                header = headers[j];

                /* Copy item pointers to array */
                for ( item = header->items; item;
                      item = item->next, ++item_index )
                {
                    items[item_index] = item;
                    items_sorted[item_index] = item;
                };
                item_count = item_index;

                if ( item_count == 0 )
                {
                    /* No items in this header, do nothing. */
                }
                else
                {
                    assert( item_count <= max_number_of_items );

                    /* First copy the items in the order that is defined in
                     * item_order[] to sorted_items[] */
                    sorted_item_index = 0;
                    for ( i = 0; i < n_order; ++i )
                    {
                        for ( item_index = 0; item_index < item_count;
                              ++item_index )
                        {
                            if ( items[item_index] )
                            {
                                if ( strcmp
                                     ( configuration.items.
                                       names[items[item_index]->type],
                                       configuration.item_order.names[i] ) ==
                                     0 )
                                {
                                    /* copy to items_sorted */
                                    items_sorted[sorted_item_index] =
                                        items[item_index];
                                    ++sorted_item_index;
                                    items[item_index] = NULL;
                                }
                            }
                        }
                    }
                    /* Then copy the remaining items to items_sorted[] */
                    for ( item_index = 0; item_index < item_count;
                          ++item_index )
                    {
                        if ( items[item_index] )
                        {
                            /* copy to items_sorted */
                            items_sorted[sorted_item_index] =
                                items[item_index];
                            ++sorted_item_index;
                            items[item_index] = NULL;
                        }
                    }

                    assert( sorted_item_index == item_count );

                    /* Now copy the items in items_sorted[] back into the linked list in
                     * the header */
                    if ( item_count > 1 )
                    {
                        /* Chain all the items */
                        for ( item_index = 0; item_index < item_count - 1;
                              ++item_index )
                        {
                            items_sorted[item_index]->next =
                                items_sorted[item_index + 1];
                        }
                    }

                    assert( item_count > 0 );
                    items_sorted[item_count - 1]->next = NULL;
                    /* now link the first item to the header. */
                    header->items = items_sorted[0];
                }
            }

            free( items_sorted );
            free( items );
        }
    }

    RB_Say( "Done sorting items in %d headers.\n", SAY_DEBUG, header_count );
}