[<prev] [next>] [day] [month] [year] [list]
Message-ID: <CAFf+5zjVKEN1ZmS3YCXN8cN7GzVyBiyd4+tzYrZG9RJ8DFE_6w@mail.gmail.com>
Date: Sat, 25 Jan 2025 21:00:28 +0530
From: Amit <amitchoudhary0523@...il.com>
To: linux-kernel@...r.kernel.org
Subject: Almost all C++ STL data structures in one C library (generic_doubly_linked_list_library.c).
I have implemented a C program that can be used as a C++ STL list, map, set,
stack, queue, deque, multimap, multiset, unordered_map, unordered_set,
unordered_multimap, and unordered_multiset (basically almost all C++ STL data
structures).
For using this library as different C++ STL data structures you have to use
different combinations of functions provided in this library.
Another unique feature of this library is that it copies user's data into its
elements, so the user doesn't have to keep his/her copy of data around. User's
data safely resides in the elements.
I have included the code of the library in this mail and also the code of the
test programs that show how to use this library as a 'sorted list' and 'map'.
------------------------------------------------
An example of using this library as a 'list' is:
------------------------------------------------
gdlll_add_element_to_front(...);
...
...
gdlll_get_front_element(...);
-------------------------------------------------------
An example of using this library as a sorted 'list' is:
-------------------------------------------------------
gdlll_add_element_sorted_ascending(...);
...
...
gdlll_get_front_element(...);
-----------------------------------------------
An example of using this library as a 'set' is:
-----------------------------------------------
if (gdlll_peek_matching_element(...) == NULL) {
gdlll_add_element_sorted_ascending(...);
}
----------------------------------------------------------
An example of using this library as an 'unordered_set' is:
----------------------------------------------------------
if (gdlll_peek_matching_element(...) == NULL) {
gdlll_add_element_to_front(...);
}
-------------------------------------------------------------------------------
For using this library as a 'map', etc, your 'data_ptr' must point to a
structure that has a 'key' member and a 'value' member.
struct mymap
{
char *key;
int value;
};
struct mymap *mm;
mm = malloc(sizeof(*mm));
mm->key = malloc(10);
strncpy(mm->key, "abcd", 10);
mm->key[4] = 0;
mm->value = 20;
dup_elem = gdlll_peek_matching_element(gc, mm, get_struct_len(mm),
compare_elems);
if (dup_elem == NULL) {
gdlll_add_element_sorted_ascending(...);
} else { // if you want to replace existing value of the key
gdlll_replace_data_in_matching_element(...);
}
-------------------------------------------------------------------------------
-------------------------------------------------
test_generic_doubly_linked_list_library_as_list.c
-------------------------------------------------
/*
* License: This file has been released under license GPLv2.
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#include "generic_doubly_linked_list_library.h"
#include <stdio.h>
int compare(struct element *first, struct element *second)
{
int i = *(int *)(first->data_ptr);
int j = *(int *)(second->data_ptr);
if (i < j) {
return -1;
} else if (i == j) {
return 0;
} else {
return 1;
}
} // end of function compare()
int main (void)
{
int i = 0;
int count = 5;
struct element *elem = NULL;
struct gdll_container * gc = gdlll_init_gdll_container(NULL);
printf("\n");
while (count-- > 0) {
printf("Please enter an integer: ");
scanf("%d", &i);
gdlll_add_element_sorted_descending(gc, &i, sizeof(i), compare);
}
printf("\n\n");
printf("Total number of elements in the list = %ld\n\n",
gdlll_get_total_number_of_elements_in_gdll_container(gc));
printf("------------------------------\n");
printf("Printing values from the list:\n");
printf("------------------------------\n");
elem = gdlll_get_front_element(gc);
while (elem != NULL) {
printf("%d\n", *(int *)(elem->data_ptr));
elem = gdlll_get_front_element(gc);
}
printf("\n");
gdlll_delete_gdll_container(gc);
return 0;
} // end of function main()
------------------------------------------------
test_generic_doubly_linked_list_library_as_map.c
------------------------------------------------
/*
* License: This file has been released under license GPLv2.
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#include "generic_doubly_linked_list_library.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STR_LEN 256
#define NUM_ELEMENTS 5
struct mymap {
char *key_str;
int val;
};
char *get_input_from_stdin_and_discard_extra_characters(char *str, long size)
{
int c = 0;
long i = 0;
// If 'size' is 0 then this function will discard all input and return NULL.
// No need to check 'str' if 'size' is 0.
if (size == 0) {
// discard all input
while ((c = getchar()) && (c != '\n') && (c != EOF));
return NULL;
}
if (!str)
return str;
if (size < 0)
return NULL;
for (i = 0; i < (size - 1); i = i + 1) {
c = getchar();
if ((c == '\n') || (c == EOF)) {
str[i] = 0;
return str;
}
str[i] = (char)(c);
} // end of for loop
str[i] = 0;
// discard rest of input
while ((c = getchar()) && (c != '\n') && (c != EOF));
return str;
} // end of function get_input_from_stdin_and_discard_extra_characters()
int compare_elems(struct element *first, struct element *second)
{
char *i = ((struct mymap *)(first->data_ptr))->key_str;
char *j = ((struct mymap *)(second->data_ptr))->key_str;
return strcmp(i, j);
} // end of function compare_elems()
long get_struct_len(struct mymap *mm)
{
// have to count null character ('\0') also.
return (strlen(mm->key_str) + 1 + sizeof(int));
} // end of function get_struct_len()
void free_key_str(struct mymap *mm, long mm_len)
{
free(mm->key_str);
} // end of function free_key_str()
int main (void)
{
struct mymap *mm = {0};
int count = NUM_ELEMENTS;
struct mymap *elem_mm = NULL;
struct element *elem = NULL;
struct element *dup_elem = NULL;
struct gdll_container *gc = NULL;
gc = gdlll_init_gdll_container(free_key_str);
if (!gc) {
printf("No memory..exiting..");
exit(1);
}
// free 'mm' before exiting the program.
mm = calloc(sizeof(*mm), 1);
if (!mm) {
printf("No memory..exiting..");
gdlll_delete_gdll_container(gc);
exit(1);
}
while (count-- > 0) {
// Don't free mm->key_str. It will be freed by the callback function
// free_key_str() when the element will be deleted.
mm->key_str = calloc(MAX_STR_LEN, 1);
if (!(mm->key_str)) {
printf("No memory..exiting..");
free(mm); // free it here as this one isn't in the library yet
gdlll_delete_gdll_container(gc);
exit(1);
}
printf("\n");
// clear the input buffer
printf("Please enter a string (key): ");
get_input_from_stdin_and_discard_extra_characters(mm->key_str,
MAX_STR_LEN);
printf("Please enter an integer value: ");
scanf("%d", &(mm->val));
get_input_from_stdin_and_discard_extra_characters(NULL, 0);
dup_elem = gdlll_peek_matching_element(gc, mm, get_struct_len(mm),
compare_elems);
if (dup_elem == NULL) {
gdlll_add_element_sorted_ascending(gc, mm, get_struct_len(mm),
compare_elems);
} else { // if you want to replace exisiting value of the key
gdlll_replace_data_in_matching_element(gc, dup_elem->data_ptr,
get_struct_len(dup_elem->data_ptr),
mm, get_struct_len(mm), compare_elems);
}
} // end of while loop
printf("\n\n");
printf("Total number of elements in the map = %ld\n\n",
gdlll_get_total_number_of_elements_in_gdll_container(gc));
printf("--------------------------------------\n");
printf("Printing keys and values from the map:\n");
printf("--------------------------------------\n");
elem = gdlll_get_front_element(gc);
while (elem != NULL) {
elem_mm = (struct mymap *)(elem->data_ptr);
printf("key:%s, value:%d\n", elem_mm->key_str, elem_mm->val);
elem = gdlll_get_front_element(gc);
}
printf("\n");
free(mm);
gdlll_delete_gdll_container(gc);
return 0;
} // end of function main()
------------------------------------
generic_doubly_linked_list_library.h
------------------------------------
/*
* License: This file has been released under license GPLv2.
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#ifndef _GENERIC_DOUBLY_LINKED_LIST_LIBRARY_H_
#define _GENERIC_DOUBLY_LINKED_LIST_LIBRARY_H_
// gdlll means generic doubly linked list library.
// gdllc means generic doubly linked list container.
// gdll means generic doubly linked list.
// Everything happened successfully.
#define GDLLL_SUCCESS 0
// 'gdllc_ptr' argument is NULL.
#define GDLLL_GDLLC_PTR_IS_NULL -1
// 'data_ptr' argument is NULL.
#define GDLLL_DATA_PTR_IS_NULL -2
// 'data_size' argument is <= 0.
#define GDLLL_DATA_SIZE_IS_INVALID -3
// There are no elements in the container.
#define GDLLL_CONTAINER_IS_EMPTY -4
// No memory available.
#define GDLLL_NO_MEMORY -5
// Matching element was not found in the list.
#define GDLLL_MATCHING_ELEMENT_NOT_FOUND -6
// The function pointer given by the user for comparing elements is NULL.
#define GDLLL_COMPARE_ELEMENTS_FUNC_PTR_IS_NULL -7
// This is used only for initializing error variables.
#define GDLLL_ERROR_INIT_VALUE -99
struct element
{
void *data_ptr;
long data_size;
struct element *prev;
struct element *next;
};
/*
* The user needs to give a function pointer to compare elements in some
* functions of this library. Below is the signature of the elements comparator
* function.
*
* The return value of this function should be -1 if 'first' is less than the
* 'second', 0 if 'first' is equal to the 'second', and 1 if 'first' is greater
* than the 'second'.
*/
typedef int (*compare_elements_function)(struct element *first,
struct element *second);
struct gdll_container
{
struct element *first;
struct element *last;
long total_number_of_elements;
// This function pointer will be called before freeing 'data_ptr' member of
// the element structure. This will be needed if the user has allocated some
// memory in 'data_ptr' and the user wants to free it before the 'data_ptr'
// member is freed by this library. So, if the user has a need for it then
// the user can give a valid function pointer to call when initializing this
// library (by calling the function 'gdlll_init_gdll_container'). The user
// may also give NULL function pointer if the user doesn't need this
// functionality.
void (*call_function_before_deleting_data)(void *data_ptr, long data_size);
};
struct gdll_container *gdlll_init_gdll_container(
void *function_ptr_to_call_before_deleting_data);
// This function doesn't check the validity of its arguments. It is the
// responsibility of the calling function to check the arguments it is passing
// to this function.
static struct element *gdlll_create_standalone_element(void *data_ptr,
long data_size);
// This function doesn't check the validity of its arguments. It is the
// responsibility of the calling function to check the arguments it is passing
// to this function. This function just removes the element from the list,
// it doesn't decrement total_number_of_elements by 1. Decrementing has to be
// done in the calling function. This function should not be called if the
// number of elements in the container is 0. The calling function should first
// check whether the number of elements in the container is 0 or not.
static void gdlll_remove_element_from_list(struct gdll_container *gdllc_ptr,
struct element *elem_ptr);
// This function doesn't check the validity of its arguments. It is the
// responsibility of the calling function to check the arguments it is passing
// to this function. This function just inserts the element in the list at the
// appropriate place, it doesn't increment total_number_of_elements by 1.
// Incrementing has to be done in the calling function. This function should not
// be called if the number of elements in the container is 0. The calling
// function should first check whether the number of elements in the container
// is 0 or not.
static void insert_element_before_element(struct gdll_container *gdllc_ptr,
struct element *elem_to_insert_ptr,
struct element *elem_before_which_to_insert_ptr);
// If gdllc_ptr is NULL, then this function returns 0
long gdlll_get_total_number_of_elements_in_gdll_container(
struct gdll_container *gdllc_ptr);
int gdlll_add_element_to_front(struct gdll_container *gdllc_ptr, void *data_ptr,
long data_size);
int gdlll_add_element_to_back(struct gdll_container *gdllc_ptr, void *data_ptr,
long data_size);
int gdlll_add_element_sorted_ascending(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func);
int gdlll_add_element_sorted_descending(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func);
// All gdlll_get_* functions remove the element from the list and then return
// the element. If you don't want the element to be removed from the list then
// use gdlll_peek_* functions. If there are no elements in the container
// then NULL is returned.
struct element *gdlll_get_front_element(struct gdll_container *gdllc_ptr);
struct element *gdlll_get_last_element(struct gdll_container *gdllc_ptr);
struct element *gdlll_get_matching_element(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func);
// All gdlll_peek_* functions return the element without removing it from the
// list. If there are no elements in the container then NULL is returned.
struct element *gdlll_peek_front_element(struct gdll_container *gdllc_ptr);
struct element *gdlll_peek_last_element(struct gdll_container *gdllc_ptr);
struct element *gdlll_peek_matching_element(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func);
int gdlll_replace_data_in_matching_element(struct gdll_container *gdllc_ptr,
void *old_data_ptr, long old_data_size,
void *new_data_ptr, long new_data_size,
compare_elements_function comp_func);
void gdlll_delete_front_element(struct gdll_container *gdllc_ptr);
void gdlll_delete_last_element(struct gdll_container *gdllc_ptr);
void gdlll_delete_matching_element(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func);
void gdlll_delete_standalone_element(struct gdll_container *gdllc_ptr,
struct element *element_to_delete,
int is_element_from_list);
void gdlll_delete_all_elements_in_gdll_container(
struct gdll_container *gdllc_ptr);
void gdlll_delete_gdll_container(struct gdll_container *gdllc_ptr);
#endif
------------------------------------
generic_doubly_linked_list_library.c
------------------------------------
/*
* License: This file has been released under license GPLv2.
*/
/*
* Author: Amit Choudhary
* Email: amitchoudhary0523 AT gmail DOT com
*/
#include "generic_doubly_linked_list_library.h"
#include <stdlib.h>
#include <string.h>
static struct element *gdlll_create_standalone_element(void *data_ptr,
long data_size)
{
struct element *elem_ptr = NULL;
elem_ptr = calloc(sizeof(*elem_ptr), 1);
if (!elem_ptr) {
return NULL;
}
elem_ptr->data_ptr = calloc((size_t)(data_size), 1);
if (!(elem_ptr->data_ptr)) {
free(elem_ptr);
return NULL;
}
memmove(elem_ptr->data_ptr, data_ptr, (size_t)(data_size));
elem_ptr->data_size = data_size;
elem_ptr->prev = NULL;
elem_ptr->next = NULL;
return elem_ptr;
} // end of gdlll_create_standalone_element() function
static void gdlll_remove_element_from_list(struct gdll_container *gdllc_ptr,
struct element *elem_ptr)
{
if (elem_ptr == gdllc_ptr->first) {
gdllc_ptr->first = elem_ptr->next;
if (gdllc_ptr->first == NULL) {
gdllc_ptr->last = NULL;
} else {
gdllc_ptr->first->prev = NULL;
}
} else if (elem_ptr == gdllc_ptr->last) {
gdllc_ptr->last = elem_ptr->prev;
if (gdllc_ptr->last == NULL) {
gdllc_ptr->first = NULL;
} else {
gdllc_ptr->last->next = NULL;
}
} else {
elem_ptr->prev->next = elem_ptr->next;
elem_ptr->next->prev = elem_ptr->prev;
}
elem_ptr->prev = NULL;
elem_ptr->next = NULL;
} // end of gdlll_remove_element_from_list() function
static void insert_element_before_element(struct gdll_container *gdllc_ptr,
struct element *elem_to_insert_ptr,
struct element *elem_before_which_to_insert_ptr)
{
if (elem_before_which_to_insert_ptr == NULL) {
// add elem_to_insert_ptr to back
gdllc_ptr->last->next = elem_to_insert_ptr;
elem_to_insert_ptr->prev = gdllc_ptr->last;
gdllc_ptr->last = elem_to_insert_ptr;
} else if (elem_before_which_to_insert_ptr == gdllc_ptr->first) {
// add elem_to_insert_ptr to front
elem_to_insert_ptr->next = gdllc_ptr->first;
elem_to_insert_ptr->next->prev = elem_to_insert_ptr;
gdllc_ptr->first = elem_to_insert_ptr;
} else {
// insert elem_to_insert_ptr before elem_before_which_to_insert_ptr
elem_to_insert_ptr->next = elem_before_which_to_insert_ptr;
elem_to_insert_ptr->prev = elem_before_which_to_insert_ptr->prev;
elem_before_which_to_insert_ptr->prev = elem_to_insert_ptr;
elem_to_insert_ptr->prev->next = elem_to_insert_ptr;
}
} // end of insert_element_before_element() function
struct gdll_container *gdlll_init_gdll_container(
void *function_ptr_to_call_before_deleting_data)
{
struct gdll_container *gdllc_ptr = calloc(sizeof(*gdllc_ptr), 1);
if (!gdllc_ptr)
return NULL;
gdllc_ptr->first = NULL;
gdllc_ptr->last = NULL;
gdllc_ptr->total_number_of_elements = 0;
gdllc_ptr->call_function_before_deleting_data =
function_ptr_to_call_before_deleting_data;
return gdllc_ptr;
} // end of gdlll_init_gdll_container() function
long gdlll_get_total_number_of_elements_in_gdll_container(
struct gdll_container *gdllc_ptr)
{
if (!gdllc_ptr) {
return 0;
}
return (gdllc_ptr->total_number_of_elements);
} // end of gdlll_get_total_number_of_elements_in_gdll_container() function
int gdlll_add_element_to_front(struct gdll_container *gdllc_ptr, void *data_ptr,
long data_size)
{
struct element *elem_ptr = NULL;
if (!gdllc_ptr) {
return GDLLL_GDLLC_PTR_IS_NULL;
}
if (!data_ptr) {
return GDLLL_DATA_PTR_IS_NULL;
}
if (data_size <= 0) {
return GDLLL_DATA_SIZE_IS_INVALID;
}
elem_ptr = gdlll_create_standalone_element(data_ptr, data_size);
if (!elem_ptr) {
return GDLLL_NO_MEMORY;
}
if (gdllc_ptr->first == NULL) {
gdllc_ptr->first = elem_ptr;
gdllc_ptr->last = elem_ptr;
} else {
elem_ptr->next = gdllc_ptr->first;
elem_ptr->next->prev = elem_ptr;
gdllc_ptr->first = elem_ptr;
}
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements + 1;
return GDLLL_SUCCESS;
} // end of gdlll_add_element_to_front() function
int gdlll_add_element_to_back(struct gdll_container *gdllc_ptr, void *data_ptr,
long data_size)
{
struct element *elem_ptr = NULL;
if (!gdllc_ptr) {
return GDLLL_GDLLC_PTR_IS_NULL;
}
if (!data_ptr) {
return GDLLL_DATA_PTR_IS_NULL;
}
if (data_size <= 0) {
return GDLLL_DATA_SIZE_IS_INVALID;
}
elem_ptr = gdlll_create_standalone_element(data_ptr, data_size);
if (!elem_ptr) {
return GDLLL_NO_MEMORY;
}
if (gdllc_ptr->first == NULL) {
gdllc_ptr->first = elem_ptr;
gdllc_ptr->last = elem_ptr;
} else {
gdllc_ptr->last->next = elem_ptr;
elem_ptr->prev = gdllc_ptr->last;
gdllc_ptr->last = elem_ptr;
}
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements + 1;
return GDLLL_SUCCESS;
} // end of gdlll_add_element_to_back() function
int gdlll_add_element_sorted_ascending(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func)
{
struct element *elem_ptr = NULL;
if (!gdllc_ptr) {
return GDLLL_GDLLC_PTR_IS_NULL;
}
if (!data_ptr) {
return GDLLL_DATA_PTR_IS_NULL;
}
if (data_size <= 0) {
return GDLLL_DATA_SIZE_IS_INVALID;
}
if (!comp_func) {
return GDLLL_COMPARE_ELEMENTS_FUNC_PTR_IS_NULL;
}
elem_ptr = gdlll_create_standalone_element(data_ptr, data_size);
if (!elem_ptr) {
return GDLLL_NO_MEMORY;
}
if (gdllc_ptr->first == NULL) {
gdllc_ptr->first = elem_ptr;
gdllc_ptr->last = elem_ptr;
} else {
struct element *temp = gdllc_ptr->first;
while ((temp) && (comp_func(elem_ptr, temp) > 0)) {
temp = temp->next;
}
// insert elem_ptr before temp
insert_element_before_element(gdllc_ptr, elem_ptr, temp);
}
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements + 1;
return GDLLL_SUCCESS;
} // end of gdlll_add_element_sorted_ascending() function
int gdlll_add_element_sorted_descending(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func)
{
struct element *elem_ptr = NULL;
if (!gdllc_ptr) {
return GDLLL_GDLLC_PTR_IS_NULL;
}
if (!data_ptr) {
return GDLLL_DATA_PTR_IS_NULL;
}
if (data_size <= 0) {
return GDLLL_DATA_SIZE_IS_INVALID;
}
if (!comp_func) {
return GDLLL_COMPARE_ELEMENTS_FUNC_PTR_IS_NULL;
}
elem_ptr = gdlll_create_standalone_element(data_ptr, data_size);
if (!elem_ptr) {
return GDLLL_NO_MEMORY;
}
if (gdllc_ptr->first == NULL) {
gdllc_ptr->first = elem_ptr;
gdllc_ptr->last = elem_ptr;
} else {
struct element *temp = gdllc_ptr->first;
while ((temp) && (comp_func(elem_ptr, temp) < 0)) {
temp = temp->next;
}
// insert elem_ptr before temp
insert_element_before_element(gdllc_ptr, elem_ptr, temp);
}
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements + 1;
return GDLLL_SUCCESS;
} // end of gdlll_add_element_sorted_descending() function
struct element *gdlll_get_front_element(struct gdll_container *gdllc_ptr)
{
struct element *temp = NULL;
if (!gdllc_ptr) {
return NULL;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return NULL;
}
temp = gdllc_ptr->first;
gdlll_remove_element_from_list(gdllc_ptr, gdllc_ptr->first);
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements - 1;
return temp;
} // end of gdlll_get_front_element() function
struct element *gdlll_get_last_element(struct gdll_container *gdllc_ptr)
{
struct element *temp = NULL;
if (!gdllc_ptr) {
return NULL;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return NULL;
}
temp = gdllc_ptr->last;
gdlll_remove_element_from_list(gdllc_ptr, gdllc_ptr->last);
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements - 1;
return temp;
} // end of gdlll_get_last_element() function
struct element *gdlll_get_matching_element(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func)
{
struct element *matching_elem_ptr = NULL;
if (!gdllc_ptr) {
return NULL;
}
if (!data_ptr) {
return NULL;
}
if (data_size <= 0) {
return NULL;
}
if (!comp_func) {
return NULL;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return NULL;
}
matching_elem_ptr = gdlll_peek_matching_element(gdllc_ptr, data_ptr,
data_size, comp_func);
if (matching_elem_ptr == NULL) {
return NULL;
}
gdlll_remove_element_from_list(gdllc_ptr, matching_elem_ptr);
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements - 1;
return matching_elem_ptr;
} // end of gdlll_get_matching_element() function
struct element *gdlll_peek_front_element(struct gdll_container *gdllc_ptr)
{
if (!gdllc_ptr) {
return NULL;
}
return (gdllc_ptr->first);
} // end of gdlll_peek_front_element() function
struct element *gdlll_peek_last_element(struct gdll_container *gdllc_ptr)
{
if (!gdllc_ptr) {
return NULL;
}
return (gdllc_ptr->last);
} // end of gdlll_peek_last_element() function
struct element *gdlll_peek_matching_element(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func)
{
struct element *elem_ptr = NULL;
struct element *temp = NULL;
if (!gdllc_ptr) {
return NULL;
}
if (!data_ptr) {
return NULL;
}
if (data_size <= 0) {
return NULL;
}
if (!comp_func) {
return NULL;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return NULL;
}
elem_ptr = gdlll_create_standalone_element(data_ptr, data_size);
if (!elem_ptr) {
return NULL;
}
temp = gdllc_ptr->first;
while ((temp) && (comp_func(elem_ptr, temp) != 0)) {
temp = temp->next;
}
gdlll_delete_standalone_element(gdllc_ptr, elem_ptr, 0);
return temp;
} // end of gdlll_peek_matching_element() function
int gdlll_replace_data_in_matching_element(struct gdll_container *gdllc_ptr,
void *old_data_ptr, long old_data_size,
void *new_data_ptr, long new_data_size,
compare_elements_function comp_func)
{
struct element *matching_elem_ptr = NULL;
void *temp_data_ptr = NULL;
if (!gdllc_ptr) {
return GDLLL_GDLLC_PTR_IS_NULL;
}
if (!old_data_ptr) {
return GDLLL_DATA_PTR_IS_NULL;
}
if (old_data_size <= 0) {
return GDLLL_DATA_SIZE_IS_INVALID;
}
if (!new_data_ptr) {
return GDLLL_DATA_PTR_IS_NULL;
}
if (new_data_size <= 0) {
return GDLLL_DATA_SIZE_IS_INVALID;
}
if (!comp_func) {
return GDLLL_COMPARE_ELEMENTS_FUNC_PTR_IS_NULL;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return GDLLL_CONTAINER_IS_EMPTY;
}
matching_elem_ptr = gdlll_peek_matching_element(gdllc_ptr, old_data_ptr,
old_data_size, comp_func);
if (matching_elem_ptr == NULL) {
return GDLLL_MATCHING_ELEMENT_NOT_FOUND;
}
temp_data_ptr = calloc((size_t)(new_data_size), 1);
if (!temp_data_ptr) {
return GDLLL_NO_MEMORY;
}
// Now, call the call_function_before_deleting_data() for 'data_ptr' of the
// matching element and then free the 'data_ptr' of the matching element
if (gdllc_ptr->call_function_before_deleting_data) {
gdllc_ptr->call_function_before_deleting_data(
matching_elem_ptr->data_ptr, matching_elem_ptr->data_size);
}
free(matching_elem_ptr->data_ptr);
matching_elem_ptr->data_ptr = temp_data_ptr;
memmove(matching_elem_ptr->data_ptr, new_data_ptr, (size_t)(new_data_size));
matching_elem_ptr->data_size = new_data_size;
return GDLLL_SUCCESS;
} // end of gdlll_replace_data_in_matching_element() function
void gdlll_delete_front_element(struct gdll_container *gdllc_ptr)
{
struct element *temp_elem_ptr = NULL;
if (!gdllc_ptr) {
return;
}
temp_elem_ptr = gdllc_ptr->first;
if (temp_elem_ptr) {
gdlll_remove_element_from_list(gdllc_ptr, temp_elem_ptr);
gdlll_delete_standalone_element(gdllc_ptr, temp_elem_ptr, 1);
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements - 1;
}
return;
} // end of gdlll_delete_front_element() function
void gdlll_delete_last_element(struct gdll_container *gdllc_ptr)
{
struct element *temp_elem_ptr = NULL;
if (!gdllc_ptr) {
return;
}
temp_elem_ptr = gdllc_ptr->last;
if (temp_elem_ptr) {
gdlll_remove_element_from_list(gdllc_ptr, temp_elem_ptr);
gdlll_delete_standalone_element(gdllc_ptr, temp_elem_ptr, 1);
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements - 1;
}
return;
} // end of gdlll_delete_last_element() function
void gdlll_delete_matching_element(struct gdll_container *gdllc_ptr,
void *data_ptr, long data_size,
compare_elements_function comp_func)
{
struct element *matching_elem_ptr = NULL;
if (!gdllc_ptr) {
return;
}
if (!data_ptr) {
return;
}
if (data_size <= 0) {
return;
}
if (!comp_func) {
return;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return;
}
matching_elem_ptr = gdlll_peek_matching_element(gdllc_ptr, data_ptr,
data_size, comp_func);
if (matching_elem_ptr == NULL) {
return;
}
gdlll_remove_element_from_list(gdllc_ptr, matching_elem_ptr);
gdlll_delete_standalone_element(gdllc_ptr, matching_elem_ptr, 1);
gdllc_ptr->total_number_of_elements =
gdllc_ptr->total_number_of_elements - 1;
return;
} // end of gdlll_delete_matching_element() function
void gdlll_delete_standalone_element(struct gdll_container *gdllc_ptr,
struct element *element_to_delete,
int is_element_from_list)
{
if (!gdllc_ptr) {
return;
}
if (!element_to_delete) {
return;
}
// Call the call_function_before_deleting_data() for 'data_ptr' of
// 'element_to_delete' and then free the 'data_ptr' of 'element_to_delete'.
// Then free the 'element_to_delete'.
if (is_element_from_list) {
if (gdllc_ptr->call_function_before_deleting_data) {
gdllc_ptr->call_function_before_deleting_data(
element_to_delete->data_ptr, element_to_delete->data_size);
}
}
free(element_to_delete->data_ptr);
free(element_to_delete);
return;
} // end of gdlll_delete_standalone_element() function
void gdlll_delete_all_elements_in_gdll_container(
struct gdll_container *gdllc_ptr)
{
struct element *temp_elem_ptr = NULL;
if (!gdllc_ptr) {
return;
}
if (gdllc_ptr->total_number_of_elements == 0) {
return;
}
temp_elem_ptr = gdllc_ptr->first;
while (temp_elem_ptr) {
gdlll_delete_front_element(gdllc_ptr);
temp_elem_ptr = gdllc_ptr->first;
}
return;
} // end of gdlll_delete_all_elements_in_gdll_container() function
void gdlll_delete_gdll_container(struct gdll_container *gdllc_ptr)
{
if (!gdllc_ptr) {
return;
}
gdlll_delete_all_elements_in_gdll_container(gdllc_ptr);
free(gdllc_ptr);
return;
} // end of gdlll_delete_gdll_container() function
Powered by blists - more mailing lists