mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 05:52:27 +01:00
108b211ee2
These are caused by fact that functions are declared with __attribute__((nonnull)) or left shit like ~0 << macro when ~0U << macro should be used.
408 lines
12 KiB
C++
408 lines
12 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License as published by the Free Software
|
|
Foundation; version 2 of the License.
|
|
|
|
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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along with
|
|
this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/******************************************************************//**
|
|
@file include/ut0lst.h
|
|
List utilities
|
|
|
|
Created 9/10/1995 Heikki Tuuri
|
|
***********************************************************************/
|
|
|
|
#ifndef ut0lst_h
|
|
#define ut0lst_h
|
|
|
|
#include "univ.i"
|
|
|
|
/*******************************************************************//**
|
|
Return offset of F in POD T.
|
|
@param T - POD pointer
|
|
@param F - Field in T */
|
|
#define IB_OFFSETOF(T, F) \
|
|
(reinterpret_cast<byte*>(&(T)->F) - reinterpret_cast<byte*>(T))
|
|
|
|
/* This module implements the two-way linear list which should be used
|
|
if a list is used in the database. Note that a single struct may belong
|
|
to two or more lists, provided that the list are given different names.
|
|
An example of the usage of the lists can be found in fil0fil.cc. */
|
|
|
|
/*******************************************************************//**
|
|
This macro expands to the unnamed type definition of a struct which acts
|
|
as the two-way list base node. The base node contains pointers
|
|
to both ends of the list and a count of nodes in the list (excluding
|
|
the base node from the count).
|
|
@param TYPE the name of the list node data type */
|
|
template <typename TYPE>
|
|
struct ut_list_base {
|
|
typedef TYPE elem_type;
|
|
|
|
ulint count; /*!< count of nodes in list */
|
|
TYPE* start; /*!< pointer to list start, NULL if empty */
|
|
TYPE* end; /*!< pointer to list end, NULL if empty */
|
|
};
|
|
|
|
#define UT_LIST_BASE_NODE_T(TYPE) ut_list_base<TYPE>
|
|
|
|
/*******************************************************************//**
|
|
This macro expands to the unnamed type definition of a struct which
|
|
should be embedded in the nodes of the list, the node type must be a struct.
|
|
This struct contains the pointers to next and previous nodes in the list.
|
|
The name of the field in the node struct should be the name given
|
|
to the list.
|
|
@param TYPE the list node type name */
|
|
/* Example:
|
|
struct LRU_node_t {
|
|
UT_LIST_NODE_T(LRU_node_t) LRU_list;
|
|
...
|
|
}
|
|
The example implements an LRU list of name LRU_list. Its nodes are of type
|
|
LRU_node_t. */
|
|
|
|
template <typename TYPE>
|
|
struct ut_list_node {
|
|
TYPE* prev; /*!< pointer to the previous node,
|
|
NULL if start of list */
|
|
TYPE* next; /*!< pointer to next node, NULL if end of list */
|
|
};
|
|
|
|
#define UT_LIST_NODE_T(TYPE) ut_list_node<TYPE>
|
|
|
|
/*******************************************************************//**
|
|
Get the list node at offset.
|
|
@param elem - list element
|
|
@param offset - offset within element.
|
|
@return reference to list node. */
|
|
template <typename Type>
|
|
ut_list_node<Type>&
|
|
ut_elem_get_node(Type& elem, size_t offset)
|
|
{
|
|
ut_a(offset < sizeof(elem));
|
|
|
|
return(*reinterpret_cast<ut_list_node<Type>*>(
|
|
reinterpret_cast<byte*>(&elem) + offset));
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Initializes the base node of a two-way list.
|
|
@param BASE the list base node
|
|
*/
|
|
#define UT_LIST_INIT(BASE)\
|
|
{\
|
|
(BASE).count = 0;\
|
|
(BASE).start = NULL;\
|
|
(BASE).end = NULL;\
|
|
}\
|
|
|
|
/*******************************************************************//**
|
|
Adds the node as the first element in a two-way linked list.
|
|
@param list the base node (not a pointer to it)
|
|
@param elem the element to add
|
|
@param offset offset of list node in elem. */
|
|
template <typename List, typename Type>
|
|
void
|
|
ut_list_prepend(
|
|
List& list,
|
|
Type& elem,
|
|
size_t offset)
|
|
{
|
|
ut_list_node<Type>& elem_node = ut_elem_get_node(elem, offset);
|
|
|
|
elem_node.prev = 0;
|
|
elem_node.next = list.start;
|
|
|
|
if (list.start != 0) {
|
|
ut_list_node<Type>& base_node =
|
|
ut_elem_get_node(*list.start, offset);
|
|
|
|
ut_ad(list.start != &elem);
|
|
|
|
base_node.prev = &elem;
|
|
}
|
|
|
|
list.start = &elem;
|
|
|
|
if (list.end == 0) {
|
|
list.end = &elem;
|
|
}
|
|
|
|
++list.count;
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Adds the node as the first element in a two-way linked list.
|
|
@param NAME list name
|
|
@param LIST the base node (not a pointer to it)
|
|
@param ELEM the element to add */
|
|
#define UT_LIST_ADD_FIRST(NAME, LIST, ELEM) \
|
|
ut_list_prepend(LIST, *ELEM, IB_OFFSETOF(ELEM, NAME))
|
|
|
|
/*******************************************************************//**
|
|
Adds the node as the last element in a two-way linked list.
|
|
@param list list
|
|
@param elem the element to add
|
|
@param offset offset of list node in elem */
|
|
template <typename List, typename Type>
|
|
void
|
|
ut_list_append(
|
|
List& list,
|
|
Type& elem,
|
|
size_t offset)
|
|
{
|
|
ut_list_node<Type>& elem_node = ut_elem_get_node(elem, offset);
|
|
|
|
elem_node.next = 0;
|
|
elem_node.prev = list.end;
|
|
|
|
if (list.end != 0) {
|
|
ut_list_node<Type>& base_node =
|
|
ut_elem_get_node(*list.end, offset);
|
|
|
|
ut_ad(list.end != &elem);
|
|
|
|
base_node.next = &elem;
|
|
}
|
|
|
|
list.end = &elem;
|
|
|
|
if (list.start == 0) {
|
|
list.start = &elem;
|
|
}
|
|
|
|
++list.count;
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Adds the node as the last element in a two-way linked list.
|
|
@param NAME list name
|
|
@param LIST list
|
|
@param ELEM the element to add */
|
|
#define UT_LIST_ADD_LAST(NAME, LIST, ELEM)\
|
|
ut_list_append(LIST, *ELEM, IB_OFFSETOF(ELEM, NAME))
|
|
|
|
/*******************************************************************//**
|
|
Inserts a ELEM2 after ELEM1 in a list.
|
|
@param list the base node
|
|
@param elem1 node after which ELEM2 is inserted
|
|
@param elem2 node being inserted after NODE1
|
|
@param offset offset of list node in elem1 and elem2 */
|
|
template <typename List, typename Type>
|
|
void
|
|
ut_list_insert(
|
|
List& list,
|
|
Type& elem1,
|
|
Type& elem2,
|
|
size_t offset)
|
|
{
|
|
ut_ad(&elem1 != &elem2);
|
|
|
|
ut_list_node<Type>& elem1_node = ut_elem_get_node(elem1, offset);
|
|
ut_list_node<Type>& elem2_node = ut_elem_get_node(elem2, offset);
|
|
|
|
elem2_node.prev = &elem1;
|
|
elem2_node.next = elem1_node.next;
|
|
|
|
if (elem1_node.next != NULL) {
|
|
ut_list_node<Type>& next_node =
|
|
ut_elem_get_node(*elem1_node.next, offset);
|
|
|
|
next_node.prev = &elem2;
|
|
}
|
|
|
|
elem1_node.next = &elem2;
|
|
|
|
if (list.end == &elem1) {
|
|
list.end = &elem2;
|
|
}
|
|
|
|
++list.count;
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Inserts a ELEM2 after ELEM1 in a list.
|
|
@param NAME list name
|
|
@param LIST the base node
|
|
@param ELEM1 node after which ELEM2 is inserted
|
|
@param ELEM2 node being inserted after ELEM1 */
|
|
#define UT_LIST_INSERT_AFTER(NAME, LIST, ELEM1, ELEM2)\
|
|
ut_list_insert(LIST, *ELEM1, *ELEM2, IB_OFFSETOF(ELEM1, NAME))
|
|
|
|
#ifdef UNIV_LIST_DEBUG
|
|
/** Invalidate the pointers in a list node.
|
|
@param NAME list name
|
|
@param N pointer to the node that was removed */
|
|
# define UT_LIST_REMOVE_CLEAR(N) \
|
|
(N).next = (Type*) -1; \
|
|
(N).prev = (N).next
|
|
#else
|
|
/** Invalidate the pointers in a list node.
|
|
@param NAME list name
|
|
@param N pointer to the node that was removed */
|
|
# define UT_LIST_REMOVE_CLEAR(N)
|
|
#endif /* UNIV_LIST_DEBUG */
|
|
|
|
/*******************************************************************//**
|
|
Removes a node from a two-way linked list.
|
|
@param list the base node (not a pointer to it)
|
|
@param elem node to be removed from the list
|
|
@param offset offset of list node within elem */
|
|
template <typename List, typename Type>
|
|
void
|
|
ut_list_remove(
|
|
List& list,
|
|
Type& elem,
|
|
size_t offset)
|
|
{
|
|
ut_list_node<Type>& elem_node = ut_elem_get_node(elem, offset);
|
|
|
|
ut_a(list.count > 0);
|
|
|
|
if (elem_node.next != NULL) {
|
|
ut_list_node<Type>& next_node =
|
|
ut_elem_get_node(*elem_node.next, offset);
|
|
|
|
next_node.prev = elem_node.prev;
|
|
} else {
|
|
list.end = elem_node.prev;
|
|
}
|
|
|
|
if (elem_node.prev != NULL) {
|
|
ut_list_node<Type>& prev_node =
|
|
ut_elem_get_node(*elem_node.prev, offset);
|
|
|
|
prev_node.next = elem_node.next;
|
|
} else {
|
|
list.start = elem_node.next;
|
|
}
|
|
|
|
UT_LIST_REMOVE_CLEAR(elem_node);
|
|
|
|
--list.count;
|
|
}
|
|
|
|
/*******************************************************************//**
|
|
Removes a node from a two-way linked list.
|
|
aram NAME list name
|
|
@param LIST the base node (not a pointer to it)
|
|
@param ELEM node to be removed from the list */
|
|
#define UT_LIST_REMOVE(NAME, LIST, ELEM) \
|
|
ut_list_remove(LIST, *ELEM, IB_OFFSETOF(ELEM, NAME))
|
|
|
|
/********************************************************************//**
|
|
Gets the next node in a two-way list.
|
|
@param NAME list name
|
|
@param N pointer to a node
|
|
@return the successor of N in NAME, or NULL */
|
|
#define UT_LIST_GET_NEXT(NAME, N)\
|
|
(((N)->NAME).next)
|
|
|
|
/********************************************************************//**
|
|
Gets the previous node in a two-way list.
|
|
@param NAME list name
|
|
@param N pointer to a node
|
|
@return the predecessor of N in NAME, or NULL */
|
|
#define UT_LIST_GET_PREV(NAME, N)\
|
|
(((N)->NAME).prev)
|
|
|
|
/********************************************************************//**
|
|
Alternative macro to get the number of nodes in a two-way list, i.e.,
|
|
its length.
|
|
@param BASE the base node (not a pointer to it).
|
|
@return the number of nodes in the list */
|
|
#define UT_LIST_GET_LEN(BASE)\
|
|
(BASE).count
|
|
|
|
/********************************************************************//**
|
|
Gets the first node in a two-way list.
|
|
@param BASE the base node (not a pointer to it)
|
|
@return first node, or NULL if the list is empty */
|
|
#define UT_LIST_GET_FIRST(BASE)\
|
|
(BASE).start
|
|
|
|
/********************************************************************//**
|
|
Gets the last node in a two-way list.
|
|
@param BASE the base node (not a pointer to it)
|
|
@return last node, or NULL if the list is empty */
|
|
#define UT_LIST_GET_LAST(BASE)\
|
|
(BASE).end
|
|
|
|
struct NullValidate { void operator()(const void* elem) { } };
|
|
|
|
/********************************************************************//**
|
|
Iterate over all the elements and call the functor for each element.
|
|
@param list base node (not a pointer to it)
|
|
@param functor Functor that is called for each element in the list
|
|
@parm node pointer to member node within list element */
|
|
template <typename List, class Functor>
|
|
void
|
|
ut_list_map(
|
|
List& list,
|
|
ut_list_node<typename List::elem_type>
|
|
List::elem_type::*node,
|
|
Functor functor)
|
|
{
|
|
ulint count = 0;
|
|
|
|
for (typename List::elem_type* elem = list.start;
|
|
elem != 0;
|
|
elem = (elem->*node).next, ++count) {
|
|
|
|
functor(elem);
|
|
}
|
|
|
|
ut_a(count == list.count);
|
|
}
|
|
|
|
/********************************************************************//**
|
|
Checks the consistency of a two-way list.
|
|
@param list base node (not a pointer to it)
|
|
@param functor Functor that is called for each element in the list
|
|
@parm node pointer to member node within list element */
|
|
template <typename List, class Functor>
|
|
void
|
|
ut_list_validate(
|
|
List& list,
|
|
ut_list_node<typename List::elem_type>
|
|
List::elem_type::*node,
|
|
Functor functor = NullValidate())
|
|
{
|
|
ut_list_map(list, node, functor);
|
|
|
|
ulint count = 0;
|
|
|
|
for (typename List::elem_type* elem = list.end;
|
|
elem != 0;
|
|
elem = (elem->*node).prev, ++count) {
|
|
|
|
functor(elem);
|
|
}
|
|
|
|
ut_a(count == list.count);
|
|
}
|
|
|
|
/********************************************************************//**
|
|
Checks the consistency of a two-way list.
|
|
@param NAME the name of the list
|
|
@param TYPE node type
|
|
@param LIST base node (not a pointer to it)
|
|
@param FUNCTOR called for each list element */
|
|
#define UT_LIST_VALIDATE(NAME, TYPE, LIST, FUNCTOR) \
|
|
ut_list_validate(LIST, &TYPE::NAME, FUNCTOR)
|
|
|
|
#define UT_LIST_CHECK(NAME, TYPE, LIST) \
|
|
ut_list_validate(LIST, &TYPE::NAME, NullValidate())
|
|
|
|
#endif /* ut0lst.h */
|