Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  vlc_list.h   Sprache: C

 

/******************************************************************************
 * vlc_list.h
 ******************************************************************************
 * Copyright © 2018 Rémi Denis-Courmont
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


#ifndef VLC_LIST_H
# define VLC_LIST_H 1

# include <stdalign.h>
# include <stdbool.h>

/**
 * \defgroup list Linked lists
 * \ingroup cext
 * @{
 * \file
 * This provides convenience helpers for linked lists.
 */


/**
 * Doubly-linked list node.
 *
 * This data structure provides a doubly-linked list node.
 * It must be embedded in each member of a list as a node proper.
 * It also serves as a list head in the object containing the list.
 */

struct vlc_list
{
    struct vlc_list *prev;
    struct vlc_list *next;
};

/**
 * Static initializer for a list head.
 */

#define VLC_LIST_INITIALIZER(h) { h, h }

/**
 * Initializes an empty list head.
 */

static inline void vlc_list_init(struct vlc_list *restrict head)
{
    head->prev = head;
    head->next = head;
}

/**
 * Inserts an element in a list.
 *
 * \param node [out] Node pointer of the element to insert.
 * \param prev Node pointer of the previous element.
 * \param next Node pointer of the next element.
 */

static inline void vlc_list_add_between(struct vlc_list *restrict node,
                                        struct vlc_list *prev,
                                        struct vlc_list *next)
{
    node->prev = prev;
    node->next = next;
    prev->next = node;
    next->prev = node;
}

/**
 * Inserts an element after another.
 *
 * \param node [out] Node pointer of the element to insert
 * \param prev Node pointer of the previous element.
 */

static inline void vlc_list_add_after(struct vlc_list *restrict node,
                                      struct vlc_list *prev)
{
    vlc_list_add_between(node, prev, prev->next);
}

/**
 * Inserts an element before another.
 *
 * \param node [out] Node pointer of the element to insert.
 * \param next Node pointer of the next element.
 */

static inline void vlc_list_add_before(struct vlc_list *restrict node,
                                       struct vlc_list *next)
{
    vlc_list_add_between(node, next->prev, next);
}

/**
 * Appends an element into a list.
 *
 * \param node [out] Node pointer of the element to append to the list.
 * \param head Head pointer of the list to append the element to.
 */

static inline void vlc_list_append(struct vlc_list *restrict node,
                                   struct vlc_list *head)
{
    vlc_list_add_before(node, head);
}

/**
 * Prepends an element into a list.
 *
 * \param node [out] Node pointer of the element to prepend to the list.
 * \param head Head pointer of the list to prepend the element to.
 */

static inline void vlc_list_prepend(struct vlc_list *restrict node,
                                    struct vlc_list *head)
{
    vlc_list_add_after(node, head);
}

/**
 * Removes an element from a list.
 *
 * \param node Node of the element to remove from a list.
 * \warning The element must be inside a list.
 * Otherwise the behaviour is undefined.
 */

static inline void vlc_list_remove(struct vlc_list *restrict node)
{
    struct vlc_list *prev = node->prev;
    struct vlc_list *next = node->next;

    prev->next = next;
    next->prev = prev;
}

/**
 * Replaces an element with another one.
 *
 * \param original [in] Node pointer of the element to remove from the list.
 * \param substitute [out] Node pointer of the replacement.
 */

static inline void vlc_list_replace(const struct vlc_list *original,
                                    struct vlc_list *restrict substitute)
{
    vlc_list_add_between(substitute, original->prev, original->next);
}

/**
 * Checks if a list is empty.
 *
 * \param head [in] Head of the list to be checked.
 *
 * \retval false The list is not empty.
 * \retval true The list is empty.
 *
 * \note Obviously the list must have been initialized.
 * Otherwise, the behaviour is undefined.
 */

static inline bool vlc_list_is_empty(const struct vlc_list *head)
{
    return head->next == head;
}

/**
 * Checks if an element is first in a list.
 *
 * \param node [in] List node of the element.
 * \param head [in] Head of the list to be checked.
 *
 * \retval false The element is not first (or is in another list).
 * \retval true The element is first.
 */

static inline bool vlc_list_is_first(const struct vlc_list *node,
                                     const struct vlc_list *head)
{
    return node->prev == head;
}

/**
 * Checks if an element is last in a list.
 *
 * \param node [in] List node of the element.
 * \param head [in] Head of the list to be checked.
 *
 * \retval false The element is not last (or is in another list).
 * \retval true The element is last.
 */

static inline bool vlc_list_is_last(const struct vlc_list *node,
                                    const struct vlc_list *head)
{
    return node->next == head;
}

/**
 * List iterator.
 */

struct vlc_list_it
{
    const struct vlc_list *head;
    struct vlc_list *current;
    struct vlc_list *next;
};

static inline
struct vlc_list_it vlc_list_it_start(struct vlc_list *head)
{
    struct vlc_list *first = head->next;

    struct vlc_list_it it = { head, first, first->next };
    return it;
}

static inline
struct vlc_list_it vlc_list_it_start_const(const struct vlc_list *head)
{
    struct vlc_list *first = head->next;

    struct vlc_list_it it = { head, first, first->next };
    return it;
}

static inline
struct vlc_list_it vlc_list_it_reverse_start(struct vlc_list *head)
{
    struct vlc_list *first = head->prev;

    struct vlc_list_it it = { head, first, first->prev };
    return it;
}

static inline
struct vlc_list_it vlc_list_it_reverse_start_const(const struct vlc_list *head)
{
    struct vlc_list *first = head->prev;

    struct vlc_list_it it = { head, first, first->prev };
    return it;
}

static inline bool vlc_list_it_continue(const struct vlc_list_it *restrict it)
{
    return it->current != it->head;
}

static inline void vlc_list_it_next(struct vlc_list_it *restrict it)
{
    struct vlc_list *next = it->next;

    it->current = next;
    it->next = next->next;
}

static inline void vlc_list_it_prev(struct vlc_list_it *restrict it)
{
    struct vlc_list *next = it->next;

    it->current = next;
    it->next = next->prev;
}

/**
 * List iteration macro.
 *
 * This macro iterates over all elements (excluding the head) of a list,
 * in order from the first to the last.
 *
 * For each iteration, it sets the cursor variable to the current element.
 *
 * \param pos Cursor pointer variable identifier.
 * \param head [in] Head pointer of the list to iterate.
 * \param member Identifier of the member of the data type
 *               serving as list node.
 * \note It it safe to delete the current item while iterating.
 * It is however <b>not</b> safe to delete another item.
 */

#define vlc_list_foreach(pos, head, member) \
    for (struct vlc_list_it vlc_list_it__##pos = vlc_list_it_start(head); \
         vlc_list_it_continue(&(vlc_list_it__##pos)) \
          && ((pos) = container_of((vlc_list_it__##pos).current, \
                                   typeof (*(pos)), member), true); \
         vlc_list_it_next(&(vlc_list_it__##pos)))
#define vlc_list_foreach_const(pos, head, member) \
    for (struct vlc_list_it vlc_list_it__##pos = vlc_list_it_start_const(head); \
         vlc_list_it_continue(&(vlc_list_it__##pos)) \
          && ((pos) = container_of((vlc_list_it__##pos).current, \
                                   const typeof (*(pos)), member), true); \
         vlc_list_it_next(&(vlc_list_it__##pos)))

/**
 * List iteration macro.
 *
 * This macro iterates over all elements (excluding the head) of a list,
 * in reversed order from the first to the last.
 *
 * For each iteration, it sets the cursor variable to the current element.
 *
 * \param pos Cursor pointer variable identifier.
 * \param head [in] Head pointer of the list to iterate.
 * \param member Identifier of the member of the data type
 *               serving as list node.
 * \note It it safe to delete the current item while iterating.
 * It is however <b>not</b> safe to delete another item.
 */

#define vlc_list_reverse_foreach(pos, head, member) \
    for (struct vlc_list_it vlc_list_it_##pos = vlc_list_it_reverse_start(head); \
         vlc_list_it_continue(&(vlc_list_it_##pos)) \
          && ((pos) = container_of((vlc_list_it_##pos).current, \
                                   typeof (*(pos)), member), true); \
         vlc_list_it_prev(&(vlc_list_it_##pos)))

/**
 * Converts a list node pointer to an element pointer.
 *
 * \param ptr list node pointer
 * \param type list data element type name
 * \param member list node member within the data element compound type
 */

#define vlc_list_entry(ptr, type, member) container_of(ptr, type, member)

static inline void *vlc_list_first_or_null(const struct vlc_list *head,
                                           size_t offset)
{
    if (vlc_list_is_empty(head))
        return NULL;
    return ((char *)(head->next)) - offset;
}

static inline void *vlc_list_last_or_null(const struct vlc_list *head,
                                          size_t offset)
{
    if (vlc_list_is_empty(head))
        return NULL;
    return ((char *)(head->prev)) - offset;
}

static inline void *vlc_list_prev_or_null(const struct vlc_list *head,
                                          const struct vlc_list *node,
                                          size_t offset)
{
    if (vlc_list_is_first(node, head))
        return NULL;
    return ((char *)(node->prev)) - offset;
}

static inline void *vlc_list_next_or_null(const struct vlc_list *head,
                                          const struct vlc_list *node,
                                          size_t offset)
{
    if (vlc_list_is_last(node, head))
        return NULL;
    return ((char *)(node->next)) - offset;
}

/**
 * Gets the first element.
 *
 * \param head [in] Head of list whose last element to get.
 *
 * \return the first entry in a list or NULL if empty.
 */

#define vlc_list_first_entry_or_null(head, type, member) \
        ((type *)vlc_list_first_or_null(head, offsetof (type, member)))

/**
 * Gets the last element.
 *
 * \param head [in] Head of list whose last element to get.
 *
 * \return the last entry in a list or NULL if empty.
 */

#define vlc_list_last_entry_or_null(head, type, member) \
        ((type *)vlc_list_last_or_null(head, offsetof (type, member)))

#define vlc_list_prev_entry_or_null(head, entry, type, member) \
        ((type *)vlc_list_prev_or_null(head, &(entry)->member, \
                                       offsetof (type, member)))
#define vlc_list_next_entry_or_null(head, entry, type, member) \
        ((type *)vlc_list_next_or_null(head, &(entry)->member, \
                                       offsetof (type, member)))

/** \todo Merging lists, splitting lists. */

/** @} */

#endif /* VLC_LIST_H */

Messung
CHZG
849710093

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104838
#Domains=499075