/* * This file is part of the PCEPlib, a PCEP protocol library. * * Copyright (C) 2020 Volta Networks https://voltanet.io/ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Author : Brady Johnson * */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "pcep_utils_logging.h" #include "pcep_utils_memory.h" #include "pcep_utils_ordered_list.h" /* Compare function that simply compares pointers. * return: * < 0 if new_entry < list_entry * == 0 if new_entry == list_entry (new_entry will be inserted after * list_entry) > 0 if new_entry > list_entry */ int pointer_compare_function(void *list_entry, void *new_entry) { return (char *)new_entry - (char *)list_entry; } ordered_list_handle *ordered_list_initialize(ordered_compare_function func_ptr) { ordered_list_handle *handle = pceplib_malloc(PCEPLIB_INFRA, sizeof(ordered_list_handle)); memset(handle, 0, sizeof(ordered_list_handle)); handle->head = NULL; handle->num_entries = 0; handle->compare_function = func_ptr; return handle; } /* free all the ordered_list_node resources and the ordered_list_handle. * it is assumed that the user is responsible fore freeing the data * pointed to by the nodes. */ void ordered_list_destroy(ordered_list_handle *handle) { if (handle == NULL) { return; } ordered_list_node *node = handle->head; ordered_list_node *next; while (node != NULL) { next = node->next_node; pceplib_free(PCEPLIB_INFRA, node); node = next; } pceplib_free(PCEPLIB_INFRA, handle); } ordered_list_node *ordered_list_add_node(ordered_list_handle *handle, void *data) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_add_node, the list has not been initialized", __func__); return NULL; } handle->num_entries++; ordered_list_node *new_node = pceplib_malloc(PCEPLIB_INFRA, sizeof(ordered_list_node)); memset(new_node, 0, sizeof(ordered_list_node)); new_node->data = data; new_node->next_node = NULL; /* check if its an empty list */ if (handle->head == NULL) { handle->head = new_node; return new_node; } ordered_list_node *prev_node = handle->head; ordered_list_node *node = prev_node; int compare_result; while (node != NULL) { compare_result = handle->compare_function(node->data, data); if (compare_result < 0) { /* insert the node */ new_node->next_node = node; if (handle->head == node) { /* add it at the beginning of the list */ handle->head = new_node; } else { prev_node->next_node = new_node; } return new_node; } /* keep searching with the next node in the list */ prev_node = node; node = node->next_node; } /* at the end of the list, add it here */ prev_node->next_node = new_node; return new_node; } ordered_list_node *ordered_list_find2(ordered_list_handle *handle, void *data, ordered_compare_function compare_func) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_find2, the list has not been initialized", __func__); return NULL; } ordered_list_node *node = handle->head; int compare_result; while (node != NULL) { compare_result = compare_func(node->data, data); if (compare_result == 0) { return node; } else { node = node->next_node; } } return NULL; } ordered_list_node *ordered_list_find(ordered_list_handle *handle, void *data) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_find, the list has not been initialized", __func__); return NULL; } return ordered_list_find2(handle, data, handle->compare_function); } void *ordered_list_remove_first_node(ordered_list_handle *handle) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_remove_first_node, the list has not been initialized", __func__); return NULL; } if (handle->head == NULL) { return NULL; } handle->num_entries--; void *data = handle->head->data; ordered_list_node *next_node = handle->head->next_node; pceplib_free(PCEPLIB_INFRA, handle->head); handle->head = next_node; return data; } void * ordered_list_remove_first_node_equals2(ordered_list_handle *handle, void *data, ordered_compare_function compare_func) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_remove_first_node_equals2, the list has not been initialized", __func__); return NULL; } if (handle->head == NULL) { return NULL; } ordered_list_node *prev_node = handle->head; ordered_list_node *node = prev_node; bool keep_walking = true; void *return_data = NULL; int compare_result; while (node != NULL && keep_walking) { compare_result = compare_func(node->data, data); if (compare_result == 0) { return_data = node->data; keep_walking = false; handle->num_entries--; /* adjust the corresponding pointers accordingly */ if (handle->head == node) { /* its the first node in the list */ handle->head = node->next_node; } else { prev_node->next_node = node->next_node; } pceplib_free(PCEPLIB_INFRA, node); } else { prev_node = node; node = node->next_node; } } return return_data; } void *ordered_list_remove_first_node_equals(ordered_list_handle *handle, void *data) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_remove_first_node_equals, the list has not been initialized", __func__); return NULL; } return ordered_list_remove_first_node_equals2(handle, data, handle->compare_function); } void *ordered_list_remove_node(ordered_list_handle *handle, ordered_list_node *prev_node, ordered_list_node *node_toRemove) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_remove_node, the list has not been initialized", __func__); return NULL; } if (handle->head == NULL) { return NULL; } void *return_data = node_toRemove->data; handle->num_entries--; if (node_toRemove == handle->head) { handle->head = node_toRemove->next_node; } else { prev_node->next_node = node_toRemove->next_node; } pceplib_free(PCEPLIB_INFRA, node_toRemove); return return_data; } void *ordered_list_remove_node2(ordered_list_handle *handle, ordered_list_node *node_to_remove) { if (handle == NULL) { pcep_log( LOG_WARNING, "%s: ordered_list_remove_node2, the list has not been initialized", __func__); return NULL; } if (handle->head == NULL) { return NULL; } ordered_list_node *node = handle->head; ordered_list_node *prev_node = handle->head; while (node != NULL) { if (node == node_to_remove) { return (ordered_list_remove_node(handle, prev_node, node)); } else { prev_node = node; node = node->next_node; } } return NULL; }