Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* Monkey HTTP Server
* ==================
* Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io>
* Copyright (C) 2010, Jonathan Gonzalez V. <zeus@gnu.org>
*
* 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.
*/
#ifndef MK_LIST_H_
#define MK_LIST_H_
#include <stddef.h>
#ifdef _WIN32
/* Windows */
#define container_of(address, type, field) ((type *)( \
(PCHAR)(address) - \
(ULONG_PTR)(&((type *)0)->field)))
#else
/* Rest of the world */
#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
#endif
struct mk_list
{
struct mk_list *prev, *next;
};
static inline void mk_list_init(struct mk_list *list)
{
list->next = list;
list->prev = list;
}
static inline void __mk_list_add(struct mk_list *_new, struct mk_list *prev,
struct mk_list *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
static inline void mk_list_add(struct mk_list *_new, struct mk_list *head)
{
__mk_list_add(_new, head->prev, head);
}
static inline void mk_list_add_after(struct mk_list *_new,
struct mk_list *prev,
struct mk_list *head)
{
struct mk_list *next;
if (head->prev == head->next || head->prev == prev) {
mk_list_add(_new, head);
return;
}
next = prev->next;
_new->next = next;
_new->prev = prev;
prev->next = _new;
next->prev = _new;
}
static inline void __mk_list_del(struct mk_list *prev, struct mk_list *next)
{
prev->next = next;
next->prev = prev;
}
static inline void mk_list_del(struct mk_list *entry)
{
__mk_list_del(entry->prev, entry->next);
entry->prev = NULL;
entry->next = NULL;
}
static inline int mk_list_is_empty(struct mk_list *head)
{
if (head->next == head) return 0;
else return -1;
}
static inline int mk_list_is_set(struct mk_list *head)
{
if (head->next && head->prev) {
return 0;
}
return -1;
}
static inline int mk_list_size(struct mk_list *head)
{
int ret = 0;
struct mk_list *it;
for (it = head->next; it != head; it = it->next, ret++);
return ret;
}
static inline int mk_list_entry_orphan(struct mk_list *head)
{
if (head->next && head->prev) {
return 0;
}
return -1;
}
static inline void mk_list_cat(struct mk_list *list, struct mk_list *head)
{
struct mk_list *last;
last = head->prev;
last->next = list->next;
list->next->prev = last;
list->prev->next = head;
head->prev = list->prev;
}
#define mk_list_foreach(curr, head) for( curr = (head)->next; curr != (head); curr = curr->next )
#define mk_list_foreach_safe(curr, n, head) \
for (curr = (head)->next, n = curr->next; curr != (head); curr = n, n = curr->next)
#define mk_list_foreach_r(curr, head) for( curr = (head)->prev; curr != (head); curr = curr->prev )
#define mk_list_foreach_safe_r(curr, n, head) \
for (curr = (head)->prev, n = curr->prev; curr != (head); curr = n, n = curr->prev)
#define mk_list_entry( ptr, type, member ) container_of( ptr, type, member )
/*
* First node of the list
* ----------------------
* Be careful with this Macro, its intended to be used when some node is already linked
* to the list (ptr). If the list is empty it will return the list address as it points
* to it self: list == list->prev == list->next.
*
* If exists some possiblity that your code handle an empty list, use mk_list_is_empty()
* previously to check if its empty or not.
*/
#define mk_list_entry_first(ptr, type, member) container_of((ptr)->next, type, member)
/* First node of the list
* ---------------------
* Be careful with this Macro, its intended to be used when some node is already linked
* to the list (ptr). If the list is empty it will return the list address as it points
* to it self: list == list->prev == list->next.
*
* If exists some possiblity that your code handle an empty list, use mk_list_is_empty()
* previously to check if its empty or not.
*/
#define mk_list_entry_last(ptr, type, member) container_of((ptr)->prev, type, member)
/* Next node */
#define mk_list_entry_next(ptr, type, member, head) \
(ptr)->next == (head) ? container_of((head)->next, type, member) : \
container_of((ptr)->next, type, member);
#endif /* !MK_LIST_H_ */