You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
308 lines
15 KiB
308 lines
15 KiB
/**
|
|
* \file scot/list_mod.h
|
|
* \author Georg Steffers <georg@steffers.org>
|
|
* \brief Templates of functions to modify typesafe lists.
|
|
*
|
|
* Here are macro definitions that create functions to modify typesafe
|
|
* lists. That is read, write, insert, delete a.s.f.
|
|
*
|
|
* Normally the macros defined here will be never called directly but only
|
|
* via MACROS that group them in a sensefull way in scot/list_impl.h.\n
|
|
* \anchor onlyfunc_mod
|
|
* \attention
|
|
* All documentation here does document the functions that are created by
|
|
* the macros, as the macros themself are pretty easy and all used the same.
|
|
* They are called with a type, that MUST be one word (use typedef if needed)
|
|
* and generates the function defined with their value.
|
|
*
|
|
* Copyright (C)2006 Georg Steffers <georg@steffers.org>
|
|
*
|
|
* 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; either version 2 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
#ifndef LIST_MOD_H
|
|
#define LIST_MOD_H
|
|
|
|
#include <stdlib.h>
|
|
#include <scot/list_impl.h>
|
|
#include <scot/memory.h> /* because we use functions from there */
|
|
|
|
|
|
/**
|
|
* \internal
|
|
* \param node a list_[type]_node_t* that should be checked for
|
|
* beeing an anchor.
|
|
* \param line the line where this MACRO is called.
|
|
* \pre a variable of type list_<type>_node_t* must exist.
|
|
* \return the code fragment
|
|
* \post None
|
|
*
|
|
* \brief check for anchor.
|
|
*
|
|
* This checks if the given \a node is an anchor. If not it calls
|
|
* LIST_ERROR, which either raises an exception if exceptions are user
|
|
* or otherwise prints out an error message to stderr and aborts the
|
|
* program.
|
|
*/
|
|
#define MOD_NODE_NO_ANCHOR_ERROR(node, line) \
|
|
if ((node->e) != NULL) \
|
|
LIST_ERROR ("list_mod.h", (line), NODE_NO_ANCHOR_ERR);
|
|
|
|
|
|
/**
|
|
* \attention
|
|
* Only the generated function is explained here, for the reason look
|
|
* \ref onlyfunc_mod "here".
|
|
*
|
|
* \param node A pointer to a node in the list.
|
|
* \pre The \a node must be part of a correctly
|
|
* initialized list.
|
|
* \return The element saved in the node.
|
|
* \post None
|
|
*
|
|
* \brief Retrive element from node.
|
|
*
|
|
* This function retrieves the element from a node of a list.
|
|
*/
|
|
#define GEN_LIST_RETRIVE(type) \
|
|
STATIC \
|
|
type * \
|
|
list_ ## type ## _retrive (list_ ## type ## _node_t *node) \
|
|
{ \
|
|
LIST_EXC_START \
|
|
LIST_CHECK_NULL (node, "list_mod.h", 18); \
|
|
LIST_EXC_END ("list_mod.h", 19, LIST_RETR_ERR); \
|
|
\
|
|
return (type *) node->e; \
|
|
}
|
|
|
|
/**
|
|
* \attention
|
|
* Only the generated function is explained here, for the reason look
|
|
* \ref onlyfunc_mod "here".
|
|
*
|
|
* \param node A pointer to a node in the list.
|
|
* \param e A pointer to a variable of the \a type, the
|
|
* list was created for.
|
|
* \pre The \a node must be part of a correctly
|
|
* initialized list. \a e must not be NULL.
|
|
* \return Nothing
|
|
* \post The element of \a node is \a e.
|
|
*
|
|
* \brief Set element od node.
|
|
*
|
|
* This function sets the element from a node of a list.
|
|
*/
|
|
#define GEN_LIST_SET(type) \
|
|
STATIC \
|
|
void \
|
|
list_ ## type ## _set ( \
|
|
list_ ## type ## _node_t *node, \
|
|
const type *e) \
|
|
{ \
|
|
LIST_EXC_START \
|
|
{ \
|
|
LIST_CHECK_NULL (node, "list_mod.h", 33); \
|
|
LIST_CHECK_NULL (e, "list_mod.h", 34); \
|
|
} \
|
|
LIST_EXC_END ("list_mod.h", 36, LIST_SET_ERR); \
|
|
\
|
|
node->e = e; \
|
|
}
|
|
|
|
/**
|
|
* \attention
|
|
* Only the generated function is explained here, for the reason look
|
|
* \ref onlyfunc_mod "here".
|
|
*
|
|
* \param node A pointer to a node in the list.
|
|
* \param e A pointer to a variable of the \a type, the
|
|
* list was created for.
|
|
* \pre The \a node must be part of a correctly
|
|
* initialized list.
|
|
* \a e must not be NULL.
|
|
* \return The node of the inserted element.
|
|
* \post List has one new node containing \a e.
|
|
*
|
|
* \brief Inserts a new node with element \a e into the list.
|
|
*
|
|
* This function creates a new list node and initializes it with
|
|
* \a e. Then this new node will be inserted behind \a node.
|
|
*/
|
|
#define GEN_LIST_INSERT(type) \
|
|
STATIC \
|
|
list_ ## type ## _node_t * \
|
|
list_ ## type ## _insert ( \
|
|
list_ ## type ## _node_t *node, \
|
|
const type *e) \
|
|
{ \
|
|
list_ ## type ## _node_t *ret; \
|
|
\
|
|
LIST_EXC_START \
|
|
{ \
|
|
list_ ## type ## _node_t *new_node; \
|
|
\
|
|
LIST_CHECK_NULL (node, "list_mod.h", 54); \
|
|
LIST_CHECK_NULL (e, "list_mod.h", 55); \
|
|
\
|
|
new_node = (list_ ## type ## _node_t *) \
|
|
LIST_MALLOC (sizeof (list_ ## type ## _node_t), \
|
|
"list_mod.h", 58); \
|
|
\
|
|
new_node->e = e; \
|
|
new_node->prev = node; \
|
|
new_node->next = node->next; \
|
|
node->next->prev = new_node; \
|
|
node->next = new_node; \
|
|
\
|
|
ret = new_node; \
|
|
} \
|
|
LIST_EXC_END ("list_mod.h", 69, LIST_INSERT_ERR); \
|
|
\
|
|
return ret; \
|
|
}
|
|
|
|
/**
|
|
* \attention
|
|
* Only the generated function is explained here, for the reason look
|
|
* \ref onlyfunc_mod "here".
|
|
*
|
|
* \param node A pointer to a node in the list.
|
|
* \pre The \a node must be part of a correctly
|
|
* initialized list.
|
|
* \return The next node behind the deleted one.
|
|
* \post The \a node is removed from the list and
|
|
* freed.
|
|
*
|
|
* \brief Deletes a new node with element \a e into the list.
|
|
*
|
|
* This function deletes a node from the list it is in. The node
|
|
* will be freed but by default NOT the element. Anyway, one can set
|
|
* a free function for elements of the list. This should free any
|
|
* resource the element has reserved.
|
|
* This function can be set with
|
|
* \link list_man.h::GEN_LIST_SET_ELEM_FREE
|
|
* list_[type]_set_elem_free ()\endlink
|
|
* and if set, is called by list_[type]_delete(). If such a function
|
|
* was set and one wants to reset to default behaviour (not to delete any
|
|
* element) one can pass NULL to \link list_man.h::GEN_LIST_SET_ELEM_FREE
|
|
* list_[type]_set_elem_free ()\endlink.
|
|
*/
|
|
#define GEN_LIST_DELETE(type) \
|
|
STATIC \
|
|
list_ ## type ## _node_t * \
|
|
list_ ## type ## _delete (list_ ## type ## _node_t *node) \
|
|
{ \
|
|
type *e; \
|
|
list_ ## type ## _node_t *prev, \
|
|
*next; \
|
|
\
|
|
LIST_EXC_START \
|
|
{ \
|
|
if (list_ ## type ## _isempty (node)) \
|
|
LIST_WARNING ("list_mod.h", 86, DEL_ON_EMPTY_LIST_WRN); \
|
|
\
|
|
e = (type *) node->e; \
|
|
\
|
|
prev = node->prev; \
|
|
next = node->next; \
|
|
prev->next = next; \
|
|
next->prev = prev; \
|
|
\
|
|
if (list_ ## type ## _elem_free != NULL && e != NULL) \
|
|
list_ ## type ## _elem_free (e); \
|
|
\
|
|
SCOT_MEM_FREE (node); \
|
|
} \
|
|
LIST_EXC_END ("list_mod.h", 101, LIST_DELETE_ERR); \
|
|
\
|
|
return next; \
|
|
}
|
|
|
|
/**
|
|
* \attention
|
|
* Only the generated function is explained here, for the reason look
|
|
* \ref onlyfunc_mod "here".
|
|
*
|
|
* \param anchor1 A pointer to the first list anchor.
|
|
* \param anchor2 A pointer to the second list anchor.
|
|
* \pre Both, \a anchor1 and \a anchor2 must be
|
|
* valid list_anchors.
|
|
* \return The anchor of the new concatenated list.
|
|
* \post A new list was created that contains both
|
|
* given lists. The anchor of at least one of the
|
|
* given lists is no longer valid and should no
|
|
* longer be used. In fact only the returned
|
|
* anchor is garantied to point to a valid list.
|
|
*
|
|
* \brief Concatenates two lists.
|
|
*
|
|
* This function joins the given two list to one. This will be done
|
|
* partly destructive...that is, at least one of the old anchors
|
|
* will be deleted.
|
|
*/
|
|
#define GEN_LIST_CONCAT(type) \
|
|
STATIC \
|
|
list_ ## type ## _node_t * \
|
|
list_ ## type ## _concat ( \
|
|
list_ ## type ## _node_t *anchor1, \
|
|
list_ ## type ## _node_t *anchor2) \
|
|
{ \
|
|
LIST_EXC_START \
|
|
{ \
|
|
LIST_CHECK_NULL (anchor1, "list_mod.h", 115); \
|
|
MOD_NODE_NO_ANCHOR_ERROR (anchor1, 116); \
|
|
LIST_CHECK_NULL (anchor2, "list_mod.h", 117); \
|
|
MOD_NODE_NO_ANCHOR_ERROR (anchor2, 118); \
|
|
} \
|
|
LIST_EXC_END ("list_mod.h", 120, LIST_CONCAT_ERR); \
|
|
\
|
|
if (list_ ## type ## _isempty (anchor1)) \
|
|
return anchor2; \
|
|
\
|
|
if (list_ ## type ## _isempty (anchor2)) \
|
|
return anchor1; \
|
|
\
|
|
anchor2->next->prev = anchor1->prev; \
|
|
anchor2->prev->next = anchor1; \
|
|
anchor1->prev->next = anchor2->next; \
|
|
anchor1->prev = anchor2->prev; \
|
|
}
|
|
|
|
|
|
/**
|
|
* \param type the datatype that this list code should handle.
|
|
* \pre Type must be a single word typename. If one wants
|
|
* to use e.g. lists of structs one has to use typedef
|
|
* to create a single word type name like this:
|
|
* typedef struct mystruct_t mystruct_t;
|
|
* \return Nothing
|
|
* \post The functions for the given datatype that are described
|
|
* here are generated within the calling build file.
|
|
*
|
|
* \brief create functions neccesary to modify lists of the given \a type.
|
|
*
|
|
* Normally this is not called directly, but by GEN_LIST_IMPL() because this
|
|
* defines just a subset of all functions neccesarry to handle typesafe lists.
|
|
*/
|
|
#define GEN_LIST_MODIFY(type) \
|
|
GEN_LIST_RETRIVE (type); \
|
|
GEN_LIST_SET (type); \
|
|
GEN_LIST_INSERT (type); \
|
|
GEN_LIST_DELETE (type); \
|
|
GEN_LIST_CONCAT (type);
|
|
|
|
|
|
|
|
#endif /* LIST_MOD_H */
|