/*
* 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "chain.h"
struct chain *new_chain(const void *value, chain_memory_manager _2be3) {
/* -----------------------------------------------------------------------------
* Create a new chain
*
* @param const void *
* @param chain_memory_manager
* @return struct chain *
* -------------------------------------------------------------------------- */
struct chain *new_pts;
new_pts = (struct chain *)malloc(sizeof(struct chain));
if (new_pts == NULL) {
logmsg(LOG_ERR, "new_chain() : malloc error");
return NULL;
}
new_pts->value = (void *)value;
new_pts->_2be3 = _2be3;
new_pts->previous = NULL;
new_pts->next = NULL;
return new_pts;
}
struct chain *new_chains_struct(struct chain * first, ...) {
/* -----------------------------------------------------------------------------
* Create new root chain from several chains
*
* @param struct chain *
* @return struct chain *
* -------------------------------------------------------------------------- */
va_list args;
struct chain *pts;
struct chain *result = first;
va_start(args, first);
while ((pts = va_arg(args, struct chain *)) != NULL) {
append_chain(pts, result);
}
va_end(args);
return result;
}
struct chain *new_chains(const void * first_value, ...) {
/* -----------------------------------------------------------------------------
* Create new root chain from several values
* if values are allocated dynamically, this is the caller who must manage
* their destruction
*
* @param const void *
* @return struct chain *
* -------------------------------------------------------------------------- */
va_list args;
struct chain *pts;
struct chain *result = new_chain(first_value, NO_FREE);
va_start(args, first_value);
while ((pts = va_arg(args, void *)) != NULL) {
append_chain(new_chain(pts, NO_FREE), result);
}
va_end(args);
return result;
}
void drop_all_chain(struct chain *root_chain) {
/* -----------------------------------------------------------------------------
* Drop entirely a chain
*
* @param struct chain *
* -------------------------------------------------------------------------- */
struct chain *pts;
struct chain *pts_tmp;
if (root_chain == NULL) return;
pts = root_chain;
while(pts != NULL) {
if (pts->_2be3 == FREE)
free(pts->value);
pts_tmp = pts->next;
free(pts);
pts = pts_tmp;
}
}
struct chain * add_chain(struct chain *new_chain,
struct chain *chain_dest,
unsigned int position) {
/* -----------------------------------------------------------------------------
* Add a new chain at the given position
* if the given position is greater thant the size,
* the new chain will be add to the end
*
* @param struct chain, the new chain
* @param struct chain, the chain where to add
* @param int
* @return struct chain *, the new root chain
* A <-> B <-> C <-> D .... insert T, position 1
* A <-> T <-> B <-> C <-> D
* -------------------------------------------------------------------------- */
struct chain *pts, *pts_last;
pts = get_chain(chain_dest, position);
pts_last = get_last_chain(new_chain);
new_chain->previous = pts->previous;
pts->previous = pts_last;
pts_last->next = pts;
if (new_chain->previous != NULL)
new_chain->previous->next = new_chain;
return (position == 0) ? new_chain : chain_dest;
}
struct chain * delete_chain(struct chain *chain_root, unsigned int position) {
/* -----------------------------------------------------------------------------
* Delete chain at the given position
* if the given position is greater thant the size,
* the last chain will be deleted
*
* @param struct chain, the chain where to delete
* @param int
* @return struct chain *, the new root chain
* A <-> B <-> C <-> D .... delete at position 1
* A <-> C <-> D
* -------------------------------------------------------------------------- */
struct chain *pts, *new_root;
pts = get_chain(chain_root, position);
if (pts == NULL) return chain_root;
if (pts->previous != NULL)
pts->previous->next = pts->next;
if (pts->next != NULL)
pts->next->previous = pts->previous;
if (pts == chain_root) {
if (pts->next != NULL)
new_root = pts->next;
else
new_root = NULL;
}
else
new_root = chain_root;
if (pts->_2be3 == FREE)
free(pts->value);
free(pts);
return new_root;
}
struct chain *get_chain(struct chain *chain_root, unsigned int position) {
/* -----------------------------------------------------------------------------
* Get chain at the given position
* if the given position is greater thant the size,
* the last chain will be got
*
* @param struct chain, the chain where to search
* @param int
* @return struct chain * or NULL
* -------------------------------------------------------------------------- */
struct chain *pts;
unsigned int count = 0;
for (pts = chain_root; pts != NULL && count < position; count++, pts = pts->next);
return pts;
}
struct chain * find_chain(struct chain * chain_root, const void *value) {
/* -----------------------------------------------------------------------------
* Get chain by value
*
* @param struct chain, the chain where to search
* @param const void *
* @return struct chain * or NULL
* -------------------------------------------------------------------------- */
struct chain *pts;
for (pts = chain_root; pts != NULL && pts->value != value; pts = pts->next);
return pts;
}
int get_chain_position(struct chain * chain_root, const void *value) {
/* -----------------------------------------------------------------------------
* Get chain position by value
*
* @param struct chain, the chain where to search
* @param const void *
* @return int or -1 if not found
* -------------------------------------------------------------------------- */
struct chain *pts;
int i = 0;
for (pts = chain_root; pts != NULL && pts->value != value; pts = pts->next, i++);
if (pts != NULL)
return -1;
return i;
}
struct chain *get_last_chain(struct chain *chain_root) {
/* -----------------------------------------------------------------------------
* Get last chain
*
* @param struct chain, the chain where to search
* @return struct chain * or NULL
* -------------------------------------------------------------------------- */
struct chain *pts;
for (pts = chain_root; pts->next != NULL; pts = pts->next);
return pts;
}
unsigned int get_nb_chain(struct chain *chain_root) {
/* -----------------------------------------------------------------------------
* Get chain number
*
* @param struct chain, the chain where to search
* @return unsigned int
* -------------------------------------------------------------------------- */
struct chain *pts;
unsigned int count = 0;
for (pts = chain_root; pts != NULL; count++, pts = pts->next);
return count;
}
struct chain *copy_chain(struct chain *chain_root) {
/* -----------------------------------------------------------------------------
* Copy chain
*
* @param struct chain, the chain where to copy
* @return struct chain *, the copy
* -------------------------------------------------------------------------- */
struct chain *chain_copy;
struct chain *pts;
if (chain_root == NULL) return NULL;
pts = chain_root;
chain_copy = new_chain(pts->value, pts->_2be3);
pts = pts->next;
while(pts != NULL) {
append_chain(new_chain(pts->value, pts->_2be3), chain_copy);
pts = pts->next;
}
return chain_copy;
}
void append_chain(struct chain *new_chain, struct chain *chain_dest) {
/* -----------------------------------------------------------------------------
* Insert chain at the end
*
* @param struct chain, the chain to add
* @param struct chain, the chain where to add
* A <-> B <-> C <-> D .... insert T at the end
* A <-> B <-> C <-> D <-> T
* -------------------------------------------------------------------------- */
struct chain *pts;
for (pts = chain_dest; pts->next != NULL; pts = pts->next);
new_chain->previous = pts;
pts->next = new_chain;
}
void print_chain(struct chain *chain_root) {
/* -----------------------------------------------------------------------------
* Print the chain to stdout
* Warning ! this only work for string
*
* @param struct chain, the root chain
* -------------------------------------------------------------------------- */
struct chain *pts;
for (pts = chain_root; pts != NULL; pts = pts->next) {
printf("%s -> ", (char *)pts->value);
}
printf("\n");
}
void print_reverse_chain(struct chain *chain_root_reverse) {
/* -----------------------------------------------------------------------------
* Print the chain to stdout from the end
* Warning ! this only work for string
*
* @param struct chain, the root chain
* -------------------------------------------------------------------------- */
struct chain *pts;
for (pts = chain_root_reverse; pts != NULL; pts = pts->previous) {
printf("%s -> ", (char *)pts->value);
}
printf("\n");
}
void print_all_chain(struct chain *chain_root) {
/* -----------------------------------------------------------------------------
* Print the chain to stdout from the beginning to the end and from the end
* to the beginning
* Warning ! this only work for string
*
* @param struct chain, the root chain
* -------------------------------------------------------------------------- */
struct chain *pts = NULL;
struct chain *last_pts = NULL;
for (pts = chain_root; pts != NULL; last_pts = pts, pts = pts->next) {
printf("%s -> ", (char *)pts->value);
}
printf("\n");
for (pts = last_pts; pts != NULL; pts = pts->previous) {
printf("%s -> ", (char *)pts->value);
}
printf("\n");
}
syntax highlighted by Code2HTML, v. 0.9.1