Back to libut API Reference


SYNOPSIS

    #include "libut/ut.h"
    
    LL_ADD(head,tmp,add);
    LL_DEL(head,tmp,del);
    LL_FIND(head,tmp,findname);
    LL_FIND_BY_MEMBER(head,tmp,member,findval);
    LL_FIND_BY_MEMBER_STR(head,tmp,member,findval);


DESCRIPTION

These macros manipulate singly-linked lists. Since they are macros, they do not require their arguments to be of a particular type. However, the structures to be formed into a list must have a member named next which points to the next structure. E.g.,

    typedef struct user_t {
        char name[10];
        int id;
        struct user_t *next;
    } user_t;

To form these structures into a linked list, a list head is also required. The head is a pointer to the first structure, and must be initially NULL.

    user_t *user_list = NULL;

LL_ADD

This is how to add an element to a linked list:

    user_t *user, *tmp;
    
    /* create the element */
    user = malloc(sizeof(user_t));
    strncpy(user->name, "Joe");
    id = 1;
    user->next = NULL;
    
    /* add the element to the list */
    LL_ADD( user_list, tmp, user );

Note that the tmp variable was created of the same structure-pointer type as the list head and the new element. It is used a temporary variable and need not be initialized.

A more fully libut-oriented approach would use UT_mem_alloc(3) instead of malloc(3), and use UT_strncpy(3) instead of strncpy(3).

LL_DEL

This is how to delete an element (given it's pointer) from a linked list:

    /* suppose user was previously LL_ADD'ed to user_list */
    user_t *user, *tmp;
    
    /* delete the element from the list */
    LL_DEL( user_list, tmp, user );

The tmp variable was created of the same structure-pointer type as the list head and the element to be deleted. It is used a temporary variable and need not be initialized.

Deleting an element from a linked list only unlinks it from that list. It does not free it.

LL_FIND

This particular macro is designed for use with structures that have a name member of type char*. It scans the linked-list to find an element whose name matches the specified name, by string equality.

    /* suppose user Joe was previously LL_ADD'ed to user_list */
    user_t *user, *tmp;
    char *sought_name = "Joe";
    
    /* find "Joe" in the list */
    LL_FIND( user_list, tmp, sought_name );

The tmp variable was created of the same structure-pointer type as the list head and the element being sought. It is used a temporary variable and need not be initialized.

Upon completion of this macro, tmp points to the element being sought, or is NULL if the element wasn't found in the list.

LL_FIND_BY_MEMBER

This macro scans the linked-list for an element having a specified value for one of its members. The test is by ``=='' equality, not string equality.

    /* suppose user Joe with id 1 was previously LL_ADD'ed to user_list */
    user_t *user, *tmp;
    int i = 1;
    
    /* find user with id 1 */
    LL_FIND_BY_MEMBER( user_list, tmp, id, i );

With this macro, the third argument (here, id) is the structure member being scanned for equality with the fourth argument (here, i). Since this is a macro, there is no problem specifying the structure member by itself; the macro expands to valid C syntax, e.g., tmp->id.

The tmp variable was created of the same structure-pointer type as the list head and the element being sought. It is used a temporary variable and need not be initialized.

Upon completion of this macro, tmp points to the element being sought, or is NULL if the element wasn't found in the list.

LL_FIND_BY_MEMBER_STR

This macro scans the linked-list for an element having a specified value for one of its string members. (It is slightly more generic than LL_FIND because it allows the string-valued structure member to be specified).

    /* suppose user Joe was previously LL_ADD'ed to user_list */
    user_t *user, *tmp;
    char *joe = "Joe";
    
    /* find user whose name is Joe */
    LL_FIND_BY_MEMBER_STR( user_list, tmp, name, joe );

With this macro, the third argument (here, name) is the structure member being scanned for string equality with the fourth argument (here, joe). Since this is a macro, there is no problem specifying the structure member by itself; the macro expands to valid C syntax, e.g., tmp->name.

The tmp variable was created of the same structure-pointer type as the list head and the element being sought. It is used a temporary variable and need not be initialized.

Upon completion of this macro, tmp points to the element being sought, or is NULL if the element wasn't found in the list.


SEE ALSO

HASH_ADD(3)


AUTHOR

Troy D. Hanson <thanson@users.sourceforge.net>