/* * 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"); }