diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..6d4dbd8 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,19 @@ +imamLL + +version 1.0 5 July 2015 + + - initial release + - basic doubly linked list support + +version 1.1 10 July 2015 + + - extended support for positioning of new elements + - fixing of memory leaking due to payload not being freed in the code + +version 1.2 24 July 2015 + + - refining of function and struct variables types + +version 1.3 27 July 2015 + + - further refine data types diff --git a/Intro.html b/Intro.html new file mode 100644 index 0000000..608b4e5 --- /dev/null +++ b/Intro.html @@ -0,0 +1,50 @@ + +Introduction to imamLL

About imamLL

 

What is Imam Linear List (imamLL)?

 

ImamLL is a simple linked list implementation library for C programming language. It is designed to be efficient and programmers friendly by minimizing number of variables required for allocating and deallocating memory from the heap. It is created in a hope that it will help developers to store arbitrary information in the programs easily.

 

Where can I use imamLL ?

 

You can use imamLL whenever you need to create data lists in your programs. Since imamLL is pointer based, it will accept any type of data and also data of arbitrary sizes into a single list. You can easily add, remove, modify and get data from the lists.

 

What are the features of imamLL ?

 

 

What are the future plans for imamLL ?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The Basics

 

There are two structures in imamLL library, a data list and a list element. The struct imamLL structure stores basic information about a list for example number of elements in a list, total number of bytes allocated by list elements, addresses of first, last and current list elements. The definition of the imamLL structure is shown below:

 

struct imamLL {

    long number_of_elements;         /* number of elements in the list */

    long size;                       /* total elements size in bytes */

    struct imamLL_element *first;    /* pointer to the first element */

    struct imamLL_element *last;     /* pointer to the last element */

    struct imamLL_element *current;  /* pointer to an arbitrary           element, used by            imamLL_element_get_* functions */

    int error;                       /* error number used by            imamLL_list_error function */

};

 

The struct imamLL_element structure stores information about each individual element in a list. The definition of the imamLL_element structure is shown below:

 

struct imamLL_element {

    void *data;                       /* pointer to the data */

    long size;                        /* size of data in bytes */

    struct imamLL_element *prev;      /* pointer to the next element */

    struct imamLL_element *next;      /* pointer to the first element */

};

 

To create a list of data, first we need to declare a pointer of type struct imamLL. For example, we want a create an integer numbers list, therefore we declare a pointer named num_list as follows:

 

struct imamLL *num_list;

 

Next, we have to allocate memory for the list by calling the function imamLL_list_create, while will return a pointer to the list,

 

num_list = imamLL_list_create ();

 

Now, to add an integer number to the list we use imamLL_element_add function. imamLL_element_add function allocates memory for an element and returns a pointer to the element. So first, we declare a pointer of type struct imamLL_element and call imamLL_element_add function.

 

struct imamLL_element *element;

 

element = imamLL_element_add (num_list, sizeof (int), 0);

The arguments in imamLL_element_add are pointer of the list, size of the element in bytes, and 0 for indicating element to be added at the bottom of the list. Finally, we can store an integer value to the element by,

 

*((int *)element->data) = 10;

 

We can store more integer values by adding more elements in the list by repeating the above codes, for example:

 

element = imamLL_element_add (num_list, sizeof (int), 0);

*((int *)element->data) = 20;

 

element = imamLL_element_add (num_list, sizeof (int), 0);

*((int *)element->data) = 30;

 

Now, we have three elements in the list having integer values 10, 20 and 30 respectively. We can print all the values in the list elements by using the following code:

 

imamLL_list_rewind (student_list);

 

while ((element = imamLL_element_get_next(student_list)) != NULL) {

 printf ("%d\n", *((int *)element->data));

}

 

The function imamLL_list_rewind, sets the current element in the list to be first element and imamLL_element_get_next function returns the next element from the current element. The imamLL_element_get_next function returns NULL when the end of the list is reached.

 

When we do not the need the list, we can free the memory associated with the list and it's elements by using:

 

imamLL_list_destroy (num_list);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

The full blown code of the example program is given below:

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

#include <imamll.h>  /*header for imamLL */

 

struct imamLL *num_list = NULL;

struct imamLL_element *element = NULL;

 

int main (int argc, char** argv)

{

        num_list = imamLL_list_create();

 

 if ( num_list == NULL) {

  printf ("Can not create the list\n");

  exit (EXIT_FAILURE);

 }

   

        element = imamLL_element_add (num_list, sizeof (int), 0);

 

        if (element == NULL) printf ("Error allocating memory for an  integer element\n");

        else *((int *)element->data) = 10;

   

 element = imamLL_element_add (num_list, sizeof (int), 0);

 

        if (element == NULL) printf ("Error allocating memory for an  integer element\n");

        else *((int *)element->data) = 20;

 

        element = imamLL_element_add (num_list, sizeof (int), 0);

 

        if (element == NULL) printf ("Error allocating memory for an  integer element\n");

        else *((int *)element->data) = 30;

   

 imamLL_list_rewind (num_list);

 

 while ((element = imamLL_element_get_next(num_list)) != NULL) {

  printf ("%d\n", *((int *)element->data));

 }

   

 imamLL_list_destroy (num_list);

 

 return 0;

}

diff --git a/License b/License new file mode 100644 index 0000000..912877e --- /dev/null +++ b/License @@ -0,0 +1,17 @@ +Copyright (c) 2015 Md Imam Hossain + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgement in the product documentation would be + appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. diff --git a/Modified b/Modified new file mode 100644 index 0000000..0588fa7 --- /dev/null +++ b/Modified @@ -0,0 +1,24 @@ +Files changed in version 1.1 + + - README + - ChangeLog + - examples/number_list.c + - examples/product_list.c + - examples/student_book.c + - src/imamll.c + - src/imamll.h + - Modified + +Files changed in version 1.2 + + - ChangeLog + - src/imamll.c + - src/imamll.h + - Modified + +Files changed in version 1.3 + + - ChangeLog + - src/imamll.c + - src/imamll.h + - Modified diff --git a/README b/README new file mode 100644 index 0000000..0f6c201 --- /dev/null +++ b/README @@ -0,0 +1,27 @@ + + Imam Linear List + + (imamLL) + + Version 1.1 + +-------------------------------------------------------------------------------------- + +This is the Imam Linear List, a simple linked list implementation library +for storing data structures and data lists into the heap memory. + +Please read Intro for a detail description and example. + +There are example programs in the examples directory and also have a look at the imamll.h header file for a better understanding of the library. + +imamLL is written in C, but should work with C++ natively. + +To install imamLL, execute build.sh script in the terminal. + +After installing the library to compile your code using gcc just add -limamll in the compile command, e.g: gcc -Wall -o main main.c -limamll + +This library is distributed under zlib license. Please read License for more information + +Enjoy! + + Md Imam Hossain (emamhd@gmail.com) diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..26c1490 --- /dev/null +++ b/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +echo "imamLL library installation" + +./compile.sh + +if [ "$?" -ne 0 ] +then +exit 1 +fi + +sudo ./install.sh + +if [ "$?" -ne 0 ] +then +exit 1 +fi + +./examples.sh + +echo "Done" + +exit 0 diff --git a/compile.sh b/compile.sh new file mode 100644 index 0000000..c019832 --- /dev/null +++ b/compile.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +echo "Compiling imamLL library..." +sleep 1 + +cd src + +gcc -c -Wall -Werror -fpic imamll.c + +if [ "$?" -ne 0 ] +then +echo "Error compiling imamll.c" +exit 1 +fi + +gcc -shared -o libimamll.so imamll.o + +if [ "$?" -ne 0 ] +then +echo "Error creating libimamll.so" +exit 1 +fi + +exit 0 diff --git a/examples.sh b/examples.sh new file mode 100644 index 0000000..c4c8963 --- /dev/null +++ b/examples.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +echo "Compiling examples..." +sleep 1 + +cd examples + +gcc -Wall -o number_list number_list.c -limamll + +if [ "$?" -ne 0 ] +then +echo "Error compiling number_list.c" +fi + +gcc -Wall -o product_list product_list.c -limamll + +if [ "$?" -ne 0 ] +then +echo "Error compiling product_list.c" +fi + +gcc -Wall -o student_book student_book.c -limamll + +if [ "$?" -ne 0 ] +then +echo "Error compiling student_book.c" +fi + +exit 0 diff --git a/examples/number_list.c b/examples/number_list.c new file mode 100644 index 0000000..e4d5aea --- /dev/null +++ b/examples/number_list.c @@ -0,0 +1,64 @@ +/* + Copyright (c) 2015 Md Imam Hossain + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Md. Imam Hossain + emamhd@gmail.com +*/ + +#include +#include +#include + +#include + +struct imamLL *number_list = NULL; +struct imamLL_element *element = NULL; +int number; + +int main (int argc, char** argv) +{ + number_list = imamLL_list_create (); + + if (number_list == NULL) { + printf ("Can not create list\n"); + exit (EXIT_FAILURE); + } + + for (number = 0; number < 10; number++) { + element = imamLL_element_add (number_list, sizeof (number), AT_END); + if (element == NULL) printf ("Error allocating memory for a number\n"); + else memcpy (element->data, &number, sizeof(number)); + } + + printf ("There are %ld numbers in the list\n", number_list->number_of_elements); + printf ("Total memory allocated %ld bytes\n\n", number_list->size); + + imamLL_list_rewind (number_list); + + while (1) { + element = imamLL_element_get_next (number_list); + if (element == NULL) break; + else printf ("%d\n", *((int *)element->data)); + } + + if (imamLL_list_destroy (number_list) == -1) printf ("Can not free memory\n"); + + return EXIT_SUCCESS; +} + diff --git a/examples/product_list.c b/examples/product_list.c new file mode 100644 index 0000000..e4d9389 --- /dev/null +++ b/examples/product_list.c @@ -0,0 +1,93 @@ +/* + Copyright (c) 2015 Md Imam Hossain + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Md. Imam Hossain + emamhd@gmail.com +*/ + + +#include +#include +#include + +#include + +struct imamLL *product_list = NULL; +struct imamLL_element *element = NULL; +struct imamLL_element *temp = NULL; + +char product[128]; + +int main (int argc, char** argv) +{ + + product_list = imamLL_list_create (); + + if (product_list == NULL) { + printf ("Can not create list\n"); + exit (EXIT_FAILURE); + } + + strcpy (product, "Bearing"); + element = imamLL_element_add (product_list, strlen (product) + 1, AT_END); + if (element == NULL) printf ("Error allocating memory for Bearing element\n"); + strcpy ((char *)element->data, product); + + strcpy (product, "Switch"); + element = imamLL_element_add (product_list, strlen (product) + 1, AT_END); + if (element == NULL) printf ("Error allocating memory for Switch element\n"); + strcpy ((char *)element->data, product); + + strcpy (product, "Nozzle"); + element = imamLL_element_add (product_list, strlen (product) + 1, AT_END); + if (element == NULL) printf ("Error allocating memory for Nozzle element\n"); + strcpy ((char *)element->data, product); + + imamLL_list_rewind (product_list); + while (1) { + element = imamLL_element_get_next (product_list); + if (element == NULL) break; + else printf ("%s\n", (char *)element->data); + } + + printf ("There are %ld elements in the list\n", product_list->number_of_elements); + printf ("Total memory allocated %ld bytes\n", product_list->size); + + strcpy (product, "Nozzle"); + element = imamLL_element_get (product_list, product, strlen (product) + 1); + + if (element == NULL) printf ("Error getting the Nozzle element"); + else { + if (imamLL_element_remove (product_list, element) != 1) printf ("Error removing the Nozzle element\n"); + } + + imamLL_list_rewind (product_list); + while (1) { + element = imamLL_element_get_next (product_list); + if (element == NULL) break; + else printf ("%s\n", (char *)element->data); + } + + printf ("There are %ld elements in the list\n", product_list->number_of_elements); + printf ("Total memory allocated %ld bytes\n", product_list->size); + + if (imamLL_list_destroy (product_list) == -1) printf ("Can not free memory\n"); + + return EXIT_SUCCESS; +} diff --git a/examples/student_book.c b/examples/student_book.c new file mode 100644 index 0000000..79afee9 --- /dev/null +++ b/examples/student_book.c @@ -0,0 +1,182 @@ +/* + Copyright (c) 2015 Md Imam Hossain + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Md. Imam Hossain + emamhd@gmail.com +*/ + +#include +#include +#include + +#include + +struct Student { + char First_Name[16]; + char Last_Name[16]; + long id; +}; + +int selection = 1; + +struct imamLL *student_list = NULL; +struct imamLL_element *element = NULL; +struct Student *student = NULL; + +void print_menu (void); +void show_students (void); +void add_student (void); +void delete_student (void); +void find_student (void); + +int main (int argc, char** argv) +{ + printf ("Creating student book...\n"); + + student_list = imamLL_list_create(); + + if (student_list == NULL) { + printf ("Can not create student book\n"); + exit (EXIT_FAILURE); + } + + printf ("There are %ld students in the book\n", student_list->number_of_elements); + printf ("Total memory allocated %ld bytes\n", student_list->size); + + while (1) { + print_menu(); + scanf ("%d", &selection); + if (selection == 1) show_students (); + else if (selection == 2) add_student (); + else if (selection == 3) delete_student (); + else if (selection == 4) find_student (); + else if (selection == 5) break; + } + + if (imamLL_list_destroy(student_list) == -1) printf ("Can not free memory allocation by student book\n"); + + return EXIT_SUCCESS; +} + +void print_menu (void) +{ + printf ("\nMenu:\n\n"); + printf ("\t1. Show students\n"); + printf ("\t2. Add a new student\n"); + printf ("\t3. Delete an existing student\n"); + printf ("\t4. Find a student\n"); + printf ("\t5. Exit\n\n"); + printf ("Select (1-5): "); +} + +void show_students (void) +{ + long count = 0; + if (student_list->number_of_elements < 1) { + printf ("\nNo students in the book\n"); + return; + } + printf ("\n"); + printf ("There are %ld students in the book\n", student_list->number_of_elements); + printf ("Total memory allocated %ld bytes\n\n", student_list->size); + imamLL_list_rewind (student_list); + while (1) { + element = imamLL_element_get_next (student_list); + if (element == NULL) break; + else { + count++; + student = (struct Student *) element->data; + printf ("%ld. %s %s %ld\n", count, student->First_Name, student->Last_Name, student->id); + } + } +} + +void add_student (void) +{ + element = imamLL_element_add (student_list, sizeof (struct Student), AT_START); + if (element == NULL) { + printf ("Error allocating memory for student\n"); + return; + } + printf ("\n"); + student = (struct Student *) element->data; + printf ("First Name: "); + scanf ("%s", student->First_Name); + printf ("Last Name: "); + scanf ("%s", student->Last_Name); + printf ("id: "); + scanf ("%ld", &student->id); + printf ("\nRegistered successfully.\n"); +} + +void delete_student (void) +{ + long id = 0; + if (student_list->number_of_elements < 1) { + printf ("\nNo students in the book\n"); + return; + } + printf ("\n"); + printf ("Student id: "); + scanf ("%ld", &id); + imamLL_list_rewind (student_list); + while (1) { + element = imamLL_element_get_next (student_list); + if (element == NULL) break; + else { + student = (struct Student *) element->data; + if (student->id == id) { + if (imamLL_element_remove (student_list, element) != 1) { + printf ("Can not delete student.\n"); + return; + } + printf ("Deleted.\n"); + return; + } + } + } + printf ("No student found.\n"); +} + +void find_student (void) +{ + long id = 0; + if (student_list->number_of_elements < 1) { + printf ("\nNo students in the book\n"); + return; + } + printf ("\n"); + printf ("Student id: "); + scanf ("%ld", &id); + imamLL_list_rewind (student_list); + while (1) { + element = imamLL_element_get_next (student_list); + if (element == NULL) break; + else { + student = (struct Student *) element->data; + if (student->id == id) { + printf ("Found:\n\n"); + printf ("First Name: %s\n", student->First_Name); + printf ("Last Name: %s\n", student->Last_Name); + return; + } + } + } + printf ("No student found.\n"); +} diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..c6bcd27 --- /dev/null +++ b/install.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +echo "Installing imamLL library..." +sleep 2 + +cd src + +if uname -p | grep -q x86_64; then + rm /usr/lib/x86_64-linux-gnu/libimamll.* + cp libimamll.so /usr/lib/x86_64-linux-gnu/ + if [ "$?" -ne 0 ] + then + echo "Error installing imamLL library" + exit 1 + fi + cp imamll.h /usr/include/ + if [ "$?" -ne 0 ] + then + echo "Error installing imamLL header" + exit 1 + fi +else + rm /usr/lib/i386-linux-gnu/libimamll.* + cp libimamll.so /usr/lib/i386-linux-gnu/ + if [ "$?" -ne 0 ] + then + echo "Error installing imamLL library" + exit 1 + fi + cp imamll.h /usr/include/ + if [ "$?" -ne 0 ] + then + echo "Error installing imamLL header" + exit 1 + fi +fi + +exit 0 diff --git a/src/imamll.c b/src/imamll.c new file mode 100644 index 0000000..747c360 --- /dev/null +++ b/src/imamll.c @@ -0,0 +1,291 @@ +/* + Imam Linear List (imamLL) a simple C based linked list library + + Copyright (c) 2015 Md Imam Hossain + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Md Imam Hossain + emamhd@gmail.com +*/ + +#include "imamll.h" + +struct imamLL *imamLL_list_create (void) +{ + struct imamLL *tmp = NULL; + tmp = (struct imamLL *) malloc(sizeof (struct imamLL)); + if (tmp == NULL) return NULL; + else { + tmp->current = NULL; + tmp->first = NULL; + tmp->last = NULL; + tmp->number_of_elements = 0; + tmp->size = 0; + tmp->error = 0; + return tmp; + } +} + +int imamLL_list_destroy (struct imamLL *list) +{ + if (list != NULL) { + if (list->number_of_elements > 0) { + if (imamLL_list_free (list) > 0) free (list); + else return -1; + } + else free (list); + return 0; + } + else return -1; +} + +int imamLL_list_free (struct imamLL *list) +{ + struct imamLL_element *tmp = list->last; + register int count = 0; + if (tmp == NULL) { + list->error = EMPTY_LIST; + return -1; + } + while (tmp != NULL) + { + struct imamLL_element *prev = tmp->prev; + tmp->prev = NULL; + tmp->next = NULL; + tmp->size = 0; + free (tmp->data); + tmp->data = NULL; + free (tmp); + tmp = prev; + count++; + } + list->current = NULL; + list->last = NULL; + list->first = NULL; + list->number_of_elements = 0; + list->size = 0; + list->error = 0; + return count; +} + +void imamLL_list_rewind (struct imamLL *list) +{ + list->current = NULL; +} + +void imamLL_list_error (struct imamLL *list, char *error_message) +{ + if (list->error == MEMORY_ALLOCATION) strcpy (error_message, "Memory allocation for element failed"); + else if (list->error == EMPTY_LIST) strcpy (error_message, "Element list is empty"); + else if (list->error == NO_MATCHING_ELEMENT) strcpy (error_message, "Element is not found"); + else strcpy (error_message, "No error is found"); +} + +struct imamLL_element *imamLL_element_add (struct imamLL *list, unsigned long element_size, uint32_t position) +{ + if (list->first == NULL) + { + list->first = (struct imamLL_element *) malloc(sizeof (struct imamLL_element)); + if (list->first == NULL) { + list->error = MEMORY_ALLOCATION; + return NULL; + } + list->first->data = (char *) malloc (sizeof (char) * element_size); + if (list->first->data == NULL) { + free (list->first); + list->error = MEMORY_ALLOCATION; + return NULL; + } + list->first->prev = NULL; + list->first->next = NULL; + list->first->size = element_size; + list->size = list->size + list->first->size; + list->number_of_elements = list->number_of_elements + 1; + list->last = list->first; + return list->first; + } + else + { + struct imamLL_element *tmp = NULL; + tmp = (struct imamLL_element *) malloc(sizeof (struct imamLL_element)); + if (tmp == NULL) { + list->error = MEMORY_ALLOCATION; + return NULL; + } + tmp->data = (char *) malloc (sizeof (char) * element_size); + if (tmp->data == NULL) { + free (tmp); + list->error = MEMORY_ALLOCATION; + return NULL; + } + if (position == AT_END) { + tmp->prev = list->last; + tmp->next = NULL; + tmp->size = element_size; + list->size = list->size + tmp->size; + list->number_of_elements = list->number_of_elements + 1; + list->last->next = tmp; + list->last = tmp; + } + else if (position == AT_START) { + tmp->prev = NULL; + tmp->next = list->first; + tmp->size = element_size; + list->size = list->size + tmp->size; + list->number_of_elements = list->number_of_elements + 1; + list->first->prev = tmp; + list->first = tmp; + } + else if (position == AT_CURRENT) { + if (list->current == NULL) { + tmp->prev = list->last; + tmp->next = NULL; + tmp->size = element_size; + list->size = list->size + tmp->size; + list->number_of_elements = list->number_of_elements + 1; + list->last->next = tmp; + list->last = tmp; + } + else { + tmp->prev = list->current; + tmp->next = list->current->next; + tmp->size = element_size; + list->size = list->size + tmp->size; + list->number_of_elements = list->number_of_elements + 1; + list->current->next = tmp; + list->current->next->prev = tmp; + } + } + return tmp; + } +} + +int imamLL_element_remove (struct imamLL *list, struct imamLL_element *element) +{ + int found = 0; + struct imamLL_element *tmp = list->first; + if (tmp == NULL) { + list->error = EMPTY_LIST; + return -1; + } + while (tmp != NULL) + { + if (memcmp (tmp, element, sizeof (struct imamLL_element)) == 0) + { + struct imamLL_element *next = tmp->next; + struct imamLL_element *prev = tmp->prev; + found = 1; + list->number_of_elements = list->number_of_elements - 1; + list->size = list->size - tmp->size; + if ((tmp == list->first) && (tmp == list->last)) + { + list->current = NULL; + list->first = NULL; + list->last = NULL; + tmp->next = NULL; + tmp->prev = NULL; + tmp->size = 0; + free (tmp->data); + tmp->data = NULL; + free (tmp); + break; + } + else if (tmp == list->first) + { + if (list->current == list->first) list->current = next; + list->first = next; + list->first->prev = NULL; + tmp->next = NULL; + tmp->prev = NULL; + tmp->size = 0; + free (tmp->data); + tmp->data = NULL; + free (tmp); + break; + } + else if (tmp == list->last) + { + if (list->current == list->last) list->current = prev; + list->last = prev; + list->last->next = NULL; + tmp->next = NULL; + tmp->prev = NULL; + tmp->size = 0; + free (tmp->data); + tmp->data = NULL; + free (tmp); + break; + } + else + { + if (list->current == tmp) list->current = next; + next->prev = prev; + prev->next = next; + tmp->next = NULL; + tmp->prev = NULL; + tmp->size = 0; + free (tmp->data); + tmp->data = NULL; + free (tmp); + break; + } + } + tmp = tmp->next; + } + if (found == 0) list->error = NO_MATCHING_ELEMENT; + return found; +} + +struct imamLL_element *imamLL_element_get (struct imamLL *list, void *element_data, uint64_t data_size) +{ + int found = 0; + struct imamLL_element *tmp = list->first; + if (tmp == NULL) return NULL; + while (tmp != NULL) + { + if (tmp->size == data_size) { + if (memcmp ((char *)tmp->data, (char *)element_data, tmp->size) == 0) + { + found = 1; + break; + } + } + tmp = tmp->next; + } + if (found == 1) return tmp; + else { + list->error = NO_MATCHING_ELEMENT; + return NULL; + } +} + +struct imamLL_element *imamLL_element_get_next (struct imamLL *list) +{ + if (list->current == NULL) list->current = list->first; + else list->current = list->current->next; + if (list->current == NULL) return NULL; + return list->current; +} + +struct imamLL_element *imamLL_element_get_prev (struct imamLL *list) +{ + if (list->current == NULL) list->current = list->last; + else list->current = list->current->prev; + if (list->current == NULL) return NULL; + return list->current; +} diff --git a/src/imamll.h b/src/imamll.h new file mode 100644 index 0000000..71c9f9a --- /dev/null +++ b/src/imamll.h @@ -0,0 +1,112 @@ +/* + Imam Linear List (imamLL) a simple C based linked list library + + Copyright (c) 2015 Md Imam Hossain + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Md Imam Hossain + emamhd@gmail.com +*/ + +#ifndef IMAMLL_H +#define IMAMLL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#define IMAM_LL_VERSION 12 + +enum imamLL_errors { + MEMORY_ALLOCATION = 1, + EMPTY_LIST = 2, + NO_MATCHING_ELEMENT = 3 +}; + +enum imamLL_position { + AT_START = 1, /* position new element at the beginning of a list */ + AT_CURRENT = 2, /* position new element after the current element of a list */ + AT_END = 3 /* position new element at the ending of a list */ +}; + +/* structure of a list */ +struct imamLL { + uint64_t number_of_elements; /* number of elements in the list */ + uint64_t size; /* total elements size in bytes */ + struct imamLL_element *first; /* pointer to the first element */ + struct imamLL_element *last; /* pointer to the last element */ + struct imamLL_element *current; /* pointer to an arbitrary element, used by imamLL_element_get_* functions */ + int error; /* error number used by imamLL_list_error function */ +}; + +/* structure of a element */ +struct imamLL_element { + void *data; /* pointer to the data */ + uint64_t size; /* size of data in bytes */ + struct imamLL_element *prev; /* pointer to the next element */ + struct imamLL_element *next; /* pointer to the first element */ +}; + +/* creates a new list by allocating memory and returns the pointer of the list */ +/* Return Value: upon successful returns pointer to newly allocated list, otherwise returns NULL*/ +extern struct imamLL *imamLL_list_create (void); + +/* frees the memory allocated by *list and it's elements */ +/* Return Value: upon successful returns 0, otherwise returns -1*/ +extern int imamLL_list_destroy (struct imamLL *list); + +/* frees the memory allocated by the elements of the *list, aka removes all the elements from the list */ +/* Return Value: upon successful returns the number of elements freed in a list, otherwise returns -1 and sets appropriate error no to error variable of a list*/ +extern int imamLL_list_free (struct imamLL *list); + +/* rewinds the current element to the first, used by used by imamLL_element_get_* functions */ +extern void imamLL_list_rewind (struct imamLL *list); + +/* copies last error information into *error_message */ +extern void imamLL_list_error (struct imamLL *list, char *error_message); + +/* allocates memory for a new element and returns the pointer of allocated element */ +/* Return Value: upon successful returns pointer to newly allocated element, otherwise returns NULL and sets appropriate error no to error variable of a list*/ +extern struct imamLL_element *imamLL_element_add (struct imamLL *list, unsigned long element_size, uint32_t position); + +/* frees and removes the matching element *element from the list */ +/* Return Value: upon successful returns 1, otherwise returns 0 and -1 and sets appropriate error no to error variable of a list*/ +extern int imamLL_element_remove (struct imamLL *list, struct imamLL_element *element); + +/* returns the pointer of a matching element */ +/* Return Value: upon successful returns pointer to found element in a list, otherwise returns NULL and sets appropriate error no to error variable of a list*/ +extern struct imamLL_element *imamLL_element_get (struct imamLL *list, void *element_data, uint64_t data_size); + +/* returns the pointer of the next element in the list */ +/* Return Value: upon successful returns pointer to next element in a list, otherwise returns NULL*/ +extern struct imamLL_element *imamLL_element_get_next (struct imamLL *list); + +/* returns the pointer of the previous element in the list */ +/* Return Value: upon successful returns pointer to next element in a list, otherwise returns NULL*/ +extern struct imamLL_element *imamLL_element_get_prev (struct imamLL *list); + + +#ifdef __cplusplus +} +#endif + +#endif /* IMAMLL_H */