/* * 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_string.h" struct chain_string *new_chain_string(const char *value) { /* ----------------------------------------------------------------------------- * Create a new chain string * * @param const char * * @return struct chain_string * * -------------------------------------------------------------------------- */ struct chain_string *new_pts; new_pts = (struct chain_string *)malloc(sizeof(struct chain_string)); if (new_pts == NULL) { logmsg(LOG_ERR, "new_chain_string() : malloc error"); return NULL; } new_pts->value = strdup(value); if (new_pts->value == NULL) { logmsg(LOG_ERR, "new_chain_string() : strdup error"); new_pts->length = 0; } else new_pts->length = strlen(value); new_pts->previous = NULL; new_pts->next = NULL; return new_pts; } struct chain_string *new_chains_string(struct chain_string * first, ...) { /* ----------------------------------------------------------------------------- * Create new chain string with several string * * @param const char * * @return struct chain_string * * -------------------------------------------------------------------------- */ va_list args; struct chain_string *pts; struct chain_string *result = first; va_start(args, first); while ((pts = va_arg(args, struct chain_string *)) != NULL) { append_chain_string(pts, result); } va_end(args); return result; } void drop_all_chain_string(struct chain_string *root_chain_string) { /* ----------------------------------------------------------------------------- * Destroy a chain string from the specified root * * @param struct chain_string * * -------------------------------------------------------------------------- */ struct chain_string *pts; struct chain_string *pts_tmp; if (root_chain_string == NULL) return; pts = root_chain_string; while(pts != NULL) { free(pts->value); pts_tmp = pts->next; free(pts); pts = pts_tmp; } } struct chain_string * add_chain_string(struct chain_string *new_chain_string, struct chain_string *chain_string_dest, unsigned int position) { /* ----------------------------------------------------------------------------- * Insert a string in a chain string at the given position * if the given position is greater thant the chain_string size, * the new chain_string will be add to the end * * @param struct chain_string *, the chain string to insert * @param struct chain_string *, where to insert * @param int * @return struct chain_string *, the new root chain string * A <-> B <-> C <-> D .... insert T, position 1 * A <-> T <-> B <-> C <-> D * -------------------------------------------------------------------------- */ struct chain_string *pts, *pts_last; pts = get_chain_string(chain_string_dest, position); pts_last = get_last_chain_string(new_chain_string); new_chain_string->previous = pts->previous; pts->previous = pts_last; pts_last->next = pts; if (new_chain_string->previous != NULL) new_chain_string->previous->next = new_chain_string; return (position == 0) ? new_chain_string : chain_string_dest; } struct chain_string * delete_chain_string(struct chain_string *chain_string_root, unsigned int position) { /* ----------------------------------------------------------------------------- * Delete a chain string at the given position * if the given position is greater thant the chain_string size, * the last chain_string will be deleted * * @param struct chain_string *, the chain string where to delete * @param int * @return struct chain_string *, the new root chain string * A <-> B <-> C <-> D .... delete in position 1 * A <-> C <-> D * -------------------------------------------------------------------------- */ struct chain_string *pts, *new_root; pts = get_chain_string(chain_string_root, position); if (pts == NULL) return chain_string_root; if (pts->previous != NULL) pts->previous->next = pts->next; if (pts->next != NULL) pts->next->previous = pts->previous; if (pts == chain_string_root) { if (pts->next != NULL) new_root = pts->next; else new_root = NULL; } else new_root = chain_string_root; free(pts->value); free(pts); return new_root; } struct chain_string * delete_chain_string_by_value(struct chain_string *chain_string_root, const char *value) { /* ----------------------------------------------------------------------------- * Delete a chain string by value * The first chain string with the given value will be deleted * * @param struct chain_string *, the chain string where to delete * @param const char * * @return struct chain_string *, the new root chain string * A <-> B <-> C <-> D .... delete in position 1 * A <-> C <-> D * -------------------------------------------------------------------------- */ struct chain_string *pts, *new_root; pts = get_chain_string_by_value(chain_string_root, value); if (pts == NULL) return chain_string_root; if (pts->previous != NULL) pts->previous->next = pts->next; if (pts->next != NULL) pts->next->previous = pts->previous; if (pts == chain_string_root) { if (pts->next != NULL) new_root = pts->next; else new_root = NULL; } else new_root = chain_string_root; free(pts->value); free(pts); return new_root; } unsigned int replace_chain_string_value(struct chain_string *chain_string_root, const char *oldvalue, const char *newvalue) { /* ----------------------------------------------------------------------------- * Replace a value by another * * @param struct chain_string *, the chain string where to do the replace * @param const char *, the string to replace * @param const char *, the string replacment * @return int * -------------------------------------------------------------------------- */ struct chain_string *pts = NULL; pts = get_chain_string_by_value(chain_string_root, oldvalue); if (pts == NULL) return 0; free(pts->value); pts->value = strdup(newvalue); if (pts->value == NULL) return 0; return 1; } struct chain_string *get_chain_string(struct chain_string *chain_string_root, unsigned int position) { /* ----------------------------------------------------------------------------- * Get a chain string by position * if the given position is greater thant the chain_string size, * the last chain_string will be got * * @param struct chain_string *, the chain string where to search * @param int * @return struct chain_string * * -------------------------------------------------------------------------- */ struct chain_string *pts; unsigned int count = 0; for (pts = chain_string_root; pts != NULL && count < position; count++, pts = pts->next); return pts; } struct chain_string *get_chain_string_by_value(struct chain_string *chain_string_root, const char *value) { /* ----------------------------------------------------------------------------- * Get a chain string by value * * @param struct chain_string *, the chain string where to search * @param const char * * @return struct chain_string * or NULL if not found * -------------------------------------------------------------------------- */ struct chain_string *pts; for (pts = chain_string_root; pts != NULL && strcmp(pts->value, value) != 0; pts = pts->next); return pts; } struct chain_string *get_last_chain_string(struct chain_string *chain_string_root) { /* ----------------------------------------------------------------------------- * Get the last chain string * * @param struct chain_string *, the chain string where to search * @return struct chain_string * * -------------------------------------------------------------------------- */ struct chain_string *pts; for (pts = chain_string_root; pts->next != NULL; pts = pts->next); return pts; } unsigned int get_nb_chain_string(struct chain_string *chain_string_root) { /* ----------------------------------------------------------------------------- * Get the number of elements * * @param struct chain_string *, the chain string where to search * @return int * -------------------------------------------------------------------------- */ struct chain_string *pts; unsigned int count = 0; for (pts = chain_string_root; pts != NULL; count++, pts = pts->next); return count; } struct chain_string *explode_to_chain_string(const char * strin, const char * delimiters) { /* ----------------------------------------------------------------------------- * Parse a string and explode it to several chain string by delimiters * * @param const char *, source string * @param const char *, delimiters * @return struct chain_string * * -------------------------------------------------------------------------- */ struct chain_string *pts = NULL; char *strin_cp = NULL; char *strin_cp_tmp = NULL; char *word = NULL; char *pts_tok = NULL; strin_cp = strdup(strin); if (strin_cp == NULL) { return NULL; } strin_cp_tmp = strin_cp; word = strtok_r(strin_cp_tmp, delimiters, &pts_tok); if (word != NULL) { pts = new_chain_string(word); while ((word = strtok_r(NULL, delimiters, &pts_tok)) != NULL) { append_chain_string(new_chain_string(word), pts); } } else { free(strin_cp); return NULL; } free(strin_cp); return pts; } struct chain_string *copy_chain_string(struct chain_string *chain_string_root) { /* ----------------------------------------------------------------------------- * Copy chain string * * @param struct chain_string *, the chain string where to copy * @return struct chain_string *, thz new copy * -------------------------------------------------------------------------- */ struct chain_string *chain_string_copy; struct chain_string *pts; if (chain_string_root == NULL) return NULL; pts = chain_string_root; chain_string_copy = new_chain_string((const char *)pts->value); pts = pts->next; while(pts != NULL) { append_chain_string(new_chain_string((const char *)pts->value), chain_string_copy); pts = pts->next; } return chain_string_copy; } void append_chain_string(struct chain_string *new_chain_string, struct chain_string *chain_string_dest) { /* ----------------------------------------------------------------------------- * Insert a chain string at the end * * @param struct chain_string *, the chain string to add * @param struct chain_string *, the root chain string * A <-> B <-> C <-> D .... insert T at the end * A <-> B <-> C <-> D <-> T * -------------------------------------------------------------------------- */ struct chain_string *pts; for (pts = chain_string_dest; pts->next != NULL; pts = pts->next); new_chain_string->previous = pts; pts->next = new_chain_string; } char * chain_string_join(struct chain_string *chain_string_root, const char *glue, unsigned int position) { /* ----------------------------------------------------------------------------- * Join all chain string element in one string with the given glue * * @param struct chain_string *, the root chain string * @param const char *, glue, * @param int, the offset * @return char *, a new string dynamically allocated or NULL * -------------------------------------------------------------------------- */ char *result = NULL, *result_realloc = NULL; struct chain_string *pts = NULL; unsigned int count = 0; int len = 0, total_size = 0, len_glue = 0; for (pts = chain_string_root; pts != NULL && count < position; count++, pts = pts->next); if (pts == NULL) return NULL; len_glue = strlen(glue); while (pts != NULL) { len = strlen(pts->value); total_size += len; if (pts->next != NULL) total_size += len_glue; result_realloc = (char *)realloc(result, (total_size + 1) * sizeof(char)); if (result_realloc == NULL) return NULL; result = result_realloc; if (pts->next != NULL) { memcpy(&result[total_size - len - len_glue], pts->value, len * sizeof(char)); memcpy(&result[total_size - len_glue], glue, len_glue * sizeof(char)); } else { memcpy(&result[total_size - len], pts->value, len * sizeof(char)); result[total_size] = '\0'; } pts = pts->next; } return result; } void print_chain_string(struct chain_string *chain_string_root) { /* ----------------------------------------------------------------------------- * Print a chain string to stdout * * @param struct chain_string *, the root chain string * -------------------------------------------------------------------------- */ struct chain_string *pts; for (pts = chain_string_root; pts != NULL; pts = pts->next) { printf("%s -> ", pts->value); } printf("\n"); } void print_reverse_chain_string(struct chain_string *chain_string_root_reverse) { /* ----------------------------------------------------------------------------- * Print a chain string to stdout from the end * * @param struct chain_string *, the root chain string * -------------------------------------------------------------------------- */ struct chain_string *pts; for (pts = chain_string_root_reverse; pts != NULL; pts = pts->previous) { printf("%s -> ", pts->value); } printf("\n"); } void print_all_chain_string(struct chain_string *chain_string_root) { /* ----------------------------------------------------------------------------- * Print a chain string to stdout from the beginning to the end and from the end * to the beginning * * @param struct chain_string *, the root chain string * -------------------------------------------------------------------------- */ struct chain_string *pts = NULL; struct chain_string *last_pts = NULL; for (pts = chain_string_root; pts != NULL; last_pts = pts, pts = pts->next) { printf("%s -> ", pts->value); } printf("\n"); for (pts = last_pts; pts != NULL; pts = pts->previous) { printf("%s -> ", pts->value); } printf("\n"); }