Skip to content

File es_list.h

File List > cubrid > src > storage > es_list.h

Go to the documentation of this file

/*
 * Copyright 2008 Search Solution Corporation
 * Copyright 2016 CUBRID Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */

/*
 * es_list.h -
 *
 * Simple doubly linked list implementation.
 *
 * Some of the internal functions ("__xxx") are useful when
 * manipulating whole lists rather than single entries, as
 * sometimes we already know the next/prev entries and we can
 * generate better code by using them directly rather than
 * using the generic single-entry routines.
 */

#ifndef _ES_LIST_H_
#define _ES_LIST_H_

#ifdef  __cplusplus
extern "C"
{
#endif

  struct es_list_head
  {
    struct es_list_head *next, *prev;
  };
  typedef struct es_list_head es_list_head_t;

#define ES_LIST_HEAD_INIT(name) { &(name), &(name) }

#define ES_LIST_HEAD(name) \
    struct es_list_head name = ES_LIST_HEAD_INIT(name)

#define ES_INIT_LIST_HEAD(ptr) do { \
    (ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)

#define ES_LIST_FIRST(name) (name)->next
#define ES_LIST_LAST(name)  (name)->prev

/*
 * Insert a new entry between two known consecutive entries.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
  static inline void __list_add (struct es_list_head *new_item, struct es_list_head *prev, struct es_list_head *next)
  {
    next->prev = new_item;
    new_item->next = next;
    new_item->prev = prev;
    prev->next = new_item;
  }

  static inline void es_list_add (struct es_list_head *new_item, struct es_list_head *head)
  {
    __list_add (new_item, head, head->next);
  }

  static inline void es_list_add_tail (struct es_list_head *new_item, struct es_list_head *head)
  {
    __list_add (new_item, head->prev, head);
  }

/*
 * Delete a list entry by making the prev/next entries
 * point to each other.
 *
 * This is only for internal list manipulation where we know
 * the prev/next entries already!
 */
  static inline void __list_del (struct es_list_head *prev, struct es_list_head *next)
  {
    next->prev = prev;
    prev->next = next;
  }

  static inline void es_list_del (struct es_list_head *entry)
  {
    __list_del (entry->prev, entry->next);
    entry->next = entry->prev = 0;
  }

  static inline void es_list_del_init (struct es_list_head *entry)
  {
    __list_del (entry->prev, entry->next);
    ES_INIT_LIST_HEAD (entry);
  }

  static inline int es_list_empty (struct es_list_head *head)
  {
    return head->next == head;
  }

  static inline void es_list_splice (struct es_list_head *list, struct es_list_head *head)
  {
    struct es_list_head *first = list->next;

    if (first != list)
      {
    struct es_list_head *last = list->prev;
    struct es_list_head *at = head->next;

    first->prev = head;
    head->next = first;

    last->next = at;
    at->prev = last;
      }
  }

#define ES_LIST_ENTRY(ptr, type, member) \
    ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))

#define ES_LIST_FOR_EACH(pos, head) \
    for (pos = (head)->next; pos != (head); pos = pos->next)

#define ES_LIST_FOR_REVERSE_EACH(pos, head) \
    for (pos = (head)->prev; pos != (head); pos = pos->prev)

#define ES_LIST_FOR_EACH_SAFE(pos, n, head) \
    for (pos = (head)->next, n = pos->next; pos != (head); \
        pos = n, n = pos->next)

#ifdef  __cplusplus
}
#endif

#endif /* _ES_LIST_H_ */